]> sjero.net Git - wget/blobdiff - src/http.c
[svn] Committed <sxsbsv854j9.fsf@florida.arsdigita.de>.
[wget] / src / http.c
index 40b1f580b68a5eaa948a4ee3520efcf11edfba76..b487cbc4ba229cdb7c4362b8a588ac66e89fc30f 100644 (file)
@@ -239,18 +239,13 @@ static int
 http_process_type (const char *hdr, void *arg)
 {
   char **result = (char **)arg;
-  char *p;
-
-  p = strrchr (hdr, ';');
-  if (p)
-    {
-      int len = p - hdr;
-      *result = (char *)xmalloc (len + 1);
-      memcpy (*result, hdr, len);
-      (*result)[len] = '\0';
-    }
-  else
-    *result = xstrdup (hdr);
+  /* Locate P on `;' or the terminating zero, whichever comes first. */
+  const char *p = strchr (hdr, ';');
+  if (!p)
+    p = hdr + strlen (hdr);
+  while (p > hdr && ISSPACE (*(p - 1)))
+    --p;
+  *result = strdupdelim (hdr, p);
   return 1;
 }
 
@@ -264,27 +259,28 @@ http_process_connection (const char *hdr, void *arg)
   return 1;
 }
 \f
-/* Persistent connections (pc).  Currently, we cache the most recently
-   used connection as persistent, provided that the HTTP server agrees
-   to make it such.  The persistence data is stored in the variables
+/* Persistent connections.  Currently, we cache the most recently used
+   connection as persistent, provided that the HTTP server agrees to
+   make it such.  The persistence data is stored in the variables
    below.  Ideally, it would be in a structure, and it should be
    possible to cache an arbitrary fixed number of these connections.
 
    I think the code is quite easy to extend in that direction.  */
 
-/* Whether the persistent connection is active. */
+/* Whether a persistent connection is active. */
 static int pc_active_p;
 
-/* Host and port of the last persistent connection. */
+/* Host and port of currently active persistent connection. */
 static unsigned char pc_last_host[4];
 static unsigned short pc_last_port;
 
-/* File descriptor of the last persistent connection. */
+/* File descriptor of the currently active persistent connection. */
 static int pc_last_fd;
 
 /* Mark the persistent connection as invalid.  This is used by the
    CLOSE_* macros after they forcefully close a registered persistent
-   connection.  */
+   connection.  This does not close the file descriptor -- it is left
+   to the caller to do that.  (Maybe it should, though.)  */
 
 static void
 invalidate_persistent (void)
@@ -343,16 +339,28 @@ static int
 persistent_available_p (const char *host, unsigned short port)
 {
   unsigned char this_host[4];
+  /* First, check whether a persistent connection is active at all.  */
   if (!pc_active_p)
     return 0;
+  /* Second, check if the active connection pertains to the correct
+     (HOST, PORT) ordered pair.  */
   if (port != pc_last_port)
     return 0;
   if (!store_hostaddress (this_host, host))
     return 0;
   if (memcmp (pc_last_host, this_host, 4))
     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
+     if the connection doesn't work out, but it's nicer to know in
+     advance.  This test is a logical followup of the first test, but
+     is "expensive" and therefore placed at the end of the list.  */
   if (!test_socket_open (pc_last_fd))
     {
+      /* Oops, the socket is no longer open.  Now that we know that,
+         let's invalidate the persistent connection before returning
+         0.  */
       CLOSE (pc_last_fd);
       invalidate_persistent ();
       return 0;
@@ -755,7 +763,7 @@ Accept: %s\r\n\
             what you accept."  Oh boy.  */
          logputs (LOG_VERBOSE, "\n");
          logputs (LOG_NOTQUIET, _("End of file while parsing headers.\n"));
-         free (hdr);
+         xfree (hdr);
          FREE_MAYBE (type);
          FREE_MAYBE (hs->newloc);
          FREE_MAYBE (all_headers);
@@ -767,7 +775,7 @@ Accept: %s\r\n\
          logputs (LOG_VERBOSE, "\n");
          logprintf (LOG_NOTQUIET, _("Read error (%s) in headers.\n"),
                     strerror (errno));
-         free (hdr);
+         xfree (hdr);
          FREE_MAYBE (type);
          FREE_MAYBE (hs->newloc);
          FREE_MAYBE (all_headers);
@@ -808,7 +816,7 @@ Accept: %s\r\n\
                hs->error = xstrdup (_("No data received"));
              else
                hs->error = xstrdup (_("Malformed status line"));
-             free (hdr);
+             xfree (hdr);
              break;
            }
          else if (!*error)
@@ -829,7 +837,7 @@ Accept: %s\r\n\
       /* Exit on empty header.  */
       if (!*hdr)
        {
-         free (hdr);
+         xfree (hdr);
          break;
        }
 
@@ -897,7 +905,7 @@ Accept: %s\r\n\
            }
        }
     done_header:
