1 #ifndef _YAHTTP_UTILITY_HPP
2 #define _YAHTTP_UTILITY_HPP 1
5 static const char *
MONTHS[] = {0,
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec",0};
6 static const char *
DAYS[] = {
"Sun",
"Mon",
"Tue",
"Wed",
"Thu",
"Fri",
"Sat",0};
10 bool operator() (
const std::string& lhs,
const std::string& rhs)
const {
12 std::string::const_iterator lhi = lhs.begin();
13 std::string::const_iterator rhi = rhs.begin();
14 for(;lhi != lhs.end() && rhi != rhs.end(); lhi++, rhi++)
15 if ((v = ::tolower(*lhi) - ::tolower(*rhi)) != 0)
return v<0;
16 if (lhi == lhs.end() && rhi != rhs.end())
return true;
17 if (lhi != lhs.end() && rhi == rhs.end())
return false;
22 typedef std::map<std::string,std::string,ASCIICINullSafeComparator>
strstr_map_t;
60 #ifdef HAVE_LOCALTIME_R
69 #ifndef HAVE_TM_GMTOFF
71 # ifdef HAVE_LOCALTIME_R
92 #ifndef HAVE_TM_GMTOFF
98 year = tm->tm_year + 1900;
99 month = tm->tm_mon + 1;
105 #ifdef HAVE_TM_GMTOFF
112 if (wday < 0 || wday > 6)
throw "Invalid date";
113 if (month < 1 || month > 12)
throw "Invalid date";
114 if (
year < 0)
throw "Invalid date";
115 if (hours < 0 || hours > 23 ||
116 minutes < 0 || minutes > 59 ||
117 seconds < 0 || seconds > 60)
throw "Invalid date";
121 std::ostringstream oss;
124 std::setfill(
'0') << std::setw(2) <<
year <<
" " <<
125 std::setfill(
'0') << std::setw(2) <<
hours <<
":" <<
126 std::setfill(
'0') << std::setw(2) <<
minutes <<
":" <<
127 std::setfill(
'0') << std::setw(2) <<
seconds <<
" ";
131 oss << std::setfill(
'0') << std::setw(2) << (tmp_off/3600);
132 oss << std::setfill(
'0') << std::setw(2) << (tmp_off%3600)/60;
138 std::ostringstream oss;
140 oss << std::setfill(
'0') << std::setw(2) <<
day <<
"-" <<
MONTHS[
month] <<
"-" <<
year <<
" " <<
141 std::setfill(
'0') << std::setw(2) <<
hours <<
":" <<
142 std::setfill(
'0') << std::setw(2) <<
minutes <<
":" <<
143 std::setfill(
'0') << std::setw(2) <<
seconds <<
" GMT";
150 #ifdef HAVE_TM_GMTOFF
151 if ( (ptr = strptime(rfc822_date.c_str(),
"%a, %d %b %Y %T %z", &tm)) != NULL) {
153 if ( (ptr = strptime(rfc822_date.c_str(),
"%a, %d %b %Y %T", &tm)) != NULL) {
156 while(*ptr && ::isspace(*ptr)) ptr++;
157 if (*ptr ==
'+') sign = 0;
158 else if (*ptr ==
'-') sign = -1;
159 else throw "Unparseable date";
162 while(*ptr && ::isdigit(*ptr)) ptr++;
164 while(*ptr && ::isspace(*ptr)) ptr++;
165 if (*ptr)
throw "Unparseable date";
168 throw "Unparseable date";
175 if ( (ptr = strptime(cookie_date.c_str(),
"%d-%b-%Y %T", &tm)) != NULL) {
176 while(*ptr && ( ::isspace(*ptr) || ::isalnum(*ptr) )) ptr++;
177 if (*ptr)
throw "Unparseable date (non-final)";
181 throw "Unparseable date (did not match pattern cookie)";
187 tm.tm_year =
year-1900;
194 #ifdef HAVE_TM_GMTOFF
204 static std::string
decodeURL(
const std::string& component) {
205 std::string result = component;
208 while((pos1 = result.find_first_of(
"%", pos2))!=std::string::npos) {
211 if (pos1 + 2 > result.length())
return result;
212 code = result.substr(pos1+1, 2);
213 a = std::tolower(code[0]); b = std::tolower(code[1]);
215 if (((
'0' > a || a >
'9') && (
'a' > a || a >
'f')) ||
216 ((
'0' > b || b >
'9') && (
'a' > b || b >
'f'))) {
221 if (
'0' <= a && a <=
'9') a = a -
'0';
222 if (
'a' <= a && a <=
'f') a = a -
'a' + 0x0a;
223 if (
'0' <= b && b <=
'9') b = b -
'0';
224 if (
'a' <= b && b <=
'f') b = b -
'a' + 0x0a;
227 result = result.replace(pos1,3,1,c);
233 static std::string
encodeURL(
const std::string& component,
bool asUrl =
true) {
234 std::string result = component;
235 std::string skip =
"+-.:,&;_#%[]?/@(){}=";
238 for(std::string::iterator iter = result.begin(); iter != result.end(); iter++) {
239 if (!std::isalnum(*iter) && (!asUrl || skip.find(*iter) == std::string::npos)) {
241 pos = std::distance(result.begin(), iter);
242 ::snprintf(repl,3,
"%02x", static_cast<unsigned char>(*iter));
243 result = result.replace(pos, 1,
"%", 1).insert(pos+1, repl, 2);
244 iter = result.begin() + pos + 2;
250 static std::string
encodeURL(
const std::wstring& component,
bool asUrl =
true) {
251 unsigned char const *p =
reinterpret_cast<unsigned char const*
>(&component[0]);
252 std::size_t s = component.size() *
sizeof((*component.begin()));
253 std::vector<unsigned char> vec(p, p+s);
255 std::ostringstream result;
256 std::string skip =
"+-.,&;_#%[]?/@(){}=";
257 for(std::vector<unsigned char>::iterator iter = vec.begin(); iter != vec.end(); iter++) {
258 if (!std::isalnum((
char)*iter) && (!asUrl || skip.find((
char)*iter) == std::string::npos)) {
260 result <<
"%" << std::hex << std::setw(2) << std::setfill('0') << static_cast<unsigned int>(*iter);
261 }
else result << (char)*iter;
275 return "Non-Authoritative Information";
279 return "Reset Content";
281 return "Partial Content";
283 return "Multiple Choices";
285 return "Moved Permanently";
291 return "Not Modified";
295 return "Temporary Redirect";
297 return "Bad Request";
299 return "Unauthorized";
301 return "Payment Required";
307 return "Method Not Allowed";
309 return "Not Acceptable";
311 return "Proxy Authentication Required";
313 return "Request Time-out";
319 return "Length Required";
321 return "Precondition Failed";
323 return "Request Entity Too Large";
325 return "Request-URI Too Large";
327 return "Unsupported Media Type";
329 return "Requested range not satisfiable";
331 return "Expectation Failed";
333 return "Internal Server Error";
335 return "Not Implemented";
337 return "Bad Gateway";
339 return "Service Unavailable";
341 return "Gateway Time-out";
343 return "HTTP Version not supported";
345 return "Unknown Status";
350 std::string::size_type pos = 0;
352 while (pos != std::string::npos) {
354 std::string::size_type nextpos = parameters.find(
"&", pos);
355 std::string::size_type delim = parameters.find(
"=", pos);
356 if (delim > nextpos) {
361 if (delim == std::string::npos) {
362 key = parameters.substr(pos);
364 key = parameters.substr(pos, delim-pos);
365 if (nextpos == std::string::npos) {
366 value = parameters.substr(delim+1);
368 value = parameters.substr(delim+1, nextpos-delim-1);
375 key = decodeURL(key);
376 value = decodeURL(value);
377 parameter_map[key] = value;
378 if (nextpos == std::string::npos) {
385 return parameter_map;
388 static bool iequals(
const std::string& a,
const std::string& b,
size_t length) {
389 std::string::const_iterator ai, bi;
391 for(ai = a.begin(), bi = b.begin(), i = 0; ai != a.end() && bi != b.end() && i < length; ai++,bi++,i++) {
392 if (::toupper(*ai) != ::toupper(*bi))
return false;
395 if (ai == a.end() && bi == b.end())
return true;
396 if ((ai == a.end() && bi != b.end()) ||
397 (ai != a.end() && bi == b.end()))
return false;
399 return ::toupper(*ai) == ::toupper(*bi);
402 static bool iequals(
const std::string& a,
const std::string& b) {
403 if (a.size() != b.size())
return false;
404 return iequals(a,b,a.size());
408 const std::locale &loc = std::locale::classic();
409 std::string::iterator iter = str.begin();
410 while(iter != str.end() && std::isspace(*iter, loc)) iter++;
411 str.erase(str.begin(), iter);
415 const std::locale &loc = std::locale::classic();
416 std::string::reverse_iterator iter = str.rbegin();
417 while(iter != str.rend() && std::isspace(*iter, loc)) iter++;
418 str.erase(iter.base(), str.end());
421 static void trim(std::string &str) {
427 std::string::const_iterator iter = str.begin();
429 const std::locale &loc = std::locale::classic();
433 while(iter != str.end()) {
435 result.insert(result.end(), std::toupper(*iter, loc));
437 result.insert(result.end(), std::tolower(*iter, loc));
438 doNext = (*(iter++) ==
'-');
static void trimRight(std::string &str)
Definition: utility.hpp:414
std::map< std::string, std::string, ASCIICINullSafeComparator > strstr_map_t
Definition: utility.hpp:22
static std::string encodeURL(const std::string &component, bool asUrl=true)
Definition: utility.hpp:233
int minutes
Definition: utility.hpp:36
void validate() const
Definition: utility.hpp:111
int year
Definition: utility.hpp:29
void initialize()
Definition: utility.hpp:45
static const char * DAYS[]
Definition: utility.hpp:6
int utc_offset
Definition: utility.hpp:39
static std::string decodeURL(const std::string &component)
Definition: utility.hpp:204
Definition: utility.hpp:9
int month
Definition: utility.hpp:31
Definition: utility.hpp:25
void parseCookie(const std::string &cookie_date)
Definition: utility.hpp:172
void fromGmtime(time_t t)
Definition: utility.hpp:82
int wday
Definition: utility.hpp:33
static bool iequals(const std::string &a, const std::string &b)
Definition: utility.hpp:402
bool operator()(const std::string &lhs, const std::string &rhs) const
Definition: utility.hpp:10
bool isSet
Definition: utility.hpp:27
int hours
Definition: utility.hpp:35
static const char * MONTHS[]
Definition: utility.hpp:5
static std::string camelizeHeader(const std::string &str)
Definition: utility.hpp:426
int day
Definition: utility.hpp:32
static std::string status2text(int status)
Definition: utility.hpp:266
void parse822(const std::string &rfc822_date)
Definition: utility.hpp:147
void fromTm(const struct tm *tm)
Definition: utility.hpp:97
void fromLocaltime(time_t t)
Definition: utility.hpp:59
void setLocal()
Definition: utility.hpp:51
static void trimLeft(std::string &str)
Definition: utility.hpp:407
std::string rfc_str() const
Definition: utility.hpp:120
static strstr_map_t parseUrlParameters(std::string parameters)
Definition: utility.hpp:349
time_t unixtime() const
Definition: utility.hpp:185
void setGm()
Definition: utility.hpp:55
DateTime()
Definition: utility.hpp:41
Definition: utility.hpp:202
int seconds
Definition: utility.hpp:37
static void trim(std::string &str)
Definition: utility.hpp:421
static bool iequals(const std::string &a, const std::string &b, size_t length)
Definition: utility.hpp:388
std::string cookie_str() const
Definition: utility.hpp:137
static std::string encodeURL(const std::wstring &component, bool asUrl=true)
Definition: utility.hpp:250