mirror of
https://github.com/moparisthebest/wget
synced 2024-07-03 16:38:41 -04:00
[svn] Implement correct parsing of HTTP Content-Disposition header.
This commit is contained in:
parent
b89b58e00a
commit
d8f368d062
@ -1,3 +1,10 @@
|
||||
2006-02-03 Mauro Tortonesi <mauro@ferrara.linux.it>
|
||||
|
||||
* http.c: Fixed support for Content-Disposition header.
|
||||
|
||||
* test.c: Added test_parse_content_disposition to the list of unit
|
||||
tests to run.
|
||||
|
||||
2006-02-02 Hrvoje Niksic <hniksic@xemacs.org>
|
||||
|
||||
* hash.c: Don't define countof if it's already defined.
|
||||
|
124
src/http.c
124
src/http.c
@ -60,6 +60,10 @@ so, delete this exception statement from your version. */
|
||||
#endif
|
||||
#include "convert.h"
|
||||
|
||||
#ifdef TESTING
|
||||
#include "test.h"
|
||||
#endif
|
||||
|
||||
extern char *version_string;
|
||||
|
||||
#ifndef MIN
|
||||
@ -850,6 +854,79 @@ skip_short_body (int fd, wgint contlen)
|
||||
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;
|
||||
}
|
||||
|
||||
/* Persistent connections. Currently, we cache the most recently used
|
||||
connection as persistent, provided that the HTTP server agrees to
|
||||
@ -1608,14 +1685,11 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy)
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
@ -2896,6 +2970,42 @@ http_cleanup (void)
|
||||
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
|
||||
*/
|
||||
|
@ -37,12 +37,10 @@ so, delete this exception statement from your version. */
|
||||
|
||||
int tests_run;
|
||||
|
||||
/* char *test_ccache(); */
|
||||
|
||||
static char *
|
||||
all_tests()
|
||||
{
|
||||
/* mu_run_test (test_ccache); */
|
||||
mu_run_test (test_parse_content_disposition);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user