From 024aadfe0a3f3352549753f6b924a45502b23314 Mon Sep 17 00:00:00 2001 From: ejurgensen Date: Wed, 1 Jan 2025 15:41:21 +0100 Subject: [PATCH] [http] Support for extracting artwork url from within StreamUrl field --- src/http.c | 36 ++++++++++++++++++++++++++++++++++++ src/http.h | 8 ++++++++ src/inputs/http.c | 21 +++++++++++++++++++-- 3 files changed, 63 insertions(+), 2 deletions(-) diff --git a/src/http.c b/src/http.c index 6a1604d4..efb34080 100644 --- a/src/http.c +++ b/src/http.c @@ -36,6 +36,7 @@ #include #include +#include #include @@ -193,6 +194,41 @@ http_client_request(struct http_client_ctx *ctx, struct http_client_session *ses return 0; } +int +http_form_urldecode(struct keyval *kv, const char *uri) +{ + struct evhttp_uri *ev_uri = NULL; + struct evkeyvalq ev_query = { 0 }; + struct evkeyval *param; + const char *query; + int ret; + + ev_uri = evhttp_uri_parse_with_flags(uri, EVHTTP_URI_NONCONFORMANT); + if (!ev_uri) + return -1; + + query = evhttp_uri_get_query(ev_uri); + if (!query) + goto error; + + ret = evhttp_parse_query_str(query, &ev_query); + if (ret < 0) + goto error; + + // musl libc doesn't have sys/queue.h so don't use TAILQ_FOREACH + for (param = ev_query.tqh_first; param; param = param->next.tqe_next) + keyval_add(kv, param->key, param->value); + + evhttp_uri_free(ev_uri); + evhttp_clear_headers(&ev_query); + return 0; + + error: + evhttp_uri_free(ev_uri); + evhttp_clear_headers(&ev_query); + return -1; +} + char * http_form_urlencode(struct keyval *kv) { diff --git a/src/http.h b/src/http.h index 755f3848..a68c5d97 100644 --- a/src/http.h +++ b/src/http.h @@ -86,6 +86,14 @@ http_client_request(struct http_client_ctx *ctx, struct http_client_session *ses char * http_form_urlencode(struct keyval *kv); +/* The reverse of http_form_urlencode, except takes a full url as input. + * + * @param kv keyval struct allocated by caller where values will be added + * @param url with the query to decode + * @return 0 if ok, otherwise -1 + */ +int +http_form_urldecode(struct keyval *kv, const char *uri); /* Returns a newly allocated string with the first stream in the m3u given in * url. If url is not a m3u, the string will be a copy of url. diff --git a/src/inputs/http.c b/src/inputs/http.c index 5a671b54..a50e48fc 100644 --- a/src/inputs/http.c +++ b/src/inputs/http.c @@ -173,8 +173,9 @@ streamurl_process(struct input_metadata *metadata, const char *url) { struct http_client_ctx client = { 0 }; struct keyval kv = { 0 }; - struct evbuffer *evbuf; + struct evbuffer *evbuf = NULL; const char *content_type; + const char *artwork_url; char *body; int ret; @@ -186,6 +187,21 @@ streamurl_process(struct input_metadata *metadata, const char *url) return -1; } + // If the StreamUrl contains a keyword followed by the actual url, e.g. http://metadata.cdnstream1.com/?yadayada&ALBUM_ART=https%3A%2F%2Fis1-ssl.mzstatic.com%2Fimage%2Fthumb%2FMusic%2F11%2Fcc%2F21%2Fmzi.nepwiuir.jpg + if (streamurl_map[0].words) + { + ret = http_form_urldecode(&kv, url); + if (ret < 0) + return -1; + + artwork_url = keyval_get(&kv, streamurl_map[0].words); + metadata->artwork_url = safe_strdup(artwork_url); + keyval_clear(&kv); + + if (metadata->artwork_url) + goto out; + } + DPRINTF(E_DBG, L_PLAYER, "Downloading StreamUrl resource '%s'\n", url); CHECK_NULL(L_PLAYER, evbuf = evbuffer_new()); @@ -219,7 +235,8 @@ streamurl_process(struct input_metadata *metadata, const char *url) out: keyval_clear(&kv); - evbuffer_free(evbuf); + if (evbuf) + evbuffer_free(evbuf); streamurl_settings_unload(); return ret; }