#ifdef HAVE_SSL
# include "gen_sslfunc.h"
#endif /* HAVE_SSL */
+#include "cookies.h"
extern char *version_string;
# endif
#endif
\f
+static int cookies_loaded_p;
#define TEXTHTML_S "text/html"
#define HTTP_ACCEPT "*/*"
const char *));
static int known_authentication_scheme_p PARAMS ((const char *));
-static time_t http_atotm PARAMS ((char *));
+time_t http_atotm PARAMS ((char *));
#define BEGINS_WITH(line, string_constant) \
(!strncasecmp (line, string_constant, sizeof (string_constant) - 1) \
static SSL_CTX *ssl_ctx = NULL;
SSL *ssl = NULL;
#endif /* HAVE_SSL */
+ char *cookies = NULL;
/* Whether this connection will be kept alive after the HTTP request
is done. */
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;
/* String of the form :PORT. Used only for non-standard ports. */
port_maybe = NULL;
+ if (1
#ifdef HAVE_SSL
- if (remport != (u->proto == URLHTTPS ? DEFAULT_HTTPS_PORT : DEFAULT_HTTP_PORT) )
+ && remport != (u->proto == URLHTTPS
+ ? DEFAULT_HTTPS_PORT : DEFAULT_HTTP_PORT)
#else
- if (remport != DEFAULT_HTTP_PORT)
+ && remport != DEFAULT_HTTP_PORT
#endif
+ )
{
port_maybe = (char *)alloca (numdigit (remport) + 2);
sprintf (port_maybe, ":%d", remport);
+ (request_keep_alive
? strlen (request_keep_alive) : 0)
+ (referer ? strlen (referer) : 0)
+ + (cookies ? strlen (cookies) : 0)
+ (wwwauth ? strlen (wwwauth) : 0)
+ (proxyauth ? strlen (proxyauth) : 0)
+ (range ? strlen (range) : 0)
User-Agent: %s\r\n\
Host: %s%s\r\n\
Accept: %s\r\n\
-%s%s%s%s%s%s%s\r\n",
+%s%s%s%s%s%s%s%s\r\n",
command, path, useragent, remhost,
port_maybe ? port_maybe : "",
HTTP_ACCEPT,
request_keep_alive ? request_keep_alive : "",
referer ? referer : "",
+ cookies ? cookies : "",
wwwauth ? wwwauth : "",
proxyauth ? proxyauth : "",
range ? range : "",
/* Free the temporary memory. */
FREE_MAYBE (wwwauth);
FREE_MAYBE (proxyauth);
+ FREE_MAYBE (cookies);
/* Send the request to server. */
#ifdef HAVE_SSL
if (header_process (hdr, "Last-Modified", header_strdup,
&hs->remote_time))
goto done_header;
+ /* Try getting cookies. */
+ if (opt.cookies)
+ if (header_process (hdr, "Set-Cookie", set_cookie_header_cb, u))
+ goto done_header;
/* Try getting www-authentication. */
if (!authenticate_h)
if (header_process (hdr, "WWW-Authenticate", header_strdup,
{
logprintf (LOG_NOTQUIET,
_("\
-
- The server does not support continued download;
+\n\
+ The server does not support continued download;\n\
refusing to truncate `%s'.\n\n"), u->local);
return CONTNOTSUPPORTED;
}
}
else /* opt.dfp */
{
+ extern int global_download_count;
fp = opt.dfp;
- if (!hs->restval)
+ /* To ensure that repeated "from scratch" downloads work for -O
+ files, we rewind the file pointer, unless restval is
+ non-zero. (This works only when -O is used on regular files,
+ but it's still a valuable feature.)
+
+ However, this loses when more than one URL is specified on
+ the command line the second rewinds eradicates the contents
+ of the first download. Thus we disable the above trick for
+ all the downloads except the very first one.
+
+ #### A possible solution to this would be to remember the
+ file position in the output document and to seek to that
+ position, instead of rewinding. */
+ if (!hs->restval && global_download_count == 0)
{
/* This will silently fail for streams that don't correspond
to regular files, but that's OK. */
rewind (fp);
+ /* ftruncate is needed because opt.dfp is opened in append
+ mode if opt.always_rest is set. */
+ ftruncate (fileno (fp), 0);
clearerr (fp);
}
}
struct http_stat hstat; /* HTTP status */
struct stat st;
+ /* This used to be done in main(), but it's a better idea to do it
+ here so that we don't go through the hoops if we're just using
+ FTP or whatever. */
+ if (opt.cookies && opt.cookies_input && !cookies_loaded_p)
+ load_cookies (opt.cookies_input);
+
*newloc = NULL;
/* Warn on (likely bogus) wildcard usage in HTTP. Don't use
hstat.restval = 0L;
/* Decide whether or not to restart. */
if (((count > 1 && (*dt & ACCEPTRANGES)) || opt.always_rest)
- && file_exists_p (u->local))
- if (stat (u->local, &st) == 0)
+ && file_exists_p (locf))
+ if (stat (locf, &st) == 0 && S_ISREG (st.st_mode))
hstat.restval = st.st_size;
/* Decide whether to send the no-cache directive. */
if (u->proxy && (count > 1 || (opt.proxy_cache == 0)))
Marcus Hennecke's atotm(), which is forgiving, fast, to-the-point,
and does not use strptime(). atotm() is to be found in the sources
of `phttpd', a little-known HTTP server written by Peter Erikson. */
-static time_t
+time_t
http_atotm (char *time_string)
{
struct tm t;
/* RFC1123: Thu, 29 Jan 1998 22:12:57 */
if (check_end (strptime (time_string, "%a, %d %b %Y %T", &t)))
return mktime_from_utc (&t);
- /* RFC850: Thu, 29-Jan-98 22:12:57 */
- if (check_end (strptime (time_string, "%a, %d-%b-%y %T", &t)))
+ /* RFC850: Thursday, 29-Jan-98 22:12:57 */
+ if (check_end (strptime (time_string, "%A, %d-%b-%y %T", &t)))
+ return mktime_from_utc (&t);
+ /* pseudo-RFC850: Thu, 29-Jan-1998 22:12:57
+ (google.com uses this for their cookies.)*/
+ if (check_end (strptime (time_string, "%a, %d-%b-%Y %T", &t)))
return mktime_from_utc (&t);
/* asctime: Thu Jan 29 22:12:57 1998 */
if (check_end (strptime (time_string, "%a %b %d %T %Y", &t)))
return 0;
}
-/* Response value needs to be in lowercase, so we cannot use HEXD2ASC
- from url.h. See RFC 2069 2.1.2 for the syntax of response-digest. */
-#define HEXD2asc(x) (((x) < 10) ? ((x) + '0') : ((x) - 10 + 'a'))
-
/* Dump the hexadecimal representation of HASH to BUF. HASH should be
an array of 16 bytes containing the hash keys, and BUF should be a
buffer of 33 writable characters (32 for hex digits plus one for
for (i = 0; i < MD5_HASHLEN; i++, hash++)
{
- *buf++ = HEXD2asc (*hash >> 4);
- *buf++ = HEXD2asc (*hash & 0xf);
+ *buf++ = XDIGIT_TO_xchar (*hash >> 4);
+ *buf++ = XDIGIT_TO_xchar (*hash & 0xf);
}
*buf = '\0';
}