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