Home | History | Annotate | Download | only in lib
      1 /***************************************************************************
      2  *                                  _   _ ____  _
      3  *  Project                     ___| | | |  _ \| |
      4  *                             / __| | | | |_) | |
      5  *                            | (__| |_| |  _ <| |___
      6  *                             \___|\___/|_| \_\_____|
      7  *
      8  * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel (at) haxx.se>, et al.
      9  *
     10  * This software is licensed as described in the file COPYING, which
     11  * you should have received as part of this distribution. The terms
     12  * are also available at https://curl.haxx.se/docs/copyright.html.
     13  *
     14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
     15  * copies of the Software, and permit persons to whom the Software is
     16  * furnished to do so, under the terms of the COPYING file.
     17  *
     18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
     19  * KIND, either express or implied.
     20  *
     21  ***************************************************************************/
     22 
     23 /***
     24 
     25 
     26 RECEIVING COOKIE INFORMATION
     27 ============================
     28 
     29 struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
     30                     const char *file, struct CookieInfo *inc, bool newsession);
     31 
     32         Inits a cookie struct to store data in a local file. This is always
     33         called before any cookies are set.
     34 
     35 struct Cookie *Curl_cookie_add(struct Curl_easy *data,
     36                  struct CookieInfo *c, bool httpheader, char *lineptr,
     37                  const char *domain, const char *path);
     38 
     39         The 'lineptr' parameter is a full "Set-cookie:" line as
     40         received from a server.
     41 
     42         The function need to replace previously stored lines that this new
     43         line superceeds.
     44 
     45         It may remove lines that are expired.
     46 
     47         It should return an indication of success/error.
     48 
     49 
     50 SENDING COOKIE INFORMATION
     51 ==========================
     52 
     53 struct Cookies *Curl_cookie_getlist(struct CookieInfo *cookie,
     54                                     char *host, char *path, bool secure);
     55 
     56         For a given host and path, return a linked list of cookies that
     57         the client should send to the server if used now. The secure
     58         boolean informs the cookie if a secure connection is achieved or
     59         not.
     60 
     61         It shall only return cookies that haven't expired.
     62 
     63 
     64 Example set of cookies:
     65 
     66     Set-cookie: PRODUCTINFO=webxpress; domain=.fidelity.com; path=/; secure
     67     Set-cookie: PERSONALIZE=none;expires=Monday, 13-Jun-1988 03:04:55 GMT;
     68     domain=.fidelity.com; path=/ftgw; secure
     69     Set-cookie: FidHist=none;expires=Monday, 13-Jun-1988 03:04:55 GMT;
     70     domain=.fidelity.com; path=/; secure
     71     Set-cookie: FidOrder=none;expires=Monday, 13-Jun-1988 03:04:55 GMT;
     72     domain=.fidelity.com; path=/; secure
     73     Set-cookie: DisPend=none;expires=Monday, 13-Jun-1988 03:04:55 GMT;
     74     domain=.fidelity.com; path=/; secure
     75     Set-cookie: FidDis=none;expires=Monday, 13-Jun-1988 03:04:55 GMT;
     76     domain=.fidelity.com; path=/; secure
     77     Set-cookie:
     78     Session_Key@6791a9e0-901a-11d0-a1c8-9b012c88aa77=none;expires=Monday,
     79     13-Jun-1988 03:04:55 GMT; domain=.fidelity.com; path=/; secure
     80 ****/
     81 
     82 
     83 #include "curl_setup.h"
     84 
     85 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
     86 
     87 #ifdef USE_LIBPSL
     88 # include <libpsl.h>
     89 #endif
     90 
     91 #include "urldata.h"
     92 #include "cookie.h"
     93 #include "strtok.h"
     94 #include "sendf.h"
     95 #include "slist.h"
     96 #include "share.h"
     97 #include "strtoofft.h"
     98 #include "strcase.h"
     99 #include "curl_memrchr.h"
    100 #include "inet_pton.h"
    101 
    102 /* The last 3 #include files should be in this order */
    103 #include "curl_printf.h"
    104 #include "curl_memory.h"
    105 #include "memdebug.h"
    106 
    107 static void freecookie(struct Cookie *co)
    108 {
    109   free(co->expirestr);
    110   free(co->domain);
    111   free(co->path);
    112   free(co->spath);
    113   free(co->name);
    114   free(co->value);
    115   free(co->maxage);
    116   free(co->version);
    117   free(co);
    118 }
    119 
    120 static bool tailmatch(const char *cooke_domain, const char *hostname)
    121 {
    122   size_t cookie_domain_len = strlen(cooke_domain);
    123   size_t hostname_len = strlen(hostname);
    124 
    125   if(hostname_len < cookie_domain_len)
    126     return FALSE;
    127 
    128   if(!strcasecompare(cooke_domain, hostname + hostname_len-cookie_domain_len))
    129     return FALSE;
    130 
    131   /* A lead char of cookie_domain is not '.'.
    132      RFC6265 4.1.2.3. The Domain Attribute says:
    133        For example, if the value of the Domain attribute is
    134        "example.com", the user agent will include the cookie in the Cookie
    135        header when making HTTP requests to example.com, www.example.com, and
    136        www.corp.example.com.
    137    */
    138   if(hostname_len == cookie_domain_len)
    139     return TRUE;
    140   if('.' == *(hostname + hostname_len - cookie_domain_len - 1))
    141     return TRUE;
    142   return FALSE;
    143 }
    144 
    145 /*
    146  * matching cookie path and url path
    147  * RFC6265 5.1.4 Paths and Path-Match
    148  */
    149 static bool pathmatch(const char *cookie_path, const char *request_uri)
    150 {
    151   size_t cookie_path_len;
    152   size_t uri_path_len;
    153   char *uri_path = NULL;
    154   char *pos;
    155   bool ret = FALSE;
    156 
    157   /* cookie_path must not have last '/' separator. ex: /sample */
    158   cookie_path_len = strlen(cookie_path);
    159   if(1 == cookie_path_len) {
    160     /* cookie_path must be '/' */
    161     return TRUE;
    162   }
    163 
    164   uri_path = strdup(request_uri);
    165   if(!uri_path)
    166     return FALSE;
    167   pos = strchr(uri_path, '?');
    168   if(pos)
    169     *pos = 0x0;
    170 
    171   /* #-fragments are already cut off! */
    172   if(0 == strlen(uri_path) || uri_path[0] != '/') {
    173     free(uri_path);
    174     uri_path = strdup("/");
    175     if(!uri_path)
    176       return FALSE;
    177   }
    178 
    179   /* here, RFC6265 5.1.4 says
    180      4. Output the characters of the uri-path from the first character up
    181         to, but not including, the right-most %x2F ("/").
    182      but URL path /hoge?fuga=xxx means /hoge/index.cgi?fuga=xxx in some site
    183      without redirect.
    184      Ignore this algorithm because /hoge is uri path for this case
    185      (uri path is not /).
    186    */
    187 
    188   uri_path_len = strlen(uri_path);
    189 
    190   if(uri_path_len < cookie_path_len) {
    191     ret = FALSE;
    192     goto pathmatched;
    193   }
    194 
    195   /* not using checkprefix() because matching should be case-sensitive */
    196   if(strncmp(cookie_path, uri_path, cookie_path_len)) {
    197     ret = FALSE;
    198     goto pathmatched;
    199   }
    200 
    201   /* The cookie-path and the uri-path are identical. */
    202   if(cookie_path_len == uri_path_len) {
    203     ret = TRUE;
    204     goto pathmatched;
    205   }
    206 
    207   /* here, cookie_path_len < url_path_len */
    208   if(uri_path[cookie_path_len] == '/') {
    209     ret = TRUE;
    210     goto pathmatched;
    211   }
    212 
    213   ret = FALSE;
    214 
    215 pathmatched:
    216   free(uri_path);
    217   return ret;
    218 }
    219 
    220 /*
    221  * cookie path sanitize
    222  */
    223 static char *sanitize_cookie_path(const char *cookie_path)
    224 {
    225   size_t len;
    226   char *new_path = strdup(cookie_path);
    227   if(!new_path)
    228     return NULL;
    229 
    230   /* some stupid site sends path attribute with '"'. */
    231   len = strlen(new_path);
    232   if(new_path[0] == '\"') {
    233     memmove((void *)new_path, (const void *)(new_path + 1), len);
    234     len--;
    235   }
    236   if(len && (new_path[len - 1] == '\"')) {
    237     new_path[len - 1] = 0x0;
    238     len--;
    239   }
    240 
    241   /* RFC6265 5.2.4 The Path Attribute */
    242   if(new_path[0] != '/') {
    243     /* Let cookie-path be the default-path. */
    244     free(new_path);
    245     new_path = strdup("/");
    246     return new_path;
    247   }
    248 
    249   /* convert /hoge/ to /hoge */
    250   if(len && new_path[len - 1] == '/') {
    251     new_path[len - 1] = 0x0;
    252   }
    253 
    254   return new_path;
    255 }
    256 
    257 /*
    258  * Load cookies from all given cookie files (CURLOPT_COOKIEFILE).
    259  *
    260  * NOTE: OOM or cookie parsing failures are ignored.
    261  */
    262 void Curl_cookie_loadfiles(struct Curl_easy *data)
    263 {
    264   struct curl_slist *list = data->change.cookielist;
    265   if(list) {
    266     Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
    267     while(list) {
    268       struct CookieInfo *newcookies = Curl_cookie_init(data,
    269                                         list->data,
    270                                         data->cookies,
    271                                         data->set.cookiesession);
    272       if(!newcookies)
    273         /* Failure may be due to OOM or a bad cookie; both are ignored
    274          * but only the first should be
    275          */
    276         infof(data, "ignoring failed cookie_init for %s\n", list->data);
    277       else
    278         data->cookies = newcookies;
    279       list = list->next;
    280     }
    281     curl_slist_free_all(data->change.cookielist); /* clean up list */
    282     data->change.cookielist = NULL; /* don't do this again! */
    283     Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
    284   }
    285 }
    286 
    287 /*
    288  * strstore() makes a strdup() on the 'newstr' and if '*str' is non-NULL
    289  * that will be freed before the allocated string is stored there.
    290  *
    291  * It is meant to easily replace strdup()
    292  */
    293 static void strstore(char **str, const char *newstr)
    294 {
    295   free(*str);
    296   *str = strdup(newstr);
    297 }
    298 
    299 /*
    300  * remove_expired() removes expired cookies.
    301  */
    302 static void remove_expired(struct CookieInfo *cookies)
    303 {
    304   struct Cookie *co, *nx, *pv;
    305   curl_off_t now = (curl_off_t)time(NULL);
    306 
    307   co = cookies->cookies;
    308   pv = NULL;
    309   while(co) {
    310     nx = co->next;
    311     if(co->expires && co->expires < now) {
    312       if(!pv) {
    313         cookies->cookies = co->next;
    314       }
    315       else {
    316         pv->next = co->next;
    317       }
    318       cookies->numcookies--;
    319       freecookie(co);
    320     }
    321     else {
    322       pv = co;
    323     }
    324     co = nx;
    325   }
    326 }
    327 
    328 /*
    329  * Return true if the given string is an IP(v4|v6) address.
    330  */
    331 static bool isip(const char *domain)
    332 {
    333   struct in_addr addr;
    334 #ifdef ENABLE_IPV6
    335   struct in6_addr addr6;
    336 #endif
    337 
    338   if(Curl_inet_pton(AF_INET, domain, &addr)
    339 #ifdef ENABLE_IPV6
    340      || Curl_inet_pton(AF_INET6, domain, &addr6)
    341 #endif
    342     ) {
    343     /* domain name given as IP address */
    344     return TRUE;
    345   }
    346 
    347   return FALSE;
    348 }
    349 
    350 /****************************************************************************
    351  *
    352  * Curl_cookie_add()
    353  *
    354  * Add a single cookie line to the cookie keeping object.
    355  *
    356  * Be aware that sometimes we get an IP-only host name, and that might also be
    357  * a numerical IPv6 address.
    358  *
    359  * Returns NULL on out of memory or invalid cookie. This is suboptimal,
    360  * as they should be treated separately.
    361  ***************************************************************************/
    362 
    363 struct Cookie *
    364 Curl_cookie_add(struct Curl_easy *data,
    365                 /* The 'data' pointer here may be NULL at times, and thus
    366                    must only be used very carefully for things that can deal
    367                    with data being NULL. Such as infof() and similar */
    368 
    369                 struct CookieInfo *c,
    370                 bool httpheader, /* TRUE if HTTP header-style line */
    371                 char *lineptr,   /* first character of the line */
    372                 const char *domain, /* default domain */
    373                 const char *path)   /* full path used when this cookie is set,
    374                                        used to get default path for the cookie
    375                                        unless set */
    376 {
    377   struct Cookie *clist;
    378   struct Cookie *co;
    379   struct Cookie *lastc = NULL;
    380   time_t now = time(NULL);
    381   bool replace_old = FALSE;
    382   bool badcookie = FALSE; /* cookies are good by default. mmmmm yummy */
    383 
    384 #ifdef USE_LIBPSL
    385   const psl_ctx_t *psl;
    386 #endif
    387 
    388 #ifdef CURL_DISABLE_VERBOSE_STRINGS
    389   (void)data;
    390 #endif
    391 
    392   /* First, alloc and init a new struct for it */
    393   co = calloc(1, sizeof(struct Cookie));
    394   if(!co)
    395     return NULL; /* bail out if we're this low on memory */
    396 
    397   if(httpheader) {
    398     /* This line was read off a HTTP-header */
    399     char name[MAX_NAME];
    400     char what[MAX_NAME];
    401     const char *ptr;
    402     const char *semiptr;
    403 
    404     size_t linelength = strlen(lineptr);
    405     if(linelength > MAX_COOKIE_LINE) {
    406       /* discard overly long lines at once */
    407       free(co);
    408       return NULL;
    409     }
    410 
    411     semiptr = strchr(lineptr, ';'); /* first, find a semicolon */
    412 
    413     while(*lineptr && ISBLANK(*lineptr))
    414       lineptr++;
    415 
    416     ptr = lineptr;
    417     do {
    418       /* we have a <what>=<this> pair or a stand-alone word here */
    419       name[0] = what[0] = 0; /* init the buffers */
    420       if(1 <= sscanf(ptr, "%" MAX_NAME_TXT "[^;\r\n=] =%"
    421                      MAX_NAME_TXT "[^;\r\n]",
    422                      name, what)) {
    423         /* Use strstore() below to properly deal with received cookie
    424            headers that have the same string property set more than once,
    425            and then we use the last one. */
    426         const char *whatptr;
    427         bool done = FALSE;
    428         bool sep;
    429         size_t len = strlen(what);
    430         size_t nlen = strlen(name);
    431         const char *endofn = &ptr[ nlen ];
    432 
    433         infof(data, "cookie size: name/val %d + %d bytes\n",
    434               nlen, len);
    435 
    436         if(nlen >= (MAX_NAME-1) || len >= (MAX_NAME-1) ||
    437            ((nlen + len) > MAX_NAME)) {
    438           /* too long individual name or contents, or too long combination of
    439              name + contents. Chrome and Firefox support 4095 or 4096 bytes
    440              combo. */
    441           freecookie(co);
    442           infof(data, "oversized cookie dropped, name/val %d + %d bytes\n",
    443                 nlen, len);
    444           return NULL;
    445         }
    446 
    447         /* name ends with a '=' ? */
    448         sep = (*endofn == '=')?TRUE:FALSE;
    449 
    450         if(nlen) {
    451           endofn--; /* move to the last character */
    452           if(ISBLANK(*endofn)) {
    453             /* skip trailing spaces in name */
    454             while(*endofn && ISBLANK(*endofn) && nlen) {
    455               endofn--;
    456               nlen--;
    457             }
    458             name[nlen] = 0; /* new end of name */
    459           }
    460         }
    461 
    462         /* Strip off trailing whitespace from the 'what' */
    463         while(len && ISBLANK(what[len-1])) {
    464           what[len-1] = 0;
    465           len--;
    466         }
    467 
    468         /* Skip leading whitespace from the 'what' */
    469         whatptr = what;
    470         while(*whatptr && ISBLANK(*whatptr))
    471           whatptr++;
    472 
    473         if(!co->name && sep) {
    474           /* The very first name/value pair is the actual cookie name */
    475           co->name = strdup(name);
    476           co->value = strdup(whatptr);
    477           if(!co->name || !co->value) {
    478             badcookie = TRUE;
    479             break;
    480           }
    481         }
    482         else if(!len) {
    483           /* this was a "<name>=" with no content, and we must allow
    484              'secure' and 'httponly' specified this weirdly */
    485           done = TRUE;
    486           if(strcasecompare("secure", name))
    487             co->secure = TRUE;
    488           else if(strcasecompare("httponly", name))
    489             co->httponly = TRUE;
    490           else if(sep)
    491             /* there was a '=' so we're not done parsing this field */
    492             done = FALSE;
    493         }
    494         if(done)
    495           ;
    496         else if(strcasecompare("path", name)) {
    497           strstore(&co->path, whatptr);
    498           if(!co->path) {
    499             badcookie = TRUE; /* out of memory bad */
    500             break;
    501           }
    502           free(co->spath); /* if this is set again */
    503           co->spath = sanitize_cookie_path(co->path);
    504           if(!co->spath) {
    505             badcookie = TRUE; /* out of memory bad */
    506             break;
    507           }
    508         }
    509         else if(strcasecompare("domain", name)) {
    510           bool is_ip;
    511 
    512           /* Now, we make sure that our host is within the given domain,
    513              or the given domain is not valid and thus cannot be set. */
    514 
    515           if('.' == whatptr[0])
    516             whatptr++; /* ignore preceding dot */
    517 
    518 #ifndef USE_LIBPSL
    519           /*
    520            * Without PSL we don't know when the incoming cookie is set on a
    521            * TLD or otherwise "protected" suffix. To reduce risk, we require a
    522            * dot OR the exact host name being "localhost".
    523            */
    524           {
    525             const char *dotp;
    526             /* check for more dots */
    527             dotp = strchr(whatptr, '.');
    528             if(!dotp && !strcasecompare("localhost", whatptr))
    529               domain = ":";
    530           }
    531 #endif
    532 
    533           is_ip = isip(domain ? domain : whatptr);
    534 
    535           if(!domain
    536              || (is_ip && !strcmp(whatptr, domain))
    537              || (!is_ip && tailmatch(whatptr, domain))) {
    538             strstore(&co->domain, whatptr);
    539             if(!co->domain) {
    540               badcookie = TRUE;
    541               break;
    542             }
    543             if(!is_ip)
    544               co->tailmatch = TRUE; /* we always do that if the domain name was
    545                                        given */
    546           }
    547           else {
    548             /* we did not get a tailmatch and then the attempted set domain
    549                is not a domain to which the current host belongs. Mark as
    550                bad. */
    551             badcookie = TRUE;
    552             infof(data, "skipped cookie with bad tailmatch domain: %s\n",
    553                   whatptr);
    554           }
    555         }
    556         else if(strcasecompare("version", name)) {
    557           strstore(&co->version, whatptr);
    558           if(!co->version) {
    559             badcookie = TRUE;
    560             break;
    561           }
    562         }
    563         else if(strcasecompare("max-age", name)) {
    564           /* Defined in RFC2109:
    565 
    566              Optional.  The Max-Age attribute defines the lifetime of the
    567              cookie, in seconds.  The delta-seconds value is a decimal non-
    568              negative integer.  After delta-seconds seconds elapse, the
    569              client should discard the cookie.  A value of zero means the
    570              cookie should be discarded immediately.
    571 
    572           */
    573           strstore(&co->maxage, whatptr);
    574           if(!co->maxage) {
    575             badcookie = TRUE;
    576             break;
    577           }
    578         }
    579         else if(strcasecompare("expires", name)) {
    580           strstore(&co->expirestr, whatptr);
    581           if(!co->expirestr) {
    582             badcookie = TRUE;
    583             break;
    584           }
    585         }
    586         /*
    587           else this is the second (or more) name we don't know
    588           about! */
    589       }
    590       else {
    591         /* this is an "illegal" <what>=<this> pair */
    592       }
    593 
    594       if(!semiptr || !*semiptr) {
    595         /* we already know there are no more cookies */
    596         semiptr = NULL;
    597         continue;
    598       }
    599 
    600       ptr = semiptr + 1;
    601       while(*ptr && ISBLANK(*ptr))
    602         ptr++;
    603       semiptr = strchr(ptr, ';'); /* now, find the next semicolon */
    604 
    605       if(!semiptr && *ptr)
    606         /* There are no more semicolons, but there's a final name=value pair
    607            coming up */
    608         semiptr = strchr(ptr, '\0');
    609     } while(semiptr);
    610 
    611     if(co->maxage) {
    612       CURLofft offt;
    613       offt = curlx_strtoofft((*co->maxage == '\"')?
    614                              &co->maxage[1]:&co->maxage[0], NULL, 10,
    615                              &co->expires);
    616       if(offt == CURL_OFFT_FLOW)
    617         /* overflow, used max value */
    618         co->expires = CURL_OFF_T_MAX;
    619       else if(!offt) {
    620         if(CURL_OFF_T_MAX - now < co->expires)
    621           /* would overflow */
    622           co->expires = CURL_OFF_T_MAX;
    623         else
    624           co->expires += now;
    625       }
    626     }
    627     else if(co->expirestr) {
    628       /* Note that if the date couldn't get parsed for whatever reason,
    629          the cookie will be treated as a session cookie */
    630       co->expires = curl_getdate(co->expirestr, NULL);
    631 
    632       /* Session cookies have expires set to 0 so if we get that back
    633          from the date parser let's add a second to make it a
    634          non-session cookie */
    635       if(co->expires == 0)
    636         co->expires = 1;
    637       else if(co->expires < 0)
    638         co->expires = 0;
    639     }
    640 
    641     if(!badcookie && !co->domain) {
    642       if(domain) {
    643         /* no domain was given in the header line, set the default */
    644         co->domain = strdup(domain);
    645         if(!co->domain)
    646           badcookie = TRUE;
    647       }
    648     }
    649 
    650     if(!badcookie && !co->path && path) {
    651       /* No path was given in the header line, set the default.
    652          Note that the passed-in path to this function MAY have a '?' and
    653          following part that MUST not be stored as part of the path. */
    654       char *queryp = strchr(path, '?');
    655 
    656       /* queryp is where the interesting part of the path ends, so now we
    657          want to the find the last */
    658       char *endslash;
    659       if(!queryp)
    660         endslash = strrchr(path, '/');
    661       else
    662         endslash = memrchr(path, '/', (size_t)(queryp - path));
    663       if(endslash) {
    664         size_t pathlen = (size_t)(endslash-path + 1); /* include end slash */
    665         co->path = malloc(pathlen + 1); /* one extra for the zero byte */
    666         if(co->path) {
    667           memcpy(co->path, path, pathlen);
    668           co->path[pathlen] = 0; /* zero terminate */
    669           co->spath = sanitize_cookie_path(co->path);
    670           if(!co->spath)
    671             badcookie = TRUE; /* out of memory bad */
    672         }
    673         else
    674           badcookie = TRUE;
    675       }
    676     }
    677 
    678     if(badcookie || !co->name) {
    679       /* we didn't get a cookie name or a bad one,
    680          this is an illegal line, bail out */
    681       freecookie(co);
    682       return NULL;
    683     }
    684 
    685   }
    686   else {
    687     /* This line is NOT a HTTP header style line, we do offer support for
    688        reading the odd netscape cookies-file format here */
    689     char *ptr;
    690     char *firstptr;
    691     char *tok_buf = NULL;
    692     int fields;
    693 
    694     /* IE introduced HTTP-only cookies to prevent XSS attacks. Cookies
    695        marked with httpOnly after the domain name are not accessible
    696        from javascripts, but since curl does not operate at javascript
    697        level, we include them anyway. In Firefox's cookie files, these
    698        lines are preceded with #HttpOnly_ and then everything is
    699        as usual, so we skip 10 characters of the line..
    700     */
    701     if(strncmp(lineptr, "#HttpOnly_", 10) == 0) {
    702       lineptr += 10;
    703       co->httponly = TRUE;
    704     }
    705 
    706     if(lineptr[0]=='#') {
    707       /* don't even try the comments */
    708       free(co);
    709       return NULL;
    710     }
    711     /* strip off the possible end-of-line characters */
    712     ptr = strchr(lineptr, '\r');
    713     if(ptr)
    714       *ptr = 0; /* clear it */
    715     ptr = strchr(lineptr, '\n');
    716     if(ptr)
    717       *ptr = 0; /* clear it */
    718 
    719     firstptr = strtok_r(lineptr, "\t", &tok_buf); /* tokenize it on the TAB */
    720 
    721     /* Now loop through the fields and init the struct we already have
    722        allocated */
    723     for(ptr = firstptr, fields = 0; ptr && !badcookie;
    724         ptr = strtok_r(NULL, "\t", &tok_buf), fields++) {
    725       switch(fields) {
    726       case 0:
    727         if(ptr[0]=='.') /* skip preceding dots */
    728           ptr++;
    729         co->domain = strdup(ptr);
    730         if(!co->domain)
    731           badcookie = TRUE;
    732         break;
    733       case 1:
    734         /* This field got its explanation on the 23rd of May 2001 by
    735            Andrs Garca:
    736 
    737            flag: A TRUE/FALSE value indicating if all machines within a given
    738            domain can access the variable. This value is set automatically by
    739            the browser, depending on the value you set for the domain.
    740 
    741            As far as I can see, it is set to true when the cookie says
    742            .domain.com and to false when the domain is complete www.domain.com
    743         */
    744         co->tailmatch = strcasecompare(ptr, "TRUE")?TRUE:FALSE;
    745         break;
    746       case 2:
    747         /* It turns out, that sometimes the file format allows the path
    748            field to remain not filled in, we try to detect this and work
    749            around it! Andrs Garca made us aware of this... */
    750         if(strcmp("TRUE", ptr) && strcmp("FALSE", ptr)) {
    751           /* only if the path doesn't look like a boolean option! */
    752           co->path = strdup(ptr);
    753           if(!co->path)
    754             badcookie = TRUE;
    755           else {
    756             co->spath = sanitize_cookie_path(co->path);
    757             if(!co->spath) {
    758               badcookie = TRUE; /* out of memory bad */
    759             }
    760           }
    761           break;
    762         }
    763         /* this doesn't look like a path, make one up! */
    764         co->path = strdup("/");
    765         if(!co->path)
    766           badcookie = TRUE;
    767         co->spath = strdup("/");
    768         if(!co->spath)
    769           badcookie = TRUE;
    770         fields++; /* add a field and fall down to secure */
    771         /* FALLTHROUGH */
    772       case 3:
    773         co->secure = strcasecompare(ptr, "TRUE")?TRUE:FALSE;
    774         break;
    775       case 4:
    776         if(curlx_strtoofft(ptr, NULL, 10, &co->expires))
    777           badcookie = TRUE;
    778         break;
    779       case 5:
    780         co->name = strdup(ptr);
    781         if(!co->name)
    782           badcookie = TRUE;
    783         break;
    784       case 6:
    785         co->value = strdup(ptr);
    786         if(!co->value)
    787           badcookie = TRUE;
    788         break;
    789       }
    790     }
    791     if(6 == fields) {
    792       /* we got a cookie with blank contents, fix it */
    793       co->value = strdup("");
    794       if(!co->value)
    795         badcookie = TRUE;
    796       else
    797         fields++;
    798     }
    799 
    800     if(!badcookie && (7 != fields))
    801       /* we did not find the sufficient number of fields */
    802       badcookie = TRUE;
    803 
    804     if(badcookie) {
    805       freecookie(co);
    806       return NULL;
    807     }
    808 
    809   }
    810 
    811   if(!c->running &&    /* read from a file */
    812      c->newsession &&  /* clean session cookies */
    813      !co->expires) {   /* this is a session cookie since it doesn't expire! */
    814     freecookie(co);
    815     return NULL;
    816   }
    817 
    818   co->livecookie = c->running;
    819 
    820   /* now, we have parsed the incoming line, we must now check if this
    821      superceeds an already existing cookie, which it may if the previous have
    822      the same domain and path as this */
    823 
    824   /* at first, remove expired cookies */
    825   remove_expired(c);
    826 
    827 #ifdef USE_LIBPSL
    828   /* Check if the domain is a Public Suffix and if yes, ignore the cookie.
    829      This needs a libpsl compiled with builtin data. */
    830   if(domain && co->domain && !isip(co->domain)) {
    831     psl = psl_builtin();
    832     if(psl && !psl_is_cookie_domain_acceptable(psl, domain, co->domain)) {
    833       infof(data,
    834             "cookie '%s' dropped, domain '%s' must not set cookies for '%s'\n",
    835             co->name, domain, co->domain);
    836       freecookie(co);
    837       return NULL;
    838     }
    839   }
    840 #endif
    841 
    842   clist = c->cookies;
    843   replace_old = FALSE;
    844   while(clist) {
    845     if(strcasecompare(clist->name, co->name)) {
    846       /* the names are identical */
    847 
    848       if(clist->domain && co->domain) {
    849         if(strcasecompare(clist->domain, co->domain) &&
    850           (clist->tailmatch == co->tailmatch))
    851           /* The domains are identical */
    852           replace_old = TRUE;
    853       }
    854       else if(!clist->domain && !co->domain)
    855         replace_old = TRUE;
    856 
    857       if(replace_old) {
    858         /* the domains were identical */
    859 
    860         if(clist->spath && co->spath) {
    861           if(strcasecompare(clist->spath, co->spath)) {
    862             replace_old = TRUE;
    863           }
    864           else
    865             replace_old = FALSE;
    866         }
    867         else if(!clist->spath && !co->spath)
    868           replace_old = TRUE;
    869         else
    870           replace_old = FALSE;
    871 
    872       }
    873 
    874       if(replace_old && !co->livecookie && clist->livecookie) {
    875         /* Both cookies matched fine, except that the already present
    876            cookie is "live", which means it was set from a header, while
    877            the new one isn't "live" and thus only read from a file. We let
    878            live cookies stay alive */
    879 
    880         /* Free the newcomer and get out of here! */
    881         freecookie(co);
    882         return NULL;
    883       }
    884 
    885       if(replace_old) {
    886         co->next = clist->next; /* get the next-pointer first */
    887 
    888         /* then free all the old pointers */
    889         free(clist->name);
    890         free(clist->value);
    891         free(clist->domain);
    892         free(clist->path);
    893         free(clist->spath);
    894         free(clist->expirestr);
    895         free(clist->version);
    896         free(clist->maxage);
    897 
    898         *clist = *co;  /* then store all the new data */
    899 
    900         free(co);   /* free the newly alloced memory */
    901         co = clist; /* point to the previous struct instead */
    902 
    903         /* We have replaced a cookie, now skip the rest of the list but
    904            make sure the 'lastc' pointer is properly set */
    905         do {
    906           lastc = clist;
    907           clist = clist->next;
    908         } while(clist);
    909         break;
    910       }
    911     }
    912     lastc = clist;
    913     clist = clist->next;
    914   }
    915 
    916   if(c->running)
    917     /* Only show this when NOT reading the cookies from a file */
    918     infof(data, "%s cookie %s=\"%s\" for domain %s, path %s, "
    919           "expire %" CURL_FORMAT_CURL_OFF_T "\n",
    920           replace_old?"Replaced":"Added", co->name, co->value,
    921           co->domain, co->path, co->expires);
    922 
    923   if(!replace_old) {
    924     /* then make the last item point on this new one */
    925     if(lastc)
    926       lastc->next = co;
    927     else
    928       c->cookies = co;
    929     c->numcookies++; /* one more cookie in the jar */
    930   }
    931 
    932   return co;
    933 }
    934 
    935 /*
    936  * get_line() makes sure to only return complete whole lines that fit in 'len'
    937  * bytes and end with a newline.
    938  */
    939 static char *get_line(char *buf, int len, FILE *input)
    940 {
    941   bool partial = FALSE;
    942   while(1) {
    943     char *b = fgets(buf, len, input);
    944     if(b) {
    945       size_t rlen = strlen(b);
    946       if(rlen && (b[rlen-1] == '\n')) {
    947         if(partial) {
    948           partial = FALSE;
    949           continue;
    950         }
    951         return b;
    952       }
    953       /* read a partial, discard the next piece that ends with newline */
    954       partial = TRUE;
    955     }
    956     else
    957       break;
    958   }
    959   return NULL;
    960 }
    961 
    962 
    963 /*****************************************************************************
    964  *
    965  * Curl_cookie_init()
    966  *
    967  * Inits a cookie struct to read data from a local file. This is always
    968  * called before any cookies are set. File may be NULL.
    969  *
    970  * If 'newsession' is TRUE, discard all "session cookies" on read from file.
    971  *
    972  * Returns NULL on out of memory. Invalid cookies are ignored.
    973  ****************************************************************************/
    974 struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
    975                                     const char *file,
    976                                     struct CookieInfo *inc,
    977                                     bool newsession)
    978 {
    979   struct CookieInfo *c;
    980   FILE *fp = NULL;
    981   bool fromfile = TRUE;
    982   char *line = NULL;
    983 
    984   if(NULL == inc) {
    985     /* we didn't get a struct, create one */
    986     c = calloc(1, sizeof(struct CookieInfo));
    987     if(!c)
    988       return NULL; /* failed to get memory */
    989     c->filename = strdup(file?file:"none"); /* copy the name just in case */
    990     if(!c->filename)
    991       goto fail; /* failed to get memory */
    992   }
    993   else {
    994     /* we got an already existing one, use that */
    995     c = inc;
    996   }
    997   c->running = FALSE; /* this is not running, this is init */
    998 
    999   if(file && !strcmp(file, "-")) {
   1000     fp = stdin;
   1001     fromfile = FALSE;
   1002   }
   1003   else if(file && !*file) {
   1004     /* points to a "" string */
   1005     fp = NULL;
   1006   }
   1007   else
   1008     fp = file?fopen(file, FOPEN_READTEXT):NULL;
   1009 
   1010   c->newsession = newsession; /* new session? */
   1011 
   1012   if(fp) {
   1013     char *lineptr;
   1014     bool headerline;
   1015 
   1016     line = malloc(MAX_COOKIE_LINE);
   1017     if(!line)
   1018       goto fail;
   1019     while(get_line(line, MAX_COOKIE_LINE, fp)) {
   1020       if(checkprefix("Set-Cookie:", line)) {
   1021         /* This is a cookie line, get it! */
   1022         lineptr = &line[11];
   1023         headerline = TRUE;
   1024       }
   1025       else {
   1026         lineptr = line;
   1027         headerline = FALSE;
   1028       }
   1029       while(*lineptr && ISBLANK(*lineptr))
   1030         lineptr++;
   1031 
   1032       Curl_cookie_add(data, c, headerline, lineptr, NULL, NULL);
   1033     }
   1034     free(line); /* free the line buffer */
   1035 
   1036     if(fromfile)
   1037       fclose(fp);
   1038   }
   1039 
   1040   c->running = TRUE;          /* now, we're running */
   1041 
   1042   return c;
   1043 
   1044 fail:
   1045   free(line);
   1046   if(!inc)
   1047     /* Only clean up if we allocated it here, as the original could still be in
   1048      * use by a share handle */
   1049     Curl_cookie_cleanup(c);
   1050   if(fromfile && fp)
   1051     fclose(fp);
   1052   return NULL; /* out of memory */
   1053 }
   1054 
   1055 /* sort this so that the longest path gets before the shorter path */
   1056 static int cookie_sort(const void *p1, const void *p2)
   1057 {
   1058   struct Cookie *c1 = *(struct Cookie **)p1;
   1059   struct Cookie *c2 = *(struct Cookie **)p2;
   1060   size_t l1, l2;
   1061 
   1062   /* 1 - compare cookie path lengths */
   1063   l1 = c1->path ? strlen(c1->path) : 0;
   1064   l2 = c2->path ? strlen(c2->path) : 0;
   1065 
   1066   if(l1 != l2)
   1067     return (l2 > l1) ? 1 : -1 ; /* avoid size_t <=> int conversions */
   1068 
   1069   /* 2 - compare cookie domain lengths */
   1070   l1 = c1->domain ? strlen(c1->domain) : 0;
   1071   l2 = c2->domain ? strlen(c2->domain) : 0;
   1072 
   1073   if(l1 != l2)
   1074     return (l2 > l1) ? 1 : -1 ;  /* avoid size_t <=> int conversions */
   1075 
   1076   /* 3 - compare cookie names */
   1077   if(c1->name && c2->name)
   1078     return strcmp(c1->name, c2->name);
   1079 
   1080   /* sorry, can't be more deterministic */
   1081   return 0;
   1082 }
   1083 
   1084 #define CLONE(field)                     \
   1085   do {                                   \
   1086     if(src->field) {                     \
   1087       d->field = strdup(src->field);     \
   1088       if(!d->field)                      \
   1089         goto fail;                       \
   1090     }                                    \
   1091   } while(0)
   1092 
   1093 static struct Cookie *dup_cookie(struct Cookie *src)
   1094 {
   1095   struct Cookie *d = calloc(sizeof(struct Cookie), 1);
   1096   if(d) {
   1097     CLONE(expirestr);
   1098     CLONE(domain);
   1099     CLONE(path);
   1100     CLONE(spath);
   1101     CLONE(name);
   1102     CLONE(value);
   1103     CLONE(maxage);
   1104     CLONE(version);
   1105     d->expires = src->expires;
   1106     d->tailmatch = src->tailmatch;
   1107     d->secure = src->secure;
   1108     d->livecookie = src->livecookie;
   1109     d->httponly = src->httponly;
   1110   }
   1111   return d;
   1112 
   1113   fail:
   1114   freecookie(d);
   1115   return NULL;
   1116 }
   1117 
   1118 /*****************************************************************************
   1119  *
   1120  * Curl_cookie_getlist()
   1121  *
   1122  * For a given host and path, return a linked list of cookies that the
   1123  * client should send to the server if used now. The secure boolean informs
   1124  * the cookie if a secure connection is achieved or not.
   1125  *
   1126  * It shall only return cookies that haven't expired.
   1127  *
   1128  ****************************************************************************/
   1129 
   1130 struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
   1131                                    const char *host, const char *path,
   1132                                    bool secure)
   1133 {
   1134   struct Cookie *newco;
   1135   struct Cookie *co;
   1136   time_t now = time(NULL);
   1137   struct Cookie *mainco = NULL;
   1138   size_t matches = 0;
   1139   bool is_ip;
   1140 
   1141   if(!c || !c->cookies)
   1142     return NULL; /* no cookie struct or no cookies in the struct */
   1143 
   1144   /* at first, remove expired cookies */
   1145   remove_expired(c);
   1146 
   1147   /* check if host is an IP(v4|v6) address */
   1148   is_ip = isip(host);
   1149 
   1150   co = c->cookies;
   1151 
   1152   while(co) {
   1153     /* only process this cookie if it is not expired or had no expire
   1154        date AND that if the cookie requires we're secure we must only
   1155        continue if we are! */
   1156     if((!co->expires || (co->expires > now)) &&
   1157        (co->secure?secure:TRUE)) {
   1158 
   1159       /* now check if the domain is correct */
   1160       if(!co->domain ||
   1161          (co->tailmatch && !is_ip && tailmatch(co->domain, host)) ||
   1162          ((!co->tailmatch || is_ip) && strcasecompare(host, co->domain)) ) {
   1163         /* the right part of the host matches the domain stuff in the
   1164            cookie data */
   1165 
   1166         /* now check the left part of the path with the cookies path
   1167            requirement */
   1168         if(!co->spath || pathmatch(co->spath, path) ) {
   1169 
   1170           /* and now, we know this is a match and we should create an
   1171              entry for the return-linked-list */
   1172 
   1173           newco = dup_cookie(co);
   1174           if(newco) {
   1175             /* then modify our next */
   1176             newco->next = mainco;
   1177 
   1178             /* point the main to us */
   1179             mainco = newco;
   1180 
   1181             matches++;
   1182           }
   1183           else {
   1184             fail:
   1185             /* failure, clear up the allocated chain and return NULL */
   1186             Curl_cookie_freelist(mainco);
   1187             return NULL;
   1188           }
   1189         }
   1190       }
   1191     }
   1192     co = co->next;
   1193   }
   1194 
   1195   if(matches) {
   1196     /* Now we need to make sure that if there is a name appearing more than
   1197        once, the longest specified path version comes first. To make this
   1198        the swiftest way, we just sort them all based on path length. */
   1199     struct Cookie **array;
   1200     size_t i;
   1201 
   1202     /* alloc an array and store all cookie pointers */
   1203     array = malloc(sizeof(struct Cookie *) * matches);
   1204     if(!array)
   1205       goto fail;
   1206 
   1207     co = mainco;
   1208 
   1209     for(i = 0; co; co = co->next)
   1210       array[i++] = co;
   1211 
   1212     /* now sort the cookie pointers in path length order */
   1213     qsort(array, matches, sizeof(struct Cookie *), cookie_sort);
   1214 
   1215     /* remake the linked list order according to the new order */
   1216 
   1217     mainco = array[0]; /* start here */
   1218     for(i = 0; i<matches-1; i++)
   1219       array[i]->next = array[i + 1];
   1220     array[matches-1]->next = NULL; /* terminate the list */
   1221 
   1222     free(array); /* remove the temporary data again */
   1223   }
   1224 
   1225   return mainco; /* return the new list */
   1226 }
   1227 
   1228 /*****************************************************************************
   1229  *
   1230  * Curl_cookie_clearall()
   1231  *
   1232  * Clear all existing cookies and reset the counter.
   1233  *
   1234  ****************************************************************************/
   1235 void Curl_cookie_clearall(struct CookieInfo *cookies)
   1236 {
   1237   if(cookies) {
   1238     Curl_cookie_freelist(cookies->cookies);
   1239     cookies->cookies = NULL;
   1240     cookies->numcookies = 0;
   1241   }
   1242 }
   1243 
   1244 /*****************************************************************************
   1245  *
   1246  * Curl_cookie_freelist()
   1247  *
   1248  * Free a list of cookies previously returned by Curl_cookie_getlist();
   1249  *
   1250  ****************************************************************************/
   1251 
   1252 void Curl_cookie_freelist(struct Cookie *co)
   1253 {
   1254   struct Cookie *next;
   1255   while(co) {
   1256     next = co->next;
   1257     freecookie(co);
   1258     co = next;
   1259   }
   1260 }
   1261 
   1262 
   1263 /*****************************************************************************
   1264  *
   1265  * Curl_cookie_clearsess()
   1266  *
   1267  * Free all session cookies in the cookies list.
   1268  *
   1269  ****************************************************************************/
   1270 void Curl_cookie_clearsess(struct CookieInfo *cookies)
   1271 {
   1272   struct Cookie *first, *curr, *next, *prev = NULL;
   1273 
   1274   if(!cookies || !cookies->cookies)
   1275     return;
   1276 
   1277   first = curr = prev = cookies->cookies;
   1278 
   1279   for(; curr; curr = next) {
   1280     next = curr->next;
   1281     if(!curr->expires) {
   1282       if(first == curr)
   1283         first = next;
   1284 
   1285       if(prev == curr)
   1286         prev = next;
   1287       else
   1288         prev->next = next;
   1289 
   1290       freecookie(curr);
   1291       cookies->numcookies--;
   1292     }
   1293     else
   1294       prev = curr;
   1295   }
   1296 
   1297   cookies->cookies = first;
   1298 }
   1299 
   1300 
   1301 /*****************************************************************************
   1302  *
   1303  * Curl_cookie_cleanup()
   1304  *
   1305  * Free a "cookie object" previous created with Curl_cookie_init().
   1306  *
   1307  ****************************************************************************/
   1308 void Curl_cookie_cleanup(struct CookieInfo *c)
   1309 {
   1310   if(c) {
   1311     free(c->filename);
   1312     Curl_cookie_freelist(c->cookies);
   1313     free(c); /* free the base struct as well */
   1314   }
   1315 }
   1316 
   1317 /* get_netscape_format()
   1318  *
   1319  * Formats a string for Netscape output file, w/o a newline at the end.
   1320  *
   1321  * Function returns a char * to a formatted line. Has to be free()d
   1322 */
   1323 static char *get_netscape_format(const struct Cookie *co)
   1324 {
   1325   return aprintf(
   1326     "%s"     /* httponly preamble */
   1327     "%s%s\t" /* domain */
   1328     "%s\t"   /* tailmatch */
   1329     "%s\t"   /* path */
   1330     "%s\t"   /* secure */
   1331     "%" CURL_FORMAT_CURL_OFF_T "\t"   /* expires */
   1332     "%s\t"   /* name */
   1333     "%s",    /* value */
   1334     co->httponly?"#HttpOnly_":"",
   1335     /* Make sure all domains are prefixed with a dot if they allow
   1336        tailmatching. This is Mozilla-style. */
   1337     (co->tailmatch && co->domain && co->domain[0] != '.')? ".":"",
   1338     co->domain?co->domain:"unknown",
   1339     co->tailmatch?"TRUE":"FALSE",
   1340     co->path?co->path:"/",
   1341     co->secure?"TRUE":"FALSE",
   1342     co->expires,
   1343     co->name,
   1344     co->value?co->value:"");
   1345 }
   1346 
   1347 /*
   1348  * cookie_output()
   1349  *
   1350  * Writes all internally known cookies to the specified file. Specify
   1351  * "-" as file name to write to stdout.
   1352  *
   1353  * The function returns non-zero on write failure.
   1354  */
   1355 static int cookie_output(struct CookieInfo *c, const char *dumphere)
   1356 {
   1357   struct Cookie *co;
   1358   FILE *out;
   1359   bool use_stdout = FALSE;
   1360   char *format_ptr;
   1361 
   1362   if((NULL == c) || (0 == c->numcookies))
   1363     /* If there are no known cookies, we don't write or even create any
   1364        destination file */
   1365     return 0;
   1366 
   1367   /* at first, remove expired cookies */
   1368   remove_expired(c);
   1369 
   1370   if(!strcmp("-", dumphere)) {
   1371     /* use stdout */
   1372     out = stdout;
   1373     use_stdout = TRUE;
   1374   }
   1375   else {
   1376     out = fopen(dumphere, FOPEN_WRITETEXT);
   1377     if(!out)
   1378       return 1; /* failure */
   1379   }
   1380 
   1381   fputs("# Netscape HTTP Cookie File\n"
   1382         "# https://curl.haxx.se/docs/http-cookies.html\n"
   1383         "# This file was generated by libcurl! Edit at your own risk.\n\n",
   1384         out);
   1385 
   1386   for(co = c->cookies; co; co = co->next) {
   1387     if(!co->domain)
   1388       continue;
   1389     format_ptr = get_netscape_format(co);
   1390     if(format_ptr == NULL) {
   1391       fprintf(out, "#\n# Fatal libcurl error\n");
   1392       if(!use_stdout)
   1393         fclose(out);
   1394       return 1;
   1395     }
   1396     fprintf(out, "%s\n", format_ptr);
   1397     free(format_ptr);
   1398   }
   1399 
   1400   if(!use_stdout)
   1401     fclose(out);
   1402 
   1403   return 0;
   1404 }
   1405 
   1406 static struct curl_slist *cookie_list(struct Curl_easy *data)
   1407 {
   1408   struct curl_slist *list = NULL;
   1409   struct curl_slist *beg;
   1410   struct Cookie *c;
   1411   char *line;
   1412 
   1413   if((data->cookies == NULL) ||
   1414       (data->cookies->numcookies == 0))
   1415     return NULL;
   1416 
   1417   for(c = data->cookies->cookies; c; c = c->next) {
   1418     if(!c->domain)
   1419       continue;
   1420     line = get_netscape_format(c);
   1421     if(!line) {
   1422       curl_slist_free_all(list);
   1423       return NULL;
   1424     }
   1425     beg = Curl_slist_append_nodup(list, line);
   1426     if(!beg) {
   1427       free(line);
   1428       curl_slist_free_all(list);
   1429       return NULL;
   1430     }
   1431     list = beg;
   1432   }
   1433 
   1434   return list;
   1435 }
   1436 
   1437 struct curl_slist *Curl_cookie_list(struct Curl_easy *data)
   1438 {
   1439   struct curl_slist *list;
   1440   Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
   1441   list = cookie_list(data);
   1442   Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
   1443   return list;
   1444 }
   1445 
   1446 void Curl_flush_cookies(struct Curl_easy *data, int cleanup)
   1447 {
   1448   if(data->set.str[STRING_COOKIEJAR]) {
   1449     if(data->change.cookielist) {
   1450       /* If there is a list of cookie files to read, do it first so that
   1451          we have all the told files read before we write the new jar.
   1452          Curl_cookie_loadfiles() LOCKS and UNLOCKS the share itself! */
   1453       Curl_cookie_loadfiles(data);
   1454     }
   1455 
   1456     Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
   1457 
   1458     /* if we have a destination file for all the cookies to get dumped to */
   1459     if(cookie_output(data->cookies, data->set.str[STRING_COOKIEJAR]))
   1460       infof(data, "WARNING: failed to save cookies in %s\n",
   1461             data->set.str[STRING_COOKIEJAR]);
   1462   }
   1463   else {
   1464     if(cleanup && data->change.cookielist) {
   1465       /* since nothing is written, we can just free the list of cookie file
   1466          names */
   1467       curl_slist_free_all(data->change.cookielist); /* clean up list */
   1468       data->change.cookielist = NULL;
   1469     }
   1470     Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
   1471   }
   1472 
   1473   if(cleanup && (!data->share || (data->cookies != data->share->cookies))) {
   1474     Curl_cookie_cleanup(data->cookies);
   1475   }
   1476   Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
   1477 }
   1478 
   1479 #endif /* CURL_DISABLE_HTTP || CURL_DISABLE_COOKIES */
   1480