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

http.hpp

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 #ifndef HTTP_HPP
00023 #define HTTP_HPP
00024 
00025 #include <string>
00026 #include <boost/shared_array.hpp>
00027 #include <boost/scoped_array.hpp>
00028 #include <boost/date_time/posix_time/posix_time.hpp>
00029 #include <ostream>
00030 #include <istream>
00031 #include <cstring>
00032 #include <sstream>
00033 #include <map>
00034 
00035 #include <fastcgi++/exceptions.hpp>
00036 #include <fastcgi++/protocol.hpp>
00037 
00039 namespace Fastcgipp
00040 {
00042    namespace Http
00043    {
00045 
00056       template<class charT> struct Post
00057       {
00059          enum Type { file, form } type;
00061          std::basic_string<charT> value;
00063          std::basic_string<charT>& filename;
00065          std::basic_string<charT> contentType;
00067          boost::shared_array<char> data;
00069          size_t size;
00070 
00071          Post(): filename(value) {}
00072          Post(const Post& x):
00073             type(x.type),
00074             value(x.value),
00075             filename(value),
00076             contentType(x.contentType),
00077             data(x.data),
00078             size(x.size)
00079          {}
00080       };
00081 
00083       enum RequestMethod
00084       {
00085          HTTP_METHOD_ERROR,
00086          HTTP_METHOD_HEAD,
00087          HTTP_METHOD_GET,
00088          HTTP_METHOD_POST,
00089          HTTP_METHOD_PUT,
00090          HTTP_METHOD_DELETE,
00091          HTTP_METHOD_TRACE,
00092          HTTP_METHOD_OPTIONS,
00093          HTTP_METHOD_CONNECT
00094       };
00095       extern const char* requestMethodLabels[];
00096       template<class charT, class Traits> inline std::basic_ostream<charT, Traits>& operator<<(std::basic_ostream<charT, Traits>& os, const RequestMethod requestMethod) { return os << requestMethodLabels[requestMethod]; }
00097    
00099 
00105       class Address
00106       {
00107       public:
00109 
00112          const unsigned int& getInt() const { return data; }
00114 
00117          Address operator=(unsigned int data_) { data=data_; return *this; }
00118          Address operator=(Address address) { data=address.data; return *this; }
00119          Address(const Address& address): data(address.data) { }
00121 
00124          explicit Address(unsigned int data_): data(data_) { }
00126          Address(): data(0) { }
00128 
00135          void assign(const char* start, const char* end);
00136          inline bool operator==(const Address x) const { return data==x.data; }
00137          inline bool operator>(const Address x) const { return data>x.data; }
00138          inline bool operator<(const Address x) const { return data<x.data; }
00139          inline bool operator<=(const Address x) const { return data<=x.data; }
00140          inline bool operator>=(const Address x) const { return data>=x.data; }
00141          inline Address operator&(const Address x) const { return Address(data&x.data); }
00142 
00143       private:
00144          template<class charT, class Traits> friend std::basic_ostream<charT, Traits>& operator<<(std::basic_ostream<charT, Traits>& os, const Address& address);
00145          template<class charT, class Traits> friend std::basic_istream<charT, Traits>& operator>>(std::basic_istream<charT, Traits>& is, Address& address);
00147          unsigned int data;
00148       };
00149 
00151 
00154       template<class charT, class Traits> std::basic_ostream<charT, Traits>& operator<<(std::basic_ostream<charT, Traits>& os, const Address& address);
00156 
00160       template<class charT, class Traits> std::basic_istream<charT, Traits>& operator>>(std::basic_istream<charT, Traits>& is, Address& address);
00161 
00163 
00169       template<class charT> struct Environment
00170       {
00172          std::basic_string<charT> host;
00174          std::basic_string<charT> userAgent;
00176          std::basic_string<charT> acceptContentTypes;
00178          std::basic_string<charT> acceptLanguages;
00180          std::basic_string<charT> acceptCharsets;
00182          std::basic_string<charT> referer;
00184          std::basic_string<charT> contentType;
00186          std::basic_string<charT> root;
00188          std::basic_string<charT> scriptName;
00190          RequestMethod requestMethod;
00192          std::basic_string<charT> requestUri;
00194          std::basic_string<charT> pathInfo;
00196          int etag;
00198          int keepAlive;
00200          unsigned int contentLength;
00202          Address serverAddress;
00204          Address remoteAddress;
00206          uint16_t serverPort;
00208          uint16_t remotePort;
00210          boost::posix_time::ptime ifModifiedSince;
00211 
00212          typedef std::map<std::basic_string<charT>, std::basic_string<charT> > Cookies;
00214          Cookies cookies;
00216          const std::basic_string<charT>& findCookie(const charT* key) const;
00217 
00218          typedef std::map<std::basic_string<charT>, std::basic_string<charT> > Gets;
00220          Gets gets;
00222          const std::basic_string<charT>& findGet(const charT* key) const;
00223 
00224          typedef std::map<std::basic_string<charT>, Post<charT> > Posts;
00226          Posts posts;
00228          const Post<charT>& findPost(const charT* key) const;
00229 
00231 
00239          void fill(const char* data, size_t size);
00241 
00250          void fillPostsMultipart(const char* data, size_t size);
00251 
00253 
00263          void fillPostsUrlEncoded(const char* data, size_t size);
00264 
00266          void clearPostBuffer() { postBuffer.reset(); postBufferSize=0; }
00267 
00268          Environment(): etag(0), keepAlive(0), serverPort(0), remotePort(0), contentLength(0) {}
00269       private:
00271          boost::scoped_array<char> boundary;
00273          size_t boundarySize;
00274 
00276          boost::scoped_array<char> postBuffer;
00278          size_t postBufferSize;
00279       };
00280 
00282 
00288       void charToString(const char* data, size_t size, std::wstring& string);
00289 
00291 
00297       inline void charToString(const char* data, size_t size, std::string& string) { string.assign(data, size); }
00298 
00300 
00310       int atoi(const char* start, const char* end);
00311 
00313 
00320       template<class charT> void decodeUrlEncoded(const char* data, size_t size, std::map<std::basic_string<charT>, std::basic_string<charT> >& output, const char fieldSeperator='&');
00321 
00323 
00333       size_t percentEscapedToRealBytes(const char* source, char* destination, size_t size);
00334 
00338       extern const char base64Characters[];
00339 
00352       template<class In, class Out> void base64Encode(In start, In end, Out destination);
00353 
00370       template<class In, class Out> Out base64Decode(In start, In end, Out destination);
00371 
00375       class SessionId
00376       {
00380          public: static const int size=12;
00381 
00382       private:
00386          char data[size];
00387 
00391          boost::posix_time::ptime timestamp;
00392 
00396          static bool seeded;
00397 
00398          template<class T> friend class Sessions;
00399       public:
00403          SessionId();
00404 
00405          SessionId(const SessionId& x): timestamp(x.timestamp) { std::memcpy(data, x.data, size); }
00406          const SessionId& operator=(const SessionId& x) { std::memcpy(data, x.data, size); timestamp=x.timestamp; return *this; }
00407 
00415          template<class charT> const SessionId& operator=(charT* data_);
00416 
00424          template<class charT> SessionId(charT* data_) { *this=data_; }
00425 
00426          template<class charT, class Traits> friend std::basic_ostream<charT, Traits>& operator<<(std::basic_ostream<charT, Traits>& os, const SessionId& x);
00427 
00428          bool operator<(const SessionId& x) const { return std::memcmp(data, x.data, SessionId::size)<0; }
00429          bool operator==(const SessionId& x) const { return std::memcmp(data, x.data, SessionId::size)==0; }
00430 
00434          void refresh() const { *const_cast<boost::posix_time::ptime*>(&timestamp)=boost::posix_time::second_clock::universal_time(); }
00435 
00436          const char* getInternalPointer() const { return data; }
00437       };
00438 
00442       template<class charT, class Traits> std::basic_ostream<charT, Traits>& operator<<(std::basic_ostream<charT, Traits>& os, const SessionId& x) { base64Encode(x.data, x.data+SessionId::size, std::ostream_iterator<charT, charT, Traits>(os)); return os; }
00443 
00454       template<class T> class Sessions: public std::map<SessionId, T>
00455       {
00456       private:
00460          const boost::posix_time::seconds keepAlive;
00461 
00465          const boost::posix_time::seconds cleanupFrequency;
00466 
00470          boost::posix_time::ptime cleanupTime;
00471       public:
00472          typedef typename std::map<SessionId, T>::iterator iterator;
00473          typedef typename std::map<SessionId, T>::const_iterator const_iterator;
00480          Sessions(int keepAlive_, int cleanupFrequency_): keepAlive(boost::posix_time::seconds(keepAlive_)), cleanupFrequency(boost::posix_time::seconds(cleanupFrequency_)), cleanupTime(boost::posix_time::second_clock::universal_time()+cleanupFrequency) { }
00481             
00487          void cleanup();
00488 
00496          iterator generate(const T& value_ = T());
00497 
00498          boost::posix_time::ptime getExpiry(const_iterator it) const { return it->first.timestamp+keepAlive; }
00499       };
00500    }
00501 }
00502 
00503 template<class T> void Fastcgipp::Http::Sessions<T>::cleanup()
00504 {
00505    if(boost::posix_time::second_clock::universal_time() < cleanupTime)
00506       return;
00507    boost::posix_time::ptime oldest(boost::posix_time::second_clock::universal_time()-keepAlive);
00508    iterator it=this->begin();
00509    while(it!=this->end())
00510    {
00511       if(it->first.timestamp < oldest)
00512          erase(it++);
00513       else
00514          ++it;
00515    }
00516    cleanupTime=boost::posix_time::second_clock::universal_time()+cleanupFrequency;
00517 }
00518 
00519 template<class In, class Out> Out Fastcgipp::Http::base64Decode(In start, In end, Out destination)
00520 {
00521    Out dest=destination;
00522 
00523    for(int buffer, bitPos=-8, padStart; start!=end || bitPos>-6; ++dest)
00524    {
00525       if(bitPos==-8)
00526       {
00527          bitPos=18;
00528          padStart=-9;
00529          buffer=0;
00530          while(bitPos!=-6)
00531          {
00532             if(start==end) return destination;
00533             int value=*start++;
00534             if(value >= 'A' && 'Z' >= value) value -= 'A';
00535             else if(value >= 'a' && 'z' >= value) value -= 'a' - 26;
00536             else if(value >= '0' && '9' >= value) value -= '0' - 52;
00537             else if(value == '+') value = 62;
00538             else if(value == '/') value = 63;
00539             else if(value == '=') { padStart=bitPos; break; }
00540             else return destination;
00541 
00542             buffer |= value << bitPos;
00543             bitPos-=6;
00544          }
00545          bitPos=16;
00546       }
00547 
00548       *dest = (buffer >> bitPos) & 0xff;
00549       bitPos-=8;
00550       if(padStart>=bitPos)
00551       {
00552          if( (padStart-bitPos)/6 )
00553             return dest;
00554          else
00555             return ++dest;
00556       }
00557    }
00558 
00559    return dest;
00560 }
00561 
00562 template<class In, class Out> void Fastcgipp::Http::base64Encode(In start, In end, Out destination)
00563 {
00564    for(int buffer, bitPos=-6, padded; start!=end || bitPos>-6; ++destination)
00565    {
00566       if(bitPos==-6)
00567       {
00568          bitPos=16;
00569          buffer=0;
00570          padded=-6;
00571          while(bitPos!=-8)
00572          {
00573             if(start!=end) 
00574                buffer |= (uint32_t)*(unsigned char*)start++ << bitPos;
00575             else padded+=6;
00576             bitPos-=8;
00577          }
00578          bitPos=18;
00579       }
00580 
00581       if(padded == bitPos)
00582       {
00583          *destination='=';
00584          padded-=6;
00585       }
00586       else *destination=base64Characters[ (buffer >> bitPos)&0x3f ];
00587       bitPos -= 6;
00588    }
00589 }
00590 
00591 template<class T> typename Fastcgipp::Http::Sessions<T>::iterator Fastcgipp::Http::Sessions<T>::generate(const T& value_)
00592 {
00593    std::pair<iterator,bool> retVal;
00594    retVal.second=false;
00595    while(!retVal.second)
00596       retVal=insert(std::pair<SessionId, T>(SessionId(), value_));
00597    return retVal.first;
00598 }
00599 
00600 #endif

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