📄 http_helpers.cpp
字号:
// HTTP_Helpers.cpp,v 1.31 2003/11/01 11:15:22 dhinton Exp
// HTTP_Helpers.cpp -- Helper utilities for both server and client
#include "HTTP_Helpers.h"
#include "ace/Log_Msg.h"
#include "ace/OS_NS_string.h"
#include "ace/Guard_T.h"
#include "ace/OS_NS_time.h"
#include "ace/OS_NS_stdio.h"
ACE_RCSID(server, HTTP_Helpers, "HTTP_Helpers.cpp,v 1.31 2003/11/01 11:15:22 dhinton Exp")
// = Static initialization.
const char *const
HTTP_Helper::months_[12]=
{
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
char const *HTTP_Helper::alphabet_ = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
char * HTTP_Helper::date_string_ = 0;
ACE_SYNCH_MUTEX HTTP_Helper::mutex_;
ACE_SYNCH_MUTEX HTTP_Status_Code::lock_;
int HTTP_Status_Code::instance_ = 0;
const char *HTTP_Status_Code::Reason[HTTP_Status_Code::MAX_STATUS_CODE + 1];
time_t
HTTP_Helper::HTTP_mktime (const char *httpdate)
{
char *buf;
ACE_NEW_RETURN (buf, char[ACE_OS::strlen (httpdate) + 1], (time_t) -1);
// Make spaces in the date be semi-colons so we can parse robustly
// with sscanf.
const char *ptr1 = httpdate;
char *ptr2 = buf;
do
{
if (*ptr1 == ' ')
*ptr2++ = ';';
else
*ptr2++ = *ptr1;
}
while (*ptr1++ != '\0');
// In HTTP/1.0, there are three versions of an HTTP_date.
// rfc1123-date = wkday "," SP dd month yyyy SP hh:mm:ss SP "GMT"
// rfc850-date = weekday "," SP dd-month-yy SP hh:mm:ss SP "GMT"
// asctime-date = wkday SP month dd SP hh:mm:ss SP yyyy
const char *rfc1123_date = "%3s,;%2d;%3s;%4d;%2d:%2d:%2d;GMT";
const char *rfc850_date = "%s,;%2d-%3s-%2d;%2d:%2d:%2d;GMT";
const char *asctime_date = "%3s;%3s;%2d;%2d:%2d:%2d;%4d";
// Should also support other versions (such as from NNTP and SMTP)
// for robustness, but it should be clear how to extend this.
struct tm tms;
char month[4];
char weekday[10];
if (::sscanf(buf, rfc1123_date,
weekday,
&tms.tm_mday,
month,
&tms.tm_year,
&tms.tm_hour,
&tms.tm_min,
&tms.tm_sec) == 7)
;
else if (::sscanf(buf, rfc850_date,
weekday,
&tms.tm_mday, month, &tms.tm_year,
&tms.tm_hour, &tms.tm_min, &tms.tm_sec) == 7)
{
weekday[3] = '\0';
}
else if (::sscanf(buf, asctime_date,
weekday,
month, &tms.tm_mday,
&tms.tm_hour, &tms.tm_min, &tms.tm_sec,
&tms.tm_year) == 7)
{
}
delete [] buf;
tms.tm_year = HTTP_Helper::fixyear (tms.tm_year);
tms.tm_mon = HTTP_Helper::HTTP_month (month);
if (tms.tm_mon == -1)
return (time_t) -1;
// mktime is a Standard C function.
{
#if !defined (ACE_HAS_REENTRANT_LIBC)
ACE_MT (ACE_Guard<ACE_SYNCH_MUTEX> g (HTTP_Helper::mutex_));
#endif /* NOT ACE_HAS_REENTRANT_LIBC */
return ACE_OS::mktime (&tms);
}
}
const char *
HTTP_Helper::HTTP_date (void)
{
if (HTTP_Helper::date_string_ == 0)
{
ACE_MT (ACE_Guard<ACE_SYNCH_MUTEX> m (HTTP_Helper::mutex_));
if (HTTP_Helper::date_string_ == 0)
{
// 40 bytes is all I need.
ACE_NEW_RETURN (HTTP_Helper::date_string_, char[40], 0);
if (!HTTP_Helper::HTTP_date (HTTP_Helper::date_string_))
{
delete [] HTTP_Helper::date_string_;
HTTP_Helper::date_string_ = 0;
}
}
}
return HTTP_Helper::date_string_;
}
const char *
HTTP_Helper::HTTP_date (char *s)
{
// Return the date-string formatted per HTTP standards. Time must
// be in UTC, so using the 'strftime' call (which obeys the locale)
// isn't correct.
static const char* months[] = {"Jan","Feb","Mar","Apr","May","Jun",
"Jul","Aug","Sep","Oct","Nov","Dec"};
static const char* days[] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
time_t tloc;
struct tm tms;
char * date_string = s;
if (ACE_OS::time (&tloc) != (time_t) -1
&& ACE_OS::gmtime_r (&tloc, &tms) != NULL)
{
ACE_OS::sprintf (date_string,
"%s, %2.2d %s %4.4d %2.2d:%2.2d:%2.2d GMT",
days[tms.tm_wday], tms.tm_mday, months[tms.tm_mon],
tms.tm_year + 1900, tms.tm_hour, tms.tm_min, tms.tm_sec);
}
else
date_string = 0;
return date_string;
}
int
HTTP_Helper::HTTP_month (const char *month)
{
for (size_t i = 0; i < 12; i++)
if (ACE_OS::strcmp(month, HTTP_Helper::months_[i]) == 0)
return i;
return -1;
}
const char *
HTTP_Helper::HTTP_month (int month)
{
if (month < 0 || month >= 12)
return 0;
return HTTP_Helper::months_[month];
}
// Fix the path if it needs fixing/is fixable.
char *
HTTP_Helper::HTTP_decode_string (char *path)
{
// replace the percentcodes with the actual character
int i, j;
char percentcode[3];
for (i = j = 0; path[i] != '\0'; i++, j++)
{
if (path[i] == '%')
{
percentcode[0] = path[++i];
percentcode[1] = path[++i];
percentcode[2] = '\0';
path[j] = (char) ACE_OS::strtol (percentcode, (char **) 0, 16);
}
else
path[j] = path[i];
}
path[j] = path[i];
return path;
}
char *
HTTP_Helper::HTTP_decode_base64 (char *data)
{
char inalphabet[256], decoder[256];
ACE_OS::memset (inalphabet, 0, sizeof (inalphabet));
ACE_OS::memset (decoder, 0, sizeof (decoder));
for (int i = ACE_OS::strlen (HTTP_Helper::alphabet_) - 1;
i >= 0;
i--)
{
inalphabet[(unsigned int) HTTP_Helper::alphabet_[i]] = 1;
decoder[(unsigned int) HTTP_Helper::alphabet_[i]] = i;
}
char *indata = data;
char *outdata = data;
int bits = 0;
int c;
int char_count = 0;
int errors = 0;
while ((c = *indata++) != '\0')
{
if (c == '=')
break;
if (c > 255 || ! inalphabet[c])
continue;
bits += decoder[c];
char_count++;
if (char_count == 4)
{
*outdata++ = (bits >> 16);
*outdata++ = ((bits >> 8) & 0xff);
*outdata++ = (bits & 0xff);
bits = 0;
char_count = 0;
}
else
bits <<= 6;
}
if (c == '\0')
{
if (char_count)
{
ACE_DEBUG ((LM_DEBUG,
"base64 encoding incomplete: at least %d bits truncated\n",
((4 - char_count) * 6)));
errors++;
}
}
else
{
// c == '='
switch (char_count)
{
case 1:
ACE_DEBUG ((LM_DEBUG,
"base64 encoding incomplete: at least 2 bits missing\n"));
errors++;
break;
case 2:
*outdata++ = (bits >> 10);
break;
case 3:
*outdata++ = (bits >> 16);
*outdata++ = ((bits >> 8) & 0xff);
break;
}
}
*outdata = '\0';
return errors ? 0 : data;
}
char *
HTTP_Helper::HTTP_encode_base64 (char *data)
{
char buf[BUFSIZ];
int c;
int error;
int char_count = 0;
int bits = 0;
error = 0;
char *indata = data;
char *outdata = buf;
const unsigned char ASCII_MAX = ~0;
while ((c = *indata++) != '\0')
{
if (c > (int)ASCII_MAX)
{
ACE_DEBUG ((LM_DEBUG, "encountered char > 255 (decimal %d)\n", c));
error++;
break;
}
bits += c;
char_count++;
if (char_count == 3)
{
*outdata++ = HTTP_Helper::alphabet_[bits >> 18];
*outdata++ = HTTP_Helper::alphabet_[(bits >> 12) & 0x3f];
*outdata++ = HTTP_Helper::alphabet_[(bits >> 6) & 0x3f];
*outdata++ = HTTP_Helper::alphabet_[bits & 0x3f];
bits = 0;
char_count = 0;
}
else
bits <<= 8;
}
if (!error)
{
if (char_count != 0)
{
bits <<= 16 - (8 * char_count);
*outdata++ = HTTP_Helper::alphabet_[bits >> 18];
*outdata++ = HTTP_Helper::alphabet_[(bits >> 12) & 0x3f];
if (char_count == 1)
{
*outdata++ = '=';
*outdata++ = '=';
}
else
{
*outdata++ = HTTP_Helper::alphabet_[(bits >> 6) & 0x3f];
*outdata++ = '=';
}
}
*outdata = '\0';
ACE_OS::strcpy (data, buf);
}
return (error ? 0 : data);
}
int
HTTP_Helper::fixyear (int year)
{
// Fix the year 2000 problem
if (year > 1000)
year -= 1900;
else if (year < 100)
{
struct tm tms;
time_t tloc;
if (ACE_OS::time (&tloc) != (time_t) -1)
{
ACE_OS::gmtime_r (&tloc, &tms);
if (tms.tm_year % 100 == year)
year = tms.tm_year;
// The last two cases check boundary conditions, in case the
// year just changed at the moment we checked to see if we
// need to fix it.
if ((year+1) % 100 == tms.tm_year % 100)
year = tms.tm_year - 1;
if (year == (tms.tm_year + 1) % 100)
year = tms.tm_year + 1;
// What to do if none of the above?
}
}
return year;
}
const char **
HTTP_Status_Code::instance (void)
{
if (HTTP_Status_Code::instance_ == 0)
{
ACE_MT (ACE_Guard<ACE_SYNCH_MUTEX> g (lock_));
if (HTTP_Status_Code::instance_ == 0)
{
for (size_t i = 0;
i < HTTP_Status_Code::MAX_STATUS_CODE + 1;
i++)
{
switch (i)
{
case STATUS_OK:
HTTP_Status_Code::Reason[i] = "OK"; break;
case STATUS_CREATED:
HTTP_Status_Code::Reason[i] = "Created"; break;
case STATUS_ACCEPTED:
HTTP_Status_Code::Reason[i] = "Accepted"; break;
case STATUS_NO_CONTENT:
HTTP_Status_Code::Reason[i] = "No Content"; break;
case STATUS_MOVED_PERMANENTLY:
HTTP_Status_Code::Reason[i] = "Moved Permanently"; break;
case STATUS_MOVED_TEMPORARILY:
HTTP_Status_Code::Reason[i] = "Moved Temporarily"; break;
case STATUS_NOT_MODIFIED:
HTTP_Status_Code::Reason[i] = "Not Modified"; break;
case STATUS_BAD_REQUEST:
HTTP_Status_Code::Reason[i] = "Bad Request"; break;
case STATUS_UNAUTHORIZED:
HTTP_Status_Code::Reason[i] = "Unauthorized"; break;
case STATUS_FORBIDDEN:
HTTP_Status_Code::Reason[i] = "Forbidden"; break;
case STATUS_NOT_FOUND:
HTTP_Status_Code::Reason[i] = "Not Found"; break;
case STATUS_INTERNAL_SERVER_ERROR:
HTTP_Status_Code::Reason[i] = "Internal Server Error"; break;
case STATUS_NOT_IMPLEMENTED:
HTTP_Status_Code::Reason[i] = "Not Implemented"; break;
case STATUS_BAD_GATEWAY:
HTTP_Status_Code::Reason[i] = "Bad Gateway"; break;
case STATUS_SERVICE_UNAVAILABLE:
HTTP_Status_Code::Reason[i] = "Service Unavailable"; break;
default:
HTTP_Status_Code::Reason[i] = "Unknown";
}
}
HTTP_Status_Code::instance_ = 1;
}
// GUARD released
}
return HTTP_Status_Code::Reason;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -