]>
git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/webserver.cc
2 PowerDNS Versatile Database Driven Nameserver
3 Copyright (C) 2002 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 as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include "webserver.hh"
29 map
<string
,WebServer::HandlerFunction
*>WebServer::d_functions
;
30 void *WebServer::d_that
;
31 string
WebServer::d_password
;
33 char WebServer::B64Decode1(char cInChar
)
35 // The incoming character will be A-Z, a-z, 0-9, +, /, or =.
36 // The idea is to quickly determine which grouping the
37 // letter belongs to and return the associated value
38 // without having to search the global encoding string
39 // (the value we're looking for would be the resulting
40 // index into that string).
42 // To do that, we'll play some tricks...
43 unsigned char iIndex
= '\0';
58 // Must be 'A'-'Z', 'a'-'z', '0'-'9', or an error...
60 // Numerically, small letters are "greater" in value than
61 // capital letters and numerals (ASCII value), and capital
62 // letters are "greater" than numerals (again, ASCII value),
63 // so we check for numerals first, then capital letters,
64 // and finally small letters.
65 iIndex
= '9' - cInChar
;
66 if ( iIndex
> 0x3F ) {
67 // Not from '0' to '9'...
68 iIndex
= 'Z' - cInChar
;
69 if ( iIndex
> 0x3F ) {
70 // Not from 'A' to 'Z'...
71 iIndex
= 'z' - cInChar
;
72 if ( iIndex
> 0x3F ) {
73 // Invalid character...cannot
75 iIndex
= 0x80; // set the high bit
79 iIndex
= (('z' - iIndex
) - 'a') + 26;
84 iIndex
= ('Z' - iIndex
) - 'A';
88 // Adjust the index...
89 iIndex
= (('9' - iIndex
) - '0') + 52;
98 int WebServer::B64Decode(const std::string
& strInput
, std::string
& strOutput
)
100 // Set up a decoding buffer
102 char* pBuf
= (char*)&cBuf
;
104 // Decoding management...
105 short iBitGroup
= 0, iInNum
= 0;
107 // While there are characters to process...
109 // We'll decode characters in blocks of 4, as
110 // there are 4 groups of 6 bits in 3 bytes. The
111 // incoming Base64 character is first decoded, and
112 // then it is inserted into the decode buffer
113 // (with any relevant shifting, as required).
114 // Later, after all 3 bytes have been reconsituted,
115 // we assign them to the output string, ultimately
116 // to be returned as the original message.
117 int iInSize
= strInput
.size();
118 unsigned char cChar
= '\0';
119 while ( iInNum
< iInSize
) {
120 // Fill the decode buffer with 4 groups of 6 bits
122 for ( iBitGroup
= 0; iBitGroup
< 4; ++iBitGroup
) {
123 if ( iInNum
< iInSize
) {
124 // Decode a character
125 cChar
= B64Decode1(strInput
.at(iInNum
++));
128 // Decode a padded zero
132 // Check for valid decode
137 switch ( iBitGroup
) {
139 // The first group is copied into
140 // the least significant 6 bits of
141 // the decode buffer...these 6 bits
142 // will eventually shift over to be
143 // the most significant bits of the
149 // For groupings 1-3, simply shift
150 // the bits in the decode buffer over
151 // by 6 and insert the 6 from the
152 // current decode character.
153 cBuf
= (cBuf
<< 6) | cChar
;
159 // Interpret the resulting 3 bytes...note there
160 // may have been padding, so those padded bytes
161 // are actually ignored.
162 strOutput
+= pBuf
[2];
163 strOutput
+= pBuf
[1];
164 strOutput
+= pBuf
[0];
173 void WebServer::registerHandler(const string
&s
, HandlerFunction
*ptr
)
178 void WebServer::setCaller(void *that
)
183 void *WebServer::serveConnection(void *p
)
185 Session
*client
=static_cast<Session
*>(p
);
188 client
->getLine(line
);
190 // L<<"page: "<<line<<endl;
192 vector
<string
> parts
;
193 stringtok(parts
,line
);
199 vector
<string
>variables
;
202 stringtok(parts
,uri
,"?");
204 // L<<"baseUrl: '"<<parts[0]<<"'"<<endl;
206 vector
<string
>urlParts
;
207 stringtok(urlParts
,parts
[0],"/");
214 // L<<"baseUrl real: '"<<baseUrl<<"'"<<endl;
217 stringtok(variables
,parts
[1],"&");
220 map
<string
,string
>varmap
;
222 for(vector
<string
>::const_iterator i
=variables
.begin();
223 i
!=variables
.end();++i
) {
226 stringtok(parts
,*i
,"=");
228 varmap
[parts
[0]]=parts
[1];
232 L
<<"'"<<parts
[0]<<"' = '"<<varmap
[parts
[0]]<<"'"<<endl
;
237 // read & ignore other lines
239 client
->getLine(line
);
242 if(!line
.find("Authorization: Basic ")) {
243 string cookie
=line
.substr(21);
246 B64Decode(cookie
,plain
);
247 vector
<string
>cparts
;
248 stringtok(cparts
,plain
,":");
250 if(cparts
.size()==2 && !strcmp(cparts
[1].c_str(),d_password
.c_str())) { // this gets rid of terminating zeros
254 }while(!line
.empty());
257 if(!d_password
.empty() && !authOK
) {
258 client
->putLine("HTTP/1.1 401 OK\n");
259 client
->putLine("WWW-Authenticate: Basic realm=\"PowerDNS\"\n");
261 client
->putLine("Connection: close\n");
262 client
->putLine("Content-type: text/html\n\n");
263 client
->putLine("Please enter a valid password!\n");
269 HandlerFunction
*fptr
;
270 if((fptr
=d_functions
[baseUrl
])) {
273 string ret
=(*fptr
)(varmap
, d_that
, &custom
);
276 client
->putLine("HTTP/1.1 200 OK\n");
277 client
->putLine("Connection: close\n");
278 client
->putLine("Content-type: text/html\n\n");
280 client
->putLine(ret
);
283 client
->putLine("HTTP/1.1 404 Not found\n");
284 client
->putLine("Connection: close\n");
285 client
->putLine("Content-type: text/html\n\n");
286 // FIXME: CSS problem?
287 client
->putLine("<html><body><h1>Did not find file '"+baseUrl
+"'</body></html>\n");
296 catch(SessionTimeoutException
&e
) {
297 L
<<Logger::Error
<<"Timeout in webserver"<<endl
;
299 catch(SessionException
&e
) {
300 L
<<Logger::Error
<<"Fatal error in webserver: "<<e
.reason
<<endl
;
302 catch(Exception
&e
) {
303 L
<<Logger::Error
<<"Exception in webserver: "<<e
.reason
<<endl
;
305 catch(exception
&e
) {
306 L
<<Logger::Error
<<"STL Exception in webserver: "<<e
.what()<<endl
;
309 L
<<Logger::Error
<<"Unknown exception in webserver"<<endl
;
319 WebServer::WebServer(const string
&listenaddress
, int port
, const string
&password
)
321 d_listenaddress
=listenaddress
;
329 Server
*s
=new Server(d_port
, d_listenaddress
);
334 L
<<Logger::Error
<<"Launched webserver on "<<d_listenaddress
<<":"<<d_port
<<endl
;
336 while((client
=s
->accept())) {
337 pthread_create(&tid
, 0 , &serveConnection
, (void *)client
);
340 catch(SessionTimeoutException
&e
) {
341 L
<<Logger::Error
<<"Timeout in webserver"<<endl
;
343 catch(SessionException
&e
) {
344 L
<<Logger::Error
<<"Fatal error in webserver: "<<e
.reason
<<endl
;
346 catch(Exception
&e
) {
347 L
<<Logger::Error
<<"Fatal error in main webserver thread: "<<e
.reason
<<endl
;
349 catch(exception
&e
) {
350 L
<<Logger::Error
<<"STL Exception in main webserver thread: "<<e
.what()<<endl
;
353 L
<<Logger::Error
<<"Unknown exception in main webserver thread"<<endl
;