From a676c18502d5ec3128db11accf04d6de3f9be949 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Wed, 17 Aug 2005 08:55:43 +0000
Subject: - Jeff Pohlmeyer found out that if you ask libcurl to load a
 cookiefile (with   CURLOPT_COOKIEFILE), add a cookie (with
 CURLOPT_COOKIELIST), tell it to   write the result to a given cookie jar and
 then never actually call   curl_easy_perform() - the given file(s) to read
 was never read but the   output file was written and thus it caused a "funny"
 result.

- While doing some tests for the bug above, I noticed that Firefox generates
  large numbers (for the expire time) in the cookies.txt file and libcurl
  didn't treat them properly. Now it does.
---
 CHANGES        | 11 +++++++
 RELEASE-NOTES  |  2 +-
 lib/cookie.c   | 29 +++++++++++++++++--
 lib/cookie.h   |  4 ++-
 lib/transfer.c | 22 ++------------
 lib/url.c      | 90 ++++++++++++++++++++++++++++++++--------------------------
 6 files changed, 93 insertions(+), 65 deletions(-)

diff --git a/CHANGES b/CHANGES
index 352768120..cd1a3448e 100644
--- a/CHANGES
+++ b/CHANGES
@@ -7,6 +7,17 @@
                                   Changelog
 
 
+Daniel (17 August 2005)
+- Jeff Pohlmeyer found out that if you ask libcurl to load a cookiefile (with
+  CURLOPT_COOKIEFILE), add a cookie (with CURLOPT_COOKIELIST), tell it to
+  write the result to a given cookie jar and then never actually call
+  curl_easy_perform() - the given file(s) to read was never read but the
+  output file was written and thus it caused a "funny" result.
+
+- While doing some tests for the bug above, I noticed that Firefox generates
+  large numbers (for the expire time) in the cookies.txt file and libcurl
+  didn't treat them properly. Now it does.
+
 Daniel (15 August 2005)
 - Added more verbose "warning" messages to the curl client for cases where it
   fails to open/read files etc to help users diagnose why it doesn't do what
diff --git a/RELEASE-NOTES b/RELEASE-NOTES
index 7f38c8e8d..15d531107 100644
--- a/RELEASE-NOTES
+++ b/RELEASE-NOTES
@@ -59,6 +59,6 @@ advice from friends like these:
  John McGowan, Georg Wicherski, Andres Garcia, Eric Cooper, Todd Kulesza,
  Tupone Alfredo, Gisle Vanem, David Shaw, Andrew Bushnell, Dan Fandrich,
  Adrian Schuur, Diego Casorran, Peteris Krumins, Jon Grubbs, Christopher
- R. Palmer, Mario Schroeder, Richard Clayton, James Bursa
+ R. Palmer, Mario Schroeder, Richard Clayton, James Bursa, Jeff Pohlmeyer
 
         Thanks! (and sorry if I forgot to mention someone)
diff --git a/lib/cookie.c b/lib/cookie.c
index 0328f20d8..0f6d681db 100644
--- a/lib/cookie.c
+++ b/lib/cookie.c
@@ -94,6 +94,8 @@ Example set of cookies:
 #include "strtok.h"
 #include "sendf.h"
 #include "memory.h"
+#include "share.h"
+#include "strtoofft.h"
 
 /* The last #include file should be: */
 #ifdef CURLDEBUG
@@ -133,6 +135,27 @@ static bool tailmatch(const char *little, const char *bigone)
   return (bool)strequal(little, bigone+biglen-littlelen);
 }
 
