wget: fix --header to not append duplicate headers

function                                             old     new   delta
wget_main                                           2551    2715    +164
wget_user_headers                                      -      62     +62
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 1/0 up/down: 226/0)             Total: 226 bytes

Signed-off-by: Bernhard Reutner-Fischer <rep.dot.nop@gmail.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Bernhard Reutner-Fischer 2015-02-18 20:41:02 +01:00 committed by Denys Vlasenko
parent 54e9585e10
commit d7bfee1edb

View File

@ -38,8 +38,14 @@
#if 0 #if 0
# define log_io(...) bb_error_msg(__VA_ARGS__) # define log_io(...) bb_error_msg(__VA_ARGS__)
# define SENDFMT(fp, fmt, ...) \
do { \
log_io("> " fmt, ##__VA_ARGS__); \
fprintf(fp, fmt, ##__VA_ARGS__); \
} while (0);
#else #else
# define log_io(...) ((void)0) # define log_io(...) ((void)0)
# define SENDFMT(fp, fmt, ...) fprintf(fp, fmt, ##__VA_ARGS__)
#endif #endif
@ -55,6 +61,36 @@ static const char P_FTP[] = "ftp";
static const char P_HTTP[] = "http"; static const char P_HTTP[] = "http";
static const char P_HTTPS[] = "https"; static const char P_HTTPS[] = "https";
#if ENABLE_FEATURE_WGET_LONG_OPTIONS
/* User-specified headers prevent using our corresponding built-in headers. */
enum {
HDR_HOST = (1<<0),
HDR_USER_AGENT = (1<<1),
HDR_RANGE = (1<<2),
HDR_AUTH = (1<<3) * ENABLE_FEATURE_WGET_AUTHENTICATION,
HDR_PROXY_AUTH = (1<<4) * ENABLE_FEATURE_WGET_AUTHENTICATION,
};
static const char wget_user_headers[] ALIGN1 =
"Host:\0"
"User-Agent:\0"
"Range:\0"
# if ENABLE_FEATURE_WGET_AUTHENTICATION
"Authorization:\0"
"Proxy-Authorization:\0"
# endif
;
# define USR_HEADER_HOST (G.user_headers & HDR_HOST)
# define USR_HEADER_USER_AGENT (G.user_headers & HDR_USER_AGENT)
# define USR_HEADER_RANGE (G.user_headers & HDR_RANGE)
# define USR_HEADER_AUTH (G.user_headers & HDR_AUTH)
# define USR_HEADER_PROXY_AUTH (G.user_headers & HDR_PROXY_AUTH)
#else /* No long options, no user-headers :( */
# define USR_HEADER_HOST 0
# define USR_HEADER_USER_AGENT 0
# define USR_HEADER_RANGE 0
# define USR_HEADER_AUTH 0
# define USR_HEADER_PROXY_AUTH 0
#endif
/* Globals */ /* Globals */
struct globals { struct globals {
@ -69,6 +105,7 @@ struct globals {
#if ENABLE_FEATURE_WGET_LONG_OPTIONS #if ENABLE_FEATURE_WGET_LONG_OPTIONS
char *post_data; char *post_data;
char *extra_headers; char *extra_headers;
unsigned char user_headers; /* Headers mentioned by the user */
#endif #endif
char *fname_out; /* where to direct output (-O) */ char *fname_out; /* where to direct output (-O) */
const char *proxy_flag; /* Use proxies if env vars are set */ const char *proxy_flag; /* Use proxies if env vars are set */
@ -830,43 +867,46 @@ static void download_one_url(const char *url)
#endif #endif
/* Send HTTP request */ /* Send HTTP request */
if (use_proxy) { if (use_proxy) {
fprintf(sfp, "GET %s://%s/%s HTTP/1.1\r\n", SENDFMT(sfp, "GET %s://%s/%s HTTP/1.1\r\n",
target.protocol, target.host, target.protocol, target.host,
target.path); target.path);
} else { } else {
fprintf(sfp, "%s /%s HTTP/1.1\r\n", SENDFMT(sfp, "%s /%s HTTP/1.1\r\n",
(option_mask32 & WGET_OPT_POST_DATA) ? "POST" : "GET", (option_mask32 & WGET_OPT_POST_DATA) ? "POST" : "GET",
target.path); target.path);
} }
if (!USR_HEADER_HOST)
fprintf(sfp, "Host: %s\r\nUser-Agent: %s\r\n", SENDFMT(sfp, "Host: %s\r\n", target.host);
target.host, G.user_agent); if (!USR_HEADER_USER_AGENT)
SENDFMT(sfp, "User-Agent: %s\r\n", G.user_agent);
/* Ask server to close the connection as soon as we are done /* Ask server to close the connection as soon as we are done
* (IOW: we do not intend to send more requests) * (IOW: we do not intend to send more requests)
*/ */
fprintf(sfp, "Connection: close\r\n"); SENDFMT(sfp, "Connection: close\r\n");
#if ENABLE_FEATURE_WGET_AUTHENTICATION #if ENABLE_FEATURE_WGET_AUTHENTICATION
if (target.user) { if (target.user && !USR_HEADER_AUTH) {
fprintf(sfp, "Proxy-Authorization: Basic %s\r\n"+6, SENDFMT(sfp, "Proxy-Authorization: Basic %s\r\n"+6,
base64enc(target.user)); base64enc(target.user));
} }
if (use_proxy && server.user) { if (use_proxy && server.user && !USR_HEADER_PROXY_AUTH) {
fprintf(sfp, "Proxy-Authorization: Basic %s\r\n", SENDFMT(sfp, "Proxy-Authorization: Basic %s\r\n",
base64enc(server.user)); base64enc(server.user));
} }
#endif #endif
if (G.beg_range != 0) if (G.beg_range != 0 && !USR_HEADER_RANGE)
fprintf(sfp, "Range: bytes=%"OFF_FMT"u-\r\n", G.beg_range); SENDFMT(sfp, "Range: bytes=%"OFF_FMT"u-\r\n", G.beg_range);
#if ENABLE_FEATURE_WGET_LONG_OPTIONS #if ENABLE_FEATURE_WGET_LONG_OPTIONS
if (G.extra_headers) if (G.extra_headers) {
log_io(G.extra_headers);
fputs(G.extra_headers, sfp); fputs(G.extra_headers, sfp);
}
if (option_mask32 & WGET_OPT_POST_DATA) { if (option_mask32 & WGET_OPT_POST_DATA) {
fprintf(sfp, SENDFMT(sfp,
"Content-Type: application/x-www-form-urlencoded\r\n" "Content-Type: application/x-www-form-urlencoded\r\n"
"Content-Length: %u\r\n" "Content-Length: %u\r\n"
"\r\n" "\r\n"
@ -876,7 +916,7 @@ static void download_one_url(const char *url)
} else } else
#endif #endif
{ {
fprintf(sfp, "\r\n"); SENDFMT(sfp, "\r\n");
} }
fflush(sfp); fflush(sfp);
@ -1093,7 +1133,9 @@ int wget_main(int argc UNUSED_PARAM, char **argv)
#if ENABLE_FEATURE_WGET_LONG_OPTIONS #if ENABLE_FEATURE_WGET_LONG_OPTIONS
applet_long_options = wget_longopts; applet_long_options = wget_longopts;
#endif #endif
opt_complementary = "-1" IF_FEATURE_WGET_TIMEOUT(":T+") IF_FEATURE_WGET_LONG_OPTIONS(":\xfe::"); opt_complementary = "-1"
IF_FEATURE_WGET_TIMEOUT(":T+")
IF_FEATURE_WGET_LONG_OPTIONS(":\xfe::");
getopt32(argv, "csqO:P:Y:U:T:" /*ignored:*/ "t:", getopt32(argv, "csqO:P:Y:U:T:" /*ignored:*/ "t:",
&G.fname_out, &G.dir_prefix, &G.fname_out, &G.dir_prefix,
&G.proxy_flag, &G.user_agent, &G.proxy_flag, &G.user_agent,
@ -1106,16 +1148,32 @@ int wget_main(int argc UNUSED_PARAM, char **argv)
#if ENABLE_FEATURE_WGET_LONG_OPTIONS #if ENABLE_FEATURE_WGET_LONG_OPTIONS
if (headers_llist) { if (headers_llist) {
int size = 1; int size = 0;
char *cp; char *hdr;
llist_t *ll = headers_llist; llist_t *ll = headers_llist;
while (ll) { while (ll) {
size += strlen(ll->data) + 2; size += strlen(ll->data) + 2;
ll = ll->link; ll = ll->link;
} }
G.extra_headers = cp = xmalloc(size); G.extra_headers = hdr = xmalloc(size + 1);
while (headers_llist) { while (headers_llist) {
cp += sprintf(cp, "%s\r\n", (char*)llist_pop(&headers_llist)); int bit;
const char *words;
size = sprintf(hdr, "%s\r\n",
(char*)llist_pop(&headers_llist));
/* a bit like index_in_substrings but don't match full key */
bit = 1;
words = wget_user_headers;
while (*words) {
if (strstr(hdr, words) == hdr) {
G.user_headers |= bit;
break;
}
bit <<= 1;
words += strlen(words) + 1;
}
hdr += size;
} }
} }
#endif #endif