]> sjero.net Git - wget/blobdiff - src/http.c
[svn] Make the MD5 references even more generic.
[wget] / src / http.c
index ffb83d9a84983b97eaaf3047709aebdaad3e79b1..2eae2f19d2ae1a70591006bf7b3bb9e765a8d260 100644 (file)
@@ -64,6 +64,9 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 # include "gen_sslfunc.h"
 #endif /* HAVE_SSL */
 #include "cookies.h"
+#ifdef USE_DIGEST
+# include "gen-md5.h"
+#endif
 
 extern char *version_string;
 
@@ -202,6 +205,10 @@ http_process_range (const char *hdr, void *arg)
   if (!strncasecmp (hdr, "bytes", 5))
     {
       hdr += 5;
+      /* "JavaWebServer/1.1.1" sends "bytes: x-y/z", contrary to the
+        HTTP spec. */
+      if (*hdr == ':')
+       ++hdr;
       hdr += skip_lws (hdr);
       if (!*hdr)
        return 0;
@@ -276,7 +283,7 @@ http_process_connection (const char *hdr, void *arg)
 /* Whether a persistent connection is active. */
 static int pc_active_p;
 /* Host and port of currently active persistent connection. */
-static unsigned char pc_last_host_ip[4];
+static struct address_list *pc_last_host_ip;
 static unsigned short pc_last_port;
 
 /* File descriptor of the currently active persistent connection. */
@@ -301,6 +308,11 @@ invalidate_persistent (void)
 #ifdef HAVE_SSL
   pc_active_ssl = 0;
 #endif /* HAVE_SSL */
+  if (pc_last_host_ip != NULL)
+    {
+      address_list_release (pc_last_host_ip);
+      pc_last_host_ip = NULL;
+    }
   DEBUGP (("Invalidating fd %d from further reuse.\n", pc_last_fd));
 }
 
