diff options
author | Havoc Pennington <hp@redhat.com> | 2003-10-10 02:42:21 +0000 |
---|---|---|
committer | Havoc Pennington <hp@redhat.com> | 2003-10-10 02:42:21 +0000 |
commit | 6a65f4802e95ba442c520f8e225da837e0a9f73b (patch) | |
tree | 734e69da90869b3788d381e75911d720ad8cfd0f | |
parent | 79d03f94fec278d270a33792aeffb33ba239bb01 (diff) |
2003-10-09 Havoc Pennington <hp@redhat.com>
Make matching rules theoretically work (add parser).
* bus/bus.c (bus_context_check_security_policy): fix up to handle
the case where destination is explicitly specified as bus driver
and someone else is eavesdropping.
* bus/policy.c (bus_client_policy_check_can_receive): fix up
definition of eavesdropping and assertion
* tools/dbus-send.c (main): use dbus_message_type_from_string
* bus/signals.c (bus_match_rule_parse): implement
* dbus/dbus-message.c (dbus_message_type_from_string): new
* dbus/dbus-errors.h (DBUS_ERROR_MATCH_RULE_INVALID): add
-rw-r--r-- | ChangeLog | 19 | ||||
-rw-r--r-- | bus/bus.c | 25 | ||||
-rw-r--r-- | bus/config-parser.c | 19 | ||||
-rw-r--r-- | bus/dispatch.c | 3 | ||||
-rw-r--r-- | bus/policy.c | 17 | ||||
-rw-r--r-- | bus/signals.c | 623 | ||||
-rw-r--r-- | dbus/dbus-errors.h | 1 | ||||
-rw-r--r-- | dbus/dbus-message.c | 28 | ||||
-rw-r--r-- | dbus/dbus-message.h | 2 | ||||
-rw-r--r-- | tools/dbus-send.c | 8 |
10 files changed, 689 insertions, 56 deletions
@@ -1,3 +1,22 @@ +2003-10-09 Havoc Pennington <hp@redhat.com> + + Make matching rules theoretically work (add parser). + + * bus/bus.c (bus_context_check_security_policy): fix up to handle + the case where destination is explicitly specified as bus driver + and someone else is eavesdropping. + + * bus/policy.c (bus_client_policy_check_can_receive): fix up + definition of eavesdropping and assertion + + * tools/dbus-send.c (main): use dbus_message_type_from_string + + * bus/signals.c (bus_match_rule_parse): implement + + * dbus/dbus-message.c (dbus_message_type_from_string): new + + * dbus/dbus-errors.h (DBUS_ERROR_MATCH_RULE_INVALID): add + 2003-10-02 Havoc Pennington <hp@pobox.com> * glib/dbus-gproxy.c (dbus_gproxy_call_no_reply): rename from @@ -872,6 +872,19 @@ bus_context_get_max_match_rules_per_connection (BusContext *context) return context->limits.max_match_rules_per_connection; } +/* + * addressed_recipient is the recipient specified in the message. + * + * proposed_recipient is the recipient we're considering sending + * to right this second, and may be an eavesdropper. + * + * sender is the sender of the message. + * + * NULL for proposed_recipient or sender definitely means the bus driver. + * + * NULL for addressed_recipient may mean the bus driver, or may mean + * no destination was specified in the message (e.g. a signal). + */ dbus_bool_t bus_context_check_security_policy (BusContext *context, DBusConnection *sender, @@ -883,15 +896,9 @@ bus_context_check_security_policy (BusContext *context, BusClientPolicy *sender_policy; BusClientPolicy *recipient_policy; - /* NULL sender, proposed_recipient means the bus driver. NULL - * addressed_recipient means the message didn't specify an explicit - * target. If proposed_recipient is NULL, then addressed_recipient - * is also NULL but is implicitly the bus driver. - */ - - _dbus_assert (proposed_recipient == NULL || - (dbus_message_get_destination (message) == NULL || - addressed_recipient != NULL)); + _dbus_assert (dbus_message_get_destination (message) == NULL || /* Signal */ + (addressed_recipient != NULL || + strcmp (dbus_message_get_destination (message), DBUS_SERVICE_ORG_FREEDESKTOP_DBUS) == 0)); /* Destination specified or is the bus driver */ if (sender != NULL) { diff --git a/bus/config-parser.c b/bus/config-parser.c index 7b9b962d..3ff3ec50 100644 --- a/bus/config-parser.c +++ b/bus/config-parser.c @@ -813,21 +813,6 @@ start_busconfig_child (BusConfigParser *parser, } } -static int -message_type_from_string (const char *type_str) -{ - if (strcmp (type_str, "method_call") == 0) - return DBUS_MESSAGE_TYPE_METHOD_CALL; - if (strcmp (type_str, "method_return") == 0) - return DBUS_MESSAGE_TYPE_METHOD_RETURN; - else if (strcmp (type_str, "signal") == 0) - return DBUS_MESSAGE_TYPE_SIGNAL; - else if (strcmp (type_str, "error") == 0) - return DBUS_MESSAGE_TYPE_ERROR; - else - return DBUS_MESSAGE_TYPE_INVALID; -} - static dbus_bool_t append_rule_from_element (BusConfigParser *parser, const char *element_name, @@ -1027,7 +1012,7 @@ append_rule_from_element (BusConfigParser *parser, message_type = DBUS_MESSAGE_TYPE_INVALID; if (send_type != NULL) { - message_type = message_type_from_string (send_type); + message_type = dbus_message_type_from_string (send_type); if (message_type == DBUS_MESSAGE_TYPE_INVALID) { dbus_set_error (error, DBUS_ERROR_FAILED, @@ -1079,7 +1064,7 @@ append_rule_from_element (BusConfigParser *parser, message_type = DBUS_MESSAGE_TYPE_INVALID; if (receive_type != NULL) { - message_type = message_type_from_string (receive_type); + message_type = dbus_message_type_from_string (receive_type); if (message_type == DBUS_MESSAGE_TYPE_INVALID) { dbus_set_error (error, DBUS_ERROR_FAILED, diff --git a/bus/dispatch.c b/bus/dispatch.c index 606c68ef..e238cb4c 100644 --- a/bus/dispatch.c +++ b/bus/dispatch.c @@ -920,7 +920,8 @@ check_add_match_all (BusContext *context, if (message == NULL) return TRUE; - if (!dbus_message_append_args (message, DBUS_TYPE_STRING, "", /* FIXME */ + /* empty string match rule matches everything */ + if (!dbus_message_append_args (message, DBUS_TYPE_STRING, "", DBUS_TYPE_INVALID)) { dbus_message_unref (message); diff --git a/bus/policy.c b/bus/policy.c index 2d462fb6..71137ca9 100644 --- a/bus/policy.c +++ b/bus/policy.c @@ -913,6 +913,9 @@ bus_client_policy_check_can_send (BusClientPolicy *policy, return allowed; } +/* See docs on what the args mean on bus_context_check_security_policy() + * comment + */ dbus_bool_t bus_client_policy_check_can_receive (BusClientPolicy *policy, BusRegistry *registry, @@ -924,20 +927,10 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy, DBusList *link; dbus_bool_t allowed; dbus_bool_t eavesdropping; - - /* NULL sender, proposed_recipient means the bus driver. NULL - * addressed_recipient means the message didn't specify an explicit - * target. If proposed_recipient is NULL, then addressed_recipient - * is also NULL but is implicitly the bus driver. - */ - _dbus_assert (proposed_recipient == NULL || - (dbus_message_get_destination (message) == NULL || - addressed_recipient != NULL)); - eavesdropping = - (proposed_recipient == NULL || /* explicitly to bus driver */ - (addressed_recipient && addressed_recipient != proposed_recipient)); /* explicitly to a different recipient */ + addressed_recipient != proposed_recipient && + dbus_message_get_destination (message) != NULL; /* policy->rules is in the order the rules appeared * in the config file, i.e. last rule that applies wins diff --git a/bus/signals.c b/bus/signals.c index 30d977c3..960d846c 100644 --- a/bus/signals.c +++ b/bus/signals.c @@ -52,6 +52,10 @@ bus_match_rule_new (DBusConnection *matches_go_to) rule->refcount = 1; rule->matches_go_to = matches_go_to; +#ifndef DBUS_BUILD_TESTS + _dbus_assert (rule->matches_go_to != NULL); +#endif + return rule; } @@ -285,6 +289,285 @@ bus_match_rule_set_path (BusMatchRule *rule, 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. + */ +#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; +} + /* * The format is comma-separated with strings quoted with single quotes * as for the shell (to escape a literal single quote, use '\''). @@ -299,24 +582,157 @@ bus_match_rule_parse (DBusConnection *matches_go_to, DBusError *error) { BusMatchRule *rule; - + RuleToken tokens[MAX_RULE_TOKENS+1]; /* NULL termination + 1 */ + int i; + + _DBUS_ASSERT_ERROR_IS_CLEAR (error); + + memset (tokens, '\0', sizeof (tokens)); + rule = bus_match_rule_new (matches_go_to); if (rule == NULL) - goto oom; - - /* FIXME implement for real */ + { + BUS_SET_OOM (error); + goto failed; + } - if (!bus_match_rule_set_message_type (rule, - DBUS_MESSAGE_TYPE_SIGNAL)) - goto oom; + if (!tokenize_rule (rule_text, tokens, error)) + goto failed; - return rule; + i = 0; + while (tokens[i].key != NULL) + { + const char *key = tokens[i].key; + const char *value = tokens[i].value; + + 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 (!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 (!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 (!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 (!bus_match_rule_set_member (rule, value)) + { + BUS_SET_OOM (error); + goto failed; + } + } + else if (strcmp (key, "path") == 0) + { + if (rule->flags & BUS_MATCH_PATH) + { + dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID, + "Key %s specified twice in match rule\n", key); + goto failed; + } + + if (!bus_match_rule_set_path (rule, value)) + { + 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 (!bus_match_rule_set_destination (rule, value)) + { + BUS_SET_OOM (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; - oom: + failed: + _DBUS_ASSERT_ERROR_IS_SET (error); if (rule) - bus_match_rule_unref (rule); - BUS_SET_OOM (error); - return NULL; + { + 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; } struct BusMatchmaker @@ -760,6 +1176,186 @@ bus_matchmaker_get_recipients (BusMatchmaker *matchmaker, #ifdef DBUS_BUILD_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); + } + + /* Reject duplicates */ + rule = check_parse (FALSE, "type='signal',type='method_call'"); + _dbus_assert (rule == NULL); + + /* Reject broken keys */ + rule = check_parse (FALSE, "blah='signal'"); + _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); + + /* Empty string values are allowed at the moment */ + rule = check_parse (TRUE, "interface="); + if (rule != NULL) + { + _dbus_assert (rule->flags == BUS_MATCH_INTERFACE); + _dbus_assert (rule->interface); + _dbus_assert (strlen (rule->interface) == 0); + + bus_match_rule_unref (rule); + } + + /* Empty string expressed with quotes */ + rule = check_parse (TRUE, "interface=''"); + if (rule != NULL) + { + _dbus_assert (rule->flags == BUS_MATCH_INTERFACE); + _dbus_assert (rule->interface); + _dbus_assert (strlen (rule->interface) == 0); + + bus_match_rule_unref (rule); + } + + /* Check whitespace in a value */ + rule = check_parse (TRUE, "interface= "); + if (rule != NULL) + { + _dbus_assert (rule->flags == BUS_MATCH_INTERFACE); + _dbus_assert (rule->interface); + _dbus_assert (strcmp (rule->interface, " ") == 0); + + bus_match_rule_unref (rule); + } + + /* Check whitespace mixed with non-whitespace in a value */ + rule = check_parse (TRUE, "interface= foo "); + if (rule != NULL) + { + _dbus_assert (rule->flags == BUS_MATCH_INTERFACE); + _dbus_assert (rule->interface); + _dbus_assert (strcmp (rule->interface, " foo ") == 0); + + bus_match_rule_unref (rule); + } + + return TRUE; +} dbus_bool_t bus_signals_test (const DBusString *test_data_dir) @@ -770,6 +1366,9 @@ bus_signals_test (const DBusString *test_data_dir) 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"); return TRUE; } diff --git a/dbus/dbus-errors.h b/dbus/dbus-errors.h index f229188a..b7b601bf 100644 --- a/dbus/dbus-errors.h +++ b/dbus/dbus-errors.h @@ -73,6 +73,7 @@ struct DBusError #define DBUS_ERROR_UNKNOWN_METHOD "org.freedesktop.DBus.Error.UnknownMethod" #define DBUS_ERROR_TIMED_OUT "org.freedesktop.DBus.Error.TimedOut" #define DBUS_ERROR_MATCH_RULE_NOT_FOUND "org.freedesktop.DBus.Error.MatchRuleNotFound" +#define DBUS_ERROR_MATCH_RULE_INVALID "org.freedesktop.DBus.Error.MatchRuleInvalid" #define DBUS_ERROR_SPAWN_EXEC_FAILED "org.freedesktop.DBus.Error.Spawn.ExecFailed" #define DBUS_ERROR_SPAWN_FORK_FAILED "org.freedesktop.DBus.Error.Spawn.ForkFailed" #define DBUS_ERROR_SPAWN_CHILD_EXITED "org.freedesktop.DBus.Error.Spawn.ChildExited" diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c index 19457468..38fd3790 100644 --- a/dbus/dbus-message.c +++ b/dbus/dbus-message.c @@ -5416,6 +5416,34 @@ dbus_message_get_data (DBusMessage *message, return res; } +/** + * Utility function to convert a machine-readable (not translated) + * string into a D-BUS message type. + * + * @code + * "method_call" -> DBUS_MESSAGE_TYPE_METHOD_CALL + * "method_return" -> DBUS_MESSAGE_TYPE_METHOD_RETURN + * "signal" -> DBUS_MESSAGE_TYPE_SIGNAL + * "error" -> DBUS_MESSAGE_TYPE_ERROR + * anything else -> DBUS_MESSAGE_TYPE_INVALID + * @endcode + * + */ +int +dbus_message_type_from_string (const char *type_str) +{ + if (strcmp (type_str, "method_call") == 0) + return DBUS_MESSAGE_TYPE_METHOD_CALL; + if (strcmp (type_str, "method_return") == 0) + return DBUS_MESSAGE_TYPE_METHOD_RETURN; + else if (strcmp (type_str, "signal") == 0) + return DBUS_MESSAGE_TYPE_SIGNAL; + else if (strcmp (type_str, "error") == 0) + return DBUS_MESSAGE_TYPE_ERROR; + else + return DBUS_MESSAGE_TYPE_INVALID; +} + /** @} */ #ifdef DBUS_BUILD_TESTS #include "dbus-test.h" diff --git a/dbus/dbus-message.h b/dbus/dbus-message.h index 888fe862..bfaf2f0d 100644 --- a/dbus/dbus-message.h +++ b/dbus/dbus-message.h @@ -275,6 +275,8 @@ dbus_bool_t dbus_message_set_data (DBusMessage *message, void* dbus_message_get_data (DBusMessage *message, dbus_int32_t slot); +int dbus_message_type_from_string (const char *type_str); + DBUS_END_DECLS; #endif /* DBUS_MESSAGE_H */ diff --git a/tools/dbus-send.c b/tools/dbus-send.c index 06a87adb..d0cca2fd 100644 --- a/tools/dbus-send.c +++ b/tools/dbus-send.c @@ -86,11 +86,9 @@ main (int argc, char *argv[]) if (type_str != NULL) { - if (strcmp (type_str, "method_call") == 0) - message_type = DBUS_MESSAGE_TYPE_METHOD_CALL; - else if (strcmp (type_str, "signal") == 0) - message_type = DBUS_MESSAGE_TYPE_SIGNAL; - else + message_type = dbus_message_type_from_string (type_str); + if (!(message_type == DBUS_MESSAGE_TYPE_METHOD_CALL || + message_type == DBUS_MESSAGE_TYPE_SIGNAL)) { fprintf (stderr, "Message type \"%s\" is not supported\n", type_str); |