souphttpsrc: Handle non-UTF8 headers and error reasons more gracefully

Especially don't put them into GstStructures in one way or another, just
ignore them or error out cleanly depending on the importance of their
content.
This commit is contained in:
Sebastian Dröge 2016-11-28 12:00:09 +02:00
parent d0f608f60b
commit 37f991f06e

View File

@ -988,6 +988,9 @@ insert_http_header (const gchar * name, const gchar * value, gpointer user_data)
GstStructure *headers = user_data; GstStructure *headers = user_data;
const GValue *gv; const GValue *gv;
if (!g_utf8_validate (name, -1, NULL) || !g_utf8_validate (value, -1, NULL))
return;
gv = gst_structure_get_value (headers, name); gv = gst_structure_get_value (headers, name);
if (gv && GST_VALUE_HOLDS_ARRAY (gv)) { if (gv && GST_VALUE_HOLDS_ARRAY (gv)) {
GValue v = G_VALUE_INIT; GValue v = G_VALUE_INIT;
@ -1035,14 +1038,31 @@ gst_soup_http_src_got_headers (GstSoupHTTPSrc * src, SoupMessage * msg)
return; return;
if (src->automatic_redirect && SOUP_STATUS_IS_REDIRECTION (msg->status_code)) { if (src->automatic_redirect && SOUP_STATUS_IS_REDIRECTION (msg->status_code)) {
src->redirection_uri = g_strdup (soup_message_headers_get_one const gchar *location;
(msg->response_headers, "Location"));
location = soup_message_headers_get_one (msg->response_headers, "Location");
if (location) {
if (!g_utf8_validate (location, -1, NULL)) {
GST_ELEMENT_ERROR_WITH_DETAILS (src, RESOURCE, SEEK,
(_("Corrupted HTTP response.")),
("Location header is not valid UTF-8"),
("http-status-code", G_TYPE_UINT, msg->status_code,
"http-redirection-uri", G_TYPE_STRING,
GST_STR_NULL (src->redirection_uri), NULL));
src->ret = GST_FLOW_ERROR;
return;
}
src->redirection_uri = g_strdup (location);
src->redirection_permanent = src->redirection_permanent =
(msg->status_code == SOUP_STATUS_MOVED_PERMANENTLY); (msg->status_code == SOUP_STATUS_MOVED_PERMANENTLY);
GST_DEBUG_OBJECT (src, "%u redirect to \"%s\" (permanent %d)", GST_DEBUG_OBJECT (src, "%u redirect to \"%s\" (permanent %d)",
msg->status_code, src->redirection_uri, src->redirection_permanent); msg->status_code, src->redirection_uri, src->redirection_permanent);
return; return;
} }
}
if (msg->status_code == SOUP_STATUS_UNAUTHORIZED) { if (msg->status_code == SOUP_STATUS_UNAUTHORIZED) {
/* force an error */ /* force an error */
@ -1110,9 +1130,13 @@ gst_soup_http_src_got_headers (GstSoupHTTPSrc * src, SoupMessage * msg)
if ((value = if ((value =
soup_message_headers_get_one (msg->response_headers, soup_message_headers_get_one (msg->response_headers,
"icy-metaint")) != NULL) { "icy-metaint")) != NULL) {
gint icy_metaint = atoi (value); gint icy_metaint;
GST_DEBUG_OBJECT (src, "icy-metaint: %s (parsed: %d)", value, icy_metaint); if (g_utf8_validate (value, -1, NULL)) {
icy_metaint = atoi (value);
GST_DEBUG_OBJECT (src, "icy-metaint: %s (parsed: %d)", value,
icy_metaint);
if (icy_metaint > 0) { if (icy_metaint > 0) {
if (src->src_caps) if (src->src_caps)
gst_caps_unref (src->src_caps); gst_caps_unref (src->src_caps);
@ -1123,33 +1147,53 @@ gst_soup_http_src_got_headers (GstSoupHTTPSrc * src, SoupMessage * msg)
gst_base_src_set_caps (GST_BASE_SRC (src), src->src_caps); gst_base_src_set_caps (GST_BASE_SRC (src), src->src_caps);
} }
} }
}
if ((value = if ((value =
soup_message_headers_get_content_type (msg->response_headers, soup_message_headers_get_content_type (msg->response_headers,
&params)) != NULL) { &params)) != NULL) {
GST_DEBUG_OBJECT (src, "Content-Type: %s", value); if (!g_utf8_validate (value, -1, NULL)) {
if (g_ascii_strcasecmp (value, "audio/L16") == 0) { GST_WARNING_OBJECT (src, "Content-Type is invalid UTF-8");
} else if (g_ascii_strcasecmp (value, "audio/L16") == 0) {
gint channels = 2; gint channels = 2;
gint rate = 44100; gint rate = 44100;
char *param; char *param;
if (src->src_caps) GST_DEBUG_OBJECT (src, "Content-Type: %s", value);
if (src->src_caps) {
gst_caps_unref (src->src_caps); gst_caps_unref (src->src_caps);
src->src_caps = NULL;
}
param = g_hash_table_lookup (params, "channels"); param = g_hash_table_lookup (params, "channels");
if (param != NULL) if (param != NULL) {
channels = atol (param); guint64 val = g_ascii_strtoull (param, NULL, 10);
if (val < 64)
channels = val;
else
channels = 0;
}
param = g_hash_table_lookup (params, "rate"); param = g_hash_table_lookup (params, "rate");
if (param != NULL) if (param != NULL) {
rate = atol (param); guint64 val = g_ascii_strtoull (param, NULL, 10);
if (val < G_MAXINT)
rate = val;
else
rate = 0;
}
if (rate > 0 && channels > 0) {
src->src_caps = gst_caps_new_simple ("audio/x-unaligned-raw", src->src_caps = gst_caps_new_simple ("audio/x-unaligned-raw",
"format", G_TYPE_STRING, "S16BE", "format", G_TYPE_STRING, "S16BE",
"layout", G_TYPE_STRING, "interleaved", "layout", G_TYPE_STRING, "interleaved",
"channels", G_TYPE_INT, channels, "rate", G_TYPE_INT, rate, NULL); "channels", G_TYPE_INT, channels, "rate", G_TYPE_INT, rate, NULL);
gst_base_src_set_caps (GST_BASE_SRC (src), src->src_caps); gst_base_src_set_caps (GST_BASE_SRC (src), src->src_caps);
}
} else { } else {
GST_DEBUG_OBJECT (src, "Content-Type: %s", value);
/* Set the Content-Type field on the caps */ /* Set the Content-Type field on the caps */
if (src->src_caps) { if (src->src_caps) {
src->src_caps = gst_caps_make_writable (src->src_caps); src->src_caps = gst_caps_make_writable (src->src_caps);
@ -1166,6 +1210,7 @@ gst_soup_http_src_got_headers (GstSoupHTTPSrc * src, SoupMessage * msg)
if ((value = if ((value =
soup_message_headers_get_one (msg->response_headers, soup_message_headers_get_one (msg->response_headers,
"icy-name")) != NULL) { "icy-name")) != NULL) {
if (g_utf8_validate (value, -1, NULL)) {
g_free (src->iradio_name); g_free (src->iradio_name);
src->iradio_name = gst_soup_http_src_unicodify (value); src->iradio_name = gst_soup_http_src_unicodify (value);
if (src->iradio_name) { if (src->iradio_name) {
@ -1173,9 +1218,11 @@ gst_soup_http_src_got_headers (GstSoupHTTPSrc * src, SoupMessage * msg)
src->iradio_name, NULL); src->iradio_name, NULL);
} }
} }
}
if ((value = if ((value =
soup_message_headers_get_one (msg->response_headers, soup_message_headers_get_one (msg->response_headers,
"icy-genre")) != NULL) { "icy-genre")) != NULL) {
if (g_utf8_validate (value, -1, NULL)) {
g_free (src->iradio_genre); g_free (src->iradio_genre);
src->iradio_genre = gst_soup_http_src_unicodify (value); src->iradio_genre = gst_soup_http_src_unicodify (value);
if (src->iradio_genre) { if (src->iradio_genre) {
@ -1183,8 +1230,10 @@ gst_soup_http_src_got_headers (GstSoupHTTPSrc * src, SoupMessage * msg)
src->iradio_genre, NULL); src->iradio_genre, NULL);
} }
} }
}
if ((value = soup_message_headers_get_one (msg->response_headers, "icy-url")) if ((value = soup_message_headers_get_one (msg->response_headers, "icy-url"))
!= NULL) { != NULL) {
if (g_utf8_validate (value, -1, NULL)) {
g_free (src->iradio_url); g_free (src->iradio_url);
src->iradio_url = gst_soup_http_src_unicodify (value); src->iradio_url = gst_soup_http_src_unicodify (value);
if (src->iradio_url) { if (src->iradio_url) {
@ -1192,6 +1241,7 @@ gst_soup_http_src_got_headers (GstSoupHTTPSrc * src, SoupMessage * msg)
src->iradio_url, NULL); src->iradio_url, NULL);
} }
} }
}
if (!gst_tag_list_is_empty (tag_list)) { if (!gst_tag_list_is_empty (tag_list)) {
GST_DEBUG_OBJECT (src, GST_DEBUG_OBJECT (src,
"calling gst_element_found_tags with %" GST_PTR_FORMAT, tag_list); "calling gst_element_found_tags with %" GST_PTR_FORMAT, tag_list);
@ -1298,6 +1348,14 @@ gst_soup_http_src_parse_status (SoupMessage * msg, GstSoupHTTPSrc * src)
} else if (SOUP_STATUS_IS_CLIENT_ERROR (msg->status_code) || } else if (SOUP_STATUS_IS_CLIENT_ERROR (msg->status_code) ||
SOUP_STATUS_IS_REDIRECTION (msg->status_code) || SOUP_STATUS_IS_REDIRECTION (msg->status_code) ||
SOUP_STATUS_IS_SERVER_ERROR (msg->status_code)) { SOUP_STATUS_IS_SERVER_ERROR (msg->status_code)) {
const gchar *reason_phrase;
reason_phrase = msg->reason_phrase;
if (reason_phrase && !g_utf8_validate (reason_phrase, -1, NULL)) {
GST_ERROR_OBJECT (src, "Invalid UTF-8 in reason");
reason_phrase = "(invalid)";
}
/* Report HTTP error. */ /* Report HTTP error. */
/* when content_size is unknown and we have just finished receiving /* when content_size is unknown and we have just finished receiving
@ -1316,8 +1374,8 @@ gst_soup_http_src_parse_status (SoupMessage * msg, GstSoupHTTPSrc * src)
*/ */
if (msg->status_code == SOUP_STATUS_NOT_FOUND) { if (msg->status_code == SOUP_STATUS_NOT_FOUND) {
GST_ELEMENT_ERROR_WITH_DETAILS (src, RESOURCE, NOT_FOUND, GST_ELEMENT_ERROR_WITH_DETAILS (src, RESOURCE, NOT_FOUND,
("%s", msg->reason_phrase), ("%s", reason_phrase),
("%s (%d), URL: %s, Redirect to: %s", msg->reason_phrase, ("%s (%d), URL: %s, Redirect to: %s", reason_phrase,
msg->status_code, src->location, msg->status_code, src->location,
GST_STR_NULL (src->redirection_uri)), GST_STR_NULL (src->redirection_uri)),
("http-status-code", G_TYPE_UINT, msg->status_code, ("http-status-code", G_TYPE_UINT, msg->status_code,
@ -1328,15 +1386,15 @@ gst_soup_http_src_parse_status (SoupMessage * msg, GstSoupHTTPSrc * src)
|| msg->status_code == SOUP_STATUS_FORBIDDEN || msg->status_code == SOUP_STATUS_FORBIDDEN
|| msg->status_code == SOUP_STATUS_PROXY_AUTHENTICATION_REQUIRED) { || msg->status_code == SOUP_STATUS_PROXY_AUTHENTICATION_REQUIRED) {
GST_ELEMENT_ERROR_WITH_DETAILS (src, RESOURCE, NOT_AUTHORIZED, ("%s", GST_ELEMENT_ERROR_WITH_DETAILS (src, RESOURCE, NOT_AUTHORIZED, ("%s",
msg->reason_phrase), ("%s (%d), URL: %s, Redirect to: %s", reason_phrase), ("%s (%d), URL: %s, Redirect to: %s",
msg->reason_phrase, msg->status_code, src->location, reason_phrase, msg->status_code, src->location,
GST_STR_NULL (src->redirection_uri)), ("http-status-code", GST_STR_NULL (src->redirection_uri)), ("http-status-code",
G_TYPE_UINT, msg->status_code, "http-redirect-uri", G_TYPE_STRING, G_TYPE_UINT, msg->status_code, "http-redirect-uri", G_TYPE_STRING,
GST_STR_NULL (src->redirection_uri), NULL)); GST_STR_NULL (src->redirection_uri), NULL));
} else { } else {
GST_ELEMENT_ERROR_WITH_DETAILS (src, RESOURCE, OPEN_READ, GST_ELEMENT_ERROR_WITH_DETAILS (src, RESOURCE, OPEN_READ,
("%s", msg->reason_phrase), ("%s", reason_phrase),
("%s (%d), URL: %s, Redirect to: %s", msg->reason_phrase, ("%s (%d), URL: %s, Redirect to: %s", reason_phrase,
msg->status_code, src->location, msg->status_code, src->location,
GST_STR_NULL (src->redirection_uri)), GST_STR_NULL (src->redirection_uri)),
("http-status-code", G_TYPE_UINT, msg->status_code, ("http-status-code", G_TYPE_UINT, msg->status_code,