[httpd] Fix parsing of uri into path parts with encoded '/' (%2F)
In path with an encoded '/' character, the parsing of the path into parts was wrong. E. g. an uri like '/api/library/composers/Adam%20Gardner%2FDavid%20Schneider' would result in the following parts: - path_part[0] = "/api" - path_part[1] = "library" - path_part[2] = "composer" - path_part[3] = "Adam Gardner" - path_part[4] = "David Schneider" Doing the decode after splitting the uri into parts fixes this and results in: - path_part[0] = "api" - path_part[1] = "library" - path_part[2] = "composer" - path_part[3] = "Adam Gardner/David Schneider"
This commit is contained in:
parent
a932cc532d
commit
b18b76413d
29
src/httpd.c
29
src/httpd.c
|
@ -883,12 +883,17 @@ httpd_gen_cb(struct evhttp_request *req, void *arg)
|
|||
void
|
||||
httpd_uri_free(struct httpd_uri_parsed *parsed)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!parsed)
|
||||
return;
|
||||
|
||||
free(parsed->uri_decoded);
|
||||
free(parsed->path);
|
||||
free(parsed->path_parts[0]);
|
||||
for (i = 0; i < ARRAY_SIZE(parsed->path_parts); i++)
|
||||
{
|
||||
free(parsed->path_parts[i]);
|
||||
}
|
||||
|
||||
evhttp_clear_headers(&(parsed->ev_query));
|
||||
|
||||
|
@ -902,8 +907,9 @@ struct httpd_uri_parsed *
|
|||
httpd_uri_parse(const char *uri)
|
||||
{
|
||||
struct httpd_uri_parsed *parsed;
|
||||
const char *path;
|
||||
char *path = NULL;
|
||||
const char *query;
|
||||
char *path_part;
|
||||
char *ptr;
|
||||
int i;
|
||||
int ret;
|
||||
|
@ -937,7 +943,7 @@ httpd_uri_parse(const char *uri)
|
|||
}
|
||||
}
|
||||
|
||||
path = evhttp_uri_get_path(parsed->ev_uri);
|
||||
path = strdup(evhttp_uri_get_path(parsed->ev_uri));
|
||||
if (!path)
|
||||
{
|
||||
DPRINTF(E_WARN, L_HTTPD, "No path in request: '%s'\n", parsed->uri);
|
||||
|
@ -951,23 +957,26 @@ httpd_uri_parse(const char *uri)
|
|||
goto error;
|
||||
}
|
||||
|
||||
CHECK_NULL(L_HTTPD, parsed->path_parts[0] = strdup(parsed->path));
|
||||
|
||||
strtok_r(parsed->path_parts[0], "/", &ptr);
|
||||
for (i = 1; (i < sizeof(parsed->path_parts) / sizeof(parsed->path_parts[0])) && parsed->path_parts[i - 1]; i++)
|
||||
path_part = strtok_r(path, "/", &ptr);
|
||||
for (i = 0; (i < ARRAY_SIZE(parsed->path_parts) && path_part); i++)
|
||||
{
|
||||
parsed->path_parts[i] = strtok_r(NULL, "/", &ptr);
|
||||
parsed->path_parts[i] = evhttp_uridecode(path_part, 0, NULL);
|
||||
path_part = strtok_r(NULL, "/", &ptr);
|
||||
}
|
||||
|
||||
if (!parsed->path_parts[0] || parsed->path_parts[i - 1] || (i < 2))
|
||||
if (path_part)
|
||||
{
|
||||
DPRINTF(E_LOG, L_HTTPD, "URI path has too many/few components (%d): '%s'\n", (parsed->path_parts[0]) ? i : 0, parsed->path);
|
||||
// If "path_part" is not NULL, we have path tokens that could not be parsed into the "parsed->path_parts" array
|
||||
DPRINTF(E_LOG, L_HTTPD, "URI path has too many components (%d): '%s'\n", i, parsed->path);
|
||||
goto error;
|
||||
}
|
||||
|
||||
free(path);
|
||||
|
||||
return parsed;
|
||||
|
||||
error:
|
||||
free(path);
|
||||
httpd_uri_free(parsed);
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -23,10 +23,9 @@ enum httpd_send_flags
|
|||
*
|
||||
* We are interested in the path and the query, so they are disassembled to
|
||||
* path_parts and ev_query. If the request is http://x:3689/foo/bar?key1=val1,
|
||||
* then part_parts[1] is "foo", [2] is "bar" and the rest is null (the first
|
||||
* element points to the copy of the path so it can be freed).
|
||||
* then part_parts[0] is "foo", [1] is "bar" and the rest is null.
|
||||
*
|
||||
* The allocated strings are URI decoded.
|
||||
* Each path_part is an allocated URI decoded string.
|
||||
*/
|
||||
struct httpd_uri_parsed
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue