Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/thirdparty/curl/lib/parsedate.c @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 1:1d09e1dec1d9 | 2:b50eed0cc0ef |
|---|---|
| 1 /*************************************************************************** | |
| 2 * _ _ ____ _ | |
| 3 * Project ___| | | | _ \| | | |
| 4 * / __| | | | |_) | | | |
| 5 * | (__| |_| | _ <| |___ | |
| 6 * \___|\___/|_| \_\_____| | |
| 7 * | |
| 8 * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. | |
| 9 * | |
| 10 * This software is licensed as described in the file COPYING, which | |
| 11 * you should have received as part of this distribution. The terms | |
| 12 * are also available at https://curl.haxx.se/docs/copyright.html. | |
| 13 * | |
| 14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell | |
| 15 * copies of the Software, and permit persons to whom the Software is | |
| 16 * furnished to do so, under the terms of the COPYING file. | |
| 17 * | |
| 18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | |
| 19 * KIND, either express or implied. | |
| 20 * | |
| 21 ***************************************************************************/ | |
| 22 /* | |
| 23 A brief summary of the date string formats this parser groks: | |
| 24 | |
| 25 RFC 2616 3.3.1 | |
| 26 | |
| 27 Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123 | |
| 28 Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036 | |
| 29 Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format | |
| 30 | |
| 31 we support dates without week day name: | |
| 32 | |
| 33 06 Nov 1994 08:49:37 GMT | |
| 34 06-Nov-94 08:49:37 GMT | |
| 35 Nov 6 08:49:37 1994 | |
| 36 | |
| 37 without the time zone: | |
| 38 | |
| 39 06 Nov 1994 08:49:37 | |
| 40 06-Nov-94 08:49:37 | |
| 41 | |
| 42 weird order: | |
| 43 | |
| 44 1994 Nov 6 08:49:37 (GNU date fails) | |
| 45 GMT 08:49:37 06-Nov-94 Sunday | |
| 46 94 6 Nov 08:49:37 (GNU date fails) | |
| 47 | |
| 48 time left out: | |
| 49 | |
| 50 1994 Nov 6 | |
| 51 06-Nov-94 | |
| 52 Sun Nov 6 94 | |
| 53 | |
| 54 unusual separators: | |
| 55 | |
| 56 1994.Nov.6 | |
| 57 Sun/Nov/6/94/GMT | |
| 58 | |
| 59 commonly used time zone names: | |
| 60 | |
| 61 Sun, 06 Nov 1994 08:49:37 CET | |
| 62 06 Nov 1994 08:49:37 EST | |
| 63 | |
| 64 time zones specified using RFC822 style: | |
| 65 | |
| 66 Sun, 12 Sep 2004 15:05:58 -0700 | |
| 67 Sat, 11 Sep 2004 21:32:11 +0200 | |
| 68 | |
| 69 compact numerical date strings: | |
| 70 | |
| 71 20040912 15:05:58 -0700 | |
| 72 20040911 +0200 | |
| 73 | |
| 74 */ | |
| 75 | |
| 76 #include "curl_setup.h" | |
| 77 | |
| 78 #include <limits.h> | |
| 79 | |
| 80 #include <curl/curl.h> | |
| 81 #include "strcase.h" | |
| 82 #include "warnless.h" | |
| 83 #include "parsedate.h" | |
| 84 | |
| 85 /* | |
| 86 * parsedate() | |
| 87 * | |
| 88 * Returns: | |
| 89 * | |
| 90 * PARSEDATE_OK - a fine conversion | |
| 91 * PARSEDATE_FAIL - failed to convert | |
| 92 * PARSEDATE_LATER - time overflow at the far end of time_t | |
| 93 * PARSEDATE_SOONER - time underflow at the low end of time_t | |
| 94 */ | |
| 95 | |
| 96 static int parsedate(const char *date, time_t *output); | |
| 97 | |
| 98 #define PARSEDATE_OK 0 | |
| 99 #define PARSEDATE_FAIL -1 | |
| 100 #define PARSEDATE_LATER 1 | |
| 101 #define PARSEDATE_SOONER 2 | |
| 102 | |
| 103 #ifndef CURL_DISABLE_PARSEDATE | |
| 104 | |
| 105 const char * const Curl_wkday[] = | |
| 106 {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}; | |
| 107 static const char * const weekday[] = | |
| 108 { "Monday", "Tuesday", "Wednesday", "Thursday", | |
| 109 "Friday", "Saturday", "Sunday" }; | |
| 110 const char * const Curl_month[]= | |
| 111 { "Jan", "Feb", "Mar", "Apr", "May", "Jun", | |
| 112 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; | |
| 113 | |
| 114 struct tzinfo { | |
| 115 char name[5]; | |
| 116 int offset; /* +/- in minutes */ | |
| 117 }; | |
| 118 | |
| 119 /* Here's a bunch of frequently used time zone names. These were supported | |
| 120 by the old getdate parser. */ | |
| 121 #define tDAYZONE -60 /* offset for daylight savings time */ | |
| 122 static const struct tzinfo tz[]= { | |
| 123 {"GMT", 0}, /* Greenwich Mean */ | |
| 124 {"UT", 0}, /* Universal Time */ | |
| 125 {"UTC", 0}, /* Universal (Coordinated) */ | |
| 126 {"WET", 0}, /* Western European */ | |
| 127 {"BST", 0 tDAYZONE}, /* British Summer */ | |
| 128 {"WAT", 60}, /* West Africa */ | |
| 129 {"AST", 240}, /* Atlantic Standard */ | |
| 130 {"ADT", 240 tDAYZONE}, /* Atlantic Daylight */ | |
| 131 {"EST", 300}, /* Eastern Standard */ | |
| 132 {"EDT", 300 tDAYZONE}, /* Eastern Daylight */ | |
| 133 {"CST", 360}, /* Central Standard */ | |
| 134 {"CDT", 360 tDAYZONE}, /* Central Daylight */ | |
| 135 {"MST", 420}, /* Mountain Standard */ | |
| 136 {"MDT", 420 tDAYZONE}, /* Mountain Daylight */ | |
| 137 {"PST", 480}, /* Pacific Standard */ | |
| 138 {"PDT", 480 tDAYZONE}, /* Pacific Daylight */ | |
| 139 {"YST", 540}, /* Yukon Standard */ | |
| 140 {"YDT", 540 tDAYZONE}, /* Yukon Daylight */ | |
| 141 {"HST", 600}, /* Hawaii Standard */ | |
| 142 {"HDT", 600 tDAYZONE}, /* Hawaii Daylight */ | |
| 143 {"CAT", 600}, /* Central Alaska */ | |
| 144 {"AHST", 600}, /* Alaska-Hawaii Standard */ | |
| 145 {"NT", 660}, /* Nome */ | |
| 146 {"IDLW", 720}, /* International Date Line West */ | |
| 147 {"CET", -60}, /* Central European */ | |
| 148 {"MET", -60}, /* Middle European */ | |
| 149 {"MEWT", -60}, /* Middle European Winter */ | |
| 150 {"MEST", -60 tDAYZONE}, /* Middle European Summer */ | |
| 151 {"CEST", -60 tDAYZONE}, /* Central European Summer */ | |
| 152 {"MESZ", -60 tDAYZONE}, /* Middle European Summer */ | |
| 153 {"FWT", -60}, /* French Winter */ | |
| 154 {"FST", -60 tDAYZONE}, /* French Summer */ | |
| 155 {"EET", -120}, /* Eastern Europe, USSR Zone 1 */ | |
| 156 {"WAST", -420}, /* West Australian Standard */ | |
| 157 {"WADT", -420 tDAYZONE}, /* West Australian Daylight */ | |
| 158 {"CCT", -480}, /* China Coast, USSR Zone 7 */ | |
| 159 {"JST", -540}, /* Japan Standard, USSR Zone 8 */ | |
| 160 {"EAST", -600}, /* Eastern Australian Standard */ | |
| 161 {"EADT", -600 tDAYZONE}, /* Eastern Australian Daylight */ | |
| 162 {"GST", -600}, /* Guam Standard, USSR Zone 9 */ | |
| 163 {"NZT", -720}, /* New Zealand */ | |
| 164 {"NZST", -720}, /* New Zealand Standard */ | |
| 165 {"NZDT", -720 tDAYZONE}, /* New Zealand Daylight */ | |
| 166 {"IDLE", -720}, /* International Date Line East */ | |
| 167 /* Next up: Military timezone names. RFC822 allowed these, but (as noted in | |
| 168 RFC 1123) had their signs wrong. Here we use the correct signs to match | |
| 169 actual military usage. | |
| 170 */ | |
| 171 {"A", 1 * 60}, /* Alpha */ | |
| 172 {"B", 2 * 60}, /* Bravo */ | |
| 173 {"C", 3 * 60}, /* Charlie */ | |
| 174 {"D", 4 * 60}, /* Delta */ | |
| 175 {"E", 5 * 60}, /* Echo */ | |
| 176 {"F", 6 * 60}, /* Foxtrot */ | |
| 177 {"G", 7 * 60}, /* Golf */ | |
| 178 {"H", 8 * 60}, /* Hotel */ | |
| 179 {"I", 9 * 60}, /* India */ | |
| 180 /* "J", Juliet is not used as a timezone, to indicate the observer's local | |
| 181 time */ | |
| 182 {"K", 10 * 60}, /* Kilo */ | |
| 183 {"L", 11 * 60}, /* Lima */ | |
| 184 {"M", 12 * 60}, /* Mike */ | |
| 185 {"N", -1 * 60}, /* November */ | |
| 186 {"O", -2 * 60}, /* Oscar */ | |
| 187 {"P", -3 * 60}, /* Papa */ | |
| 188 {"Q", -4 * 60}, /* Quebec */ | |
| 189 {"R", -5 * 60}, /* Romeo */ | |
| 190 {"S", -6 * 60}, /* Sierra */ | |
| 191 {"T", -7 * 60}, /* Tango */ | |
| 192 {"U", -8 * 60}, /* Uniform */ | |
| 193 {"V", -9 * 60}, /* Victor */ | |
| 194 {"W", -10 * 60}, /* Whiskey */ | |
| 195 {"X", -11 * 60}, /* X-ray */ | |
| 196 {"Y", -12 * 60}, /* Yankee */ | |
| 197 {"Z", 0}, /* Zulu, zero meridian, a.k.a. UTC */ | |
| 198 }; | |
| 199 | |
| 200 /* returns: | |
| 201 -1 no day | |
| 202 0 monday - 6 sunday | |
| 203 */ | |
| 204 | |
| 205 static int checkday(const char *check, size_t len) | |
| 206 { | |
| 207 int i; | |
| 208 const char * const *what; | |
| 209 bool found = FALSE; | |
| 210 if(len > 3) | |
| 211 what = &weekday[0]; | |
| 212 else | |
| 213 what = &Curl_wkday[0]; | |
| 214 for(i = 0; i<7; i++) { | |
| 215 if(strcasecompare(check, what[0])) { | |
| 216 found = TRUE; | |
| 217 break; | |
| 218 } | |
| 219 what++; | |
| 220 } | |
| 221 return found?i:-1; | |
| 222 } | |
| 223 | |
| 224 static int checkmonth(const char *check) | |
| 225 { | |
| 226 int i; | |
| 227 const char * const *what; | |
| 228 bool found = FALSE; | |
| 229 | |
| 230 what = &Curl_month[0]; | |
| 231 for(i = 0; i<12; i++) { | |
| 232 if(strcasecompare(check, what[0])) { | |
| 233 found = TRUE; | |
| 234 break; | |
| 235 } | |
| 236 what++; | |
| 237 } | |
| 238 return found?i:-1; /* return the offset or -1, no real offset is -1 */ | |
| 239 } | |
| 240 | |
| 241 /* return the time zone offset between GMT and the input one, in number | |
| 242 of seconds or -1 if the timezone wasn't found/legal */ | |
| 243 | |
| 244 static int checktz(const char *check) | |
| 245 { | |
| 246 unsigned int i; | |
| 247 const struct tzinfo *what; | |
| 248 bool found = FALSE; | |
| 249 | |
| 250 what = tz; | |
| 251 for(i = 0; i< sizeof(tz)/sizeof(tz[0]); i++) { | |
| 252 if(strcasecompare(check, what->name)) { | |
| 253 found = TRUE; | |
| 254 break; | |
| 255 } | |
| 256 what++; | |
| 257 } | |
| 258 return found?what->offset*60:-1; | |
| 259 } | |
| 260 | |
| 261 static void skip(const char **date) | |
| 262 { | |
| 263 /* skip everything that aren't letters or digits */ | |
| 264 while(**date && !ISALNUM(**date)) | |
| 265 (*date)++; | |
| 266 } | |
| 267 | |
| 268 enum assume { | |
| 269 DATE_MDAY, | |
| 270 DATE_YEAR, | |
| 271 DATE_TIME | |
| 272 }; | |
| 273 | |
| 274 /* this is a clone of 'struct tm' but with all fields we don't need or use | |
| 275 cut out */ | |
| 276 struct my_tm { | |
| 277 int tm_sec; | |
| 278 int tm_min; | |
| 279 int tm_hour; | |
| 280 int tm_mday; | |
| 281 int tm_mon; | |
| 282 int tm_year; /* full year */ | |
| 283 }; | |
| 284 | |
| 285 /* struct tm to time since epoch in GMT time zone. | |
| 286 * This is similar to the standard mktime function but for GMT only, and | |
| 287 * doesn't suffer from the various bugs and portability problems that | |
| 288 * some systems' implementations have. | |
| 289 * | |
| 290 * Returns 0 on success, otherwise non-zero. | |
| 291 */ | |
| 292 static void my_timegm(struct my_tm *tm, time_t *t) | |
| 293 { | |
| 294 static const int month_days_cumulative [12] = | |
| 295 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; | |
| 296 int month, year, leap_days; | |
| 297 | |
| 298 year = tm->tm_year; | |
| 299 month = tm->tm_mon; | |
| 300 if(month < 0) { | |
| 301 year += (11 - month) / 12; | |
| 302 month = 11 - (11 - month) % 12; | |
| 303 } | |
| 304 else if(month >= 12) { | |
| 305 year -= month / 12; | |
| 306 month = month % 12; | |
| 307 } | |
| 308 | |
| 309 leap_days = year - (tm->tm_mon <= 1); | |
| 310 leap_days = ((leap_days / 4) - (leap_days / 100) + (leap_days / 400) | |
| 311 - (1969 / 4) + (1969 / 100) - (1969 / 400)); | |
| 312 | |
| 313 *t = ((((time_t) (year - 1970) * 365 | |
| 314 + leap_days + month_days_cumulative[month] + tm->tm_mday - 1) * 24 | |
| 315 + tm->tm_hour) * 60 + tm->tm_min) * 60 + tm->tm_sec; | |
| 316 } | |
| 317 | |
| 318 /* | |
| 319 * parsedate() | |
| 320 * | |
| 321 * Returns: | |
| 322 * | |
| 323 * PARSEDATE_OK - a fine conversion | |
| 324 * PARSEDATE_FAIL - failed to convert | |
| 325 * PARSEDATE_LATER - time overflow at the far end of time_t | |
| 326 * PARSEDATE_SOONER - time underflow at the low end of time_t | |
| 327 */ | |
| 328 | |
| 329 static int parsedate(const char *date, time_t *output) | |
| 330 { | |
| 331 time_t t = 0; | |
| 332 int wdaynum = -1; /* day of the week number, 0-6 (mon-sun) */ | |
| 333 int monnum = -1; /* month of the year number, 0-11 */ | |
| 334 int mdaynum = -1; /* day of month, 1 - 31 */ | |
| 335 int hournum = -1; | |
| 336 int minnum = -1; | |
| 337 int secnum = -1; | |
| 338 int yearnum = -1; | |
| 339 int tzoff = -1; | |
| 340 struct my_tm tm; | |
| 341 enum assume dignext = DATE_MDAY; | |
| 342 const char *indate = date; /* save the original pointer */ | |
| 343 int part = 0; /* max 6 parts */ | |
| 344 | |
| 345 while(*date && (part < 6)) { | |
| 346 bool found = FALSE; | |
| 347 | |
| 348 skip(&date); | |
| 349 | |
| 350 if(ISALPHA(*date)) { | |
| 351 /* a name coming up */ | |
| 352 char buf[32]=""; | |
| 353 size_t len; | |
| 354 if(sscanf(date, "%31[ABCDEFGHIJKLMNOPQRSTUVWXYZ" | |
| 355 "abcdefghijklmnopqrstuvwxyz]", buf)) | |
| 356 len = strlen(buf); | |
| 357 else | |
| 358 len = 0; | |
| 359 | |
| 360 if(wdaynum == -1) { | |
| 361 wdaynum = checkday(buf, len); | |
| 362 if(wdaynum != -1) | |
| 363 found = TRUE; | |
| 364 } | |
| 365 if(!found && (monnum == -1)) { | |
| 366 monnum = checkmonth(buf); | |
| 367 if(monnum != -1) | |
| 368 found = TRUE; | |
| 369 } | |
| 370 | |
| 371 if(!found && (tzoff == -1)) { | |
| 372 /* this just must be a time zone string */ | |
| 373 tzoff = checktz(buf); | |
| 374 if(tzoff != -1) | |
| 375 found = TRUE; | |
| 376 } | |
| 377 | |
| 378 if(!found) | |
| 379 return PARSEDATE_FAIL; /* bad string */ | |
| 380 | |
| 381 date += len; | |
| 382 } | |
| 383 else if(ISDIGIT(*date)) { | |
| 384 /* a digit */ | |
| 385 int val; | |
| 386 char *end; | |
| 387 int len = 0; | |
| 388 if((secnum == -1) && | |
| 389 (3 == sscanf(date, "%02d:%02d:%02d%n", | |
| 390 &hournum, &minnum, &secnum, &len))) { | |
| 391 /* time stamp! */ | |
| 392 date += len; | |
| 393 } | |
| 394 else if((secnum == -1) && | |
| 395 (2 == sscanf(date, "%02d:%02d%n", &hournum, &minnum, &len))) { | |
| 396 /* time stamp without seconds */ | |
| 397 date += len; | |
| 398 secnum = 0; | |
| 399 } | |
| 400 else { | |
| 401 long lval; | |
| 402 int error; | |
| 403 int old_errno; | |
| 404 | |
| 405 old_errno = errno; | |
| 406 errno = 0; | |
| 407 lval = strtol(date, &end, 10); | |
| 408 error = errno; | |
| 409 if(errno != old_errno) | |
| 410 errno = old_errno; | |
| 411 | |
| 412 if(error) | |
| 413 return PARSEDATE_FAIL; | |
| 414 | |
| 415 #if LONG_MAX != INT_MAX | |
| 416 if((lval > (long)INT_MAX) || (lval < (long)INT_MIN)) | |
| 417 return PARSEDATE_FAIL; | |
| 418 #endif | |
| 419 | |
| 420 val = curlx_sltosi(lval); | |
| 421 | |
| 422 if((tzoff == -1) && | |
| 423 ((end - date) == 4) && | |
| 424 (val <= 1400) && | |
| 425 (indate< date) && | |
| 426 ((date[-1] == '+' || date[-1] == '-'))) { | |
| 427 /* four digits and a value less than or equal to 1400 (to take into | |
| 428 account all sorts of funny time zone diffs) and it is preceded | |
| 429 with a plus or minus. This is a time zone indication. 1400 is | |
| 430 picked since +1300 is frequently used and +1400 is mentioned as | |
| 431 an edge number in the document "ISO C 200X Proposal: Timezone | |
| 432 Functions" at http://david.tribble.com/text/c0xtimezone.html If | |
| 433 anyone has a more authoritative source for the exact maximum time | |
| 434 zone offsets, please speak up! */ | |
| 435 found = TRUE; | |
| 436 tzoff = (val/100 * 60 + val%100)*60; | |
| 437 | |
| 438 /* the + and - prefix indicates the local time compared to GMT, | |
| 439 this we need their reversed math to get what we want */ | |
| 440 tzoff = date[-1]=='+'?-tzoff:tzoff; | |
| 441 } | |
| 442 | |
| 443 if(((end - date) == 8) && | |
| 444 (yearnum == -1) && | |
| 445 (monnum == -1) && | |
| 446 (mdaynum == -1)) { | |
| 447 /* 8 digits, no year, month or day yet. This is YYYYMMDD */ | |
| 448 found = TRUE; | |
| 449 yearnum = val/10000; | |
| 450 monnum = (val%10000)/100-1; /* month is 0 - 11 */ | |
| 451 mdaynum = val%100; | |
| 452 } | |
| 453 | |
| 454 if(!found && (dignext == DATE_MDAY) && (mdaynum == -1)) { | |
| 455 if((val > 0) && (val<32)) { | |
| 456 mdaynum = val; | |
| 457 found = TRUE; | |
| 458 } | |
| 459 dignext = DATE_YEAR; | |
| 460 } | |
| 461 | |
| 462 if(!found && (dignext == DATE_YEAR) && (yearnum == -1)) { | |
| 463 yearnum = val; | |
| 464 found = TRUE; | |
| 465 if(yearnum < 100) { | |
| 466 if(yearnum > 70) | |
| 467 yearnum += 1900; | |
| 468 else | |
| 469 yearnum += 2000; | |
| 470 } | |
| 471 if(mdaynum == -1) | |
| 472 dignext = DATE_MDAY; | |
| 473 } | |
| 474 | |
| 475 if(!found) | |
| 476 return PARSEDATE_FAIL; | |
| 477 | |
| 478 date = end; | |
| 479 } | |
| 480 } | |
| 481 | |
| 482 part++; | |
| 483 } | |
| 484 | |
| 485 if(-1 == secnum) | |
| 486 secnum = minnum = hournum = 0; /* no time, make it zero */ | |
| 487 | |
| 488 if((-1 == mdaynum) || | |
| 489 (-1 == monnum) || | |
| 490 (-1 == yearnum)) | |
| 491 /* lacks vital info, fail */ | |
| 492 return PARSEDATE_FAIL; | |
| 493 | |
| 494 #ifdef HAVE_TIME_T_UNSIGNED | |
| 495 if(yearnum < 1970) { | |
| 496 /* only positive numbers cannot return earlier */ | |
| 497 *output = TIME_T_MIN; | |
| 498 return PARSEDATE_SOONER; | |
| 499 } | |
| 500 #endif | |
| 501 | |
| 502 #if (SIZEOF_TIME_T < 5) | |
| 503 | |
| 504 #ifdef HAVE_TIME_T_UNSIGNED | |
| 505 /* an unsigned 32 bit time_t can only hold dates to 2106 */ | |
| 506 if(yearnum > 2105) { | |
| 507 *output = TIME_T_MAX; | |
| 508 return PARSEDATE_LATER; | |
| 509 } | |
| 510 #else | |
| 511 /* a signed 32 bit time_t can only hold dates to the beginning of 2038 */ | |
| 512 if(yearnum > 2037) { | |
| 513 *output = TIME_T_MAX; | |
| 514 return PARSEDATE_LATER; | |
| 515 } | |
| 516 if(yearnum < 1903) { | |
| 517 *output = TIME_T_MIN; | |
| 518 return PARSEDATE_SOONER; | |
| 519 } | |
| 520 #endif | |
| 521 | |
| 522 #else | |
| 523 /* The Gregorian calendar was introduced 1582 */ | |
| 524 if(yearnum < 1583) | |
| 525 return PARSEDATE_FAIL; | |
| 526 #endif | |
| 527 | |
| 528 if((mdaynum > 31) || (monnum > 11) || | |
| 529 (hournum > 23) || (minnum > 59) || (secnum > 60)) | |
| 530 return PARSEDATE_FAIL; /* clearly an illegal date */ | |
| 531 | |
| 532 tm.tm_sec = secnum; | |
| 533 tm.tm_min = minnum; | |
| 534 tm.tm_hour = hournum; | |
| 535 tm.tm_mday = mdaynum; | |
| 536 tm.tm_mon = monnum; | |
| 537 tm.tm_year = yearnum; | |
| 538 | |
| 539 /* my_timegm() returns a time_t. time_t is often 32 bits, sometimes even on | |
| 540 architectures that feature 64 bit 'long' but ultimately time_t is the | |
| 541 correct data type to use. | |
| 542 */ | |
| 543 my_timegm(&tm, &t); | |
| 544 | |
| 545 /* Add the time zone diff between local time zone and GMT. */ | |
| 546 if(tzoff == -1) | |
| 547 tzoff = 0; | |
| 548 | |
| 549 if((tzoff > 0) && (t > TIME_T_MAX - tzoff)) { | |
| 550 *output = TIME_T_MAX; | |
| 551 return PARSEDATE_LATER; /* time_t overflow */ | |
| 552 } | |
| 553 | |
| 554 t += tzoff; | |
| 555 | |
| 556 *output = t; | |
| 557 | |
| 558 return PARSEDATE_OK; | |
| 559 } | |
| 560 #else | |
| 561 /* disabled */ | |
| 562 static int parsedate(const char *date, time_t *output) | |
| 563 { | |
| 564 (void)date; | |
| 565 *output = 0; | |
| 566 return PARSEDATE_OK; /* a lie */ | |
| 567 } | |
| 568 #endif | |
| 569 | |
| 570 time_t curl_getdate(const char *p, const time_t *now) | |
| 571 { | |
| 572 time_t parsed = -1; | |
| 573 int rc = parsedate(p, &parsed); | |
| 574 (void)now; /* legacy argument from the past that we ignore */ | |
| 575 | |
| 576 if(rc == PARSEDATE_OK) { | |
| 577 if(parsed == -1) | |
| 578 /* avoid returning -1 for a working scenario */ | |
| 579 parsed++; | |
| 580 return parsed; | |
| 581 } | |
| 582 /* everything else is fail */ | |
| 583 return -1; | |
| 584 } | |
| 585 | |
| 586 /* | |
| 587 * Curl_gmtime() is a gmtime() replacement for portability. Do not use the | |
| 588 * gmtime_r() or gmtime() functions anywhere else but here. | |
| 589 * | |
| 590 */ | |
| 591 | |
| 592 CURLcode Curl_gmtime(time_t intime, struct tm *store) | |
| 593 { | |
| 594 const struct tm *tm; | |
| 595 #ifdef HAVE_GMTIME_R | |
| 596 /* thread-safe version */ | |
| 597 tm = (struct tm *)gmtime_r(&intime, store); | |
| 598 #else | |
| 599 tm = gmtime(&intime); | |
| 600 if(tm) | |
| 601 *store = *tm; /* copy the pointed struct to the local copy */ | |
| 602 #endif | |
| 603 | |
| 604 if(!tm) | |
| 605 return CURLE_BAD_FUNCTION_ARGUMENT; | |
| 606 return CURLE_OK; | |
| 607 } |
