00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <boost/lexical_cast.hpp>
00011 #include <boost/thread/mutex.hpp>
00012 #include <pion/net/HTTPTypes.hpp>
00013 #include <cstdio>
00014 #include <ctime>
00015
00016
00017 namespace pion {
00018 namespace net {
00019
00020
00021
00022 const std::string HTTPTypes::STRING_EMPTY;
00023 const std::string HTTPTypes::STRING_CRLF("\x0D\x0A");
00024 const std::string HTTPTypes::STRING_HTTP_VERSION("HTTP/");
00025 const std::string HTTPTypes::HEADER_NAME_VALUE_DELIMITER(": ");
00026
00027
00028 const std::string HTTPTypes::HEADER_HOST("Host");
00029 const std::string HTTPTypes::HEADER_COOKIE("Cookie");
00030 const std::string HTTPTypes::HEADER_SET_COOKIE("Set-Cookie");
00031 const std::string HTTPTypes::HEADER_CONNECTION("Connection");
00032 const std::string HTTPTypes::HEADER_CONTENT_TYPE("Content-Type");
00033 const std::string HTTPTypes::HEADER_CONTENT_LENGTH("Content-Length");
00034 const std::string HTTPTypes::HEADER_CONTENT_LOCATION("Content-Location");
00035 const std::string HTTPTypes::HEADER_CONTENT_ENCODING("Content-Encoding");
00036 const std::string HTTPTypes::HEADER_LAST_MODIFIED("Last-Modified");
00037 const std::string HTTPTypes::HEADER_IF_MODIFIED_SINCE("If-Modified-Since");
00038 const std::string HTTPTypes::HEADER_TRANSFER_ENCODING("Transfer-Encoding");
00039 const std::string HTTPTypes::HEADER_LOCATION("Location");
00040 const std::string HTTPTypes::HEADER_AUTHORIZATION("Authorization");
00041 const std::string HTTPTypes::HEADER_REFERER("Referer");
00042 const std::string HTTPTypes::HEADER_USER_AGENT("User-Agent");
00043 const std::string HTTPTypes::HEADER_X_FORWARDED_FOR("X-Forwarded-For");
00044
00045
00046 const std::string HTTPTypes::CONTENT_TYPE_HTML("text/html");
00047 const std::string HTTPTypes::CONTENT_TYPE_TEXT("text/plain");
00048 const std::string HTTPTypes::CONTENT_TYPE_XML("text/xml");
00049 const std::string HTTPTypes::CONTENT_TYPE_URLENCODED("application/x-www-form-urlencoded");
00050
00051
00052 const std::string HTTPTypes::REQUEST_METHOD_HEAD("HEAD");
00053 const std::string HTTPTypes::REQUEST_METHOD_GET("GET");
00054 const std::string HTTPTypes::REQUEST_METHOD_PUT("PUT");
00055 const std::string HTTPTypes::REQUEST_METHOD_POST("POST");
00056 const std::string HTTPTypes::REQUEST_METHOD_DELETE("DELETE");
00057
00058
00059 const std::string HTTPTypes::RESPONSE_MESSAGE_OK("OK");
00060 const std::string HTTPTypes::RESPONSE_MESSAGE_CREATED("Created");
00061 const std::string HTTPTypes::RESPONSE_MESSAGE_NO_CONTENT("No Content");
00062 const std::string HTTPTypes::RESPONSE_MESSAGE_FOUND("Found");
00063 const std::string HTTPTypes::RESPONSE_MESSAGE_UNAUTHORIZED("Unauthorized");
00064 const std::string HTTPTypes::RESPONSE_MESSAGE_FORBIDDEN("Forbidden");
00065 const std::string HTTPTypes::RESPONSE_MESSAGE_NOT_FOUND("Not Found");
00066 const std::string HTTPTypes::RESPONSE_MESSAGE_METHOD_NOT_ALLOWED("Method Not Allowed");
00067 const std::string HTTPTypes::RESPONSE_MESSAGE_NOT_MODIFIED("Not Modified");
00068 const std::string HTTPTypes::RESPONSE_MESSAGE_BAD_REQUEST("Bad Request");
00069 const std::string HTTPTypes::RESPONSE_MESSAGE_SERVER_ERROR("Server Error");
00070 const std::string HTTPTypes::RESPONSE_MESSAGE_NOT_IMPLEMENTED("Not Implemented");
00071 const std::string HTTPTypes::RESPONSE_MESSAGE_CONTINUE("Continue");
00072
00073
00074 const unsigned int HTTPTypes::RESPONSE_CODE_OK = 200;
00075 const unsigned int HTTPTypes::RESPONSE_CODE_CREATED = 201;
00076 const unsigned int HTTPTypes::RESPONSE_CODE_NO_CONTENT = 204;
00077 const unsigned int HTTPTypes::RESPONSE_CODE_FOUND = 302;
00078 const unsigned int HTTPTypes::RESPONSE_CODE_UNAUTHORIZED = 401;
00079 const unsigned int HTTPTypes::RESPONSE_CODE_FORBIDDEN = 403;
00080 const unsigned int HTTPTypes::RESPONSE_CODE_NOT_FOUND = 404;
00081 const unsigned int HTTPTypes::RESPONSE_CODE_METHOD_NOT_ALLOWED = 405;
00082 const unsigned int HTTPTypes::RESPONSE_CODE_NOT_MODIFIED = 304;
00083 const unsigned int HTTPTypes::RESPONSE_CODE_BAD_REQUEST = 400;
00084 const unsigned int HTTPTypes::RESPONSE_CODE_SERVER_ERROR = 500;
00085 const unsigned int HTTPTypes::RESPONSE_CODE_NOT_IMPLEMENTED = 501;
00086 const unsigned int HTTPTypes::RESPONSE_CODE_CONTINUE = 100;
00087
00088
00089
00090
00091 bool HTTPTypes::base64_decode(const std::string &input, std::string &output)
00092 {
00093 static const char nop = -1;
00094 static const char decoding_data[] = {
00095 nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop,
00096 nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop,
00097 nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop, 62, nop,nop,nop, 63,
00098 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,nop,nop, nop,nop,nop,nop,
00099 nop, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
00100 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,nop, nop,nop,nop,nop,
00101 nop,26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
00102 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,nop, nop,nop,nop,nop,
00103 nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop,
00104 nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop,
00105 nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop,
00106 nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop,
00107 nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop,
00108 nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop,
00109 nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop,
00110 nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop
00111 };
00112
00113 unsigned int input_length=input.size();
00114 const char * input_ptr = input.data();
00115
00116
00117 output.clear();
00118 output.reserve(((input_length+2)/3)*4);
00119
00120
00121
00122
00123 for (unsigned int i=0; i<input_length;i++) {
00124 char base64code0;
00125 char base64code1;
00126 char base64code2 = 0;
00127 char base64code3;
00128
00129 base64code0 = decoding_data[static_cast<int>(input_ptr[i])];
00130 if(base64code0==nop)
00131 return false;
00132 if(!(++i<input_length))
00133 return false;
00134 base64code1 = decoding_data[static_cast<int>(input_ptr[i])];
00135 if(base64code1==nop)
00136 return false;
00137
00138 output += ((base64code0 << 2) | ((base64code1 >> 4) & 0x3));
00139
00140 if(++i<input_length) {
00141 char c = input_ptr[i];
00142 if(c =='=') {
00143 BOOST_ASSERT( (base64code1 & 0x0f)==0);
00144 return true;
00145 }
00146 base64code2 = decoding_data[static_cast<int>(input_ptr[i])];
00147 if(base64code2==nop)
00148 return false;
00149
00150 output += ((base64code1 << 4) & 0xf0) | ((base64code2 >> 2) & 0x0f);
00151 }
00152
00153 if(++i<input_length) {
00154 char c = input_ptr[i];
00155 if(c =='=') {
00156 BOOST_ASSERT( (base64code2 & 0x03)==0);
00157 return true;
00158 }
00159 base64code3 = decoding_data[static_cast<int>(input_ptr[i])];
00160 if(base64code3==nop)
00161 return false;
00162
00163 output += (((base64code2 << 6) & 0xc0) | base64code3 );
00164 }
00165
00166 }
00167
00168 return true;
00169 }
00170
00171 bool HTTPTypes::base64_encode(const std::string &input, std::string &output)
00172 {
00173 static const char encoding_data[] =
00174 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
00175
00176 unsigned int input_length=input.size();
00177 const char * input_ptr = input.data();
00178
00179
00180 output.clear();
00181 output.reserve(((input_length+2)/3)*4);
00182
00183
00184
00185
00186 for (unsigned int i=0; i<input_length;i++) {
00187 int base64code0=0;
00188 int base64code1=0;
00189 int base64code2=0;
00190 int base64code3=0;
00191
00192 base64code0 = (input_ptr[i] >> 2) & 0x3f;
00193 output += encoding_data[base64code0];
00194 base64code1 = (input_ptr[i] << 4 ) & 0x3f;
00195
00196 if (++i < input_length) {
00197 base64code1 |= (input_ptr[i] >> 4) & 0x0f;
00198 output += encoding_data[base64code1];
00199 base64code2 = (input_ptr[i] << 2) & 0x3f;
00200
00201 if (++i < input_length) {
00202 base64code2 |= (input_ptr[i] >> 6) & 0x03;
00203 base64code3 = input_ptr[i] & 0x3f;
00204 output += encoding_data[base64code2];
00205 output += encoding_data[base64code3];
00206 } else {
00207 output += encoding_data[base64code2];
00208 output += '=';
00209 }
00210 } else {
00211 output += encoding_data[base64code1];
00212 output += '=';
00213 output += '=';
00214 }
00215 }
00216
00217 return true;
00218 }
00219
00220 std::string HTTPTypes::url_decode(const std::string& str)
00221 {
00222 char decode_buf[3];
00223 std::string result;
00224 result.reserve(str.size());
00225
00226 for (std::string::size_type pos = 0; pos < str.size(); ++pos) {
00227 switch(str[pos]) {
00228 case '+':
00229
00230 result += ' ';
00231 break;
00232 case '%':
00233
00234 if (pos + 2 < str.size()) {
00235 decode_buf[0] = str[++pos];
00236 decode_buf[1] = str[++pos];
00237 decode_buf[2] = '\0';
00238 result += static_cast<char>( strtol(decode_buf, 0, 16) );
00239 } else {
00240
00241 result += '%';
00242 }
00243 break;
00244 default:
00245
00246 result += str[pos];
00247 }
00248 };
00249
00250 return result;
00251 }
00252
00253 std::string HTTPTypes::url_encode(const std::string& str)
00254 {
00255 char encode_buf[4];
00256 std::string result;
00257 encode_buf[0] = '%';
00258 result.reserve(str.size());
00259
00260
00261
00262
00263 for (std::string::size_type pos = 0; pos < str.size(); ++pos) {
00264 switch(str[pos]) {
00265 default:
00266 if (str[pos] > 32 && str[pos] < 127) {
00267
00268 result += str[pos];
00269 break;
00270 }
00271
00272 case ' ':
00273 case '$': case '&': case '+': case ',': case '/': case ':':
00274 case ';': case '=': case '?': case '@': case '"': case '<':
00275 case '>': case '#': case '%': case '{': case '}': case '|':
00276 case '\\': case '^': case '~': case '[': case ']': case '`':
00277
00278 sprintf(encode_buf+1, "%.2X", (unsigned char)(str[pos]));
00279 result += encode_buf;
00280 break;
00281 }
00282 };
00283
00284 return result;
00285 }
00286
00287 std::string HTTPTypes::get_date_string(const time_t t)
00288 {
00289
00290 static boost::mutex time_mutex;
00291 static const char *TIME_FORMAT = "%a, %d %b %Y %H:%M:%S GMT";
00292 static const unsigned int TIME_BUF_SIZE = 100;
00293 char time_buf[TIME_BUF_SIZE+1];
00294
00295 boost::mutex::scoped_lock time_lock(time_mutex);
00296 if (strftime(time_buf, TIME_BUF_SIZE, TIME_FORMAT, gmtime(&t)) == 0)
00297 time_buf[0] = '\0';
00298 time_lock.unlock();
00299
00300 return std::string(time_buf);
00301 }
00302
00303 std::string HTTPTypes::make_query_string(const QueryParams& query_params)
00304 {
00305 std::string query_string;
00306 for (QueryParams::const_iterator i = query_params.begin(); i != query_params.end(); ++i) {
00307 if (i != query_params.begin())
00308 query_string += '&';
00309 query_string += url_encode(i->first);
00310 query_string += '=';
00311 query_string += url_encode(i->second);
00312 }
00313 return query_string;
00314 }
00315
00316 std::string HTTPTypes::make_set_cookie_header(const std::string& name,
00317 const std::string& value,
00318 const std::string& path,
00319 const bool has_max_age,
00320 const unsigned long max_age)
00321 {
00322 std::string set_cookie_header(name);
00323 set_cookie_header += "=\"";
00324 set_cookie_header += value;
00325 set_cookie_header += "\"; Version=\"1\"";
00326 if (! path.empty()) {
00327 set_cookie_header += "; Path=\"";
00328 set_cookie_header += path;
00329 set_cookie_header += '\"';
00330 }
00331 if (has_max_age) {
00332 set_cookie_header += "; Max-Age=\"";
00333 set_cookie_header += boost::lexical_cast<std::string>(max_age);
00334 set_cookie_header += '\"';
00335 }
00336 return set_cookie_header;
00337 }
00338
00339
00340 }
00341 }
00342