From 7cb8fc2f23668ff1a4ffc9c5c9fcca23420ff096 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 23 Jun 2014 18:15:00 +0200 Subject: [PATCH] webui: when wget or curl is used, stream directly for /play handler --- src/http.c | 57 ++++++++++++++++++++++++++++++++++------------- src/http.h | 9 ++++++++ src/webui/webui.c | 15 ++++++++++++- 3 files changed, 65 insertions(+), 16 deletions(-) diff --git a/src/http.c b/src/http.c index 5932d8a9..0973ebba 100644 --- a/src/http.c +++ b/src/http.c @@ -94,8 +94,9 @@ static http_path_t * http_resolve(http_connection_t *hc, char **remainp, char **argsp) { http_path_t *hp; - int n = 0; + int n = 0, cut = 0; char *v, *path = tvh_strdupa(hc->hc_url); + char *npath; /* Canocalize path (or at least remove excess slashes) */ v = path; @@ -109,19 +110,35 @@ http_resolve(http_connection_t *hc, char **remainp, char **argsp) v++; } - LIST_FOREACH(hp, &http_paths, hp_link) { - if(!strncmp(path, hp->hp_path, hp->hp_len)) { - if(path[hp->hp_len] == 0 || - path[hp->hp_len] == '/' || - path[hp->hp_len] == '?') - break; - } - } - - if(hp == NULL) - return NULL; + while (1) { - v = hc->hc_url + n + hp->hp_len; + LIST_FOREACH(hp, &http_paths, hp_link) { + if(!strncmp(path, hp->hp_path, hp->hp_len)) { + if(path[hp->hp_len] == 0 || + path[hp->hp_len] == '/' || + path[hp->hp_len] == '?') + break; + } + } + + if(hp == NULL) + return NULL; + + cut += hp->hp_len; + + if(hp->hp_path_modify == NULL) + break; + + npath = hp->hp_path_modify(hc, path, &cut); + if(npath == NULL) + break; + + path = tvh_strdupa(npath); + free(npath); + + } + + v = hc->hc_url + n + cut; *remainp = NULL; *argsp = NULL; @@ -648,8 +665,8 @@ http_tokenize(char *buf, char **vec, int vecsize, int delimiter) * Add a callback for a given "virtual path" on our HTTP server */ http_path_t * -http_path_add(const char *path, void *opaque, http_callback_t *callback, - uint32_t accessmask) +http_path_add_modify(const char *path, void *opaque, http_callback_t *callback, + uint32_t accessmask, http_path_modify_t *path_modify) { http_path_t *hp = malloc(sizeof(http_path_t)); char *tmp; @@ -664,10 +681,20 @@ http_path_add(const char *path, void *opaque, http_callback_t *callback, hp->hp_opaque = opaque; hp->hp_callback = callback; hp->hp_accessmask = accessmask; + hp->hp_path_modify = path_modify; LIST_INSERT_HEAD(&http_paths, hp, hp_link); return hp; } +/** + * Add a callback for a given "virtual path" on our HTTP server + */ +http_path_t * +http_path_add(const char *path, void *opaque, http_callback_t *callback, + uint32_t accessmask) +{ + return http_path_add_modify(path, opaque, callback, accessmask, NULL); +} /** * De-escape HTTP URL diff --git a/src/http.h b/src/http.h index d80901ec..ee52cfac 100644 --- a/src/http.h +++ b/src/http.h @@ -177,6 +177,10 @@ void http_send_header(http_connection_t *hc, int rc, const char *content, typedef int (http_callback_t)(http_connection_t *hc, const char *remain, void *opaque); +typedef char * (http_path_modify_t)(http_connection_t *hc, + const char * path, int *cut); + + typedef struct http_path { LIST_ENTRY(http_path) hp_link; const char *hp_path; @@ -184,8 +188,13 @@ typedef struct http_path { http_callback_t *hp_callback; int hp_len; uint32_t hp_accessmask; + http_path_modify_t *hp_path_modify; } http_path_t; +http_path_t *http_path_add_modify(const char *path, void *opaque, + http_callback_t *callback, + uint32_t accessmask, + http_path_modify_t path_modify); http_path_t *http_path_add(const char *path, void *opaque, http_callback_t *callback, uint32_t accessmask); diff --git a/src/webui/webui.c b/src/webui/webui.c index 069bb05b..5cb1dc8c 100644 --- a/src/webui/webui.c +++ b/src/webui/webui.c @@ -984,6 +984,19 @@ http://%s/%s\r\n", title, host, remain); return 0; } +static char * +page_play_path_modify(http_connection_t *hc, const char *path, int *cut) +{ + /* + * For curl and wget do not set the playlist, stream directly + */ + const char *agent = http_arg_get(&hc->hc_args, "User-Agent"); + if (strncasecmp(agent, "curl/", 5) == 0 || + strncasecmp(agent, "wget/", 5) == 0) + return strdup(path + 5); + return NULL; +} + static int page_play(http_connection_t *hc, const char *remain, void *opaque) { @@ -1204,7 +1217,7 @@ webui_init(int xspf) http_path_add("", NULL, page_root2, ACCESS_WEB_INTERFACE); http_path_add("/", NULL, page_root, ACCESS_WEB_INTERFACE); - http_path_add("/play", NULL, page_play, ACCESS_WEB_INTERFACE); + http_path_add_modify("/play", NULL, page_play, ACCESS_WEB_INTERFACE, page_play_path_modify); http_path_add("/dvrfile", NULL, page_dvrfile, ACCESS_WEB_INTERFACE); http_path_add("/favicon.ico", NULL, favicon, ACCESS_WEB_INTERFACE); http_path_add("/playlist", NULL, page_http_playlist, ACCESS_WEB_INTERFACE);