mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-11-09 02:46:16 +01:00
Add g_dbus_utils_object_path_escape and g_dbus_utils_object_path_unescape
These two APIs are useful to publish an object which path content is not controlled (e.g. dynamically built or coming from external source). Closes #968 (Rebased and tweaked by Frederic Martinsons) Signed-off-by: Frederic Martinsons <frederic.martinsons@sigfox.com>
This commit is contained in:
parent
86aec50c0a
commit
47355c358d
@ -2804,6 +2804,9 @@ g_dbus_is_member_name
|
||||
g_dbus_is_interface_name
|
||||
g_dbus_gvalue_to_gvariant
|
||||
g_dbus_gvariant_to_gvalue
|
||||
g_dbus_escape_object_path_bytestring
|
||||
g_dbus_escape_object_path
|
||||
g_dbus_unescape_object_path
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
|
124
gio/gdbusutils.c
124
gio/gdbusutils.c
@ -693,3 +693,127 @@ g_dbus_gvalue_to_gvariant (const GValue *gvalue,
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_dbus_escape_object_path_bytestring:
|
||||
* @bytes: (array zero-terminated=1) (element-type guint8): the string of bytes to escape
|
||||
*
|
||||
* Escapes @bytes for use in a D-Bus object path component.
|
||||
* @bytes is an array of zero or more nonzero bytes in an
|
||||
* unspecified encoding, followed by a single zero byte.
|
||||
*
|
||||
* The escaping method consists of replacing all non-alphanumeric
|
||||
* characters (see g_ascii_isalnum()) with their hexadecimal value
|
||||
* preceded by an underscore (`_`). For example:
|
||||
* `foo.bar.baz` will become `foo_2ebar_2ebaz`.
|
||||
*
|
||||
* This method is appropriate to use when the input is nearly
|
||||
* a valid object path component but is not when your input
|
||||
* is far from being a valid object path component.
|
||||
* Other escaping algorithms are also valid to use with
|
||||
* D-Bus object paths.
|
||||
*
|
||||
* This can be reversed with g_dbus_unescape_object_path().
|
||||
*
|
||||
* Returns: an escaped version of @bytes. Free with g_free().
|
||||
*
|
||||
* Since: 2.68
|
||||
*
|
||||
*/
|
||||
gchar *
|
||||
g_dbus_escape_object_path_bytestring (const guint8 *bytes)
|
||||
{
|
||||
GString *escaped;
|
||||
const guint8 *p;
|
||||
|
||||
g_return_val_if_fail (bytes != NULL, NULL);
|
||||
|
||||
if (*bytes == '\0')
|
||||
return g_strdup ("_");
|
||||
|
||||
escaped = g_string_new (NULL);
|
||||
for (p = bytes; *p; p++)
|
||||
{
|
||||
if (g_ascii_isalnum (*p))
|
||||
g_string_append_c (escaped, *p);
|
||||
else
|
||||
g_string_append_printf (escaped, "_%02x", *p);
|
||||
}
|
||||
|
||||
return g_string_free (escaped, FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_dbus_escape_object_path:
|
||||
* @s: the string to escape
|
||||
*
|
||||
* This is a language binding friendly version of g_dbus_escape_object_path_bytestring().
|
||||
*
|
||||
* Returns: an escaped version of @s. Free with g_free().
|
||||
*
|
||||
* Since: 2.68
|
||||
*/
|
||||
gchar *
|
||||
g_dbus_escape_object_path (const gchar *s)
|
||||
{
|
||||
return (gchar *) g_dbus_escape_object_path_bytestring ((const guint8 *) s);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_dbus_unescape_object_path:
|
||||
* @s: the string to unescape
|
||||
*
|
||||
* Unescapes an string that was previously escaped with
|
||||
* g_dbus_escape_object_path(). If the string is in a format that could
|
||||
* not have been returned by g_dbus_escape_object_path(), this function
|
||||
* returns %NULL.
|
||||
*
|
||||
* Encoding alphanumeric characters which do not need to be
|
||||
* encoded is not allowed (e.g `_63` is not valid, the string
|
||||
* should contain `c` instead).
|
||||
*
|
||||
* Returns: (array zero-terminated=1) (element-type guint8) (nullable): an
|
||||
* unescaped version of @s, or %NULL if @s is not a string returned
|
||||
* from g_dbus_escape_object_path(). Free with g_free().
|
||||
*
|
||||
* Since: 2.68
|
||||
*/
|
||||
guint8 *
|
||||
g_dbus_unescape_object_path (const gchar *s)
|
||||
{
|
||||
GString *unescaped;
|
||||
const gchar *p;
|
||||
|
||||
g_return_val_if_fail (s != NULL, NULL);
|
||||
|
||||
if (g_str_equal (s, "_"))
|
||||
return (guint8 *) g_strdup ("");
|
||||
|
||||
unescaped = g_string_new (NULL);
|
||||
for (p = s; *p; p++)
|
||||
{
|
||||
gint hi, lo;
|
||||
|
||||
if (g_ascii_isalnum (*p))
|
||||
{
|
||||
g_string_append_c (unescaped, *p);
|
||||
}
|
||||
else if (*p == '_' &&
|
||||
((hi = g_ascii_xdigit_value (p[1])) >= 0) &&
|
||||
((lo = g_ascii_xdigit_value (p[2])) >= 0) &&
|
||||
(hi || lo) && /* \0 is not allowed */
|
||||
!g_ascii_isalnum ((hi << 4) | lo)) /* alnums must not be encoded */
|
||||
{
|
||||
g_string_append_c (unescaped, (hi << 4) | lo);
|
||||
p += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* the string was not encoded correctly */
|
||||
g_string_free (unescaped, TRUE);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return (guint8 *) g_string_free (unescaped, FALSE);
|
||||
}
|
||||
|
@ -49,6 +49,12 @@ void g_dbus_gvariant_to_gvalue (GVariant *value,
|
||||
GLIB_AVAILABLE_IN_ALL
|
||||
GVariant *g_dbus_gvalue_to_gvariant (const GValue *gvalue,
|
||||
const GVariantType *type);
|
||||
GLIB_AVAILABLE_IN_2_68
|
||||
gchar *g_dbus_escape_object_path_bytestring (const guint8 *bytes);
|
||||
GLIB_AVAILABLE_IN_2_68
|
||||
gchar *g_dbus_escape_object_path (const gchar *s);
|
||||
GLIB_AVAILABLE_IN_2_68
|
||||
guint8 *g_dbus_unescape_object_path (const gchar *s);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@ -769,6 +769,49 @@ test_validate_names (void)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
assert_cmp_escaped_object_path (const gchar *s,
|
||||
const gchar *correct_escaped)
|
||||
{
|
||||
gchar *escaped;
|
||||
guint8 *unescaped;
|
||||
|
||||
escaped = g_dbus_escape_object_path (s);
|
||||
g_assert_cmpstr (escaped, ==, correct_escaped);
|
||||
|
||||
g_free (escaped);
|
||||
escaped = g_dbus_escape_object_path_bytestring ((const guint8 *) s);
|
||||
g_assert_cmpstr (escaped, ==, correct_escaped);
|
||||
|
||||
unescaped = g_dbus_unescape_object_path (escaped);
|
||||
g_assert_cmpstr ((const gchar *) unescaped, ==, s);
|
||||
|
||||
g_free (escaped);
|
||||
g_free (unescaped);
|
||||
}
|
||||
|
||||
static void
|
||||
test_escape_object_path (void)
|
||||
{
|
||||
assert_cmp_escaped_object_path ("Foo42", "Foo42");
|
||||
assert_cmp_escaped_object_path ("foo.bar.baz", "foo_2ebar_2ebaz");
|
||||
assert_cmp_escaped_object_path ("foo_bar_baz", "foo_5fbar_5fbaz");
|
||||
assert_cmp_escaped_object_path ("_", "_5f");
|
||||
assert_cmp_escaped_object_path ("__", "_5f_5f");
|
||||
assert_cmp_escaped_object_path ("", "_");
|
||||
assert_cmp_escaped_object_path (":1.42", "_3a1_2e42");
|
||||
assert_cmp_escaped_object_path ("a/b", "a_2fb");
|
||||
assert_cmp_escaped_object_path (" ", "_20");
|
||||
assert_cmp_escaped_object_path ("\n", "_0a");
|
||||
|
||||
g_assert_null (g_dbus_unescape_object_path ("_ii"));
|
||||
g_assert_null (g_dbus_unescape_object_path ("döner"));
|
||||
g_assert_null (g_dbus_unescape_object_path ("_00"));
|
||||
g_assert_null (g_dbus_unescape_object_path ("_61"));
|
||||
g_assert_null (g_dbus_unescape_object_path ("_ga"));
|
||||
g_assert_null (g_dbus_unescape_object_path ("_ag"));
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
int
|
||||
@ -786,6 +829,7 @@ main (int argc,
|
||||
g_test_add_func ("/gdbus/validate-names", test_validate_names);
|
||||
g_test_add_func ("/gdbus/bus-own-name", test_bus_own_name);
|
||||
g_test_add_func ("/gdbus/bus-watch-name", test_bus_watch_name);
|
||||
g_test_add_func ("/gdbus/escape-object-path", test_escape_object_path);
|
||||
|
||||
ret = g_test_run();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user