1
0
mirror of https://github.com/moparisthebest/wget synced 2024-07-03 16:38:41 -04:00

[svn] Handle multiple Set-Cookie headers sent by the server.

This commit is contained in:
hniksic 2005-03-06 14:53:02 -08:00
parent 30aaf5a19a
commit 976c54d0e6
2 changed files with 84 additions and 48 deletions

View File

@ -1,3 +1,8 @@
2005-03-06 Hrvoje Niksic <hniksic@xemacs.org>
* http.c (gethttp): Handle multiple Set-Cookie headers sent by
remote server.
2005-03-06 Hrvoje Niksic <hniksic@xemacs.org>
* init.c (defaults): Use passive FTP by default.

View File

@ -1,5 +1,5 @@
/* HTTP support.
Copyright (C) 2003 Free Software Foundation, Inc.
Copyright (C) 2005 Free Software Foundation, Inc.
This file is part of GNU Wget.
@ -403,7 +403,7 @@ post_file (int sock, const char *file_name, wgint promised_size)
}
static const char *
head_terminator (const char *hunk, int oldlen, int peeklen)
response_head_terminator (const char *hunk, int oldlen, int peeklen)
{
const char *start, *end;
@ -441,9 +441,9 @@ head_terminator (const char *hunk, int oldlen, int peeklen)
data can be treated as body. */
static char *
fd_read_http_head (int fd)
read_http_response_head (int fd)
{
return fd_read_hunk (fd, head_terminator, 512);
return fd_read_hunk (fd, response_head_terminator, 512);
}
struct response {
@ -474,10 +474,10 @@ struct response {
/* Create a new response object from the text of the HTTP response,
available in HEAD. That text is automatically split into
constituent header lines for fast retrieval using
response_header_*. */
resp_header_*. */
static struct response *
response_new (const char *head)
resp_new (const char *head)
{
const char *hdr;
int count, size;
@ -493,7 +493,7 @@ response_new (const char *head)
return resp;
}
/* Split HEAD into header lines, so that response_header_* functions
/* Split HEAD into header lines, so that resp_header_* functions
don't need to do this over and over again. */
size = count = 0;
@ -524,27 +524,36 @@ response_new (const char *head)
return resp;
}
/* Locate the header named NAME in the request data. If found, set
*BEGPTR to its starting, and *ENDPTR to its ending position, and
return 1. Otherwise return 0.
/* Locate the header named NAME in the request data, starting with
position START. This allows the code to loop through the request
data, filtering for all requests of a given name. Returns the
found position, or -1 for failure. The code that uses this
function typically looks like this:
This function is used as a building block for response_header_copy
and response_header_strdup. */
for (pos = 0; (pos = resp_header_locate (...)) != -1; pos++)
... do something with header ...
If you only care about one header, use resp_header_get instead of
this function. */
static int
response_header_bounds (const struct response *resp, const char *name,
const char **begptr, const char **endptr)
resp_header_locate (const struct response *resp, const char *name, int start,
const char **begptr, const char **endptr)
{
int i;
const char **headers = resp->headers;
int name_len;
if (!headers || !headers[1])
return 0;
return -1;
name_len = strlen (name);
if (start > 0)
i = start;
else
i = 1;
for (i = 1; headers[i + 1]; i++)
for (; headers[i + 1]; i++)
{
const char *b = headers[i];
const char *e = headers[i + 1];
@ -559,26 +568,41 @@ response_header_bounds (const struct response *resp, const char *name,
--e;
*begptr = b;
*endptr = e;
return 1;
return i;
}
}
return 0;
return -1;
}
/* Find and retrieve the header named NAME in the request data. If
found, set *BEGPTR to its starting, and *ENDPTR to its ending
position, and return 1. Otherwise return 0.
This function is used as a building block for resp_header_copy
and resp_header_strdup. */
static int
resp_header_get (const struct response *resp, const char *name,
const char **begptr, const char **endptr)
{
int pos = resp_header_locate (resp, name, 0, begptr, endptr);
return pos != -1;
}
/* Copy the response header named NAME to buffer BUF, no longer than
BUFSIZE (BUFSIZE includes the terminating 0). If the header
exists, 1 is returned, otherwise 0. If there should be no limit on
the size of the header, use response_header_strdup instead.
the size of the header, use resp_header_strdup instead.
If BUFSIZE is 0, no data is copied, but the boolean indication of
whether the header is present is still returned. */
static int
response_header_copy (const struct response *resp, const char *name,
char *buf, int bufsize)
resp_header_copy (const struct response *resp, const char *name,
char *buf, int bufsize)
{
const char *b, *e;
if (!response_header_bounds (resp, name, &b, &e))
if (!resp_header_get (resp, name, &b, &e))
return 0;
if (bufsize)
{
@ -593,10 +617,10 @@ response_header_copy (const struct response *resp, const char *name,
malloc. If such a header does not exist in RESP, return NULL. */
static char *
response_header_strdup (const struct response *resp, const char *name)
resp_header_strdup (const struct response *resp, const char *name)
{
const char *b, *e;
if (!response_header_bounds (resp, name, &b, &e))
if (!resp_header_get (resp, name, &b, &e))
return NULL;
return strdupdelim (b, e);
}
@ -610,7 +634,7 @@ response_header_strdup (const struct response *resp, const char *name)
returned in *MESSAGE. */
static int
response_status (const struct response *resp, char **message)
resp_status (const struct response *resp, char **message)
{
int status;
const char *p, *end;
@ -670,7 +694,7 @@ response_status (const struct response *resp, char **message)
/* Release the resources used by RESP. */
static void
response_free (struct response *resp)
resp_free (struct response *resp)
{
xfree_null (resp->headers);
xfree (resp);
@ -1354,7 +1378,7 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy)
return WRITEFAILED;
}
head = fd_read_http_head (sock);
head = read_http_response_head (sock);
if (!head)
{
logprintf (LOG_VERBOSE, _("Failed reading proxy response: %s\n"),
@ -1370,9 +1394,9 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy)
}
DEBUGP (("proxy responded with: [%s]\n", head));
resp = response_new (head);
statcode = response_status (resp, &message);
response_free (resp);
resp = resp_new (head);
statcode = resp_status (resp, &message);
resp_free (resp);
if (statcode != 200)
{
failed_tunnel:
@ -1429,7 +1453,7 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy)
contrange = 0;
*dt &= ~RETROKF;
head = fd_read_http_head (sock);
head = read_http_response_head (sock);
if (!head)
{
if (errno == 0)
@ -1450,11 +1474,11 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy)
}
DEBUGP (("\n---response begin---\n%s---response end---\n", head));
resp = response_new (head);
resp = resp_new (head);
/* Check for status line. */
message = NULL;
statcode = response_status (resp, &message);
statcode = resp_status (resp, &message);
if (!opt.server_response)
logprintf (LOG_VERBOSE, "%2d %s\n", statcode,
message ? escnonprint (message) : "");
@ -1465,7 +1489,7 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy)
}
if (!opt.ignore_length
&& response_header_copy (resp, "Content-Length", hdrval, sizeof (hdrval)))
&& resp_header_copy (resp, "Content-Length", hdrval, sizeof (hdrval)))
{
wgint parsed;
errno = 0;
@ -1484,10 +1508,9 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy)
/* Check for keep-alive related responses. */
if (!inhibit_keep_alive && contlen != -1)
{
if (response_header_copy (resp, "Keep-Alive", NULL, 0))
if (resp_header_copy (resp, "Keep-Alive", NULL, 0))
keep_alive = 1;
else if (response_header_copy (resp, "Connection", hdrval,
sizeof (hdrval)))
else if (resp_header_copy (resp, "Connection", hdrval, sizeof (hdrval)))
{
if (0 == strcasecmp (hdrval, "Keep-Alive"))
keep_alive = 1;
@ -1511,8 +1534,8 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy)
}
else
{
char *www_authenticate = response_header_strdup (resp,
"WWW-Authenticate");
char *www_authenticate = resp_header_strdup (resp,
"WWW-Authenticate");
/* If the authentication scheme is unknown or if it's the
"Basic" authentication (which we try by default), there's
no sense in retrying. */
@ -1552,7 +1575,7 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy)
else
hs->error = xstrdup (message);
type = response_header_strdup (resp, "Content-Type");
type = resp_header_strdup (resp, "Content-Type");
if (type)
{
char *tmp = strchr (type, ';');
@ -1563,27 +1586,35 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy)
*tmp = '\0';
}
}
hs->newloc = response_header_strdup (resp, "Location");
hs->remote_time = response_header_strdup (resp, "Last-Modified");
hs->newloc = resp_header_strdup (resp, "Location");
hs->remote_time = resp_header_strdup (resp, "Last-Modified");
/* Handle (possibly multiple instances of) the Set-Cookie header. */
{
char *set_cookie = response_header_strdup (resp, "Set-Cookie");
if (set_cookie)
int scpos;
const char *scbeg, *scend;
/* The jar should have been created by now. */
assert (wget_cookie_jar != NULL);
for (scpos = 0;
(scpos = resp_header_locate (resp, "Set-Cookie", scpos,
&scbeg, &scend)) != -1;
++scpos)
{
/* The jar should have been created by now. */
assert (wget_cookie_jar != NULL);
char *set_cookie = strdupdelim (scbeg, scend);
cookie_handle_set_cookie (wget_cookie_jar, u->host, u->port, u->path,
set_cookie);
xfree (set_cookie);
}
}
if (response_header_copy (resp, "Content-Range", hdrval, sizeof (hdrval)))
if (resp_header_copy (resp, "Content-Range", hdrval, sizeof (hdrval)))
{
wgint first_byte_pos, last_byte_pos, entity_length;
if (parse_content_range (hdrval, &first_byte_pos, &last_byte_pos,
&entity_length))
contrange = first_byte_pos;
}
response_free (resp);
resp_free (resp);
/* 20x responses are counted among successful by default. */
if (H_20X (statcode))