-      free (hdr);
+      xfree (hdr);
     }
 
   logputs (LOG_VERBOSE, "\n");
@@ -927,12 +935,12 @@ Accept: %s\r\n\
             retrying it.  */
        failed:
          logputs (LOG_NOTQUIET, _("Authorization failed.\n"));
-         free (authenticate_h);
+         xfree (authenticate_h);
          return AUTHFAILED;
        }
       else if (!known_authentication_scheme_p (authenticate_h))
        {
-         free (authenticate_h);
+         xfree (authenticate_h);
          logputs (LOG_NOTQUIET, _("Unknown authentication scheme.\n"));
          return AUTHFAILED;
        }
@@ -952,7 +960,7 @@ Accept: %s\r\n\
   /* We do not need this anymore.  */
   if (authenticate_h)
     {
-      free (authenticate_h);
+      xfree (authenticate_h);
       authenticate_h = NULL;
     }
 
@@ -1184,8 +1192,8 @@ File `%s' already there, will not retrieve.\n"), u->local);
       if (((suf = suffix (u->local)) != NULL)
          && (!strcmp (suf, "html") || !strcmp (suf, "htm")))
        *dt |= TEXTHTML;
-      free (suf);
-      free(filename_plus_orig_suffix);  /* must precede every return! */
+      xfree (suf);
+      xfree (filename_plus_orig_suffix); /* must precede every return! */
       /* Another harmless lie: */
       return RETROK;
     }
@@ -1278,7 +1286,7 @@ File `%s' already there, will not retrieve.\n"), u->local);
 #ifdef WINDOWS
          ws_changetitle (hurl, 1);
 #endif
-         free (hurl);
+         xfree (hurl);
        }
 
       /* Default document type is empty.  However, if spider mode is
@@ -1333,7 +1341,7 @@ File `%s' already there, will not retrieve.\n"), u->local);
        case HOSTERR: case CONREFUSED: case PROXERR: case AUTHFAILED:
          /* Fatal errors just return from the function.  */
          FREEHSTAT (hstat);
-         free(filename_plus_orig_suffix);  /* must precede every return! */
+         xfree (filename_plus_orig_suffix); /* must precede every return! */
          return err;
          break;
        case FWRITEERR: case FOPENERR:
@@ -1342,7 +1350,7 @@ File `%s' already there, will not retrieve.\n"), u->local);
          logprintf (LOG_NOTQUIET, _("Cannot write to `%s' (%s).\n"),
                     u->local, strerror (errno));
          FREEHSTAT (hstat);
-         free(filename_plus_orig_suffix);  /* must precede every return! */
+         xfree (filename_plus_orig_suffix); /* must precede every return! */
          return err;
          break;
        case NEWLOCATION:
