• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

http.cpp

Go to the documentation of this file.
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             charToString(value, valueSize, pathInfo);
00246          break;
00247       case 11:
00248          if(!memcmp(name, "HTTP_ACCEPT", 11))
00249             charToString(value, valueSize, acceptContentTypes);
00250          else if(!memcmp(name, "HTTP_COOKIE", 11))
00251             decodeUrlEncoded(value, valueSize, cookies, ';');
00252          else if(!memcmp(name, "SERVER_ADDR", 11))
00253             serverAddress.assign(value, value+valueSize);
00254          else if(!memcmp(name, "REMOTE_ADDR", 11))
00255             remoteAddress.assign(value, value+valueSize);
00256          else if(!memcmp(name, "SERVER_PORT", 11))
00257             serverPort=atoi(value, value+valueSize);
00258          else if(!memcmp(name, "REMOTE_PORT", 11))
00259             remotePort=atoi(value, value+valueSize);
00260          else if(!memcmp(name, "SCRIPT_NAME", 11))
00261             charToString(value, valueSize, scriptName);
00262          else if(!memcmp(name, "REQUEST_URI", 11))
00263             charToString(value, valueSize, requestUri);
00264          break;
00265       case 12:
00266          if(!memcmp(name, "HTTP_REFERER", 12) && valueSize)
00267             charToString(value, valueSize, referer);
00268          else if(!memcmp(name, "CONTENT_TYPE", 12))
00269          {
00270             const char* end=(char*)memchr(value, ';', valueSize);
00271             charToString(value, end?end-value:valueSize, contentType);
00272             if(end)
00273             {
00274                const char* start=(char*)memchr(end, '=', valueSize-(end-data));
00275                if(start)
00276                {
00277                   boundarySize=valueSize-(++start-value);
00278                   boundary.reset(new char[boundarySize]);
00279                   memcpy(boundary.get(), start, boundarySize);
00280                }
00281             }
00282          }
00283          else if(!memcmp(name, "QUERY_STRING", 12) && valueSize)
00284             decodeUrlEncoded(value, valueSize, gets);
00285          break;
00286       case 13:
00287          if(!memcmp(name, "DOCUMENT_ROOT", 13))
00288             charToString(value, valueSize, root);
00289          break;
00290       case 14:
00291          if(!memcmp(name, "REQUEST_METHOD", 14))
00292          {
00293             requestMethod = HTTP_METHOD_ERROR;
00294             switch(valueSize)
00295             {
00296             case 3:
00297                if(!memcmp(value, requestMethodLabels[HTTP_METHOD_GET], 3)) requestMethod = HTTP_METHOD_GET;
00298                else if(!memcmp(value, requestMethodLabels[HTTP_METHOD_PUT], 3)) requestMethod = HTTP_METHOD_PUT;
00299                break;
00300             case 4:
00301                if(!memcmp(value, requestMethodLabels[HTTP_METHOD_HEAD], 4)) requestMethod = HTTP_METHOD_HEAD;
00302                else if(!memcmp(value, requestMethodLabels[HTTP_METHOD_POST], 4)) requestMethod = HTTP_METHOD_POST;
00303                break;
00304             case 5:
00305                if(!memcmp(value, requestMethodLabels[HTTP_METHOD_TRACE], 5)) requestMethod = HTTP_METHOD_TRACE;
00306                break;
00307             case 6:
00308                if(!memcmp(value, requestMethodLabels[HTTP_METHOD_DELETE], 6)) requestMethod = HTTP_METHOD_DELETE;
00309                break;
00310             case 7:
00311                if(!memcmp(value, requestMethodLabels[HTTP_METHOD_OPTIONS], 7)) requestMethod = HTTP_METHOD_OPTIONS;
00312                else if(!memcmp(value, requestMethodLabels[HTTP_METHOD_OPTIONS], 7)) requestMethod = HTTP_METHOD_CONNECT;
00313                break;
00314             }
00315          }
00316          else if(!memcmp(name, "CONTENT_LENGTH", 14))
00317             contentLength=atoi(value, value+valueSize);
00318          break;
00319       case 15:
00320          if(!memcmp(name, "HTTP_USER_AGENT", 15))
00321             charToString(value, valueSize, userAgent);
00322          else if(!memcmp(name, "HTTP_KEEP_ALIVE", 15))
00323             keepAlive=atoi(value, value+valueSize);
00324          break;
00325       case 18:
00326          if(!memcmp(name, "HTTP_IF_NONE_MATCH", 18))
00327             etag=atoi(value, value+valueSize);
00328          break;
00329       case 19:
00330          if(!memcmp(name, "HTTP_ACCEPT_CHARSET", 19))
00331             charToString(value, valueSize, acceptCharsets);
00332          break;
00333       case 20:
00334          if(!memcmp(name, "HTTP_ACCEPT_LANGUAGE", 20))
00335             charToString(value, valueSize, acceptLanguages);
00336          break;
00337       case 22:
00338          if(!memcmp(name, "HTTP_IF_MODIFIED_SINCE", 22))
00339          {
00340             stringstream dateStream;
00341             dateStream.write(value, valueSize);
00342             dateStream.imbue(locale(locale::classic(), new posix_time::time_input_facet("%a, %d %b %Y %H:%M:%S GMT")));
00343             dateStream >> ifModifiedSince;
00344          }
00345          break;
00346       }
00347    }}
00348 }
00349 
00350 template void Fastcgipp::Http::Environment<char>::fillPostsMultipart(const char* data, size_t size);
00351 template void Fastcgipp::Http::Environment<wchar_t>::fillPostsMultipart(const char* data, size_t size);
00352 template<class charT> void Fastcgipp::Http::Environment<charT>::fillPostsMultipart(const char* data, size_t size)
00353 {
00354    using namespace std;
00355    while(1)
00356    {{
00357       size_t bufferSize=postBufferSize+size;
00358       char* buffer=new char[bufferSize];
00359       if(postBufferSize) memcpy(buffer, postBuffer.get(), postBufferSize);
00360       memcpy(buffer+postBufferSize, data, size);
00361       postBuffer.reset(buffer);
00362       postBufferSize=bufferSize;
00363 
00364       const char* end=0;
00365       for(const char* i=buffer+boundarySize; i<buffer+bufferSize-boundarySize; ++i)
00366          if(!memcmp(i, boundary.get(), boundarySize))
00367          {
00368             end=i;
00369             break;
00370          }
00371       
00372       if(!end)
00373          return;
00374 
00375       end-=4;
00376       const char* start=buffer+boundarySize+2;
00377       const char* bodyStart=start;
00378       for(; bodyStart<=end-4; ++bodyStart)
00379          if(!memcmp(bodyStart, "\r\n\r\n", 4)) break;
00380       bodyStart+=4;
00381 
00382 
00383       const char* contentTypeStart;
00384       ssize_t contentTypeSize=-1;
00385       const char* nameStart;
00386       ssize_t nameSize=-1;
00387       const char* filenameStart;
00388       ssize_t filenameSize=-1;
00389       // Fill out above values
00390       {
00391          const char cContentType[] = "Content-Type: ";
00392          const char cContentDisposition[] = "Content-Disposition: ";
00393          const char cFilename[] = "filename=\"";
00394          const char cName[] = "name=\"";
00395 
00396          enum ParseState { TITLE, CONTENT_DISPOSITION, FILENAME, NAME, CONTENT_TYPE, SKIP } parseState=TITLE;
00397          for(const char* i=start; i<bodyStart; ++i)
00398          {
00399             switch(*i)
00400             {
00401                case '\n':
00402                case '\r':
00403                {
00404                   if(parseState==CONTENT_TYPE)
00405                      contentTypeSize=i-contentTypeStart;
00406                   parseState=TITLE;
00407                   break;
00408                }
00409 
00410                case '"':
00411                {
00412                   if(parseState==FILENAME)
00413                   {
00414                      filenameSize=i-filenameStart;
00415                      parseState=CONTENT_DISPOSITION;
00416                   }
00417                   else if(parseState==NAME)
00418                   {
00419                      nameSize=i-nameStart;
00420                      parseState=CONTENT_DISPOSITION;
00421                   }
00422                   break;
00423                }
00424 
00425                default:
00426                {
00427                   if(parseState==TITLE)
00428                   {
00429                      if(sizeof(cContentType)-1 <= bodyStart-i && !memcmp(cContentType, i, sizeof(cContentType)-1))
00430                      {
00431                         parseState=CONTENT_TYPE;
00432                         i += sizeof(cContentType)-1;
00433                         contentTypeStart=i;
00434                      }
00435                      else if(sizeof(cContentDisposition)-1 <= bodyStart-i && !memcmp(cContentDisposition, i, sizeof(cContentDisposition)-1))
00436                      {
00437                         parseState=CONTENT_DISPOSITION;
00438                         i += sizeof(cContentDisposition)-1;
00439                      }
00440                      else
00441                         parseState=SKIP;
00442                   }
00443                   else if(parseState==CONTENT_DISPOSITION)
00444                   {
00445                      if(sizeof(cFilename)-1 <= bodyStart-i && !memcmp(cFilename, i, sizeof(cFilename)-1))
00446                      {
00447                         parseState=FILENAME;
00448                         i += sizeof(cFilename)-1;
00449                         filenameStart=i;
00450                      }
00451                      else if(sizeof(cName)-1 <= bodyStart-i && !memcmp(cName, i, sizeof(cName)-1))
00452                      {
00453                         parseState=NAME;
00454                         i += sizeof(cName)-1;
00455                         nameStart=i;
00456                      }
00457                   }
00458                   break;
00459                }
00460             }
00461          }
00462       }
00463 
00464       
00465       if(nameSize != -1)
00466       {
00467          basic_string<charT> name;
00468          charToString(nameStart, nameSize, name);
00469 
00470          Post<charT>& thePost=posts[name];
00471          if(contentTypeSize != -1)
00472          {
00473             thePost.type=Post<charT>::file;
00474             charToString(contentTypeStart, contentTypeSize, thePost.contentType);
00475             if(filenameSize != -1) charToString(filenameStart, filenameSize, thePost.filename);
00476             thePost.size=end-bodyStart;
00477             if(thePost.size)
00478             {
00479                thePost.data.reset(new char[thePost.size]);
00480                memcpy(thePost.data.get(), bodyStart, thePost.size);
00481             }
00482          }
00483          else
00484          {
00485             thePost.type=Post<charT>::form;
00486             charToString(bodyStart, end-bodyStart, thePost.value);
00487          }
00488       }
00489 
00490       bufferSize=bufferSize-(end-buffer+2);
00491       if(!bufferSize)
00492       {
00493          postBuffer.reset();
00494          return;
00495       }
00496       buffer=new char[bufferSize];
00497       memcpy(buffer, end+2, bufferSize);
00498       postBuffer.reset(buffer);
00499       postBufferSize=bufferSize;
00500       size=0;
00501    }}
00502 }
00503 
00504 template void Fastcgipp::Http::Environment<char>::fillPostsUrlEncoded(const char* data, size_t size);
00505 template void Fastcgipp::Http::Environment<wchar_t>::fillPostsUrlEncoded(const char* data, size_t size);
00506 template<class charT> void Fastcgipp::Http::Environment<charT>::fillPostsUrlEncoded(const char* data, size_t size)
00507 {
00508    using namespace std;
00509 
00510    if(!postBuffer.get() && size)
00511    {
00512       postBuffer.reset(new char[contentLength]);
00513       postBufferSize=0;
00514    }
00515 
00516    // We don't want a buffer overflow so only process a max length of processLength
00517    size=min(size, contentLength-postBufferSize);
00518 
00519    memcpy(postBuffer.get()+postBufferSize, data, size);
00520    postBufferSize+=size;
00521 
00522    if(postBufferSize != contentLength)
00523       return;
00524 
00525    char* nameStart=postBuffer.get();
00526    size_t nameSize;
00527    char* valueStart=0;
00528    size_t valueSize;
00529    for(char* i=postBuffer.get(); i<=postBuffer.get()+postBufferSize; ++i)
00530    {
00531       if(*i == '=' && nameStart && !valueStart)
00532       {
00533          nameSize=percentEscapedToRealBytes(nameStart, nameStart, i-nameStart);
00534          valueStart=i+1;
00535       }
00536       else if( (i==postBuffer.get()+postBufferSize || *i == '&') && nameStart && valueStart)
00537       {
00538          valueSize=percentEscapedToRealBytes(valueStart, valueStart, i-valueStart);
00539 
00540          basic_string<charT> name;
00541          charToString(nameStart, nameSize, name);
00542          nameStart=i+1;
00543          Post<charT>& thePost=posts[name];
00544          thePost.type=Post<charT>::form;
00545          charToString(valueStart, valueSize, thePost.value);
00546          valueStart=0;
00547       }
00548    }
00549 }
00550 
00551 bool Fastcgipp::Http::SessionId::seeded=false;
00552 
00553 Fastcgipp::Http::SessionId::SessionId()
00554 {
00555    if(!seeded)
00556    {
00557       std::srand(boost::posix_time::microsec_clock::universal_time().time_of_day().fractional_seconds());
00558       seeded=true;
00559    }
00560 
00561    for(char* i=data; i<data+size; ++i)
00562       *i=char(rand()%256);
00563    timestamp = boost::posix_time::second_clock::universal_time();
00564 }
00565 
00566 template const Fastcgipp::Http::SessionId& Fastcgipp::Http::SessionId::operator=<const char>(const char* data_);
00567 template const Fastcgipp::Http::SessionId& Fastcgipp::Http::SessionId::operator=<const wchar_t>(const wchar_t* data_);
00568 template<class charT> const Fastcgipp::Http::SessionId& Fastcgipp::Http::SessionId::operator=(charT* data_)
00569 {
00570    std::memset(data, 0, size);
00571    base64Decode(data_, data_+size*4/3, data);
00572    timestamp = boost::posix_time::second_clock::universal_time();
00573    return *this;
00574 }
00575 
00576 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);
00577 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);
00578 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)
00579 {
00580    using namespace std;
00581 
00582    boost::scoped_array<char> buffer(new char[size]);
00583    memcpy(buffer.get(), data, size);
00584 
00585    char* nameStart=buffer.get();
00586    size_t nameSize;
00587    char* valueStart=0;
00588    size_t valueSize;
00589    for(char* i=buffer.get(); i<=buffer.get()+size; ++i)
00590    {
00591       if(*i == ' ' && nameStart && !valueStart)
00592          ++nameStart;
00593 
00594       else if(*i == '=' && nameStart && !valueStart)
00595       {
00596          nameSize=percentEscapedToRealBytes(nameStart, nameStart, i-nameStart);
00597          valueStart=i+1;
00598       }
00599       else if( (i==buffer.get()+size || *i == fieldSeperator) && nameStart && valueStart)
00600       {
00601          valueSize=percentEscapedToRealBytes(valueStart, valueStart, i-valueStart);
00602 
00603          basic_string<charT> name;
00604          charToString(nameStart, nameSize, name);
00605          nameStart=i+1;
00606          basic_string<charT>& value=output[name];
00607          charToString(valueStart, valueSize, value);
00608          valueStart=0;
00609       }
00610    }
00611 }
00612 
00613 const char Fastcgipp::Http::base64Characters[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
00614 const char* Fastcgipp::Http::requestMethodLabels[]= {
00615    "ERROR",
00616    "HEAD",
00617    "GET",
00618    "POST",
00619    "PUT",
00620    "DELETE",
00621    "TRACE",
00622    "OPTIONS",
00623    "CONNECT"
00624 };
00625 
00626 template const std::basic_string<char>& Fastcgipp::Http::Environment<char>::findCookie(const char* key) const;
00627 template const std::basic_string<wchar_t>& Fastcgipp::Http::Environment<wchar_t>::findCookie(const wchar_t* key) const;
00628 template<class charT> const std::basic_string<charT>& Fastcgipp::Http::Environment<charT>::findCookie(const charT* key) const
00629 {
00630    static const std::basic_string<charT> emptyString;
00631    typename Cookies::const_iterator it=cookies.find(key);
00632    if(it==cookies.end())
00633       return emptyString;
00634    else
00635       return it->second;
00636 }
00637 
00638 template const std::basic_string<char>& Fastcgipp::Http::Environment<char>::findGet(const char* key) const;
00639 template const std::basic_string<wchar_t>& Fastcgipp::Http::Environment<wchar_t>::findGet(const wchar_t* key) const;
00640 template<class charT> const std::basic_string<charT>& Fastcgipp::Http::Environment<charT>::findGet(const charT* key) const
00641 {
00642    static const std::basic_string<charT> emptyString;
00643    typename Gets::const_iterator it=gets.find(key);
00644    if(it==gets.end())
00645       return emptyString;
00646    else
00647       return it->second;
00648 }
00649 
00650 template const Fastcgipp::Http::Post<char>& Fastcgipp::Http::Environment<char>::findPost(const char* key) const;
00651 template const Fastcgipp::Http::Post<wchar_t>& Fastcgipp::Http::Environment<wchar_t>::findPost(const wchar_t* key) const;
00652 template<class charT> const Fastcgipp::Http::Post<charT>& Fastcgipp::Http::Environment<charT>::findPost(const charT* key) const
00653 {
00654    static const Post<charT> emptyPost;
00655    typename Posts::const_iterator it=posts.find(key);
00656    if(it==posts.end())
00657       return emptyPost;
00658    else
00659       return it->second;
00660 }

Generated on Fri Jan 21 2011 12:29:32 for fastcgi++ by  doxygen 1.7.2