* dbus/dbus-marshal-validate.c, doc/dbus-specification.xml,

test/Makefile.am, test/test-names.c: allow hyphens in bus names.
This commit is contained in:
Waldo Bastian 2005-09-12 08:19:33 +00:00
parent 5e8110d79a
commit 8b34c2c538
6 changed files with 230 additions and 64 deletions

View file

@ -1,3 +1,9 @@
2005-09-12 Waldo Bastian <bastian@kde.org>
* dbus/dbus-marshal-validate.c,
doc/dbus-specification.xml, test/Makefile.am,
test/test-names.c: allow hyphens in bus names.
2005-09-11 Mark McLoughlin <mark@skynet.ie>
* test/data/auth/fallback.auth-script: we don't

View file

@ -677,7 +677,7 @@ _dbus_validate_body_with_reason (const DBusString *expected_signature,
}
/**
* Determine wether the given charater is valid as the first charater
* Determine wether the given character is valid as the first character
* in a name.
*/
#define VALID_INITIAL_NAME_CHARACTER(c) \
@ -686,7 +686,7 @@ _dbus_validate_body_with_reason (const DBusString *expected_signature,
((c) == '_') )
/**
* Determine wether the given charater is valid as a second or later
* Determine wether the given character is valid as a second or later
* character in a name
*/
#define VALID_NAME_CHARACTER(c) \
@ -922,53 +922,24 @@ _dbus_validate_error_name (const DBusString *str,
return _dbus_validate_interface (str, start, len);
}
/* This assumes the first char exists and is ':' */
static dbus_bool_t
_dbus_validate_unique_name (const DBusString *str,
int start,
int len)
{
const unsigned char *s;
const unsigned char *end;
const unsigned char *name;
/**
* Determine wether the given character is valid as the first character
* in a bus name.
*/
#define VALID_INITIAL_BUS_NAME_CHARACTER(c) \
( ((c) >= 'A' && (c) <= 'Z') || \
((c) >= 'a' && (c) <= 'z') || \
((c) == '_') || ((c) == '-'))
_dbus_assert (start >= 0);
_dbus_assert (len >= 0);
_dbus_assert (start <= _dbus_string_get_length (str));
if (len > _dbus_string_get_length (str) - start)
return FALSE;
if (len > DBUS_MAXIMUM_NAME_LENGTH)
return FALSE;
_dbus_assert (len > 0);
name = _dbus_string_get_const_data (str) + start;
end = name + len;
_dbus_assert (*name == ':');
s = name + 1;
while (s != end)
{
if (*s == '.')
{
if (_DBUS_UNLIKELY ((s + 1) == end))
return FALSE;
if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*(s + 1))))
return FALSE;
++s; /* we just validated the next char, so skip two */
}
else if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s)))
{
return FALSE;
}
++s;
}
return TRUE;
}
/**
* Determine wether the given character is valid as a second or later
* character in a bus name
*/
#define VALID_BUS_NAME_CHARACTER(c) \
( ((c) >= '0' && (c) <= '9') || \
((c) >= 'A' && (c) <= 'Z') || \
((c) >= 'a' && (c) <= 'z') || \
((c) == '_') || ((c) == '-'))
/**
* Checks that the given range of the string is a valid bus name in
@ -988,12 +959,86 @@ _dbus_validate_bus_name (const DBusString *str,
int start,
int len)
{
if (_DBUS_UNLIKELY (len == 0))
const unsigned char *s;
const unsigned char *end;
const unsigned char *iface;
const unsigned char *last_dot;
_dbus_assert (start >= 0);
_dbus_assert (len >= 0);
_dbus_assert (start <= _dbus_string_get_length (str));
if (len > _dbus_string_get_length (str) - start)
return FALSE;
if (len > DBUS_MAXIMUM_NAME_LENGTH)
return FALSE;
if (len == 0)
return FALSE;
last_dot = NULL;
iface = _dbus_string_get_const_data (str) + start;
end = iface + len;
s = iface;
/* check special cases of first char so it doesn't have to be done
* in the loop. Note we know len > 0
*/
if (*s == ':')
{
/* unique name */
++s;
while (s != end)
{
if (*s == '.')
{
if (_DBUS_UNLIKELY ((s + 1) == end))
return FALSE;
if (_DBUS_UNLIKELY (!VALID_BUS_NAME_CHARACTER (*(s + 1))))
return FALSE;
++s; /* we just validated the next char, so skip two */
}
else if (_DBUS_UNLIKELY (!VALID_BUS_NAME_CHARACTER (*s)))
{
return FALSE;
}
++s;
}
return TRUE;
}
else if (_DBUS_UNLIKELY (*s == '.')) /* disallow starting with a . */
return FALSE;
else if (_DBUS_UNLIKELY (!VALID_INITIAL_BUS_NAME_CHARACTER (*s)))
return FALSE;
if (_dbus_string_get_byte (str, start) == ':')
return _dbus_validate_unique_name (str, start, len);
else
return _dbus_validate_interface (str, start, len);
++s;
while (s != end)
{
if (*s == '.')
{
if (_DBUS_UNLIKELY ((s + 1) == end))
return FALSE;
else if (_DBUS_UNLIKELY (!VALID_INITIAL_BUS_NAME_CHARACTER (*(s + 1))))
return FALSE;
last_dot = s;
++s; /* we just validated the next char, so skip two */
}
else if (_DBUS_UNLIKELY (!VALID_BUS_NAME_CHARACTER (*s)))
{
return FALSE;
}
++s;
}
if (_DBUS_UNLIKELY (last_dot == NULL))
return FALSE;
return TRUE;
}
/**

View file

@ -974,7 +974,7 @@
additional restrictions that apply to interface names
specifically:
<itemizedlist>
<listitem><para>They are composed of 1 or more elements separated by
<listitem><para>Interface names are composed of 1 or more elements separated by
a period ('.') character. All elements must contain at least
one character.
</para>
@ -984,25 +984,54 @@
</para>
</listitem>
<listitem><para>They must contain at least one '.' (period)
<listitem><para>Interface names must contain at least one '.' (period)
character (and thus at least two elements).
</para></listitem>
<listitem><para>They must not begin with a '.' (period) character.</para></listitem>
<listitem><para>They must not exceed the maximum name length.</para></listitem>
<listitem><para>Interface names must not begin with a '.' (period) character.</para></listitem>
<listitem><para>Interface names must not exceed the maximum name length.</para></listitem>
</itemizedlist>
</para>
</sect3>
<sect3 id="message-protocol-names-bus">
<title>Bus names</title>
<para>
Bus names have the same restrictions as interface names, with a
special exception for unique connection names. A unique name's first
element must start with a colon (':') character. After the colon, any
characters in "[A-Z][a-z][0-9]_" may appear. Elements after
the first must follow the usual rules, except that they may start with
a digit. Bus names not starting with a colon have none of these
exceptions and follow the same rules as interface names.
Connections have one or more bus names associated with them.
A connection has exactly one bus name that is a unique connection
name. The unique connection name remains with the connection for
its entire lifetime.
A bus name is of type <literal>STRING</literal>,
meaning that it must be valid UTF-8. However, there are also
some additional restrictions that apply to bus names
specifically:
<itemizedlist>
<listitem><para>Bus names that start with a colon (':')
character are unique connection names.
</para>
</listitem>
<listitem><para>Bus names are composed of 1 or more elements separated by
a period ('.') character. All elements must contain at least
one character.
</para>
</listitem>
<listitem><para>Each element must only contain the ASCII characters
"[A-Z][a-z][0-9]_-". Only elements that are part of a unique
connection name may begin with a digit, elements in
other bus names must not begin with a digit.
</para>
</listitem>
<listitem><para>Bus names must contain at least one '.' (period)
character (and thus at least two elements).
</para></listitem>
<listitem><para>Bus names must not begin with a '.' (period) character.</para></listitem>
<listitem><para>Bus names must not exceed the maximum name length.</para></listitem>
</itemizedlist>
</para>
<para>
Note that the hyphen ('-') character is allowed in bus names but
not in interface names.
</para>
</sect3>
<sect3 id="message-protocol-names-member">

View file

@ -22,3 +22,4 @@ test-sleep-forever
decode-gcov
shell-test
test-shell-service
test-names

View file

@ -14,7 +14,7 @@ INCLUDES=-I$(top_srcdir) $(DBUS_TEST_CFLAGS)
if DBUS_BUILD_TESTS
## break-loader removed for now
TEST_BINARIES=test-service test-shell-service shell-test spawn-test test-segfault test-exit test-sleep-forever
TEST_BINARIES=test-service test-names test-shell-service shell-test spawn-test test-segfault test-exit test-sleep-forever
#enable stand alone make check test
TESTS=shell-test
@ -36,6 +36,11 @@ test_service_SOURCES= \
test-utils.c \
test-utils.h
test_names_SOURCES= \
test-names.c \
test-utils.c \
test-utils.h
##break_loader_SOURCES= \
## break-loader.c
@ -65,6 +70,7 @@ decode_gcov_SOURCES= \
TEST_LIBS=$(DBUS_TEST_LIBS) $(top_builddir)/dbus/libdbus-convenience.la
test_service_LDADD=$(TEST_LIBS)
test_names_LDADD=$(TEST_LIBS)
## break_loader_LDADD= $(TEST_LIBS)
test_shell_service_LDADD=$(TEST_LIBS)
shell_test_LDADD=$(TEST_LIBS)

79
test/test-names.c Normal file
View file

@ -0,0 +1,79 @@
#include "test-utils.h"
static DBusLoop *loop;
static void
die (const char *message)
{
fprintf (stderr, "*** test-names: %s", message);
exit (1);
}
static void
TestName(DBusConnection *connection, const char *name, int expectedSuccess)
{
DBusError error;
dbus_error_init (&error);
(void) dbus_bus_request_name (connection, name, 0, &error);
if (dbus_error_is_set (&error))
{
if (expectedSuccess)
fprintf (stderr, "Error acquiring name '%s': %s\n", name, error.message);
else
fprintf (stdout, "Expected Error acquiring name '%s': %s\n", name, error.message);
_dbus_verbose ("*** Failed to acquire name '%s': %s\n", name,
error.message);
dbus_error_free (&error);
if (expectedSuccess)
exit (1);
}
else
{
if (!expectedSuccess)
fprintf (stderr, "Unexpected Success acquiring name '%s'\n", name);
else
fprintf (stdout, "Successfully acquired name '%s'\n", name);
_dbus_verbose ("*** Managed to acquire name '%s'\n", name);
if (!expectedSuccess)
exit (1);
}
}
int
main (int argc,
char **argv)
{
DBusError error;
int result;
DBusConnection *connection;
dbus_error_init (&error);
connection = dbus_bus_get (DBUS_BUS_SESSION, &error);
if (connection == NULL)
{
fprintf (stderr, "*** Failed to open connection to system bus: %s\n",
error.message);
dbus_error_free (&error);
return 1;
}
loop = _dbus_loop_new ();
if (loop == NULL)
die ("No memory\n");
if (!test_connection_setup (loop, connection))
die ("No memory\n");
TestName(connection, "org.freedesktop.DBus.Test", TRUE);
TestName(connection, "org.freedesktop.DBus.Test-2", TRUE);
TestName(connection, "org.freedesktop.DBus.Test_2", TRUE);
#if 0
TestName(connection, "Test_2", TRUE);
#endif
_dbus_verbose ("*** Test service name exiting\n");
return 0;
}