fastcgi++
|
00001 00002 /*************************************************************************** 00003 * Copyright (C) 2007 Eddie Carle [eddie@erctech.org] * 00004 * * 00005 * This file is part of fastcgi++. * 00006 * * 00007 * fastcgi++ is free software: you can redistribute it and/or modify it * 00008 * under the terms of the GNU Lesser General Public License as published * 00009 * by the Free Software Foundation, either version 3 of the License, or (at * 00010 * your option) any later version. * 00011 * * 00012 * fastcgi++ is distributed in the hope that it will be useful, but WITHOUT * 00013 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * 00014 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * 00015 * License for more details. * 00016 * * 00017 * You should have received a copy of the GNU Lesser General Public License * 00018 * along with fastcgi++. If not, see <http://www.gnu.org/licenses/>. * 00019 ****************************************************************************/ 00020 00021 00022 #include <algorithm> 00023 #include <boost/date_time/posix_time/posix_time.hpp> 00024 00025 #include <fastcgi++/http.hpp> 00026 00027 #include "utf8_codecvt.hpp" 00028 00029 void Fastcgipp::Http::Address::assign(const char* start, const char* end) 00030 { 00031 data=0; 00032 for(int i=24; i>=0; i-=8) 00033 { 00034 char* point=(char*)memchr(start, '.', end-start); 00035 data|=atoi(start, end)<<i; 00036 if(!point || point+1>=end) break; 00037 start=point+1; 00038 } 00039 } 00040 00041 template std::basic_ostream<char, std::char_traits<char> >& Fastcgipp::Http::operator<< <char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >& os, const Address& address); 00042 template std::basic_ostream<wchar_t, std::char_traits<wchar_t> >& Fastcgipp::Http::operator<< <wchar_t, std::char_traits<wchar_t> >(std::basic_ostream<wchar_t, std::char_traits<wchar_t> >& os, const Address& address); 00043 template<class charT, class Traits> std::basic_ostream<charT, Traits>& Fastcgipp::Http::operator<<(std::basic_ostream<charT, Traits>& os, const Address& address) 00044 { 00045 using namespace std; 00046 if(!os.good()) return os; 00047 00048 try 00049 { 00050 typename basic_ostream<charT, Traits>::sentry opfx(os); 00051 if(opfx) 00052 { 00053 streamsize fieldWidth=os.width(0); 00054 charT buffer[20]; 00055 charT* bufPtr=buffer; 00056 locale loc(os.getloc(), new num_put<charT, charT*>); 00057 00058 for(uint32_t mask=0xff000000, shift=24; mask!=0; mask>>=8, shift-=8) 00059 { 00060 bufPtr=use_facet<num_put<charT, charT*> >(loc).put(bufPtr, os, os.fill(), static_cast<long unsigned int>((address.data&mask)>>shift)); 00061 *bufPtr++=os.widen('.'); 00062 } 00063 --bufPtr; 00064 00065 charT* ptr=buffer; 00066 ostreambuf_iterator<charT,Traits> sink(os); 00067 if(os.flags() & ios_base::left) 00068 for(int i=max(fieldWidth, bufPtr-buffer); i>0; i--) 00069 { 00070 if(ptr!=bufPtr) *sink++=*ptr++; 00071 else *sink++=os.fill(); 00072 } 00073 else 00074 for(int i=fieldWidth-(bufPtr-buffer); ptr!=bufPtr;) 00075 { 00076 if(i>0) { *sink++=os.fill(); --i; } 00077 else *sink++=*ptr++; 00078 } 00079 00080 if(sink.failed()) os.setstate(ios_base::failbit); 00081 } 00082 } 00083 catch(bad_alloc&) 00084 { 00085 ios_base::iostate exception_mask = os.exceptions(); 00086 os.exceptions(ios_base::goodbit); 00087 os.setstate(ios_base::badbit); 00088 os.exceptions(exception_mask); 00089 if(exception_mask & ios_base::badbit) throw; 00090 } 00091 catch(...) 00092 { 00093 ios_base::iostate exception_mask = os.exceptions(); 00094 os.exceptions(ios_base::goodbit); 00095 os.setstate(ios_base::failbit); 00096 os.exceptions(exception_mask); 00097 if(exception_mask & ios_base::failbit) throw; 00098 } 00099 return os; 00100 } 00101 00102 template std::basic_istream<char, std::char_traits<char> >& Fastcgipp::Http::operator>> <char, std::char_traits<char> >(std::basic_istream<char, std::char_traits<char> >& is, Address& address); 00103 template std::basic_istream<wchar_t, std::char_traits<wchar_t> >& Fastcgipp::Http::operator>> <wchar_t, std::char_traits<wchar_t> >(std::basic_istream<wchar_t, std::char_traits<wchar_t> >& is, Address& address); 00104 template<class charT, class Traits> std::basic_istream<charT, Traits>& Fastcgipp::Http::operator>>(std::basic_istream<charT, Traits>& is, Address& address) 00105 { 00106 using namespace std; 00107 if(!is.good()) return is; 00108 00109 ios_base::iostate err = ios::goodbit; 00110 try 00111 { 00112 typename basic_istream<charT, Traits>::sentry ipfx(is); 00113 if(ipfx) 00114 { 00115 uint32_t data=0; 00116 istreambuf_iterator<charT, Traits> it(is); 00117 for(int i=24; i>=0; i-=8, ++it) 00118 { 00119 uint32_t value; 00120 use_facet<num_get<charT, istreambuf_iterator<charT, Traits> > >(is.getloc()).get(it, istreambuf_iterator<charT, Traits>(), is, err, value); 00121 data|=value<<i; 00122 if(i && *it!=is.widen('.')) err = ios::failbit; 00123 } 00124 if(err == ios::goodbit) address=data; 00125 else is.setstate(err); 00126 } 00127 } 00128 catch(bad_alloc&) 00129 { 00130 ios_base::iostate exception_mask = is.exceptions(); 00131 is.exceptions(ios_base::goodbit); 00132 is.setstate(ios_base::badbit); 00133 is.exceptions(exception_mask); 00134 if(exception_mask & ios_base::badbit) throw; 00135 } 00136 catch(...) 00137 { 00138 ios_base::iostate exception_mask = is.exceptions(); 00139 is.exceptions(ios_base::goodbit); 00140 is.setstate(ios_base::failbit); 00141 is.exceptions(exception_mask); 00142 if(exception_mask & ios_base::failbit) throw; 00143 } 00144 00145 return is; 00146 } 00147 00148 void Fastcgipp::Http::charToString(const char* data, size_t size, std::wstring& string) 00149 { 00150 const size_t bufferSize=512; 00151 wchar_t buffer[bufferSize]; 00152 using namespace std; 00153 00154 if(size) 00155 { 00156 codecvt_base::result cr=codecvt_base::partial; 00157 while(cr==codecvt_base::partial) 00158 {{ 00159 wchar_t* it; 00160 const char* tmpData; 00161 mbstate_t conversionState = mbstate_t(); 00162 cr=use_facet<codecvt<wchar_t, char, mbstate_t> >(locale(locale::classic(), new utf8CodeCvt::utf8_codecvt_facet)).in(conversionState, data, data+size, tmpData, buffer, buffer+bufferSize, it); 00163 string.append(buffer, it); 00164 size-=tmpData-data; 00165 data=tmpData; 00166 }} 00167 if(cr==codecvt_base::error) throw Exceptions::CodeCvt(); 00168 } 00169 } 00170 00171 int Fastcgipp::Http::atoi(const char* start, const char* end) 00172 { 00173 bool neg=false; 00174 if(*start=='-') 00175 { 00176 neg=true; 00177 ++start; 00178 } 00179 int result=0; 00180 for(; 0x30 <= *start && *start <= 0x39 && start<end; ++start) 00181 result=result*10+(*start&0x0f); 00182 00183 return neg?-result:result; 00184 } 00185 00186 size_t Fastcgipp::Http::percentEscapedToRealBytes(const char* source, char* destination, size_t size) 00187 { 00188 if (size < 1) return 0; 00189 00190 unsigned int i=0; 00191 char* start=destination; 00192 while(1) 00193 { 00194 if(*source=='%') 00195 { 00196 *destination=0; 00197 for(int shift=4; shift>=0; shift-=4) 00198 { 00199 if(++i==size) break; 00200 ++source; 00201 if((*source|0x20) >= 'a' && (*source|0x20) <= 'f') 00202 *destination|=((*source|0x20)-0x57)<<shift; 00203 else if(*source >= '0' && *source <= '9') 00204 *destination|=(*source&0x0f)<<shift; 00205 } 00206 ++source; 00207 ++destination; 00208 } 00209 else if(*source=='+') 00210 { 00211 *destination++=' '; 00212 ++source; 00213 } 00214 else 00215 *destination++=*source++; 00216 00217 if(++i==size) break; 00218 } 00219 return destination-start; 00220 } 00221 00222 template void Fastcgipp::Http::Environment<char>::fill(const char* data, size_t size); 00223 template void Fastcgipp::Http::Environment<wchar_t>::fill(const char* data, size_t size); 00224 template<class charT> void Fastcgipp::Http::Environment<charT>::fill(const char* data, size_t size) 00225 { 00226 using namespace std; 00227 using namespace boost; 00228 00229 while(size) 00230 {{ 00231 size_t nameSize; 00232 size_t valueSize; 00233 const char* name; 00234 const char* value; 00235 Protocol::processParamHeader(data, size, name, nameSize, value, valueSize); 00236 size-=value-data+valueSize; 00237 data=value+valueSize; 00238 00239 switch(nameSize) 00240 { 00241 case 9: 00242 if(!memcmp(name, "HTTP_HOST", 9)) 00243 charToString(value, valueSize, host); 00244 else if(!memcmp(name, "PATH_INFO", 9)) 00245 { 00246 boost::scoped_array<char> buffer(new char[valueSize]); 00247 const char* source=value; 00248 int size=-1; 00249 for(; source<value+valueSize+1; ++source, ++size) 00250 { 00251 if(*source == '/' || source == value+valueSize) 00252 { 00253 if(size > 0) 00254 { 00255 percentEscapedToRealBytes(source-size, buffer.get(), size); 00256 pathInfo.push_back(std::basic_string<charT>()); 00257 charToString(buffer.get(), size, pathInfo.back()); 00258 } 00259 size=-1; 00260 } 00261 } 00262 } 00263 break; 00264 case 11: 00265 if(!memcmp(name, "HTTP_ACCEPT", 11)) 00266 charToString(value, valueSize, acceptContentTypes); 00267 else if(!memcmp(name, "HTTP_COOKIE", 11)) 00268 decodeUrlEncoded(value, valueSize, cookies, ';'); 00269 else if(!memcmp(name, "SERVER_ADDR", 11)) 00270 serverAddress.assign(value, value+valueSize); 00271 else if(!memcmp(name, "REMOTE_ADDR", 11)) 00272 remoteAddress.assign(value, value+valueSize); 00273 else if(!memcmp(name, "SERVER_PORT", 11)) 00274 serverPort=atoi(value, value+valueSize); 00275 else if(!memcmp(name, "REMOTE_PORT", 11)) 00276 remotePort=atoi(value, value+valueSize); 00277 else if(!memcmp(name, "SCRIPT_NAME", 11)) 00278 charToString(value, valueSize, scriptName); 00279 else if(!memcmp(name, "REQUEST_URI", 11)) 00280 charToString(value, valueSize, requestUri); 00281 break; 00282 case 12: 00283 if(!memcmp(name, "HTTP_REFERER", 12) && valueSize) 00284 charToString(value, valueSize, referer); 00285 else if(!memcmp(name, "CONTENT_TYPE", 12)) 00286 { 00287 const char* end=(char*)memchr(value, ';', valueSize); 00288 charToString(value, end?end-value:valueSize, contentType); 00289 if(end) 00290 { 00291 const char* start=(char*)memchr(end, '=', valueSize-(end-data)); 00292 if(start) 00293 { 00294 boundarySize=valueSize-(++start-value); 00295 boundary.reset(new char[boundarySize]); 00296 memcpy(boundary.get(), start, boundarySize); 00297 } 00298 } 00299 } 00300 else if(!memcmp(name, "QUERY_STRING", 12) && valueSize) 00301 decodeUrlEncoded(value, valueSize, gets); 00302 break; 00303 case 13: 00304 if(!memcmp(name, "DOCUMENT_ROOT", 13)) 00305 charToString(value, valueSize, root); 00306 break; 00307 case 14: 00308 if(!memcmp(name, "REQUEST_METHOD", 14)) 00309 { 00310 requestMethod = HTTP_METHOD_ERROR; 00311 switch(valueSize) 00312 { 00313 case 3: 00314 if(!memcmp(value, requestMethodLabels[HTTP_METHOD_GET], 3)) requestMethod = HTTP_METHOD_GET; 00315 else if(!memcmp(value, requestMethodLabels[HTTP_METHOD_PUT], 3)) requestMethod = HTTP_METHOD_PUT; 00316 break; 00317 case 4: 00318 if(!memcmp(value, requestMethodLabels[HTTP_METHOD_HEAD], 4)) requestMethod = HTTP_METHOD_HEAD; 00319 else if(!memcmp(value, requestMethodLabels[HTTP_METHOD_POST], 4)) requestMethod = HTTP_METHOD_POST; 00320 break; 00321 case 5: 00322 if(!memcmp(value, requestMethodLabels[HTTP_METHOD_TRACE], 5)) requestMethod = HTTP_METHOD_TRACE; 00323 break; 00324 case 6: 00325 if(!memcmp(value, requestMethodLabels[HTTP_METHOD_DELETE], 6)) requestMethod = HTTP_METHOD_DELETE; 00326 break; 00327 case 7: 00328 if(!memcmp(value, requestMethodLabels[HTTP_METHOD_OPTIONS], 7)) requestMethod = HTTP_METHOD_OPTIONS; 00329 else if(!memcmp(value, requestMethodLabels[HTTP_METHOD_OPTIONS], 7)) requestMethod = HTTP_METHOD_CONNECT; 00330 break; 00331 } 00332 } 00333 else if(!memcmp(name, "CONTENT_LENGTH", 14)) 00334 contentLength=atoi(value, value+valueSize); 00335 break; 00336 case 15: 00337 if(!memcmp(name, "HTTP_USER_AGENT", 15)) 00338 charToString(value, valueSize, userAgent); 00339 else if(!memcmp(name, "HTTP_KEEP_ALIVE", 15)) 00340 keepAlive=atoi(value, value+valueSize); 00341 break; 00342 case 18: 00343 if(!memcmp(name, "HTTP_IF_NONE_MATCH", 18)) 00344 etag=atoi(value, value+valueSize); 00345 break; 00346 case 19: 00347 if(!memcmp(name, "HTTP_ACCEPT_CHARSET", 19)) 00348 charToString(value, valueSize, acceptCharsets); 00349 break; 00350 case 20: 00351 if(!memcmp(name, "HTTP_ACCEPT_LANGUAGE", 20)) 00352 charToString(value, valueSize, acceptLanguages); 00353 break; 00354 case 22: 00355 if(!memcmp(name, "HTTP_IF_MODIFIED_SINCE", 22)) 00356 { 00357 stringstream dateStream; 00358 dateStream.write(value, valueSize); 00359 dateStream.imbue(locale(locale::classic(), new posix_time::time_input_facet("%a, %d %b %Y %H:%M:%S GMT"))); 00360 dateStream >> ifModifiedSince; 00361 } 00362 break; 00363 } 00364 }} 00365 } 00366 00367 template void Fastcgipp::Http::Environment<char>::fillPostsMultipart(const char* data, size_t size); 00368 template void Fastcgipp::Http::Environment<wchar_t>::fillPostsMultipart(const char* data, size_t size); 00369 template<class charT> void Fastcgipp::Http::Environment<charT>::fillPostsMultipart(const char* data, size_t size) 00370 { 00371 using namespace std; 00372 while(1) 00373 {{ 00374 size_t bufferSize=postBufferSize+size; 00375 char* buffer=new char[bufferSize]; 00376 if(postBufferSize) memcpy(buffer, postBuffer.get(), postBufferSize); 00377 memcpy(buffer+postBufferSize, data, size); 00378 postBuffer.reset(buffer); 00379 postBufferSize=bufferSize; 00380 00381 const char* end=0; 00382 for(const char* i=buffer+boundarySize; i<buffer+bufferSize-boundarySize; ++i) 00383 if(!memcmp(i, boundary.get(), boundarySize)) 00384 { 00385 end=i; 00386 break; 00387 } 00388 00389 if(!end) 00390 return; 00391 00392 end-=4; 00393 const char* start=buffer+boundarySize+2; 00394 const char* bodyStart=start; 00395 for(; bodyStart<=end-4; ++bodyStart) 00396 if(!memcmp(bodyStart, "\r\n\r\n", 4)) break; 00397 bodyStart+=4; 00398 00399 00400 const char* contentTypeStart; 00401 ssize_t contentTypeSize=-1; 00402 const char* nameStart; 00403 ssize_t nameSize=-1; 00404 const char* filenameStart; 00405 ssize_t filenameSize=-1; 00406 // Fill out above values 00407 { 00408 const char cContentType[] = "Content-Type: "; 00409 const char cContentDisposition[] = "Content-Disposition: "; 00410 const char cFilename[] = "filename=\""; 00411 const char cName[] = "name=\""; 00412 00413 enum ParseState { TITLE, CONTENT_DISPOSITION, FILENAME, NAME, CONTENT_TYPE, SKIP } parseState=TITLE; 00414 for(const char* i=start; i<bodyStart; ++i) 00415 { 00416 switch(*i) 00417 { 00418 case '\n': 00419 case '\r': 00420 { 00421 if(parseState==CONTENT_TYPE) 00422 contentTypeSize=i-contentTypeStart; 00423 parseState=TITLE; 00424 break; 00425 } 00426 00427 case '"': 00428 { 00429 if(parseState==FILENAME) 00430 { 00431 filenameSize=i-filenameStart; 00432 parseState=CONTENT_DISPOSITION; 00433 } 00434 else if(parseState==NAME) 00435 { 00436 nameSize=i-nameStart; 00437 parseState=CONTENT_DISPOSITION; 00438 } 00439 break; 00440 } 00441 00442 default: 00443 { 00444 if(parseState==TITLE) 00445 { 00446 if(sizeof(cContentType)-1 <= bodyStart-i && !memcmp(cContentType, i, sizeof(cContentType)-1)) 00447 { 00448 parseState=CONTENT_TYPE; 00449 i += sizeof(cContentType)-1; 00450 contentTypeStart=i; 00451 } 00452 else if(sizeof(cContentDisposition)-1 <= bodyStart-i && !memcmp(cContentDisposition, i, sizeof(cContentDisposition)-1)) 00453 { 00454 parseState=CONTENT_DISPOSITION; 00455 i += sizeof(cContentDisposition)-1; 00456 } 00457 else 00458 parseState=SKIP; 00459 } 00460 else if(parseState==CONTENT_DISPOSITION) 00461 { 00462 if(sizeof(cFilename)-1 <= bodyStart-i && !memcmp(cFilename, i, sizeof(cFilename)-1)) 00463 { 00464 parseState=FILENAME; 00465 i += sizeof(cFilename)-1; 00466 filenameStart=i; 00467 } 00468 else if(sizeof(cName)-1 <= bodyStart-i && !memcmp(cName, i, sizeof(cName)-1)) 00469 { 00470 parseState=NAME; 00471 i += sizeof(cName)-1; 00472 nameStart=i; 00473 } 00474 } 00475 break; 00476 } 00477 } 00478 } 00479 } 00480 00481 00482 if(nameSize != -1) 00483 { 00484 basic_string<charT> name; 00485 charToString(nameStart, nameSize, name); 00486 00487 Post<charT>& thePost=posts[name]; 00488 if(contentTypeSize != -1) 00489 { 00490 thePost.type=Post<charT>::file; 00491 charToString(contentTypeStart, contentTypeSize, thePost.contentType); 00492 if(filenameSize != -1) charToString(filenameStart, filenameSize, thePost.filename); 00493 thePost.m_size=end-bodyStart; 00494 if(thePost.size()) 00495 { 00496 thePost.m_data = new char[thePost.size()]; 00497 memcpy(thePost.m_data, bodyStart, thePost.size()); 00498 } 00499 } 00500 else 00501 { 00502 thePost.type=Post<charT>::form; 00503 charToString(bodyStart, end-bodyStart, thePost.value); 00504 } 00505 } 00506 00507 bufferSize=bufferSize-(end-buffer+2); 00508 if(!bufferSize) 00509 { 00510 postBuffer.reset(); 00511 return; 00512 } 00513 buffer=new char[bufferSize]; 00514 memcpy(buffer, end+2, bufferSize); 00515 postBuffer.reset(buffer); 00516 postBufferSize=bufferSize; 00517 size=0; 00518 }} 00519 } 00520 00521 template void Fastcgipp::Http::Environment<char>::fillPostsUrlEncoded(const char* data, size_t size); 00522 template void Fastcgipp::Http::Environment<wchar_t>::fillPostsUrlEncoded(const char* data, size_t size); 00523 template<class charT> void Fastcgipp::Http::Environment<charT>::fillPostsUrlEncoded(const char* data, size_t size) 00524 { 00525 using namespace std; 00526 00527 if(!postBuffer.get() && size) 00528 { 00529 postBuffer.reset(new char[contentLength]); 00530 postBufferSize=0; 00531 } 00532 00533 // We don't want a buffer overflow so only process a max length of processLength 00534 size=min(size, contentLength-postBufferSize); 00535 00536 memcpy(postBuffer.get()+postBufferSize, data, size); 00537 postBufferSize+=size; 00538 00539 if(postBufferSize != contentLength) 00540 return; 00541 00542 char* nameStart=postBuffer.get(); 00543 size_t nameSize; 00544 char* valueStart=0; 00545 size_t valueSize; 00546 for(char* i=postBuffer.get(); i<=postBuffer.get()+postBufferSize; ++i) 00547 { 00548 if(*i == '=' && nameStart && !valueStart) 00549 { 00550 nameSize=percentEscapedToRealBytes(nameStart, nameStart, i-nameStart); 00551 valueStart=i+1; 00552 } 00553 else if( (i==postBuffer.get()+postBufferSize || *i == '&') && nameStart && valueStart) 00554 { 00555 valueSize=percentEscapedToRealBytes(valueStart, valueStart, i-valueStart); 00556 00557 basic_string<charT> name; 00558 charToString(nameStart, nameSize, name); 00559 nameStart=i+1; 00560 Post<charT>& thePost=posts[name]; 00561 thePost.type=Post<charT>::form; 00562 charToString(valueStart, valueSize, thePost.value); 00563 valueStart=0; 00564 } 00565 } 00566 } 00567 00568 bool Fastcgipp::Http::SessionId::seeded=false; 00569 00570 Fastcgipp::Http::SessionId::SessionId() 00571 { 00572 if(!seeded) 00573 { 00574 std::srand(boost::posix_time::microsec_clock::universal_time().time_of_day().fractional_seconds()); 00575 seeded=true; 00576 } 00577 00578 for(char* i=data; i<data+size; ++i) 00579 *i=char(rand()%256); 00580 timestamp = boost::posix_time::second_clock::universal_time(); 00581 } 00582 00583 template const Fastcgipp::Http::SessionId& Fastcgipp::Http::SessionId::operator=<const char>(const char* data_); 00584 template const Fastcgipp::Http::SessionId& Fastcgipp::Http::SessionId::operator=<const wchar_t>(const wchar_t* data_); 00585 template<class charT> const Fastcgipp::Http::SessionId& Fastcgipp::Http::SessionId::operator=(charT* data_) 00586 { 00587 std::memset(data, 0, size); 00588 base64Decode(data_, data_+size*4/3, data); 00589 timestamp = boost::posix_time::second_clock::universal_time(); 00590 return *this; 00591 } 00592 00593 template void Fastcgipp::Http::decodeUrlEncoded<char>(const char* data, size_t size, std::map<std::basic_string<char>, std::basic_string<char> >& output, const char fieldSeperator); 00594 template void Fastcgipp::Http::decodeUrlEncoded<wchar_t>(const char* data, size_t size, std::map<std::basic_string<wchar_t>, std::basic_string<wchar_t> >& output, const char fieldSeperator); 00595 template<class charT> void Fastcgipp::Http::decodeUrlEncoded(const char* data, size_t size, std::map<std::basic_string<charT>, std::basic_string<charT> >& output, const char fieldSeperator) 00596 { 00597 using namespace std; 00598 00599 boost::scoped_array<char> buffer(new char[size]); 00600 memcpy(buffer.get(), data, size); 00601 00602 char* nameStart=buffer.get(); 00603 size_t nameSize; 00604 char* valueStart=0; 00605 size_t valueSize; 00606 for(char* i=buffer.get(); i<=buffer.get()+size; ++i) 00607 { 00608 if(*i == ' ' && nameStart && !valueStart) 00609 ++nameStart; 00610 00611 else if(*i == '=' && nameStart && !valueStart) 00612 { 00613 nameSize=percentEscapedToRealBytes(nameStart, nameStart, i-nameStart); 00614 valueStart=i+1; 00615 } 00616 else if( (i==buffer.get()+size || *i == fieldSeperator) && nameStart && valueStart) 00617 { 00618 valueSize=percentEscapedToRealBytes(valueStart, valueStart, i-valueStart); 00619 00620 basic_string<charT> name; 00621 charToString(nameStart, nameSize, name); 00622 nameStart=i+1; 00623 basic_string<charT>& value=output[name]; 00624 charToString(valueStart, valueSize, value); 00625 valueStart=0; 00626 } 00627 } 00628 } 00629 00630 const char Fastcgipp::Http::base64Characters[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 00631 const char* Fastcgipp::Http::requestMethodLabels[]= { 00632 "ERROR", 00633 "HEAD", 00634 "GET", 00635 "POST", 00636 "PUT", 00637 "DELETE", 00638 "TRACE", 00639 "OPTIONS", 00640 "CONNECT" 00641 }; 00642 00643 template const std::basic_string<char>& Fastcgipp::Http::Environment<char>::findCookie(const char* key) const; 00644 template const std::basic_string<wchar_t>& Fastcgipp::Http::Environment<wchar_t>::findCookie(const wchar_t* key) const; 00645 template<class charT> const std::basic_string<charT>& Fastcgipp::Http::Environment<charT>::findCookie(const charT* key) const 00646 { 00647 static const std::basic_string<charT> emptyString; 00648 typename Cookies::const_iterator it=cookies.find(key); 00649 if(it==cookies.end()) 00650 return emptyString; 00651 else 00652 return it->second; 00653 } 00654 00655 template const std::basic_string<char>& Fastcgipp::Http::Environment<char>::findGet(const char* key) const; 00656 template const std::basic_string<wchar_t>& Fastcgipp::Http::Environment<wchar_t>::findGet(const wchar_t* key) const; 00657 template<class charT> const std::basic_string<charT>& Fastcgipp::Http::Environment<charT>::findGet(const charT* key) const 00658 { 00659 static const std::basic_string<charT> emptyString; 00660 typename Gets::const_iterator it=gets.find(key); 00661 if(it==gets.end()) 00662 return emptyString; 00663 else 00664 return it->second; 00665 } 00666 00667 template const Fastcgipp::Http::Post<char>& Fastcgipp::Http::Environment<char>::findPost(const char* key) const; 00668 template const Fastcgipp::Http::Post<wchar_t>& Fastcgipp::Http::Environment<wchar_t>::findPost(const wchar_t* key) const; 00669 template<class charT> const Fastcgipp::Http::Post<charT>& Fastcgipp::Http::Environment<charT>::findPost(const charT* key) const 00670 { 00671 static const Post<charT> emptyPost; 00672 typename Posts::const_iterator it=posts.find(key); 00673 if(it==posts.end()) 00674 return emptyPost; 00675 else 00676 return it->second; 00677 } 00678 00679 template bool Fastcgipp::Http::Environment<char>::checkForGet(const char* key) const; 00680 template bool Fastcgipp::Http::Environment<wchar_t>::checkForGet(const wchar_t* key) const; 00681 template<class charT> bool Fastcgipp::Http::Environment<charT>::checkForGet(const charT* key) const 00682 { 00683 typename Gets::const_iterator it=gets.find(key); 00684 if(it==gets.end()) 00685 return false; 00686 else 00687 return true; 00688 } 00689 00690 template bool Fastcgipp::Http::Environment<char>::checkForPost(const char* key) const; 00691 template bool Fastcgipp::Http::Environment<wchar_t>::checkForPost(const wchar_t* key) const; 00692 template<class charT> bool Fastcgipp::Http::Environment<charT>::checkForPost(const charT* key) const 00693 { 00694 typename Posts::const_iterator it=posts.find(key); 00695 if(it==posts.end()) 00696 return false; 00697 else 00698 return true; 00699 }