diff options
author | Brad King <brad.king@kitware.com> | 2023-03-20 20:40:49 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2023-03-20 20:40:49 (GMT) |
commit | e3dc4df9b95272037d27be25ae5ef030ffd83fa4 (patch) | |
tree | 6132bc02d5204bd988b32ee8ab06053ec7c0e4c4 /Utilities/cmcurl/lib/parsedate.c | |
parent | 4e6c3cd93bc870f44442e6d7e59896bc6d86ce25 (diff) | |
parent | e8bff971d9d835a65bcb1711e7214afe37b238e0 (diff) | |
download | CMake-e3dc4df9b95272037d27be25ae5ef030ffd83fa4.zip CMake-e3dc4df9b95272037d27be25ae5ef030ffd83fa4.tar.gz CMake-e3dc4df9b95272037d27be25ae5ef030ffd83fa4.tar.bz2 |
Merge branch 'upstream-curl' into update-curl
* upstream-curl:
curl 2023-03-20 (b16d1fa8)
Diffstat (limited to 'Utilities/cmcurl/lib/parsedate.c')
-rw-r--r-- | Utilities/cmcurl/lib/parsedate.c | 159 |
1 files changed, 100 insertions, 59 deletions
diff --git a/Utilities/cmcurl/lib/parsedate.c b/Utilities/cmcurl/lib/parsedate.c index 82ac1d8..1662dd3 100644 --- a/Utilities/cmcurl/lib/parsedate.c +++ b/Utilities/cmcurl/lib/parsedate.c @@ -212,56 +212,55 @@ static int checkday(const char *check, size_t len) { int i; const char * const *what; - bool found = FALSE; if(len > 3) what = &weekday[0]; - else + else if(len == 3) what = &Curl_wkday[0]; + else + return -1; /* too short */ for(i = 0; i<7; i++) { - if(strcasecompare(check, what[0])) { - found = TRUE; - break; - } + size_t ilen = strlen(what[0]); + if((ilen == len) && + strncasecompare(check, what[0], len)) + return i; what++; } - return found?i:-1; + return -1; } -static int checkmonth(const char *check) +static int checkmonth(const char *check, size_t len) { int i; - const char * const *what; - bool found = FALSE; + const char * const *what = &Curl_month[0]; + if(len != 3) + return -1; /* not a month */ - what = &Curl_month[0]; for(i = 0; i<12; i++) { - if(strcasecompare(check, what[0])) { - found = TRUE; - break; - } + if(strncasecompare(check, what[0], 3)) + return i; what++; } - return found?i:-1; /* return the offset or -1, no real offset is -1 */ + return -1; /* return the offset or -1, no real offset is -1 */ } /* return the time zone offset between GMT and the input one, in number of seconds or -1 if the timezone wasn't found/legal */ -static int checktz(const char *check) +static int checktz(const char *check, size_t len) { unsigned int i; - const struct tzinfo *what; - bool found = FALSE; + const struct tzinfo *what = tz; + if(len > 4) /* longer than any valid timezone */ + return -1; - what = tz; for(i = 0; i< sizeof(tz)/sizeof(tz[0]); i++) { - if(strcasecompare(check, what->name)) { - found = TRUE; - break; - } + size_t ilen = strlen(what->name); + if((ilen == len) && + strncasecompare(check, what->name, len)) + return what->offset*60; what++; } - return found?what->offset*60:-1; + return -1; } static void skip(const char **date) @@ -294,6 +293,53 @@ static time_t time2epoch(int sec, int min, int hour, + hour) * 60 + min) * 60 + sec; } +/* Returns the value of a single-digit or two-digit decimal number, return + then pointer to after the number. The 'date' pointer is known to point to a + digit. */ +static int oneortwodigit(const char *date, const char **endp) +{ + int num = date[0] - '0'; + if(ISDIGIT(date[1])) { + *endp = &date[2]; + return num*10 + (date[1] - '0'); + } + *endp = &date[1]; + return num; +} + + +/* HH:MM:SS or HH:MM and accept single-digits too */ +static bool match_time(const char *date, + int *h, int *m, int *s, char **endp) +{ + const char *p; + int hh, mm, ss = 0; + hh = oneortwodigit(date, &p); + if((hh < 24) && (*p == ':') && ISDIGIT(p[1])) { + mm = oneortwodigit(&p[1], &p); + if(mm < 60) { + if((*p == ':') && ISDIGIT(p[1])) { + ss = oneortwodigit(&p[1], &p); + if(ss <= 60) { + /* valid HH:MM:SS */ + goto match; + } + } + else { + /* valid HH:MM */ + goto match; + } + } + } + return FALSE; /* not a time string */ + match: + *h = hh; + *m = mm; + *s = ss; + *endp = (char *)p; + return TRUE; +} + /* * parsedate() * @@ -305,6 +351,9 @@ static time_t time2epoch(int sec, int min, int hour, * PARSEDATE_SOONER - time underflow at the low end of time_t */ +/* Wednesday is the longest name this parser knows about */ +#define NAME_LEN 12 + static int parsedate(const char *date, time_t *output) { time_t t = 0; @@ -327,32 +376,32 @@ static int parsedate(const char *date, time_t *output) if(ISALPHA(*date)) { /* a name coming up */ - char buf[32]=""; - size_t len; - if(sscanf(date, "%31[ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz]", buf)) - len = strlen(buf); - else - len = 0; - - if(wdaynum == -1) { - wdaynum = checkday(buf, len); - if(wdaynum != -1) - found = TRUE; - } - if(!found && (monnum == -1)) { - monnum = checkmonth(buf); - if(monnum != -1) - found = TRUE; + size_t len = 0; + const char *p = date; + while(ISALPHA(*p) && (len < NAME_LEN)) { + p++; + len++; } - if(!found && (tzoff == -1)) { - /* this just must be a time zone string */ - tzoff = checktz(buf); - if(tzoff != -1) - found = TRUE; - } + if(len != NAME_LEN) { + if(wdaynum == -1) { + wdaynum = checkday(date, len); + if(wdaynum != -1) + found = TRUE; + } + if(!found && (monnum == -1)) { + monnum = checkmonth(date, len); + if(monnum != -1) + found = TRUE; + } + if(!found && (tzoff == -1)) { + /* this just must be a time zone string */ + tzoff = checktz(date, len); + if(tzoff != -1) + found = TRUE; + } + } if(!found) return PARSEDATE_FAIL; /* bad string */ @@ -362,18 +411,10 @@ static int parsedate(const char *date, time_t *output) /* a digit */ int val; char *end; - int len = 0; if((secnum == -1) && - (3 == sscanf(date, "%02d:%02d:%02d%n", - &hournum, &minnum, &secnum, &len))) { - /* time stamp! */ - date += len; - } - else if((secnum == -1) && - (2 == sscanf(date, "%02d:%02d%n", &hournum, &minnum, &len))) { - /* time stamp without seconds */ - date += len; - secnum = 0; + match_time(date, &hournum, &minnum, &secnum, &end)) { + /* time stamp */ + date = end; } else { long lval; |