Commit 1bf3bf19 authored by Pavel Hrdina's avatar Pavel Hrdina

util: Introduce virtDBusUtil(En|De)codeStr helpers

D-Bus object path element can contain only [a-zA-Z0-9_] characters so
we need to encode existing unique IDs.  In case of UUID it's simple, we
just change '-' into '_' but in case of storage volumes we need to use
'key' which is arbitrary string.

This helpers encode the string using this algorithm:

    [a-zA-Z0-9]         >       [a-zA-Z0-9]
    anything else       >       _XX where XX is hex representation
Reviewed-by: default avatarKaterina Koukiou <kkoukiou@redhat.com>
Signed-off-by: Pavel Hrdina's avatarPavel Hrdina <phrdina@redhat.com>
parent 860084e1
......@@ -5,6 +5,7 @@
*Makefile
*Makefile.in
*~
.deps
__pycache__
vgcore.*
......@@ -31,6 +32,7 @@ vgcore.*
/docs/*.1
/src/.deps/
/src/libvirt-dbus
/src/org.libvirt.service
/tests/test_util
......@@ -181,6 +181,70 @@ virtDBusUtilDecodeUUID(const gchar *uuid)
return g_strdelimit(ret, "_", '-');
}
static guchar
virtDBusUtilNumToHexchar(const guchar c)
{
if (c < 10)
return '0' + c;
return 'a' + (c & 0x0f) - 10;
}
static guchar
virtDBusUtilHexcharToNum(const guchar c)
{
if (c >= 'a')
return 10 + c - 'a';
return c - '0';
}
gchar *
virtDBusUtilEncodeStr(const gchar *str)
{
gint len = strlen(str);
gint j = 0;
gchar *ret = g_new(gchar, len * 3 + 1);
for (gint i = 0; i < len; i++) {
guchar c = str[i];
if ((c >= 'A' && c <= 'Z') ||
(c >= 'a' && c <= 'z') ||
(c >= '0' && c <= '9')) {
ret[j++] = c;
} else {
ret[j] = '_';
ret[j + 1] = virtDBusUtilNumToHexchar(c >> 4);
ret[j + 2] = virtDBusUtilNumToHexchar(c);
j += 3;
}
}
ret[j] = 0;
return ret;
}
gchar *
virtDBusUtilDecodeStr(const gchar *str)
{
gint len = strlen(str);
gint j = 0;
gchar *ret = g_new(gchar, len + 1);
for (gint i = 0; i < len; i++) {
gchar c = str[i];
if (c != '_' || (i + 2) >= len) {
ret[j++] = c;
} else {
guchar a = virtDBusUtilHexcharToNum(str[i + 1]);
guchar b = virtDBusUtilHexcharToNum(str[i + 2]);
ret[j++] = (a << 4) + b;
i += 2;
}
}
ret[j] = 0;
return ret;
}
gchar *
virtDBusUtilBusPathForVirDomain(virDomainPtr domain,
const gchar *domainPath)
......
......@@ -42,6 +42,12 @@ virtDBusUtilGVariantToTypedParams(GVariantIter *iter,
void
virtDBusUtilSetLastVirtError(GError **error);
gchar *
virtDBusUtilEncodeStr(const gchar *str);
gchar *
virtDBusUtilDecodeStr(const gchar *str);
gchar *
virtDBusUtilBusPathForVirDomain(virDomainPtr domain,
const gchar *domainPath);
......
......@@ -3,11 +3,31 @@ test_helpers = \
conftest.py
test_programs = \
$(check_PROGRAMS) \
test_connect.py \
test_domain.py \
test_network.py \
test_storage.py
check_PROGRAMS = \
test_util
test_util_SOURCES = \
test_util.c $(top_srcdir)/src/util.c
test_util_CFLAGS = \
-I$(top_srcdir)/src \
$(GIO2_CFLAGS) \
$(GLIB2_CFLAGS) \
$(LIBVIRT_CFLAGS)
test_util_LDFLAGS = \
$(GIO2_LDFLAGS) \
$(GLIB2_LDFLAGS) \
$(LIBVIRT_LDFLAGS)
test_util_LDADD = \
$(GIO2_LIBS) \
$(GLIB2_LIBS) \
$(LIBVIRT_LIBS)
EXTRA_DIST = \
$(test_helpers) \
$(test_programs) \
......
#include "util.h"
static gint
virtTestEncodeStr(const gchar *input,
const gchar *expected)
{
g_autofree gchar *encoded = virtDBusUtilEncodeStr(input);
if (!g_str_equal(encoded, expected)) {
g_printerr("encode failed: expected '%s' actual '%s'\n",
expected, encoded);
return -1;
}
return 0;
}
static gint
virtTestDecodeStr(const gchar *input,
const gchar *expected)
{
g_autofree gchar *decoded = virtDBusUtilDecodeStr(input);
if (!g_str_equal(decoded, expected)) {
g_printerr("decode failed: expected '%s' actual '%s'\n",
expected, decoded);
return -1;
}
return 0;
}
gint
main(void)
{
#define TEST_ENCODE_DECODE(input, output) \
if (virtTestEncodeStr(input, output) < 0) \
return EXIT_FAILURE; \
if (virtTestDecodeStr(output, input) < 0) \
return EXIT_FAILURE;
TEST_ENCODE_DECODE("foobar", "foobar");
TEST_ENCODE_DECODE("_", "_5f");
TEST_ENCODE_DECODE("/path/to/some/file.img", "_2fpath_2fto_2fsome_2ffile_2eimg");
return EXIT_SUCCESS;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment