00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "httpDate.h"
00016
00017 #include <ctype.h>
00018
00019 static const int num_weekdays = 7;
00020 static const char * const weekdays[num_weekdays] = {
00021 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
00022 };
00023
00024 static const int num_months = 12;
00025 static const char * const months[num_months] = {
00026 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
00027 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
00028 };
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 HTTPDate::
00039 HTTPDate(const string &format) {
00040 _time = (time_t)(-1);
00041
00042 struct tm t;
00043 memset(&t, 0, sizeof(t));
00044
00045 bool got_weekday = false;
00046 bool got_month = false;
00047 bool got_day = false;
00048 bool got_year = false;
00049 bool got_hour = false;
00050 bool got_minute = false;
00051 bool got_second = false;
00052
00053 enum ExpectNext {
00054 EN_none,
00055 EN_second,
00056 EN_year
00057 };
00058 ExpectNext expect_next = EN_none;
00059
00060 size_t pos = 0;
00061 string token = get_token(format, pos);
00062 while (!token.empty()) {
00063 ExpectNext expected = expect_next;
00064 expect_next = EN_none;
00065
00066 if (isdigit(token[0])) {
00067
00068 int value = atoi(token.c_str());
00069 if (token[token.length() - 1] == ':') {
00070
00071 if (!got_hour) {
00072 t.tm_hour = value;
00073 got_hour = true;
00074
00075 } else if (!got_minute) {
00076 t.tm_min = value;
00077 got_minute = true;
00078 expect_next = EN_second;
00079
00080 } else {
00081 return;
00082 }
00083
00084 } else if (token[token.length() - 1] == '/') {
00085
00086 if (!got_month) {
00087 t.tm_mon = value - 1;
00088 got_month = true;
00089
00090 } else if (!got_day) {
00091 t.tm_mday = value;
00092 got_day = true;
00093 expect_next = EN_year;
00094
00095 } else {
00096 return;
00097 }
00098
00099 } else {
00100 if (expected == EN_second) {
00101
00102 t.tm_sec = value;
00103 got_second = true;
00104
00105 } else if (expected == EN_year) {
00106
00107 t.tm_year = value;
00108 got_year = true;
00109
00110 } else if (!got_day) {
00111
00112 t.tm_mday = value;
00113 got_day = true;
00114
00115 } else if (!got_year) {
00116
00117 t.tm_year = value;
00118 got_year = true;
00119
00120 } else if (!got_hour) {
00121 t.tm_hour = value;
00122 got_hour = true;
00123
00124 } else if (!got_minute) {
00125 t.tm_min = value;
00126 got_minute = true;
00127
00128 } else if (!got_second) {
00129 t.tm_sec = value;
00130 got_second = true;
00131
00132 } else {
00133
00134 return;
00135 }
00136 }
00137
00138 } else {
00139
00140
00141
00142 bool matched = false;
00143 int i;
00144
00145 for (i = 0; i < num_weekdays && !matched; i++) {
00146 if (token == weekdays[i]) {
00147 if (got_weekday) {
00148 return;
00149 }
00150 matched = true;
00151 got_weekday = true;
00152 t.tm_wday = i;
00153 }
00154 }
00155
00156 for (i = 0; i < num_months && !matched; i++) {
00157 if (token == months[i]) {
00158 if (got_month) {
00159 return;
00160 }
00161 matched = true;
00162 got_month = true;
00163 t.tm_mon = i;
00164 }
00165 }
00166
00167 if (!matched && token == "Gmt") {
00168 matched = true;
00169 }
00170
00171 if (!matched) {
00172
00173 return;
00174 }
00175 }
00176
00177 token = get_token(format, pos);
00178 }
00179
00180
00181 if (!(got_month && got_day && got_year && got_hour && got_minute)) {
00182 return;
00183 }
00184
00185
00186 if (t.tm_year < 100) {
00187
00188
00189 time_t now = time(NULL);
00190 struct tm *tp = gmtime(&now);
00191 t.tm_year += 100 * (tp->tm_year / 100);
00192 if (t.tm_year - tp->tm_year > 50) {
00193 t.tm_year -= 100;
00194 }
00195
00196 } else if (t.tm_year < 1900) {
00197
00198 return;
00199
00200 } else {
00201 t.tm_year -= 1900;
00202 }
00203
00204 if (!((t.tm_mon >= 0 && t.tm_mon < num_months) &&
00205 (t.tm_mday >= 1 && t.tm_mday <= 31) &&
00206 (t.tm_hour >= 0 && t.tm_hour < 60) &&
00207 (t.tm_min >= 0 && t.tm_min < 60) &&
00208 (t.tm_sec >= 0 && t.tm_sec < 62) )) {
00209 return;
00210 }
00211
00212
00213
00214
00215 #if 0
00216
00217 _time = timegm(&t);
00218
00219 #else // __GNUC__
00220
00221 _time = mktime(&t);
00222
00223 if (_time != (time_t)-1) {
00224
00225
00226 extern long int timezone;
00227 _time -= timezone;
00228 }
00229 #endif // __GNUC__
00230 }
00231
00232
00233
00234
00235
00236
00237 string HTTPDate::
00238 get_string() const {
00239 if (!is_valid()) {
00240 return "Invalid Date";
00241 }
00242
00243 struct tm *tp = gmtime(&_time);
00244
00245 ostringstream result;
00246 result
00247 << weekdays[tp->tm_wday] << ", "
00248 << setw(2) << setfill('0') << tp->tm_mday << " "
00249 << months[tp->tm_mon] << " "
00250 << setw(4) << setfill('0') << tp->tm_year + 1900 << " "
00251 << setw(2) << setfill('0') << tp->tm_hour << ":"
00252 << setw(2) << setfill('0') << tp->tm_min << ":"
00253 << setw(2) << setfill('0') << tp->tm_sec << " GMT";
00254
00255 return result.str();
00256 }
00257
00258
00259
00260
00261
00262
00263
00264 bool HTTPDate::
00265 input(istream &in) {
00266 (*this) = HTTPDate();
00267
00268
00269 char ch;
00270 in >> ch;
00271 if (ch != '"') {
00272 return false;
00273 }
00274
00275 string date;
00276 ch = in.get();
00277 while (!in.fail() && !in.eof() && ch != '"') {
00278 date += ch;
00279 ch = in.get();
00280 }
00281
00282 if (ch != '"') {
00283 return false;
00284 }
00285
00286
00287 HTTPDate new_date(date);
00288 (*this) = new_date;
00289 return is_valid();
00290 }
00291
00292
00293
00294
00295
00296
00297 void HTTPDate::
00298 output(ostream &out) const {
00299
00300
00301 out << '"' << get_string() << '"';
00302 }
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320 string HTTPDate::
00321 get_token(const string &str, size_t &pos) {
00322
00323 size_t start = pos;
00324 while (start < str.length() && !isalnum(str[start])) {
00325 start++;
00326 }
00327
00328 if (start >= str.length()) {
00329
00330 pos = string::npos;
00331 return string();
00332 }
00333
00334 string token;
00335
00336 if (isalpha(str[start])) {
00337
00338 token = toupper(str[start]);
00339 pos = start + 1;
00340 while (pos < str.length() && isalpha(str[pos])) {
00341 if (token.length() < 3) {
00342 token += tolower(str[pos]);
00343 }
00344 pos++;
00345 }
00346
00347 } else {
00348
00349 pos = start + 1;
00350 while (pos < str.length() && isdigit(str[pos])) {
00351 pos++;
00352 }
00353
00354 if (pos < str.length() && !isalpha(str[pos])) {
00355 pos++;
00356 }
00357 token = str.substr(start, pos - start);
00358 }
00359
00360 return token;
00361 }