Hi,
The attached patch adds support for multiple headers of the same type by
introducing a new option --append-header.
References:
http://www.mail-archive.com/[EMAIL PROTECTED]/msg09021.html
https://savannah.gnu.org/bugs/?20521
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=366434
Regards,
Marton
# HG changeset patch
# User Marton Balint <[EMAIL PROTECTED]>
# Date 1227989647 -3600
# Node ID 7196e66f974acbfed6c5c9728a75749245afb5e9
# Parent dd1cd4ad2b27d3abc38e991e80f31a18517a8c80
Add support for multiple headers of the same type
The --header option overwrites any existing HTTP header
with the same type, this patch introduces the --append-header
option which simply appends the specified header to the headers.
It fixes the following bug reports:
https://savannah.gnu.org/bugs/?20521
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=366434
diff -r dd1cd4ad2b27 -r 7196e66f974a doc/ChangeLog
--- a/doc/ChangeLog Wed Nov 26 21:53:40 2008 -0800
+++ b/doc/ChangeLog Sat Nov 29 21:14:07 2008 +0100
@@ -1,3 +1,8 @@
+2008-11-29 Marton Balint <[EMAIL PROTECTED]>
+
+ * wget.texi (Download Options): Document new command line option
+ --append-header.
+
2008-11-15 Steven Schubiger <[EMAIL PROTECTED]>
* sample.wgetrc: Comment the waitretry "default" value,
diff -r dd1cd4ad2b27 -r 7196e66f974a doc/wget.texi
--- a/doc/wget.texi Wed Nov 26 21:53:40 2008 -0800
+++ b/doc/wget.texi Sat Nov 29 21:14:07 2008 +0100
@@ -1285,7 +1285,21 @@
@end example
In versions of Wget prior to 1.10 such use of @samp{--header} caused
-sending of duplicate headers.
+sending of duplicate headers. If you want to specify duplicate headers
+use the @samp{--append-header} option.
+
[EMAIL PROTECTED] header, add
[EMAIL PROTECTED] [EMAIL PROTECTED]
+Basically the same as option @samp{--header}, but you may specify the same
+header multiple times.
+
[EMAIL PROTECTED]
[EMAIL PROTECTED]
+wget --append-header "Pragma: no-cache" \
+ --append-header "Pragma: custom-directive" \
+ http://foo/service
[EMAIL PROTECTED] group
[EMAIL PROTECTED] example
@cindex redirect
@item [EMAIL PROTECTED]
diff -r dd1cd4ad2b27 -r 7196e66f974a src/ChangeLog
--- a/src/ChangeLog Wed Nov 26 21:53:40 2008 -0800
+++ b/src/ChangeLog Sat Nov 29 21:14:07 2008 +0100
@@ -1,3 +1,13 @@
+2008-11-29 Marton Balint <[EMAIL PROTECTED]>
+
+ * http.c (request_set_header, request_set_user_header): New arg
+ append_header to specify whether the header should be appended or
+ replaced. All callers changed.
+ (gethttp): append --append-header headers to the HTTP headers.
+
+ * init.c (cmd_spec_append_header), main.c options.h: add new option
+ --append-header.
+
2008-11-13 Micah Cowan <[EMAIL PROTECTED]>
* http.c (gethttp): Don't do anything when content-length >= our
diff -r dd1cd4ad2b27 -r 7196e66f974a src/http.c
--- a/src/http.c Wed Nov 26 21:53:40 2008 -0800
+++ b/src/http.c Sat Nov 29 21:14:07 2008 +0100
@@ -216,20 +216,20 @@
sources. For example:
// Don't free literal strings!
- request_set_header (req, "Pragma", "no-cache", rel_none);
+ request_set_header (req, "Pragma", "no-cache", rel_none, false);
// Don't free a global variable, we'll need it later.
- request_set_header (req, "Referer", opt.referer, rel_none);
+ request_set_header (req, "Referer", opt.referer, rel_none, false);
// Value freshly allocated, free it when done.
request_set_header (req, "Range",
aprintf ("bytes=%s-", number_to_static_string (hs->restval)),
- rel_value);
+ rel_value, false);
*/
static void
request_set_header (struct request *req, char *name, char *value,
- enum rp release_policy)
+ enum rp release_policy, bool append_header)
{
struct request_header *hdr;
int i;
@@ -243,17 +243,20 @@
return;
}
- for (i = 0; i < req->hcount; i++)
+ if (!append_header)
{
- hdr = &req->headers[i];
- if (0 == strcasecmp (name, hdr->name))
+ for (i = 0; i < req->hcount; i++)
{
- /* Replace existing header. */
- release_header (hdr);
- hdr->name = name;
- hdr->value = value;
- hdr->release_policy = release_policy;
- return;
+ hdr = &req->headers[i];
+ if (0 == strcasecmp (name, hdr->name))
+ {
+ /* Replace existing header. */
+ release_header (hdr);
+ hdr->name = name;
+ hdr->value = value;
+ hdr->release_policy = release_policy;
+ return;
+ }
}
}
@@ -276,7 +279,7 @@
request_set_header (req, "Foo", "bar"). */
static void
-request_set_user_header (struct request *req, const char *header)
+request_set_user_header (struct request *req, const char *header, bool append_header)
{
char *name;
const char *p = strchr (header, ':');
@@ -286,7 +289,7 @@
++p;
while (c_isspace (*p))
++p;
- request_set_header (req, xstrdup (name), (char *) p, rel_name);
+ request_set_header (req, xstrdup (name), (char *) p, rel_name, append_header);
}
/* Remove the header with specified name from REQ. Returns true if
@@ -420,7 +423,7 @@
{
request_set_header (req, "Authorization",
basic_authentication_encode (user, passwd),
- rel_value);
+ rel_value, false);
}
return do_challenge;
}
@@ -1344,9 +1347,11 @@
#define SET_USER_AGENT(req) do { \
if (!opt.useragent) \
request_set_header (req, "User-Agent", \
- aprintf ("Wget/%s", version_string), rel_value); \
+ aprintf ("Wget/%s", version_string), \
+ rel_value, false); \
else if (*opt.useragent) \
- request_set_header (req, "User-Agent", opt.useragent, rel_none); \
+ request_set_header (req, "User-Agent", opt.useragent, \
+ rel_none, false); \
} while (0)
/* The flags that allow clobbering the file (opening with "wb").
@@ -1479,16 +1484,16 @@
request_set_method (req, meth, meth_arg);
}
- request_set_header (req, "Referer", (char *) hs->referer, rel_none);
+ request_set_header (req, "Referer", (char *) hs->referer, rel_none, false);
if (*dt & SEND_NOCACHE)
- request_set_header (req, "Pragma", "no-cache", rel_none);
+ request_set_header (req, "Pragma", "no-cache", rel_none, false);
if (hs->restval)
request_set_header (req, "Range",
aprintf ("bytes=%s-",
number_to_static_string (hs->restval)),
- rel_value);
+ rel_value, false);
SET_USER_AGENT (req);
- request_set_header (req, "Accept", "*/*", rel_none);
+ request_set_header (req, "Accept", "*/*", rel_none, false);
/* Find the username and password for authentication. */
user = u->user;
@@ -1525,11 +1530,11 @@
int add_squares = strchr (u->host, ':') != NULL;
request_set_header (req, "Host",
aprintf (hfmt[add_port][add_squares], u->host, u->port),
- rel_value);
+ rel_value, false);
}
if (!inhibit_keep_alive)
- request_set_header (req, "Connection", "Keep-Alive", rel_none);
+ request_set_header (req, "Connection", "Keep-Alive", rel_none, false);
if (opt.cookies)
request_set_header (req, "Cookie",
@@ -1541,12 +1546,12 @@
0
#endif
),
- rel_value);
+ rel_value, false);
if (opt.post_data || opt.post_file_name)
{
request_set_header (req, "Content-Type",
- "application/x-www-form-urlencoded", rel_none);
+ "application/x-www-form-urlencoded", rel_none, false);
if (opt.post_data)
post_data_size = strlen (opt.post_data);
else
@@ -1561,7 +1566,7 @@
}
request_set_header (req, "Content-Length",
xstrdup (number_to_static_string (post_data_size)),
- rel_value);
+ rel_value, false);
}
/* Add the user headers. */
@@ -1569,7 +1574,15 @@
{
int i;
for (i = 0; opt.user_headers[i]; i++)
- request_set_user_header (req, opt.user_headers[i]);
+ request_set_user_header (req, opt.user_headers[i], false);
+ }
+
+ /* Append the user headers. */
+ if (opt.user_headers_append)
+ {
+ int i;
+ for (i = 0; opt.user_headers_append[i]; i++)
+ request_set_user_header (req, opt.user_headers_append[i], true);
}
retry_with_auth:
@@ -1609,7 +1622,8 @@
#ifdef HAVE_SSL
if (u->scheme != SCHEME_HTTPS)
#endif
- request_set_header (req, "Proxy-Authorization", proxyauth, rel_value);
+ request_set_header (req, "Proxy-Authorization", proxyauth, rel_value,
+ false);
}
keep_alive = false;
@@ -1685,7 +1699,7 @@
if (proxyauth)
{
request_set_header (connreq, "Proxy-Authorization",
- proxyauth, rel_value);
+ proxyauth, rel_value, false);
/* Now that PROXYAUTH is part of the CONNECT request,
zero it out so we don't send proxy authorization with
the regular request below. */
@@ -2006,7 +2020,7 @@
request_method (req),
pth,
&auth_finished),
- rel_value);
+ rel_value, false);
if (BEGINS_WITH (www_authenticate, "NTLM"))
ntlm_seen = true;
else if (!u->user && BEGINS_WITH (www_authenticate, "Basic"))
diff -r dd1cd4ad2b27 -r 7196e66f974a src/init.c
--- a/src/init.c Wed Nov 26 21:53:40 2008 -0800
+++ b/src/init.c Sat Nov 29 21:14:07 2008 +0100
@@ -84,6 +84,7 @@
CMD_DECLARE (cmd_spec_dirstruct);
CMD_DECLARE (cmd_spec_header);
+CMD_DECLARE (cmd_spec_append_header);
CMD_DECLARE (cmd_spec_htmlify);
CMD_DECLARE (cmd_spec_mirror);
CMD_DECLARE (cmd_spec_prefer_family);
@@ -113,6 +114,7 @@
{ "accept", &opt.accepts, cmd_vector },
{ "addhostdir", &opt.add_hostdir, cmd_boolean },
{ "alwaysrest", &opt.always_rest, cmd_boolean }, /* deprecated */
+ { "appendheader", NULL, cmd_spec_append_header },
{ "askpassword", &opt.ask_passwd, cmd_boolean },
{ "authnochallenge", &opt.auth_without_challenge,
cmd_boolean },
@@ -1152,6 +1154,27 @@
}
static bool
+cmd_spec_append_header (const char *com, const char *val, void *place_ignored)
+{
+ /* Empty value means reset the list of headers. */
+ if (*val == '\0')
+ {
+ fprintf (stderr, _("%s: %s: Missing append header.\n"),
+ exec_name, com);
+ return false;
+ }
+
+ if (!check_user_specified_header (val))
+ {
+ fprintf (stderr, _("%s: %s: Invalid append header %s.\n"),
+ exec_name, com, quote (val));
+ return false;
+ }
+ opt.user_headers_append = vec_append (opt.user_headers_append, val);
+ return true;
+}
+
+static bool
cmd_spec_htmlify (const char *com, const char *val, void *place_ignored)
{
int flag = cmd_boolean (com, val, &opt.htmlify);
@@ -1549,6 +1572,7 @@
xfree_null (opt.http_user);
xfree_null (opt.http_passwd);
free_vec (opt.user_headers);
+ free_vec (opt.user_headers_append);
# ifdef HAVE_SSL
xfree_null (opt.cert_file);
xfree_null (opt.private_key);
diff -r dd1cd4ad2b27 -r 7196e66f974a src/main.c
--- a/src/main.c Wed Nov 26 21:53:40 2008 -0800
+++ b/src/main.c Sat Nov 29 21:14:07 2008 +0100
@@ -142,6 +142,7 @@
static struct cmdline_option option_data[] =
{
{ "accept", 'A', OPT_VALUE, "accept", -1 },
+ { "append-header", 0, OPT_VALUE, "appendheader", -1 },
{ "append-output", 'a', OPT__APPEND_OUTPUT, NULL, required_argument },
{ "ask-password", 0, OPT_BOOLEAN, "askpassword", -1 },
{ "auth-no-challenge", 0, OPT_BOOLEAN, "authnochallenge", -1 },
@@ -524,6 +525,8 @@
--ignore-length ignore `Content-Length' header field.\n"),
N_("\
--header=STRING insert STRING among the headers.\n"),
+ N_("\
+ --append-header=STRING append STRING after the headers.\n"),
N_("\
--max-redirect maximum redirections allowed per page.\n"),
N_("\
diff -r dd1cd4ad2b27 -r 7196e66f974a src/options.h
--- a/src/options.h Wed Nov 26 21:53:40 2008 -0800
+++ b/src/options.h Sat Nov 29 21:14:07 2008 +0100
@@ -99,6 +99,7 @@
char *http_user; /* HTTP username. */
char *http_passwd; /* HTTP password. */
char **user_headers; /* User-defined header(s). */
+ char **user_headers_append; /* User-defined append header(s). */
bool http_keep_alive; /* whether we use keep-alive */
bool use_proxy; /* Do we use proxy? */