diff options
-rw-r--r-- | ChangeLog | 41 | ||||
-rw-r--r-- | dbus/dbus-marshal.c | 588 | ||||
-rw-r--r-- | dbus/dbus-marshal.h | 76 | ||||
-rw-r--r-- | dbus/dbus-message-builder.c | 2 | ||||
-rw-r--r-- | dbus/dbus-message.c | 122 | ||||
-rw-r--r-- | dbus/dbus-message.h | 6 | ||||
-rw-r--r-- | dbus/dbus-protocol.h | 1 | ||||
-rw-r--r-- | dbus/dbus.h | 1 | ||||
-rw-r--r-- | doc/dbus-specification.sgml | 7 | ||||
-rw-r--r-- | test/data/invalid-messages/dict-with-nil-value.message | 12 | ||||
-rw-r--r-- | test/data/invalid-messages/too-short-dict.message | 11 | ||||
-rw-r--r-- | test/data/valid-messages/dict-simple.message | 11 | ||||
-rw-r--r-- | test/data/valid-messages/dict.message | 29 |
13 files changed, 851 insertions, 56 deletions
@@ -1,3 +1,44 @@ +2003-03-10 Anders Carlsson <andersca@codefactory.se> + + * dbus/dbus-marshal.c: + (_dbus_marshal_set_string): + Take a length argument so we can marshal the correct string + length. + + (_dbus_marshal_dict), (_dbus_demarshal_dict), + (_dbus_marshal_get_arg_end_pos), (_dbus_marshal_validate_arg), + (_dbus_marshal_test): + * dbus/dbus-marshal.h: + Add support for marshalling and demarshalling dicts. + + * dbus/dbus-message-builder.c: (_dbus_message_data_load): + Add support for TYPE DICT. + + * dbus/dbus-message.c: (set_string_field): + Adjust header padding. + + (dbus_message_append_args_valist), (dbus_message_append_dict), + (dbus_message_get_args_valist), (dbus_message_iter_get_arg_type), + (dbus_message_iter_get_dict), (_dbus_message_loader_return_buffer), + (check_message_handling), (check_have_valid_message): + * dbus/dbus-message.h: + Add functions for setting and getting dicts. + + * dbus/dbus-protocol.h: + Add DBUS_TYPE_DICT. + + * dbus/dbus.h: + Add dbus-dict.h + + * doc/dbus-specification.sgml: + Add information about how dicts are marshalled. + + * test/data/invalid-messages/dict-with-nil-value.message: + * test/data/invalid-messages/too-short-dict.message: + * test/data/valid-messages/dict-simple.message: + * test/data/valid-messages/dict.message: + Add sample messages containing dicts. + 2003-03-08 Anders Carlsson <andersca@codefactory.se> * dbus/dbus-dict.h: Add DBUS_END_DECLS. diff --git a/dbus/dbus-marshal.c b/dbus/dbus-marshal.c index f78757fd..4c721f66 100644 --- a/dbus/dbus-marshal.c +++ b/dbus/dbus-marshal.c @@ -198,6 +198,7 @@ _dbus_marshal_set_uint32 (DBusString *str, * @param offset the byte offset where string should be written * @param byte_order the byte order to use * @param value the value + * @param len the length to use * @returns #TRUE on success * */ @@ -205,10 +206,10 @@ dbus_bool_t _dbus_marshal_set_string (DBusString *str, int byte_order, int offset, - const DBusString *value) + const DBusString *value, + int len) { int old_len; - int new_len; _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN || byte_order == DBUS_BIG_ENDIAN); @@ -216,14 +217,12 @@ _dbus_marshal_set_string (DBusString *str, old_len = _dbus_demarshal_uint32 (str, byte_order, offset, NULL); - new_len = _dbus_string_get_length (value); - - if (!_dbus_string_replace_len (value, 0, new_len, + if (!_dbus_string_replace_len (value, 0, len, str, offset + 4, old_len)) return FALSE; _dbus_marshal_set_uint32 (str, byte_order, - offset, new_len); + offset, len); return TRUE; } @@ -496,6 +495,193 @@ _dbus_marshal_string_array (DBusString *str, return FALSE; } + +/** + * Marshals a dict + * @param str the string to append the marshalled value to + * @param byte_order the byte order to use + * @param dict the dict + * @returns #TRUE on success + */ +dbus_bool_t +_dbus_marshal_dict (DBusString *str, + int byte_order, + DBusDict *dict) +{ + int old_string_len; + int i, len; + char **keys; + + old_string_len = _dbus_string_get_length (str); + + if (!dbus_dict_get_keys (dict, &keys, &len)) + goto error; + + if (len == 0) + return TRUE; + + if (!_dbus_marshal_string_array (str, byte_order, + keys, len)) + goto error; + + for (i = 0; i < len; i++) + { + int value_type; + + value_type = dbus_dict_get_value_type (dict, keys[i]); + + if (!_dbus_string_append_byte (str, value_type)) + goto error; + + switch (dbus_dict_get_value_type (dict, keys[i])) + { + case DBUS_TYPE_BOOLEAN: + { + dbus_bool_t value; + + if (!dbus_dict_get_boolean (dict, keys[i], &value)) + goto error; + + if (!_dbus_string_append_byte (str, (value != FALSE))) + goto error; + + break; + } + + case DBUS_TYPE_INT32: + { + dbus_int32_t value; + + if (!dbus_dict_get_int32 (dict, keys[i], &value)) + goto error; + + if (!_dbus_marshal_int32 (str, byte_order, value)) + goto error; + + break; + } + case DBUS_TYPE_UINT32: + { + dbus_uint32_t value; + + if (!dbus_dict_get_uint32 (dict, keys[i], &value)) + goto error; + + if (!_dbus_marshal_uint32 (str, byte_order, value)) + goto error; + + break; + } + case DBUS_TYPE_DOUBLE: + { + double value; + + if (!dbus_dict_get_double (dict, keys[i], &value)) + goto error; + + if (!_dbus_marshal_double (str, byte_order, value)) + goto error; + + break; + } + case DBUS_TYPE_INT32_ARRAY: + { + const dbus_int32_t *value; + int len; + + if (!dbus_dict_get_int32_array (dict, keys[i], &value, &len)) + goto error; + + if (!_dbus_marshal_int32_array (str, byte_order, value, len)) + goto error; + + break; + } + case DBUS_TYPE_STRING: + { + const char *value; + + if (!dbus_dict_get_string (dict, keys[i], &value)) + goto error; + + if (!_dbus_marshal_string (str, byte_order, value)) + goto error; + + break; + } + case DBUS_TYPE_BOOLEAN_ARRAY: + { + const unsigned char *value; + int len; + + if (!dbus_dict_get_boolean_array (dict, keys[i], &value, &len)) + goto error; + + if (!_dbus_marshal_byte_array (str, byte_order, value, len)) + goto error; + + break; + } + case DBUS_TYPE_UINT32_ARRAY: + { + const dbus_uint32_t *value; + int len; + + if (!dbus_dict_get_uint32_array (dict, keys[i], &value, &len)) + goto error; + + if (!_dbus_marshal_uint32_array (str, byte_order, value, len)) + goto error; + + break; + } + case DBUS_TYPE_DOUBLE_ARRAY: + { + const double *value; + int len; + + if (!dbus_dict_get_double_array (dict, keys[i], &value, &len)) + goto error; + + if (!_dbus_marshal_double_array (str, byte_order, value, len)) + goto error; + + break; + } + case DBUS_TYPE_STRING_ARRAY: + { + const char **value; + int len; + + if (!dbus_dict_get_string_array (dict, keys[i], &value, &len)) + goto error; + + if (!_dbus_marshal_string_array (str, byte_order, value, len)) + goto error; + + break; + } + default: + _dbus_warn ("unknwon value type %d\n", dbus_dict_get_value_type (dict, keys[i])); + _dbus_assert_not_reached ("unknown value type in dict"); + } + } + + dbus_free_string_array (keys); + + return TRUE; + + error: + + dbus_free_string_array (keys); + + /* Restore previous length */ + _dbus_string_set_length (str, old_string_len); + + return FALSE; +} + + /** * Demarshals a double. * @@ -848,6 +1034,212 @@ _dbus_demarshal_string_array (const DBusString *str, return NULL; } +/** + * Demarshals a dict + * + * @param str the string containing the data + * @param byte_order the byte order + * @param pos the position in the string + * @param new_pos the new position in the string + * @returns the demarshalled dict + */ +DBusDict * +_dbus_demarshal_dict (const DBusString *str, + int byte_order, + int pos, + int *new_pos) +{ + char **keys; + int i, len; + DBusDict *dict; + + dict = dbus_dict_new (); + if (!dict) + return NULL; + + keys = _dbus_demarshal_string_array (str, byte_order, pos, &pos, &len); + + if (!keys) + goto error; + + for (i = 0; i < len; i++) + { + int value_type; + + switch ((value_type = _dbus_string_get_byte (str, pos ++))) + { + case DBUS_TYPE_BOOLEAN: + { + dbus_bool_t value; + + value = _dbus_string_get_byte (str, pos ++); + + if (!dbus_dict_set_boolean (dict, keys[i], value)) + goto error; + break; + } + case DBUS_TYPE_INT32: + { + dbus_int32_t value; + + value = _dbus_demarshal_int32 (str, byte_order, pos, &pos); + + if (!dbus_dict_set_int32 (dict, keys[i], value)) + goto error; + + break; + } + case DBUS_TYPE_UINT32: + { + dbus_uint32_t value; + + value = _dbus_demarshal_uint32 (str, byte_order, pos, &pos); + + if (!dbus_dict_set_uint32 (dict, keys[i], value)) + goto error; + + break; + } + case DBUS_TYPE_DOUBLE: + { + double value; + + value = _dbus_demarshal_double (str, byte_order, pos, &pos); + + if (!dbus_dict_set_double (dict, keys[i], value)) + goto error; + + break; + } + case DBUS_TYPE_STRING: + { + char *value; + + value = _dbus_demarshal_string (str, byte_order, pos, &pos); + + if (!value) + goto error; + + if (!dbus_dict_set_string (dict, keys[i], value)) + { + dbus_free (value); + goto error; + } + + dbus_free (value); + + break; + } + case DBUS_TYPE_BOOLEAN_ARRAY: + { + unsigned char *value; + int len; + + value = _dbus_demarshal_byte_array (str, byte_order, pos, &pos, &len); + + if (!value) + goto error; + + if (!dbus_dict_set_boolean_array (dict, keys[i], value, len)) + { + dbus_free (value); + goto error; + } + + dbus_free (value); + break; + } + case DBUS_TYPE_INT32_ARRAY: + { + dbus_int32_t *value; + int len; + + value = _dbus_demarshal_int32_array (str, byte_order, pos, &pos, &len); + + if (!value) + goto error; + + if (!dbus_dict_set_int32_array (dict, keys[i], value, len)) + { + dbus_free (value); + goto error; + } + + dbus_free (value); + break; + } + case DBUS_TYPE_UINT32_ARRAY: + { + dbus_uint32_t *value; + int len; + + value = _dbus_demarshal_uint32_array (str, byte_order, pos, &pos, &len); + + if (!value) + goto error; + + if (!dbus_dict_set_uint32_array (dict, keys[i], value, len)) + { + dbus_free (value); + goto error; + } + + dbus_free (value); + break; + } + case DBUS_TYPE_DOUBLE_ARRAY: + { + double *value; + int len; + + value = _dbus_demarshal_double_array (str, byte_order, pos, &pos, &len); + + if (!value) + goto error; + + if (!dbus_dict_set_double_array (dict, keys[i], value, len)) + { + dbus_free (value); + goto error; + } + + dbus_free (value); + break; + } + case DBUS_TYPE_STRING_ARRAY: + { + char **value; + int len; + + value = _dbus_demarshal_string_array (str, byte_order, pos, &pos, &len); + + if (!value) + goto error; + + if (!dbus_dict_set_string_array (dict, keys[i], value, len)) + { + dbus_free_string_array (value); + goto error; + } + + dbus_free_string_array (value); + break; + } + default: + _dbus_warn ("unknown value type %d\n", value_type); + _dbus_assert_not_reached ("unknown value arg"); + } + } + + dbus_free_string_array (keys); + return dict; + + error: + dbus_free_string_array (keys); + dbus_dict_unref (dict); + return NULL; +} + /** * Returns the position right after the end of an argument. PERFORMS * NO VALIDATION WHATSOEVER. The message must have been previously @@ -980,7 +1372,34 @@ _dbus_marshal_get_arg_end_pos (const DBusString *str, *end_pos = pos; } break; - + + case DBUS_TYPE_DICT: + { + int len, i; + + /* Demarshal the length */ + len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &pos); + + for (i = 0; i < len; i++) + { + int str_len; + + /* Demarshal string length */ + str_len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos); + pos += str_len + 1; + } + + /* Now check the values */ + for (i = 0; i < len; i++) + { + if (!_dbus_marshal_get_arg_end_pos (str, byte_order, pos, &pos)) + return FALSE; + } + + *end_pos = pos; + + break; + } default: _dbus_warn ("Unknown message arg type %d\n", *data); _dbus_assert_not_reached ("Unknown message argument type\n"); @@ -1289,7 +1708,53 @@ _dbus_marshal_validate_arg (const DBusString *str, *end_pos = pos; } break; - + + case DBUS_TYPE_DICT: + { + int len; + int i; + + len = demarshal_and_validate_len (str, byte_order, pos + 1, &pos); + if (len < 0) + return FALSE; + + for (i = 0; i < len; i++) + { + int str_len; + + str_len = demarshal_and_validate_len (str, byte_order, + pos, &pos); + if (str_len < 0) + return FALSE; + + if (!validate_string (str, pos, str_len, &pos)) + return FALSE; + } + + /* Now validate each argument */ + for (i = 0; i < len; i++) + { + if (pos >= _dbus_string_get_length (str)) + { + _dbus_verbose ("not enough values in dict\n"); + return FALSE; + } + + if (_dbus_string_get_byte (str, pos) == DBUS_TYPE_NIL) + { + _dbus_verbose ("can't have NIL values in dicts\n"); + return FALSE; + } + + if (!_dbus_marshal_validate_arg (str, byte_order, pos, &pos)) + return FALSE; + } + + *end_pos = pos; + + break; + } + default: _dbus_verbose ("Unknown message arg type %d\n", *data); return FALSE; @@ -1426,7 +1891,23 @@ _dbus_marshal_test (void) DBusString str; char *tmp1, *tmp2; dbus_int32_t array1[3] = { 0x123, 0x456, 0x789 }, *array2; - int pos = 0, len; + int pos = 0, i, len; + dbus_bool_t our_bool; + dbus_int32_t our_int; + dbus_uint32_t our_uint; + double our_double; + const char *our_string; + const unsigned char boolean_array[] = { TRUE, FALSE, FALSE, TRUE }; + const unsigned char *our_boolean_array; + const dbus_int32_t int32_array[] = { 0x12345678, -1911, 0, 0xaffe, 0xedd1e }; + const dbus_int32_t *our_int32_array; + const dbus_uint32_t uint32_array[] = { 0x12345678, 0, 0xdeadbeef, 0x87654321, 0xffffffff }; + const dbus_uint32_t *our_uint32_array; + const double double_array[] = { 3.14159, 1.2345, 6.7890 }; + const double *our_double_array; + const char *string_array[] = { "This", "Is", "A", "Test" }; + const char **our_string_array; + DBusDict *dict; if (!_dbus_string_init (&str, _DBUS_INT_MAX)) _dbus_assert_not_reached ("failed to init string"); @@ -1491,7 +1972,96 @@ _dbus_marshal_test (void) dbus_free (array2); + /* Marshal dicts */ + dict = dbus_dict_new (); + if (dbus_dict_get_value_type (dict, "foo") != DBUS_TYPE_NIL) + _dbus_assert_not_reached ("didn't return DBUS_TYPE_NIL for non-existant entry"); + + if (!dbus_dict_set_boolean (dict, "boolean", TRUE)) + _dbus_assert_not_reached ("could not add boolean value"); + + if (!dbus_dict_set_int32 (dict, "int32", 0x12345678)) + _dbus_assert_not_reached ("could not add int32 value"); + + if (!dbus_dict_set_uint32 (dict, "uint32", 0x87654321)) + _dbus_assert_not_reached ("could not add uint32 value"); + + if (!dbus_dict_set_double (dict, "double", 3.14159)) + _dbus_assert_not_reached ("could not add double value"); + + if (!dbus_dict_set_string (dict, "string", "test string")) + _dbus_assert_not_reached ("could not add string value"); + + if (!dbus_dict_set_boolean_array (dict, "boolean_array", boolean_array, 4)) + _dbus_assert_not_reached ("could not add boolean array"); + + if (!dbus_dict_set_int32_array (dict, "int32_array", int32_array, 5)) + _dbus_assert_not_reached ("could not add int32 array"); + + if (!dbus_dict_set_uint32_array (dict, "uint32_array", uint32_array, 5)) + _dbus_assert_not_reached ("could not add uint32 array"); + + if (!dbus_dict_set_double_array (dict, "double_array", double_array, 3)) + _dbus_assert_not_reached ("could not add double array"); + + if (!dbus_dict_set_string_array (dict, "string_array", string_array, 4)) + _dbus_assert_not_reached ("could not add string array"); + + if (!_dbus_marshal_dict (&str, DBUS_BIG_ENDIAN, dict)) + _dbus_assert_not_reached ("could not marshal dict"); + + dbus_dict_unref (dict); + + dict = _dbus_demarshal_dict (&str, DBUS_BIG_ENDIAN, pos, &pos); + + if (!dbus_dict_get_boolean (dict, "boolean", &our_bool) || + !our_bool) + _dbus_assert_not_reached ("could not get boolean value"); + + if (!dbus_dict_get_int32 (dict, "int32", &our_int) || our_int != 0x12345678) + _dbus_assert_not_reached ("could not get int32 value or int32 values differ"); + + if (!dbus_dict_get_uint32 (dict, "uint32", &our_uint) || our_uint != 0x87654321) + _dbus_assert_not_reached ("could not get uint32 value or uint32 values differ"); + + if (!dbus_dict_get_double (dict, "double", &our_double) + || our_double != 3.14159) + _dbus_assert_not_reached ("could not get double value or double values differ"); + + if (!dbus_dict_get_string (dict, "string", &our_string) || strcmp (our_string, "test string") != 0) + _dbus_assert_not_reached ("could not get string value or string values differ"); + + if (!dbus_dict_get_boolean_array (dict, "boolean_array", &our_boolean_array, &len) || + len != 4 || memcmp (boolean_array, our_boolean_array, 4) != 0) + _dbus_assert_not_reached ("could not get boolean array value or boolean array values differ"); + + if (!dbus_dict_get_int32_array (dict, "int32_array", &our_int32_array, &len) || + len != 5 || memcmp (int32_array, our_int32_array, 5 * sizeof (dbus_int32_t)) != 0) + _dbus_assert_not_reached ("could not get int32 array value or int32 array values differ"); + + if (!dbus_dict_get_uint32_array (dict, "uint32_array", &our_uint32_array, &len) || + len != 5 || memcmp (uint32_array, our_uint32_array, 5 * sizeof (dbus_uint32_t) ) != 0) + _dbus_assert_not_reached ("could not get uint32 array value or uint32 array values differ"); + + if (!dbus_dict_get_double_array (dict, "double_array", &our_double_array, &len) || + len != 3 || memcmp (double_array, our_double_array, 3 * sizeof (double)) != 0) + _dbus_assert_not_reached ("could not get double array value or double array values differ"); + + if (!dbus_dict_get_string_array (dict, "string_array", &our_string_array, &len)) + _dbus_assert_not_reached ("could not get string array value"); + + if (len != 4) + _dbus_assert_not_reached ("string array lengths differ"); + + for (i = 0; i < len; i++) + { + if (strcmp (our_string_array[i], string_array[i]) != 0) + _dbus_assert_not_reached ("string array fields differ"); + } + + dbus_dict_unref (dict); + _dbus_string_free (&str); diff --git a/dbus/dbus-marshal.h b/dbus/dbus-marshal.h index cedca6b8..156ad09f 100644 --- a/dbus/dbus-marshal.h +++ b/dbus/dbus-marshal.h @@ -25,6 +25,7 @@ #define DBUS_MARSHAL_H #include <config.h> +#include <dbus/dbus-dict.h> #include <dbus/dbus-protocol.h> #include <dbus/dbus-types.h> #include <dbus/dbus-string.h> @@ -88,7 +89,8 @@ void _dbus_marshal_set_uint32 (DBusString *str, dbus_bool_t _dbus_marshal_set_string (DBusString *str, int byte_order, int offset, - const DBusString *value); + const DBusString *value, + int len); dbus_bool_t _dbus_marshal_int32 (DBusString *str, @@ -123,48 +125,56 @@ dbus_bool_t _dbus_marshal_string_array (DBusString *str, int byte_order, const char **value, int len); +dbus_bool_t _dbus_marshal_dict (DBusString *str, + int byte_order, + DBusDict *dict); double _dbus_demarshal_double (const DBusString *str, - int byte_order, - int pos, - int *new_pos); + int byte_order, + int pos, + int *new_pos); dbus_int32_t _dbus_demarshal_int32 (const DBusString *str, - int byte_order, - int pos, - int *new_pos); + int byte_order, + int pos, + int *new_pos); dbus_uint32_t _dbus_demarshal_uint32 (const DBusString *str, - int byte_order, - int pos, - int *new_pos); + int byte_order, + int pos, + int *new_pos); char * _dbus_demarshal_string (const DBusString *str, - int byte_order, - int pos, - int *new_pos); + int byte_order, + int pos, + int *new_pos); unsigned char *_dbus_demarshal_byte_array (const DBusString *str, - int byte_order, - int pos, - int *new_pos, - int *array_len); + int byte_order, + int pos, + int *new_pos, + int *array_len); dbus_int32_t * _dbus_demarshal_int32_array (const DBusString *str, - int byte_order, - int pos, - int *new_pos, - int *array_len); + int byte_order, + int pos, + int *new_pos, + int *array_len); dbus_uint32_t *_dbus_demarshal_uint32_array (const DBusString *str, - int byte_order, - int pos, - int *new_pos, - int *array_len); + int byte_order, + int pos, + int *new_pos, + int *array_len); double * _dbus_demarshal_double_array (const DBusString *str, - int byte_order, - int pos, - int *new_pos, - int *array_len); + int byte_order, + int pos, + int *new_pos, + int *array_len); char ** _dbus_demarshal_string_array (const DBusString *str, - int byte_order, - int pos, - int *new_pos, - int *array_len); + int byte_order, + int pos, + int *new_pos, + int *array_len); +DBusDict * _dbus_demarshal_dict (const DBusString *str, + int byte_order, + int pos, + int *new_pos); + dbus_bool_t _dbus_marshal_get_arg_end_pos (const DBusString *str, diff --git a/dbus/dbus-message-builder.c b/dbus/dbus-message-builder.c index 3501da9a..54b5de70 100644 --- a/dbus/dbus-message-builder.c +++ b/dbus/dbus-message-builder.c @@ -648,6 +648,8 @@ _dbus_message_data_load (DBusString *dest, code = DBUS_TYPE_DOUBLE; else if (_dbus_string_starts_with_c_str (&line, "STRING")) code = DBUS_TYPE_STRING; + else if (_dbus_string_starts_with_c_str (&line, "DICT")) + code = DBUS_TYPE_DICT; else { const char *s; diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c index db1b94bf..a25480cb 100644 --- a/dbus/dbus-message.c +++ b/dbus/dbus-message.c @@ -493,15 +493,21 @@ set_string_field (DBusMessage *message, DBusString v; int old_len; int new_len; + int len; + + clear_header_padding (message); old_len = _dbus_string_get_length (&message->header); + len = strlen (value); + _dbus_string_init_const_len (&v, value, - strlen (value) + 1); /* include nul */ + len + 1); /* include nul */ if (!_dbus_marshal_set_string (&message->header, message->byte_order, - offset, &v)) - return FALSE; + offset, &v, + len)) + goto failed; new_len = _dbus_string_get_length (&message->header); @@ -509,7 +515,19 @@ set_string_field (DBusMessage *message, offset, new_len - old_len); + if (!append_header_padding (message)) + goto failed; + return TRUE; + + failed: + /* this must succeed because it was allocated on function entry and + * DBusString doesn't ever realloc smaller + */ + if (!append_header_padding (message)) + _dbus_assert_not_reached ("failed to reappend header padding"); + + return FALSE; } } @@ -1162,7 +1180,15 @@ dbus_message_append_args_valist (DBusMessage *message, goto enomem; } break; - + case DBUS_TYPE_DICT: + { + DBusDict *dict; + + dict = va_arg (var_args, DBusDict *); + + if (!dbus_message_append_dict (message, dict)) + goto enomem; + } default: _dbus_warn ("Unknown field type %d\n", type); } @@ -1485,6 +1511,31 @@ dbus_message_append_string_array (DBusMessage *message, } /** + * Appends a dict to the message. + * + * @param message the message + * @param dict the dict + * @returns #TRUE on success + */ +dbus_bool_t +dbus_message_append_dict (DBusMessage *message, + DBusDict *dict) +{ + _dbus_assert (!message->locked); + + if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_DICT)) + return FALSE; + + if (!_dbus_marshal_dict (&message->body, message->byte_order, dict)) + { + _dbus_string_shorten (&message->body, 1); + return FALSE; + } + + return TRUE; +} + +/** * Gets arguments from a message given a variable argument list. * The variable argument list should contain the type of the * argumen followed by a pointer to where the value should be @@ -1696,6 +1747,16 @@ dbus_message_get_args_valist (DBusMessage *message, return DBUS_RESULT_NO_MEMORY; break; } + case DBUS_TYPE_DICT: + { + DBusDict **dict; + + dict = va_arg (var_args, DBusDict **); + + if (!dbus_message_iter_get_dict (iter, dict)) + return DBUS_RESULT_NO_MEMORY; + break; + } default: _dbus_warn ("Unknown field type %d\n", spec_type); } @@ -1850,7 +1911,7 @@ dbus_message_iter_get_arg_type (DBusMessageIter *iter) _dbus_string_get_const_data_len (&iter->message->body, &data, iter->pos, 1); - if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_STRING_ARRAY) + if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_DICT) return *data; return DBUS_TYPE_INVALID; @@ -2062,7 +2123,7 @@ dbus_message_iter_get_double_array (DBusMessageIter *iter, * @param iter the iterator * @param value return location for array values * @param len return location for length of byte array - * @returns the byte array + * @returns #TRUE on success */ dbus_bool_t dbus_message_iter_get_byte_array (DBusMessageIter *iter, @@ -2093,7 +2154,7 @@ dbus_message_iter_get_byte_array (DBusMessageIter *iter, * @param iter the iterator * @param value return location for string values * @param len return location for length of byte array - * @returns the byte array + * @returns #TRUE on success */ dbus_bool_t dbus_message_iter_get_string_array (DBusMessageIter *iter, @@ -2112,6 +2173,30 @@ dbus_message_iter_get_string_array (DBusMessageIter *iter, } /** + * Returns the dict that the iterator may point to. + * Note that you need to check that the iterator points + * to a dict prior to using this function. + * + * @param iter the iterator + * @param dict return location for dict + * @returns #TRUE on success + */ +dbus_bool_t +dbus_message_iter_get_dict (DBusMessageIter *iter, + DBusDict **dict) +{ + _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_DICT); + + *dict = _dbus_demarshal_dict (&iter->message->body, iter->message->byte_order, + iter->pos + 1, NULL); + + if (!*dict) + return FALSE; + else + return TRUE; +} + +/** * Sets the message sender. * * @param message the message @@ -2630,9 +2715,10 @@ _dbus_message_loader_return_buffer (DBusMessageLoader *loader, */ header_len = header_len_unsigned; body_len = body_len_unsigned; - + if (_DBUS_ALIGN_VALUE (header_len, 8) != header_len_unsigned) { + _dbus_verbose ("header length %d is not aligned to 8 bytes\n", header_len); loader->corrupted = TRUE; @@ -2654,8 +2740,8 @@ _dbus_message_loader_return_buffer (DBusMessageLoader *loader, int next_arg; #if 0 - _dbus_verbose_bytes_of_string (&loader->data, 0, header_len); -#endif + _dbus_verbose_bytes_of_string (&loader->data, 0, header_len + body_len); +#endif if (!decode_header_data (&loader->data, header_len, byte_order, fields, &header_padding)) { @@ -2899,7 +2985,7 @@ check_message_handling (DBusMessage *message) /* If we implement message_set_arg (message, n, value) * then we would want to test it here */ - + iter = dbus_message_get_args_iter (message); while ((type = dbus_message_iter_get_arg_type (iter)) != DBUS_TYPE_INVALID) { @@ -2967,7 +3053,18 @@ check_message_handling (DBusMessage *message) dbus_free_string_array (values); } break; - + + case DBUS_TYPE_DICT: + { + DBusDict *dict; + + if (!dbus_message_iter_get_dict (iter, &dict)) + return FALSE; + + dbus_dict_unref (dict); + } + break; + default: break; } @@ -3025,6 +3122,7 @@ check_have_valid_message (DBusMessageLoader *loader) failed: if (message) dbus_message_unref (message); + return retval; } diff --git a/dbus/dbus-message.h b/dbus/dbus-message.h index bb2b620e..4ea63060 100644 --- a/dbus/dbus-message.h +++ b/dbus/dbus-message.h @@ -28,6 +28,7 @@ #define DBUS_MESSAGE_H #include <dbus/dbus-macros.h> +#include <dbus/dbus-dict.h> #include <dbus/dbus-types.h> #include <stdarg.h> @@ -94,7 +95,8 @@ dbus_bool_t dbus_message_append_byte_array (DBusMessage *message, dbus_bool_t dbus_message_append_string_array (DBusMessage *message, const char **value, int len); - +dbus_bool_t dbus_message_append_dict (DBusMessage *message, + DBusDict *dict); DBusMessageIter *dbus_message_get_args_iter (DBusMessage *message); DBusResultCode dbus_message_get_args (DBusMessage *message, @@ -134,6 +136,8 @@ dbus_bool_t dbus_message_iter_get_byte_array (DBusMessageIter *iter, dbus_bool_t dbus_message_iter_get_string_array (DBusMessageIter *iter, char ***value, int *len); +dbus_bool_t dbus_message_iter_get_dict (DBusMessageIter *iter, + DBusDict **dict); DBUS_END_DECLS; diff --git a/dbus/dbus-protocol.h b/dbus/dbus-protocol.h index 1a6fcb80..e0b0c985 100644 --- a/dbus/dbus-protocol.h +++ b/dbus/dbus-protocol.h @@ -53,6 +53,7 @@ extern "C" { #define DBUS_TYPE_DOUBLE_ARRAY 10 #define DBUS_TYPE_BYTE_ARRAY 11 #define DBUS_TYPE_STRING_ARRAY 12 +#define DBUS_TYPE_DICT 13 /* Header flags */ #define DBUS_HEADER_FLAG_ERROR 0x1 diff --git a/dbus/dbus.h b/dbus/dbus.h index 025ccbb2..1128d362 100644 --- a/dbus/dbus.h +++ b/dbus/dbus.h @@ -29,6 +29,7 @@ #include <dbus/dbus-address.h> #include <dbus/dbus-bus.h> #include <dbus/dbus-connection.h> +#include <dbus/dbus-dict.h> #include <dbus/dbus-errors.h> #include <dbus/dbus-macros.h> #include <dbus/dbus-message.h> diff --git a/doc/dbus-specification.sgml b/doc/dbus-specification.sgml index 0845d806..dba70baf 100644 --- a/doc/dbus-specification.sgml +++ b/doc/dbus-specification.sgml @@ -406,7 +406,12 @@ <entry>UINT32 giving the number of values in the array, followed by the given number of STRING values. </entry> - </row> + </row><row> + <entry>DICT</entry> + <entry>STRING_ARRAY with the keys, followed by the given + number of values encoded as type code as a byte followed by the encoded value. + </entry> + </row> </tbody> </tgroup> </informaltable> diff --git a/test/data/invalid-messages/dict-with-nil-value.message b/test/data/invalid-messages/dict-with-nil-value.message new file mode 100644 index 00000000..8f899605 --- /dev/null +++ b/test/data/invalid-messages/dict-with-nil-value.message @@ -0,0 +1,12 @@ +# Message with lots of different argument types + +VALID_HEADER +END_LENGTH Header +ALIGN 8 +START_LENGTH Body +TYPE DICT +STRING_ARRAY { 'nil', 'uint32' } +TYPE NIL +TYPE UINT32 +UINT32 0x8765432 +END_LENGTH Body diff --git a/test/data/invalid-messages/too-short-dict.message b/test/data/invalid-messages/too-short-dict.message new file mode 100644 index 00000000..6df40b33 --- /dev/null +++ b/test/data/invalid-messages/too-short-dict.message @@ -0,0 +1,11 @@ +# Message with lots of different argument types + +VALID_HEADER +END_LENGTH Header +ALIGN 8 +START_LENGTH Body +TYPE DICT +STRING_ARRAY { 'int32', 'uint32' } +TYPE UINT32 +UINT32 0x8765432 +END_LENGTH Body diff --git a/test/data/valid-messages/dict-simple.message b/test/data/valid-messages/dict-simple.message new file mode 100644 index 00000000..0b9d0186 --- /dev/null +++ b/test/data/valid-messages/dict-simple.message @@ -0,0 +1,11 @@ +# A simple dict + +VALID_HEADER +END_LENGTH Header +ALIGN 8 +START_LENGTH Body +TYPE DICT +STRING_ARRAY { 'int32' } +TYPE INT32 +INT32 0x12345678 +END_LENGTH Body diff --git a/test/data/valid-messages/dict.message b/test/data/valid-messages/dict.message new file mode 100644 index 00000000..0532e682 --- /dev/null +++ b/test/data/valid-messages/dict.message @@ -0,0 +1,29 @@ +# Dict with different values + +VALID_HEADER +END_LENGTH Header +ALIGN 8 +START_LENGTH Body +TYPE DICT +STRING_ARRAY { 'boolean', 'int32', 'uint32', 'double', 'string', 'boolean_array', 'int32_array', 'uint32_array', 'double_array', 'string_array' } +TYPE BOOLEAN +BYTE 1 +TYPE INT32 +INT32 0x12345678 +TYPE UINT32 +UINT32 0x8765432 +TYPE DOUBLE +DOUBLE 3.141592653589 +TYPE STRING +STRING 'This is a string' +TYPE BOOLEAN_ARRAY +BOOLEAN_ARRAY { true, false, false, true, false } +TYPE INT32_ARRAY +INT32_ARRAY { 1, -2, 3, -4, 5, -6, 7, -8, 9, -10 } +TYPE UINT32_ARRAY +UINT32_ARRAY { 11, 12, 314, 1911, 57692, 1237, 2834 } +TYPE DOUBLE_ARRAY +DOUBLE_ARRAY { 0.1, 0.2, 3.1415926, 2.7183, 10.0, 9.99 } +TYPE STRING_ARRAY +STRING_ARRAY { 'Hello', 'This', 'Is', 'A', 'String', 'Array!' } +END_LENGTH Body |