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