guri: Make G_URI_FLAGS_PARSE_STRICT the default

Make `G_URI_FLAGS_PARSE_RELAXED` available instead, for the
implementations which need to handle user-provided or incorrect URIs.
The default should nudge people towards being compliant with RFC 3986.

This required also adding a new `G_URI_PARAMS_PARSE_RELAXED` flag, as
previously parsing param strings *always* used relaxed mode and there
was no way to control it. Now it defaults to using strict mode, and the
new flag allows for relaxed mode to be enabled if needed.

Signed-off-by: Philip Withnall <withnall@endlessm.com>

Fixes: #2149
This commit is contained in:
Philip Withnall 2020-08-06 15:14:26 +01:00
parent 943b1e45ab
commit b654eb1846
7 changed files with 99 additions and 88 deletions

View File

@ -31,7 +31,7 @@ LLVMFuzzerTestOneInput (const unsigned char *data, size_t size)
/* ignore @size (g_uri_parse() doesnt support it); ensure @data is nul-terminated */ /* ignore @size (g_uri_parse() doesnt support it); ensure @data is nul-terminated */
nul_terminated_data = (unsigned char *) g_strndup ((const gchar *) data, size); nul_terminated_data = (unsigned char *) g_strndup ((const gchar *) data, size);
test_with_flags ((const gchar *) nul_terminated_data, G_URI_FLAGS_NONE); test_with_flags ((const gchar *) nul_terminated_data, G_URI_FLAGS_NONE);
test_with_flags ((const gchar *) nul_terminated_data, G_URI_FLAGS_PARSE_STRICT); test_with_flags ((const gchar *) nul_terminated_data, G_URI_FLAGS_PARSE_RELAXED);
g_free (nul_terminated_data); g_free (nul_terminated_data);
return 0; return 0;

View File

