From 8b34c2c538f182fe29af58f5153b9dd7cdbaf7fa Mon Sep 17 00:00:00 2001 From: Waldo Bastian Date: Mon, 12 Sep 2005 08:19:33 +0000 Subject: * dbus/dbus-marshal-validate.c, doc/dbus-specification.xml, test/Makefile.am, test/test-names.c: allow hyphens in bus names. --- ChangeLog | 6 ++ dbus/dbus-marshal-validate.c | 127 +++++++++++++++++++++++++++++-------------- doc/dbus-specification.xml | 51 +++++++++++++---- test/.cvsignore | 1 + test/Makefile.am | 8 ++- test/test-names.c | 79 +++++++++++++++++++++++++++ 6 files changed, 219 insertions(+), 53 deletions(-) create mode 100644 test/test-names.c diff --git a/ChangeLog b/ChangeLog index ebb200fc..68507f6a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2005-09-12 Waldo Bastian + + * 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 * test/data/auth/fallback.auth-script: we don't diff --git a/dbus/dbus-marshal-validate.c b/dbus/dbus-marshal-validate.c index 92050a59..e9aa26a8 100644 --- a/dbus/dbus-marshal-validate.c +++ b/dbus/dbus-marshal-validate.c @@ -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,15 +922,47 @@ _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) +/** + * 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) == '-')) + +/** + * 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 + * the D-BUS protocol. This includes a length restriction, etc., see + * the specification. + * + * @todo this is inconsistent with most of DBusString in that + * it allows a start,len range that extends past the string end. + * + * @param str the string + * @param start first byte index to check + * @param len number of bytes to check + * @returns #TRUE if the byte range exists and is a valid name + */ +dbus_bool_t +_dbus_validate_bus_name (const DBusString *str, + int start, + int len) { const unsigned char *s; const unsigned char *end; - const unsigned char *name; + const unsigned char *iface; + const unsigned char *last_dot; _dbus_assert (start >= 0); _dbus_assert (len >= 0); @@ -942,12 +974,47 @@ _dbus_validate_unique_name (const DBusString *str, if (len > DBUS_MAXIMUM_NAME_LENGTH) return FALSE; - _dbus_assert (len > 0); + if (len == 0) + return FALSE; - name = _dbus_string_get_const_data (str) + start; - end = name + len; - _dbus_assert (*name == ':'); - s = name + 1; + 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; + else + ++s; while (s != end) { @@ -955,11 +1022,12 @@ _dbus_validate_unique_name (const DBusString *str, { if (_DBUS_UNLIKELY ((s + 1) == end)) return FALSE; - if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*(s + 1)))) + 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_NAME_CHARACTER (*s))) + else if (_DBUS_UNLIKELY (!VALID_BUS_NAME_CHARACTER (*s))) { return FALSE; } @@ -967,33 +1035,10 @@ _dbus_validate_unique_name (const DBusString *str, ++s; } - return TRUE; -} - -/** - * Checks that the given range of the string is a valid bus name in - * the D-BUS protocol. This includes a length restriction, etc., see - * the specification. - * - * @todo this is inconsistent with most of DBusString in that - * it allows a start,len range that extends past the string end. - * - * @param str the string - * @param start first byte index to check - * @param len number of bytes to check - * @returns #TRUE if the byte range exists and is a valid name - */ -dbus_bool_t -_dbus_validate_bus_name (const DBusString *str, - int start, - int len) -{ - if (_DBUS_UNLIKELY (len == 0)) + if (_DBUS_UNLIKELY (last_dot == NULL)) 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); + + return TRUE; } /** diff --git a/doc/dbus-specification.xml b/doc/dbus-specification.xml index 0ea43a87..0194ff42 100644 --- a/doc/dbus-specification.xml +++ b/doc/dbus-specification.xml @@ -974,7 +974,7 @@ additional restrictions that apply to interface names specifically: - They are composed of 1 or more elements separated by + Interface names are composed of 1 or more elements separated by a period ('.') character. All elements must contain at least one character. @@ -984,25 +984,54 @@ - They must contain at least one '.' (period) + Interface names must contain at least one '.' (period) character (and thus at least two elements). - They must not begin with a '.' (period) character. - They must not exceed the maximum name length. + Interface names must not begin with a '.' (period) character. + Interface names must not exceed the maximum name length. Bus names - 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 STRING, + meaning that it must be valid UTF-8. However, there are also + some additional restrictions that apply to bus names + specifically: + + Bus names that start with a colon (':') + character are unique connection names. + + + Bus names are composed of 1 or more elements separated by + a period ('.') character. All elements must contain at least + one character. + + + 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. + + + + Bus names must contain at least one '.' (period) + character (and thus at least two elements). + + + Bus names must not begin with a '.' (period) character. + Bus names must not exceed the maximum name length. + + + + Note that the hyphen ('-') character is allowed in bus names but + not in interface names. diff --git a/test/.cvsignore b/test/.cvsignore index 20de1a28..f7a65876 100644 --- a/test/.cvsignore +++ b/test/.cvsignore @@ -22,3 +22,4 @@ test-sleep-forever decode-gcov shell-test test-shell-service +test-names diff --git a/test/Makefile.am b/test/Makefile.am index e0a25aa4..5f904887 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -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) diff --git a/test/test-names.c b/test/test-names.c new file mode 100644 index 00000000..b29648dc --- /dev/null +++ b/test/test-names.c @@ -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; +} -- cgit