mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-26 07:26:15 +01:00
uri: change parse_params() to take a separator set
This should give a bit more flexibility, without drawbacks. Many URI encoding accept either '&' or ';' as separators. Change the documentation to reflect that '&' is probably more common (http query string). Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
This commit is contained in:
parent
db9987d269
commit
d022b7199b
@ -10,7 +10,7 @@ LLVMFuzzerTestOneInput (const unsigned char *data, size_t size)
|
|||||||
if (size > G_MAXSSIZE)
|
if (size > G_MAXSSIZE)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
parsed_params = g_uri_parse_params ((const gchar *) data, (gssize) size, '&', FALSE);
|
parsed_params = g_uri_parse_params ((const gchar *) data, (gssize) size, "&", FALSE);
|
||||||
if (parsed_params == NULL)
|
if (parsed_params == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
30
glib/guri.c
30
glib/guri.c
@ -1750,8 +1750,11 @@ str_ascii_case_equal (gconstpointer v1,
|
|||||||
* @params: a `%`-encoded string containing "attribute=value"
|
* @params: a `%`-encoded string containing "attribute=value"
|
||||||
* parameters
|
* parameters
|
||||||
* @length: the length of @params, or -1 if it is NUL-terminated
|
* @length: the length of @params, or -1 if it is NUL-terminated
|
||||||
* @separator: the separator character between parameters.
|
* @separators: the separator byte character set between parameters. (usually
|
||||||
* (usually ';', but sometimes '&')
|
* "&", but sometimes ";" or both "&;"). Note that this function works on
|
||||||
|
* bytes not characters, so it can't be used to delimit UTF-8 strings for
|
||||||
|
* anything but ASCII characters. You may pass an empty set, in which case
|
||||||
|
* no splitting will occur.
|
||||||
* @case_insensitive: whether parameter names are case insensitive
|
* @case_insensitive: whether parameter names are case insensitive
|
||||||
*
|
*
|
||||||
* Many URI schemes include one or more attribute/value pairs as part of the URI
|
* Many URI schemes include one or more attribute/value pairs as part of the URI
|
||||||
@ -1759,7 +1762,7 @@ str_ascii_case_equal (gconstpointer v1,
|
|||||||
*
|
*
|
||||||
* 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 @separator, 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 non-%G_URI_FLAGS_PARSE_STRICT
|
||||||
* 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 with %G_URI_FLAGS_PARSE_STRICT and
|
||||||
@ -1768,7 +1771,7 @@ str_ascii_case_equal (gconstpointer v1,
|
|||||||
*
|
*
|
||||||
* Return value: (transfer full) (element-type utf8 utf8): a hash table of
|
* Return value: (transfer full) (element-type utf8 utf8): a hash table of
|
||||||
* attribute/value pairs. Both names and values will be fully-decoded. If
|
* attribute/value pairs. Both names and values will be fully-decoded. If
|
||||||
* @params cannot be parsed (eg, it contains two @separator characters in a
|
* @params cannot be parsed (eg, it contains two @separators characters in a
|
||||||
* row), then %NULL is returned.
|
* row), then %NULL is returned.
|
||||||
*
|
*
|
||||||
* Since: 2.66
|
* Since: 2.66
|
||||||
@ -1776,15 +1779,17 @@ str_ascii_case_equal (gconstpointer v1,
|
|||||||
GHashTable *
|
GHashTable *
|
||||||
g_uri_parse_params (const gchar *params,
|
g_uri_parse_params (const gchar *params,
|
||||||
gssize length,
|
gssize length,
|
||||||
gchar separator,
|
const gchar *separators,
|
||||||
gboolean case_insensitive)
|
gboolean case_insensitive)
|
||||||
{
|
{
|
||||||
GHashTable *hash;
|
GHashTable *hash;
|
||||||
const gchar *end, *attr, *attr_end, *value, *value_end;
|
const gchar *end, *attr, *attr_end, *value, *value_end, *s;
|
||||||
gchar *decoded_attr, *decoded_value;
|
gchar *decoded_attr, *decoded_value;
|
||||||
|
guint8 sep_table[256]; /* 1 = index is a separator; 0 otherwise */
|
||||||
|
|
||||||
g_return_val_if_fail (length == 0 || params != NULL, NULL);
|
g_return_val_if_fail (length == 0 || params != NULL, NULL);
|
||||||
g_return_val_if_fail (length >= -1, NULL);
|
g_return_val_if_fail (length >= -1, NULL);
|
||||||
|
g_return_val_if_fail (separators != NULL, NULL);
|
||||||
|
|
||||||
if (case_insensitive)
|
if (case_insensitive)
|
||||||
{
|
{
|
||||||
@ -1803,12 +1808,19 @@ g_uri_parse_params (const gchar *params,
|
|||||||
else
|
else
|
||||||
end = params + length;
|
end = params + length;
|
||||||
|
|
||||||
|
memset (sep_table, FALSE, sizeof (sep_table));
|
||||||
|
for (s = separators; *s != '\0'; ++s)
|
||||||
|
sep_table[*(guchar *)s] = TRUE;
|
||||||
|
|
||||||
attr = params;
|
attr = params;
|
||||||
while (attr < end)
|
while (attr < end)
|
||||||
{
|
{
|
||||||
value_end = memchr (attr, separator, end - attr);
|
/* Check if each character in @attr is a separator, by indexing by the
|
||||||
if (!value_end)
|
* character value into the @sep_table, which has value 1 stored at an
|
||||||
value_end = end;
|
* index if that index is a separator. */
|
||||||
|
for (value_end = attr; value_end < end; value_end++)
|
||||||
|
if (sep_table[*(guchar *)value_end])
|
||||||
|
break;
|
||||||
|
|
||||||
attr_end = memchr (attr, '=', value_end - attr);
|
attr_end = memchr (attr, '=', value_end - attr);
|
||||||
if (!attr_end)
|
if (!attr_end)
|
||||||
|
@ -225,7 +225,7 @@ GUriFlags g_uri_get_flags (GUri *uri);
|
|||||||
GLIB_AVAILABLE_IN_2_66
|
GLIB_AVAILABLE_IN_2_66
|
||||||
GHashTable * g_uri_parse_params (const gchar *params,
|
GHashTable * g_uri_parse_params (const gchar *params,
|
||||||
gssize length,
|
gssize length,
|
||||||
gchar separator,
|
const gchar *separators,
|
||||||
gboolean case_insensitive);
|
gboolean case_insensitive);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1270,22 +1270,24 @@ test_uri_parse_params (gconstpointer test_data)
|
|||||||
{
|
{
|
||||||
/* Inputs */
|
/* Inputs */
|
||||||
const gchar *uri;
|
const gchar *uri;
|
||||||
gchar separator;
|
gchar *separators;
|
||||||
gboolean case_insensitive;
|
gboolean case_insensitive;
|
||||||
/* Outputs */
|
/* Outputs */
|
||||||
gssize expected_n_params; /* -1 => error expected */
|
gssize expected_n_params; /* -1 => error expected */
|
||||||
/* key, value, key, value, …, limited to length 2*expected_n_params */
|
/* key, value, key, value, …, limited to length 2*expected_n_params */
|
||||||
const gchar *expected_param_key_values[4];
|
const gchar *expected_param_key_values[6];
|
||||||
}
|
}
|
||||||
tests[] =
|
tests[] =
|
||||||
{
|
{
|
||||||
{ "", '&', FALSE, 0, { NULL, }},
|
{ "", "&", FALSE, 0, { NULL, }},
|
||||||
{ "p1=foo&p2=bar", '&', FALSE, 2, { "p1", "foo", "p2", "bar" }},
|
{ "p1=foo&p2=bar", "&", FALSE, 2, { "p1", "foo", "p2", "bar" }},
|
||||||
{ "p1=foo&&P1=bar", '&', FALSE, -1, { NULL, }},
|
{ "p1=foo&p2=bar;p3=baz", "&;", FALSE, 3, { "p1", "foo", "p2", "bar", "p3", "baz" }},
|
||||||
{ "%00=foo", '&', FALSE, -1, { NULL, }},
|
{ "p1=foo&p2=bar", "", FALSE, 1, { "p1", "foo&p2=bar" }},
|
||||||
{ "p1=%00", '&', FALSE, -1, { NULL, }},
|
{ "p1=foo&&P1=bar", "&", FALSE, -1, { NULL, }},
|
||||||
{ "p1=foo&P1=bar", '&', TRUE, 1, { "p1", "bar", NULL, }},
|
{ "%00=foo", "&", FALSE, -1, { NULL, }},
|
||||||
{ "=%", '&', FALSE, 1, { "", "%", NULL, }},
|
{ "p1=%00", "&", FALSE, -1, { NULL, }},
|
||||||
|
{ "p1=foo&P1=bar", "&", TRUE, 1, { "p1", "bar", NULL, }},
|
||||||
|
{ "=%", "&", FALSE, 1, { "", "%", NULL, }},
|
||||||
};
|
};
|
||||||
gsize i;
|
gsize i;
|
||||||
|
|
||||||
@ -1315,7 +1317,7 @@ test_uri_parse_params (gconstpointer test_data)
|
|||||||
uri = g_memdup (tests[i].uri, uri_len);
|
uri = g_memdup (tests[i].uri, uri_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
params = g_uri_parse_params (uri, uri_len, tests[i].separator, tests[i].case_insensitive);
|
params = g_uri_parse_params (uri, uri_len, tests[i].separators, tests[i].case_insensitive);
|
||||||
|
|
||||||
if (tests[i].expected_n_params < 0)
|
if (tests[i].expected_n_params < 0)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user