mirror of
https://github.com/owntone/owntone-server.git
synced 2024-12-26 23:25:56 -05:00
Implement URI encoding quirk for iTunes and Roku
iTunes and Roku devices do not encode + as %2B in the query string and do not encode space as + either in the query string (though at least the Roku encode space as %20 everywhere). This needs to be worked around or browse queries fail to parse because + was decoded as space when the query really needs a + character.
This commit is contained in:
parent
09ef188d90
commit
c9868175fd
88
src/httpd.c
88
src/httpd.c
@ -49,15 +49,19 @@
|
||||
/*
|
||||
* HTTP client quirks by User-Agent, from mt-daapd
|
||||
*
|
||||
* - Roku:
|
||||
* + Does not encode space as + in query string
|
||||
* - iTunes:
|
||||
* + Does not encode space as + in query string
|
||||
* + Connection: Keep-Alive on HTTP error 401
|
||||
* - Hifidelio:
|
||||
* + Connection: Keep-Alive for streaming (Connection: close not honoured)
|
||||
*
|
||||
* These quirks are not implemented. Implement as needed.
|
||||
*
|
||||
* Implemented quirks:
|
||||
*
|
||||
* - Roku:
|
||||
* + Does not encode space as + in query string
|
||||
* - iTunes:
|
||||
* + Does not encode space as + in query string
|
||||
*/
|
||||
|
||||
|
||||
@ -715,6 +719,84 @@ exit_cb(int fd, short event, void *arg)
|
||||
httpd_exit = 1;
|
||||
}
|
||||
|
||||
char *
|
||||
httpd_fixup_uri(struct evhttp_request *req)
|
||||
{
|
||||
const char *ua;
|
||||
const char *uri;
|
||||
const char *u;
|
||||
const char *q;
|
||||
char *fixed;
|
||||
char *f;
|
||||
int len;
|
||||
|
||||
uri = evhttp_request_uri(req);
|
||||
if (!uri)
|
||||
return NULL;
|
||||
|
||||
/* No query string, nothing to do */
|
||||
q = strchr(uri, '?');
|
||||
if (!q)
|
||||
return strdup(uri);
|
||||
|
||||
ua = evhttp_find_header(req->input_headers, "User-Agent");
|
||||
if (!ua)
|
||||
return strdup(uri);
|
||||
|
||||
if ((strncmp(ua, "iTunes", strlen("iTunes")) != 0)
|
||||
&& (strncmp(ua, "Roku", strlen("Roku")) != 0))
|
||||
return strdup(uri);
|
||||
|
||||
/* Reencode + as %2B and space as + in the query,
|
||||
which iTunes and Roku devices don't do */
|
||||
len = strlen(uri);
|
||||
|
||||
u = q;
|
||||
while (*u)
|
||||
{
|
||||
if (*u == '+')
|
||||
len += 2;
|
||||
|
||||
u++;
|
||||
}
|
||||
|
||||
fixed = (char *)malloc(len + 1);
|
||||
if (!fixed)
|
||||
return NULL;
|
||||
|
||||
strncpy(fixed, uri, q - uri);
|
||||
|
||||
f = fixed + (q - uri);
|
||||
while (*q)
|
||||
{
|
||||
switch (*q)
|
||||
{
|
||||
case '+':
|
||||
*f = '%';
|
||||
f++;
|
||||
*f = '2';
|
||||
f++;
|
||||
*f = 'B';
|
||||
break;
|
||||
|
||||
case ' ':
|
||||
*f = '+';
|
||||
break;
|
||||
|
||||
default:
|
||||
*f = *q;
|
||||
break;
|
||||
}
|
||||
|
||||
q++;
|
||||
f++;
|
||||
}
|
||||
|
||||
*f = '\0';
|
||||
|
||||
return fixed;
|
||||
}
|
||||
|
||||
static char *http_reply_401 = "<html><head><title>401 Unauthorized</title></head><body>Authorization required</body></html>";
|
||||
|
||||
int
|
||||
|
@ -9,6 +9,9 @@
|
||||
void
|
||||
httpd_stream_file(struct evhttp_request *req, int id);
|
||||
|
||||
char *
|
||||
httpd_fixup_uri(struct evhttp_request *req);
|
||||
|
||||
int
|
||||
httpd_basic_auth(struct evhttp_request *req, char *user, char *passwd, char *realm);
|
||||
|
||||
|
@ -1782,7 +1782,6 @@ static struct uri_map daap_handlers[] =
|
||||
void
|
||||
daap_request(struct evhttp_request *req)
|
||||
{
|
||||
const char *req_uri;
|
||||
char *full_uri;
|
||||
char *uri;
|
||||
char *ptr;
|
||||
@ -1796,23 +1795,27 @@ daap_request(struct evhttp_request *req)
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
req_uri = evhttp_request_uri(req);
|
||||
|
||||
full_uri = strdup(req_uri);
|
||||
full_uri = httpd_fixup_uri(req);
|
||||
if (!full_uri)
|
||||
{
|
||||
evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||
return;
|
||||
}
|
||||
|
||||
ptr = strchr(full_uri, '?');
|
||||
if (ptr)
|
||||
*ptr = '\0';
|
||||
|
||||
uri = strdup(full_uri);
|
||||
if (!uri)
|
||||
{
|
||||
evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||
return;
|
||||
}
|
||||
|
||||
if (ptr)
|
||||
*ptr = '?';
|
||||
|
||||
ptr = full_uri;
|
||||
full_uri = evhttp_decode_uri(full_uri);
|
||||
free(ptr);
|
||||
|
||||
ptr = uri;
|
||||
uri = evhttp_decode_uri(uri);
|
||||
free(ptr);
|
||||
|
@ -897,7 +897,6 @@ static struct uri_map rsp_handlers[] =
|
||||
void
|
||||
rsp_request(struct evhttp_request *req)
|
||||
{
|
||||
const char *req_uri;
|
||||
char *full_uri;
|
||||
char *uri;
|
||||
char *ptr;
|
||||
@ -910,23 +909,27 @@ rsp_request(struct evhttp_request *req)
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
req_uri = evhttp_request_uri(req);
|
||||
|
||||
full_uri = strdup(req_uri);
|
||||
full_uri = httpd_fixup_uri(req);
|
||||
if (!full_uri)
|
||||
{
|
||||
rsp_send_error(req, "Server error");
|
||||
return;
|
||||
}
|
||||
|
||||
ptr = strchr(full_uri, '?');
|
||||
if (ptr)
|
||||
*ptr = '\0';
|
||||
|
||||
uri = strdup(full_uri);
|
||||
if (!uri)
|
||||
{
|
||||
rsp_send_error(req, "Server error");
|
||||
return;
|
||||
}
|
||||
|
||||
if (ptr)
|
||||
*ptr = '?';
|
||||
|
||||
ptr = full_uri;
|
||||
full_uri = evhttp_decode_uri(full_uri);
|
||||
free(ptr);
|
||||
|
||||
ptr = uri;
|
||||
uri = evhttp_decode_uri(uri);
|
||||
free(ptr);
|
||||
|
Loading…
Reference in New Issue
Block a user