uri: teach g_uri_parse_params() to decode www-form query

This is a minor convenience, to avoid caller to do further '+' decoding.

According to the W3C HTML specification, space characters are replaced
by '+': https://url.spec.whatwg.org/#urlencoded-parsing

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
This commit is contained in:
Marc-André Lureau 2020-06-30 19:35:59 +04:00
parent e2d3349c56
commit 30ad9c6711
3 changed files with 19 additions and 6 deletions

View File

@ -237,6 +237,7 @@ uri_decoder (gchar **out,
const gchar *start,
gsize length,
gboolean just_normalize,
gboolean www_form,
GUriFlags flags,
GUriError parse_error,
GError **error)
@ -287,6 +288,8 @@ uri_decoder (gchar **out,
s += 2;
}
}
else if (www_form && *s == '+')
*d++ = ' ';
else
*d++ = *s;
}
@ -314,11 +317,12 @@ static gboolean
uri_decode (gchar **out,
const gchar *start,
gsize length,
gboolean www_form,
GUriFlags flags,
GUriError parse_error,
GError **error)
{
return uri_decoder (out, start, length, FALSE, flags,
return uri_decoder (out, start, length, FALSE, www_form, flags,
parse_error, error) != -1;
}
@ -330,7 +334,7 @@ uri_normalize (gchar **out,
GUriError parse_error,
GError **error)
{
return uri_decoder (out, start, length, TRUE, flags,
return uri_decoder (out, start, length, TRUE, FALSE, flags,
parse_error, error) != -1;
}
@ -450,7 +454,7 @@ parse_host (const gchar *start,
}
flags &= ~G_URI_FLAGS_ENCODED;
if (!uri_decode (&decoded, start, length, flags,
if (!uri_decode (&decoded, start, length, FALSE, flags,
G_URI_ERROR_BAD_HOST, error))
return FALSE;
@ -771,7 +775,7 @@ g_uri_split_internal (const gchar *uri_string,
end = p + strcspn (p, "#");
if (*end == '#')
{
if (!uri_decode (fragment, end + 1, strlen (end + 1), flags,
if (!uri_decode (fragment, end + 1, strlen (end + 1), FALSE, flags,
G_URI_ERROR_BAD_FRAGMENT, error))
goto fail;
}
@ -1786,6 +1790,7 @@ g_uri_parse_params (const gchar *params,
const gchar *end, *attr, *attr_end, *value, *value_end, *s;
gchar *decoded_attr, *decoded_value;
guint8 sep_table[256]; /* 1 = index is a separator; 0 otherwise */
gboolean www_form = flags & G_URI_PARAMS_WWW_FORM;
g_return_val_if_fail (length == 0 || params != NULL, NULL);
g_return_val_if_fail (length >= -1, NULL);
@ -1829,7 +1834,7 @@ g_uri_parse_params (const gchar *params,
return NULL;
}
if (!uri_decode (&decoded_attr, attr, attr_end - attr,
0, G_URI_ERROR_MISC, NULL))
www_form, G_URI_FLAGS_NONE, G_URI_ERROR_MISC, NULL))
{
g_hash_table_destroy (hash);
return NULL;
@ -1837,7 +1842,7 @@ g_uri_parse_params (const gchar *params,
value = attr_end + 1;
if (!uri_decode (&decoded_value, value, value_end - value,
0, G_URI_ERROR_MISC, NULL))
www_form, G_URI_FLAGS_NONE, G_URI_ERROR_MISC, NULL))
{
g_free (decoded_attr);
g_hash_table_destroy (hash);
@ -2118,6 +2123,7 @@ g_uri_unescape_segment (const gchar *escaped_string,
if (!uri_decode (&unescaped,
escaped_string, length,
FALSE,
G_URI_FLAGS_PARSE_STRICT,
0, NULL))
return NULL;
@ -2232,6 +2238,7 @@ g_uri_unescape_bytes (const gchar *escaped_string,
unescaped_length = uri_decoder (&buf,
escaped_string, length,
FALSE,
FALSE,
G_URI_FLAGS_PARSE_STRICT|G_URI_FLAGS_ENCODED,
0, NULL);
if (unescaped_length == -1)

View File

@ -226,6 +226,7 @@ GUriFlags g_uri_get_flags (GUri *uri);
* GUriParamsFlags:
* @G_URI_PARAMS_NONE: No flags set.
* @G_URI_PARAMS_CASE_INSENSITIVE: whether parameter names are case insensitive.
* @G_URI_PARAMS_WWW_FORM: replace `+` with space character.
*
* Flags modifying the way parameters are handled.
*
@ -235,6 +236,7 @@ GLIB_AVAILABLE_TYPE_IN_2_66
typedef enum {
G_URI_PARAMS_NONE = 0,
G_URI_PARAMS_CASE_INSENSITIVE = 1 << 0,
G_URI_PARAMS_WWW_FORM = 1 << 1,
} GUriParamsFlags;
GLIB_AVAILABLE_IN_2_66

View File

@ -1288,6 +1288,10 @@ test_uri_parse_params (gconstpointer test_data)
{ "=%", "&", G_URI_PARAMS_NONE, 1, { "", "%", NULL, }},
{ "=", "&", G_URI_PARAMS_NONE, 1, { "", "", NULL, }},
{ "foo", "&", G_URI_PARAMS_NONE, -1, { NULL, }},
{ "foo=bar+%26+baz&saisons=%C3%89t%C3%A9%2Bhiver", "&", G_URI_PARAMS_WWW_FORM,
2, { "foo", "bar & baz", "saisons", "Été+hiver", NULL, }},
{ "foo=bar+%26+baz&saisons=%C3%89t%C3%A9%2Bhiver", "&", G_URI_PARAMS_NONE,
2, { "foo", "bar+&+baz", "saisons", "Été+hiver", NULL, }},
};
gsize i;