]>
git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/webserver.cc
2 PowerDNS Versatile Database Driven Nameserver
3 Copyright (C) 2002-2012 PowerDNS.COM BV
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License version 2
7 as published by the Free Software Foundation
9 Additionally, the license of this program contains a special
10 exception which allows to distribute the program in binary form when
11 it is linked against OpenSSL.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 #include "webserver.hh"
34 map
<string
,WebServer::HandlerFunction
*>WebServer::d_functions
;
35 void *WebServer::d_that
;
36 string
WebServer::d_password
;
38 int WebServer::B64Decode(const std::string
& strInput
, std::string
& strOutput
)
40 return ::B64Decode(strInput
, strOutput
);
43 void WebServer::registerHandler(const string
&s
, HandlerFunction
*ptr
)
48 void WebServer::setCaller(void *that
)
53 void *WebServer::serveConnection(void *p
)
55 pthread_detach(pthread_self());
56 Session
*client
=static_cast<Session
*>(p
);
62 client
->setTimeout(5);
63 client
->getLine(line
);
66 throw HttpBadRequestException();
67 // L<<"page: "<<line<<endl;
70 stringtok(parts
,line
);
78 vector
<string
>variables
;
81 stringtok(parts
,uri
,"?");
83 // L<<"baseUrl: '"<<parts[0]<<"'"<<endl;
85 vector
<string
>urlParts
;
86 stringtok(urlParts
,parts
[0],"/");
93 // L<<"baseUrl real: '"<<baseUrl<<"'"<<endl;
96 stringtok(variables
,parts
[1],"&");
99 map
<string
,string
>varmap
;
101 for(vector
<string
>::const_iterator i
=variables
.begin();
102 i
!=variables
.end();++i
) {
105 stringtok(parts
,*i
,"=");
107 varmap
[parts
[0]]=parts
[1];
115 // read & ignore other lines
117 client
->getLine(line
);
123 size_t colon
= line
.find(":");
124 if(colon
==std::string::npos
)
125 throw HttpBadRequestException();
127 string header
= toLower(line
.substr(0, colon
));
128 string value
= line
.substr(line
.find_first_not_of(' ', colon
+1));
130 if(header
== "authorization" && toLower(value
).find("basic ") == 0) {
131 string cookie
=value
.substr(6);
134 B64Decode(cookie
,plain
);
135 vector
<string
>cparts
;
136 stringtok(cparts
,plain
,":");
137 // L<<Logger::Error<<"Entered password: '"<<cparts[1].c_str()<<"', should be '"<<d_password.c_str()<<"'"<<endl;
138 if(cparts
.size()==2 && !strcmp(cparts
[1].c_str(),d_password
.c_str())) { // this gets rid of terminating zeros
142 else if(header
== "content-length" && method
=="POST") {
143 postlen
= atoi(value
.c_str());
144 // cout<<"Got a post: "<<postlen<<" bytes"<<endl;
146 else if(header
== "accept") {
147 // json wins over html
148 if(value
.find("application/json")!=std::string::npos
) {
150 } else if(value
.find("text/html")!=std::string::npos
) {
155 ; // cerr<<"Ignoring line: "<<line<<endl;
161 post
= client
->get(postlen
);
163 // cout<<"Post: '"<<post<<"'"<<endl;
165 if(!d_password
.empty() && !authOK
)
166 throw HttpUnauthorizedException();
168 HandlerFunction
*fptr
;
169 if(d_functions
.count(baseUrl
) && (fptr
=d_functions
[baseUrl
])) {
171 string ret
=(*fptr
)(method
, post
, varmap
, d_that
, &custom
);
174 client
->putLine("HTTP/1.1 200 OK\n");
175 client
->putLine("Connection: close\n");
176 client
->putLine("Content-Type: text/html; charset=utf-8\n\n");
178 client
->putLine(ret
);
181 throw HttpNotFoundException();
185 catch(HttpException
&e
) {
186 client
->putLine(e
.statusLine());
187 client
->putLine("Connection: close\n");
188 client
->putLine(e
.headers());
190 client
->putLine("Content-Type: text/html; charset=utf-8\n\n");
191 client
->putLine("<!html><title>" + e
.what() + "</title><h1>" + e
.what() + "</h1>");
192 } else if (want_json
) {
193 client
->putLine("Content-Type: application/json\n\n");
194 client
->putLine(returnJSONError(e
.what()));
196 client
->putLine("Content-Type: text/plain; charset=utf-8\n\n");
197 client
->putLine(e
.what());
207 catch(SessionTimeoutException
&e
) {
208 // L<<Logger::Error<<"Timeout in webserver"<<endl;
210 catch(PDNSException
&e
) {
211 L
<<Logger::Error
<<"Exception in webserver: "<<e
.reason
<<endl
;
213 catch(std::exception
&e
) {
214 L
<<Logger::Error
<<"STL Exception in webserver: "<<e
.what()<<endl
;
217 L
<<Logger::Error
<<"Unknown exception in webserver"<<endl
;
221 WebServer::WebServer(const string
&listenaddress
, int port
, const string
&password
)
223 d_listenaddress
=listenaddress
;
226 d_server
= 0; // on exception, this class becomes a NOOP later on
228 d_server
= new Server(d_port
, d_listenaddress
);
230 catch(SessionException
&e
) {
231 L
<<Logger::Error
<<"Fatal error in webserver: "<<e
.reason
<<endl
;
243 L
<<Logger::Error
<<"Launched webserver on " << d_server
->d_local
.toStringWithPort() <<endl
;
245 while((client
=d_server
->accept())) {
246 pthread_create(&tid
, 0 , &serveConnection
, (void *)client
);
249 catch(SessionTimeoutException
&e
) {
250 // L<<Logger::Error<<"Timeout in webserver"<<endl;
252 catch(PDNSException
&e
) {
253 L
<<Logger::Error
<<"Exception in main webserver thread: "<<e
.reason
<<endl
;
255 catch(std::exception
&e
) {
256 L
<<Logger::Error
<<"STL Exception in main webserver thread: "<<e
.what()<<endl
;
259 L
<<Logger::Error
<<"Unknown exception in main webserver thread"<<endl
;