@ -546,7 +546,7 @@ g_network_address_parse_uri (const gchar *uri,
gchar *hostname = NULL; gchar *hostname = NULL;
gint port; gint port;
if (!g_uri_split_network (uri, G_URI_FLAGS_PARSE_STRICT, if (!g_uri_split_network (uri, G_URI_FLAGS_NONE,
&scheme, &hostname, &port, NULL)) &scheme, &hostname, &port, NULL))
{ {
g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,

View File

@ -148,7 +148,7 @@ g_proxy_resolver_lookup (GProxyResolver *resolver,
g_return_val_if_fail (G_IS_PROXY_RESOLVER (resolver), NULL); g_return_val_if_fail (G_IS_PROXY_RESOLVER (resolver), NULL);
g_return_val_if_fail (uri != NULL, NULL); g_return_val_if_fail (uri != NULL, NULL);
if (!g_uri_is_valid (uri, G_URI_FLAGS_PARSE_STRICT, NULL)) if (!g_uri_is_valid (uri, G_URI_FLAGS_NONE, NULL))
{ {
g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
"Invalid URI %s", uri); "Invalid URI %s", uri);
@ -186,7 +186,7 @@ g_proxy_resolver_lookup_async (GProxyResolver *resolver,
g_return_if_fail (G_IS_PROXY_RESOLVER (resolver)); g_return_if_fail (G_IS_PROXY_RESOLVER (resolver));
g_return_if_fail (uri != NULL); g_return_if_fail (uri != NULL);
if (!g_uri_is_valid (uri, G_URI_FLAGS_PARSE_STRICT, NULL)) if (!g_uri_is_valid (uri, G_URI_FLAGS_NONE, NULL))
{ {
g_set_error (&error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, g_set_error (&error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
"Invalid URI %s", uri); "Invalid URI %s", uri);

View File

@ -329,7 +329,7 @@ g_simple_proxy_resolver_lookup (GProxyResolver *proxy_resolver,
gchar *host = NULL; gchar *host = NULL;
gint port; gint port;
if (g_uri_split_network (uri, G_URI_FLAGS_PARSE_STRICT, NULL, if (g_uri_split_network (uri, G_URI_FLAGS_NONE, NULL,
&host, &port, NULL) && &host, &port, NULL) &&
ignore_host (resolver, host, port > 0 ? port : 0)) ignore_host (resolver, host, port > 0 ? port : 0))
proxy = "direct://"; proxy = "direct://";

View File

@ -306,7 +306,7 @@ uri_decoder (gchar **out,
!g_ascii_isxdigit (s[2])) !g_ascii_isxdigit (s[2]))
{ {
/* % followed by non-hex or the end of the string; this is an error */ /* % followed by non-hex or the end of the string; this is an error */
if (flags & G_URI_FLAGS_PARSE_STRICT) if (!(flags & G_URI_FLAGS_PARSE_RELAXED))
{ {
g_set_error_literal (error, G_URI_ERROR, parse_error, g_set_error_literal (error, G_URI_ERROR, parse_error,
/* xgettext: no-c-format */ /* xgettext: no-c-format */
@ -710,7 +710,7 @@ g_uri_split_internal (const gchar *uri_string,
if (fragment) if (fragment)
*fragment = NULL; *fragment = NULL;
if (!(flags & G_URI_FLAGS_PARSE_STRICT) && strpbrk (uri_string, " \t\n\r")) if ((flags & G_URI_FLAGS_PARSE_RELAXED) && strpbrk (uri_string, " \t\n\r"))
{ {
cleaned_uri_string = uri_cleanup (uri_string); cleaned_uri_string = uri_cleanup (uri_string);
uri_string = cleaned_uri_string; uri_string = cleaned_uri_string;
@ -745,7 +745,7 @@ g_uri_split_internal (const gchar *uri_string,
at = memchr (p, '@', path_start - p); at = memchr (p, '@', path_start - p);
if (at) if (at)
{ {
if (!(flags & G_URI_FLAGS_PARSE_STRICT)) if (flags & G_URI_FLAGS_PARSE_RELAXED)
{ {
gchar *next_at; gchar *next_at;
@ -780,7 +780,7 @@ g_uri_split_internal (const gchar *uri_string,
p = at + 1; p = at + 1;
} }
if (!(flags & G_URI_FLAGS_PARSE_STRICT)) if (flags & G_URI_FLAGS_PARSE_RELAXED)
{ {
semi = strchr (p, ';'); semi = strchr (p, ';');
if (semi && semi < path_start) if (semi && semi < path_start)
@ -1987,6 +1987,7 @@ g_uri_params_iter_next (GUriParamsIter *iter,
const gchar *attr_end, *val, *val_end; const gchar *attr_end, *val, *val_end;
gchar *decoded_attr, *decoded_value; gchar *decoded_attr, *decoded_value;
gboolean www_form = ri->flags & G_URI_PARAMS_WWW_FORM; gboolean www_form = ri->flags & G_URI_PARAMS_WWW_FORM;
GUriFlags decode_flags = G_URI_FLAGS_NONE;
g_return_val_if_fail (iter != NULL, FALSE); g_return_val_if_fail (iter != NULL, FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE); g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
@ -2000,6 +2001,9 @@ g_uri_params_iter_next (GUriParamsIter *iter,
if (ri->attr >= ri->end) if (ri->attr >= ri->end)
return FALSE; return FALSE;
if (ri->flags & G_URI_PARAMS_PARSE_RELAXED)
decode_flags |= G_URI_FLAGS_PARSE_RELAXED;
/* Check if each character in @attr is a separator, by indexing by the /* Check if each character in @attr is a separator, by indexing by the
* character value into the @sep_table, which has value 1 stored at an * character value into the @sep_table, which has value 1 stored at an
* index if that index is a separator. */ * index if that index is a separator. */
@ -2015,14 +2019,14 @@ g_uri_params_iter_next (GUriParamsIter *iter,
return FALSE; return FALSE;
} }
if (!uri_decode (&decoded_attr, NULL, ri->attr, attr_end - ri->attr, if (!uri_decode (&decoded_attr, NULL, ri->attr, attr_end - ri->attr,
www_form, G_URI_FLAGS_NONE, G_URI_ERROR_FAILED, error)) www_form, decode_flags, G_URI_ERROR_FAILED, error))
{ {
return FALSE; return FALSE;
} }
val = attr_end + 1; val = attr_end + 1;
if (!uri_decode (&decoded_value, NULL, val, val_end - val, if (!uri_decode (&decoded_value, NULL, val, val_end - val,
www_form, G_URI_FLAGS_NONE, G_URI_ERROR_FAILED, error)) www_form, decode_flags, G_URI_ERROR_FAILED, error))
{ {
g_free (decoded_attr); g_free (decoded_attr);
return FALSE; return FALSE;
@ -2062,9 +2066,9 @@ g_uri_params_iter_next (GUriParamsIter *iter,
* The @params string is assumed to still be `%`-encoded, but the returned * The @params string is assumed to still be `%`-encoded, but the returned
* values will be fully decoded. (Thus it is possible that the returned values * values will be fully decoded. (Thus it is possible that the returned values
* may contain `=` or @separators, if the value was encoded in the input.) * may contain `=` or @separators, if the value was encoded in the input.)
* Invalid `%`-encoding is treated as with the non-%G_URI_FLAGS_PARSE_STRICT * Invalid `%`-encoding is treated as with the %G_URI_FLAGS_PARSE_RELAXED
* rules for g_uri_parse(). (However, if @params is the path or query string * rules for g_uri_parse(). (However, if @params is the path or query string
* from a #GUri that was parsed with %G_URI_FLAGS_PARSE_STRICT and * from a #GUri that was parsed without %G_URI_FLAGS_PARSE_RELAXED and
* %G_URI_FLAGS_ENCODED, then you already know that it does not contain any * %G_URI_FLAGS_ENCODED, then you already know that it does not contain any
* invalid encoding.) * invalid encoding.)
* *
@ -2401,7 +2405,7 @@ g_uri_unescape_segment (const gchar *escaped_string,
illegal_characters, illegal_characters,
escaped_string, length, escaped_string, length,
FALSE, FALSE, FALSE, FALSE,
G_URI_FLAGS_PARSE_STRICT|G_URI_FLAGS_ENCODED, G_URI_FLAGS_ENCODED,
0, NULL); 0, NULL);
if (decoded_len < 0) if (decoded_len < 0)
return NULL; return NULL;
@ -2524,7 +2528,7 @@ g_uri_unescape_bytes (const gchar *escaped_string,
escaped_string, length, escaped_string, length,
FALSE, FALSE,
FALSE, FALSE,
G_URI_FLAGS_PARSE_STRICT|G_URI_FLAGS_ENCODED, G_URI_FLAGS_ENCODED,
G_URI_ERROR_FAILED, error); G_URI_ERROR_FAILED, error);
if (unescaped_length == -1) if (unescaped_length == -1)
return NULL; return NULL;

View File

@ -38,9 +38,11 @@ void g_uri_unref (GUri *uri);
/** /**
* GUriFlags: * GUriFlags:
* @G_URI_FLAGS_NONE: No flags set. * @G_URI_FLAGS_NONE: No flags set.
* @G_URI_FLAGS_PARSE_STRICT: Parse the URI strictly according to the * @G_URI_FLAGS_PARSE_RELAXED: Parse the URI more relaxedly than the
* [RFC 3986](https://tools.ietf.org/html/rfc3986) grammar, rather than * [RFC 3986](https://tools.ietf.org/html/rfc3986) grammar specifies,
* fixing up or ignoring common mistakes. * fixing up or ignoring common mistakes in URIs coming from external
* sources. This is also needed for some obscure URI schemes where `;`
* separates the host from the path. Dont use this flag unless you need to.
* @G_URI_FLAGS_HAS_PASSWORD: The userinfo field may contain a password, * @G_URI_FLAGS_HAS_PASSWORD: The userinfo field may contain a password,
* which will be separated from the username by `:`. * which will be separated from the username by `:`.
* @G_URI_FLAGS_HAS_AUTH_PARAMS: The userinfo may contain additional * @G_URI_FLAGS_HAS_AUTH_PARAMS: The userinfo may contain additional
@ -73,7 +75,7 @@ void g_uri_unref (GUri *uri);
GLIB_AVAILABLE_TYPE_IN_2_66 GLIB_AVAILABLE_TYPE_IN_2_66
typedef enum { typedef enum {
G_URI_FLAGS_NONE = 0, G_URI_FLAGS_NONE = 0,
G_URI_FLAGS_PARSE_STRICT = 1 << 0, G_URI_FLAGS_PARSE_RELAXED = 1 << 0,
G_URI_FLAGS_HAS_PASSWORD = 1 << 1, G_URI_FLAGS_HAS_PASSWORD = 1 << 1,
G_URI_FLAGS_HAS_AUTH_PARAMS = 1 << 2, G_URI_FLAGS_HAS_AUTH_PARAMS = 1 << 2,
G_URI_FLAGS_ENCODED = 1 << 3, G_URI_FLAGS_ENCODED = 1 << 3,
@ -239,6 +241,7 @@ GUriFlags g_uri_get_flags (GUri *uri);
* @G_URI_PARAMS_CASE_INSENSITIVE: Parameter names are case insensitive. * @G_URI_PARAMS_CASE_INSENSITIVE: Parameter names are case insensitive.
* @G_URI_PARAMS_WWW_FORM: Replace `+` with space character. Only useful for * @G_URI_PARAMS_WWW_FORM: Replace `+` with space character. Only useful for
* URLs on the web, using the `https` or `http` schemas. * URLs on the web, using the `https` or `http` schemas.
* @G_URI_PARAMS_PARSE_RELAXED: See %G_URI_FLAGS_PARSE_RELAXED.
* *
* Flags modifying the way parameters are handled by g_uri_parse_params() and * Flags modifying the way parameters are handled by g_uri_parse_params() and
* #GUriParamsIter. * #GUriParamsIter.
@ -250,6 +253,7 @@ typedef enum {
G_URI_PARAMS_NONE = 0, G_URI_PARAMS_NONE = 0,
G_URI_PARAMS_CASE_INSENSITIVE = 1 << 0, G_URI_PARAMS_CASE_INSENSITIVE = 1 << 0,
G_URI_PARAMS_WWW_FORM = 1 << 1, G_URI_PARAMS_WWW_FORM = 1 << 1,
G_URI_PARAMS_PARSE_RELAXED = 1 << 2,
} GUriParamsFlags; } GUriParamsFlags;
GLIB_AVAILABLE_IN_2_66 GLIB_AVAILABLE_IN_2_66

View File

@ -512,201 +512,202 @@ typedef struct {
typedef struct { typedef struct {
const gchar *orig; const gchar *orig;
GUriFlags flags;
const UriParts parts; const UriParts parts;
} UriAbsoluteTest; } UriAbsoluteTest;
static const UriAbsoluteTest absolute_tests[] = { static const UriAbsoluteTest absolute_tests[] = {
{ "foo:", { "foo:", G_URI_FLAGS_NONE,
{ "foo", NULL, NULL, -1, "", NULL, NULL } { "foo", NULL, NULL, -1, "", NULL, NULL }
}, },
{ "file:/dev/null", { "file:/dev/null", G_URI_FLAGS_NONE,
{ "file", NULL, NULL, -1, "/dev/null", NULL, NULL } { "file", NULL, NULL, -1, "/dev/null", NULL, NULL }
}, },
{ "file:///dev/null", { "file:///dev/null", G_URI_FLAGS_NONE,
{ "file", NULL, "", -1, "/dev/null", NULL, NULL } { "file", NULL, "", -1, "/dev/null", NULL, NULL }
}, },
{ "ftp://user@host/path", { "ftp://user@host/path", G_URI_FLAGS_NONE,
{ "ftp", "user", "host", -1, "/path", NULL, NULL } { "ftp", "user", "host", -1, "/path", NULL, NULL }
}, },
{ "ftp://user@host:9999/path", { "ftp://user@host:9999/path", G_URI_FLAGS_NONE,
{ "ftp", "user", "host", 9999, "/path", NULL, NULL } { "ftp", "user", "host", 9999, "/path", NULL, NULL }
}, },
{ "ftp://user:password@host/path", { "ftp://user:password@host/path", G_URI_FLAGS_NONE,
{ "ftp", "user:password", "host", -1, "/path", NULL, NULL } { "ftp", "user:password", "host", -1, "/path", NULL, NULL }
}, },
{ "ftp://user:password@host:9999/path", { "ftp://user:password@host:9999/path", G_URI_FLAGS_NONE,
{ "ftp", "user:password", "host", 9999, "/path", NULL, NULL } { "ftp", "user:password", "host", 9999, "/path", NULL, NULL }
}, },
{ "ftp://user:password@host", { "ftp://user:password@host", G_URI_FLAGS_NONE,
{ "ftp", "user:password", "host", -1, "", NULL, NULL } { "ftp", "user:password", "host", -1, "", NULL, NULL }
}, },
{ "http://us%65r@host", { "http://us%65r@host", G_URI_FLAGS_NONE,
{ "http", "user", "host", -1, "", NULL, NULL } { "http", "user", "host", -1, "", NULL, NULL }
}, },
{ "http://us%40r@host", { "http://us%40r@host", G_URI_FLAGS_NONE,
{ "http", "us@r", "host", -1, "", NULL, NULL } { "http", "us@r", "host", -1, "", NULL, NULL }
}, },
{ "http://us%3ar@host", { "http://us%3ar@host", G_URI_FLAGS_NONE,
{ "http", "us:r", "host", -1, "", NULL, NULL } { "http", "us:r", "host", -1, "", NULL, NULL }
}, },
{ "http://us%2fr@host", { "http://us%2fr@host", G_URI_FLAGS_NONE,
{ "http", "us/r", "host", -1, "", NULL, NULL } { "http", "us/r", "host", -1, "", NULL, NULL }
}, },
{ "http://us%3fr@host", { "http://us%3fr@host", G_URI_FLAGS_NONE,
{ "http", "us?r", "host", -1, "", NULL, NULL } { "http", "us?r", "host", -1, "", NULL, NULL }
}, },
{ "http://host?query", { "http://host?query", G_URI_FLAGS_NONE,
{ "http", NULL, "host", -1, "", "query", NULL } { "http", NULL, "host", -1, "", "query", NULL }
}, },
{ "http://host/path?query=http%3A%2F%2Fhost%2Fpath%3Fchildparam%3Dchildvalue&param=value", { "http://host/path?query=http%3A%2F%2Fhost%2Fpath%3Fchildparam%3Dchildvalue&param=value", G_URI_FLAGS_NONE,
{ "http", NULL, "host", -1, "/path", "query=http://host/path?childparam=childvalue&param=value", NULL } { "http", NULL, "host", -1, "/path", "query=http://host/path?childparam=childvalue&param=value", NULL }
}, },
{ "http://control-chars/%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%7F", { "http://control-chars/%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%7F", G_URI_FLAGS_NONE,
{ "http", NULL, "control-chars", -1, "/\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x7F", NULL, NULL } { "http", NULL, "control-chars", -1, "/\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x7F", NULL, NULL }
}, },
{ "http://space/%20", { "http://space/%20", G_URI_FLAGS_NONE,
{ "http", NULL, "space", -1, "/ ", NULL, NULL } { "http", NULL, "space", -1, "/ ", NULL, NULL }
}, },
{ "http://delims/%3C%3E%23%25%22", { "http://delims/%3C%3E%23%25%22", G_URI_FLAGS_NONE,
{ "http", NULL, "delims", -1, "/<>#%\"", NULL, NULL } { "http", NULL, "delims", -1, "/<>#%\"", NULL, NULL }
}, },
{ "http://unwise-chars/%7B%7D%7C%5C%5E%5B%5D%60", { "http://unwise-chars/%7B%7D%7C%5C%5E%5B%5D%60", G_URI_FLAGS_NONE,
{ "http", NULL, "unwise-chars", -1, "/{}|\\^[]`", NULL, NULL } { "http", NULL, "unwise-chars", -1, "/{}|\\^[]`", NULL, NULL }
}, },
/* From RFC 2732 */ /* From RFC 2732 */
{ "http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html", { "http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html", G_URI_FLAGS_NONE,
{ "http", NULL, "FEDC:BA98:7654:3210:FEDC:BA98:7654:3210", 80, "/index.html", NULL, NULL } { "http", NULL, "FEDC:BA98:7654:3210:FEDC:BA98:7654:3210", 80, "/index.html", NULL, NULL }
}, },
{ "http://[1080:0:0:0:8:800:200C:417A]/index.html", { "http://[1080:0:0:0:8:800:200C:417A]/index.html", G_URI_FLAGS_NONE,
{ "http", NULL, "1080:0:0:0:8:800:200C:417A", -1, "/index.html", NULL, NULL } { "http", NULL, "1080:0:0:0:8:800:200C:417A", -1, "/index.html", NULL, NULL }
}, },
{ "http://[3ffe:2a00:100:7031::1]", { "http://[3ffe:2a00:100:7031::1]", G_URI_FLAGS_NONE,
{ "http", NULL, "3ffe:2a00:100:7031::1", -1, "", NULL, NULL } { "http", NULL, "3ffe:2a00:100:7031::1", -1, "", NULL, NULL }
}, },
{ "http://[1080::8:800:200C:417A]/foo", { "http://[1080::8:800:200C:417A]/foo", G_URI_FLAGS_NONE,
{ "http", NULL, "1080::8:800:200C:417A", -1, "/foo", NULL, NULL } { "http", NULL, "1080::8:800:200C:417A", -1, "/foo", NULL, NULL }
}, },
{ "http://[::192.9.5.5]/ipng", { "http://[::192.9.5.5]/ipng", G_URI_FLAGS_NONE,
{ "http", NULL, "::192.9.5.5", -1, "/ipng", NULL, NULL } { "http", NULL, "::192.9.5.5", -1, "/ipng", NULL, NULL }
}, },
{ "http://[::FFFF:129.144.52.38]:80/index.html", { "http://[::FFFF:129.144.52.38]:80/index.html", G_URI_FLAGS_NONE,
{ "http", NULL, "::FFFF:129.144.52.38", 80, "/index.html", NULL, NULL } { "http", NULL, "::FFFF:129.144.52.38", 80, "/index.html", NULL, NULL }
}, },
{ "http://[2010:836B:4179::836B:4179]", { "http://[2010:836B:4179::836B:4179]", G_URI_FLAGS_NONE,
{ "http", NULL, "2010:836B:4179::836B:4179", -1, "", NULL, NULL } { "http", NULL, "2010:836B:4179::836B:4179", -1, "", NULL, NULL }
}, },
/* some problematic URIs that are handled differently in libsoup */ /* some problematic URIs that are handled differently in libsoup */
{ "http://host/path with spaces", { "http://host/path with spaces", G_URI_FLAGS_PARSE_RELAXED,
{ "http", NULL, "host", -1, "/path with spaces", NULL, NULL } { "http", NULL, "host", -1, "/path with spaces", NULL, NULL }
}, },
{ " http://host/path", { " http://host/path", G_URI_FLAGS_PARSE_RELAXED,
{ "http", NULL, "host", -1, "/path", NULL, NULL } { "http", NULL, "host", -1, "/path", NULL, NULL }
}, },
{ "http://host/path ", { "http://host/path ", G_URI_FLAGS_PARSE_RELAXED,
{ "http", NULL, "host", -1, "/path", NULL, NULL } { "http", NULL, "host", -1, "/path", NULL, NULL }
}, },
{ "http://host ", { "http://host ", G_URI_FLAGS_PARSE_RELAXED,
{ "http", NULL, "host", -1, "", NULL, NULL } { "http", NULL, "host", -1, "", NULL, NULL }
}, },
{ "http://host:999 ", { "http://host:999 ", G_URI_FLAGS_PARSE_RELAXED,
{ "http", NULL, "host", 999, "", NULL, NULL } { "http", NULL, "host", 999, "", NULL, NULL }
}, },
{ "http://host/pa\nth", { "http://host/pa\nth", G_URI_FLAGS_PARSE_RELAXED,
{ "http", NULL, "host", -1, "/path", NULL, NULL } { "http", NULL, "host", -1, "/path", NULL, NULL }
}, },
{ "http:\r\n//host/path", { "http:\r\n//host/path", G_URI_FLAGS_PARSE_RELAXED,
{ "http", NULL, "host", -1, "/path", NULL, NULL } { "http", NULL, "host", -1, "/path", NULL, NULL }
}, },
{ "http://\thost/path", { "http://\thost/path", G_URI_FLAGS_PARSE_RELAXED,
{ "http", NULL, "host", -1, "/path", NULL, NULL } { "http", NULL, "host", -1, "/path", NULL, NULL }
}, },
/* Bug 594405; 0-length is different from not-present */ /* Bug 594405; 0-length is different from not-present */
{ "http://host/path?", { "http://host/path?", G_URI_FLAGS_NONE,
{ "http", NULL, "host", -1, "/path", "", NULL } { "http", NULL, "host", -1, "/path", "", NULL }
}, },
{ "http://host/path#", { "http://host/path#", G_URI_FLAGS_NONE,
{ "http", NULL, "host", -1, "/path", NULL, "" }, { "http", NULL, "host", -1, "/path", NULL, "" },
}, },
/* Bug 590524; ignore bad %-encoding */ /* Bug 590524; ignore bad %-encoding */
{ "http://host/path%", { "http://host/path%", G_URI_FLAGS_PARSE_RELAXED,
{ "http", NULL, "host", -1, "/path%", NULL, NULL } { "http", NULL, "host", -1, "/path%", NULL, NULL }
}, },
{ "http://h%ost/path", { "http://h%ost/path", G_URI_FLAGS_PARSE_RELAXED,
{ "http", NULL, "h%ost", -1, "/path", NULL, NULL } { "http", NULL, "h%ost", -1, "/path", NULL, NULL }
}, },
{ "http://host/path%%", { "http://host/path%%", G_URI_FLAGS_PARSE_RELAXED,
{ "http", NULL, "host", -1, "/path%%", NULL, NULL } { "http", NULL, "host", -1, "/path%%", NULL, NULL }
}, },
{ "http://host/path%%%", { "http://host/path%%%", G_URI_FLAGS_PARSE_RELAXED,
{ "http", NULL, "host", -1, "/path%%%", NULL, NULL } { "http", NULL, "host", -1, "/path%%%", NULL, NULL }
}, },
{ "http://host/path%/x/", { "http://host/path%/x/", G_URI_FLAGS_PARSE_RELAXED,
{ "http", NULL, "host", -1, "/path%/x/", NULL, NULL } { "http", NULL, "host", -1, "/path%/x/", NULL, NULL }
}, },
{ "http://host/path%0x/", { "http://host/path%0x/", G_URI_FLAGS_PARSE_RELAXED,
{ "http", NULL, "host", -1, "/path%0x/", NULL, NULL } { "http", NULL, "host", -1, "/path%0x/", NULL, NULL }
}, },
{ "http://host/path%ax", { "http://host/path%ax", G_URI_FLAGS_PARSE_RELAXED,
{ "http", NULL, "host", -1, "/path%ax", NULL, NULL } { "http", NULL, "host", -1, "/path%ax", NULL, NULL }
}, },
/* GUri doesn't %-encode non-ASCII characters */ /* GUri doesn't %-encode non-ASCII characters */
{ "http://host/p\xc3\xa4th/", { "http://host/p\xc3\xa4th/", G_URI_FLAGS_NONE,
{ "http", NULL, "host", -1, "/p\xc3\xa4th/", NULL, NULL } { "http", NULL, "host", -1, "/p\xc3\xa4th/", NULL, NULL }
}, },
{ "HTTP:////////////////", { "HTTP:////////////////", G_URI_FLAGS_NONE,
{ "http", NULL, "", -1, "//////////////", NULL, NULL } { "http", NULL, "", -1, "//////////////", NULL, NULL }
}, },
{ "http://@host", { "http://@host", G_URI_FLAGS_NONE,
{ "http", "", "host", -1, "", NULL, NULL } { "http", "", "host", -1, "", NULL, NULL }
}, },
{ "http://:@host", { "http://:@host", G_URI_FLAGS_NONE,
{ "http", ":", "host", -1, "", NULL, NULL } { "http", ":", "host", -1, "", NULL, NULL }
}, },
{ "scheme://foo%3Abar._webdav._tcp.local", { "scheme://foo%3Abar._webdav._tcp.local", G_URI_FLAGS_NONE,
{ "scheme", NULL, "foo:bar._webdav._tcp.local", -1, "", NULL, NULL} { "scheme", NULL, "foo:bar._webdav._tcp.local", -1, "", NULL, NULL}
}, },
/* IPv6 scope ID parsing (both correct and incorrect) */ /* IPv6 scope ID parsing (both correct and incorrect) */
{ "http://[fe80::dead:beef%em1]/", { "http://[fe80::dead:beef%em1]/", G_URI_FLAGS_NONE,
{ "http", NULL, "fe80::dead:beef%em1", -1, "/", NULL, NULL } { "http", NULL, "fe80::dead:beef%em1", -1, "/", NULL, NULL }
}, },
{ "http://[fe80::dead:beef%25em1]/", { "http://[fe80::dead:beef%25em1]/", G_URI_FLAGS_NONE,
{ "http", NULL, "fe80::dead:beef%em1", -1, "/", NULL, NULL } { "http", NULL, "fe80::dead:beef%em1", -1, "/", NULL, NULL }
}, },
{ "http://[fe80::dead:beef%10]/", { "http://[fe80::dead:beef%10]/", G_URI_FLAGS_NONE,
{ "http", NULL, "fe80::dead:beef%10", -1, "/", NULL, NULL } { "http", NULL, "fe80::dead:beef%10", -1, "/", NULL, NULL }
}, },
/* ".." past top */ /* ".." past top */
{ "http://example.com/..", { "http://example.com/..", G_URI_FLAGS_NONE,
{ "http", NULL, "example.com", -1, "/..", NULL, NULL } { "http", NULL, "example.com", -1, "/..", NULL, NULL }
}, },
/* scheme parsing */ /* scheme parsing */
{ "foo0://host/path", { "foo0://host/path", G_URI_FLAGS_NONE,
{ "foo0", NULL, "host", -1, "/path", NULL, NULL } }, { "foo0", NULL, "host", -1, "/path", NULL, NULL } },
{ "f0.o://host/path", { "f0.o://host/path", G_URI_FLAGS_NONE,
{ "f0.o", NULL, "host", -1, "/path", NULL, NULL } }, { "f0.o", NULL, "host", -1, "/path", NULL, NULL } },
{ "http++://host/path", { "http++://host/path", G_URI_FLAGS_NONE,
{ "http++", NULL, "host", -1, "/path", NULL, NULL } }, { "http++", NULL, "host", -1, "/path", NULL, NULL } },
{ "http-ish://host/path", { "http-ish://host/path", G_URI_FLAGS_NONE,
{ "http-ish", NULL, "host", -1, "/path", NULL, NULL } }, { "http-ish", NULL, "host", -1, "/path", NULL, NULL } },
/* IPv6 scope ID parsing (both correct and incorrect) */ /* IPv6 scope ID parsing (both correct and incorrect) */
{ "http://[fe80::dead:beef%em1]/", { "http://[fe80::dead:beef%em1]/", G_URI_FLAGS_NONE,
{ "http", NULL, "fe80::dead:beef%em1", -1, "/", NULL, NULL } }, { "http", NULL, "fe80::dead:beef%em1", -1, "/", NULL, NULL } },
{ "http://[fe80::dead:beef%25em1]/", { "http://[fe80::dead:beef%25em1]/", G_URI_FLAGS_NONE,
{ "http", NULL, "fe80::dead:beef%em1", -1, "/", NULL, NULL } }, { "http", NULL, "fe80::dead:beef%em1", -1, "/", NULL, NULL } },
{ "http://[fe80::dead:beef%10]/", { "http://[fe80::dead:beef%10]/", G_URI_FLAGS_NONE,
{ "http", NULL, "fe80::dead:beef%10", -1, "/", NULL, NULL } }, { "http", NULL, "fe80::dead:beef%10", -1, "/", NULL, NULL } },
{ "http://[fe80::dead:beef%25]/", { "http://[fe80::dead:beef%25]/", G_URI_FLAGS_NONE,
{ "http", NULL, "fe80::dead:beef%25", -1, "/", NULL, NULL } }, { "http", NULL, "fe80::dead:beef%25", -1, "/", NULL, NULL } },
}; };
static int num_absolute_tests = G_N_ELEMENTS (absolute_tests); static int num_absolute_tests = G_N_ELEMENTS (absolute_tests);
@ -722,7 +723,9 @@ test_uri_parsing_absolute (void)
GError *error = NULL; GError *error = NULL;
GUri *uri; GUri *uri;
uri = g_uri_parse (test->orig, G_URI_FLAGS_NONE, &error); g_test_message ("Test %d: %s", i, test->orig);
uri = g_uri_parse (test->orig, test->flags, &error);
g_assert_no_error (error); g_assert_no_error (error);
g_assert_cmpstr (g_uri_get_scheme (uri), ==, test->parts.scheme); g_assert_cmpstr (g_uri_get_scheme (uri), ==, test->parts.scheme);
@ -872,7 +875,7 @@ test_uri_parsing_relative (void)
g_assert_cmpstr (resolved, ==, test->resolved); g_assert_cmpstr (resolved, ==, test->resolved);
g_free (resolved); g_free (resolved);
} }
uri = g_uri_parse_relative (base, "%%", G_URI_FLAGS_PARSE_STRICT, &error); uri = g_uri_parse_relative (base, "%%", G_URI_FLAGS_NONE, &error);
g_assert_null (uri); g_assert_null (uri);
g_assert_error (error, G_URI_ERROR, G_URI_ERROR_BAD_PATH); g_assert_error (error, G_URI_ERROR, G_URI_ERROR_BAD_PATH);
g_clear_error (&error); g_clear_error (&error);
@ -899,7 +902,7 @@ test_uri_parsing_relative (void)
g_assert_error (error, G_URI_ERROR, G_URI_ERROR_FAILED); g_assert_error (error, G_URI_ERROR, G_URI_ERROR_FAILED);
g_clear_error (&error); g_clear_error (&error);
resolved = g_uri_resolve_relative ("%%", "a", G_URI_FLAGS_NONE, &error); resolved = g_uri_resolve_relative ("%%", "a", G_URI_FLAGS_PARSE_RELAXED, &error);
g_assert_null (resolved); g_assert_null (resolved);
g_assert_error (error, G_URI_ERROR, G_URI_ERROR_FAILED); g_assert_error (error, G_URI_ERROR, G_URI_ERROR_FAILED);
g_clear_error (&error); g_clear_error (&error);
@ -1071,7 +1074,7 @@ test_uri_split (void)
g_free (host); g_free (host);
g_uri_split ("scheme://@@@host:1234/path?query#fragment", g_uri_split ("scheme://@@@host:1234/path?query#fragment",
G_URI_FLAGS_ENCODED, G_URI_FLAGS_ENCODED | G_URI_FLAGS_PARSE_RELAXED,
NULL, NULL,
&userinfo, &userinfo,
NULL, NULL,
@ -1086,7 +1089,7 @@ test_uri_split (void)
g_uri_split ("http://f;oo/", g_uri_split ("http://f;oo/",
G_URI_FLAGS_NONE, G_URI_FLAGS_NONE | G_URI_FLAGS_PARSE_RELAXED,
NULL, NULL,
NULL, NULL,
NULL, NULL,
@ -1266,7 +1269,7 @@ test_uri_split (void)
g_clear_error (&error); g_clear_error (&error);
g_uri_split_with_user ("scheme://user:pa%x0s;auth@host:1234/path?query#fragment", g_uri_split_with_user ("scheme://user:pa%x0s;auth@host:1234/path?query#fragment",
G_URI_FLAGS_HAS_PASSWORD|G_URI_FLAGS_PARSE_STRICT, G_URI_FLAGS_HAS_PASSWORD,
&scheme, &scheme,
&user, &user,
&pass, &pass,
@ -1313,8 +1316,8 @@ test_uri_is_valid (void)
g_assert_true (g_uri_is_valid ("http://127.127.127.b/", G_URI_FLAGS_NONE, NULL)); g_assert_true (g_uri_is_valid ("http://127.127.127.b/", G_URI_FLAGS_NONE, NULL));
g_assert_true (g_uri_is_valid ("http://\xc3\x89XAMPLE.COM/", G_URI_FLAGS_NONE, NULL)); g_assert_true (g_uri_is_valid ("http://\xc3\x89XAMPLE.COM/", G_URI_FLAGS_NONE, NULL));
g_assert_true (g_uri_is_valid (" \r http\t://f oo \t\n ", G_URI_FLAGS_NONE, NULL)); g_assert_true (g_uri_is_valid (" \r http\t://f oo \t\n ", G_URI_FLAGS_PARSE_RELAXED, NULL));
g_assert_false (g_uri_is_valid (" \r http\t://f oo \t\n ", G_URI_FLAGS_PARSE_STRICT, &error)); g_assert_false (g_uri_is_valid (" \r http\t://f oo \t\n ", G_URI_FLAGS_NONE, &error));
g_assert_error (error, G_URI_ERROR, G_URI_ERROR_BAD_SCHEME); g_assert_error (error, G_URI_ERROR, G_URI_ERROR_BAD_SCHEME);
g_clear_error (&error); g_clear_error (&error);
@ -1391,7 +1394,7 @@ static const struct
{ "p1=foo&P1=bar", "&", G_URI_PARAMS_CASE_INSENSITIVE, { "p1=foo&P1=bar", "&", G_URI_PARAMS_CASE_INSENSITIVE,
2, { "p1", "foo", "P1", "bar" }, 2, { "p1", "foo", "P1", "bar" },
1, { "p1", "bar", NULL, }}, 1, { "p1", "bar", NULL, }},
{ "=%", "&", G_URI_PARAMS_NONE, { "=%", "&", G_URI_PARAMS_PARSE_RELAXED,
1, { "", "%", NULL, }, 1, { "", "%", NULL, },
1, { "", "%", NULL, }}, 1, { "", "%", NULL, }},
{ "=", "&", G_URI_PARAMS_NONE, { "=", "&", G_URI_PARAMS_NONE,