00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076 #include "setup.h"
00077 #include <stdio.h>
00078 #include <ctype.h>
00079 #include <string.h>
00080
00081 #ifdef HAVE_STDLIB_H
00082 #include <stdlib.h>
00083 #endif
00084
00085 #include <curl/curl.h>
00086
00087 static time_t Curl_parsedate(const char *date);
00088
00089 const char * const Curl_wkday[] =
00090 {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
00091 static const char * const weekday[] =
00092 { "Monday", "Tuesday", "Wednesday", "Thursday",
00093 "Friday", "Saturday", "Sunday" };
00094 const char * const Curl_month[]=
00095 { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
00096 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
00097
00098 struct tzinfo {
00099 const char *name;
00100 int offset;
00101 };
00102
00103
00104
00105 #define tDAYZONE -60
00106 static const struct tzinfo tz[]= {
00107 {"GMT", 0},
00108 {"UTC", 0},
00109 {"WET", 0},
00110 {"BST", 0 tDAYZONE},
00111 {"WAT", 60},
00112 {"AST", 240},
00113 {"ADT", 240 tDAYZONE},
00114 {"EST", 300},
00115 {"EDT", 300 tDAYZONE},
00116 {"CST", 360},
00117 {"CDT", 360 tDAYZONE},
00118 {"MST", 420},
00119 {"MDT", 420 tDAYZONE},
00120 {"PST", 480},
00121 {"PDT", 480 tDAYZONE},
00122 {"YST", 540},
00123 {"YDT", 540 tDAYZONE},
00124 {"HST", 600},
00125 {"HDT", 600 tDAYZONE},
00126 {"CAT", 600},
00127 {"AHST", 600},
00128 {"NT", 660},
00129 {"IDLW", 720},
00130 {"CET", -60},
00131 {"MET", -60},
00132 {"MEWT", -60},
00133 {"MEST", -60 tDAYZONE},
00134 {"CEST", -60 tDAYZONE},
00135 {"MESZ", -60 tDAYZONE},
00136 {"FWT", -60},
00137 {"FST", -60 tDAYZONE},
00138 {"EET", -120},
00139 {"WAST", -420},
00140 {"WADT", -420 tDAYZONE},
00141 {"CCT", -480},
00142 {"JST", -540},
00143 {"EAST", -600},
00144 {"EADT", -600 tDAYZONE},
00145 {"GST", -600},
00146 {"NZT", -720},
00147 {"NZST", -720},
00148 {"NZDT", -720 tDAYZONE},
00149 {"IDLE", -720},
00150 };
00151
00152
00153
00154
00155
00156
00157 static int checkday(char *check, size_t len)
00158 {
00159 int i;
00160 const char * const *what;
00161 bool found= FALSE;
00162 if(len > 3)
00163 what = &weekday[0];
00164 else
00165 what = &Curl_wkday[0];
00166 for(i=0; i<7; i++) {
00167 if(curl_strequal(check, what[0])) {
00168 found=TRUE;
00169 break;
00170 }
00171 what++;
00172 }
00173 return found?i:-1;
00174 }
00175
00176 static int checkmonth(char *check)
00177 {
00178 int i;
00179 const char * const *what;
00180 bool found= FALSE;
00181
00182 what = &Curl_month[0];
00183 for(i=0; i<12; i++) {
00184 if(curl_strequal(check, what[0])) {
00185 found=TRUE;
00186 break;
00187 }
00188 what++;
00189 }
00190 return found?i:-1;
00191 }
00192
00193
00194
00195
00196 static int checktz(char *check)
00197 {
00198 unsigned int i;
00199 const struct tzinfo *what;
00200 bool found= FALSE;
00201
00202 what = tz;
00203 for(i=0; i< sizeof(tz)/sizeof(tz[0]); i++) {
00204 if(curl_strequal(check, what->name)) {
00205 found=TRUE;
00206 break;
00207 }
00208 what++;
00209 }
00210 return found?what->offset*60:-1;
00211 }
00212
00213 static void skip(const char **date)
00214 {
00215
00216 while(**date && !ISALNUM(**date))
00217 (*date)++;
00218 }
00219
00220 enum assume {
00221 DATE_MDAY,
00222 DATE_YEAR,
00223 DATE_TIME
00224 };
00225
00226 static time_t Curl_parsedate(const char *date)
00227 {
00228 time_t t = 0;
00229 int wdaynum=-1;
00230 int monnum=-1;
00231 int mdaynum=-1;
00232 int hournum=-1;
00233 int minnum=-1;
00234 int secnum=-1;
00235 int yearnum=-1;
00236 int tzoff=-1;
00237 struct tm tm;
00238 enum assume dignext = DATE_MDAY;
00239 const char *indate = date;
00240 int part = 0;
00241
00242 while(*date && (part < 6)) {
00243 bool found=FALSE;
00244
00245 skip(&date);
00246
00247 if(ISALPHA(*date)) {
00248
00249 char buf[32]="";
00250 size_t len;
00251 sscanf(date, "%31[A-Za-z]", buf);
00252 len = strlen(buf);
00253
00254 if(wdaynum == -1) {
00255 wdaynum = checkday(buf, len);
00256 if(wdaynum != -1)
00257 found = TRUE;
00258 }
00259 if(!found && (monnum == -1)) {
00260 monnum = checkmonth(buf);
00261 if(monnum != -1)
00262 found = TRUE;
00263 }
00264
00265 if(!found && (tzoff == -1)) {
00266
00267 tzoff = checktz(buf);
00268 if(tzoff != -1)
00269 found = TRUE;
00270 }
00271
00272 if(!found)
00273 return -1;
00274
00275 date += len;
00276 }
00277 else if(ISDIGIT(*date)) {
00278
00279 int val;
00280 char *end;
00281 if((secnum == -1) &&
00282 (3 == sscanf(date, "%02d:%02d:%02d", &hournum, &minnum, &secnum))) {
00283
00284 date += 8;
00285 found = TRUE;
00286 }
00287 else {
00288 val = (int)strtol(date, &end, 10);
00289
00290 if((tzoff == -1) &&
00291 ((end - date) == 4) &&
00292 (val < 1300) &&
00293 (indate< date) &&
00294 ((date[-1] == '+' || date[-1] == '-'))) {
00295
00296
00297 found = TRUE;
00298 tzoff = (val/100 * 60 + val%100)*60;
00299
00300
00301
00302 tzoff = date[-1]=='+'?-tzoff:tzoff;
00303 }
00304
00305 if(((end - date) == 8) &&
00306 (yearnum == -1) &&
00307 (monnum == -1) &&
00308 (mdaynum == -1)) {
00309
00310 found = TRUE;
00311 yearnum = val/10000;
00312 monnum = (val%10000)/100-1;
00313 mdaynum = val%100;
00314 }
00315
00316 if(!found && (dignext == DATE_MDAY) && (mdaynum == -1)) {
00317 if((val > 0) && (val<32)) {
00318 mdaynum = val;
00319 found = TRUE;
00320 }
00321 dignext = DATE_YEAR;
00322 }
00323
00324 if(!found && (dignext == DATE_YEAR) && (yearnum == -1)) {
00325 yearnum = val;
00326 found = TRUE;
00327 if(yearnum < 1900) {
00328 if (yearnum > 70)
00329 yearnum += 1900;
00330 else
00331 yearnum += 2000;
00332 }
00333 if(mdaynum == -1)
00334 dignext = DATE_MDAY;
00335 }
00336
00337 if(!found)
00338 return -1;
00339
00340 date = end;
00341 }
00342 }
00343
00344 part++;
00345 }
00346
00347 if(-1 == secnum)
00348 secnum = minnum = hournum = 0;
00349
00350 if((-1 == mdaynum) ||
00351 (-1 == monnum) ||
00352 (-1 == yearnum))
00353
00354 return -1;
00355
00356 #if SIZEOF_TIME_T < 5
00357
00358 if(yearnum > 2037)
00359 return 0x7fffffff;
00360 #endif
00361
00362 tm.tm_sec = secnum;
00363 tm.tm_min = minnum;
00364 tm.tm_hour = hournum;
00365 tm.tm_mday = mdaynum;
00366 tm.tm_mon = monnum;
00367 tm.tm_year = yearnum - 1900;
00368 tm.tm_wday = 0;
00369 tm.tm_yday = 0;
00370 tm.tm_isdst = 0;
00371
00372
00373
00374
00375
00376
00377
00378
00379 t = mktime(&tm);
00380
00381
00382 if(-1 != (int)t) {
00383 struct tm *gmt;
00384 long delta;
00385 time_t t2;
00386
00387 #ifdef HAVE_GMTIME_R
00388
00389 struct tm keeptime2;
00390 gmt = (struct tm *)gmtime_r(&t, &keeptime2);
00391 if(!gmt)
00392 return -1;
00393 t2 = mktime(gmt);
00394 #else
00395
00396
00397
00398
00399
00400 struct tm gmt2;
00401 gmt = gmtime(&t);
00402 if(!gmt)
00403 return -1;
00404 gmt2 = *gmt;
00405 t2 = mktime(&gmt2);
00406 #endif
00407
00408
00409
00410 delta = (long)((tzoff!=-1?tzoff:0) + (t - t2));
00411
00412 if((delta>0) && (t + delta < t))
00413 return -1;
00414
00415 t += delta;
00416 }
00417
00418 return t;
00419 }
00420
00421 time_t curl_getdate(const char *p, const time_t *now)
00422 {
00423 (void)now;
00424 return Curl_parsedate(p);
00425 }