Browse Source

cookies: Support multiple -b parameters

Previously only a single -b cookie parameter was supported with the last
one winning.  This adds support for supplying multiple -b params to have
them serialized semicolon separated.  Both cookiefiles and cookies can be
entered multiple times.

Closes #6649
Reviewed-by: Daniel Stenberg <daniel@haxx.se>
Daniel Gustafsson 3 years ago
parent
commit
82c583dcf0
7 changed files with 48 additions and 15 deletions
  1. 1 1
      docs/cmdline-opts/cookie.d
  2. 2 2
      src/tool_cfgable.c
  3. 2 2
      src/tool_cfgable.h
  4. 6 2
      src/tool_getparam.c
  5. 29 4
      src/tool_operate.c
  6. 6 2
      tests/data/test329
  7. 2 2
      tests/data/test6

+ 1 - 1
docs/cmdline-opts/cookie.d

@@ -31,7 +31,7 @@ name then both will be sent on a future transfer to that server, likely not
 what you intended.  To address these issues set a domain in Set-Cookie (doing
 that will include sub domains) or use the Netscape format.
 
-If this option is used several times, the last one will be used.
+This option can be used multiple times.
 
 Users very often want to both read cookies from a file and write updated
 cookies back to a file, so using both --cookie and --cookie-jar in the same

+ 2 - 2
src/tool_cfgable.c

@@ -56,9 +56,9 @@ static void free_config_fields(struct OperationConfig *config)
   Curl_safefree(config->useragent);
   Curl_safefree(config->altsvc);
   Curl_safefree(config->hsts);
-  Curl_safefree(config->cookie);
+  curl_slist_free_all(config->cookies);
   Curl_safefree(config->cookiejar);
-  Curl_safefree(config->cookiefile);
+  curl_slist_free_all(config->cookiefiles);
 
   Curl_safefree(config->postfields);
   Curl_safefree(config->referer);

+ 2 - 2
src/tool_cfgable.h

@@ -54,9 +54,9 @@ struct OperationConfig {
   char *random_file;
   char *egd_file;
   char *useragent;
-  char *cookie;             /* single line with specified cookies */
+  struct curl_slist *cookies;  /* cookies to serialize into a single line */
   char *cookiejar;          /* write to this file */
-  char *cookiefile;         /* read from this file */
+  struct curl_slist *cookiefiles;  /* file(s) to load cookies from */
   char *altsvc;             /* alt-svc cache file name */
   char *hsts;               /* HSTS cache file name */
   bool cookiesession;       /* new session? */

+ 6 - 2
src/tool_getparam.c

@@ -1320,11 +1320,15 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
         }
         else if(strchr(nextarg, '=')) {
           /* A cookie string must have a =-letter */
-          GetStr(&config->cookie, nextarg);
+          err = add2list(&config->cookies, nextarg);
+          if(err)
+            return err;
           break;
         }
         /* We have a cookie file to read from! */
-        GetStr(&config->cookiefile, nextarg);
+        err = add2list(&config->cookiefiles, nextarg);
+        if(err)
+          return err;
       }
       break;
     case 'B':

+ 29 - 4
src/tool_operate.c

@@ -82,6 +82,7 @@
 #include "tool_help.h"
 #include "tool_hugehelp.h"
 #include "tool_progress.h"
+#include "dynbuf.h"
 
 #include "memdebug.h" /* keep this as LAST include */
 
@@ -1765,11 +1766,35 @@ static CURLcode single_transfer(struct GlobalConfig *global,
         my_setopt_slist(curl, CURLOPT_POSTQUOTE, config->postquote);
         my_setopt_slist(curl, CURLOPT_PREQUOTE, config->prequote);
 
-        if(config->cookie)
-          my_setopt_str(curl, CURLOPT_COOKIE, config->cookie);
+        if(config->cookies) {
+          struct curlx_dynbuf cookies;
+          struct curl_slist *cl;
+          CURLcode ret;
 
-        if(config->cookiefile)
-          my_setopt_str(curl, CURLOPT_COOKIEFILE, config->cookiefile);
+          /* The maximum size needs to match MAX_NAME in cookie.h */
+          curlx_dyn_init(&cookies, 4096);
+          for(cl = config->cookies; cl; cl = cl->next) {
+            if(cl == config->cookies)
+              ret = curlx_dyn_addf(&cookies, "%s", cl->data);
+            else
+              ret = curlx_dyn_addf(&cookies, ";%s", cl->data);
+
+            if(ret) {
+              result = CURLE_OUT_OF_MEMORY;
+              break;
+            }
+          }
+
+          my_setopt_str(curl, CURLOPT_COOKIE, curlx_dyn_ptr(&cookies));
+          curlx_dyn_free(&cookies);
+        }
+
+        if(config->cookiefiles) {
+          struct curl_slist *cfl;
+
+          for(cfl = config->cookiefiles; cfl; cfl = cfl->next)
+            my_setopt_str(curl, CURLOPT_COOKIEFILE, cfl->data);
+        }
 
         /* new in libcurl 7.9 */
         if(config->cookiejar)

+ 6 - 2
tests/data/test329

@@ -33,6 +33,9 @@ moo
 <file name="log/jar329.txt" mode="text">
 .host.foo.com	TRUE	/we/want/	FALSE	2147483647	test	no
 </file>
+<file name="log/jar329-2.txt" mode="text">
+.host.foo.com	TRUE	/we/want/	FALSE	2147483647	tester	yes
+</file>
 <server>
 http
 </server>
@@ -46,7 +49,7 @@ HTTP cookie with Max-Age=0
 TZ=GMT
 </setenv>
  <command>
-http://%HOSTIP:%HTTPPORT/we/want/329 -b log/jar329.txt -H "Host: host.foo.com" http://%HOSTIP:%HTTPPORT/we/want/3290002
+http://%HOSTIP:%HTTPPORT/we/want/329 -b log/jar329.txt -b log/jar329-2.txt -H "Host: host.foo.com" http://%HOSTIP:%HTTPPORT/we/want/3290002
 </command>
 </client>
 
@@ -57,12 +60,13 @@ GET /we/want/329 HTTP/1.1
 Host: host.foo.com
 User-Agent: curl/%VERSION
 Accept: */*
-Cookie: test=no
+Cookie: tester=yes; test=no
 
 GET /we/want/3290002 HTTP/1.1
 Host: host.foo.com
 User-Agent: curl/%VERSION
 Accept: */*
+Cookie: tester=yes
 
 </protocol>
 </verify>

+ 2 - 2
tests/data/test6

@@ -29,7 +29,7 @@ http
 HTTP with simple cookie send
  </name>
  <command>
-http://%HOSTIP:%HTTPPORT/we/want/that/page/6 -b "name=contents;name2=content2"
+http://%HOSTIP:%HTTPPORT/we/want/that/page/6 -b "name=contents;name2=content2" -b name3=content3
 </command>
 </client>
 
@@ -40,7 +40,7 @@ GET /we/want/that/page/6 HTTP/1.1
 Host: %HOSTIP:%HTTPPORT
 User-Agent: curl/%VERSION
 Accept: */*
-Cookie: name=contents;name2=content2
+Cookie: name=contents;name2=content2;name3=content3
 
 </protocol>
 </verify>