diff options
Diffstat (limited to 'dbus/dbus-marshal.c')
| -rw-r--r-- | dbus/dbus-marshal.c | 588 | 
1 files changed, 579 insertions, 9 deletions
| 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); | 
