From 428c1a2b3cb4a0a3d1d9f08e85498db3951925f3 Mon Sep 17 00:00:00 2001
From: hniksic <devnull@localhost>
Date: Tue, 26 Apr 2005 06:34:33 -0700
Subject: [PATCH] [svn] Fix various cookie-related problems.

---
 src/ChangeLog | 15 +++++++++++++++
 src/cookies.c | 15 ++++++++++++++-
 src/http.c    | 43 +++++++++++++++++++++++++++++++------------
 src/main.c    |  2 +-
 4 files changed, 61 insertions(+), 14 deletions(-)

diff --git a/src/ChangeLog b/src/ChangeLog
index 883a41af..9ae9dee7 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,18 @@
+2005-04-26  Hrvoje Niksic  <hniksic@xemacs.org>
+
+	* cookies.c (cookie_handle_set_cookie): Delete the part of the
+	path after the trailing slash.
+
+	* http.c (gethttp): Call cookie_handle_set_cookie with path that
+	begins with '/'.
+
+2005-04-26  Hrvoje Niksic  <hniksic@xemacs.org>
+
+	* http.c (gethttp): Call skip_short_body only if keep_alive is in
+	use.
+	(gethttp): Send the User-Agent header with the CONNECT request as
+	well.
+
 2005-04-25  Hrvoje Niksic  <hniksic@xemacs.org>
 
 	* main.c (option_data): Removed support for the undocumented flag
diff --git a/src/cookies.c b/src/cookies.c
index d0d9e610..45d45159 100644
--- a/src/cookies.c
+++ b/src/cookies.c
@@ -870,9 +870,19 @@ cookie_handle_set_cookie (struct cookie_jar *jar,
     }
 
   if (!cookie->path)
-    cookie->path = xstrdup (path);
+    {
+      /* The cookie doesn't set path: set it to the URL path, sans the
+	 file part ("/dir/file" truncated to "/dir/").  */
+      char *trailing_slash = strrchr (path, '/');
+      if (trailing_slash)
+	cookie->path = strdupdelim (path, trailing_slash + 1);
+      else
+	/* no slash in the string -- can this even happen? */
+	cookie->path = xstrdup (path);
+    }
   else
     {
+      /* The cookie sets its own path; verify that it is legal. */
       if (!check_path_match (cookie->path, path))
 	{
 	  DEBUGP (("Attempt to fake the path: %s, %s\n",
@@ -881,6 +891,9 @@ cookie_handle_set_cookie (struct cookie_jar *jar,
 	}
     }
 
+  /* Now store the cookie, or discard an existing cookie, if
+     discarding was requested.  */
+
   if (cookie->discard_requested)
     {
       discard_matching_cookie (jar, cookie);
diff --git a/src/http.c b/src/http.c
index 6a5cf1f9..77861d89 100644
--- a/src/http.c
+++ b/src/http.c
@@ -1113,6 +1113,14 @@ time_t http_atotm PARAMS ((const char *));
    && (ISSPACE (line[sizeof (string_constant) - 1])			\
        || !line[sizeof (string_constant) - 1]))
 
+#define SET_USER_AGENT(req)						\
+  if (opt.useragent)							\
+    request_set_header (req, "User-Agent", opt.useragent, rel_none);	\
+  else									\
+    request_set_header (req, "User-Agent",				\
+			aprintf ("Wget/%s", version_string), rel_value);
+
+
 /* Retrieve a document through HTTP protocol.  It recognizes status
    code, and correctly handles redirections.  It closes the network
    socket.  If it receives an error from the functions below it, it
@@ -1245,11 +1253,7 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy)
 			aprintf ("bytes=%s-",
 				 number_to_static_string (hs->restval)),
 			rel_value);
-  if (opt.useragent)
-    request_set_header (req, "User-Agent", opt.useragent, rel_none);
-  else
-    request_set_header (req, "User-Agent",
-			aprintf ("Wget/%s", version_string), rel_value);
+  SET_USER_AGENT (req);
   request_set_header (req, "Accept", "*/*", rel_none);
 
   /* Find the username and password for authentication. */
@@ -1455,6 +1459,7 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy)
 	  struct request *connreq = request_new ();
 	  request_set_method (connreq, "CONNECT",
 			      aprintf ("%s:%d", u->host, u->port));
+	  SET_USER_AGENT (req);
 	  if (proxyauth)
 	    {
 	      request_set_header (connreq, "Proxy-Authorization",
@@ -1464,6 +1469,10 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy)
 		 the regular request below.  */
 	      proxyauth = NULL;
 	    }
+	  /* Examples in rfc2817 use the Host header in CONNECT
+	     requests.  I don't see how that gains anything, given
+	     that the contents of Host would be exactly the same as
+	     the contents of CONNECT.  */
 
 	  write_error = request_send (connreq, sock);
 	  request_free (connreq);
@@ -1622,10 +1631,13 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy)
   if (statcode == HTTP_STATUS_UNAUTHORIZED)
     {
       /* Authorization is required.  */
-      if (skip_short_body (sock, contlen))
-	CLOSE_FINISH (sock);
-      else
-	CLOSE_INVALIDATE (sock);
+      if (keep_alive)
+	{
+	  if (skip_short_body (sock, contlen))
+	    CLOSE_FINISH (sock);
+	  else
+	    CLOSE_INVALIDATE (sock);
+	}
       pconn.authorized = 0;
       if (auth_finished || !(user && passwd))
 	{
@@ -1714,6 +1726,7 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy)
 
   /* Handle (possibly multiple instances of) the Set-Cookie header. */
   {
+    char *pth = NULL;
     int scpos;
     const char *scbeg, *scend;
     /* The jar should have been created by now. */
@@ -1723,10 +1736,16 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy)
 				      &scbeg, &scend)) != -1;
 	 ++scpos)
       {
-	char *set_cookie = strdupdelim (scbeg, scend);
-	cookie_handle_set_cookie (wget_cookie_jar, u->host, u->port, u->path,
+	char *set_cookie; BOUNDED_TO_ALLOCA (scbeg, scend, set_cookie);
+	if (pth == NULL)
+	  {
+	    /* u->path doesn't begin with /, which cookies.c expects. */
+	    pth = (char *) alloca (1 + strlen (u->path) + 1);
+	    pth[0] = '/';
+	    strcpy (pth + 1, u->path);
+	  }
+	cookie_handle_set_cookie (wget_cookie_jar, u->host, u->port, pth,
 				  set_cookie);
-	xfree (set_cookie);
       }
   }
 
diff --git a/src/main.c b/src/main.c
index fcbe53a5..e340dc83 100644
--- a/src/main.c
+++ b/src/main.c
@@ -245,7 +245,7 @@ struct cmdline_option option_data[] =
     { IF_SSL ("sslcertkey"), 0, OPT_VALUE, "sslcertkey", -1 },
     { IF_SSL ("sslcerttype"), 0, OPT_VALUE, "sslcerttype", -1 },
     { IF_SSL ("sslcheckcert"), 0, OPT_VALUE, "sslcheckcert", -1 },
-    { IF_SSL ("sslprotocol"), 0, OPT_VALUE, "sslprotocol", -1 },
+    { IF_SSL ("secure-protocol"), 0, OPT_VALUE, "secureprotocol", -1 },
     { "strict-comments", 0, OPT_BOOLEAN, "strictcomments", -1 },
     { "timeout", 'T', OPT_VALUE, "timeout", -1 },
     { "timestamping", 'N', OPT_BOOLEAN, "timestamping", -1 },