#endif
#include "convert.h"
+#ifdef TESTING
+#include "test.h"
+#endif
+
extern char *version_string;
#ifndef MIN
DEBUGP (("] done.\n"));
return true;
}
+
+static bool
+extract_param_value_delim (const char *begin, const char *end,
+ const char *param_name, char **param_value)
+{
+ const char *p;
+ int len;
+
+ assert (begin);
+ assert (end);
+ assert (param_name);
+ assert (param_value);
+
+ len = strlen (param_name);
+
+ /* skip initial whitespaces */
+ p = begin;
+ while (*p && ISSPACE (*p) && p < end) ++p;
+
+ if (end - p > len
+ && 0 == strncasecmp (p, param_name, len))
+ {
+ const char *e;
+
+ /* skip white spaces, equal sign and inital quote */
+ p += len;
+ while (*p && (ISSPACE (*p) || *p == '\"' || *p == '=') && p < end) ++p;
+
+ /* find last quote */
+ e = p;
+ while (*e && *e != '\"' && e < end) ++e;
+
+ *param_value = strdupdelim (p, e);
+
+ return true;
+ }
+
+ return false;
+}
+
+/* Parse the `Content-Disposition' header and extract the information it
+ contains. Returns true if successful, false otherwise. */
+static bool
+parse_content_disposition (const char *hdrval, char **filename)
+{
+ const char *b = hdrval; /* b - begin */
+ const char *e = hdrval; /* e - end */
+
+ assert (hdrval);
+ assert (filename);
+
+ for (; *e; ++e)
+ {
+ if (*e == ';'
+ && e > b)
+ {
+ /* process chars b->e-1 */
+ if (true == extract_param_value_delim (b, e - 1, "filename", filename))
+ return true;
+
+ b = e + 1;
+ }
+ }
+
+ if (b != e)
+ {
+ /* process chars b->e */
+ if (true == extract_param_value_delim (b, e, "filename", filename))
+ return true;
+ }
+
+ return false;
+}
\f
/* Persistent connections. Currently, we cache the most recently used
connection as persistent, provided that the HTTP server agrees to
bool host_lookup_failed = false;
- DEBUGP(("in gethttp 1\n"));
-
#ifdef HAVE_SSL
if (u->scheme == SCHEME_HTTPS)
{
}
#endif /* HAVE_SSL */
- DEBUGP(("in gethttp 2\n"));
- DEBUGP(("in gethttp 3\n"));
-
/* Initialize certain elements of struct http_stat. */
hs->len = 0;
hs->contlen = -1;
print_server_response (resp, " ");
}
- DEBUGP(("in gethttp 4\n"));
-
/* Determine the local filename if needed. Notice that if -O is used
* hstat.local_file is set by http_loop to the argument of -O. */
if (!hs->local_file)
{
- if (resp_header_copy (resp, "Content-Disposition", hdrval, sizeof (hdrval)))
- /* Honor Content-Disposition. */
- {
- hs->local_file = xstrdup (hdrval);
- }
- else
- /* Choose filename according to URL name. */
+ /* Honor Content-Disposition whether possible. */
+ if (!resp_header_copy (resp, "Content-Disposition", hdrval, sizeof (hdrval))
+ || false == parse_content_disposition (hdrval, &hs->local_file))
{
+ /* Choose filename according to URL name. */
hs->local_file = url_file_name (u);
}
}
- DEBUGP(("in gethttp 5\n"));
-
/* TODO: perform this check only once. */
if (opt.noclobber && file_exists_p (hs->local_file))
{
return RETRFINISHED;
}
+ /* Print fetch message, if opt.verbose. */
+ if (opt.verbose)
+ {
+ logprintf (LOG_NOTQUIET, _("Saving to: `%s'\n"),
+ HYPHENP (hs->local_file) ? "STDOUT" : hs->local_file);
+ }
+
/* Open the local file. */
if (!output_stream)
{
struct http_stat hstat; /* HTTP status */
struct_stat st;
- DEBUGP(("in http_loop\n"));
-
/* Assert that no value for *LOCAL_FILE was passed. */
assert (local_file == NULL || *local_file == NULL);
/* THE loop */
do
{
- DEBUGP(("in http_loop LOOP\n"));
-
/* Increment the pass counter. */
++count;
sleep_between_retrievals (count);
if (opt.verbose)
{
char *hurl = url_string (u, true);
- char tmp[256];
- strcpy (tmp, " ");
- if (count > 1)
- sprintf (tmp, _("(try:%2d)"), count);
- logprintf (LOG_VERBOSE, "--%s-- %s\n %s\n",
- tms, hurl, tmp);
+
+ if (count > 1)
+ {
+ char tmp[256];
+ sprintf (tmp, _("(try:%2d)"), count);
+ logprintf (LOG_NOTQUIET, "--%s-- %s %s\n",
+ tms, tmp, hurl);
+ }
+ else
+ {
+ logprintf (LOG_NOTQUIET, "--%s-- %s\n",
+ tms, hurl);
+ }
+
#ifdef WINDOWS
ws_changetitle (hurl);
#endif
/* Non-fatal errors continue executing the loop, which will
bring them to "while" statement at the end, to judge
whether the number of tries was exceeded. */
- //free_hstat (&hstat);
+ /* free_hstat (&hstat); */
printwhat (count, opt.ntry);
continue;
case HOSTERR: case CONIMPOSSIBLE: case PROXERR: case AUTHFAILED:
else
logputs (LOG_VERBOSE,
_("Remote file is newer, retrieving.\n"));
+
+ logputs (LOG_VERBOSE, "\n");
}
- //free_hstat (&hstat);
+ /* free_hstat (&hstat); */
hstat.timestamp_checked = true;
continue;
}
_("%s (%s) - Connection closed at byte %s. "),
tms, tmrate, number_to_static_string (hstat.len));
printwhat (count, opt.ntry);
- //free_hstat (&hstat);
+ /* free_hstat (&hstat); */
continue;
}
else
tms, tmrate, number_to_static_string (hstat.len),
hstat.rderrmsg);
printwhat (count, opt.ntry);
- //free_hstat (&hstat);
+ /* free_hstat (&hstat); */
continue;
}
else /* hstat.res == -1 and contlen is given */
number_to_static_string (hstat.contlen),
hstat.rderrmsg);
printwhat (count, opt.ntry);
- //free_hstat (&hstat);
+ /* free_hstat (&hstat); */
continue;
}
}
cookie_jar_delete (wget_cookie_jar);
}
+
+#ifdef TESTING
+
+char *
+test_parse_content_disposition()
+{
+ int i;
+ struct {
+ char *hdrval;
+ char *filename;
+ bool result;
+ } test_array[] = {
+ { "filename=\"file.ext\"", "file.ext", true },
+ { "attachment; filename=\"file.ext\"", "file.ext", true },
+ { "attachment; filename=\"file.ext\"; dummy", "file.ext", true },
+ { "attachment", NULL, false },
+ };
+
+ for (i = 0; i < sizeof(test_array)/sizeof(test_array[0]); ++i)
+ {
+ char *filename;
+ bool res = parse_content_disposition (test_array[i].hdrval, &filename);
+
+ mu_assert ("test_parse_content_disposition: wrong result",
+ res == test_array[i].result
+ && (res == false
+ || 0 == strcmp (test_array[i].filename, filename)));
+
+ /* printf ("test %d: %s\n", i, res == false ? "false" : filename); */
+ }
+
+ return NULL;
+}
+
+#endif /* TESTING */
+
/*
* vim: et ts=2 sw=2
*/