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;
}
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)
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;
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);
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);
hs->error = xstrdup (_("No data received"));
else
hs->error = xstrdup (_("Malformed status line"));
- free (hdr);
+ xfree (hdr);
break;
}
else if (!*error)
/* Exit on empty header. */
if (!*hdr)
{
- free (hdr);
+ xfree (hdr);
break;
}
}
}
done_header:
- free (hdr);
+ xfree (hdr);
}
logputs (LOG_VERBOSE, "\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;
}
/* We do not need this anymore. */
if (authenticate_h)
{
- free (authenticate_h);
+ xfree (authenticate_h);
authenticate_h = NULL;
}
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;
}
#ifdef WINDOWS
ws_changetitle (hurl, 1);
#endif
- free (hurl);
+ xfree (hurl);
}
/* Default document type is empty. However, if spider mode is
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:
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:
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:
/* #### 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;
}
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)
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;
}
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 */
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
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 */
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
"^ *(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;