diff options
Diffstat (limited to 'src/3rd_party/dbus-1.7.8/bus/signals.c')
-rw-r--r-- | src/3rd_party/dbus-1.7.8/bus/signals.c | 2841 |
1 files changed, 0 insertions, 2841 deletions
diff --git a/src/3rd_party/dbus-1.7.8/bus/signals.c b/src/3rd_party/dbus-1.7.8/bus/signals.c deleted file mode 100644 index 4c500c67fd..0000000000 --- a/src/3rd_party/dbus-1.7.8/bus/signals.c +++ /dev/null @@ -1,2841 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ -/* signals.c Bus signal connection implementation - * - * Copyright (C) 2003, 2005 Red Hat, Inc. - * - * Licensed under the Academic Free License version 2.1 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include <config.h> -#include "signals.h" -#include "services.h" -#include "utils.h" -#include <dbus/dbus-marshal-validate.h> - -struct BusMatchRule -{ - int refcount; /**< reference count */ - - DBusConnection *matches_go_to; /**< Owner of the rule */ - - unsigned int flags; /**< BusMatchFlags */ - - int message_type; - char *interface; - char *member; - char *sender; - char *destination; - char *path; - - unsigned int *arg_lens; - char **args; - int args_len; -}; - -#define BUS_MATCH_ARG_NAMESPACE 0x4000000u -#define BUS_MATCH_ARG_IS_PATH 0x8000000u - -#define BUS_MATCH_ARG_FLAGS (BUS_MATCH_ARG_NAMESPACE | BUS_MATCH_ARG_IS_PATH) - -BusMatchRule* -bus_match_rule_new (DBusConnection *matches_go_to) -{ - BusMatchRule *rule; - - rule = dbus_new0 (BusMatchRule, 1); - if (rule == NULL) - return NULL; - - rule->refcount = 1; - rule->matches_go_to = matches_go_to; - -#ifndef DBUS_ENABLE_EMBEDDED_TESTS - _dbus_assert (rule->matches_go_to != NULL); -#endif - - return rule; -} - -BusMatchRule * -bus_match_rule_ref (BusMatchRule *rule) -{ - _dbus_assert (rule->refcount > 0); - - rule->refcount += 1; - - return rule; -} - -void -bus_match_rule_unref (BusMatchRule *rule) -{ - _dbus_assert (rule->refcount > 0); - - rule->refcount -= 1; - if (rule->refcount == 0) - { - dbus_free (rule->interface); - dbus_free (rule->member); - dbus_free (rule->sender); - dbus_free (rule->destination); - dbus_free (rule->path); - dbus_free (rule->arg_lens); - - /* can't use dbus_free_string_array() since there - * are embedded NULL - */ - if (rule->args) - { - int i; - - i = 0; - while (i < rule->args_len) - { - if (rule->args[i]) - dbus_free (rule->args[i]); - ++i; - } - - dbus_free (rule->args); - } - - dbus_free (rule); - } -} - -#ifdef DBUS_ENABLE_VERBOSE_MODE -/* Note this function does not do escaping, so it's only - * good for debug spew at the moment - */ -static char* -match_rule_to_string (BusMatchRule *rule) -{ - DBusString str; - char *ret; - - if (!_dbus_string_init (&str)) - { - char *s; - while ((s = _dbus_strdup ("nomem")) == NULL) - ; /* only OK for debug spew... */ - return s; - } - - if (rule->flags & BUS_MATCH_MESSAGE_TYPE) - { - if (!_dbus_string_append_printf (&str, "type='%s'", - dbus_message_type_to_string (rule->message_type))) - goto nomem; - } - - if (rule->flags & BUS_MATCH_INTERFACE) - { - if (_dbus_string_get_length (&str) > 0) - { - if (!_dbus_string_append (&str, ",")) - goto nomem; - } - - if (!_dbus_string_append_printf (&str, "interface='%s'", rule->interface)) - goto nomem; - } - - if (rule->flags & BUS_MATCH_MEMBER) - { - if (_dbus_string_get_length (&str) > 0) - { - if (!_dbus_string_append (&str, ",")) - goto nomem; - } - - if (!_dbus_string_append_printf (&str, "member='%s'", rule->member)) - goto nomem; - } - - if (rule->flags & BUS_MATCH_PATH) - { - if (_dbus_string_get_length (&str) > 0) - { - if (!_dbus_string_append (&str, ",")) - goto nomem; - } - - if (!_dbus_string_append_printf (&str, "path='%s'", rule->path)) - goto nomem; - } - - if (rule->flags & BUS_MATCH_PATH_NAMESPACE) - { - if (_dbus_string_get_length (&str) > 0) - { - if (!_dbus_string_append (&str, ",")) - goto nomem; - } - - if (!_dbus_string_append_printf (&str, "path_namespace='%s'", rule->path)) - goto nomem; - } - - if (rule->flags & BUS_MATCH_SENDER) - { - if (_dbus_string_get_length (&str) > 0) - { - if (!_dbus_string_append (&str, ",")) - goto nomem; - } - - if (!_dbus_string_append_printf (&str, "sender='%s'", rule->sender)) - goto nomem; - } - - if (rule->flags & BUS_MATCH_DESTINATION) - { - if (_dbus_string_get_length (&str) > 0) - { - if (!_dbus_string_append (&str, ",")) - goto nomem; - } - - if (!_dbus_string_append_printf (&str, "destination='%s'", rule->destination)) - goto nomem; - } - - if (rule->flags & BUS_MATCH_CLIENT_IS_EAVESDROPPING) - { - if (_dbus_string_get_length (&str) > 0) - { - if (!_dbus_string_append (&str, ",")) - goto nomem; - } - - if (!_dbus_string_append_printf (&str, "eavesdrop='%s'", - (rule->flags & BUS_MATCH_CLIENT_IS_EAVESDROPPING) ? - "true" : "false")) - goto nomem; - } - - if (rule->flags & BUS_MATCH_ARGS) - { - int i; - - _dbus_assert (rule->args != NULL); - - i = 0; - while (i < rule->args_len) - { - if (rule->args[i] != NULL) - { - dbus_bool_t is_path, is_namespace; - - if (_dbus_string_get_length (&str) > 0) - { - if (!_dbus_string_append (&str, ",")) - goto nomem; - } - - is_path = (rule->arg_lens[i] & BUS_MATCH_ARG_IS_PATH) != 0; - is_namespace = (rule->arg_lens[i] & BUS_MATCH_ARG_NAMESPACE) != 0; - - if (!_dbus_string_append_printf (&str, - "arg%d%s='%s'", - i, - is_path ? "path" : - is_namespace ? "namespace" : "", - rule->args[i])) - goto nomem; - } - - ++i; - } - } - - if (!_dbus_string_steal_data (&str, &ret)) - goto nomem; - - _dbus_string_free (&str); - return ret; - - nomem: - _dbus_string_free (&str); - { - char *s; - while ((s = _dbus_strdup ("nomem")) == NULL) - ; /* only OK for debug spew... */ - return s; - } -} -#endif /* DBUS_ENABLE_VERBOSE_MODE */ - -dbus_bool_t -bus_match_rule_set_message_type (BusMatchRule *rule, - int type) -{ - rule->flags |= BUS_MATCH_MESSAGE_TYPE; - - rule->message_type = type; - - return TRUE; -} - -dbus_bool_t -bus_match_rule_set_interface (BusMatchRule *rule, - const char *interface) -{ - char *new; - - _dbus_assert (interface != NULL); - - new = _dbus_strdup (interface); - if (new == NULL) - return FALSE; - - rule->flags |= BUS_MATCH_INTERFACE; - dbus_free (rule->interface); - rule->interface = new; - - return TRUE; -} - -dbus_bool_t -bus_match_rule_set_member (BusMatchRule *rule, - const char *member) -{ - char *new; - - _dbus_assert (member != NULL); - - new = _dbus_strdup (member); - if (new == NULL) - return FALSE; - - rule->flags |= BUS_MATCH_MEMBER; - dbus_free (rule->member); - rule->member = new; - - return TRUE; -} - -dbus_bool_t -bus_match_rule_set_sender (BusMatchRule *rule, - const char *sender) -{ - char *new; - - _dbus_assert (sender != NULL); - - new = _dbus_strdup (sender); - if (new == NULL) - return FALSE; - - rule->flags |= BUS_MATCH_SENDER; - dbus_free (rule->sender); - rule->sender = new; - - return TRUE; -} - -dbus_bool_t -bus_match_rule_set_destination (BusMatchRule *rule, - const char *destination) -{ - char *new; - - _dbus_assert (destination != NULL); - - new = _dbus_strdup (destination); - if (new == NULL) - return FALSE; - - rule->flags |= BUS_MATCH_DESTINATION; - dbus_free (rule->destination); - rule->destination = new; - - return TRUE; -} - -void -bus_match_rule_set_client_is_eavesdropping (BusMatchRule *rule, - dbus_bool_t is_eavesdropping) -{ - if (is_eavesdropping) - rule->flags |= BUS_MATCH_CLIENT_IS_EAVESDROPPING; - else - rule->flags &= ~(BUS_MATCH_CLIENT_IS_EAVESDROPPING); -} - -dbus_bool_t -bus_match_rule_set_path (BusMatchRule *rule, - const char *path, - dbus_bool_t is_namespace) -{ - char *new; - - _dbus_assert (path != NULL); - - new = _dbus_strdup (path); - if (new == NULL) - return FALSE; - - rule->flags &= ~(BUS_MATCH_PATH|BUS_MATCH_PATH_NAMESPACE); - - if (is_namespace) - rule->flags |= BUS_MATCH_PATH_NAMESPACE; - else - rule->flags |= BUS_MATCH_PATH; - - dbus_free (rule->path); - rule->path = new; - - return TRUE; -} - -dbus_bool_t -bus_match_rule_set_arg (BusMatchRule *rule, - int arg, - const DBusString *value, - dbus_bool_t is_path, - dbus_bool_t is_namespace) -{ - int length; - char *new; - - _dbus_assert (value != NULL); - - /* args_len is the number of args not including null termination - * in the char** - */ - if (arg >= rule->args_len) - { - unsigned int *new_arg_lens; - char **new_args; - int new_args_len; - int i; - - new_args_len = arg + 1; - - /* add another + 1 here for null termination */ - new_args = dbus_realloc (rule->args, - sizeof (char *) * (new_args_len + 1)); - if (new_args == NULL) - return FALSE; - - /* NULL the new slots */ - i = rule->args_len; - while (i <= new_args_len) /* <= for null termination */ - { - new_args[i] = NULL; - ++i; - } - - rule->args = new_args; - - /* and now add to the lengths */ - new_arg_lens = dbus_realloc (rule->arg_lens, - sizeof (int) * (new_args_len + 1)); - - if (new_arg_lens == NULL) - return FALSE; - - /* zero the new slots */ - i = rule->args_len; - while (i <= new_args_len) /* <= for null termination */ - { - new_arg_lens[i] = 0; - ++i; - } - - rule->arg_lens = new_arg_lens; - rule->args_len = new_args_len; - } - - length = _dbus_string_get_length (value); - if (!_dbus_string_copy_data (value, &new)) - return FALSE; - - rule->flags |= BUS_MATCH_ARGS; - - dbus_free (rule->args[arg]); - rule->arg_lens[arg] = length; - rule->args[arg] = new; - - if (is_path) - rule->arg_lens[arg] |= BUS_MATCH_ARG_IS_PATH; - - if (is_namespace) - rule->arg_lens[arg] |= BUS_MATCH_ARG_NAMESPACE; - - /* NULL termination didn't get busted */ - _dbus_assert (rule->args[rule->args_len] == NULL); - _dbus_assert (rule->arg_lens[rule->args_len] == 0); - - return TRUE; -} - -#define ISWHITE(c) (((c) == ' ') || ((c) == '\t') || ((c) == '\n') || ((c) == '\r')) - -static dbus_bool_t -find_key (const DBusString *str, - int start, - DBusString *key, - int *value_pos, - DBusError *error) -{ - const char *p; - const char *s; - const char *key_start; - const char *key_end; - - _DBUS_ASSERT_ERROR_IS_CLEAR (error); - - s = _dbus_string_get_const_data (str); - - p = s + start; - - while (*p && ISWHITE (*p)) - ++p; - - key_start = p; - - while (*p && *p != '=' && !ISWHITE (*p)) - ++p; - - key_end = p; - - while (*p && ISWHITE (*p)) - ++p; - - if (key_start == key_end) - { - /* Empty match rules or trailing whitespace are OK */ - *value_pos = p - s; - return TRUE; - } - - if (*p != '=') - { - dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID, - "Match rule has a key with no subsequent '=' character"); - return FALSE; - } - ++p; - - if (!_dbus_string_append_len (key, key_start, key_end - key_start)) - { - BUS_SET_OOM (error); - return FALSE; - } - - *value_pos = p - s; - - return TRUE; -} - -static dbus_bool_t -find_value (const DBusString *str, - int start, - const char *key, - DBusString *value, - int *value_end, - DBusError *error) -{ - const char *p; - const char *s; - char quote_char; - int orig_len; - - _DBUS_ASSERT_ERROR_IS_CLEAR (error); - - orig_len = _dbus_string_get_length (value); - - s = _dbus_string_get_const_data (str); - - p = s + start; - - quote_char = '\0'; - - while (*p) - { - if (quote_char == '\0') - { - switch (*p) - { - case '\0': - goto done; - - case '\'': - quote_char = '\''; - goto next; - - case ',': - ++p; - goto done; - - case '\\': - quote_char = '\\'; - goto next; - - default: - if (!_dbus_string_append_byte (value, *p)) - { - BUS_SET_OOM (error); - goto failed; - } - } - } - else if (quote_char == '\\') - { - /* \ only counts as an escape if escaping a quote mark */ - if (*p != '\'') - { - if (!_dbus_string_append_byte (value, '\\')) - { - BUS_SET_OOM (error); - goto failed; - } - } - - if (!_dbus_string_append_byte (value, *p)) - { - BUS_SET_OOM (error); - goto failed; - } - - quote_char = '\0'; - } - else - { - _dbus_assert (quote_char == '\''); - - if (*p == '\'') - { - quote_char = '\0'; - } - else - { - if (!_dbus_string_append_byte (value, *p)) - { - BUS_SET_OOM (error); - goto failed; - } - } - } - - next: - ++p; - } - - done: - - if (quote_char == '\\') - { - if (!_dbus_string_append_byte (value, '\\')) - { - BUS_SET_OOM (error); - goto failed; - } - } - else if (quote_char == '\'') - { - dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID, - "Unbalanced quotation marks in match rule"); - goto failed; - } - else - _dbus_assert (quote_char == '\0'); - - /* Zero-length values are allowed */ - - *value_end = p - s; - - return TRUE; - - failed: - _DBUS_ASSERT_ERROR_IS_SET (error); - _dbus_string_set_length (value, orig_len); - return FALSE; -} - -/* duplicates aren't allowed so the real legitimate max is only 6 or - * so. Leaving extra so we don't have to bother to update it. - * FIXME this is sort of busted now with arg matching, but we let - * you match on up to 10 args for now - */ -#define MAX_RULE_TOKENS 16 - -/* this is slightly too high level to be termed a "token" - * but let's not be pedantic. - */ -typedef struct -{ - char *key; - char *value; -} RuleToken; - -static dbus_bool_t -tokenize_rule (const DBusString *rule_text, - RuleToken tokens[MAX_RULE_TOKENS], - DBusError *error) -{ - int i; - int pos; - DBusString key; - DBusString value; - dbus_bool_t retval; - - retval = FALSE; - - if (!_dbus_string_init (&key)) - { - BUS_SET_OOM (error); - return FALSE; - } - - if (!_dbus_string_init (&value)) - { - _dbus_string_free (&key); - BUS_SET_OOM (error); - return FALSE; - } - - i = 0; - pos = 0; - while (i < MAX_RULE_TOKENS && - pos < _dbus_string_get_length (rule_text)) - { - _dbus_assert (tokens[i].key == NULL); - _dbus_assert (tokens[i].value == NULL); - - if (!find_key (rule_text, pos, &key, &pos, error)) - goto out; - - if (_dbus_string_get_length (&key) == 0) - goto next; - - if (!_dbus_string_steal_data (&key, &tokens[i].key)) - { - BUS_SET_OOM (error); - goto out; - } - - if (!find_value (rule_text, pos, tokens[i].key, &value, &pos, error)) - goto out; - - if (!_dbus_string_steal_data (&value, &tokens[i].value)) - { - BUS_SET_OOM (error); - goto out; - } - - next: - ++i; - } - - retval = TRUE; - - out: - if (!retval) - { - i = 0; - while (tokens[i].key || tokens[i].value) - { - dbus_free (tokens[i].key); - dbus_free (tokens[i].value); - tokens[i].key = NULL; - tokens[i].value = NULL; - ++i; - } - } - - _dbus_string_free (&key); - _dbus_string_free (&value); - - return retval; -} - -static dbus_bool_t -bus_match_rule_parse_arg_match (BusMatchRule *rule, - const char *key, - const DBusString *value, - DBusError *error) -{ - dbus_bool_t is_path = FALSE; - dbus_bool_t is_namespace = FALSE; - DBusString key_str; - unsigned long arg; - int length; - int end; - - /* For now, arg0='foo' always implies that 'foo' is a - * DBUS_TYPE_STRING. Someday we could add an arg0type='int32' thing - * if we wanted, which would specify another type, in which case - * arg0='5' would have the 5 parsed as an int rather than string. - */ - - /* First we need to parse arg0 = 0, arg27 = 27 */ - - _dbus_string_init_const (&key_str, key); - length = _dbus_string_get_length (&key_str); - - if (_dbus_string_get_length (&key_str) < 4) - { - dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID, - "Key '%s' in match rule starts with 'arg' but lacks an arg number. Should be 'arg0' or 'arg7' for example.\n", key); - goto failed; - } - - if (!_dbus_string_parse_uint (&key_str, 3, &arg, &end)) - { - dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID, - "Key '%s' in match rule starts with 'arg' but could not parse arg number. Should be 'arg0' or 'arg7' for example.\n", key); - goto failed; - } - - if (end != length) - { - if ((end + strlen ("path")) == length && - _dbus_string_ends_with_c_str (&key_str, "path")) - { - is_path = TRUE; - } - else if (_dbus_string_equal_c_str (&key_str, "arg0namespace")) - { - int value_len = _dbus_string_get_length (value); - - is_namespace = TRUE; - - if (!_dbus_validate_bus_namespace (value, 0, value_len)) - { - dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID, - "arg0namespace='%s' is not a valid prefix of a bus name", - _dbus_string_get_const_data (value)); - goto failed; - } - } - else - { - dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID, - "Key '%s' in match rule contains junk after argument number (%u). Only 'arg%upath' (for example) or 'arg0namespace' are valid", key, arg, arg); - goto failed; - } - } - - /* If we didn't check this we could allocate a huge amount of RAM */ - if (arg > DBUS_MAXIMUM_MATCH_RULE_ARG_NUMBER) - { - dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID, - "Key '%s' in match rule has arg number %lu but the maximum is %d.\n", key, (unsigned long) arg, DBUS_MAXIMUM_MATCH_RULE_ARG_NUMBER); - goto failed; - } - - if ((rule->flags & BUS_MATCH_ARGS) && - rule->args_len > (int) arg && - rule->args[arg] != NULL) - { - dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID, - "Argument %d matched more than once in match rule\n", key); - goto failed; - } - - if (!bus_match_rule_set_arg (rule, arg, value, is_path, is_namespace)) - { - BUS_SET_OOM (error); - goto failed; - } - - return TRUE; - - failed: - _DBUS_ASSERT_ERROR_IS_SET (error); - return FALSE; -} - -/* - * The format is comma-separated with strings quoted with single quotes - * as for the shell (to escape a literal single quote, use '\''). - * - * type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus',member='Foo', - * path='/bar/foo',destination=':452345.34' - * - */ -BusMatchRule* -bus_match_rule_parse (DBusConnection *matches_go_to, - const DBusString *rule_text, - DBusError *error) -{ - BusMatchRule *rule; - RuleToken tokens[MAX_RULE_TOKENS+1]; /* NULL termination + 1 */ - int i; - - _DBUS_ASSERT_ERROR_IS_CLEAR (error); - - if (_dbus_string_get_length (rule_text) > DBUS_MAXIMUM_MATCH_RULE_LENGTH) - { - dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED, - "Match rule text is %d bytes, maximum is %d", - _dbus_string_get_length (rule_text), - DBUS_MAXIMUM_MATCH_RULE_LENGTH); - return NULL; - } - - memset (tokens, '\0', sizeof (tokens)); - - rule = bus_match_rule_new (matches_go_to); - if (rule == NULL) - { - BUS_SET_OOM (error); - goto failed; - } - - if (!tokenize_rule (rule_text, tokens, error)) - goto failed; - - i = 0; - while (tokens[i].key != NULL) - { - DBusString tmp_str; - int len; - const char *key = tokens[i].key; - const char *value = tokens[i].value; - - _dbus_string_init_const (&tmp_str, value); - len = _dbus_string_get_length (&tmp_str); - - if (strcmp (key, "type") == 0) - { - int t; - - if (rule->flags & BUS_MATCH_MESSAGE_TYPE) - { - dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID, - "Key %s specified twice in match rule\n", key); - goto failed; - } - - t = dbus_message_type_from_string (value); - - if (t == DBUS_MESSAGE_TYPE_INVALID) - { - dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID, - "Invalid message type (%s) in match rule\n", value); - goto failed; - } - - if (!bus_match_rule_set_message_type (rule, t)) - { - BUS_SET_OOM (error); - goto failed; - } - } - else if (strcmp (key, "sender") == 0) - { - if (rule->flags & BUS_MATCH_SENDER) - { - dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID, - "Key %s specified twice in match rule\n", key); - goto failed; - } - - if (!_dbus_validate_bus_name (&tmp_str, 0, len)) - { - dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID, - "Sender name '%s' is invalid\n", value); - goto failed; - } - - if (!bus_match_rule_set_sender (rule, value)) - { - BUS_SET_OOM (error); - goto failed; - } - } - else if (strcmp (key, "interface") == 0) - { - if (rule->flags & BUS_MATCH_INTERFACE) - { - dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID, - "Key %s specified twice in match rule\n", key); - goto failed; - } - - if (!_dbus_validate_interface (&tmp_str, 0, len)) - { - dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID, - "Interface name '%s' is invalid\n", value); - goto failed; - } - - if (!bus_match_rule_set_interface (rule, value)) - { - BUS_SET_OOM (error); - goto failed; - } - } - else if (strcmp (key, "member") == 0) - { - if (rule->flags & BUS_MATCH_MEMBER) - { - dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID, - "Key %s specified twice in match rule\n", key); - goto failed; - } - - if (!_dbus_validate_member (&tmp_str, 0, len)) - { - dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID, - "Member name '%s' is invalid\n", value); - goto failed; - } - - if (!bus_match_rule_set_member (rule, value)) - { - BUS_SET_OOM (error); - goto failed; - } - } - else if (strcmp (key, "path") == 0 || - strcmp (key, "path_namespace") == 0) - { - dbus_bool_t is_namespace = (strcmp (key, "path_namespace") == 0); - - if (rule->flags & (BUS_MATCH_PATH | BUS_MATCH_PATH_NAMESPACE)) - { - dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID, - "path or path_namespace specified twice in match rule\n"); - goto failed; - } - - if (!_dbus_validate_path (&tmp_str, 0, len)) - { - dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID, - "Path '%s' is invalid\n", value); - goto failed; - } - - if (!bus_match_rule_set_path (rule, value, is_namespace)) - { - BUS_SET_OOM (error); - goto failed; - } - } - else if (strcmp (key, "destination") == 0) - { - if (rule->flags & BUS_MATCH_DESTINATION) - { - dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID, - "Key %s specified twice in match rule\n", key); - goto failed; - } - - if (!_dbus_validate_bus_name (&tmp_str, 0, len)) - { - dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID, - "Destination name '%s' is invalid\n", value); - goto failed; - } - - if (!bus_match_rule_set_destination (rule, value)) - { - BUS_SET_OOM (error); - goto failed; - } - } - else if (strcmp (key, "eavesdrop") == 0) - { - /* do not detect "eavesdrop" being used more than once in rule: - * 1) it's not possible, it's only in the flags - * 2) it might be used twice to disable eavesdropping when it's - * automatically added (eg dbus-monitor/bustle) */ - - /* we accept only "true|false" as possible values */ - if ((strcmp (value, "true") == 0)) - { - bus_match_rule_set_client_is_eavesdropping (rule, TRUE); - } - else if (strcmp (value, "false") == 0) - { - bus_match_rule_set_client_is_eavesdropping (rule, FALSE); - } - else - { - dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID, - "eavesdrop='%s' is invalid, " - "it should be 'true' or 'false'\n", - value); - goto failed; - } - } - else if (strncmp (key, "arg", 3) == 0) - { - if (!bus_match_rule_parse_arg_match (rule, key, &tmp_str, error)) - goto failed; - } - else - { - dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID, - "Unknown key \"%s\" in match rule", - key); - goto failed; - } - - ++i; - } - - - goto out; - - failed: - _DBUS_ASSERT_ERROR_IS_SET (error); - if (rule) - { - bus_match_rule_unref (rule); - rule = NULL; - } - - out: - - i = 0; - while (tokens[i].key || tokens[i].value) - { - _dbus_assert (i < MAX_RULE_TOKENS); - dbus_free (tokens[i].key); - dbus_free (tokens[i].value); - ++i; - } - - return rule; -} - -typedef struct RulePool RulePool; -struct RulePool -{ - /* Maps non-NULL interface names to non-NULL (DBusList **)s */ - DBusHashTable *rules_by_iface; - - /* List of BusMatchRules which don't specify an interface */ - DBusList *rules_without_iface; -}; - -struct BusMatchmaker -{ - int refcount; - - /* Pools of rules, grouped by the type of message they match. 0 - * (DBUS_MESSAGE_TYPE_INVALID) represents rules that do not specify a message - * type. - */ - RulePool rules_by_type[DBUS_NUM_MESSAGE_TYPES]; -}; - -static void -rule_list_free (DBusList **rules) -{ - while (*rules != NULL) - { - BusMatchRule *rule; - - rule = (*rules)->data; - bus_match_rule_unref (rule); - _dbus_list_remove_link (rules, *rules); - } -} - -static void -rule_list_ptr_free (DBusList **list) -{ - /* We have to cope with NULL because the hash table frees the "existing" - * value (which is NULL) when creating a new table entry... - */ - if (list != NULL) - { - rule_list_free (list); - dbus_free (list); - } -} - -BusMatchmaker* -bus_matchmaker_new (void) -{ - BusMatchmaker *matchmaker; - int i; - - matchmaker = dbus_new0 (BusMatchmaker, 1); - if (matchmaker == NULL) - return NULL; - - matchmaker->refcount = 1; - - for (i = DBUS_MESSAGE_TYPE_INVALID; i < DBUS_NUM_MESSAGE_TYPES; i++) - { - RulePool *p = matchmaker->rules_by_type + i; - - p->rules_by_iface = _dbus_hash_table_new (DBUS_HASH_STRING, - dbus_free, (DBusFreeFunction) rule_list_ptr_free); - - if (p->rules_by_iface == NULL) - goto nomem; - } - - return matchmaker; - - nomem: - for (i = DBUS_MESSAGE_TYPE_INVALID; i < DBUS_NUM_MESSAGE_TYPES; i++) - { - RulePool *p = matchmaker->rules_by_type + i; - - if (p->rules_by_iface == NULL) - break; - else - _dbus_hash_table_unref (p->rules_by_iface); - } - dbus_free (matchmaker); - - return NULL; -} - -static DBusList ** -bus_matchmaker_get_rules (BusMatchmaker *matchmaker, - int message_type, - const char *interface, - dbus_bool_t create) -{ - RulePool *p; - - _dbus_assert (message_type >= 0); - _dbus_assert (message_type < DBUS_NUM_MESSAGE_TYPES); - - _dbus_verbose ("Looking up rules for message_type %d, interface %s\n", - message_type, - interface != NULL ? interface : "<null>"); - - p = matchmaker->rules_by_type + message_type; - - if (interface == NULL) - { - return &p->rules_without_iface; - } - else - { - DBusList **list; - - list = _dbus_hash_table_lookup_string (p->rules_by_iface, interface); - - if (list == NULL && create) - { - char *dupped_interface; - - list = dbus_new0 (DBusList *, 1); - if (list == NULL) - return NULL; - - dupped_interface = _dbus_strdup (interface); - if (dupped_interface == NULL) - { - dbus_free (list); - return NULL; - } - - _dbus_verbose ("Adding list for type %d, iface %s\n", message_type, - interface); - - if (!_dbus_hash_table_insert_string (p->rules_by_iface, - dupped_interface, list)) - { - dbus_free (list); - dbus_free (dupped_interface); - return NULL; - } - } - - return list; - } -} - -static void -bus_matchmaker_gc_rules (BusMatchmaker *matchmaker, - int message_type, - const char *interface, - DBusList **rules) -{ - RulePool *p; - - if (interface == NULL) - return; - - if (*rules != NULL) - return; - - _dbus_verbose ("GCing HT entry for message_type %u, interface %s\n", - message_type, interface); - - p = matchmaker->rules_by_type + message_type; - - _dbus_assert (_dbus_hash_table_lookup_string (p->rules_by_iface, interface) - == rules); - - _dbus_hash_table_remove_string (p->rules_by_iface, interface); -} - -BusMatchmaker * -bus_matchmaker_ref (BusMatchmaker *matchmaker) -{ - _dbus_assert (matchmaker->refcount > 0); - - matchmaker->refcount += 1; - - return matchmaker; -} - -void -bus_matchmaker_unref (BusMatchmaker *matchmaker) -{ - _dbus_assert (matchmaker->refcount > 0); - - matchmaker->refcount -= 1; - if (matchmaker->refcount == 0) - { - int i; - - for (i = DBUS_MESSAGE_TYPE_INVALID; i < DBUS_NUM_MESSAGE_TYPES; i++) - { - RulePool *p = matchmaker->rules_by_type + i; - - _dbus_hash_table_unref (p->rules_by_iface); - rule_list_free (&p->rules_without_iface); - } - - dbus_free (matchmaker); - } -} - -/* The rule can't be modified after it's added. */ -dbus_bool_t -bus_matchmaker_add_rule (BusMatchmaker *matchmaker, - BusMatchRule *rule) -{ - DBusList **rules; - - _dbus_assert (bus_connection_is_active (rule->matches_go_to)); - - _dbus_verbose ("Adding rule with message_type %d, interface %s\n", - rule->message_type, - rule->interface != NULL ? rule->interface : "<null>"); - - rules = bus_matchmaker_get_rules (matchmaker, rule->message_type, - rule->interface, TRUE); - - if (rules == NULL) - return FALSE; - - if (!_dbus_list_append (rules, rule)) - return FALSE; - - if (!bus_connection_add_match_rule (rule->matches_go_to, rule)) - { - _dbus_list_remove_last (rules, rule); - bus_matchmaker_gc_rules (matchmaker, rule->message_type, - rule->interface, rules); - return FALSE; - } - - bus_match_rule_ref (rule); - -#ifdef DBUS_ENABLE_VERBOSE_MODE - { - char *s = match_rule_to_string (rule); - - _dbus_verbose ("Added match rule %s to connection %p\n", - s, rule->matches_go_to); - dbus_free (s); - } -#endif - - return TRUE; -} - -static dbus_bool_t -match_rule_equal (BusMatchRule *a, - BusMatchRule *b) -{ - if (a->flags != b->flags) - return FALSE; - - if (a->matches_go_to != b->matches_go_to) - return FALSE; - - if ((a->flags & BUS_MATCH_MESSAGE_TYPE) && - a->message_type != b->message_type) - return FALSE; - - if ((a->flags & BUS_MATCH_MEMBER) && - strcmp (a->member, b->member) != 0) - return FALSE; - - if ((a->flags & BUS_MATCH_PATH) && - strcmp (a->path, b->path) != 0) - return FALSE; - - if ((a->flags & BUS_MATCH_INTERFACE) && - strcmp (a->interface, b->interface) != 0) - return FALSE; - - if ((a->flags & BUS_MATCH_SENDER) && - strcmp (a->sender, b->sender) != 0) - return FALSE; - - if ((a->flags & BUS_MATCH_DESTINATION) && - strcmp (a->destination, b->destination) != 0) - return FALSE; - - /* we already compared the value of flags, and - * BUS_MATCH_CLIENT_IS_EAVESDROPPING does not have another struct member */ - - if (a->flags & BUS_MATCH_ARGS) - { - int i; - - if (a->args_len != b->args_len) - return FALSE; - - i = 0; - while (i < a->args_len) - { - int length; - - if ((a->args[i] != NULL) != (b->args[i] != NULL)) - return FALSE; - - if (a->arg_lens[i] != b->arg_lens[i]) - return FALSE; - - length = a->arg_lens[i] & ~BUS_MATCH_ARG_FLAGS; - - if (a->args[i] != NULL) - { - _dbus_assert (b->args[i] != NULL); - if (memcmp (a->args[i], b->args[i], length) != 0) - return FALSE; - } - - ++i; - } - } - - return TRUE; -} - -static void -bus_matchmaker_remove_rule_link (DBusList **rules, - DBusList *link) -{ - BusMatchRule *rule = link->data; - - bus_connection_remove_match_rule (rule->matches_go_to, rule); - _dbus_list_remove_link (rules, link); - -#ifdef DBUS_ENABLE_VERBOSE_MODE - { - char *s = match_rule_to_string (rule); - - _dbus_verbose ("Removed match rule %s for connection %p\n", - s, rule->matches_go_to); - dbus_free (s); - } -#endif - - bus_match_rule_unref (rule); -} - -void -bus_matchmaker_remove_rule (BusMatchmaker *matchmaker, - BusMatchRule *rule) -{ - DBusList **rules; - - _dbus_verbose ("Removing rule with message_type %d, interface %s\n", - rule->message_type, - rule->interface != NULL ? rule->interface : "<null>"); - - bus_connection_remove_match_rule (rule->matches_go_to, rule); - - rules = bus_matchmaker_get_rules (matchmaker, rule->message_type, - rule->interface, FALSE); - - /* We should only be asked to remove a rule by identity right after it was - * added, so there should be a list for it. - */ - _dbus_assert (rules != NULL); - - _dbus_list_remove (rules, rule); - bus_matchmaker_gc_rules (matchmaker, rule->message_type, rule->interface, - rules); - -#ifdef DBUS_ENABLE_VERBOSE_MODE - { - char *s = match_rule_to_string (rule); - - _dbus_verbose ("Removed match rule %s for connection %p\n", - s, rule->matches_go_to); - dbus_free (s); - } -#endif - - bus_match_rule_unref (rule); -} - -/* Remove a single rule which is equal to the given rule by value */ -dbus_bool_t -bus_matchmaker_remove_rule_by_value (BusMatchmaker *matchmaker, - BusMatchRule *value, - DBusError *error) -{ - DBusList **rules; - DBusList *link = NULL; - - _dbus_verbose ("Removing rule by value with message_type %d, interface %s\n", - value->message_type, - value->interface != NULL ? value->interface : "<null>"); - - rules = bus_matchmaker_get_rules (matchmaker, value->message_type, - value->interface, FALSE); - - if (rules != NULL) - { - /* we traverse backward because bus_connection_remove_match_rule() - * removes the most-recently-added rule - */ - link = _dbus_list_get_last_link (rules); - while (link != NULL) - { - BusMatchRule *rule; - DBusList *prev; - - rule = link->data; - prev = _dbus_list_get_prev_link (rules, link); - - if (match_rule_equal (rule, value)) - { - bus_matchmaker_remove_rule_link (rules, link); - break; - } - - link = prev; - } - } - - if (link == NULL) - { - dbus_set_error (error, DBUS_ERROR_MATCH_RULE_NOT_FOUND, - "The given match rule wasn't found and can't be removed"); - return FALSE; - } - - bus_matchmaker_gc_rules (matchmaker, value->message_type, value->interface, - rules); - - return TRUE; -} - -static void -rule_list_remove_by_connection (DBusList **rules, - DBusConnection *connection) -{ - DBusList *link; - - link = _dbus_list_get_first_link (rules); - while (link != NULL) - { - BusMatchRule *rule; - DBusList *next; - - rule = link->data; - next = _dbus_list_get_next_link (rules, link); - - if (rule->matches_go_to == connection) - { - bus_matchmaker_remove_rule_link (rules, link); - } - else if (((rule->flags & BUS_MATCH_SENDER) && *rule->sender == ':') || - ((rule->flags & BUS_MATCH_DESTINATION) && *rule->destination == ':')) - { - /* The rule matches to/from a base service, see if it's the - * one being disconnected, since we know this service name - * will never be recycled. - */ - const char *name; - - name = bus_connection_get_name (connection); - _dbus_assert (name != NULL); /* because we're an active connection */ - - if (((rule->flags & BUS_MATCH_SENDER) && - strcmp (rule->sender, name) == 0) || - ((rule->flags & BUS_MATCH_DESTINATION) && - strcmp (rule->destination, name) == 0)) - { - bus_matchmaker_remove_rule_link (rules, link); - } - } - - link = next; - } -} - -void -bus_matchmaker_disconnected (BusMatchmaker *matchmaker, - DBusConnection *connection) -{ - int i; - - /* FIXME - * - * This scans all match rules on the bus. We could avoid that - * for the rules belonging to the connection, since we keep - * a list of those; but for the rules that just refer to - * the connection we'd need to do something more elaborate. - */ - - _dbus_assert (bus_connection_is_active (connection)); - - _dbus_verbose ("Removing all rules for connection %p\n", connection); - - for (i = DBUS_MESSAGE_TYPE_INVALID; i < DBUS_NUM_MESSAGE_TYPES; i++) - { - RulePool *p = matchmaker->rules_by_type + i; - DBusHashIter iter; - - rule_list_remove_by_connection (&p->rules_without_iface, connection); - - _dbus_hash_iter_init (p->rules_by_iface, &iter); - while (_dbus_hash_iter_next (&iter)) - { - DBusList **items = _dbus_hash_iter_get_value (&iter); - - rule_list_remove_by_connection (items, connection); - - if (*items == NULL) - _dbus_hash_iter_remove_entry (&iter); - } - } -} - -static dbus_bool_t -connection_is_primary_owner (DBusConnection *connection, - const char *service_name) -{ - BusService *service; - DBusString str; - BusRegistry *registry; - - _dbus_assert (connection != NULL); - - registry = bus_connection_get_registry (connection); - - _dbus_string_init_const (&str, service_name); - service = bus_registry_lookup (registry, &str); - - if (service == NULL) - return FALSE; /* Service doesn't exist so connection can't own it. */ - - return bus_service_get_primary_owners_connection (service) == connection; -} - -static dbus_bool_t -str_has_prefix (const char *str, const char *prefix) -{ - size_t prefix_len; - prefix_len = strlen (prefix); - if (strncmp (str, prefix, prefix_len) == 0) - return TRUE; - else - return FALSE; -} - -static dbus_bool_t -match_rule_matches (BusMatchRule *rule, - DBusConnection *sender, - DBusConnection *addressed_recipient, - DBusMessage *message, - BusMatchFlags already_matched) -{ - dbus_bool_t wants_to_eavesdrop = FALSE; - int flags; - - /* All features of the match rule are AND'd together, - * so FALSE if any of them don't match. - */ - - /* sender/addressed_recipient of #NULL may mean bus driver, - * or for addressed_recipient may mean a message with no - * specific recipient (i.e. a signal) - */ - - /* Don't bother re-matching features we've already checked implicitly. */ - flags = rule->flags & (~already_matched); - - if (flags & BUS_MATCH_CLIENT_IS_EAVESDROPPING) - wants_to_eavesdrop = TRUE; - - if (flags & BUS_MATCH_MESSAGE_TYPE) - { - _dbus_assert (rule->message_type != DBUS_MESSAGE_TYPE_INVALID); - - if (rule->message_type != dbus_message_get_type (message)) - return FALSE; - } - - if (flags & BUS_MATCH_INTERFACE) - { - const char *iface; - - _dbus_assert (rule->interface != NULL); - - iface = dbus_message_get_interface (message); - if (iface == NULL) - return FALSE; - - if (strcmp (iface, rule->interface) != 0) - return FALSE; - } - - if (flags & BUS_MATCH_MEMBER) - { - const char *member; - - _dbus_assert (rule->member != NULL); - - member = dbus_message_get_member (message); - if (member == NULL) - return FALSE; - - if (strcmp (member, rule->member) != 0) - return FALSE; - } - - if (flags & BUS_MATCH_SENDER) - { - _dbus_assert (rule->sender != NULL); - - if (sender == NULL) - { - if (strcmp (rule->sender, - DBUS_SERVICE_DBUS) != 0) - return FALSE; - } - else - { - if (!connection_is_primary_owner (sender, rule->sender)) - return FALSE; - } - } - - /* Note: this part is relevant for eavesdropper rules: - * Two cases: - * 1) rule has a destination to be matched - * (flag BUS_MATCH_DESTINATION present). Rule will match if: - * - rule->destination matches the addressed_recipient - * AND - * - wants_to_eavesdrop=TRUE - * - * Note: (the case in which addressed_recipient is the actual rule owner - * is handled elsewere in dispatch.c:bus_dispatch_matches(). - * - * 2) rule has no destination. Rule will match if: - * - message has no specified destination (ie broadcasts) - * (Note: this will rule out unicast method calls and unicast signals, - * fixing FDO#269748) - * OR - * - wants_to_eavesdrop=TRUE (destination-catch-all situation) - */ - if (flags & BUS_MATCH_DESTINATION) - { - const char *destination; - - _dbus_assert (rule->destination != NULL); - - destination = dbus_message_get_destination (message); - if (destination == NULL) - /* broadcast, but this rule specified a destination: no match */ - return FALSE; - - /* rule owner does not intend to eavesdrop: we'll deliver only msgs - * directed to it, NOT MATCHING */ - if (!wants_to_eavesdrop) - return FALSE; - - if (addressed_recipient == NULL) - { - if (strcmp (rule->destination, - DBUS_SERVICE_DBUS) != 0) - return FALSE; - } - else - { - if (!connection_is_primary_owner (addressed_recipient, rule->destination)) - return FALSE; - } - } else { /* no destination in rule */ - dbus_bool_t msg_is_broadcast; - - _dbus_assert (rule->destination == NULL); - - msg_is_broadcast = (dbus_message_get_destination (message) == NULL); - - if (!wants_to_eavesdrop && !msg_is_broadcast) - return FALSE; - - /* if we are here rule owner intends to eavesdrop - * OR - * message is being broadcasted */ - } - - if (flags & BUS_MATCH_PATH) - { - const char *path; - - _dbus_assert (rule->path != NULL); - - path = dbus_message_get_path (message); - if (path == NULL) - return FALSE; - - if (strcmp (path, rule->path) != 0) - return FALSE; - } - - if (flags & BUS_MATCH_PATH_NAMESPACE) - { - const char *path; - int len; - - _dbus_assert (rule->path != NULL); - - path = dbus_message_get_path (message); - if (path == NULL) - return FALSE; - - if (!str_has_prefix (path, rule->path)) - return FALSE; - - len = strlen (rule->path); - - /* Check that the actual argument is within the expected - * namespace, rather than just starting with that string, - * by checking that the matched prefix is followed by a '/' - * or the end of the path. - * - * Special case: the only valid path of length 1, "/", - * matches everything. - */ - if (len > 1 && path[len] != '\0' && path[len] != '/') - return FALSE; - } - - if (flags & BUS_MATCH_ARGS) - { - int i; - DBusMessageIter iter; - - _dbus_assert (rule->args != NULL); - - dbus_message_iter_init (message, &iter); - - i = 0; - while (i < rule->args_len) - { - int current_type; - const char *expected_arg; - int expected_length; - dbus_bool_t is_path, is_namespace; - - expected_arg = rule->args[i]; - expected_length = rule->arg_lens[i] & ~BUS_MATCH_ARG_FLAGS; - is_path = (rule->arg_lens[i] & BUS_MATCH_ARG_IS_PATH) != 0; - is_namespace = (rule->arg_lens[i] & BUS_MATCH_ARG_NAMESPACE) != 0; - - current_type = dbus_message_iter_get_arg_type (&iter); - - if (expected_arg != NULL) - { - const char *actual_arg; - int actual_length; - - if (current_type != DBUS_TYPE_STRING && - (!is_path || current_type != DBUS_TYPE_OBJECT_PATH)) - return FALSE; - - actual_arg = NULL; - dbus_message_iter_get_basic (&iter, &actual_arg); - _dbus_assert (actual_arg != NULL); - - actual_length = strlen (actual_arg); - - if (is_path) - { - if (actual_length < expected_length && - actual_arg[actual_length - 1] != '/') - return FALSE; - - if (expected_length < actual_length && - expected_arg[expected_length - 1] != '/') - return FALSE; - - if (memcmp (actual_arg, expected_arg, - MIN (actual_length, expected_length)) != 0) - return FALSE; - } - else if (is_namespace) - { - if (expected_length > actual_length) - return FALSE; - - /* If the actual argument doesn't start with the expected - * namespace, then we don't match. - */ - if (memcmp (expected_arg, actual_arg, expected_length) != 0) - return FALSE; - - if (expected_length < actual_length) - { - /* Check that the actual argument is within the expected - * namespace, rather than just starting with that string, - * by checking that the matched prefix ends in a '.'. - * - * This doesn't stop "foo.bar." matching "foo.bar..baz" - * which is an invalid namespace, but at some point the - * daemon can't cover up for broken services. - */ - if (actual_arg[expected_length] != '.') - return FALSE; - } - /* otherwise we had an exact match. */ - } - else - { - if (expected_length != actual_length || - memcmp (expected_arg, actual_arg, expected_length) != 0) - return FALSE; - } - - } - - if (current_type != DBUS_TYPE_INVALID) - dbus_message_iter_next (&iter); - - ++i; - } - } - - return TRUE; -} - -static dbus_bool_t -get_recipients_from_list (DBusList **rules, - DBusConnection *sender, - DBusConnection *addressed_recipient, - DBusMessage *message, - DBusList **recipients_p) -{ - DBusList *link; - - if (rules == NULL) - return TRUE; - - link = _dbus_list_get_first_link (rules); - while (link != NULL) - { - BusMatchRule *rule; - - rule = link->data; - -#ifdef DBUS_ENABLE_VERBOSE_MODE - { - char *s = match_rule_to_string (rule); - - _dbus_verbose ("Checking whether message matches rule %s for connection %p\n", - s, rule->matches_go_to); - dbus_free (s); - } -#endif - - if (match_rule_matches (rule, - sender, addressed_recipient, message, - BUS_MATCH_MESSAGE_TYPE | BUS_MATCH_INTERFACE)) - { - _dbus_verbose ("Rule matched\n"); - - /* Append to the list if we haven't already */ - if (bus_connection_mark_stamp (rule->matches_go_to)) - { - if (!_dbus_list_append (recipients_p, rule->matches_go_to)) - return FALSE; - } - else - { - _dbus_verbose ("Connection already receiving this message, so not adding again\n"); - } - } - - link = _dbus_list_get_next_link (rules, link); - } - - return TRUE; -} - -dbus_bool_t -bus_matchmaker_get_recipients (BusMatchmaker *matchmaker, - BusConnections *connections, - DBusConnection *sender, - DBusConnection *addressed_recipient, - DBusMessage *message, - DBusList **recipients_p) -{ - int type; - const char *interface; - DBusList **neither, **just_type, **just_iface, **both; - - _dbus_assert (*recipients_p == NULL); - - /* This avoids sending same message to the same connection twice. - * Purpose of the stamp instead of a bool is to avoid iterating over - * all connections resetting the bool each time. - */ - bus_connections_increment_stamp (connections); - - /* addressed_recipient is already receiving the message, don't add to list. - * NULL addressed_recipient means either bus driver, or this is a signal - * and thus lacks a specific addressed_recipient. - */ - if (addressed_recipient != NULL) - bus_connection_mark_stamp (addressed_recipient); - - type = dbus_message_get_type (message); - interface = dbus_message_get_interface (message); - - neither = bus_matchmaker_get_rules (matchmaker, DBUS_MESSAGE_TYPE_INVALID, - NULL, FALSE); - just_type = just_iface = both = NULL; - - if (interface != NULL) - just_iface = bus_matchmaker_get_rules (matchmaker, - DBUS_MESSAGE_TYPE_INVALID, interface, FALSE); - - if (type > DBUS_MESSAGE_TYPE_INVALID && type < DBUS_NUM_MESSAGE_TYPES) - { - just_type = bus_matchmaker_get_rules (matchmaker, type, NULL, FALSE); - - if (interface != NULL) - both = bus_matchmaker_get_rules (matchmaker, type, interface, FALSE); - } - - if (!(get_recipients_from_list (neither, sender, addressed_recipient, - message, recipients_p) && - get_recipients_from_list (just_iface, sender, addressed_recipient, - message, recipients_p) && - get_recipients_from_list (just_type, sender, addressed_recipient, - message, recipients_p) && - get_recipients_from_list (both, sender, addressed_recipient, - message, recipients_p))) - { - _dbus_list_clear (recipients_p); - return FALSE; - } - - return TRUE; -} - -#ifdef DBUS_ENABLE_EMBEDDED_TESTS -#include "test.h" -#include <stdlib.h> - -static BusMatchRule* -check_parse (dbus_bool_t should_succeed, - const char *text) -{ - BusMatchRule *rule; - DBusString str; - DBusError error; - - dbus_error_init (&error); - - _dbus_string_init_const (&str, text); - - rule = bus_match_rule_parse (NULL, &str, &error); - if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY)) - { - dbus_error_free (&error); - return NULL; - } - - if (should_succeed && rule == NULL) - { - _dbus_warn ("Failed to parse: %s: %s: \"%s\"\n", - error.name, error.message, - _dbus_string_get_const_data (&str)); - exit (1); - } - - if (!should_succeed && rule != NULL) - { - _dbus_warn ("Failed to fail to parse: \"%s\"\n", - _dbus_string_get_const_data (&str)); - exit (1); - } - - dbus_error_free (&error); - - return rule; -} - -static void -assert_large_rule (BusMatchRule *rule) -{ - _dbus_assert (rule->flags & BUS_MATCH_MESSAGE_TYPE); - _dbus_assert (rule->flags & BUS_MATCH_SENDER); - _dbus_assert (rule->flags & BUS_MATCH_INTERFACE); - _dbus_assert (rule->flags & BUS_MATCH_MEMBER); - _dbus_assert (rule->flags & BUS_MATCH_DESTINATION); - _dbus_assert (rule->flags & BUS_MATCH_PATH); - - _dbus_assert (rule->message_type == DBUS_MESSAGE_TYPE_SIGNAL); - _dbus_assert (rule->interface != NULL); - _dbus_assert (rule->member != NULL); - _dbus_assert (rule->sender != NULL); - _dbus_assert (rule->destination != NULL); - _dbus_assert (rule->path != NULL); - - _dbus_assert (strcmp (rule->interface, "org.freedesktop.DBusInterface") == 0); - _dbus_assert (strcmp (rule->sender, "org.freedesktop.DBusSender") == 0); - _dbus_assert (strcmp (rule->member, "Foo") == 0); - _dbus_assert (strcmp (rule->path, "/bar/foo") == 0); - _dbus_assert (strcmp (rule->destination, ":452345.34") == 0); -} - -static dbus_bool_t -test_parsing (void *data) -{ - BusMatchRule *rule; - - rule = check_parse (TRUE, "type='signal',sender='org.freedesktop.DBusSender',interface='org.freedesktop.DBusInterface',member='Foo',path='/bar/foo',destination=':452345.34'"); - if (rule != NULL) - { - assert_large_rule (rule); - bus_match_rule_unref (rule); - } - - /* With extra whitespace and useless quotes */ - rule = check_parse (TRUE, " type='signal', \tsender='org.freedes''ktop.DBusSender', interface='org.freedesktop.DBusInterface''''', \tmember='Foo',path='/bar/foo',destination=':452345.34'''''"); - if (rule != NULL) - { - assert_large_rule (rule); - bus_match_rule_unref (rule); - } - - - /* A simple signal connection */ - rule = check_parse (TRUE, "type='signal',path='/foo',interface='org.Bar'"); - if (rule != NULL) - { - _dbus_assert (rule->flags & BUS_MATCH_MESSAGE_TYPE); - _dbus_assert (rule->flags & BUS_MATCH_INTERFACE); - _dbus_assert (rule->flags & BUS_MATCH_PATH); - - _dbus_assert (rule->message_type == DBUS_MESSAGE_TYPE_SIGNAL); - _dbus_assert (rule->interface != NULL); - _dbus_assert (rule->path != NULL); - - _dbus_assert (strcmp (rule->interface, "org.Bar") == 0); - _dbus_assert (strcmp (rule->path, "/foo") == 0); - - bus_match_rule_unref (rule); - } - - /* argN */ - rule = check_parse (TRUE, "arg0='foo'"); - if (rule != NULL) - { - _dbus_assert (rule->flags == BUS_MATCH_ARGS); - _dbus_assert (rule->args != NULL); - _dbus_assert (rule->args_len == 1); - _dbus_assert (rule->args[0] != NULL); - _dbus_assert (rule->args[1] == NULL); - _dbus_assert (strcmp (rule->args[0], "foo") == 0); - - bus_match_rule_unref (rule); - } - - rule = check_parse (TRUE, "arg1='foo'"); - if (rule != NULL) - { - _dbus_assert (rule->flags == BUS_MATCH_ARGS); - _dbus_assert (rule->args != NULL); - _dbus_assert (rule->args_len == 2); - _dbus_assert (rule->args[0] == NULL); - _dbus_assert (rule->args[1] != NULL); - _dbus_assert (rule->args[2] == NULL); - _dbus_assert (strcmp (rule->args[1], "foo") == 0); - - bus_match_rule_unref (rule); - } - - rule = check_parse (TRUE, "arg2='foo'"); - if (rule != NULL) - { - _dbus_assert (rule->flags == BUS_MATCH_ARGS); - _dbus_assert (rule->args != NULL); - _dbus_assert (rule->args_len == 3); - _dbus_assert (rule->args[0] == NULL); - _dbus_assert (rule->args[1] == NULL); - _dbus_assert (rule->args[2] != NULL); - _dbus_assert (rule->args[3] == NULL); - _dbus_assert (strcmp (rule->args[2], "foo") == 0); - - bus_match_rule_unref (rule); - } - - rule = check_parse (TRUE, "arg40='foo'"); - if (rule != NULL) - { - _dbus_assert (rule->flags == BUS_MATCH_ARGS); - _dbus_assert (rule->args != NULL); - _dbus_assert (rule->args_len == 41); - _dbus_assert (rule->args[0] == NULL); - _dbus_assert (rule->args[1] == NULL); - _dbus_assert (rule->args[40] != NULL); - _dbus_assert (rule->args[41] == NULL); - _dbus_assert (strcmp (rule->args[40], "foo") == 0); - - bus_match_rule_unref (rule); - } - - rule = check_parse (TRUE, "arg63='foo'"); - if (rule != NULL) - { - _dbus_assert (rule->flags == BUS_MATCH_ARGS); - _dbus_assert (rule->args != NULL); - _dbus_assert (rule->args_len == 64); - _dbus_assert (rule->args[0] == NULL); - _dbus_assert (rule->args[1] == NULL); - _dbus_assert (rule->args[63] != NULL); - _dbus_assert (rule->args[64] == NULL); - _dbus_assert (strcmp (rule->args[63], "foo") == 0); - - bus_match_rule_unref (rule); - } - - rule = check_parse (TRUE, "arg7path='/foo'"); - if (rule != NULL) - { - _dbus_assert (rule->flags = BUS_MATCH_ARGS); - _dbus_assert (rule->args != NULL); - _dbus_assert (rule->args_len == 8); - _dbus_assert (rule->args[7] != NULL); - _dbus_assert (rule->args[8] == NULL); - _dbus_assert (strcmp (rule->args[7], "/foo") == 0); - _dbus_assert ((rule->arg_lens[7] & BUS_MATCH_ARG_IS_PATH) - == BUS_MATCH_ARG_IS_PATH); - - bus_match_rule_unref (rule); - } - - /* Arg 0 namespace matches */ - rule = check_parse (TRUE, "arg0namespace='foo'"); - if (rule != NULL) - { - _dbus_assert (rule->flags == BUS_MATCH_ARGS); - _dbus_assert (rule->args != NULL); - _dbus_assert (rule->args_len == 1); - _dbus_assert (strcmp (rule->args[0], "foo") == 0); - _dbus_assert ((rule->arg_lens[0] & BUS_MATCH_ARG_NAMESPACE) - == BUS_MATCH_ARG_NAMESPACE); - - bus_match_rule_unref (rule); - } - - rule = check_parse (TRUE, "arg0namespace='foo.bar'"); - if (rule != NULL) - { - _dbus_assert (rule->flags == BUS_MATCH_ARGS); - _dbus_assert (rule->args != NULL); - _dbus_assert (rule->args_len == 1); - _dbus_assert (strcmp (rule->args[0], "foo.bar") == 0); - _dbus_assert ((rule->arg_lens[0] & BUS_MATCH_ARG_NAMESPACE) - == BUS_MATCH_ARG_NAMESPACE); - - bus_match_rule_unref (rule); - } - - /* Only arg0namespace is supported. */ - rule = check_parse (FALSE, "arg1namespace='foo'"); - _dbus_assert (rule == NULL); - - /* An empty string isn't a valid namespace prefix (you should just not - * specify this key at all). - */ - rule = check_parse (FALSE, "arg0namespace=''"); - _dbus_assert (rule == NULL); - - /* Trailing periods aren't allowed (earlier versions of the arg0namespace - * spec allowed a single trailing period, which altered the semantics) */ - rule = check_parse (FALSE, "arg0namespace='foo.'"); - _dbus_assert (rule == NULL); - - rule = check_parse (FALSE, "arg0namespace='foo.bar.'"); - _dbus_assert (rule == NULL); - - rule = check_parse (FALSE, "arg0namespace='foo..'"); - _dbus_assert (rule == NULL); - - rule = check_parse (FALSE, "arg0namespace='foo.bar..'"); - _dbus_assert (rule == NULL); - - /* Too-large argN */ - rule = check_parse (FALSE, "arg300='foo'"); - _dbus_assert (rule == NULL); - rule = check_parse (FALSE, "arg64='foo'"); - _dbus_assert (rule == NULL); - - /* No N in argN */ - rule = check_parse (FALSE, "arg='foo'"); - _dbus_assert (rule == NULL); - rule = check_parse (FALSE, "argv='foo'"); - _dbus_assert (rule == NULL); - rule = check_parse (FALSE, "arg3junk='foo'"); - _dbus_assert (rule == NULL); - rule = check_parse (FALSE, "argument='foo'"); - _dbus_assert (rule == NULL); - - /* Reject duplicates */ - rule = check_parse (FALSE, "type='signal',type='method_call'"); - _dbus_assert (rule == NULL); - - rule = check_parse (TRUE, "path_namespace='/foo/bar'"); - if (rule != NULL) - { - _dbus_assert (rule->flags == BUS_MATCH_PATH_NAMESPACE); - _dbus_assert (rule->path != NULL); - _dbus_assert (strcmp (rule->path, "/foo/bar") == 0); - - bus_match_rule_unref (rule); - } - - /* Almost a duplicate */ - rule = check_parse (FALSE, "path='/foo',path_namespace='/foo'"); - _dbus_assert (rule == NULL); - - /* Trailing / was supported in the initial proposal, but now isn't */ - rule = check_parse (FALSE, "path_namespace='/foo/'"); - _dbus_assert (rule == NULL); - - /* Duplicates with the argN code */ - rule = check_parse (FALSE, "arg0='foo',arg0='bar'"); - _dbus_assert (rule == NULL); - rule = check_parse (FALSE, "arg3='foo',arg3='bar'"); - _dbus_assert (rule == NULL); - rule = check_parse (FALSE, "arg30='foo',arg30='bar'"); - _dbus_assert (rule == NULL); - - /* Reject broken keys */ - rule = check_parse (FALSE, "blah='signal'"); - _dbus_assert (rule == NULL); - - /* Reject broken values */ - rule = check_parse (FALSE, "type='chouin'"); - _dbus_assert (rule == NULL); - rule = check_parse (FALSE, "interface='abc@def++'"); - _dbus_assert (rule == NULL); - rule = check_parse (FALSE, "service='youpi'"); - _dbus_assert (rule == NULL); - - /* Allow empty rule */ - rule = check_parse (TRUE, ""); - if (rule != NULL) - { - _dbus_assert (rule->flags == 0); - - bus_match_rule_unref (rule); - } - - /* All-whitespace rule is the same as empty */ - rule = check_parse (TRUE, " \t"); - if (rule != NULL) - { - _dbus_assert (rule->flags == 0); - - bus_match_rule_unref (rule); - } - - /* But with non-whitespace chars and no =value, it's not OK */ - rule = check_parse (FALSE, "type"); - _dbus_assert (rule == NULL); - - return TRUE; -} - -static struct { - const char *first; - const char *second; -} equality_tests[] = { - { "type='signal'", "type='signal'" }, - { "type='signal',interface='foo.bar'", "interface='foo.bar',type='signal'" }, - { "type='signal',member='bar'", "member='bar',type='signal'" }, - { "type='method_call',sender=':1.0'", "sender=':1.0',type='method_call'" }, - { "type='method_call',destination=':1.0'", "destination=':1.0',type='method_call'" }, - { "type='method_call',path='/foo/bar'", "path='/foo/bar',type='method_call'" }, - { "type='method_call',arg0='blah'", "arg0='blah',type='method_call'" }, - { "type='method_call',arg0='boo'", "arg0='boo',type='method_call'" }, - { "type='method_call',arg0='blah',arg1='baz'", "arg0='blah',arg1='baz',type='method_call'" }, - { "type='method_call',arg3='foosh'", "arg3='foosh',type='method_call'" }, - { "arg3='fool'", "arg3='fool'" }, - { "arg0namespace='fool'", "arg0namespace='fool'" }, - { "member='food'", "member='food'" } -}; - -static void -test_equality (void) -{ - int i; - - i = 0; - while (i < _DBUS_N_ELEMENTS (equality_tests)) - { - BusMatchRule *first; - BusMatchRule *second; - int j; - - first = check_parse (TRUE, equality_tests[i].first); - _dbus_assert (first != NULL); - second = check_parse (TRUE, equality_tests[i].second); - _dbus_assert (second != NULL); - - if (!match_rule_equal (first, second)) - { - _dbus_warn ("rule %s and %s should have been equal\n", - equality_tests[i].first, - equality_tests[i].second); - exit (1); - } - - bus_match_rule_unref (second); - - /* Check that the rule is not equal to any of the - * others besides its pair match - */ - j = 0; - while (j < _DBUS_N_ELEMENTS (equality_tests)) - { - if (i != j) - { - second = check_parse (TRUE, equality_tests[j].second); - - if (match_rule_equal (first, second)) - { - _dbus_warn ("rule %s and %s should not have been equal\n", - equality_tests[i].first, - equality_tests[j].second); - exit (1); - } - - bus_match_rule_unref (second); - } - - ++j; - } - - bus_match_rule_unref (first); - - ++i; - } -} - -static const char* -should_match_message_1[] = { - "type='signal'", - "member='Frobated'", - "arg0='foobar'", - "type='signal',member='Frobated'", - "type='signal',member='Frobated',arg0='foobar'", - "member='Frobated',arg0='foobar'", - "type='signal',arg0='foobar'", - /* The definition of argXpath matches says: "As with normal argument matches, - * if the argument is exactly equal to the string given in the match rule - * then the rule is satisfied." So this should match (even though the - * argument is not a valid path)! - */ - "arg0path='foobar'", - "arg0namespace='foobar'", - NULL -}; - -static const char* -should_not_match_message_1[] = { - "type='method_call'", - "type='error'", - "type='method_return'", - "type='signal',member='Oopsed'", - "arg0='blah'", - "arg1='foobar'", - "arg2='foobar'", - "arg3='foobar'", - "arg0='3'", - "arg1='3'", - "arg0='foobar',arg1='abcdef'", - "arg0='foobar',arg1='abcdef',arg2='abcdefghi',arg3='abcdefghi',arg4='abcdefghi'", - "arg0='foobar',arg1='abcdef',arg4='abcdefghi',arg3='abcdefghi',arg2='abcdefghi'", - "arg0path='foo'", - "arg0path='foobar/'", - "arg1path='3'", - "arg0namespace='foo'", - "arg0namespace='foo',arg1='abcdef'", - "arg0namespace='moo'", - NULL -}; - -#define EXAMPLE_NAME "com.example.backend.foo" - -static const char * -should_match_message_2[] = { - /* EXAMPLE_NAME is in all of these namespaces */ - "arg0namespace='com.example.backend'", - "arg0namespace='com.example'", - "arg0namespace='com'", - - /* If the client specifies the name exactly, with no trailing period, then - * it should match. - */ - "arg0namespace='com.example.backend.foo'", - - NULL -}; - -static const char * -should_not_match_message_2[] = { - /* These are not even prefixes */ - "arg0namespace='com.example.backend.foo.bar'", - "arg0namespace='com.example.backend.foobar'", - - /* These are prefixes, but they're not parent namespaces. */ - "arg0namespace='com.example.backend.fo'", - "arg0namespace='com.example.backen'", - "arg0namespace='com.exampl'", - "arg0namespace='co'", - - NULL -}; - -static void -check_matches (dbus_bool_t expected_to_match, - int number, - DBusMessage *message, - const char *rule_text) -{ - BusMatchRule *rule; - dbus_bool_t matched; - - rule = check_parse (TRUE, rule_text); - _dbus_assert (rule != NULL); - - /* We can't test sender/destination rules since we pass NULL here */ - matched = match_rule_matches (rule, NULL, NULL, message, 0); - - if (matched != expected_to_match) - { - _dbus_warn ("Expected rule %s to %s message %d, failed\n", - rule_text, expected_to_match ? - "match" : "not match", number); - exit (1); - } - - bus_match_rule_unref (rule); -} - -static void -check_matching (DBusMessage *message, - int number, - const char **should_match, - const char **should_not_match) -{ - int i; - - i = 0; - while (should_match[i] != NULL) - { - check_matches (TRUE, number, message, should_match[i]); - ++i; - } - - i = 0; - while (should_not_match[i] != NULL) - { - check_matches (FALSE, number, message, should_not_match[i]); - ++i; - } -} - -static void -test_matching (void) -{ - DBusMessage *message1, *message2; - const char *v_STRING; - dbus_int32_t v_INT32; - - message1 = dbus_message_new (DBUS_MESSAGE_TYPE_SIGNAL); - _dbus_assert (message1 != NULL); - if (!dbus_message_set_member (message1, "Frobated")) - _dbus_assert_not_reached ("oom"); - - v_STRING = "foobar"; - v_INT32 = 3; - if (!dbus_message_append_args (message1, - DBUS_TYPE_STRING, &v_STRING, - DBUS_TYPE_INT32, &v_INT32, - NULL)) - _dbus_assert_not_reached ("oom"); - - check_matching (message1, 1, - should_match_message_1, - should_not_match_message_1); - - dbus_message_unref (message1); - - message2 = dbus_message_new (DBUS_MESSAGE_TYPE_SIGNAL); - _dbus_assert (message2 != NULL); - if (!dbus_message_set_member (message2, "NameOwnerChanged")) - _dbus_assert_not_reached ("oom"); - - /* Obviously this isn't really a NameOwnerChanged signal. */ - v_STRING = EXAMPLE_NAME; - if (!dbus_message_append_args (message2, - DBUS_TYPE_STRING, &v_STRING, - NULL)) - _dbus_assert_not_reached ("oom"); - - check_matching (message2, 2, - should_match_message_2, - should_not_match_message_2); - - dbus_message_unref (message2); -} - -#define PATH_MATCH_RULE "arg0path='/aa/bb/'" - -/* This is a list of paths that should be matched by PATH_MATCH_RULE, taken - * from the specification. Notice that not all of them are actually legal D-Bus - * paths. - * - * The author of this test takes no responsibility for the semantics of - * this match rule key. - */ -static const char *paths_that_should_be_matched[] = { - "/aa/", - "/aa/bb/", - "/aa/bb/cc/", -#define FIRST_VALID_PATH_WHICH_SHOULD_MATCH 3 - "/", - "/aa/bb/cc", - NULL -}; - -/* These paths should not be matched by PATH_MATCH_RULE. */ -static const char *paths_that_should_not_be_matched[] = { - "/aa/b", - "/aa", - /* or even... */ - "/aa/bb", - NULL -}; - -static void -test_path_match (int type, - const char *path, - const char *rule_text, - BusMatchRule *rule, - dbus_bool_t should_match) -{ - DBusMessage *message = dbus_message_new (DBUS_MESSAGE_TYPE_SIGNAL); - dbus_bool_t matched; - - _dbus_assert (message != NULL); - if (!dbus_message_set_member (message, "Foo")) - _dbus_assert_not_reached ("oom"); - - if (!dbus_message_append_args (message, - type, &path, - NULL)) - _dbus_assert_not_reached ("oom"); - - matched = match_rule_matches (rule, NULL, NULL, message, 0); - - if (matched != should_match) - { - _dbus_warn ("Expected rule %s to %s message " - "with first arg %s of type '%c', failed\n", - rule_text, - should_match ? "match" : "not match", - path, - (char) type); - exit (1); - } - - dbus_message_unref (message); -} - -static void -test_path_matching (void) -{ - BusMatchRule *rule; - const char **s; - - rule = check_parse (TRUE, PATH_MATCH_RULE); - _dbus_assert (rule != NULL); - - for (s = paths_that_should_be_matched; *s != NULL; s++) - test_path_match (DBUS_TYPE_STRING, *s, PATH_MATCH_RULE, rule, TRUE); - - for (s = paths_that_should_be_matched + FIRST_VALID_PATH_WHICH_SHOULD_MATCH; - *s != NULL; s++) - test_path_match (DBUS_TYPE_OBJECT_PATH, *s, PATH_MATCH_RULE, rule, TRUE); - - for (s = paths_that_should_not_be_matched; *s != NULL; s++) - { - test_path_match (DBUS_TYPE_STRING, *s, PATH_MATCH_RULE, rule, FALSE); - test_path_match (DBUS_TYPE_OBJECT_PATH, *s, PATH_MATCH_RULE, rule, FALSE); - } - - bus_match_rule_unref (rule); -} - -static const char* -path_namespace_should_match_message_1[] = { - "type='signal',path_namespace='/'", - "type='signal',path_namespace='/foo'", - "type='signal',path_namespace='/foo/TheObjectManager'", - NULL -}; - -static const char* -path_namespace_should_not_match_message_1[] = { - "type='signal',path_namespace='/bar'", - "type='signal',path_namespace='/bar/TheObjectManager'", - NULL -}; - -static const char* -path_namespace_should_match_message_2[] = { - "type='signal',path_namespace='/'", - "type='signal',path_namespace='/foo/TheObjectManager'", - NULL -}; - -static const char* -path_namespace_should_not_match_message_2[] = { - NULL -}; - -static const char* -path_namespace_should_match_message_3[] = { - "type='signal',path_namespace='/'", - NULL -}; - -static const char* -path_namespace_should_not_match_message_3[] = { - "type='signal',path_namespace='/foo/TheObjectManager'", - NULL -}; - -static const char* -path_namespace_should_match_message_4[] = { - "type='signal',path_namespace='/'", - NULL -}; - -static const char* -path_namespace_should_not_match_message_4[] = { - "type='signal',path_namespace='/foo/TheObjectManager'", - NULL -}; - -static void -test_matching_path_namespace (void) -{ - DBusMessage *message1; - DBusMessage *message2; - DBusMessage *message3; - DBusMessage *message4; - - message1 = dbus_message_new (DBUS_MESSAGE_TYPE_SIGNAL); - _dbus_assert (message1 != NULL); - if (!dbus_message_set_path (message1, "/foo/TheObjectManager")) - _dbus_assert_not_reached ("oom"); - - message2 = dbus_message_new (DBUS_MESSAGE_TYPE_SIGNAL); - _dbus_assert (message2 != NULL); - if (!dbus_message_set_path (message2, "/foo/TheObjectManager/child_object")) - _dbus_assert_not_reached ("oom"); - - message3 = dbus_message_new (DBUS_MESSAGE_TYPE_SIGNAL); - _dbus_assert (message3 != NULL); - if (!dbus_message_set_path (message3, "/foo/TheObjectManagerOther")) - _dbus_assert_not_reached ("oom"); - - message4 = dbus_message_new (DBUS_MESSAGE_TYPE_SIGNAL); - _dbus_assert (message4 != NULL); - if (!dbus_message_set_path (message4, "/")) - _dbus_assert_not_reached ("oom"); - - check_matching (message1, 1, - path_namespace_should_match_message_1, - path_namespace_should_not_match_message_1); - check_matching (message2, 2, - path_namespace_should_match_message_2, - path_namespace_should_not_match_message_2); - check_matching (message3, 3, - path_namespace_should_match_message_3, - path_namespace_should_not_match_message_3); - check_matching (message4, 4, - path_namespace_should_match_message_4, - path_namespace_should_not_match_message_4); - - dbus_message_unref (message4); - dbus_message_unref (message3); - dbus_message_unref (message2); - dbus_message_unref (message1); -} - -dbus_bool_t -bus_signals_test (const DBusString *test_data_dir) -{ - BusMatchmaker *matchmaker; - - matchmaker = bus_matchmaker_new (); - bus_matchmaker_ref (matchmaker); - bus_matchmaker_unref (matchmaker); - bus_matchmaker_unref (matchmaker); - - if (!_dbus_test_oom_handling ("parsing match rules", test_parsing, NULL)) - _dbus_assert_not_reached ("Parsing match rules test failed"); - - test_equality (); - test_matching (); - test_path_matching (); - test_matching_path_namespace (); - - return TRUE; -} - -#endif /* DBUS_ENABLE_EMBEDDED_TESTS */ - |