From: Bert Hubert Date: Fri, 30 Nov 2012 16:10:12 +0000 (+0000) Subject: -- libjson-cpp is now a dependency, remotebackend is mandatory for building from... X-Git-Tag: auth-3.2-rc2~62 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a2ce158cf669539fc46ce62324dbf86210196e3a;p=pdns -- libjson-cpp is now a dependency, remotebackend is mandatory for building from now on -- teach our appalling webserver about different methods, allow it to read POSTed forms, teach it to parse JSON restful requests on our database! git-svn-id: svn://svn.powerdns.com/pdns/trunk/pdns@2939 d19b8d6e-7fed-0310-83ef-9ca221ded41b --- diff --git a/pdns/webserver.cc b/pdns/webserver.cc index 8e94d9027..ae0190466 100644 --- a/pdns/webserver.cc +++ b/pdns/webserver.cc @@ -62,9 +62,11 @@ void *WebServer::serveConnection(void *p) vector parts; stringtok(parts,line); - string uri; - if(parts.size()>1) + string method, uri; + if(parts.size()>1) { + method=parts[0]; uri=parts[1]; + } vectorvariables; @@ -102,7 +104,7 @@ void *WebServer::serveConnection(void *p) } bool authOK=0; - + int postlen = 0; // read & ignore other lines do { client->getLine(line); @@ -121,8 +123,21 @@ void *WebServer::serveConnection(void *p) authOK=1; } } + else if(boost::starts_with(line, "Content-Length: ") && method=="POST") { + postlen = atoi(line.c_str() + strlen("Content-Length: ")); +// cout<<"Got a post: "<get(postlen); + + // cout<<"Post: '"<putLine("HTTP/1.1 401 OK\n"); client->putLine("WWW-Authenticate: Basic realm=\"PowerDNS\"\n"); @@ -138,7 +153,7 @@ void *WebServer::serveConnection(void *p) HandlerFunction *fptr; if(d_functions.count(baseUrl) && (fptr=d_functions[baseUrl])) { bool custom=false; - string ret=(*fptr)(varmap, d_that, &custom); + string ret=(*fptr)(method, post, varmap, d_that, &custom); if(!custom) { client->putLine("HTTP/1.1 200 OK\n"); diff --git a/pdns/webserver.hh b/pdns/webserver.hh index 878fbecde..bde1e7634 100644 --- a/pdns/webserver.hh +++ b/pdns/webserver.hh @@ -1,6 +1,6 @@ /* PowerDNS Versatile Database Driven Nameserver - Copyright (C) 2002 PowerDNS.COM BV + Copyright (C) 2002-2012 PowerDNS.COM BV This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 @@ -32,7 +32,7 @@ public: void go(); static void* serveConnection(void *); void setCaller(void *that); - typedef string HandlerFunction(const map&varmap, void *that, bool *custom); + typedef string HandlerFunction(const string& method, const string& post, const map&varmap, void *that, bool *custom); void registerHandler(const string &, HandlerFunction *ptr); private: static char B64Decode1(char cInChar); diff --git a/pdns/ws.cc b/pdns/ws.cc index 9220e46bc..fb9caac07 100644 --- a/pdns/ws.cc +++ b/pdns/ws.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2002 - 2007 PowerDNS.COM BV + Copyright (C) 2002 - 2012 PowerDNS.COM BV This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 @@ -28,6 +28,7 @@ #include #include #include "namespaces.hh" +#include extern StatBag S; @@ -152,7 +153,7 @@ string StatWebServer::makePercentage(const double& val) return (boost::format("%.01f%%") % val).str(); } -string StatWebServer::indexfunction(const map &varmap, void *ptr, bool *custom) +string StatWebServer::indexfunction(const string& method, const string& post, const map &varmap, void *ptr, bool *custom) { StatWebServer *sws=static_cast(ptr); maprvarmap=varmap; @@ -231,11 +232,10 @@ string StatWebServer::indexfunction(const map &varmap, void *ptr, } -string StatWebServer::jsonstat(const map &varmap, void *ptr, bool *custom) +string StatWebServer::jsonstat(const string& method, const string& post, const map &varmap, void *ptr, bool *custom) { - *custom=1; + *custom=1; // indicates we build the response string ret="HTTP/1.1 200 OK\r\n" - "Date: Wed, 30 Nov 2011 22:01:15 GMT\r\n" // XXX FIXME real date! "Server: PowerDNS/"VERSION"\r\n" "Connection: close\r\n" "Access-Control-Allow-Origin: *\r\n" @@ -353,6 +353,95 @@ string StatWebServer::jsonstat(const map &varmap, void *ptr, bool ret += "]"; } + if(command == "zone-rest") { // http://jsonstat?command=zone-rest&rest=/powerdns.nl/www.powerdns.nl/a + vector parts; + stringtok(parts, ourvarmap["rest"], "/"); + if(parts.size() != 3) + return ret+"{\"error\": \"Could not parse rest parameter\"}"; + UeberBackend B; + SOAData sd; + sd.db = (DNSBackend*)-1; + if(!B.getSOA(parts[0], sd) || !sd.db) { + map err; + err["error"]= "Could not find domain '"+ourvarmap["zone"]+"'"; + return ret+returnJSONObject(err); + } + + QType qtype; + qtype=parts[2]; + string qname=parts[1]; + extern PacketCache PC; + PC.purge(qname); + // cerr<<"domain id: "< object; + bool first=1; + + while(B.get(rr)) { + if(!first) ret += ", "; + first=false; + object.clear(); + object["name"] = rr.qname; + object["type"] = rr.qtype.getName(); + object["ttl"] = lexical_cast(rr.ttl); + object["priority"] = lexical_cast(rr.priority); + object["content"] = rr.content; + ret+=returnJSONObject(object); + } + ret+="]}"; + } + else if(method=="DELETE") { + sd.db->replaceRRSet(sd.domain_id, qname, qtype, vector()); + + } + else if(method=="POST") { + Json::Value root; // will contains the root value after parsing. + Json::Reader reader; + if(!reader.parse(post, root )) { + return ret+"{\"error\": \"Unable to parse JSON\""; + } + + const Json::Value records=root["records"]; + + DNSResourceRecord rr; + vector rrset; + for(unsigned int i = 0 ; i < records.size(); ++i) { + const Json::Value& record = records[i]; + rr.qname=record["name"].asString(); + rr.content=record["content"].asString(); + rr.qtype=record["type"].asString(); + rr.domain_id = sd.domain_id; + rr.auth=0; + rr.ttl=atoi(record["ttl"].asString().c_str()); + rr.priority=atoi(record["priority"].asString().c_str()); + + rrset.push_back(rr); + + if(rr.qtype.getCode() == QType::MX || rr.qtype.getCode() == QType::SRV) + rr.content = lexical_cast(rr.priority)+" "+rr.content; + + try { + shared_ptr drc(DNSRecordContent::mastermake(rr.qtype.getCode(), 1, rr.content)); + string tmp=drc->serialize(rr.qname); + } + catch(std::exception& e) + { + map err; + err["error"]= "Following record had a problem: "+rr.qname+" IN " +rr.qtype.getName()+ " " + rr.content+": "+e.what(); + return ret+returnJSONObject(err); + } + } + // but now what + sd.db->startTransaction(qname); + sd.db->replaceRRSet(sd.domain_id, qname, qtype, rrset); + sd.db->commitTransaction(); + } + } if(command=="log-grep") { ret += makeLogGrepJSON(ourvarmap, ::arg()["logfile"], " pdns["); } diff --git a/pdns/ws.hh b/pdns/ws.hh index 63f1fc996..e5c6ff726 100644 --- a/pdns/ws.hh +++ b/pdns/ws.hh @@ -86,8 +86,8 @@ public: private: static void *threadHelper(void *); static void *statThreadHelper(void *p); - static string indexfunction(const map &varmap, void *ptr, bool *custom); - static string jsonstat(const map &varmap, void *ptr, bool *custom); + static string indexfunction(const string& method, const string& post, const map &varmap, void *ptr, bool *custom); + static string jsonstat(const string& method, const string& post, const map &varmap, void *ptr, bool *custom); void printvars(ostringstream &ret); void printargs(ostringstream &ret); void launch();