@@ -1352,11 +1360,11 @@ File `%s' already there, will not retrieve.\n"), u->local);
              logprintf (LOG_NOTQUIET,
                         _("ERROR: Redirection (%d) without location.\n"),
                         hstat.statcode);
-             free(filename_plus_orig_suffix);  /* must precede every return! */
+             xfree (filename_plus_orig_suffix); /* must precede every return! */
              return WRONGCODE;
            }
          FREEHSTAT (hstat);
-         free(filename_plus_orig_suffix);  /* must precede every return! */
+         xfree (filename_plus_orig_suffix); /* must precede every return! */
          return NEWLOCATION;
          break;
        case RETRFINISHED:
@@ -1373,13 +1381,13 @@ File `%s' already there, will not retrieve.\n"), u->local);
              /* #### Ugly ugly ugly! */
              char *hurl = str_url (u->proxy ? u->proxy : u, 1);
              logprintf (LOG_NONVERBOSE, "%s:\n", hurl);
-             free (hurl);
+             xfree (hurl);
            }
          logprintf (LOG_NOTQUIET, _("%s ERROR %d: %s.\n"),
                     tms, hstat.statcode, hstat.error);
          logputs (LOG_VERBOSE, "\n");
          FREEHSTAT (hstat);
-         free(filename_plus_orig_suffix);  /* must precede every return! */
+         xfree (filename_plus_orig_suffix); /* must precede every return! */
          return WRONGCODE;
        }
 
@@ -1423,7 +1431,7 @@ Last-modified header invalid -- time-stamp ignored.\n"));
 Server file no newer than local file `%s' -- not retrieving.\n\n"),
                             local_filename);
                  FREEHSTAT (hstat);
-                 free(filename_plus_orig_suffix);/*must precede every return!*/
+                 xfree (filename_plus_orig_suffix); /*must precede every return!*/
                  return RETROK;
                }
              else if (tml >= tmr)
@@ -1451,7 +1459,7 @@ The sizes do not match (local %ld) -- retrieving.\n"), local_size);
       if (opt.spider)
        {
          logprintf (LOG_NOTQUIET, "%d %s\n\n", hstat.statcode, hstat.error);
-         free(filename_plus_orig_suffix);  /* must precede every return! */
+         xfree (filename_plus_orig_suffix); /* must precede every return! */
          return RETROK;
        }
 
@@ -1481,7 +1489,7 @@ The sizes do not match (local %ld) -- retrieving.\n"), local_size);
          else
            downloaded_file(FILE_DOWNLOADED_NORMALLY, locf);
 
-         free(filename_plus_orig_suffix);  /* must precede every return! */
+         xfree(filename_plus_orig_suffix); /* must precede every return! */
          return RETROK;
        }
       else if (hstat.res == 0) /* No read error */
@@ -1507,7 +1515,7 @@ The sizes do not match (local %ld) -- retrieving.\n"), local_size);
              else
                downloaded_file(FILE_DOWNLOADED_NORMALLY, locf);
              
-             free(filename_plus_orig_suffix);  /* must precede every return! */
+             xfree (filename_plus_orig_suffix); /* must precede every return! */
              return RETROK;
            }
          else if (hstat.len < hstat.contlen) /* meaning we lost the
@@ -1536,7 +1544,7 @@ The sizes do not match (local %ld) -- retrieving.\n"), local_size);
              else
                downloaded_file(FILE_DOWNLOADED_NORMALLY, locf);
              
-             free(filename_plus_orig_suffix);  /* must precede every return! */
+             xfree (filename_plus_orig_suffix); /* must precede every return! */
              return RETROK;
            }
          else                  /* the same, but not accepted */
@@ -1572,7 +1580,7 @@ The sizes do not match (local %ld) -- retrieving.\n"), local_size);
       break;
     }
   while (!opt.ntry || (count < opt.ntry));
-  free(filename_plus_orig_suffix);  /* must precede every return! */
+  xfree (filename_plus_orig_suffix); /* must precede every return! */
   return TRYLIMEXC;
 }
 \f
@@ -1602,7 +1610,7 @@ mktime_from_utc (struct tm *t)
    "^ *(GMT|[+-][0-9]|$)", 0 otherwise.  P being NULL (a valid result of
    strptime()) is considered a failure and 0 is returned.  */
 static int
-check_end (char *p)
+check_end (const char *p)
 {
   if (!p)
     return 0;