]> sjero.net Git - wget/blobdiff - src/http.c
[svn] Update copyright notices.
[wget] / src / http.c
index ecf29384c68708116e3a28422c97975775cf7993..2ea8a79d452214974d3962036a15ac2a3ad81397 100644 (file)
@@ -1,20 +1,21 @@
 /* HTTP support.
-   Copyright (C) 1995, 1996, 1997, 1998, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001
+   Free Software Foundation, Inc.
 
-This file is part of Wget.
+This file is part of GNU Wget.
 
-This program is free software; you can redistribute it and/or modify
+GNU Wget is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or
 (at your option) any later version.
 
-This program is distributed in the hope that it will be useful,
+GNU Wget is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
+along with Wget; if not, write to the Free Software
 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #include <config.h>
@@ -596,10 +597,6 @@ gethttp (struct urlinfo *u, struct http_stat *hs, int *dt)
   keep_alive = 0;
   http_keep_alive_1 = http_keep_alive_2 = 0;
 
-  if (opt.cookies)
-    cookies = build_cookies_request (u->host, u->port, u->path,
-                                    u->proto == URLHTTPS);
-
   /* Initialize certain elements of struct http_stat.  */
   hs->len = 0L;
   hs->contlen = -1;
@@ -807,6 +804,10 @@ gethttp (struct urlinfo *u, struct http_stat *hs, int *dt)
   else
     request_keep_alive = NULL;
 
+  if (opt.cookies)
+    cookies = build_cookies_request (ou->host, ou->port, ou->path,
+                                    ou->proto == URLHTTPS);
+
   /* Allocate the memory for the request.  */
   request = (char *)alloca (strlen (command) + strlen (path)
                            + strlen (useragent)
@@ -909,7 +910,6 @@ Accept: %s\r\n\
          logputs (LOG_NOTQUIET, _("End of file while parsing headers.\n"));
          xfree (hdr);
          FREE_MAYBE (type);
-         FREE_MAYBE (hs->newloc);
          FREE_MAYBE (all_headers);
          CLOSE_INVALIDATE (sock);
          return HEOF;
@@ -921,7 +921,6 @@ Accept: %s\r\n\
                     strerror (errno));
          xfree (hdr);
          FREE_MAYBE (type);
-         FREE_MAYBE (hs->newloc);
          FREE_MAYBE (all_headers);
          CLOSE_INVALIDATE (sock);
          return HERR;
@@ -1121,6 +1120,30 @@ Accept: %s\r\n\
   if (H_20X (statcode))
     *dt |= RETROKF;
 
+  /* Return if redirected.  */
+  if (H_REDIRECTED (statcode) || statcode == HTTP_STATUS_MULTIPLE_CHOICES)
+    {
+      /* RFC2068 says that in case of the 300 (multiple choices)
+        response, the server can output a preferred URL through
+        `Location' header; otherwise, the request should be treated
+        like GET.  So, if the location is set, it will be a
+        redirection; otherwise, just proceed normally.  */
+      if (statcode == HTTP_STATUS_MULTIPLE_CHOICES && !hs->newloc)
+       *dt |= RETROKF;
+      else
+       {
+         logprintf (LOG_VERBOSE,
+                    _("Location: %s%s\n"),
+                    hs->newloc ? hs->newloc : _("unspecified"),
+                    hs->newloc ? _(" [following]") : "");
+         CLOSE_INVALIDATE (sock);      /* would be CLOSE_FINISH, but there
+                                          might be more bytes in the body. */
+         FREE_MAYBE (type);
+         FREE_MAYBE (all_headers);
+         return NEWLOCATION;
+       }
+    }
+
   if (type && !strncasecmp (type, TEXTHTML_S, strlen (TEXTHTML_S)))
     *dt |= TEXTHTML;
   else
@@ -1168,7 +1191,11 @@ Accept: %s\r\n\
       if (opt.always_rest)
        {
          /* Check for condition #2. */
-         if (hs->restval == contlen)
+         if (hs->restval > 0               /* restart was requested. */
+             && contlen != -1              /* we got content-length. */
+             && hs->restval >= contlen     /* file fully downloaded
+                                              or has shrunk.  */
+             )
            {
              logputs (LOG_VERBOSE, _("\
 \n    The file is already fully retrieved; nothing to do.\n\n"));
@@ -1176,11 +1203,10 @@ Accept: %s\r\n\
              hs->len = contlen;
              hs->res = 0;
              FREE_MAYBE (type);
-             FREE_MAYBE (hs->newloc);
              FREE_MAYBE (all_headers);
              CLOSE_INVALIDATE (sock);  /* would be CLOSE_FINISH, but there
                                           might be more bytes in the body. */
-             return RETRFINISHED;
+             return RETRUNNEEDED;
            }
 
          /* Check for condition #1. */
@@ -1189,8 +1215,11 @@ Accept: %s\r\n\
              logprintf (LOG_NOTQUIET,
                         _("\
 \n\
-    The server does not support continued download;\n\
-    refusing to truncate `%s'.\n\n"), u->local);
+Continued download failed on this file, which conflicts with `-c'.\n\
+Refusing to truncate existing file `%s'.\n\n"), u->local);
+             FREE_MAYBE (type);
+             FREE_MAYBE (all_headers);
+             CLOSE_INVALIDATE (sock);
              return CONTNOTSUPPORTED;
            }
 
