diff options
Diffstat (limited to 'Utilities/cmcurl/lib/cookie.c')
-rw-r--r-- | Utilities/cmcurl/lib/cookie.c | 99 |
1 files changed, 60 insertions, 39 deletions
diff --git a/Utilities/cmcurl/lib/cookie.c b/Utilities/cmcurl/lib/cookie.c index 9a9e14d..69bc042 100644 --- a/Utilities/cmcurl/lib/cookie.c +++ b/Utilities/cmcurl/lib/cookie.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -96,6 +96,9 @@ Example set of cookies: #include "curl_get_line.h" #include "curl_memrchr.h" #include "inet_pton.h" +#include "parsedate.h" +#include "rand.h" +#include "rename.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" @@ -536,9 +539,9 @@ Curl_cookie_add(struct Curl_easy *data, * only test for names where that can possibly be true. */ if(nlen > 3 && name[0] == '_' && name[1] == '_') { - if(strncasecompare("__Secure-", name, 9)) + if(!strncmp("__Secure-", name, 9)) co->prefix |= COOKIE_PREFIX__SECURE; - else if(strncasecompare("__Host-", name, 7)) + else if(!strncmp("__Host-", name, 7)) co->prefix |= COOKIE_PREFIX__HOST; } @@ -715,7 +718,7 @@ Curl_cookie_add(struct Curl_easy *data, else if(co->expirestr) { /* Note that if the date couldn't get parsed for whatever reason, the cookie will be treated as a session cookie */ - co->expires = curl_getdate(co->expirestr, NULL); + co->expires = Curl_getdate_capped(co->expirestr); /* Session cookies have expires set to 0 so if we get that back from the date parser let's add a second to make it a @@ -819,22 +822,14 @@ Curl_cookie_add(struct Curl_easy *data, badcookie = TRUE; break; case 1: - /* This field got its explanation on the 23rd of May 2001 by - Andrés García: - - flag: A TRUE/FALSE value indicating if all machines within a given - domain can access the variable. This value is set automatically by - the browser, depending on the value you set for the domain. - - As far as I can see, it is set to true when the cookie says + /* flag: A TRUE/FALSE value indicating if all machines within a given + domain can access the variable. Set TRUE when the cookie says .domain.com and to false when the domain is complete www.domain.com */ co->tailmatch = strcasecompare(ptr, "TRUE")?TRUE:FALSE; break; case 2: - /* It turns out, that sometimes the file format allows the path - field to remain not filled in, we try to detect this and work - around it! Andrés García made us aware of this... */ + /* The file format allows the path field to remain not filled in */ if(strcmp("TRUE", ptr) && strcmp("FALSE", ptr)) { /* only if the path doesn't look like a boolean option! */ co->path = strdup(ptr); @@ -1053,7 +1048,7 @@ Curl_cookie_add(struct Curl_easy *data, *clist = *co; /* then store all the new data */ - free(co); /* free the newly alloced memory */ + free(co); /* free the newly allocated memory */ co = clist; /* point to the previous struct instead */ /* We have replaced a cookie, now skip the rest of the list but @@ -1098,6 +1093,8 @@ Curl_cookie_add(struct Curl_easy *data, * * If 'newsession' is TRUE, discard all "session cookies" on read from file. * + * Note that 'data' might be called as NULL pointer. + * * Returns NULL on out of memory. Invalid cookies are ignored. ****************************************************************************/ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data, @@ -1168,6 +1165,8 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data, } c->running = TRUE; /* now, we're running */ + if(data) + data->state.cookie_engine = TRUE; return c; @@ -1504,11 +1503,14 @@ static char *get_netscape_format(const struct Cookie *co) * * The function returns non-zero on write failure. */ -static int cookie_output(struct CookieInfo *c, const char *dumphere) +static int cookie_output(struct Curl_easy *data, + struct CookieInfo *c, const char *filename) { struct Cookie *co; - FILE *out; + FILE *out = NULL; bool use_stdout = FALSE; + char *tempstore = NULL; + bool error = false; if(!c) /* no cookie engine alive */ @@ -1517,16 +1519,24 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere) /* at first, remove expired cookies */ remove_expired(c); - if(!strcmp("-", dumphere)) { + if(!strcmp("-", filename)) { /* use stdout */ out = stdout; use_stdout = TRUE; } else { - out = fopen(dumphere, FOPEN_WRITETEXT); - if(!out) { - return 1; /* failure */ - } + unsigned char randsuffix[9]; + + if(Curl_rand_hex(data, randsuffix, sizeof(randsuffix))) + return 2; + + tempstore = aprintf("%s.%s.tmp", filename, randsuffix); + if(!tempstore) + return 1; + + out = fopen(tempstore, FOPEN_WRITETEXT); + if(!out) + goto error; } fputs("# Netscape HTTP Cookie File\n" @@ -1536,35 +1546,31 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere) if(c->numcookies) { unsigned int i; - unsigned int j; + size_t nvalid = 0; struct Cookie **array; - array = malloc(sizeof(struct Cookie *) * c->numcookies); + array = calloc(1, sizeof(struct Cookie *) * c->numcookies); if(!array) { - if(!use_stdout) - fclose(out); - return 1; + goto error; } - j = 0; + /* only sort the cookies with a domain property */ for(i = 0; i < COOKIE_HASH_SIZE; i++) { for(co = c->cookies[i]; co; co = co->next) { if(!co->domain) continue; - array[j++] = co; + array[nvalid++] = co; } } - qsort(array, c->numcookies, sizeof(struct Cookie *), cookie_sort_ct); + qsort(array, nvalid, sizeof(struct Cookie *), cookie_sort_ct); - for(i = 0; i < j; i++) { + for(i = 0; i < nvalid; i++) { char *format_ptr = get_netscape_format(array[i]); if(format_ptr == NULL) { fprintf(out, "#\n# Fatal libcurl error\n"); free(array); - if(!use_stdout) - fclose(out); - return 1; + goto error; } fprintf(out, "%s\n", format_ptr); free(format_ptr); @@ -1572,10 +1578,24 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere) free(array); } - if(!use_stdout) + + if(!use_stdout) { fclose(out); + out = NULL; + if(Curl_rename(tempstore, filename)) { + unlink(tempstore); + goto error; + } + } - return 0; + goto cleanup; +error: + error = true; +cleanup: + if(out && !use_stdout) + fclose(out); + free(tempstore); + return error ? 1 : 0; } static struct curl_slist *cookie_list(struct Curl_easy *data) @@ -1621,7 +1641,7 @@ struct curl_slist *Curl_cookie_list(struct Curl_easy *data) return list; } -void Curl_flush_cookies(struct Curl_easy *data, int cleanup) +void Curl_flush_cookies(struct Curl_easy *data, bool cleanup) { if(data->set.str[STRING_COOKIEJAR]) { if(data->change.cookielist) { @@ -1634,7 +1654,7 @@ void Curl_flush_cookies(struct Curl_easy *data, int cleanup) Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); /* if we have a destination file for all the cookies to get dumped to */ - if(cookie_output(data->cookies, data->set.str[STRING_COOKIEJAR])) + if(cookie_output(data, data->cookies, data->set.str[STRING_COOKIEJAR])) infof(data, "WARNING: failed to save cookies in %s\n", data->set.str[STRING_COOKIEJAR]); } @@ -1650,6 +1670,7 @@ void Curl_flush_cookies(struct Curl_easy *data, int cleanup) if(cleanup && (!data->share || (data->cookies != data->share->cookies))) { Curl_cookie_cleanup(data->cookies); + data->cookies = NULL; } Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); } |