mirror of
https://github.com/mirror/wget.git
synced 2025-03-07 00:00:20 +08: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>
|
2006-02-02 Hrvoje Niksic <hniksic@xemacs.org>
|
||||||
|
|
||||||
* hash.c: Don't define countof if it's already defined.
|
* hash.c: Don't define countof if it's already defined.
|
||||||
|
122
src/http.c
122
src/http.c
@ -60,6 +60,10 @@ so, delete this exception statement from your version. */
|
|||||||
#endif
|
#endif
|
||||||
#include "convert.h"
|
#include "convert.h"
|
||||||
|
|
||||||
|
#ifdef TESTING
|
||||||
|
#include "test.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
extern char *version_string;
|
extern char *version_string;
|
||||||
|
|
||||||
#ifndef MIN
|
#ifndef MIN
|
||||||
@ -850,6 +854,79 @@ skip_short_body (int fd, wgint contlen)
|
|||||||
DEBUGP (("] done.\n"));
|
DEBUGP (("] done.\n"));
|
||||||
return true;
|
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
|
/* Persistent connections. Currently, we cache the most recently used
|
||||||
connection as persistent, provided that the HTTP server agrees to
|
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. */
|
* hstat.local_file is set by http_loop to the argument of -O. */
|
||||||
if (!hs->local_file)
|
if (!hs->local_file)
|
||||||
{
|
{
|
||||||
if (resp_header_copy (resp, "Content-Disposition", hdrval, sizeof (hdrval)))
|
/* Honor Content-Disposition whether possible. */
|
||||||
/* Honor Content-Disposition. */
|
if (!resp_header_copy (resp, "Content-Disposition", hdrval, sizeof (hdrval))
|
||||||
|
|| false == parse_content_disposition (hdrval, &hs->local_file))
|
||||||
{
|
{
|
||||||
hs->local_file = xstrdup (hdrval);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
/* Choose filename according to URL name. */
|
/* Choose filename according to URL name. */
|
||||||
{
|
|
||||||
hs->local_file = url_file_name (u);
|
hs->local_file = url_file_name (u);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2896,6 +2970,42 @@ http_cleanup (void)
|
|||||||
cookie_jar_delete (wget_cookie_jar);
|
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
|
* vim: et ts=2 sw=2
|
||||||
*/
|
*/
|
||||||
|
@ -37,12 +37,10 @@ so, delete this exception statement from your version. */
|
|||||||
|
|
||||||
int tests_run;
|
int tests_run;
|
||||||
|
|
||||||
/* char *test_ccache(); */
|
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
all_tests()
|
all_tests()
|
||||||
{
|
{
|
||||||
/* mu_run_test (test_ccache); */
|
mu_run_test (test_parse_content_disposition);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user