@@ -1199,14 +1228,12 @@ Accept: %s\r\n\
 
       hs->restval = 0;
     }
-
   else if (contrange != hs->restval ||
           (H_PARTIAL (statcode) && contrange == -1))
     {
       /* This means the whole request was somehow misunderstood by the
         server.  Bail out.  */
       FREE_MAYBE (type);
-      FREE_MAYBE (hs->newloc);
       FREE_MAYBE (all_headers);
       CLOSE_INVALIDATE (sock);
       return RANGEERR;
@@ -1222,29 +1249,6 @@ Accept: %s\r\n\
     }
   hs->contlen = contlen;
 
-  /* Return if redirected.  */
-  if (H_REDIRECTED (statcode) || statcode == HTTP_STATUS_MULTIPLE_CHOICES)
-    {
-      /* RFC2068 says that in case of the 300 (multiple choices)
-        response, the server can output a preferred URL through
-        `Location' header; otherwise, the request should be treated
-        like GET.  So, if the location is set, it will be a
-        redirection; otherwise, just proceed normally.  */
-      if (statcode == HTTP_STATUS_MULTIPLE_CHOICES && !hs->newloc)
-       *dt |= RETROKF;
-      else
-       {
-         logprintf (LOG_VERBOSE,
-                    _("Location: %s%s\n"),
-                    hs->newloc ? hs->newloc : _("unspecified"),
-                    hs->newloc ? _(" [following]") : "");
-         CLOSE_INVALIDATE (sock);      /* would be CLOSE_FINISH, but there
-                                          might be more bytes in the body. */
-         FREE_MAYBE (type);
-         FREE_MAYBE (all_headers);
-         return NEWLOCATION;
-       }
-    }
   if (opt.verbose)
     {
       if ((*dt & RETROKF) && !opt.server_response)
@@ -1403,11 +1407,8 @@ http_loop (struct urlinfo *u, char **newloc, int *dt)
   else
     locf = opt.output_document;
 
-  /* Yuck.  Multiple returns suck.  We need to remember to free() the space we
-     xmalloc() here before EACH return.  This is one reason it's better to set
-     flags that influence flow control and then return once at the end. */
-  filename_len = strlen(u->local);
-  filename_plus_orig_suffix = xmalloc(filename_len + sizeof(".orig"));
+  filename_len = strlen (u->local);
+  filename_plus_orig_suffix = alloca (filename_len + sizeof (".orig"));
 
   if (opt.noclobber && file_exists_p (u->local))
     {
@@ -1425,7 +1426,6 @@ File `%s' already there, will not retrieve.\n"), u->local);
          && (!strcmp (suf, "html") || !strcmp (suf, "htm")))
        *dt |= TEXTHTML;
       xfree (suf);
-      xfree (filename_plus_orig_suffix); /* must precede every return! */
       /* Another harmless lie: */
       return RETROK;
     }
@@ -1453,11 +1453,12 @@ File `%s' already there, will not retrieve.\n"), u->local);
             in url.c.  Replacing sprintf with inline calls to
             strcpy() and long_to_string() made a difference.
             --hniksic */
-         strcpy(filename_plus_orig_suffix, u->local);
-         strcpy(filename_plus_orig_suffix + filename_len, ".orig");
+         memcpy (filename_plus_orig_suffix, u->local, filename_len);
+         memcpy (filename_plus_orig_suffix + filename_len,
+                 ".orig", sizeof (".orig"));
 
          /* Try to stat() the .orig file. */
-         if (stat(filename_plus_orig_suffix, &st) == 0)
+         if (stat (filename_plus_orig_suffix, &st) == 0)
            {
              local_dot_orig_file_exists = TRUE;
              local_filename = filename_plus_orig_suffix;
@@ -1518,10 +1519,18 @@ File `%s' already there, will not retrieve.\n"), u->local);
       hstat.restval = 0L;
       /* Decide whether or not to restart.  */
       if (((count > 1 && (*dt & ACCEPTRANGES)) || opt.always_rest)
+         /* #### this calls access() and then stat(); could be optimized. */
          && file_exists_p (locf))
        if (stat (locf, &st) == 0 && S_ISREG (st.st_mode))
          hstat.restval = st.st_size;
 
+      /* In `-c' is used and the file is existing and non-empty,
+        refuse to truncate it if the server doesn't support continued
+        downloads.  */
+      hstat.no_truncate = 0;
+      if (opt.always_rest && hstat.restval)
+       hstat.no_truncate = 1;
+
       /* Decide whether to send the no-cache directive.  We send it in
         two cases:
           a) we're using a proxy, and we're past our first retrieval.
@@ -1547,13 +1556,6 @@ File `%s' already there, will not retrieve.\n"), u->local);
       else
        locf = opt.output_document;
 
-      /* In `-c' is used, check whether the file we're writing to
-        exists before we've done anything.  If so, we'll refuse to
-        truncate it if the server doesn't support continued
-        downloads.  */
-      if (opt.always_rest)
-       hstat.no_truncate = file_exists_p (locf);
-
       /* Time?  */
       tms = time_str (NULL);
       /* Get the new location (with or without the redirection).  */
@@ -1575,7 +1577,6 @@ File `%s' already there, will not retrieve.\n"), u->local);
        case SSLERRCTXCREATE: case CONTNOTSUPPORTED:
          /* Fatal errors just return from the function.  */
          FREEHSTAT (hstat);
-         xfree (filename_plus_orig_suffix); /* must precede every return! */
          return err;
          break;
        case FWRITEERR: case FOPENERR:
@@ -1591,7 +1592,6 @@ File `%s' already there, will not retrieve.\n"), u->local);
          logputs (LOG_VERBOSE, "\n");
          logprintf (LOG_NOTQUIET, _("Unable to establish SSL connection.\n"));
          FREEHSTAT (hstat);
-         xfree (filename_plus_orig_suffix); /* must precede every return! */
          return err;
          break;
        case NEWLOCATION:
@@ -1601,13 +1601,16 @@ File `%s' already there, will not retrieve.\n"), u->local);
              logprintf (LOG_NOTQUIET,
                         _("ERROR: Redirection (%d) without location.\n"),
                         hstat.statcode);
-             xfree (filename_plus_orig_suffix); /* must precede every return! */
              return WRONGCODE;
            }
          FREEHSTAT (hstat);
-         xfree (filename_plus_orig_suffix); /* must precede every return! */
          return NEWLOCATION;
          break;
+       case RETRUNNEEDED:
+         /* The file was already fully retrieved. */
+         FREEHSTAT (hstat);
+         return RETROK;
+         break;
        case RETRFINISHED:
          /* Deal with you later.  */
          break;
@@ -1628,7 +1631,6 @@ File `%s' already there, will not retrieve.\n"), u->local);
                     tms, hstat.statcode, hstat.error);
          logputs (LOG_VERBOSE, "\n");
          FREEHSTAT (hstat);
-         xfree (filename_plus_orig_suffix); /* must precede every return! */
          return WRONGCODE;
        }
 
@@ -1672,7 +1674,6 @@ Last-modified header invalid -- time-stamp ignored.\n"));
 Server file no newer than local file `%s' -- not retrieving.\n\n"),
                             local_filename);
                  FREEHSTAT (hstat);
-                 xfree (filename_plus_orig_suffix); /*must precede every return!*/
                  return RETROK;
                }
              else if (tml >= tmr)
@@ -1710,7 +1711,6 @@ 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);
-         xfree (filename_plus_orig_suffix); /* must precede every return! */
          return RETROK;
        }
 
@@ -1740,7 +1740,6 @@ The sizes do not match (local %ld) -- retrieving.\n"), local_size);
          else
            downloaded_file(FILE_DOWNLOADED_NORMALLY, locf);
 
-         xfree(filename_plus_orig_suffix); /* must precede every return! */
          return RETROK;
        }
       else if (hstat.res == 0) /* No read error */
@@ -1766,7 +1765,6 @@ The sizes do not match (local %ld) -- retrieving.\n"), local_size);
              else
                downloaded_file(FILE_DOWNLOADED_NORMALLY, locf);
              
-             xfree (filename_plus_orig_suffix); /* must precede every return! */
              return RETROK;
            }
          else if (hstat.len < hstat.contlen) /* meaning we lost the
@@ -1795,7 +1793,6 @@ The sizes do not match (local %ld) -- retrieving.\n"), local_size);
              else
                downloaded_file(FILE_DOWNLOADED_NORMALLY, locf);
              
-             xfree (filename_plus_orig_suffix); /* must precede every return! */
              return RETROK;
            }
          else                  /* the same, but not accepted */
@@ -1831,7 +1828,6 @@ The sizes do not match (local %ld) -- retrieving.\n"), local_size);
       break;
     }
   while (!opt.ntry || (count < opt.ntry));
-  xfree (filename_plus_orig_suffix); /* must precede every return! */
   return TRYLIMEXC;
 }
 \f