@@ -319,8 +331,6 @@ register_persistent (const char *host, unsigned short port, int fd
 #endif
                     )
 {
-  int success;
-
   if (pc_active_p)
     {
       if (pc_last_fd == fd)
@@ -347,10 +357,13 @@ register_persistent (const char *host, unsigned short port, int fd
        }
     }
 
+  assert (pc_last_host_ip == NULL);
+
   /* This lookup_host cannot fail, because it has the results in the
      cache.  */
-  success = lookup_host (host, pc_last_host_ip);
-  assert (success);
+  pc_last_host_ip = lookup_host (host, 1);
+  assert (pc_last_host_ip != NULL);
+
   pc_last_port = port;
   pc_last_fd = fd;
   pc_active_p = 1;
@@ -371,7 +384,9 @@ persistent_available_p (const char *host, unsigned short port
 #endif
                        )
 {
-  unsigned char this_host_ip[4];
+  int success;
+  struct address_list *this_host_ip;
+
   /* First, check whether a persistent connection is active at all.  */
   if (!pc_active_p)
     return 0;
@@ -379,6 +394,7 @@ persistent_available_p (const char *host, unsigned short port
      (HOST, PORT) ordered pair.  */
   if (port != pc_last_port)
     return 0;
+
 #ifdef HAVE_SSL
   /* Second, a): check if current connection is (not) ssl, too.  This
      test is unlikely to fail because HTTP and HTTPS typicaly use
@@ -388,10 +404,19 @@ persistent_available_p (const char *host, unsigned short port
   if (ssl != pc_active_ssl)
     return 0;
 #endif /* HAVE_SSL */
-  if (!lookup_host (host, this_host_ip))
+
+  this_host_ip = lookup_host (host, 1);
+  if (!this_host_ip)
     return 0;
-  if (memcmp (pc_last_host_ip, this_host_ip, 4))
+
+  /* To equate the two host names for the purposes of persistent
+     connections, they need to share all the IP addresses in the
+     list.  */
+  success = address_list_match_all (pc_last_host_ip, this_host_ip);
+  address_list_release (this_host_ip);
+  if (!success)
     return 0;
+
   /* Third: check whether the connection is still open.  This is
      important because most server implement a liberal (short) timeout
      on persistent connections.  Wget can of course always reconnect
@@ -521,7 +546,6 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy)
   int sock, hcount, num_written, all_length, statcode;
   long contlen, contrange;
   struct url *conn;
-  uerr_t err;
   FILE *fp;
   int auth_tried_already;
   struct rbuf rbuf;
@@ -529,7 +553,6 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy)
   static SSL_CTX *ssl_ctx = NULL;
   SSL *ssl = NULL;
 #endif /* HAVE_SSL */
-  struct wget_timer *timer;
   char *cookies = NULL;
 
   /* Whether this connection will be kept alive after the HTTP request
@@ -547,7 +570,7 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy)
   /* initialize ssl_ctx on first run */
   if (!ssl_ctx)
     {
-      err = init_ssl (&ssl_ctx);
+      uerr_t err = init_ssl (&ssl_ctx);
       if (err != 0)
        {
          switch (err)
@@ -622,42 +645,17 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy)
 #endif /* HAVE_SSL */
       )
     {
-      logprintf (LOG_VERBOSE, _("Connecting to %s:%hu... "),
-                conn->host, conn->port);
-      err = make_connection (&sock, conn->host, conn->port);
-      switch (err)
-       {
-       case HOSTERR:
-         logputs (LOG_VERBOSE, "\n");
-         logprintf (LOG_NOTQUIET, "%s: %s.\n", conn->host, herrmsg (h_errno));
-         return HOSTERR;
-         break;
-       case CONSOCKERR:
-         logputs (LOG_VERBOSE, "\n");
-         logprintf (LOG_NOTQUIET, "socket: %s\n", strerror (errno));
-         return CONSOCKERR;
-         break;
-       case CONREFUSED:
-         logputs (LOG_VERBOSE, "\n");
-         logprintf (LOG_NOTQUIET,
-                    _("Connection to %s:%hu refused.\n"), conn->host,
-                    conn->port);
-         CLOSE (sock);
-         return CONREFUSED;
-       case CONERROR:
-         logputs (LOG_VERBOSE, "\n");
-         logprintf (LOG_NOTQUIET, "connect: %s\n", strerror (errno));
-         CLOSE (sock);
-         return CONERROR;
-         break;
-       case NOCONERROR:
-         /* Everything is fine!  */
-         logputs (LOG_VERBOSE, _("connected!\n"));
-         break;
-       default:
-         abort ();
-         break;
-       }
+      struct address_list *al = lookup_host (conn->host, 0);
+      if (!al)
+       return HOSTERR;
+      set_connection_host_name (conn->host);
+      sock = connect_to_many (al, conn->port, 0);
+      set_connection_host_name (NULL);
+      address_list_release (al);
+
+      if (sock < 0)
+       return errno == ECONNREFUSED ? CONREFUSED : CONERROR;
+
 #ifdef HAVE_SSL
      if (conn->scheme == SCHEME_HTTPS)
        if (connect_ssl (&ssl, ssl_ctx,sock) != 0)
@@ -1352,13 +1350,12 @@ Refusing to truncate existing file `%s'.\n\n"), *hs->local_file);
      should be some overhead information.  */
   if (opt.save_headers)
     fwrite (all_headers, 1, all_length, fp);
-  timer = wtimer_new ();
+
   /* Get the contents of the document.  */
   hs->res = get_contents (sock, fp, &hs->len, hs->restval,
                          (contlen != -1 ? contlen : 0),
-                         &rbuf, keep_alive);
-  hs->dltime = wtimer_elapsed (timer);
-  wtimer_delete (timer);
+                         &rbuf, keep_alive, &hs->dltime);
+
   {
     /* Close or flush the file.  We have to be careful to check for
        error here.  Checking the result of fwrite() is not enough --
@@ -2239,37 +2236,37 @@ digest_authentication_encode (const char *au, const char *user,
 
   /* Calculate the digest value.  */
   {
-    MD5_CONTEXT_TYPE ctx;
+    ALLOCA_MD5_CONTEXT (ctx);
     unsigned char hash[MD5_HASHLEN];
     unsigned char a1buf[MD5_HASHLEN * 2 + 1], a2buf[MD5_HASHLEN * 2 + 1];
     unsigned char response_digest[MD5_HASHLEN * 2 + 1];
 
     /* A1BUF = H(user ":" realm ":" password) */
-    MD5_INIT (&ctx);
-    MD5_UPDATE (user, strlen (user), &ctx);
-    MD5_UPDATE (":", 1, &ctx);
-    MD5_UPDATE (realm, strlen (realm), &ctx);
-    MD5_UPDATE (":", 1, &ctx);
-    MD5_UPDATE (passwd, strlen (passwd), &ctx);
-    MD5_FINISH (&ctx, hash);
+    gen_md5_init (ctx);
+    gen_md5_update (user, strlen (user), ctx);
+    gen_md5_update (":", 1, ctx);
+    gen_md5_update (realm, strlen (realm), ctx);
+    gen_md5_update (":", 1, ctx);
+    gen_md5_update (passwd, strlen (passwd), ctx);
+    gen_md5_finish (ctx, hash);
     dump_hash (a1buf, hash);
 
     /* A2BUF = H(method ":" path) */
-    MD5_INIT (&ctx);
-    MD5_UPDATE (method, strlen (method), &ctx);
-    MD5_UPDATE (":", 1, &ctx);
-    MD5_UPDATE (path, strlen (path), &ctx);
-    MD5_FINISH (&ctx, hash);
+    gen_md5_init (ctx);
+    gen_md5_update (method, strlen (method), ctx);
+    gen_md5_update (":", 1, ctx);
+    gen_md5_update (path, strlen (path), ctx);
+    gen_md5_finish (ctx, hash);
     dump_hash (a2buf, hash);
 
     /* RESPONSE_DIGEST = H(A1BUF ":" nonce ":" A2BUF) */
-    MD5_INIT (&ctx);
-    MD5_UPDATE (a1buf, MD5_HASHLEN * 2, &ctx);
-    MD5_UPDATE (":", 1, &ctx);
-    MD5_UPDATE (nonce, strlen (nonce), &ctx);
-    MD5_UPDATE (":", 1, &ctx);
-    MD5_UPDATE (a2buf, MD5_HASHLEN * 2, &ctx);
-    MD5_FINISH (&ctx, hash);
+    gen_md5_init (ctx);
+    gen_md5_update (a1buf, MD5_HASHLEN * 2, ctx);
+    gen_md5_update (":", 1, ctx);
+    gen_md5_update (nonce, strlen (nonce), ctx);
+    gen_md5_update (":", 1, ctx);
+    gen_md5_update (a2buf, MD5_HASHLEN * 2, ctx);
+    gen_md5_finish (ctx, hash);
     dump_hash (response_digest, hash);
 
     res = (char*) xmalloc (strlen (user)
@@ -2334,3 +2331,10 @@ create_authorization_line (const char *au, const char *user,
 #endif /* USE_DIGEST */
   return wwwauth;
 }
+\f
+void
+http_cleanup (void)
+{
+  if (pc_last_host_ip)
+    address_list_release (pc_last_host_ip);
+}