diff options
| -rw-r--r-- | ChangeLog | 6 | ||||
| -rw-r--r-- | dbus/dbus-marshal-validate.c | 127 | ||||
| -rw-r--r-- | doc/dbus-specification.xml | 51 | ||||
| -rw-r--r-- | test/.cvsignore | 1 | ||||
| -rw-r--r-- | test/Makefile.am | 8 | ||||
| -rw-r--r-- | test/test-names.c | 79 | 
6 files changed, 219 insertions, 53 deletions
| @@ -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 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:            <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"> 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; +} | 
