summaryrefslogtreecommitdiffstats
path: root/Utilities/cmcurl/lib/parsedate.c
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2023-03-20 20:40:49 (GMT)
committerBrad King <brad.king@kitware.com>2023-03-20 20:40:49 (GMT)
commite3dc4df9b95272037d27be25ae5ef030ffd83fa4 (patch)
tree6132bc02d5204bd988b32ee8ab06053ec7c0e4c4 /Utilities/cmcurl/lib/parsedate.c
parent4e6c3cd93bc870f44442e6d7e59896bc6d86ce25 (diff)
parente8bff971d9d835a65bcb1711e7214afe37b238e0 (diff)
downloadCMake-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.c159
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;