From 0bc5d2ca4cee4e6ace987d424098d643e40f1ca1 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Sat, 16 Apr 2016 23:27:38 +0100 Subject: create date and time to seconds since epoch processing utility function currently NetSurf uses curl_getdate to convert textural date and time strings into seconds since epoch. It is betetr to move this functionality to a utility function so curl_getdate can easily be replaced if required. --- content/llcache.c | 82 ++++++++++++++++++++++++++++++++++------------------- content/urldb.c | 23 +++++++-------- desktop/gui_fetch.h | 4 +-- utils/time.h | 24 +++++++++++++++- utils/utils.c | 57 ++++++++++++++++++++++++++----------- 5 files changed, 130 insertions(+), 60 deletions(-) diff --git a/content/llcache.c b/content/llcache.c index 7144dc585..9381ce958 100644 --- a/content/llcache.c +++ b/content/llcache.c @@ -37,7 +37,6 @@ #include #include -#include #include #include "utils/config.h" @@ -590,59 +589,79 @@ static nserror llcache_fetch_split_header(const uint8_t *data, size_t len, static nserror llcache_fetch_parse_header(llcache_object *object, const uint8_t *data, size_t len, char **name, char **value) { - nserror error; + nserror res; /* Set fetch response time if not already set */ - if (object->cache.res_time == 0) + if (object->cache.res_time == 0) { object->cache.res_time = time(NULL); + } /* Decompose header into name-value pair */ - error = llcache_fetch_split_header(data, len, name, value); - if (error != NSERROR_OK) - return error; + res = llcache_fetch_split_header(data, len, name, value); + if (res != NSERROR_OK) { + return res; + } /* Parse cache headers to populate cache control data */ -#define SKIP_ST(p) while (*p != '\0' && (*p == ' ' || *p == '\t')) p++ - if (5 < len && strcasecmp(*name, "Date") == 0) { + if ((5 < len) && + strcasecmp(*name, "Date") == 0) { /* extract Date header */ - object->cache.date = curl_getdate(*value, NULL); - } else if (4 < len && strcasecmp(*name, "Age") == 0) { + nsc_strntimet(*value, + strlen(*value), + &object->cache.date); + } else if ((4 < len) && + strcasecmp(*name, "Age") == 0) { /* extract Age header */ - if ('0' <= **value && **value <= '9') + if ('0' <= **value && **value <= '9') { object->cache.age = atoi(*value); - } else if (8 < len && strcasecmp(*name, "Expires") == 0) { + } + } else if ((8 < len) && + strcasecmp(*name, "Expires") == 0) { /* extract Expires header */ - object->cache.expires = curl_getdate(*value, NULL); - } else if (14 < len && strcasecmp(*name, "Cache-Control") == 0) { + res = nsc_strntimet(*value, + strlen(*value), + &object->cache.expires); + if (res != NSERROR_OK) { + object->cache.expires = (time_t)0x7fffffff; + } + } else if ((14 < len) && + strcasecmp(*name, "Cache-Control") == 0) { /* extract and parse Cache-Control header */ const char *start = *value; const char *comma = *value; while (*comma != '\0') { - while (*comma != '\0' && *comma != ',') + while (*comma != '\0' && *comma != ',') { comma++; - - if (8 < comma - start && (strncasecmp(start, - "no-cache", 8) == 0 || - strncasecmp(start, "no-store", 8) == 0)) - /* When we get a disk cache we should - * distinguish between these two */ + } + + if ((8 < comma - start) && + (strncasecmp(start, "no-cache", 8) == 0 || + strncasecmp(start, "no-store", 8) == 0)) { + /** + * \todo When we get a disk cache we should + * distinguish between these two. + */ object->cache.no_cache = LLCACHE_VALIDATE_ALWAYS; - else if (7 < comma - start && - strncasecmp(start, "max-age", 7) == 0) { + } else if ((7 < comma - start) && + strncasecmp(start, "max-age", 7) == 0) { /* Find '=' */ - while (start < comma && *start != '=') + while (start < comma && *start != '=') { start++; + } /* Skip over it */ start++; +#define SKIP_ST(p) while (*p != '\0' && (*p == ' ' || *p == '\t')) p++ + /* Skip whitespace */ SKIP_ST(start); - if (start < comma) + if (start < comma) { object->cache.max_age = atoi(start); + } } if (*comma != '\0') { @@ -652,10 +671,13 @@ static nserror llcache_fetch_parse_header(llcache_object *object, SKIP_ST(comma); } +#undef SKIP_ST + /* Set start for next token */ start = comma; } - } else if (5 < len && strcasecmp(*name, "ETag") == 0) { + } else if ((5 < len) && + (strcasecmp(*name, "ETag") == 0)) { /* extract ETag header */ free(object->cache.etag); object->cache.etag = strdup(*value); @@ -664,12 +686,14 @@ static nserror llcache_fetch_parse_header(llcache_object *object, free(*value); return NSERROR_NOMEM; } - } else if (14 < len && strcasecmp(*name, "Last-Modified") == 0) { + } else if ((14 < len) && + (strcasecmp(*name, "Last-Modified") == 0)) { /* extract Last-Modified header */ - object->cache.last_modified = curl_getdate(*value, NULL); + nsc_strntimet(*value, + strlen(*value), + &object->cache.last_modified); } -#undef SKIP_ST return NSERROR_OK; } diff --git a/content/urldb.c b/content/urldb.c index edb49b549..d7a7fed1c 100644 --- a/content/urldb.c +++ b/content/urldb.c @@ -95,7 +95,6 @@ #include #include #include -#include #include "utils/nsoption.h" #include "utils/log.h" @@ -103,6 +102,7 @@ #include "utils/url.h" #include "utils/utils.h" #include "utils/bloom.h" +#include "utils/time.h" #include "image/bitmap.h" #include "desktop/cookie_manager.h" #include "desktop/gui_internal.h" @@ -1587,22 +1587,21 @@ static bool urldb_parse_avpair(struct cookie_internal_data *c, char *n, } else if (strcasecmp(n, "Expires") == 0) { char *datenoday; time_t expires; + nserror res; - /* Strip dayname from date (these are hugely - * variable and liable to break the parser. - * They also serve no useful purpose) */ + /* Strip dayname from date (these are hugely variable + * and liable to break the parser. They also serve no + * useful purpose) */ for (datenoday = v; *datenoday && !isdigit(*datenoday); datenoday++) ; /* do nothing */ - expires = curl_getdate(datenoday, NULL); - if (expires == -1) { - /* assume we have an unrepresentable - * date => force it to the maximum - * possible value of a 32bit time_t - * (this may break in 2038. We'll - * deal with that once we come to - * it) */ + res = nsc_strntimet(datenoday, strlen(datenoday), &expires); + if (res != NSERROR_OK) { + /* assume we have an unrepresentable date => + * force it to the maximum possible value of a + * 32bit time_t (this may break in 2038. We'll + * deal with that once we come to it) */ expires = (time_t)0x7fffffff; } c->expires = expires; diff --git a/desktop/gui_fetch.h b/desktop/gui_fetch.h index 20db39d20..22c5e6a2e 100644 --- a/desktop/gui_fetch.h +++ b/desktop/gui_fetch.h @@ -91,8 +91,8 @@ struct gui_fetch_table { /** * Find a MIME type for a local file * - * @note only used in curl fetcher on RISC OS otherwise its a - * strdup of filetype. + * @note only used in curl fetcher in form file controls on + * RISC OS otherwise its a strdup of a filetype call. * * \param ro_path RISC OS style path to file on disk * \return MIME type string (on heap, caller should free), or NULL diff --git a/utils/time.h b/utils/time.h index bde2ff66a..a99cdc24a 100644 --- a/utils/time.h +++ b/utils/time.h @@ -48,6 +48,28 @@ int nsc_sntimet(char *str, size_t size, time_t *timep); * @param timep Pointer to result. * @return NSERROR_OK on success or error code on faliure. */ -nserror nsc_snptimet(char *str, size_t size, time_t *timep); +nserror nsc_snptimet(const char *str, size_t size, time_t *timep); + + +/** + * Converts a date string to a number of seconds since epoch + * + * returns the number of seconds since the Epoch, January 1st 1970 + * 00:00:00 in the UTC time zone, for the date and time that the + * \a str parameter specifies. + * + * datetime strings passed must be in one of the formats specified in: + * - RFC 822 (updated in RFC 1123) using time zone name or time zone delta + * - RFC 850 (obsoleted by RFC 1036) + * - ANSI C's asctime() format. + * + * @param[in] str The datetime string to parse + * @param[in] size The length of the source string + * @param[out] timep Pointer to result on success unmodified on error. + * @return NSERROR_OK on success and timep updated else + * NSERROR_INVALID if the string parsing failed otherwise a suitable + * error code + */ +nserror nsc_strntimet(const char *str, size_t size, time_t *timep); #endif diff --git a/utils/utils.c b/utils/utils.c index f97d14ea4..b3dee8bcc 100644 --- a/utils/utils.c +++ b/utils/utils.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "utils/config.h" #include "utils/log.h" @@ -47,13 +48,15 @@ char *remove_underscores(const char *s, bool replacespace) char *ret; len = strlen(s); ret = malloc(len + 1); - if (ret == NULL) + if (ret == NULL) { return NULL; + } for (i = 0, ii = 0; i < len; i++) { - if (s[i] != '_') + if (s[i] != '_') { ret[ii++] = s[i]; - else if (replacespace) + } else if (replacespace) { ret[ii++] = ' '; + } } ret[ii] = '\0'; return ret; @@ -94,11 +97,14 @@ char *cnv_space2nbsp(const char *s) char *d, *d0; unsigned int numNBS; /* Convert space & TAB into non breaking space character (0xA0) */ - for (numNBS = 0, srcP = (const char *)s; *srcP != '\0'; ++srcP) - if (*srcP == ' ' || *srcP == '\t') + for (numNBS = 0, srcP = (const char *)s; *srcP != '\0'; ++srcP) { + if (*srcP == ' ' || *srcP == '\t') { ++numNBS; - if ((d = (char *)malloc((srcP - s) + numNBS + 1)) == NULL) + } + } + if ((d = (char *)malloc((srcP - s) + numNBS + 1)) == NULL) { return NULL; + } for (d0 = d, srcP = (const char *)s; *srcP != '\0'; ++srcP) { if (*srcP == ' ' || *srcP == '\t') { *d0++ = 0xC2; @@ -116,8 +122,9 @@ bool is_dir(const char *path) { struct stat s; - if (stat(path, &s)) + if (stat(path, &s)) { return false; + } return S_ISDIR(s.st_mode) ? true : false; } @@ -227,7 +234,7 @@ nserror regcomp_wrapper(regex_t *preg, const char *regex, int cflags) * The size of buffers within human_friendly_bytesize. * * We can have a fairly good estimate of how long the buffer needs to - * be. The unsigned long can store a value representing a maximum + * be. The unsigned long can store a value representing a maximum * size of around 4 GB. Therefore the greatest space required is to * represent 1023MB. Currently that would be represented as "1023MB" * so 12 including a null terminator. Ideally we would be able to @@ -500,7 +507,7 @@ int uname(struct utsname *buf) { strcpy(buf->release,"release"); strcpy(buf->version,"version"); strcpy(buf->machine,"pc"); - + return 0; } #endif @@ -526,7 +533,7 @@ int inet_aton(const char *cp, struct in_addr *inp) unsigned int b1, b2, b3, b4; unsigned char c; - if (strspn(cp, "0123456789.") < strlen(cp)) + if (strspn(cp, "0123456789.") < strlen(cp)) return 0; if (sscanf(cp, "%3u.%3u.%3u.%3u%c", &b1, &b2, &b3, &b4, &c) != 4) @@ -550,17 +557,17 @@ int inet_pton(int af, const char *src, void *dst) if (af == AF_INET) { ret = inet_aton(src, dst); - } + } #if !defined(NO_IPV6) else if (af == AF_INET6) { /* TODO: implement v6 address support */ ret = -1; - errno = EAFNOSUPPORT; - } + errno = EAFNOSUPPORT; + } #endif else { ret = -1; - errno = EAFNOSUPPORT; + errno = EAFNOSUPPORT; } return ret; @@ -588,10 +595,11 @@ int nsc_sntimet(char *str, size_t size, time_t *timep) } return strftime(str, size, "%s", ltm); -#endif +#endif } -nserror nsc_snptimet(char *str, size_t size, time_t *timep) +/* exported function documented in utils/time.h */ +nserror nsc_snptimet(const char *str, size_t size, time_t *timep) { time_t time_out; @@ -628,3 +636,20 @@ nserror nsc_snptimet(char *str, size_t size, time_t *timep) return NSERROR_OK; } + + +/* exported function documented in utils/time.h */ +nserror nsc_strntimet(const char *str, size_t size, time_t *timep) +{ + time_t result; + + result = curl_getdate(str, NULL); + + if (result == -1) { + return NSERROR_INVALID; + } + + *timep = result; + + return NSERROR_OK; +} -- cgit v1.2.3