/* 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>
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;
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)
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;
strerror (errno));
xfree (hdr);
FREE_MAYBE (type);
- FREE_MAYBE (hs->newloc);
FREE_MAYBE (all_headers);
CLOSE_INVALIDATE (sock);
return HERR;
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
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"));
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. */
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;
}
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;
}
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)
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))
{
&& (!strcmp (suf, "html") || !strcmp (suf, "htm")))
*dt |= TEXTHTML;
xfree (suf);
- xfree (filename_plus_orig_suffix); /* must precede every return! */
/* Another harmless lie: */
return RETROK;
}
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;
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.
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). */
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:
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:
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;
tms, hstat.statcode, hstat.error);
logputs (LOG_VERBOSE, "\n");
FREEHSTAT (hstat);
- xfree (filename_plus_orig_suffix); /* must precede every return! */
return WRONGCODE;
}
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)
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;
}
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 */
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
else
downloaded_file(FILE_DOWNLOADED_NORMALLY, locf);
- xfree (filename_plus_orig_suffix); /* must precede every return! */
return RETROK;
}
else /* the same, but not accepted */
break;
}
while (!opt.ntry || (count < opt.ntry));
- xfree (filename_plus_orig_suffix); /* must precede every return! */
return TRYLIMEXC;
}
\f