+/*
+ * Load cookies from all given cookie files (CURLOPT_COOKIEFILE).
+ */
+void Curl_cookie_loadfiles(struct SessionHandle *data)
+{
+  struct curl_slist *list = data->change.cookielist;
+  if(list) {
+    Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
+    while(list) {
+      data->cookies = Curl_cookie_init(data,
+                                       list->data,
+                                       data->cookies,
+                                       data->set.cookiesession);
+      list = list->next;
+    }
+    Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
+    curl_slist_free_all(data->change.cookielist); /* clean up list */
+    data->change.cookielist = NULL; /* don't do this again! */
+  }
+}
+
 /****************************************************************************
  *
  * Curl_cookie_add()
@@ -473,7 +496,7 @@ Curl_cookie_add(struct SessionHandle *data,
         co->secure = (bool)strequal(ptr, "TRUE");
         break;
       case 4:
-        co->expires = atoi(ptr);
+        co->expires = curlx_strtoofft(ptr, NULL, 10);
         break;
       case 5:
         co->name = strdup(ptr);
@@ -832,7 +855,7 @@ static char *get_netscape_format(const struct Cookie *co)
      "%s\t"   /* tailmatch */
      "%s\t"   /* path */
      "%s\t"   /* secure */
-     "%u\t"   /* expires */
+     "%" FORMAT_OFF_T "\t"   /* expires */
      "%s\t"   /* name */
      "%s",    /* value */
      /* Make sure all domains are prefixed with a dot if they allow
@@ -842,7 +865,7 @@ static char *get_netscape_format(const struct Cookie *co)
      co->tailmatch?"TRUE":"FALSE",
      co->path?co->path:"/",
      co->secure?"TRUE":"FALSE",
-     (unsigned int)co->expires,
+     co->expires,
      co->name,
      co->value?co->value:"");
 }
diff --git a/lib/cookie.h b/lib/cookie.h
index aed9f73f7..f5fdb6784 100644
--- a/lib/cookie.h
+++ b/lib/cookie.h
@@ -38,7 +38,7 @@ struct Cookie {
   char *value;       /* name = <this> */
   char *path;         /* path = <this> */
   char *domain;      /* domain = <this> */
-  long expires;    /* expires = <this> */
+  curl_off_t expires;  /* expires = <this> */
   char *expirestr;   /* the plain text version */
   bool tailmatch;    /* weather we do tail-matchning of the domain name */
 
@@ -94,8 +94,10 @@ int Curl_cookie_output(struct CookieInfo *, char *);
 
 #if defined(CURL_DISABLE_HTTP) || defined(CURL_DISABLE_COOKIES)
 #define Curl_cookie_list(x) NULL
+#define Curl_cookie_loadfiles(x)
 #else
 struct curl_slist *Curl_cookie_list(struct SessionHandle *data);
+void Curl_cookie_loadfiles(struct SessionHandle *data);
 #endif
 
 #endif
diff --git a/lib/transfer.c b/lib/transfer.c
index 544ac8560..8f885f5d9 100644
--- a/lib/transfer.c
+++ b/lib/transfer.c
@@ -1641,25 +1641,9 @@ CURLcode Curl_pretransfer(struct SessionHandle *data)
   data->state.authhost.want = data->set.httpauth;
   data->state.authproxy.want = data->set.proxyauth;
 
-#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
-  /* If there was a list of cookie files to read and we haven't done it before,
-     do it now! */
-  if(data->change.cookielist) {
-    struct curl_slist *list = data->change.cookielist;
-    Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
-    while(list) {
-      data->cookies = Curl_cookie_init(data,
-                                       list->data,
-                                       data->cookies,
-                                       data->set.cookiesession);
-      list = list->next;
-    }
-    Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
-    curl_slist_free_all(data->change.cookielist); /* clean up list */
-    data->change.cookielist = NULL; /* don't do this again! */
-  }
-#endif   /* CURL_DISABLE_HTTP */
-
+  /* If there is a list of cookie files to read, do it now! */
+  if(data->change.cookielist)
+    Curl_cookie_loadfiles(data);
 
  /* Allow data->set.use_port to set which port to use. This needs to be
   * disabled for example when we follow Location: headers to URLs using
diff --git a/lib/url.c b/lib/url.c
index 3698affd1..f245a1986 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -227,16 +227,24 @@ CURLcode Curl_close(struct SessionHandle *data)
   Curl_safefree(data->state.headerbuff);
 
 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
-  if(data->change.cookielist) /* clean up list if any */
-    curl_slist_free_all(data->change.cookielist);
-
   Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
   if(data->set.cookiejar) {
+    if(data->change.cookielist)
+      /* If there is a list of cookie files to read, do it first so that
+         we have all the told files read before we write the new jar */
+      Curl_cookie_loadfiles(data);
+
     /* we have a "destination" for all the cookies to get dumped to */
     if(Curl_cookie_output(data->cookies, data->set.cookiejar))
       infof(data, "WARNING: failed to save cookies in %s\n",
             data->set.cookiejar);
   }
