Skip to content

Commit 221400c

Browse files
enricolorenzoni59Flole998
authored andcommitted
iptv: handle relative key URL
1 parent 0327265 commit 221400c

1 file changed

Lines changed: 72 additions & 1 deletion

File tree

‎src/input/mpegts/iptv/iptv_http.c‎

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,69 @@ iptv_http_reconnect ( http_client_t *hc, const char *url )
347347
urlreset(&u);
348348
}
349349

350+
/*
351+
* Return the index of the last occurrence of character `x` in string `s`
352+
*/
353+
static
354+
int last_index_of(const char *s, char x) {
355+
int i;
356+
int len = strlen(s);
357+
assert(s != NULL);
358+
for (i = len - 1; i >= 0; i--) {
359+
if (s[i] == x) {
360+
return i;
361+
}
362+
}
363+
return -1; // x not found
364+
}
365+
366+
/*
367+
* Allocates a string with the absolute URL obtained by merging the absolute base and the relative URLs
368+
*/
369+
static char * merge_absolute_and_relative_urls(const char * absolute_url, const char * relative_url) {
370+
size_t absoute_key_url_len, last_slash_pos;
371+
char * absolute_key_url;
372+
const unsigned int max_levels = 100;
373+
int i;
374+
375+
// allocate enough memory to contain `s` + `url` + \0
376+
absoute_key_url_len = strlen(absolute_url) + strlen(relative_url) + 1;
377+
absolute_key_url = (char*)malloc(absoute_key_url_len);
378+
memset(absolute_key_url, 0, absoute_key_url_len);
379+
380+
// copy the url up to the last /
381+
// http://test/ab/cd becomes http://test/ab/
382+
last_slash_pos = last_index_of(absolute_url, '/');
383+
assert(last_slash_pos < absoute_key_url_len);
384+
assert(last_slash_pos > 0);
385+
memcpy(absolute_key_url, absolute_url, last_slash_pos+1);
386+
387+
for (i = 0; i < max_levels && (strncmp(relative_url, "../", strlen("../")) == 0); i++) {
388+
// skip `../` in relative_url
389+
relative_url = relative_url + 3;
390+
391+
// replace the last / with \0
392+
// http://test/ab/ becomes http://test/ab
393+
last_slash_pos = last_index_of(absolute_key_url, '/');
394+
assert(last_slash_pos < absoute_key_url_len);
395+
assert(last_slash_pos > 0);
396+
absolute_key_url[last_slash_pos] = 0;
397+
398+
// keep until the remaining /
399+
// http://test/ab becomes http://test/
400+
last_slash_pos = last_index_of(absolute_key_url, '/');
401+
assert(last_slash_pos < absoute_key_url_len);
402+
assert(last_slash_pos > 0);
403+
absolute_key_url[last_slash_pos+1] = 0;
404+
}
405+
406+
// concat `s` to the base URL
407+
assert(strlen(absolute_key_url) + strlen(relative_url) < absoute_key_url_len);
408+
memcpy(absolute_key_url+strlen(absolute_key_url), relative_url, strlen(relative_url)+1);
409+
410+
return absolute_key_url;
411+
}
412+
350413
static int
351414
iptv_http_complete
352415
( http_client_t *hc )
@@ -356,6 +419,7 @@ iptv_http_complete
356419
char *url;
357420
htsmsg_t *m, *m2;
358421
int r;
422+
char * absolute_key_url = NULL;
359423

360424
if (hp == NULL || hp->shutdown || hp->im == NULL)
361425
return 0;
@@ -396,13 +460,20 @@ iptv_http_complete
396460
tvherror(LS_IPTV, "no URI in KEY attribute");
397461
goto end;
398462
}
463+
if (memcmp(s, "../", strlen("../")) == 0) {
464+
tvhtrace(LS_IPTV, "KEY URI: relative URL detected (%s), rewriting it", s);
465+
absolute_key_url = merge_absolute_and_relative_urls(url, s);
466+
s = absolute_key_url;
467+
tvhtrace(LS_IPTV, "new KEY URI: '%s'", s);
468+
}
399469
hp->hls_encrypted = 1;
400470
if (strcmp(hp->hls_key_url ?: "", s)) {
401471
free(hp->hls_key_url);
402472
hp->hls_key_url = strdup(s);
403473
free(hp->hls_url_after_key);
404474
hp->hls_url_after_key = url;
405-
url = strdup(s);
475+
url = strdup(s);
476+
free(absolute_key_url);
406477
hc->hc_data_complete = iptv_http_complete_key;
407478
sbuf_reset(&hp->key_sbuf, 32);
408479
}

0 commit comments

Comments
 (0)