the cookies. */
struct cookie_jar {
- /* Mapping between domains and their corresponding cookies. */
- struct hash_table *chains_by_domain;
+ /* Cookie chains indexed by domain. */
+ struct hash_table *chains;
int cookie_count; /* number of cookies in the jar. */
};
struct cookie_jar *
cookie_jar_new (void)
{
- struct cookie_jar *jar = xmalloc (sizeof (struct cookie_jar));
- jar->chains_by_domain = make_nocase_string_hash_table (0);
+ struct cookie_jar *jar = xnew (struct cookie_jar);
+ jar->chains = make_nocase_string_hash_table (0);
jar->cookie_count = 0;
return jar;
}
whole. */
int permanent; /* whether the cookie should outlive
- the session */
- time_t expiry_time; /* time when the cookie expires */
+ the session. */
+ time_t expiry_time; /* time when the cookie expires, 0
+ means undetermined. */
int discard_requested; /* whether cookie was created to
request discarding another
- cookie */
+ cookie. */
char *attr; /* cookie attribute name */
char *value; /* cookie attribute value */
- struct cookie_jar *jar; /* pointer back to the cookie jar, for
- convenience. */
struct cookie *next; /* used for chaining of cookies in the
same domain. */
};
#define PORT_ANY (-1)
-#define COOKIE_EXPIRED_P(c) ((c)->expiry_time != 0 && (c)->expiry_time < cookies_now)
/* Allocate and return a new, empty cookie structure. */
static struct cookie *
cookie_new (void)
{
- struct cookie *cookie = xmalloc (sizeof (struct cookie));
- memset (cookie, '\0', sizeof (struct cookie));
+ struct cookie *cookie = xnew0 (struct cookie);
- /* Both cookie->permanent and cookie->expiry_time are now 0. By
- default, we assume that the cookie is non-permanent and valid
- until the end of the session. */
+ /* Both cookie->permanent and cookie->expiry_time are now 0. This
+ means that the cookie doesn't expire, but is only valid for this
+ session (i.e. not written out to disk). */
cookie->port = PORT_ANY;
return cookie;
}
+/* Non-zero if the cookie has expired. Assumes cookies_now has been
+ set by one of the entry point functions. */
+
+static int
+cookie_expired_p (const struct cookie *c)
+{
+ return c->expiry_time != 0 && c->expiry_time < cookies_now;
+}
+
/* Deallocate COOKIE and its components. */
static void
delete_cookie (struct cookie *cookie)
{
- FREE_MAYBE (cookie->domain);
- FREE_MAYBE (cookie->path);
- FREE_MAYBE (cookie->attr);
- FREE_MAYBE (cookie->value);
+ xfree_null (cookie->domain);
+ xfree_null (cookie->path);
+ xfree_null (cookie->attr);
+ xfree_null (cookie->value);
xfree (cookie);
}
\f
/* Functions for storing cookies.
- All cookies can be reached beginning with jar->chains_by_domain.
- The key in that table is the domain name, and the value is a linked
- list of all cookies from that domain. Every new cookie is placed
- on the head of the list. */
+ All cookies can be reached beginning with jar->chains. The key in
+ that table is the domain name, and the value is a linked list of
+ all cookies from that domain. Every new cookie is placed on the
+ head of the list. */
/* Find and return a cookie in JAR whose domain, path, and attribute
name correspond to COOKIE. If found, PREVPTR will point to the
{
struct cookie *chain, *prev;
- chain = hash_table_get (jar->chains_by_domain, cookie->domain);
+ chain = hash_table_get (jar->chains, cookie->domain);
if (!chain)
goto nomatch;
struct cookie *chain_head;
char *chain_key;
- if (hash_table_get_pair (jar->chains_by_domain, cookie->domain,
+ if (hash_table_get_pair (jar->chains, cookie->domain,
&chain_key, &chain_head))
{
/* A chain of cookies in this domain already exists. Check for
chain_key = xstrdup (cookie->domain);
}
- hash_table_put (jar->chains_by_domain, chain_key, cookie);
+ hash_table_put (jar->chains, chain_key, cookie);
++jar->cookie_count;
- DEBUGP (("\nStored cookie %s %d%s %s %s %d %s %s %s\n",
- cookie->domain, cookie->port,
- cookie->port == PORT_ANY ? " (ANY)" : "",
- cookie->path,
- cookie->permanent ? "permanent" : "nonpermanent",
- cookie->secure,
- cookie->expiry_time
- ? asctime (localtime (&cookie->expiry_time)) : "<undefined>",
- cookie->attr, cookie->value));
+#ifdef ENABLE_DEBUG
+ if (opt.debug)
+ {
+ time_t exptime = (time_t) cookie->expiry_time;
+ DEBUGP (("\nStored cookie %s %d%s %s <%s> <%s> [expiry %s] %s %s\n",
+ cookie->domain, cookie->port,
+ cookie->port == PORT_ANY ? " (ANY)" : "",
+ cookie->path,
+ cookie->permanent ? "permanent" : "session",
+ cookie->secure ? "secure" : "insecure",
+ cookie->expiry_time ? datetime_str (&exptime) : "none",
+ cookie->attr, cookie->value));
+ }
+#endif
}
/* Discard a cookie matching COOKIE's domain, port, path, and
{
struct cookie *prev, *victim;
- if (!hash_table_count (jar->chains_by_domain))
+ if (!hash_table_count (jar->chains))
/* No elements == nothing to discard. */
return;
char *chain_key = NULL;
int res;
- res = hash_table_get_pair (jar->chains_by_domain, victim->domain,
+ res = hash_table_get_pair (jar->chains, victim->domain,
&chain_key, NULL);
assert (res != 0);
if (!victim->next)
{
/* VICTIM was the only cookie in the chain. Destroy the
chain and deallocate the chain key. */
- hash_table_remove (jar->chains_by_domain, victim->domain);
+ hash_table_remove (jar->chains, victim->domain);
xfree (chain_key);
}
else
- hash_table_put (jar->chains_by_domain, chain_key, victim->next);
+ hash_table_put (jar->chains, chain_key, victim->next);
}
delete_cookie (victim);
DEBUGP (("Discarded old cookie.\n"));
{
if (!VALUE_NON_EMPTY)
return 0;
- FREE_MAYBE (cookie->domain);
+ xfree_null (cookie->domain);
/* Strictly speaking, we should set cookie->domain_exact if the
domain doesn't begin with a dot. But many sites set the
domain to "foo.com" and expect "subhost.foo.com" to get the
{
if (!VALUE_NON_EMPTY)
return 0;
- FREE_MAYBE (cookie->path);
+ xfree_null (cookie->path);
cookie->path = strdupdelim (value_b, value_e);
return 1;
}
cookie->expiry_time = (time_t)expires;
}
else
- /* Error in expiration spec. Assume default (cookie valid for
- this session.) */
+ /* Error in expiration spec. Assume default (cookie doesn't
+ expire, but valid only for this session.) */
;
/* According to netscape's specification, expiry time in the
/* Check whether ADDR matches <digits>.<digits>.<digits>.<digits>.
- We don't want to call network functions like inet_addr() because all
- we need is a check, preferrably one that is small, fast, and
- well-defined. */
+ We don't want to call network functions like inet_addr() because
+ all we need is a check, preferrably one that is small, fast, and
+ well-defined. */
static int
numeric_address_p (const char *addr)
depending on the contents. */
void
-cookie_jar_process_set_cookie (struct cookie_jar *jar,
- const char *host, int port,
- const char *path, const char *set_cookie)
+cookie_handle_set_cookie (struct cookie_jar *jar,
+ const char *host, int port,
+ const char *path, const char *set_cookie)
{
struct cookie *cookie;
cookies_now = time (NULL);
if (!cookie->domain)
{
copy_domain:
+ /* If the domain was not provided, we use the one we're talking
+ to, and set exact match. */
cookie->domain = xstrdup (host);
- cookie->port = port;
+ cookie->domain_exact = 1;
+ /* Set the port, but only if it's non-default. */
+ if (port != 80 && port != 443)
+ cookie->port = port;
}
else
{
int passes, passcnt;
/* Bail out quickly if there are no cookies in the jar. */
- if (!hash_table_count (jar->chains_by_domain))
+ if (!hash_table_count (jar->chains))
return 0;
if (numeric_address_p (host))
srk.fer.hr's, then fer.hr's. */
while (1)
{
- struct cookie *chain = hash_table_get (jar->chains_by_domain, host);
+ struct cookie *chain = hash_table_get (jar->chains, host);
if (chain)
dest[dest_count++] = chain;
if (++passcnt >= passes)
{
int pg;
- if (COOKIE_EXPIRED_P (cookie))
+ if (cookie_expired_p (cookie))
/* Ignore stale cookies. Don't bother unchaining the cookie at
this point -- Wget is a relatively short-lived application, and
stale cookies will not be saved by `save_cookies'. On the
generated, NULL is returned. */
char *
-cookie_jar_generate_cookie_header (struct cookie_jar *jar, const char *host,
- int port, const char *path,
- int connection_secure_p)
+cookie_header (struct cookie_jar *jar, const char *host,
+ int port, const char *path, int secflag)
{
struct cookie **chains;
int chain_count;
count = 0;
for (i = 0; i < chain_count; i++)
for (cookie = chains[i]; cookie; cookie = cookie->next)
- if (cookie_matches_url (cookie, host, port, path, connection_secure_p,
- NULL))
+ if (cookie_matches_url (cookie, host, port, path, secflag, NULL))
++count;
if (!count)
return NULL; /* no cookies matched */
for (cookie = chains[i]; cookie; cookie = cookie->next)
{
int pg;
- if (!cookie_matches_url (cookie, host, port, path,
- connection_secure_p, &pg))
+ if (!cookie_matches_url (cookie, host, port, path, secflag, &pg))
continue;
outgoing[ocnt].cookie = cookie;
outgoing[ocnt].domain_goodness = strlen (cookie->domain);
}
/* Allocate output buffer:
- "Cookie: " -- 8
name=value pairs -- result_size
"; " separators -- (count - 1) * 2
- \r\n line ending -- 2
\0 terminator -- 1 */
- result_size = 8 + result_size + (count - 1) * 2 + 2 + 1;
+ result_size = result_size + (count - 1) * 2 + 1;
result = xmalloc (result_size);
pos = 0;
- strcpy (result, "Cookie: ");
- pos += 8;
for (i = 0; i < count; i++)
{
struct cookie *c = outgoing[i].cookie;
result[pos++] = ' ';
}
}
- result[pos++] = '\r';
- result[pos++] = '\n';
result[pos++] = '\0';
assert (pos == result_size);
return result;
malloced.) */
*expires_e = '\0';
sscanf (expires_b, "%lf", &expiry);
- if (expiry < cookies_now)
- /* ignore stale cookie. */
- goto abort;
- cookie->expiry_time = expiry;
- /* If the cookie has survived being saved into an external file,
- it is obviously permanent. */
- cookie->permanent = 1;
+ if (expiry == 0)
+ {
+ /* EXPIRY can be 0 for session cookies saved because the
+ user specified `--keep-session-cookies' in the past.
+ They remain session cookies, and will be saved only if
+ the user has specified `keep-session-cookies' again. */
+ }
+ else
+ {
+ if (expiry < cookies_now)
+ goto abort; /* ignore stale cookie. */
+ cookie->expiry_time = expiry;
+ cookie->permanent = 1;
+ }
store_cookie (jar, cookie);
struct cookie *cookie = (struct cookie *)value;
for (; cookie; cookie = cookie->next)
{
- if (!cookie->permanent)
+ if (!cookie->permanent && !opt.keep_session_cookies)
continue;
- if (COOKIE_EXPIRED_P (cookie))
+ if (cookie_expired_p (cookie))
continue;
if (!cookie->domain_exact)
fputc ('.', fp);
}
fputs ("# HTTP cookie file.\n", fp);
- fprintf (fp, "# Generated by Wget on %s.\n", datetime_str (NULL));
+ fprintf (fp, "# Generated by Wget on %s.\n", datetime_str (&cookies_now));
fputs ("# Edit at your own risk.\n\n", fp);
- hash_table_map (jar->chains_by_domain, save_cookies_mapper, fp);
+ hash_table_map (jar->chains, save_cookies_mapper, fp);
if (ferror (fp))
logprintf (LOG_NOTQUIET, _("Error writing to `%s': %s\n"),
file, strerror (errno));
-
if (fclose (fp) < 0)
logprintf (LOG_NOTQUIET, _("Error closing `%s': %s\n"),
file, strerror (errno));
struct cookie_jar *jar = (struct cookie_jar *)arg;
/* Remove the chain from the table and free the key. */
- hash_table_remove (jar->chains_by_domain, chain_key);
+ hash_table_remove (jar->chains, chain_key);
xfree (chain_key);
/* Then delete all the cookies in the chain. */
void
cookie_jar_delete (struct cookie_jar *jar)
{
- hash_table_map (jar->chains_by_domain, nuke_cookie_chain, jar);
- hash_table_destroy (jar->chains_by_domain);
+ hash_table_map (jar->chains, nuke_cookie_chain, jar);
+ hash_table_destroy (jar->chains);
xfree (jar);
}
\f