+  else {
+    if(data->change.cookielist)
+      /* since nothing is written, we can just free the list of cookie file
+         names */
+      curl_slist_free_all(data->change.cookielist); /* clean up list */
+  }
 
   if( !data->share || (data->cookies != data->share->cookies) ) {
     Curl_cookie_cleanup(data->cookies);
@@ -2951,44 +2959,44 @@ static CURLcode CreateConnection(struct SessionHandle *data,
       char proxypasswd[MAX_CURL_PASSWORD_LENGTH];
 
       if(2 == sscanf(proxyptr,
-		     "%" MAX_CURL_USER_LENGTH_TXT"[^:]:"
-		     "%" MAX_CURL_PASSWORD_LENGTH_TXT "[^@]",
-		     proxyuser, proxypasswd)) {
-	CURLcode res = CURLE_OK;
-
-	/* found user and password, rip them out.  note that we are
-	   unescaping them, as there is otherwise no way to have a
-	   username or password with reserved characters like ':' in
-	   them. */
-	Curl_safefree(conn->proxyuser);
-	conn->proxyuser = curl_unescape(proxyuser,0);
-
-	if(!conn->proxyuser)
-	  res = CURLE_OUT_OF_MEMORY;
-	else {
-	  Curl_safefree(conn->proxypasswd);
-	  conn->proxypasswd = curl_unescape(proxypasswd,0);
-
-	  if(!conn->proxypasswd)
-	    res = CURLE_OUT_OF_MEMORY;
-	}
-
-	if(CURLE_OK == res) {
-	  conn->bits.proxy_user_passwd = TRUE; /* enable it */
-	  atsign = strdup(atsign+1); /* the right side of the @-letter */
-
-	  if(atsign) {
-	    free(proxydup); /* free the former proxy string */
-	    proxydup = proxyptr = atsign; /* now use this instead */
-	  }
-	  else
-	    res = CURLE_OUT_OF_MEMORY;
-	}
-
-	if(res) {
-	  free(proxydup); /* free the allocated proxy string */
-	  return res;
-	}
+                     "%" MAX_CURL_USER_LENGTH_TXT"[^:]:"
+                     "%" MAX_CURL_PASSWORD_LENGTH_TXT "[^@]",
+                     proxyuser, proxypasswd)) {
+        CURLcode res = CURLE_OK;
+
+        /* found user and password, rip them out.  note that we are
+           unescaping them, as there is otherwise no way to have a
+           username or password with reserved characters like ':' in
+           them. */
+        Curl_safefree(conn->proxyuser);
+        conn->proxyuser = curl_unescape(proxyuser,0);
+
+        if(!conn->proxyuser)
+          res = CURLE_OUT_OF_MEMORY;
+        else {
+          Curl_safefree(conn->proxypasswd);
+          conn->proxypasswd = curl_unescape(proxypasswd,0);
+
+          if(!conn->proxypasswd)
+            res = CURLE_OUT_OF_MEMORY;
+        }
+
+        if(CURLE_OK == res) {
+          conn->bits.proxy_user_passwd = TRUE; /* enable it */
+          atsign = strdup(atsign+1); /* the right side of the @-letter */
+
+          if(atsign) {
+            free(proxydup); /* free the former proxy string */
+            proxydup = proxyptr = atsign; /* now use this instead */
+          }
+          else
+            res = CURLE_OUT_OF_MEMORY;
+        }
+
+        if(res) {
+          free(proxydup); /* free the allocated proxy string */
+          return res;
+        }
       }
     }
 
-- 
cgit v1.2.3