diff options
| author | Havoc Pennington <hp@redhat.com> | 2003-08-18 15:27:33 +0000 | 
|---|---|---|
| committer | Havoc Pennington <hp@redhat.com> | 2003-08-18 15:27:33 +0000 | 
| commit | 95717a938b237d12211935f6a7467ef610288fe5 (patch) | |
| tree | 9182521c86f31e74ad642eb19b431a433859c85f | |
| parent | 7c3693a53b4eba0db1aebe1edab5ded21eb7757f (diff) | |
2003-08-17  Havoc Pennington  <hp@pobox.com>
	This doesn't compile yet, but syncing up so I can hack on it from
	work. What are branches for if not broken code? ;-)
	* dbus/dbus-protocol.h: remove DBUS_HEADER_FIELD_NAME, add
	DBUS_HEADER_FIELD_INTERFACE, DBUS_HEADER_FIELD_MEMBER,
	DBUS_HEADER_FIELD_ERROR_NAME
	* dbus/dbus-hash.c: Introduce DBUS_HASH_TWO_STRINGS as hack to use
	for the interface+member pairs
	(string_hash): change to use g_str_hash algorithm
	(find_direct_function, find_string_function): refactor these to
	share most code.
	* dbus/dbus-message.c: port all of this over to support
	interface/member fields instead of name field
	* dbus/dbus-object-registry.c: port over
	* dbus/dbus-string.c (_dbus_string_validate_interface): rename
	from _dbus_string_validate_name
	* bus/dbus-daemon-1.1: change file format for the
	<deny>/<allow> stuff to match new message naming scheme
	* bus/policy.c: port over
	* bus/config-parser.c: parse new format
