From 82c583dcf009f038a9ceccc695f942f24015f9ab Mon Sep 17 00:00:00 2001 From: Daniel Gustafsson Date: Thu, 25 Feb 2021 18:12:28 +0100 Subject: [PATCH] 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 --- docs/cmdline-opts/cookie.d | 2 +- src/tool_cfgable.c | 4 ++-- src/tool_cfgable.h | 4 ++-- src/tool_getparam.c | 8 ++++++-- src/tool_operate.c | 33 +++++++++++++++++++++++++++++---- tests/data/test329 | 8 ++++++-- tests/data/test6 | 4 ++-- 7 files changed, 48 insertions(+), 15 deletions(-) diff --git a/docs/cmdline-opts/cookie.d b/docs/cmdline-opts/cookie.d index 5d2c9d783..d5e63e427 100644 --- a/docs/cmdline-opts/cookie.d +++ b/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 diff --git a/src/tool_cfgable.c b/src/tool_cfgable.c index ea186a7c3..c3f7cecb1 100644 --- a/src/tool_cfgable.c +++ b/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); diff --git a/src/tool_cfgable.h b/src/tool_cfgable.h index bd84315f5..95c66d081 100644 --- a/src/tool_cfgable.h +++ b/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? */ diff --git a/src/tool_getparam.c b/src/tool_getparam.c index 5b155cf00..f1393c373 100644 --- a/src/tool_getparam.c +++ b/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': diff --git a/src/tool_operate.c b/src/tool_operate.c index 2605a4cdf..e2b287269 100644 --- a/src/tool_operate.c +++ b/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) diff --git a/tests/data/test329 b/tests/data/test329 index 81b8383c1..67aac4baa 100644 --- a/tests/data/test329 +++ b/tests/data/test329 @@ -33,6 +33,9 @@ moo .host.foo.com TRUE /we/want/ FALSE 2147483647 test no + +.host.foo.com TRUE /we/want/ FALSE 2147483647 tester yes + http @@ -46,7 +49,7 @@ HTTP cookie with Max-Age=0 TZ=GMT -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 @@ -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 diff --git a/tests/data/test6 b/tests/data/test6 index efd15a901..bbd67cbf8 100644 --- a/tests/data/test6 +++ b/tests/data/test6 @@ -29,7 +29,7 @@ http HTTP with simple cookie send -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 @@ -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