From 38b37ed1045b86625778bb21413bd9f78225d03a Mon Sep 17 00:00:00 2001 From: hniksic Date: Tue, 4 Nov 2003 16:11:33 -0800 Subject: [PATCH] [svn] New option --keep-session-cookies. --- src/ChangeLog | 12 ++++++ src/cookies.c | 103 +++++++++++++++++++++++++++++--------------------- src/cookies.h | 9 ++--- src/http.c | 12 +++--- src/init.c | 1 + src/main.c | 5 +++ src/options.h | 8 ++-- src/utils.c | 12 ++---- 8 files changed, 95 insertions(+), 67 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index 96fe01c1..f83a97bf 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,15 @@ +2003-11-05 Hrvoje Niksic + + * cookies.c (save_cookies_mapper): Respect the setting of + keep-session-cookies. + (cookie_jar_load): Import session cookies. + Based on code submitted by Nicolas Schodet. + + * utils.c (datetime_str): Use information in TM when it's + non-NULL. + + * main.c (main): New option `--keep-session-cookies'. + 2003-11-04 Hrvoje Niksic * Makefile.in (realclean): Delete config.h.in. diff --git a/src/cookies.c b/src/cookies.c index 259d0012..599d2daa 100644 --- a/src/cookies.c +++ b/src/cookies.c @@ -108,12 +108,13 @@ struct cookie { 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 */ @@ -123,7 +124,6 @@ struct cookie { }; #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. */ @@ -132,14 +132,23 @@ cookie_new (void) { 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 @@ -252,15 +261,20 @@ store_cookie (struct cookie_jar *jar, struct cookie *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)) : "", - 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 @@ -386,8 +400,8 @@ update_cookie_field (struct cookie *cookie, 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 @@ -649,9 +663,9 @@ parse_set_cookies (const char *sc, /* Check whether ADDR matches .... - 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) @@ -818,9 +832,9 @@ check_path_match (const char *cookie_path, const char *path) 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); @@ -969,7 +983,7 @@ cookie_matches_url (const struct cookie *cookie, { 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 @@ -1097,9 +1111,8 @@ goodness_comparator (const void *p1, const void *p2) 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; @@ -1132,8 +1145,7 @@ cookie_jar_generate_cookie_header (struct cookie_jar *jar, const char *host, 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 */ @@ -1148,8 +1160,7 @@ cookie_jar_generate_cookie_header (struct cookie_jar *jar, const char *host, 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); @@ -1356,14 +1367,21 @@ cookie_jar_load (struct cookie_jar *jar, const char *file) 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); @@ -1388,9 +1406,9 @@ save_cookies_mapper (void *key, void *value, void *arg) 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); @@ -1428,7 +1446,7 @@ cookie_jar_save (struct cookie_jar *jar, const char *file) } 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, save_cookies_mapper, fp); @@ -1436,7 +1454,6 @@ cookie_jar_save (struct cookie_jar *jar, const char *file) 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)); diff --git a/src/cookies.h b/src/cookies.h index d9dc477c..7533a461 100644 --- a/src/cookies.h +++ b/src/cookies.h @@ -35,11 +35,10 @@ struct cookie_jar; struct cookie_jar *cookie_jar_new PARAMS ((void)); void cookie_jar_delete PARAMS ((struct cookie_jar *)); -void cookie_jar_process_set_cookie PARAMS ((struct cookie_jar *, const char *, - int, const char *, const char *)); -char *cookie_jar_generate_cookie_header PARAMS ((struct cookie_jar *, - const char *, int, - const char *, int)); +void cookie_handle_set_cookie PARAMS ((struct cookie_jar *, const char *, + int, const char *, const char *)); +char *cookie_header PARAMS ((struct cookie_jar *, + const char *, int, const char *, int)); void cookie_jar_load PARAMS ((struct cookie_jar *, const char *)); void cookie_jar_save PARAMS ((struct cookie_jar *, const char *)); diff --git a/src/http.c b/src/http.c index 7104f8e0..2d27dbb5 100644 --- a/src/http.c +++ b/src/http.c @@ -344,8 +344,7 @@ http_process_set_cookie (const char *hdr, void *arg) /* The jar should have been created by now. */ assert (wget_cookie_jar != NULL); - cookie_jar_process_set_cookie (wget_cookie_jar, u->host, u->port, u->path, - hdr); + cookie_handle_set_cookie (wget_cookie_jar, u->host, u->port, u->path, hdr); return 1; } @@ -901,14 +900,13 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy) request_keep_alive = NULL; if (opt.cookies) - cookies = cookie_jar_generate_cookie_header (wget_cookie_jar, u->host, - u->port, u->path, + cookies = cookie_header (wget_cookie_jar, u->host, u->port, u->path, #ifdef HAVE_SSL - u->scheme == SCHEME_HTTPS + u->scheme == SCHEME_HTTPS #else - 0 + 0 #endif - ); + ); if (opt.post_data || opt.post_file_name) { diff --git a/src/init.c b/src/init.c index 8cc77bc7..a92b5e11 100644 --- a/src/init.c +++ b/src/init.c @@ -167,6 +167,7 @@ static struct { { "ignoretags", &opt.ignore_tags, cmd_vector }, { "includedirectories", &opt.includes, cmd_directory_vector }, { "input", &opt.input_filename, cmd_file }, + { "keepsessioncookies", &opt.keep_session_cookies, cmd_boolean }, { "killlonger", &opt.kill_longer, cmd_boolean }, { "limitrate", &opt.limit_rate, cmd_bytes }, { "loadcookies", &opt.cookies_input, cmd_file }, diff --git a/src/main.c b/src/main.c index 94aef3b5..207654b3 100644 --- a/src/main.c +++ b/src/main.c @@ -210,6 +210,7 @@ HTTP options:\n\ --cookies=off don't use cookies.\n\ --load-cookies=FILE load cookies from FILE before session.\n\ --save-cookies=FILE save cookies to FILE after session.\n\ + --keep-session-cookies load and save session (non-permanent) cookies.\n\ --post-data=STRING use the POST method; send STRING as the data.\n\ --post-file=FILE use the POST method; send contents of FILE.\n\ \n"), stdout); @@ -287,6 +288,7 @@ main (int argc, char *const *argv) { "help", no_argument, NULL, 'h' }, { "html-extension", no_argument, NULL, 'E' }, { "ignore-length", no_argument, NULL, 138 }, + { "keep-session-cookies", no_argument, NULL, 181 }, { "mirror", no_argument, NULL, 'm' }, { "no-clobber", no_argument, NULL, 141 }, { "no-directories", no_argument, NULL, 147 }, @@ -536,6 +538,9 @@ GNU General Public License for more details.\n")); case 177: setoptval ("strictcomments", "on"); break; + case 181: + setoptval ("keepsessioncookies", "on"); + break; /* Options accepting an argument: */ case 129: diff --git a/src/options.h b/src/options.h index 55ee968e..6adeb6bd 100644 --- a/src/options.h +++ b/src/options.h @@ -177,9 +177,11 @@ struct options int sslprotocol; /* 0 = auto / 1 = v2 / 2 = v3 / 3 = TLSv1 */ #endif /* HAVE_SSL */ - int cookies; - char *cookies_input; - char *cookies_output; + int cookies; /* whether cookies are used. */ + char *cookies_input; /* file we're loading the cookies from. */ + char *cookies_output; /* file we're saving the cookies to. */ + int keep_session_cookies; /* whether session cookies should be + saved and loaded. */ char *post_data; /* POST query string */ char *post_file_name; /* File to post */ diff --git a/src/utils.c b/src/utils.c index 5b577587..5f99fa7e 100644 --- a/src/utils.c +++ b/src/utils.c @@ -177,20 +177,14 @@ sepstring (const char *s) /* Return pointer to a static char[] buffer in which zero-terminated string-representation of TM (in form hh:mm:ss) is printed. - If TM is non-NULL, the current time-in-seconds will be stored - there. - - (#### This is misleading: one would expect TM would be used instead - of the current time in that case. This design was probably - influenced by the design time(2), and should be changed at some - points. No callers use non-NULL TM anyway.) */ + If TM is NULL, the current time will be used. */ char * time_str (time_t *tm) { static char output[15]; struct tm *ptm; - time_t secs = time (tm); + time_t secs = tm ? *tm : time (NULL); if (secs == -1) { @@ -211,7 +205,7 @@ datetime_str (time_t *tm) { static char output[20]; /* "YYYY-MM-DD hh:mm:ss" + \0 */ struct tm *ptm; - time_t secs = time (tm); + time_t secs = tm ? *tm : time (NULL); if (secs == -1) {