| -rw-r--r-- | ChangeLog | 30 | ||||
| -rw-r--r-- | bus/bus.c | 33 | ||||
| -rw-r--r-- | bus/config-parser.c | 188 | ||||
| -rw-r--r-- | bus/connection.c | 26 | ||||
| -rw-r--r-- | bus/dispatch.c | 47 | ||||
| -rw-r--r-- | bus/policy.c | 76 | ||||
| -rw-r--r-- | bus/policy.h | 12 | ||||
| -rw-r--r-- | dbus/dbus-bus.c | 25 | ||||
| -rw-r--r-- | dbus/dbus-connection.c | 54 | ||||
| -rw-r--r-- | dbus/dbus-hash.c | 378 | ||||
| -rw-r--r-- | dbus/dbus-hash.h | 115 | ||||
| -rw-r--r-- | dbus/dbus-message.c | 386 | ||||
| -rw-r--r-- | dbus/dbus-message.h | 22 | ||||
| -rw-r--r-- | dbus/dbus-object-registry.c | 89 | ||||
| -rw-r--r-- | dbus/dbus-object-registry.h | 6 | ||||
| -rw-r--r-- | dbus/dbus-protocol.h | 55 | ||||
| -rw-r--r-- | dbus/dbus-string.c | 88 | ||||
| -rw-r--r-- | dbus/dbus-string.h | 8 | 
18 files changed, 1224 insertions, 414 deletions
| @@ -1,3 +1,33 @@ +2003-08-17  Havoc Pennington  <hp@pobox.com> + +	This doesn't compile yet, but syncing up so I can hack on it from +	work. What are branches for if not broken code? ;-) +	 +	* dbus/dbus-protocol.h: remove DBUS_HEADER_FIELD_NAME, add +	DBUS_HEADER_FIELD_INTERFACE, DBUS_HEADER_FIELD_MEMBER, +	DBUS_HEADER_FIELD_ERROR_NAME +	 +	* dbus/dbus-hash.c: Introduce DBUS_HASH_TWO_STRINGS as hack to use +	for the interface+member pairs +	(string_hash): change to use g_str_hash algorithm +	(find_direct_function, find_string_function): refactor these to +	share most code. +	 +	* dbus/dbus-message.c: port all of this over to support  +	interface/member fields instead of name field + +	* dbus/dbus-object-registry.c: port over +	 +	* dbus/dbus-string.c (_dbus_string_validate_interface): rename +	from _dbus_string_validate_name + +	* bus/dbus-daemon-1.1: change file format for the  +	<deny>/<allow> stuff to match new message naming scheme + +	* bus/policy.c: port over + +	* bus/config-parser.c: parse new format +	  2003-08-16  Havoc Pennington  <hp@pobox.com>  	* dbus/dbus-object-registry.c (add_and_remove_objects): remove @@ -870,20 +870,21 @@ bus_context_check_security_policy (BusContext     *context,             * the hello message to the bus driver             */            if (recipient == NULL && -              dbus_message_has_name (message, DBUS_MESSAGE_HELLO)) +              dbus_message_has_interface (message, DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS) && +              dbus_message_has_member (message, "Hello"))              {                _dbus_verbose ("security check allowing %s message\n", -                             DBUS_MESSAGE_HELLO); +                             "Hello");                return TRUE;              }            else              {                _dbus_verbose ("security check disallowing non-%s message\n", -                             DBUS_MESSAGE_HELLO); +                             "Hello");                dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,                                "Client tried to send a message other than %s without being registered", -                              DBUS_MESSAGE_HELLO); +                              "Hello");                return FALSE;              } @@ -934,9 +935,14 @@ bus_context_check_security_policy (BusContext     *context,                        "A security policy in place prevents this sender "                        "from sending this message to this recipient, "                        "see message bus configuration file (rejected message " -                      "had name \"%s\" destination \"%s\")", -                      dbus_message_get_name (message), -                      dest ? dest : DBUS_SERVICE_DBUS); +                      "had interface \"%s\" member \"%s\" error name \"%s\" destination \"%s\")", +                      dbus_message_get_interface (message) ? +                      dbus_message_get_interface (message) : "(unset)", +                      dbus_message_get_member (message) ? +                      dbus_message_get_member (message) : "(unset)", +                      dbus_message_get_error_name (message) ? +                      dbus_message_get_error_name (message) : "(unset)", +                      dest ? dest : DBUS_SERVICE_ORG_FREEDESKTOP_DBUS);        _dbus_verbose ("security policy disallowing message due to sender policy\n");        return FALSE;      } @@ -951,9 +957,14 @@ bus_context_check_security_policy (BusContext     *context,                        "A security policy in place prevents this recipient "                        "from receiving this message from this sender, "                        "see message bus configuration file (rejected message " -                      "had name \"%s\" destination \"%s\")", -                      dbus_message_get_name (message), -                      dest ? dest : DBUS_SERVICE_DBUS); +                      "had interface \"%s\" member \"%s\" error name \"%s\" destination \"%s\")", +                      dbus_message_get_interface (message) ? +                      dbus_message_get_interface (message) : "(unset)", +                      dbus_message_get_member (message) ? +                      dbus_message_get_member (message) : "(unset)", +                      dbus_message_get_error_name (message) ? +                      dbus_message_get_error_name (message) : "(unset)", +                      dest ? dest : DBUS_SERVICE_ORG_FREEDESKTOP_DBUS);        _dbus_verbose ("security policy disallowing message due to recipient policy\n");        return FALSE;      } @@ -966,7 +977,7 @@ bus_context_check_security_policy (BusContext     *context,        const char *dest = dbus_message_get_destination (message);        dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,                        "The destination service \"%s\" has a full message queue", -                      dest ? dest : DBUS_SERVICE_DBUS); +                      dest ? dest : DBUS_SERVICE_ORG_FREEDESKTOP_DBUS);        _dbus_verbose ("security policy disallowing message due to full message queue\n");        return FALSE;      } diff --git a/bus/config-parser.c b/bus/config-parser.c index c42278e1..471c67d8 100644 --- a/bus/config-parser.c +++ b/bus/config-parser.c @@ -816,11 +816,15 @@ append_rule_from_element (BusConfigParser   *parser,                            dbus_bool_t        allow,                            DBusError         *error)  { -  const char *send; -  const char *receive; +  const char *send_interface; +  const char *send_member; +  const char *send_error; +  const char *send_service; +  const char *receive_interface; +  const char *receive_member; +  const char *receive_error; +  const char *receive_service;    const char *own; -  const char *send_to; -  const char *receive_from;    const char *user;    const char *group;    BusPolicyRule *rule; @@ -829,57 +833,112 @@ append_rule_from_element (BusConfigParser   *parser,                            attribute_names,                            attribute_values,                            error, -                          "send", &send, -                          "receive", &receive, +                          "send_interface", &send_interface, +                          "send_member", &send_member, +                          "send_error", &send_error, +                          "send_service", &send_service, +                          "receive_interface", &receive_interface, +                          "receive_member", &receive_member, +                          "receive_error", &receive_error, +                          "receive_service", &receive_service,                            "own", &own, -                          "send_to", &send_to, -                          "receive_from", &receive_from,                            "user", &user,                            "group", &group,                            NULL))      return FALSE; -  if (!(send || receive || own || send_to || receive_from || -        user || group)) +  if (!(send_interface || send_member || send_error || send_service || +        receive_interface || receive_member || receive_error || receive_service || +        own || user || group))      {        dbus_set_error (error, DBUS_ERROR_FAILED,                        "Element <%s> must have one or more attributes",                        element_name);        return FALSE;      } -   -  if (((send && own) || -       (send && receive) || -       (send && receive_from) || -       (send && user) || -       (send && group)) || - -      ((receive && own) || -       (receive && send_to) || -       (receive && user) || -       (receive && group)) || - -      ((own && send_to) || -       (own && receive_from) || -       (own && user) || -       (own && group)) || -      ((send_to && receive_from) || -       (send_to && user) || -       (send_to && group)) || +  if ((send_member && send_interface == NULL) || +      (receive_member && receive_interface == NULL)) +    { +      dbus_set_error (error, DBUS_ERROR_FAILED, +                      "On element <%s>, if you specify a member you must specify an interface", +                      element_name); +      return FALSE; +    } +   +  /* Allowed combinations of elements are: +   * +   *   base, must be all send or all receive: +   *     interface +   *     interface + member +   *     error +   *  +   *   base send_ can combine with send_service, +   *   base receive_ with receive_service +   * +   *   user, group, own must occur alone +   */ -      ((receive_from && user) || -       (receive_from && group)) || +  if (((send_interface && send_error) || +       (send_interface && receive_interface) || +       (send_interface && receive_member) || +       (send_interface && receive_error) || +       (send_interface && receive_service) || +       (send_interface && own) || +       (send_interface && user) || +       (send_interface && group)) || + +      ((send_member && send_error) || +       (send_member && receive_interface) || +       (send_member && receive_member) || +       (send_member && receive_error) || +       (send_member && receive_service) || +       (send_member && own) || +       (send_member && user) || +       (send_member && group)) || +       +      ((send_error && receive_interface) || +       (send_error && receive_member) || +       (send_error && receive_error) || +       (send_error && receive_service) || +       (send_error && own) || +       (send_error && user) || +       (send_error && group)) || + +      ((send_service && receive_interface) || +       (send_service && receive_member) || +       (send_service && receive_error) || +       (send_service && receive_service) || +       (send_service && own) || +       (send_service && user) || +       (send_service && group)) || + +      ((receive_interface && receive_error) || +       (receive_interface && own) || +       (receive_interface && user) || +       (receive_interface && group)) || + +      ((receive_member && receive_error) || +       (receive_member && own) || +       (receive_member && user) || +       (receive_member && group)) || + +      ((receive_error && own) || +       (receive_error && user) || +       (receive_error && group)) || + +      ((own && user) || +       (own && group)) || -      (user && group)) +      ((user && group)))      {        dbus_set_error (error, DBUS_ERROR_FAILED,                        "Invalid combination of attributes on element <%s>, " -                      "only send/send_to or receive/receive_from may be paired", +                      "only send_foo/send_service or receive_foo/receive_service may be paired",                        element_name);        return FALSE;      } - +           rule = NULL;    /* In BusPolicyRule, NULL represents wildcard. @@ -887,41 +946,60 @@ append_rule_from_element (BusConfigParser   *parser,     */  #define IS_WILDCARD(str) ((str) && ((str)[0]) == '*' && ((str)[1]) == '\0') -  if (send || send_to) +  if (send_interface || send_member || send_error || send_service)      {        rule = bus_policy_rule_new (BUS_POLICY_RULE_SEND, allow);         if (rule == NULL)          goto nomem; - -      if (IS_WILDCARD (send)) -        send = NULL; -      if (IS_WILDCARD (send_to)) -        send_to = NULL; -      rule->d.send.message_name = _dbus_strdup (send); -      rule->d.send.destination = _dbus_strdup (send_to); -      if (send && rule->d.send.message_name == NULL) +      if (IS_WILDCARD (send_interface)) +        send_interface = NULL; +      if (IS_WILDCARD (send_member)) +        send_member = NULL; +      if (IS_WILDCARD (send_error)) +        send_error = NULL; +      if (IS_WILDCARD (send_service)) +        send_service = NULL; +       +      rule->d.send.interface = _dbus_strdup (send_interface); +      rule->d.send.member = _dbus_strdup (send_member); +      rule->d.send.error = _dbus_strdup (send_error); +      rule->d.send.destination = _dbus_strdup (send_service); +      if (send_interface && rule->d.send.interface == NULL) +        goto nomem; +      if (send_member && rule->d.send.member == NULL)          goto nomem; -      if (send_to && rule->d.send.destination == NULL) +      if (send_error && rule->d.send.error == NULL) +        goto nomem; +      if (send_service && rule->d.send.destination == NULL)          goto nomem;      } -  else if (receive || receive_from) +  else if (receive_interface || receive_member || receive_error || receive_service)      {        rule = bus_policy_rule_new (BUS_POLICY_RULE_RECEIVE, allow);         if (rule == NULL)          goto nomem; - -      if (IS_WILDCARD (receive)) -        receive = NULL; - -      if (IS_WILDCARD (receive_from)) -        receive_from = NULL; -      rule->d.receive.message_name = _dbus_strdup (receive); -      rule->d.receive.origin = _dbus_strdup (receive_from); -      if (receive && rule->d.receive.message_name == NULL) +      if (IS_WILDCARD (receive_interface)) +        receive_interface = NULL; +      if (IS_WILDCARD (receive_member)) +        receive_member = NULL; +      if (IS_WILDCARD (receive_error)) +        receive_error = NULL; +      if (IS_WILDCARD (receive_service)) +        receive_service = NULL; + +      rule->d.receive.interface = _dbus_strdup (receive_interface); +      rule->d.receive.member = _dbus_strdup (receive_member); +      rule->d.receive.error = _dbus_strdup (receive_error); +      rule->d.receive.origin = _dbus_strdup (receive_service); +      if (receive_interface && rule->d.receive.interface == NULL) +        goto nomem; +      if (receive_member && rule->d.receive.member == NULL) +        goto nomem; +      if (receive_error && rule->d.receive.error == NULL)          goto nomem; -      if (receive_from && rule->d.receive.origin == NULL) +      if (receive_service && rule->d.receive.origin == NULL)          goto nomem;      }    else if (own) diff --git a/bus/connection.c b/bus/connection.c index e588039e..4df00bfd 100644 --- a/bus/connection.c +++ b/bus/connection.c @@ -972,10 +972,10 @@ bus_connection_preallocate_oom_error (DBusConnection *connection)      }    /* d->name may be NULL, but that is OK */ -  if (!dbus_message_set_name (message, DBUS_ERROR_NO_MEMORY) || +  if (!dbus_message_set_error_name (message, DBUS_ERROR_NO_MEMORY) ||        !dbus_message_set_destination (message, d->name) ||        !dbus_message_set_sender (message, -                                DBUS_SERVICE_DBUS)) +                                DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))      {        dbus_connection_free_preallocated_send (connection, preallocated);        dbus_message_unref (message); @@ -1312,10 +1312,15 @@ bus_transaction_send_from_driver (BusTransaction *transaction,     * to check security policy since it was not done in     * dispatch.c     */ -  _dbus_verbose ("Sending %s from driver\n", -                 dbus_message_get_name (message)); -   -  if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS)) +  _dbus_verbose ("Sending %s %s %s from driver\n", +                 dbus_message_get_interface (message) ? +                 dbus_message_get_interface (message) : "(no interface)", +                 dbus_message_get_member (message) ? +                 dbus_message_get_member (message) : "(no member)", +                 dbus_message_get_error_name (message) ? +                 dbus_message_get_error_name (message) : "(no error name)"); +                  +  if (!dbus_message_set_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))      return FALSE;    /* If security policy doesn't allow the message, we silently @@ -1337,11 +1342,16 @@ bus_transaction_send (BusTransaction *transaction,    BusConnectionData *d;    DBusList *link; -  _dbus_verbose ("  trying to add %s %s to transaction%s\n", +  _dbus_verbose ("  trying to add %s interface=%s member=%s error=%s to transaction%s\n",                   dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR ? "error" :                   dbus_message_get_reply_serial (message) != 0 ? "reply" :                   "message", -                 dbus_message_get_name (message), +                 dbus_message_get_interface (message) ? +                 dbus_message_get_interface (message) : "(unset)", +                 dbus_message_get_member (message) ? +                 dbus_message_get_member (message) : "(unset)", +                 dbus_message_get_error_name (message) ? +                 dbus_message_get_error_name (message) : "(unset)",                   dbus_connection_get_is_connected (connection) ?                   "" : " (disconnected)"); diff --git a/bus/dispatch.c b/bus/dispatch.c index e8f0c9ba..934619f1 100644 --- a/bus/dispatch.c +++ b/bus/dispatch.c @@ -104,7 +104,7 @@ static DBusHandlerResult  bus_dispatch (DBusConnection *connection,                DBusMessage    *message)  { -  const char *sender, *service_name, *message_name; +  const char *sender, *service_name;    DBusError error;    BusTransaction *transaction;    BusContext *context; @@ -126,14 +126,24 @@ bus_dispatch (DBusConnection *connection,    /* Ref connection in case we disconnect it at some point in here */    dbus_connection_ref (connection); - +      service_name = dbus_message_get_destination (message); -  message_name = dbus_message_get_name (message); - -  _dbus_assert (message_name != NULL); /* DBusMessageLoader is supposed to check this */ -  _dbus_verbose ("DISPATCH: %s to %s\n", -                 message_name, service_name ? service_name : "peer"); +#ifdef DBUS_ENABLE_VERBOSE_MODE +  { +    const char *interface_name, *member_name, *error_name; + +    interface_name = dbus_message_get_interface (message); +    member_name = dbus_message_get_member (message); +    error_name = dbus_message_get_error_name (message); +     +    _dbus_verbose ("DISPATCH: %s %s %s to %s\n", +                   interface_name ? interface_name : "(no interface)", +                   member_name ? member_name : "(no member)", +                   error_name ? error_name : "(no error name)", +                   service_name ? service_name : "peer"); +  } +#endif /* DBUS_ENABLE_VERBOSE_MODE */    /* If service_name is NULL, this is a message to the bus daemon, not     * intended to actually go "on the bus"; e.g. a peer-to-peer @@ -142,7 +152,8 @@ bus_dispatch (DBusConnection *connection,     */    if (service_name == NULL)      {       -      if (strcmp (message_name, DBUS_MESSAGE_LOCAL_DISCONNECT) == 0) +      if (dbus_message_has_interface (message, DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL) && +          dbus_message_has_member (message, "Disconnect"))          bus_connection_disconnected (connection);        /* DBusConnection also handles some of these automatically, we leave @@ -182,7 +193,7 @@ bus_dispatch (DBusConnection *connection,        service_name = dbus_message_get_destination (message);      } -  if (strcmp (service_name, DBUS_SERVICE_DBUS) == 0) /* to bus driver */ +  if (strcmp (service_name, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS) == 0) /* to bus driver */      {        if (!bus_context_check_security_policy (context,                                                connection, NULL, message, &error)) @@ -191,7 +202,7 @@ bus_dispatch (DBusConnection *connection,            goto out;          } -      _dbus_verbose ("Giving message to %s\n", DBUS_SERVICE_DBUS); +      _dbus_verbose ("Giving message to %s\n", DBUS_SERVICE_ORG_FREEDESKTOP_DBUS);        if (!bus_driver_handle_message (connection, transaction, message, &error))          goto out;      } @@ -679,7 +690,7 @@ check_hello_message (BusContext     *context,    message = NULL;    message = dbus_message_new_method_call (DBUS_MESSAGE_HELLO, -                                          DBUS_SERVICE_DBUS); +                                          DBUS_SERVICE_ORG_FREEDESKTOP_DBUS);    if (message == NULL)      return TRUE; @@ -721,7 +732,7 @@ check_hello_message (BusContext     *context,    _dbus_verbose ("Received %s on %p\n",                   dbus_message_get_name (message), connection); -  if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS)) +  if (!dbus_message_has_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))      {        _dbus_warn ("Message has wrong sender %s\n",                    dbus_message_get_sender (message) ? @@ -911,7 +922,7 @@ check_nonexistent_service_activation (BusContext     *context,    dbus_error_init (&error);    message = dbus_message_new_method_call (DBUS_MESSAGE_ACTIVATE_SERVICE, -                                          DBUS_SERVICE_DBUS); +                                          DBUS_SERVICE_ORG_FREEDESKTOP_DBUS);    if (message == NULL)      return TRUE; @@ -959,7 +970,7 @@ check_nonexistent_service_activation (BusContext     *context,    if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)      { -      if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS)) +      if (!dbus_message_has_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))          {            _dbus_warn ("Message has wrong sender %s\n",                        dbus_message_get_sender (message) ? @@ -1465,7 +1476,7 @@ check_existent_service_activation (BusContext     *context,    dbus_error_init (&error);    message = dbus_message_new_method_call (DBUS_MESSAGE_ACTIVATE_SERVICE, -                                          DBUS_SERVICE_DBUS); +                                          DBUS_SERVICE_ORG_FREEDESKTOP_DBUS);    if (message == NULL)      return TRUE; @@ -1519,7 +1530,7 @@ check_existent_service_activation (BusContext     *context,    if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)      { -      if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS)) +      if (!dbus_message_has_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))          {            _dbus_warn ("Message has wrong sender %s\n",                        dbus_message_get_sender (message) ? @@ -1673,7 +1684,7 @@ check_segfault_service_activation (BusContext     *context,    dbus_error_init (&error);    message = dbus_message_new_method_call (DBUS_MESSAGE_ACTIVATE_SERVICE, -                                          DBUS_SERVICE_DBUS); +                                          DBUS_SERVICE_ORG_FREEDESKTOP_DBUS);    if (message == NULL)      return TRUE; @@ -1722,7 +1733,7 @@ check_segfault_service_activation (BusContext     *context,    if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)      { -      if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS)) +      if (!dbus_message_has_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))          {            _dbus_warn ("Message has wrong sender %s\n",                        dbus_message_get_sender (message) ? diff --git a/bus/policy.c b/bus/policy.c index 2f8e2ca3..3b3ceb4e 100644 --- a/bus/policy.c +++ b/bus/policy.c @@ -80,11 +80,15 @@ bus_policy_rule_unref (BusPolicyRule *rule)        switch (rule->type)          {          case BUS_POLICY_RULE_SEND: -          dbus_free (rule->d.send.message_name); +          dbus_free (rule->d.send.interface); +          dbus_free (rule->d.send.member); +          dbus_free (rule->d.send.error);            dbus_free (rule->d.send.destination);            break;          case BUS_POLICY_RULE_RECEIVE: -          dbus_free (rule->d.receive.message_name); +          dbus_free (rule->d.receive.interface); +          dbus_free (rule->d.receive.member); +          dbus_free (rule->d.receive.error);            dbus_free (rule->d.receive.origin);            break;          case BUS_POLICY_RULE_OWN: @@ -680,8 +684,8 @@ bus_client_policy_optimize (BusClientPolicy *policy)    /* The idea here is that if we have:     *  -   * <allow send="foo"/> -   * <deny send="*"/> +   * <allow send_interface="foo.bar"/> +   * <deny send_interface="*"/>     *     * (for example) the deny will always override the allow.  So we     * delete the allow. Ditto for deny followed by allow, etc. This is @@ -713,12 +717,16 @@ bus_client_policy_optimize (BusClientPolicy *policy)          {          case BUS_POLICY_RULE_SEND:            remove_preceding = -            rule->d.send.message_name == NULL && +            rule->d.send.interface == NULL && +            rule->d.send.member == NULL && +            rule->d.send.error == NULL &&              rule->d.send.destination == NULL;            break;          case BUS_POLICY_RULE_RECEIVE:            remove_preceding = -            rule->d.receive.message_name == NULL && +            rule->d.receive.interface == NULL && +            rule->d.receive.member == NULL && +            rule->d.receive.error == NULL &&              rule->d.receive.origin == NULL;            break;          case BUS_POLICY_RULE_OWN: @@ -791,16 +799,34 @@ bus_client_policy_check_can_send (BusClientPolicy *policy,            continue;          } -      if (rule->d.send.message_name != NULL) +      if (rule->d.send.interface != NULL)          { -          if (!dbus_message_has_name (message, -                                      rule->d.send.message_name)) +          if (!dbus_message_has_interface (message, +                                           rule->d.send.interface))              { -              _dbus_verbose ("  (policy) skipping rule for different message name\n"); +              _dbus_verbose ("  (policy) skipping rule for different interface\n");                continue;              }          } - +      else if (rule->d.send.member != NULL) +        { +          if (!dbus_message_has_member (message, +                                        rule->d.send.member)) +            { +              _dbus_verbose ("  (policy) skipping rule for different member\n"); +              continue; +            } +        } +      else if (rule->d.send.error != NULL) +        { +          if (!dbus_message_has_error_name (message, +                                            rule->d.send.error)) +            { +              _dbus_verbose ("  (policy) skipping rule for different error name\n"); +              continue; +            } +        } +              if (rule->d.send.destination != NULL)          {            /* receiver can be NULL for messages that are sent to the @@ -886,16 +912,34 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy,            continue;          } -      if (rule->d.receive.message_name != NULL) +      if (rule->d.receive.interface != NULL)          { -          if (!dbus_message_has_name (message, -                                      rule->d.receive.message_name)) +          if (!dbus_message_has_interface (message, +                                           rule->d.receive.interface))              { -              _dbus_verbose ("  (policy) skipping rule for different message name\n"); +              _dbus_verbose ("  (policy) skipping rule for different interface\n");                continue;              }          } - +      else if (rule->d.receive.member != NULL) +        { +          if (!dbus_message_has_member (message, +                                        rule->d.receive.member)) +            { +              _dbus_verbose ("  (policy) skipping rule for different member\n"); +              continue; +            } +        } +      else if (rule->d.receive.error != NULL) +        { +          if (!dbus_message_has_error_name (message, +                                            rule->d.receive.error)) +            { +              _dbus_verbose ("  (policy) skipping rule for different error name\n"); +              continue; +            } +        } +              if (rule->d.receive.origin != NULL)          {                      /* sender can be NULL for messages that originate from the diff --git a/bus/policy.h b/bus/policy.h index 940085ee..2aa69aaf 100644 --- a/bus/policy.h +++ b/bus/policy.h @@ -54,15 +54,19 @@ struct BusPolicyRule    {      struct      { -      /* either can be NULL meaning "any" */ -      char *message_name; +      /* any of these can be NULL meaning "any" */ +      char *interface; +      char *member; +      char *error;        char *destination;      } send;      struct      { -      /* either can be NULL meaning "any" */ -      char *message_name; +      /* any of these can be NULL meaning "any" */ +      char *interface; +      char *member; +      char *error;        char *origin;      } receive; diff --git a/dbus/dbus-bus.c b/dbus/dbus-bus.c index 214978da..445606e2 100644 --- a/dbus/dbus-bus.c +++ b/dbus/dbus-bus.c @@ -32,6 +32,10 @@   * @ingroup DBus   * @brief Functions for communicating with the message bus   * + * + * @todo get rid of most of these; they should be done + * with DBusGProxy and the Qt equivalent, i.e. the same + * way any other interface would be used.   */ @@ -398,8 +402,9 @@ dbus_bus_register (DBusConnection *connection,        return TRUE;      } -  message = dbus_message_new_method_call (DBUS_MESSAGE_HELLO, -                                          DBUS_SERVICE_DBUS); +  message = dbus_message_new_method_call (DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS, +                                          "Hello", +                                          DBUS_SERVICE_ORG_FREEDESKTOP_DBUS);    if (!message) @@ -516,9 +521,9 @@ dbus_bus_acquire_service (DBusConnection *connection,    _dbus_return_val_if_fail (service_name != NULL, 0);    _dbus_return_val_if_error_is_set (error, 0); -  message = dbus_message_new_method_call (DBUS_MESSAGE_ACQUIRE_SERVICE, -                                          DBUS_SERVICE_DBUS); - +  message = dbus_message_new_method_call (DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS, +                                          "AcquireService", +                                          DBUS_SERVICE_ORG_FREEDESKTOP_DBUS);    if (message == NULL)      { @@ -590,8 +595,9 @@ dbus_bus_service_exists (DBusConnection *connection,    _dbus_return_val_if_fail (service_name != NULL, FALSE);    _dbus_return_val_if_error_is_set (error, FALSE); -  message = dbus_message_new_method_call (DBUS_MESSAGE_SERVICE_EXISTS, -                                          DBUS_SERVICE_DBUS); +  message = dbus_message_new_method_call (DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS, +                                          "ServiceExists", +                                          DBUS_SERVICE_ORG_FREEDESKTOP_DBUS);    if (message == NULL)      {        _DBUS_SET_OOM (error); @@ -652,8 +658,9 @@ dbus_bus_activate_service (DBusConnection *connection,    DBusMessage *msg;    DBusMessage *reply; -  msg = dbus_message_new_method_call (DBUS_MESSAGE_ACTIVATE_SERVICE, -                                      DBUS_SERVICE_DBUS); +  msg = dbus_message_new_method_call (DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS, +                                      "ActivateService", +                                      DBUS_SERVICE_ORG_FREEDESKTOP_DBUS);    if (!dbus_message_append_args (msg, DBUS_TYPE_STRING, service_name,  			  	 DBUS_TYPE_UINT32, flags, DBUS_TYPE_INVALID)) diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index bc26a3ec..7be35b4c 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -296,9 +296,11 @@ _dbus_connection_queue_received_message_link (DBusConnection  *connection,    _dbus_connection_wakeup_mainloop (connection); -  _dbus_assert (dbus_message_get_name (message) != NULL);    _dbus_verbose ("Message %p (%s) added to incoming queue %p, %d incoming\n", -                 message, dbus_message_get_name (message), +                 message, +                 dbus_message_get_interface (message) ? +                 dbus_message_get_interface (message) : +                 "no interface",                   connection,                   connection->n_incoming);  } @@ -381,7 +383,10 @@ _dbus_connection_message_sent (DBusConnection *connection,    connection->n_outgoing -= 1;    _dbus_verbose ("Message %p (%s) removed from outgoing queue %p, %d left to send\n", -                 message, dbus_message_get_name (message), +                 message, +                 dbus_message_get_interface (message) ? +                 dbus_message_get_interface (message) : +                 "no interface",                   connection, connection->n_outgoing);    /* Save this link in the link cache also */ @@ -820,7 +825,9 @@ _dbus_connection_new_for_transport (DBusTransport *transport)    if (io_path_cond == NULL)      goto error; -  disconnect_message = dbus_message_new_signal (DBUS_MESSAGE_LOCAL_DISCONNECT); +  disconnect_message = dbus_message_new_signal (DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL, +                                                "Disconnect"); +      if (disconnect_message == NULL)      goto error; @@ -1482,7 +1489,9 @@ _dbus_connection_send_preallocated_unlocked (DBusConnection       *connection,    _dbus_verbose ("Message %p (%s) added to outgoing queue %p, %d pending to send\n",                   message, -                 dbus_message_get_name (message), +                 dbus_message_get_interface (message) ? +                 dbus_message_get_interface (message) : +                 "no interface",                   connection,                   connection->n_outgoing); @@ -1530,7 +1539,12 @@ dbus_connection_send_preallocated (DBusConnection       *connection,    _dbus_return_if_fail (preallocated != NULL);    _dbus_return_if_fail (message != NULL);    _dbus_return_if_fail (preallocated->connection == connection); -  _dbus_return_if_fail (dbus_message_get_name (message) != NULL); +  _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL || +                        (dbus_message_get_interface (message) != NULL && +                         dbus_message_get_member (message) != NULL)); +  _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL || +                        (dbus_message_get_interface (message) != NULL && +                         dbus_message_get_member (message) != NULL));    CONNECTION_LOCK (connection);    _dbus_connection_send_preallocated_unlocked (connection, @@ -1854,8 +1868,7 @@ _dbus_connection_block_for_reply (DBusConnection     *connection,          {                      status = _dbus_connection_get_dispatch_status_unlocked (connection); -          _dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply %s\n", -                         dbus_message_get_name (reply)); +          _dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply\n");            /* Unlocks, and calls out to user code */            _dbus_connection_update_dispatch_status_and_unlock (connection, status); @@ -2148,7 +2161,10 @@ _dbus_connection_pop_message_link_unlocked (DBusConnection *connection)        connection->n_incoming -= 1;        _dbus_verbose ("Message %p (%s) removed from incoming queue %p, %d incoming\n", -                     link->data, dbus_message_get_name (link->data), +                     link->data, +                     dbus_message_get_interface (link->data) ? +                     dbus_message_get_interface (link->data) : +                     "no interface",                       connection, connection->n_incoming);        return link; @@ -2194,7 +2210,10 @@ _dbus_connection_putback_message_link_unlocked (DBusConnection *connection,    connection->n_incoming += 1;    _dbus_verbose ("Message %p (%s) put back into queue %p, %d incoming\n", -                 message_link->data, dbus_message_get_name (message_link->data), +                 message_link->data, +                 dbus_message_get_interface (message_link->data) ? +                 dbus_message_get_interface (message_link->data) : +                 "no interface",                   connection, connection->n_incoming);  } @@ -2523,7 +2542,10 @@ dbus_connection_dispatch (DBusConnection *connection)     * since we acquired the dispatcher     */    _dbus_verbose ("  running object handler on message %p (%s)\n", -                 message, dbus_message_get_name (message)); +                 message, +                 dbus_message_get_interface (message) ? +                 dbus_message_get_interface (message) : +                 "no interface");    result = _dbus_object_registry_handle_and_unlock (connection->objects,                                                      message); @@ -2549,8 +2571,9 @@ dbus_connection_dispatch (DBusConnection *connection)          }        if (!_dbus_string_append_printf (&str, -                                       "Method \"%s\" doesn't exist\n", -                                       dbus_message_get_name (message))) +                                       "Method \"%s\" on interface \"%s\" doesn't exist\n", +                                       dbus_message_get_member (message), +                                       dbus_message_get_interface (message)))          {            _dbus_string_free (&str);            result = DBUS_HANDLER_RESULT_NEED_MEMORY; @@ -2586,7 +2609,10 @@ dbus_connection_dispatch (DBusConnection *connection)      }    _dbus_verbose ("  done dispatching %p (%s) on connection %p\n", message, -                 dbus_message_get_name (message), connection); +                 dbus_message_get_interface (message) ? +                 dbus_message_get_interface (message) : +                 "no interface", +                 connection);   out:    if (result == DBUS_HANDLER_RESULT_NEED_MEMORY) diff --git a/dbus/dbus-hash.c b/dbus/dbus-hash.c index 2c410010..f4547815 100644 --- a/dbus/dbus-hash.c +++ b/dbus/dbus-hash.c @@ -221,26 +221,32 @@ typedef struct    int n_entries_on_init;     /**< used to detect table resize since initialization */  } DBusRealHashIter; -static DBusHashEntry* find_direct_function (DBusHashTable          *table, -                                            void                   *key, -                                            dbus_bool_t             create_if_not_found, -                                            DBusHashEntry        ***bucket, -                                            DBusPreallocatedHash   *preallocated); -static DBusHashEntry* find_string_function (DBusHashTable          *table, -                                            void                   *key, -                                            dbus_bool_t             create_if_not_found, -                                            DBusHashEntry        ***bucket, -                                            DBusPreallocatedHash   *preallocated); -static unsigned int   string_hash          (const char             *str); -static void           rebuild_table        (DBusHashTable          *table); -static DBusHashEntry* alloc_entry          (DBusHashTable          *table); -static void           remove_entry         (DBusHashTable          *table, -                                            DBusHashEntry         **bucket, -                                            DBusHashEntry          *entry); -static void           free_entry           (DBusHashTable          *table, -                                            DBusHashEntry          *entry); -static void           free_entry_data      (DBusHashTable          *table, -                                            DBusHashEntry          *entry); +static DBusHashEntry* find_direct_function      (DBusHashTable          *table, +                                                 void                   *key, +                                                 dbus_bool_t             create_if_not_found, +                                                 DBusHashEntry        ***bucket, +                                                 DBusPreallocatedHash   *preallocated); +static DBusHashEntry* find_string_function      (DBusHashTable          *table, +                                                 void                   *key, +                                                 dbus_bool_t             create_if_not_found, +                                                 DBusHashEntry        ***bucket, +                                                 DBusPreallocatedHash   *preallocated); +static DBusHashEntry* find_two_strings_function (DBusHashTable          *table, +                                                 void                   *key, +                                                 dbus_bool_t             create_if_not_found, +                                                 DBusHashEntry        ***bucket, +                                                 DBusPreallocatedHash   *preallocated); +static unsigned int   string_hash               (const char             *str); +static unsigned int   two_strings_hash          (const char             *str); +static void           rebuild_table             (DBusHashTable          *table); +static DBusHashEntry* alloc_entry               (DBusHashTable          *table); +static void           remove_entry              (DBusHashTable          *table, +                                                 DBusHashEntry         **bucket, +                                                 DBusHashEntry          *entry); +static void           free_entry                (DBusHashTable          *table, +                                                 DBusHashEntry          *entry); +static void           free_entry_data           (DBusHashTable          *table, +                                                 DBusHashEntry          *entry);  /** @} */ @@ -323,6 +329,9 @@ _dbus_hash_table_new (DBusHashType     type,      case DBUS_HASH_STRING:        table->find_function = find_string_function;        break; +    case DBUS_HASH_TWO_STRINGS: +      table->find_function = find_two_strings_function; +      break;      default:        _dbus_assert_not_reached ("Unknown hash table type");        break; @@ -685,6 +694,24 @@ _dbus_hash_iter_get_string_key (DBusHashIter *iter)  }  /** + * Gets the key for the current entry. + * Only works for hash tables of type #DBUS_HASH_TWO_STRINGS + * @param iter the hash table iterator. + */ +const char* +_dbus_hash_iter_get_two_strings_key (DBusHashIter *iter) +{ +  DBusRealHashIter *real; + +  real = (DBusRealHashIter*) iter; + +  _dbus_assert (real->table != NULL); +  _dbus_assert (real->entry != NULL); + +  return real->entry->key; +} + +/**   * A low-level but efficient interface for manipulating the hash   * table.  It's efficient because you can get, set, and optionally   * create the hash entry while only running the hash function one @@ -803,64 +830,63 @@ add_entry (DBusHashTable        *table,    return entry;  } +/* This is g_str_hash from GLib which was + * extensively discussed/tested/profiled + */  static unsigned int  string_hash (const char *str)  { -  register unsigned int result; -  register int c; +  const char *p = str; +  unsigned int h = *p; -  /* -   * I tried a zillion different hash functions and asked many other -   * people for advice.  Many people had their own favorite functions, -   * all different, but no-one had much idea why they were good ones. -   * I chose the one below (multiply by 9 and add new character) -   * because of the following reasons: -   * -   * 1. Multiplying by 10 is perfect for keys that are decimal strings, -   *    and multiplying by 9 is just about as good. -   * 2. Times-9 is (shift-left-3) plus (old).  This means that each -   *    character's bits hang around in the low-order bits of the -   *    hash value for ever, plus they spread fairly rapidly up to -   *    the high-order bits to fill out the hash value.  This seems -   *    works well both for decimal and non-decimal strings. -   */ +  if (h) +    for (p += 1; *p != '\0'; p++) +      h = (h << 5) - h + *p; -  /* FIXME the hash function in GLib is better than this one */ -   -  result = 0; -  while (TRUE) -    { -      c = *str; -      str++; -      if (c == 0) -        break; -       -      result += (result << 3) + c; -    } +  return h; +} + +/* This hashes a memory block with two nul-terminated strings + * in it, used in dbus-object-registry.c at the moment. + */ +static unsigned int +two_strings_hash (const char *str) +{ +  const char *p = str; +  unsigned int h = *p; + +  if (h) +    for (p += 1; *p != '\0'; p++) +      h = (h << 5) - h + *p; + +  for (p += 1; *p != '\0'; p++) +    h = (h << 5) - h + *p; -  return result; +  return h;  } +typedef int (* KeyCompareFunc) (const void *key_a, const void *key_b); +  static DBusHashEntry* -find_string_function (DBusHashTable        *table, -                      void                 *key, -                      dbus_bool_t           create_if_not_found, -                      DBusHashEntry      ***bucket, -                      DBusPreallocatedHash *preallocated) +find_generic_function (DBusHashTable        *table, +                       void                 *key, +                       unsigned int          idx, +                       KeyCompareFunc        compare_func, +                       dbus_bool_t           create_if_not_found, +                       DBusHashEntry      ***bucket, +                       DBusPreallocatedHash *preallocated)  {    DBusHashEntry *entry; -  unsigned int idx;    if (bucket)      *bucket = NULL; -   -  idx = string_hash (key) & table->mask;    /* Search all of the entries in this bucket. */    entry = table->buckets[idx];    while (entry != NULL)      { -      if (strcmp (key, entry->key) == 0) +      if ((compare_func == NULL && key == entry->key) || +          (compare_func != NULL && (* compare_func) (key, entry->key) == 0))          {            if (bucket)              *bucket = &(table->buckets[idx]); @@ -878,50 +904,75 @@ find_string_function (DBusHashTable        *table,      entry = add_entry (table, idx, key, bucket, preallocated);    else if (preallocated)      _dbus_hash_table_free_preallocated_entry (table, preallocated); - +      return entry;  }  static DBusHashEntry* -find_direct_function (DBusHashTable        *table, +find_string_function (DBusHashTable        *table,                        void                 *key,                        dbus_bool_t           create_if_not_found,                        DBusHashEntry      ***bucket,                        DBusPreallocatedHash *preallocated)  { -  DBusHashEntry *entry;    unsigned int idx; +   +  idx = string_hash (key) & table->mask; -  if (bucket) -    *bucket = NULL; +  return find_generic_function (table, key, idx, +                                (KeyCompareFunc) strcmp, create_if_not_found, bucket, +                                preallocated); +} + +static int +two_strings_cmp (const char *a, +                 const char *b) +{ +  size_t len_a; +  size_t len_b; +  int res; -  idx = RANDOM_INDEX (table, key) & table->mask; +  res = strcmp (a, b); +  if (res != 0) +    return res; -  /* Search all of the entries in this bucket. */ -  entry = table->buckets[idx]; -  while (entry != NULL) -    { -      if (key == entry->key) -        { -          if (bucket) -            *bucket = &(table->buckets[idx]); +  len_a = strlen (a); +  len_b = strlen (b); -          if (preallocated) -            _dbus_hash_table_free_preallocated_entry (table, preallocated); -           -          return entry; -        } -       -      entry = entry->next; -    } +  return strcmp (a + len_a + 1, b + len_b + 1); +} -  /* Entry not found.  Add a new one to the bucket. */ -  if (create_if_not_found) -    entry = add_entry (table, idx, key, bucket, preallocated); -  else if (preallocated) -    _dbus_hash_table_free_preallocated_entry (table, preallocated); +static DBusHashEntry* +find_two_strings_function (DBusHashTable        *table, +                           void                 *key, +                           dbus_bool_t           create_if_not_found, +                           DBusHashEntry      ***bucket, +                           DBusPreallocatedHash *preallocated) +{ +  unsigned int idx; +   +  idx = two_strings_hash (key) & table->mask; -  return entry; +  return find_generic_function (table, key, idx, +                                (KeyCompareFunc) two_strings_cmp, create_if_not_found, bucket, +                                preallocated); +} + +static DBusHashEntry* +find_direct_function (DBusHashTable        *table, +                      void                 *key, +                      dbus_bool_t           create_if_not_found, +                      DBusHashEntry      ***bucket, +                      DBusPreallocatedHash *preallocated) +{ +  unsigned int idx; +   +  idx = RANDOM_INDEX (table, key) & table->mask; + + +  return find_generic_function (table, key, idx, +                                NULL, create_if_not_found, bucket, +                                preallocated);  }  static void @@ -1021,6 +1072,9 @@ rebuild_table (DBusHashTable *table)              case DBUS_HASH_STRING:                idx = string_hash (entry->key) & table->mask;                break; +            case DBUS_HASH_TWO_STRINGS: +              idx = two_strings_hash (entry->key) & table->mask; +              break;              case DBUS_HASH_INT:              case DBUS_HASH_ULONG:              case DBUS_HASH_POINTER: @@ -1070,6 +1124,31 @@ _dbus_hash_table_lookup_string (DBusHashTable *table,  }  /** + * Looks up the value for a given string in a hash table + * of type #DBUS_HASH_TWO_STRINGS. Returns %NULL if the value + * is not present. (A not-present entry is indistinguishable + * from an entry with a value of %NULL.) + * @param table the hash table. + * @param key the string to look up. + * @returns the value of the hash entry. + */ +void* +_dbus_hash_table_lookup_two_strings (DBusHashTable *table, +                                     const char    *key) +{ +  DBusHashEntry *entry; + +  _dbus_assert (table->key_type == DBUS_HASH_TWO_STRINGS); +   +  entry = (* table->find_function) (table, (char*) key, FALSE, NULL, NULL); + +  if (entry) +    return entry->value; +  else +    return NULL; +} + +/**   * Looks up the value for a given integer in a hash table   * of type #DBUS_HASH_INT. Returns %NULL if the value   * is not present. (A not-present entry is indistinguishable @@ -1184,6 +1263,34 @@ _dbus_hash_table_remove_string (DBusHashTable *table,   * @returns #TRUE if the entry existed   */  dbus_bool_t +_dbus_hash_table_remove_two_strings (DBusHashTable *table, +                                     const char    *key) +{ +  DBusHashEntry *entry; +  DBusHashEntry **bucket; +   +  _dbus_assert (table->key_type == DBUS_HASH_TWO_STRINGS); +   +  entry = (* table->find_function) (table, (char*) key, FALSE, &bucket, NULL); + +  if (entry) +    { +      remove_entry (table, bucket, entry); +      return TRUE; +    } +  else +    return FALSE; +} + +/** + * Removes the hash entry for the given key. If no hash entry + * for the key exists, does nothing. + * + * @param table the hash table. + * @param key the hash key. + * @returns #TRUE if the entry existed + */ +dbus_bool_t  _dbus_hash_table_remove_int (DBusHashTable *table,                               int            key)  { @@ -1312,6 +1419,40 @@ _dbus_hash_table_insert_string (DBusHashTable *table,   * @param value the hash entry value.   */  dbus_bool_t +_dbus_hash_table_insert_two_strings (DBusHashTable *table, +                                     char          *key, +                                     void          *value) +{ +  DBusPreallocatedHash *preallocated; + +  _dbus_assert (table->key_type == DBUS_HASH_TWO_STRINGS); + +  preallocated = _dbus_hash_table_preallocate_entry (table); +  if (preallocated == NULL) +    return FALSE; + +  _dbus_hash_table_insert_string_preallocated (table, preallocated, +                                               key, value); +   +  return TRUE; +} + +/** + * Creates a hash entry with the given key and value. + * The key and value are not copied; they are stored + * in the hash table by reference. If an entry with the + * given key already exists, the previous key and value + * are overwritten (and freed if the hash table has + * a key_free_function and/or value_free_function). + * + * Returns #FALSE if memory for the new hash entry + * can't be allocated. + *  + * @param table the hash table. + * @param key the hash entry key. + * @param value the hash entry value. + */ +dbus_bool_t  _dbus_hash_table_insert_int (DBusHashTable *table,                               int            key,                               void          *value) @@ -1536,6 +1677,28 @@ count_entries (DBusHashTable *table)    return count;  } +/* Copy the foo\0bar\0 double string thing */ +static char* +_dbus_strdup2 (const char *str) +{ +  size_t len; +  char *copy; +   +  if (str == NULL) +    return NULL; +   +  len = strlen (str); +  len += strlen ((str + len + 1)); + +  copy = dbus_malloc (len + 2); +  if (copy == NULL) +    return NULL; + +  memcpy (copy, str, len + 2); +   +  return copy; +} +  /**   * @ingroup DBusHashTableInternals   * Unit test for DBusHashTable @@ -1548,6 +1711,7 @@ _dbus_hash_test (void)    DBusHashTable *table1;    DBusHashTable *table2;    DBusHashTable *table3; +  DBusHashTable *table4;    DBusHashIter iter;  #define N_HASH_KEYS 5000    char **keys; @@ -1569,7 +1733,16 @@ _dbus_hash_test (void)    i = 0;    while (i < N_HASH_KEYS)      { -      sprintf (keys[i], "Hash key %d", i);  +      int len; + +      /* all the hash keys are TWO_STRINGS, but +       * then we can also use those as regular strings. +       */ +       +      len = sprintf (keys[i], "Hash key %d", i); +      sprintf (keys[i] + len + 1, "Two string %d", i); +      _dbus_assert (*(keys[i] + len) == '\0'); +      _dbus_assert (*(keys[i] + len + 1) != '\0');        ++i;      }    printf ("... done.\n"); @@ -1588,6 +1761,12 @@ _dbus_hash_test (void)                                   NULL, dbus_free);    if (table3 == NULL)      goto out; + +  table4 = _dbus_hash_table_new (DBUS_HASH_TWO_STRINGS, +                                 dbus_free, dbus_free); +  if (table4 == NULL) +    goto out; +    /* Insert and remove a bunch of stuff, counting the table in between     * to be sure it's not broken and that iteration works @@ -1624,10 +1803,22 @@ _dbus_hash_test (void)        if (!_dbus_hash_table_insert_ulong (table3,                                            i, value))          goto out; + +      key = _dbus_strdup2 (keys[i]); +      if (key == NULL) +        goto out; +      value = _dbus_strdup ("Value!"); +      if (value == NULL) +        goto out; +       +      if (!_dbus_hash_table_insert_string (table4, +                                           key, value)) +        goto out;        _dbus_assert (count_entries (table1) == i + 1);        _dbus_assert (count_entries (table2) == i + 1);        _dbus_assert (count_entries (table3) == i + 1); +      _dbus_assert (count_entries (table4) == i + 1);        value = _dbus_hash_table_lookup_string (table1, keys[i]);        _dbus_assert (value != NULL); @@ -1640,6 +1831,10 @@ _dbus_hash_test (void)        value = _dbus_hash_table_lookup_ulong (table3, i);        _dbus_assert (value != NULL);        _dbus_assert (strcmp (value, keys[i]) == 0); + +      value = _dbus_hash_table_lookup_ulong (table4, i); +      _dbus_assert (value != NULL); +      _dbus_assert (strcmp (value, keys[i]) == 0);        ++i;      } @@ -1654,9 +1849,13 @@ _dbus_hash_test (void)        _dbus_hash_table_remove_ulong (table3, i);  +      _dbus_hash_table_remove_two_strings (table4, +                                           keys[i]); +              _dbus_assert (count_entries (table1) == i);        _dbus_assert (count_entries (table2) == i);        _dbus_assert (count_entries (table3) == i); +      _dbus_assert (count_entries (table4) == i);        --i;      } @@ -1664,12 +1863,15 @@ _dbus_hash_test (void)    _dbus_hash_table_ref (table1);    _dbus_hash_table_ref (table2);    _dbus_hash_table_ref (table3); +  _dbus_hash_table_ref (table4);    _dbus_hash_table_unref (table1);    _dbus_hash_table_unref (table2);    _dbus_hash_table_unref (table3); +  _dbus_hash_table_unref (table4);    _dbus_hash_table_unref (table1);    _dbus_hash_table_unref (table2);    _dbus_hash_table_unref (table3); +  _dbus_hash_table_unref (table4);    table3 = NULL;    /* Insert a bunch of stuff then check diff --git a/dbus/dbus-hash.h b/dbus/dbus-hash.h index 566d4021..25b81dd6 100644 --- a/dbus/dbus-hash.h +++ b/dbus/dbus-hash.h @@ -52,61 +52,68 @@ typedef struct DBusHashIter  DBusHashIter;   */  typedef enum  { -  DBUS_HASH_STRING,  /**< Hash keys are strings. */ -  DBUS_HASH_INT,     /**< Hash keys are integers. */ -  DBUS_HASH_POINTER, /**< Hash keys are pointers. */ -  DBUS_HASH_ULONG    /**< Hash keys are unsigned long. */ +  DBUS_HASH_STRING,        /**< Hash keys are strings. */ +  DBUS_HASH_TWO_STRINGS,   /**< Hash key is two strings in one memory block, i.e. foo\0bar\0 */ +  DBUS_HASH_INT,           /**< Hash keys are integers. */ +  DBUS_HASH_POINTER,       /**< Hash keys are pointers. */ +  DBUS_HASH_ULONG          /**< Hash keys are unsigned long. */  } DBusHashType; - -DBusHashTable* _dbus_hash_table_new            (DBusHashType      type, -                                                DBusFreeFunction  key_free_function, -                                                DBusFreeFunction  value_free_function); -void           _dbus_hash_table_ref            (DBusHashTable    *table); -void           _dbus_hash_table_unref          (DBusHashTable    *table); -void           _dbus_hash_iter_init            (DBusHashTable    *table, -                                                DBusHashIter     *iter); -dbus_bool_t    _dbus_hash_iter_next            (DBusHashIter     *iter); -void           _dbus_hash_iter_remove_entry    (DBusHashIter     *iter); -void*          _dbus_hash_iter_get_value       (DBusHashIter     *iter); -void           _dbus_hash_iter_set_value       (DBusHashIter     *iter, -                                                void             *value); -int            _dbus_hash_iter_get_int_key     (DBusHashIter     *iter); -const char*    _dbus_hash_iter_get_string_key  (DBusHashIter     *iter); -unsigned long  _dbus_hash_iter_get_ulong_key   (DBusHashIter     *iter); -dbus_bool_t    _dbus_hash_iter_lookup          (DBusHashTable    *table, -                                                void             *key, -                                                dbus_bool_t       create_if_not_found, -                                                DBusHashIter     *iter); -void*          _dbus_hash_table_lookup_string  (DBusHashTable    *table, -                                                const char       *key); -void*          _dbus_hash_table_lookup_int     (DBusHashTable    *table, -                                                int               key); -void*          _dbus_hash_table_lookup_pointer (DBusHashTable    *table, -                                                void             *key); -void*          _dbus_hash_table_lookup_ulong   (DBusHashTable    *table, -                                                unsigned long     key); -dbus_bool_t    _dbus_hash_table_remove_string  (DBusHashTable    *table, -                                                const char       *key); -dbus_bool_t    _dbus_hash_table_remove_int     (DBusHashTable    *table, -                                                int               key); -dbus_bool_t    _dbus_hash_table_remove_pointer (DBusHashTable    *table, -                                                void             *key); -dbus_bool_t    _dbus_hash_table_remove_ulong   (DBusHashTable    *table, -                                                unsigned long     key); -dbus_bool_t    _dbus_hash_table_insert_string  (DBusHashTable    *table, -                                                char             *key, -                                                void             *value); -dbus_bool_t    _dbus_hash_table_insert_int     (DBusHashTable    *table, -                                                int               key, -                                                void             *value); -dbus_bool_t    _dbus_hash_table_insert_pointer (DBusHashTable    *table, -                                                void             *key, -                                                void             *value); -dbus_bool_t    _dbus_hash_table_insert_ulong   (DBusHashTable    *table, -                                                unsigned long     key, -                                                void             *value); -int            _dbus_hash_table_get_n_entries  (DBusHashTable    *table); - +DBusHashTable* _dbus_hash_table_new                (DBusHashType      type, +                                                    DBusFreeFunction  key_free_function, +                                                    DBusFreeFunction  value_free_function); +void           _dbus_hash_table_ref                (DBusHashTable    *table); +void           _dbus_hash_table_unref              (DBusHashTable    *table); +void           _dbus_hash_iter_init                (DBusHashTable    *table, +                                                    DBusHashIter     *iter); +dbus_bool_t    _dbus_hash_iter_next                (DBusHashIter     *iter); +void           _dbus_hash_iter_remove_entry        (DBusHashIter     *iter); +void*          _dbus_hash_iter_get_value           (DBusHashIter     *iter); +void           _dbus_hash_iter_set_value           (DBusHashIter     *iter, +                                                    void             *value); +int            _dbus_hash_iter_get_int_key         (DBusHashIter     *iter); +const char*    _dbus_hash_iter_get_string_key      (DBusHashIter     *iter); +const char*    _dbus_hash_iter_get_two_strings_key (DBusHashIter     *iter); +unsigned long  _dbus_hash_iter_get_ulong_key       (DBusHashIter     *iter); +dbus_bool_t    _dbus_hash_iter_lookup              (DBusHashTable    *table, +                                                    void             *key, +                                                    dbus_bool_t       create_if_not_found, +                                                    DBusHashIter     *iter); +void*          _dbus_hash_table_lookup_string      (DBusHashTable    *table, +                                                    const char       *key); +void*          _dbus_hash_table_lookup_two_strings (DBusHashTable    *table, +                                                    const char       *key); +void*          _dbus_hash_table_lookup_int         (DBusHashTable    *table, +                                                    int               key); +void*          _dbus_hash_table_lookup_pointer     (DBusHashTable    *table, +                                                    void             *key); +void*          _dbus_hash_table_lookup_ulong       (DBusHashTable    *table, +                                                    unsigned long     key); +dbus_bool_t    _dbus_hash_table_remove_string      (DBusHashTable    *table, +                                                    const char       *key); +dbus_bool_t    _dbus_hash_table_remove_two_strings (DBusHashTable    *table, +                                                    const char       *key); +dbus_bool_t    _dbus_hash_table_remove_int         (DBusHashTable    *table, +                                                    int               key); +dbus_bool_t    _dbus_hash_table_remove_pointer     (DBusHashTable    *table, +                                                    void             *key); +dbus_bool_t    _dbus_hash_table_remove_ulong       (DBusHashTable    *table, +                                                    unsigned long     key); +dbus_bool_t    _dbus_hash_table_insert_string      (DBusHashTable    *table, +                                                    char             *key, +                                                    void             *value); +dbus_bool_t    _dbus_hash_table_insert_two_strings (DBusHashTable    *table, +                                                    char             *key, +                                                    void             *value); +dbus_bool_t    _dbus_hash_table_insert_int         (DBusHashTable    *table, +                                                    int               key, +                                                    void             *value); +dbus_bool_t    _dbus_hash_table_insert_pointer     (DBusHashTable    *table, +                                                    void             *key, +                                                    void             *value); +dbus_bool_t    _dbus_hash_table_insert_ulong       (DBusHashTable    *table, +                                                    unsigned long     key, +                                                    void             *value); +int            _dbus_hash_table_get_n_entries      (DBusHashTable    *table);  /* Preallocation */  typedef struct DBusPreallocatedHash DBusPreallocatedHash; diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c index 5f3d01e0..e5bbcab1 100644 --- a/dbus/dbus-message.c +++ b/dbus/dbus-message.c @@ -47,7 +47,9 @@ enum    FIELD_HEADER_LENGTH,    FIELD_BODY_LENGTH,    FIELD_CLIENT_SERIAL, -  FIELD_NAME, +  FIELD_INTERFACE, +  FIELD_MEMBER, +  FIELD_ERROR_NAME,    FIELD_SERVICE,    FIELD_SENDER,    FIELD_REPLY_SERIAL, @@ -60,7 +62,9 @@ static dbus_bool_t field_is_named[FIELD_LAST] =    FALSE, /* FIELD_HEADER_LENGTH */    FALSE, /* FIELD_BODY_LENGTH */    FALSE, /* FIELD_CLIENT_SERIAL */ -  TRUE,  /* FIELD_NAME */ +  TRUE,  /* FIELD_INTERFACE */ +  TRUE,  /* FIELD_MEMBER */ +  TRUE,  /* FIELD_ERROR_NAME */    TRUE,  /* FIELD_SERVICE */    TRUE,  /* FIELD_SENDER */    TRUE   /* FIELD_REPLY_SERIAL */ @@ -593,9 +597,17 @@ set_string_field (DBusMessage *message,            return append_string_field (message, field,                                        DBUS_HEADER_FIELD_SENDER,                                        value); -        case FIELD_NAME: +        case FIELD_INTERFACE:            return append_string_field (message, field, -                                      DBUS_HEADER_FIELD_NAME, +                                      DBUS_HEADER_FIELD_INTERFACE, +                                      value); +        case FIELD_MEMBER: +          return append_string_field (message, field, +                                      DBUS_HEADER_FIELD_MEMBER, +                                      value); +        case FIELD_ERROR_NAME: +          return append_string_field (message, field, +                                      DBUS_HEADER_FIELD_ERROR_NAME,                                        value);          case FIELD_SERVICE:            return append_string_field (message, field, @@ -817,10 +829,16 @@ _dbus_message_remove_size_counter (DBusMessage  *message,  static dbus_bool_t  dbus_message_create_header (DBusMessage *message,                              int          type, -                            const char  *name, +                            const char  *interface, +                            const char  *member, +                            const char  *error_name,                              const char  *service)  {    unsigned int flags; + +  _dbus_assert ((interface && member) || +                (error_name) || +                !(interface || member || error_name));    if (!_dbus_string_append_byte (&message->header, message->byte_order))      return FALSE; @@ -857,12 +875,30 @@ dbus_message_create_header (DBusMessage *message,          return FALSE;      } -  if (name != NULL) +  if (interface != NULL) +    { +      if (!append_string_field (message, +                                FIELD_INTERFACE, +                                DBUS_HEADER_FIELD_INTERFACE, +                                interface)) +        return FALSE; +    } + +  if (member != NULL)      {        if (!append_string_field (message, -                                FIELD_NAME, -                                DBUS_HEADER_FIELD_NAME, -                                name)) +                                FIELD_MEMBER, +                                DBUS_HEADER_FIELD_MEMBER, +                                member)) +        return FALSE; +    } + +  if (error_name != NULL) +    { +      if (!append_string_field (message, +                                FIELD_ERROR_NAME, +                                DBUS_HEADER_FIELD_ERROR_NAME, +                                error_name))          return FALSE;      } @@ -979,7 +1015,7 @@ dbus_message_new (int message_type)    if (!dbus_message_create_header (message,                                     message_type, -                                   NULL, NULL)) +                                   NULL, NULL, NULL, NULL))      {        dbus_message_unref (message);        return NULL; @@ -995,18 +1031,21 @@ dbus_message_new (int message_type)   * this is appropriate when using D-BUS in a peer-to-peer context (no   * message bus).   * - * @param name name of the message + * @param interface interface to invoke method on + * @param method method to invoke   * @param destination_service service that the message should be sent to or #NULL   * @returns a new DBusMessage, free with dbus_message_unref()   * @see dbus_message_unref()   */  DBusMessage* -dbus_message_new_method_call (const char *name, +dbus_message_new_method_call (const char *interface, +                              const char *method,                                const char *destination_service)		    {    DBusMessage *message; -  _dbus_return_val_if_fail (name != NULL, NULL); +  _dbus_return_val_if_fail (interface != NULL, NULL); +  _dbus_return_val_if_fail (method != NULL, NULL);    message = dbus_message_new_empty_header ();    if (message == NULL) @@ -1014,7 +1053,7 @@ dbus_message_new_method_call (const char *name,    if (!dbus_message_create_header (message,                                     DBUS_MESSAGE_TYPE_METHOD_CALL, -                                   name, destination_service)) +                                   interface, method, NULL, destination_service))      {        dbus_message_unref (message);        return NULL; @@ -1036,14 +1075,12 @@ DBusMessage*  dbus_message_new_method_return (DBusMessage *method_call)  {    DBusMessage *message; -  const char *sender, *name; +  const char *sender;    _dbus_return_val_if_fail (method_call != NULL, NULL);    sender = get_string_field (method_call,                               FIELD_SENDER, NULL); -  name = get_string_field (method_call, -			   FIELD_NAME, NULL);    /* sender is allowed to be null here in peer-to-peer case */ @@ -1053,7 +1090,7 @@ dbus_message_new_method_return (DBusMessage *method_call)    if (!dbus_message_create_header (message,                                     DBUS_MESSAGE_TYPE_METHOD_RETURN, -                                   name, sender)) +                                   NULL, NULL, NULL, sender))      {        dbus_message_unref (message);        return NULL; @@ -1071,15 +1108,18 @@ dbus_message_new_method_return (DBusMessage *method_call)  /**   * Constructs a new message representing a signal emission. Returns - * #NULL if memory can't be allocated for the message. The name - * passed in is the name of the signal. + * #NULL if memory can't be allocated for the message. + * A signal is identified by its originating interface, and + * the name of the signal.   * + * @param interface the interface the signal is emitted from   * @param name name of the signal   * @returns a new DBusMessage, free with dbus_message_unref()   * @see dbus_message_unref()   */  DBusMessage* -dbus_message_new_signal (const char *name) +dbus_message_new_signal (const char *interface, +                         const char *name)  {    DBusMessage *message; @@ -1091,7 +1131,7 @@ dbus_message_new_signal (const char *name)    if (!dbus_message_create_header (message,                                     DBUS_MESSAGE_TYPE_SIGNAL, -                                   name, NULL)) +                                   interface, name, NULL, NULL))      {        dbus_message_unref (message);        return NULL; @@ -1134,7 +1174,7 @@ dbus_message_new_error (DBusMessage *reply_to,    if (!dbus_message_create_header (message,                                     DBUS_MESSAGE_TYPE_ERROR, -                                   error_name, sender)) +                                   NULL, NULL, error_name, sender))      {        dbus_message_unref (message);        return NULL; @@ -1312,46 +1352,139 @@ dbus_message_get_type (DBusMessage *message)    return type;  } +/** + * Sets the interface this message is being sent to + * (for DBUS_MESSAGE_TYPE_METHOD_CALL) or + * the interface a signal is being emitted from + * (for DBUS_MESSAGE_TYPE_SIGNAL). + * + * @param message the message + * @param interface the interface + * @returns #FALSE if not enough memory + */ +dbus_bool_t +dbus_message_set_interface (DBusMessage  *message, +                            const char   *interface) +{ +  _dbus_return_val_if_fail (message != NULL, FALSE); +  _dbus_return_val_if_fail (!message->locked, FALSE); +   +  if (interface == NULL) +    { +      delete_string_field (message, FIELD_INTERFACE); +      return TRUE; +    } +  else +    { +      return set_string_field (message, +                               FIELD_INTERFACE, +                               interface); +    } +}  /** - * Sets the message name. + * Gets the interface this message is being sent to + * (for DBUS_MESSAGE_TYPE_METHOD_CALL) or being emitted + * from (for DBUS_MESSAGE_TYPE_SIGNAL). + * The interface name is fully-qualified (namespaced).   *   * @param message the message - * @param name the name + * @returns the message interface (should not be freed) + */ +const char* +dbus_message_get_interface (DBusMessage *message) +{ +  _dbus_return_val_if_fail (message != NULL, NULL); +   +  return get_string_field (message, FIELD_INTERFACE, NULL); +} + +/** + * Sets the interface member being invoked + * (DBUS_MESSAGE_TYPE_METHOD_CALL) or emitted + * (DBUS_MESSAGE_TYPE_SIGNAL). + * The interface name is fully-qualified (namespaced). + * + * @param message the message + * @param member the member   * @returns #FALSE if not enough memory   */  dbus_bool_t -dbus_message_set_name (DBusMessage  *message, -                       const char   *name) +dbus_message_set_member (DBusMessage  *message, +                       const char   *member)  {    _dbus_return_val_if_fail (message != NULL, FALSE);    _dbus_return_val_if_fail (!message->locked, FALSE); -  if (name == NULL) +  if (member == NULL)      { -      delete_string_field (message, FIELD_NAME); +      delete_string_field (message, FIELD_MEMBER);        return TRUE;      }    else      {        return set_string_field (message, -                               FIELD_NAME, -                               name); +                               FIELD_MEMBER, +                               member);      }  }  /** - * Gets the name of a message. + * Gets the interface member being invoked + * (DBUS_MESSAGE_TYPE_METHOD_CALL) or emitted + * (DBUS_MESSAGE_TYPE_SIGNAL). + *  + * @param message the message + * @returns the member name (should not be freed) + */ +const char* +dbus_message_get_member (DBusMessage *message) +{ +  _dbus_return_val_if_fail (message != NULL, NULL); +   +  return get_string_field (message, FIELD_MEMBER, NULL); +} + +/** + * Sets the name of the error (DBUS_MESSAGE_TYPE_ERROR). + * The name is fully-qualified (namespaced).   *   * @param message the message - * @returns the message name (should not be freed) + * @param name the name + * @returns #FALSE if not enough memory + */ +dbus_bool_t +dbus_message_set_error_name (DBusMessage  *message, +                             const char   *error_name) +{ +  _dbus_return_val_if_fail (message != NULL, FALSE); +  _dbus_return_val_if_fail (!message->locked, FALSE); +   +  if (error_name == NULL) +    { +      delete_string_field (message, FIELD_ERROR_NAME); +      return TRUE; +    } +  else +    { +      return set_string_field (message, +                               FIELD_ERROR_NAME, +                               error_name); +    } +} + +/** + * Gets the error name (DBUS_MESSAGE_TYPE_ERROR only). + *  + * @param message the message + * @returns the error name (should not be freed)   */  const char* -dbus_message_get_name (DBusMessage *message) +dbus_message_get_error_name (DBusMessage *message)  {    _dbus_return_val_if_fail (message != NULL, NULL); -  return get_string_field (message, FIELD_NAME, NULL); +  return get_string_field (message, FIELD_ERROR_NAME, NULL);  }  /** @@ -3917,27 +4050,54 @@ dbus_message_get_sender (DBusMessage *message)  }  /** - * Checks whether the message has the given name. - * If the message has no name or has a different - * name, returns #FALSE. + * Checks whether the message has the given interface field.  If the + * message has no interface field or has a different one, returns + * #FALSE. + * + * @param message the message + * @param interface the name to check (must not be #NULL) + *  + * @returns #TRUE if the message has the given name + */ +dbus_bool_t +dbus_message_has_interface (DBusMessage *message, +                            const char  *interface) +{ +  const char *n; + +  _dbus_return_val_if_fail (message != NULL, FALSE); +  _dbus_return_val_if_fail (interface != NULL, FALSE); +   +  n = dbus_message_get_interface (message); + +  if (n && strcmp (n, interface) == 0) +    return TRUE; +  else +    return FALSE; +} + + +/** + * Checks whether the message has the given member field.  If the + * message has no member field or has a different one, returns #FALSE.   *   * @param message the message - * @param name the name to check (must not be #NULL) + * @param member the name to check (must not be #NULL)   *    * @returns #TRUE if the message has the given name   */  dbus_bool_t -dbus_message_has_name (DBusMessage *message, -                       const char  *name) +dbus_message_has_member (DBusMessage *message, +                         const char  *member)  {    const char *n;    _dbus_return_val_if_fail (message != NULL, FALSE); -  _dbus_return_val_if_fail (name != NULL, FALSE); +  _dbus_return_val_if_fail (member != NULL, FALSE); -  n = dbus_message_get_name (message); +  n = dbus_message_get_member (message); -  if (n && strcmp (n, name) == 0) +  if (n && strcmp (n, member) == 0)      return TRUE;    else      return FALSE; @@ -4034,7 +4194,7 @@ dbus_set_error_from_message (DBusError   *error,                           DBUS_TYPE_STRING, &str,                           DBUS_TYPE_INVALID); -  dbus_set_error (error, dbus_message_get_name (message), +  dbus_set_error (error, dbus_message_get_error_name (message),                    str ? "%s" : NULL, str);    dbus_free (str); @@ -4216,9 +4376,17 @@ _dbus_message_loader_get_buffer (DBusMessageLoader  *loader,                         (((dbus_uint32_t)c) << 8)  |     \                         ((dbus_uint32_t)d)) -/** DBUS_HEADER_FIELD_NAME packed into a dbus_uint32_t */ -#define DBUS_HEADER_FIELD_NAME_AS_UINT32    \ -  FOUR_CHARS_TO_UINT32 ('n', 'a', 'm', 'e') +/** DBUS_HEADER_FIELD_INTERFACE packed into a dbus_uint32_t */ +#define DBUS_HEADER_FIELD_INTERFACE_AS_UINT32    \ +  FOUR_CHARS_TO_UINT32 ('i', 'f', 'c', 'e') + +/** DBUS_HEADER_FIELD_MEMBER packed into a dbus_uint32_t */ +#define DBUS_HEADER_FIELD_MEMBER_AS_UINT32    \ +  FOUR_CHARS_TO_UINT32 ('m', 'e', 'b', 'r') + +/** DBUS_HEADER_FIELD_ERROR_NAME packed into a dbus_uint32_t */ +#define DBUS_HEADER_FIELD_ERROR_NAME_AS_UINT32    \ +  FOUR_CHARS_TO_UINT32 ('e', 'r', 'n', 'm')  /** DBUS_HEADER_FIELD_SERVICE packed into a dbus_uint32_t */  #define DBUS_HEADER_FIELD_SERVICE_AS_UINT32 \ @@ -4267,23 +4435,41 @@ decode_string_field (const DBusString   *data,    _dbus_string_init_const (&tmp,                             _dbus_string_get_const_data (data) + string_data_pos); -  if (field == FIELD_NAME) +  if (field == FIELD_INTERFACE)      { -      if (!_dbus_string_validate_name (&tmp, 0, _dbus_string_get_length (&tmp))) +      if (!_dbus_string_validate_interface (&tmp, 0, _dbus_string_get_length (&tmp)))          {            _dbus_verbose ("%s field has invalid content \"%s\"\n",                           field_name, _dbus_string_get_const_data (&tmp));            return FALSE;          } -      if (_dbus_string_starts_with_c_str (&tmp, -                                          DBUS_NAMESPACE_LOCAL_MESSAGE)) +      if (_dbus_string_equal_c_str (&tmp, +                                    DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL))          { -          _dbus_verbose ("Message is in the local namespace\n"); +          _dbus_verbose ("Message is on the local interface\n");            return FALSE;          }      } -  else +  else if (field == FIELD_MEMBER) +    { +      if (!_dbus_string_validate_member (&tmp, 0, _dbus_string_get_length (&tmp))) +        { +          _dbus_verbose ("%s field has invalid content \"%s\"\n", +                         field_name, _dbus_string_get_const_data (&tmp)); +          return FALSE; +        } +    } +  else if (field == FIELD_ERROR_NAME) +    { +      if (!_dbus_string_validate_error_name (&tmp, 0, _dbus_string_get_length (&tmp))) +        { +          _dbus_verbose ("%s field has invalid content \"%s\"\n", +                         field_name, _dbus_string_get_const_data (&tmp)); +          return FALSE; +        } +    } +  else if (field == FIELD_SERVICE)      {        if (!_dbus_string_validate_service (&tmp, 0, _dbus_string_get_length (&tmp)))          { @@ -4292,6 +4478,10 @@ decode_string_field (const DBusString   *data,            return FALSE;          }      } +  else +    { +      _dbus_assert_not_reached ("Unknown field\n"); +    }    fields[field].offset = _DBUS_ALIGN_VALUE (pos, 4); @@ -4307,6 +4497,7 @@ static dbus_bool_t  decode_header_data (const DBusString   *data,  		    int		        header_len,  		    int                 byte_order, +                    int                 message_type,                      HeaderField         fields[FIELD_LAST],  		    int                *message_padding)  { @@ -4375,13 +4566,27 @@ decode_header_data (const DBusString   *data,              return FALSE;            break; -        case DBUS_HEADER_FIELD_NAME_AS_UINT32: +        case DBUS_HEADER_FIELD_INTERFACE_AS_UINT32: +          if (!decode_string_field (data, fields, pos, type, +                                    FIELD_INTERFACE, +                                    DBUS_HEADER_FIELD_INTERFACE)) +            return FALSE; +          break; + +        case DBUS_HEADER_FIELD_MEMBER_AS_UINT32:            if (!decode_string_field (data, fields, pos, type, -                                    FIELD_NAME, -                                    DBUS_HEADER_FIELD_NAME)) +                                    FIELD_MEMBER, +                                    DBUS_HEADER_FIELD_MEMBER))              return FALSE;            break; +        case DBUS_HEADER_FIELD_ERROR_NAME_AS_UINT32: +          if (!decode_string_field (data, fields, pos, type, +                                    FIELD_ERROR_NAME, +                                    DBUS_HEADER_FIELD_ERROR_NAME)) +            return FALSE; +          break; +            	case DBUS_HEADER_FIELD_SENDER_AS_UINT32:            if (!decode_string_field (data, fields, pos, type,                                      FIELD_SENDER, @@ -4430,12 +4635,37 @@ decode_header_data (const DBusString   *data,          }      } -  /* Name field is mandatory */ -  if (fields[FIELD_NAME].offset < 0) +  /* Depending on message type, enforce presence of certain fields. */ +  switch (message_type)      { -      _dbus_verbose ("No %s field provided\n", -                     DBUS_HEADER_FIELD_NAME); -      return FALSE; +    case DBUS_MESSAGE_TYPE_SIGNAL: +    case DBUS_MESSAGE_TYPE_METHOD_CALL: +      if (fields[FIELD_INTERFACE].offset < 0) +        { +          _dbus_verbose ("No %s field provided\n", +                         DBUS_HEADER_FIELD_INTERFACE); +          return FALSE; +        } +      if (fields[FIELD_MEMBER].offset < 0) +        { +          _dbus_verbose ("No %s field provided\n", +                         DBUS_HEADER_FIELD_MEMBER); +          return FALSE; +        } +      break; +    case DBUS_MESSAGE_TYPE_ERROR: +      if (fields[FIELD_ERROR_NAME].offset < 0) +        { +          _dbus_verbose ("No %s field provided\n", +                         DBUS_HEADER_FIELD_ERROR_NAME); +          return FALSE; +        } +      break; +    case DBUS_MESSAGE_TYPE_METHOD_RETURN: +      break; +    default: +      /* An unknown type, spec requires us to ignore it */ +      break;      }    if (message_padding) @@ -4579,7 +4809,8 @@ _dbus_message_loader_queue_messages (DBusMessageLoader *loader)  #if 0  	  _dbus_verbose_bytes_of_string (&loader->data, 0, header_len + body_len);  #endif	   - 	  if (!decode_header_data (&loader->data, header_len, byte_order, + 	  if (!decode_header_data (&loader->data, message_type, +                                   header_len, byte_order,                                     fields, &header_padding))  	    {                _dbus_verbose ("Header was invalid\n"); @@ -6010,15 +6241,19 @@ _dbus_message_test (const char *test_data_dir)    _dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter)); -  message = dbus_message_new_method_call ("test.Message", "org.freedesktop.DBus.Test"); -  _dbus_assert (dbus_message_has_destination (message, "org.freedesktop.DBus.Test")); +  message = dbus_message_new_method_call ("Foo.TestInterface", +                                          "TestMethod", +                                          "org.freedesktop.DBus.TestService"); +  _dbus_assert (dbus_message_has_destination (message, "org.freedesktop.DBus.TestService")); +  _dbus_assert (dbus_message_has_interface (message, "Foo.TestInterface")); +  _dbus_assert (dbus_message_has_member (message, "TestMethod"));    _dbus_message_set_serial (message, 1234);    dbus_message_set_sender (message, "org.foo.bar");    _dbus_assert (dbus_message_has_sender (message, "org.foo.bar"));    dbus_message_set_sender (message, NULL);    _dbus_assert (!dbus_message_has_sender (message, "org.foo.bar"));    _dbus_assert (dbus_message_get_serial (message) == 1234); -  _dbus_assert (dbus_message_has_destination (message, "org.freedesktop.DBus.Test")); +  _dbus_assert (dbus_message_has_destination (message, "org.freedesktop.DBus.TestService"));    _dbus_assert (dbus_message_get_no_reply (message) == FALSE);    dbus_message_set_no_reply (message, TRUE); @@ -6029,7 +6264,9 @@ _dbus_message_test (const char *test_data_dir)    dbus_message_unref (message);    /* Test the vararg functions */ -  message = dbus_message_new_method_call ("test.Message", "org.freedesktop.DBus.Test"); +  message = dbus_message_new_method_call ("Foo.TestInterface", +                                          "TestMethod", +                                          "org.freedesktop.DBus.TestService");    _dbus_message_set_serial (message, 1);    dbus_message_append_args (message,  			    DBUS_TYPE_INT32, -0x12345678, @@ -6087,15 +6324,22 @@ _dbus_message_test (const char *test_data_dir)    verify_test_message (copy); -  name1 = dbus_message_get_name (message); -  name2 = dbus_message_get_name (copy); +  name1 = dbus_message_get_interface (message); +  name2 = dbus_message_get_interface (copy); + +  _dbus_assert (strcmp (name1, name2) == 0); + +  name1 = dbus_message_get_member (message); +  name2 = dbus_message_get_member (copy);    _dbus_assert (strcmp (name1, name2) == 0);    dbus_message_unref (message);    dbus_message_unref (copy); -   -  message = dbus_message_new_method_call ("test.Message", "org.freedesktop.DBus.Test"); + +  message = dbus_message_new_method_call ("Foo.TestInterface", +                                          "TestMethod", +                                          "org.freedesktop.DBus.TestService");    _dbus_message_set_serial (message, 1);    dbus_message_set_reply_serial (message, 0x12345678); diff --git a/dbus/dbus-message.h b/dbus/dbus-message.h index 1b61c8d1..dc204585 100644 --- a/dbus/dbus-message.h +++ b/dbus/dbus-message.h @@ -58,10 +58,12 @@ struct DBusMessageIter  };  DBusMessage* dbus_message_new               (int          message_type); -DBusMessage* dbus_message_new_method_call   (const char  *name, +DBusMessage* dbus_message_new_method_call   (const char  *interface, +                                             const char  *method,                                               const char  *destination_service);  DBusMessage* dbus_message_new_method_return (DBusMessage *method_call); -DBusMessage* dbus_message_new_signal        (const char  *name); +DBusMessage* dbus_message_new_signal        (const char  *interface, +                                             const char  *name);  DBusMessage* dbus_message_new_error         (DBusMessage *reply_to,                                               const char  *error_name,                                               const char  *error_message); @@ -71,9 +73,15 @@ DBusMessage *dbus_message_copy              (const DBusMessage *message);  void          dbus_message_ref              (DBusMessage   *message);  void          dbus_message_unref            (DBusMessage   *message);  int           dbus_message_get_type         (DBusMessage   *message); -dbus_bool_t   dbus_message_set_name         (DBusMessage   *message, +dbus_bool_t   dbus_message_set_interface    (DBusMessage   *message, +                                             const char    *interface); +const char*   dbus_message_get_interface    (DBusMessage   *message); +dbus_bool_t   dbus_message_set_member       (DBusMessage   *message, +                                             const char    *member); +const char*   dbus_message_get_member       (DBusMessage   *message); +dbus_bool_t   dbus_message_set_error_name   (DBusMessage   *message,                                               const char    *name); -const char*   dbus_message_get_name         (DBusMessage   *message); +const char*   dbus_message_get_error_name   (DBusMessage   *message);  dbus_bool_t   dbus_message_set_destination  (DBusMessage   *message,                                               const char    *destination);  const char*   dbus_message_get_destination  (DBusMessage   *message); @@ -83,7 +91,11 @@ const char*   dbus_message_get_sender       (DBusMessage   *message);  void          dbus_message_set_no_reply     (DBusMessage   *message,                                               dbus_bool_t    no_reply);  dbus_bool_t   dbus_message_get_no_reply     (DBusMessage   *message); -dbus_bool_t   dbus_message_has_name         (DBusMessage   *message, +dbus_bool_t   dbus_message_has_interface    (DBusMessage   *message, +                                             const char    *interface); +dbus_bool_t   dbus_message_has_member       (DBusMessage   *message, +                                             const char    *member); +dbus_bool_t   dbus_message_has_error_name   (DBusMessage   *message,                                               const char    *name);  dbus_bool_t   dbus_message_has_destination  (DBusMessage   *message,                                               const char    *service); diff --git a/dbus/dbus-object-registry.c b/dbus/dbus-object-registry.c index d3d175d8..e5a81315 100644 --- a/dbus/dbus-object-registry.c +++ b/dbus/dbus-object-registry.c @@ -63,7 +63,7 @@ struct DBusSignalEntry    dbus_uint16_t *connections;      /**< Index of each object connected (can have dups for multiple                                      * connections)                                      */ -  char name[4];                    /**< Name of signal (actually allocated larger) */ +  char name[4];                    /**< Interface of signal, nul, then name of signal (actually allocated larger) */  };   /* 14 bits for object index, 32K objects */ @@ -144,8 +144,8 @@ _dbus_object_registry_new (DBusConnection *connection)    if (interface_table == NULL)      goto oom; -  signal_table = _dbus_hash_table_new (DBUS_HASH_STRING, -                                          NULL, free_signal_entry); +  signal_table = _dbus_hash_table_new (DBUS_HASH_TWO_STRINGS, +                                       NULL, free_signal_entry);    if (signal_table == NULL)      goto oom; @@ -431,32 +431,45 @@ object_remove_from_interfaces (DBusObjectRegistry *registry,  static DBusSignalEntry*  lookup_signal (DBusObjectRegistry *registry, -               const char         *name, +               const char         *signal_interface, +               const char         *signal_name,                 dbus_bool_t         create_if_not_found)  {    DBusSignalEntry *entry;    int sz; -  int len; +  size_t len_interface, len_name; +  char buf[2 * DBUS_MAXIMUM_NAME_LENGTH + 2]; + +  /* This is all a little scary and maybe we shouldn't jump +   * through these hoops just to save some bytes. +   */ -  entry = _dbus_hash_table_lookup_string (registry->signal_table, -                                          name); +  len_interface = strlen (signal_interface); +  len_name = strlen (signal_name); +   +  _dbus_assert (len_interface + len_name + 2 <= sizeof (buf)); + +  memcpy (buf, signal_interface, len_interface + 1); +  memcpy (buf + len_interface + 1, signal_name, len_name + 1); +   +  entry = _dbus_hash_table_lookup_two_strings (registry->signal_table, +                                               buf);    if (entry != NULL || !create_if_not_found)      return entry;    _dbus_assert (create_if_not_found); -  len = strlen (name); -  sz = _DBUS_STRUCT_OFFSET (DBusSignalEntry, name) + len + 1; +  sz = _DBUS_STRUCT_OFFSET (DBusSignalEntry, name) + len_interface + len_name + 2;    entry = dbus_malloc (sz);    if (entry == NULL)      return NULL;    entry->n_connections = 0;    entry->n_allocated = 0;    entry->connections = NULL; -  memcpy (entry->name, name, len + 1); +  memcpy (entry->name, buf, len_interface + len_name + 2); -  if (!_dbus_hash_table_insert_string (registry->signal_table, -                                       entry->name, entry)) +  if (!_dbus_hash_table_insert_two_strings (registry->signal_table, +                                            entry->name, entry))      {        dbus_free (entry);        return NULL; @@ -469,8 +482,8 @@ static void  delete_signal (DBusObjectRegistry *registry,                 DBusSignalEntry *entry)  { -  _dbus_hash_table_remove_string (registry->signal_table, -                                  entry->name); +  _dbus_hash_table_remove_two_strings (registry->signal_table, +                                       entry->name);  }  static dbus_bool_t @@ -553,11 +566,11 @@ object_remove_from_signals (DBusObjectRegistry *registry,        i = 0;        while (entry->signals[i] != NULL)          { -          DBusSignalEntry *iface = entry->signals[i]; +          DBusSignalEntry *signal = entry->signals[i]; -          signal_entry_remove_object (iface, entry->id_index); -          if (iface->n_connections == 0) -            delete_signal (registry, iface); +          signal_entry_remove_object (signal, entry->id_index); +          if (signal->n_connections == 0) +            delete_signal (registry, signal);            ++i;          }      } @@ -573,19 +586,24 @@ object_remove_from_signals (DBusObjectRegistry *registry,   *    * @param registry the object registry   * @param object_id object that would like to see the signal - * @param signal signal name + * @param signal_interface signal interface name + * @param signal_name signal member name   *   * @returns #FALSE if no memory   */  dbus_bool_t  _dbus_object_registry_connect_locked (DBusObjectRegistry *registry,                                        const DBusObjectID *object_id, +                                      const char         *signal_interface,                                        const char         *signal_name)  {    DBusSignalEntry **new_signals;    DBusSignalEntry *signal;    DBusObjectEntry *entry;    int i; + +  _dbus_assert (signal_interface != NULL); +  _dbus_assert (signal_name != NULL);    entry = validate_id (registry, object_id);    if (entry == NULL) @@ -617,7 +635,7 @@ _dbus_object_registry_connect_locked (DBusObjectRegistry *registry,    entry->signals = new_signals; -  signal = lookup_signal (registry, signal_name, TRUE);  +  signal = lookup_signal (registry, signal_interface, signal_name, TRUE);     if (signal == NULL)      goto oom; @@ -642,30 +660,35 @@ _dbus_object_registry_connect_locked (DBusObjectRegistry *registry,   *   * @param registry the object registry   * @param object_id object that would like to see the signal - * @param signal signal name + * @param signal_interface signal interface + * @param signal_name signal name   */  void  _dbus_object_registry_disconnect_locked (DBusObjectRegistry      *registry,                                           const DBusObjectID      *object_id, +                                         const char              *signal_interface,                                           const char              *signal_name)  {    DBusObjectEntry *entry;    DBusSignalEntry *signal; + +  _dbus_assert (signal_interface != NULL); +  _dbus_assert (signal_name != NULL);    entry = validate_id (registry, object_id);    if (entry == NULL)      { -      _dbus_warn ("Tried to disconnect signal \"%s\" from a nonexistent D-BUS object ID\n", -                  signal_name); +      _dbus_warn ("Tried to disconnect signal \"%s\"::\"%s\" from a nonexistent D-BUS object ID\n", +                  signal_interface, signal_name);        return;      } -  signal = lookup_signal (registry, signal_name, FALSE); +  signal = lookup_signal (registry, signal_interface, signal_name, FALSE);    if (signal == NULL)      { -      _dbus_warn ("Tried to disconnect signal \"%s\" but no such signal is connected\n", -                  signal_name); +      _dbus_warn ("Tried to disconnect signal \"%s\"::\"%s\" but no such signal is connected\n", +                  signal_interface, signal_name);        return;      } @@ -695,7 +718,7 @@ handle_method_call_and_unlock (DBusObjectRegistry *registry,     * it to the first object that supports the given interface.     */    iface_entry = lookup_interface (registry, -                                  dbus_message_get_name (message), +                                  dbus_message_get_interface (message),                                    FALSE);    if (iface_entry == NULL) @@ -750,7 +773,8 @@ handle_signal_and_unlock (DBusObjectRegistry *registry,    _dbus_assert (message != NULL);    signal_entry = lookup_signal (registry, -                                dbus_message_get_name (message), +                                dbus_message_get_interface (message), +                                dbus_message_get_member (message),                                  FALSE);    if (signal_entry == NULL) @@ -1291,7 +1315,8 @@ add_and_remove_objects (DBusObjectRegistry *registry)        ++i;      } -  message = dbus_message_new_method_call ("org.freedesktop.Test.Foo", NULL); +  message = dbus_message_new_method_call ("org.freedesktop.Test.Foo", +                                          "Bar", NULL);    if (message != NULL)      {        if (_dbus_object_registry_handle_and_unlock (registry, message) != @@ -1300,7 +1325,8 @@ add_and_remove_objects (DBusObjectRegistry *registry)        dbus_message_unref (message);      } -  message = dbus_message_new_method_call ("org.freedesktop.Test.Blah", NULL); +  message = dbus_message_new_method_call ("org.freedesktop.Test.Blah", +                                          "Baz", NULL);    if (message != NULL)      {        if (_dbus_object_registry_handle_and_unlock (registry, message) != @@ -1309,7 +1335,8 @@ add_and_remove_objects (DBusObjectRegistry *registry)        dbus_message_unref (message);      } -  message = dbus_message_new_method_call ("org.freedesktop.Test.NotRegisteredIface", NULL); +  message = dbus_message_new_method_call ("org.freedesktop.Test.NotRegisteredIface", +                                          "Boo", NULL);    if (message != NULL)      {        if (_dbus_object_registry_handle_and_unlock (registry, message) != diff --git a/dbus/dbus-object-registry.h b/dbus/dbus-object-registry.h index bcbd0f84..29c92b9c 100644 --- a/dbus/dbus-object-registry.h +++ b/dbus/dbus-object-registry.h @@ -45,10 +45,12 @@ DBusHandlerResult _dbus_object_registry_handle_and_unlock (DBusObjectRegistry  void              _dbus_object_registry_free_all_unlocked (DBusObjectRegistry      *registry);  dbus_bool_t       _dbus_object_registry_connect_locked    (DBusObjectRegistry      *registry,                                                             const DBusObjectID      *object_id, -                                                           const char              *signal); +                                                           const char              *signal_interface, +                                                           const char              *signal_name);  void              _dbus_object_registry_disconnect_locked (DBusObjectRegistry      *registry,                                                             const DBusObjectID      *object_id, -                                                           const char              *signal); +                                                           const char              *signal_interface, +                                                           const char              *signal_name);  DBUS_END_DECLS; diff --git a/dbus/dbus-protocol.h b/dbus/dbus-protocol.h index e027cf56..a1f4a722 100644 --- a/dbus/dbus-protocol.h +++ b/dbus/dbus-protocol.h @@ -57,7 +57,7 @@ extern "C" {  #define DBUS_TYPE_LAST DBUS_TYPE_OBJECT_ID -/* Max length in bytes of a service or message name */ +/* Max length in bytes of a service or interface or member name */  #define DBUS_MAXIMUM_NAME_LENGTH 256  /* Types of message */ @@ -71,14 +71,16 @@ extern "C" {  #define DBUS_HEADER_FLAG_NO_REPLY_EXPECTED 0x1  /* Header fields */ -#define DBUS_HEADER_FIELD_NAME    "name" -#define DBUS_HEADER_FIELD_SERVICE "srvc" -#define DBUS_HEADER_FIELD_REPLY	  "rply" -#define DBUS_HEADER_FIELD_SENDER  "sndr" +#define DBUS_HEADER_FIELD_INTERFACE  "ifce" +#define DBUS_HEADER_FIELD_MEMBER     "mebr" +#define DBUS_HEADER_FIELD_ERROR_NAME "ernm" +#define DBUS_HEADER_FIELD_SERVICE    "srvc" +#define DBUS_HEADER_FIELD_REPLY	     "rply" +#define DBUS_HEADER_FIELD_SENDER     "sndr"  /* Services */ -#define DBUS_SERVICE_DBUS      "org.freedesktop.DBus" -#define DBUS_SERVICE_BROADCAST "org.freedesktop.DBus.Broadcast" +#define DBUS_SERVICE_ORG_FREEDESKTOP_DBUS      "org.freedesktop.DBus" +#define DBUS_SERVICE_ORG_FREEDESKTOP_BROADCAST "org.freedesktop.Broadcast"  /* Service owner flags */  #define DBUS_SERVICE_FLAG_PROHIBIT_REPLACEMENT 0x1 @@ -94,23 +96,30 @@ extern "C" {  #define DBUS_ACTIVATION_REPLY_ACTIVATED      0x0  #define DBUS_ACTIVATION_REPLY_ALREADY_ACTIVE 0x1 -/* Messages */ -#define DBUS_MESSAGE_ACTIVATE_SERVICE      "org.freedesktop.DBus.ActivateService"   -#define DBUS_MESSAGE_SERVICE_EXISTS        "org.freedesktop.DBus.ServiceExists" -#define DBUS_MESSAGE_HELLO                 "org.freedesktop.DBus.Hello" -#define DBUS_MESSAGE_LIST_SERVICES         "org.freedesktop.DBus.ListServices" -#define DBUS_MESSAGE_ACQUIRE_SERVICE       "org.freedesktop.DBus.AcquireService" -#define DBUS_MESSAGE_SERVICE_ACQUIRED      "org.freedesktop.DBus.ServiceAcquired" -#define DBUS_MESSAGE_SERVICE_CREATED       "org.freedesktop.DBus.ServiceCreated" -#define DBUS_MESSAGE_SERVICE_DELETED       "org.freedesktop.DBus.ServiceDeleted" -#define DBUS_MESSAGE_SERVICE_LOST          "org.freedesktop.DBus.ServiceLost" - - -/* This namespace is reserved for locally-synthesized messages, you can't - * send messages that have this namespace. +/* Interfaces, these #define don't do much other than + * catch typos at compile time   */ -#define DBUS_NAMESPACE_LOCAL_MESSAGE       "org.freedesktop.Local." -#define DBUS_MESSAGE_LOCAL_DISCONNECT      DBUS_NAMESPACE_LOCAL_MESSAGE"Disconnect" +#define DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS  "org.freedesktop.DBus" + +/* This is a special interface whose methods can only be invoked + * by the local implementation (messages from remote apps aren't + * allowed to specify this interface). + */ +#define DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL "org.freedesktop.Local" + +#if 0 +  /* these are a bad idea, FIXME */ +#define DBUS_METHOD_ORG_FREEDESKTOP_DBUS_ACTIVATE_SERVICE      "ActivateService"   +#define DBUS_METHOD_ORG_FREEDESKTOP_DBUS_SERVICE_EXISTS        "ServiceExists" +#define DBUS_METHOD_ORG_FREEDESKTOP_DBUS_HELLO                 "Hello" +#define DBUS_METHOD_ORG_FREEDESKTOP_DBUS_LIST_SERVICES         "ListServices" +#define DBUS_METHOD_ORG_FREEDESKTOP_DBUS_ACQUIRE_SERVICE       "AcquireService" + +#define DBUS_SIGNAL_ORG_FREEDESKTOP_DBUS_SERVICE_ACQUIRED      "ServiceAcquired" +#define DBUS_SIGNAL_ORG_FREEDESKTOP_DBUS_SERVICE_CREATED       "ServiceCreated" +#define DBUS_SIGNAL_ORG_FREEDESKTOP_DBUS_SERVICE_DELETED       "ServiceDeleted" +#define DBUS_SIGNAL_ORG_FREEDESKTOP_DBUS_SERVICE_LOST          "ServiceLost" +#endif /* #if 0 */  #ifdef __cplusplus  } diff --git a/dbus/dbus-string.c b/dbus/dbus-string.c index f4f7a2ad..848135fc 100644 --- a/dbus/dbus-string.c +++ b/dbus/dbus-string.c @@ -2846,7 +2846,7 @@ _dbus_string_validate_nul (const DBusString *str,  }  /** - * Checks that the given range of the string is a valid message name + * Checks that the given range of the string is a valid interface name   * in the D-BUS protocol. This includes a length restriction, etc.,   * see the specification. It does not validate UTF-8, that has to be   * done separately for now. @@ -2860,9 +2860,9 @@ _dbus_string_validate_nul (const DBusString *str,   * @returns #TRUE if the byte range exists and is a valid name   */  dbus_bool_t -_dbus_string_validate_name (const DBusString  *str, -                            int                start, -                            int                len) +_dbus_string_validate_interface (const DBusString  *str, +                                 int                start, +                                 int                len)  {    const unsigned char *s;    const unsigned char *end; @@ -2902,6 +2902,86 @@ _dbus_string_validate_name (const DBusString  *str,    return TRUE;  } +/** + * Checks that the given range of the string is a valid member name + * in the D-BUS protocol. This includes a length restriction, etc., + * see the specification. It does not validate UTF-8, that has to be + * done separately for now. + * + * @todo this is inconsistent with most of DBusString in that + * it allows a start,len range that isn't in the string. + *  + * @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_string_validate_member (const DBusString  *str, +                              int                start, +                              int                len) +{ +  const unsigned char *s; +  const unsigned char *end; +  dbus_bool_t saw_dot; +   +  DBUS_CONST_STRING_PREAMBLE (str); +  _dbus_assert (start >= 0); +  _dbus_assert (len >= 0); +  _dbus_assert (start <= real->len); +   +  if (len > real->len - start) +    return FALSE; + +  if (len > DBUS_MAXIMUM_NAME_LENGTH) +    return FALSE; + +  if (len == 0) +    return FALSE; + +  saw_dot = FALSE; +  s = real->str + start; +  end = s + len; +  while (s != end) +    { +      if (*s == '.') +        { +          saw_dot = TRUE; +          break; +        } +       +      ++s; +    } + +  /* No dot allowed in member names */ +  if (saw_dot) +    return FALSE; +   +  return TRUE; +} + +/** + * Checks that the given range of the string is a valid error name + * in the D-BUS protocol. This includes a length restriction, etc., + * see the specification. It does not validate UTF-8, that has to be + * done separately for now. + * + * @todo this is inconsistent with most of DBusString in that + * it allows a start,len range that isn't in the string. + *  + * @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_string_validate_error_name (const DBusString  *str, +                                  int                start, +                                  int                len) +{ +  /* Same restrictions as interface name at the moment */ +  return _dbus_string_validate_interface (str, start, len); +}  /**   * Checks that the given range of the string is a valid service name diff --git a/dbus/dbus-string.h b/dbus/dbus-string.h index 732359a0..6f164be6 100644 --- a/dbus/dbus-string.h +++ b/dbus/dbus-string.h @@ -223,7 +223,13 @@ dbus_bool_t   _dbus_string_validate_utf8         (const DBusString  *str,  dbus_bool_t   _dbus_string_validate_nul          (const DBusString  *str,                                                    int                start,                                                    int                len); -dbus_bool_t   _dbus_string_validate_name         (const DBusString  *str, +dbus_bool_t   _dbus_string_validate_interface    (const DBusString  *str, +                                                  int                start, +                                                  int                len); +dbus_bool_t   _dbus_string_validate_member       (const DBusString  *str, +                                                  int                start, +                                                  int                len); +dbus_bool_t   _dbus_string_validate_error_name   (const DBusString  *str,                                                    int                start,                                                    int                len);  dbus_bool_t   _dbus_string_validate_service      (const DBusString  *str, | 
