+ * Returns the byte array that the iterator may point to.
+ * Note that you need to check that the iterator points
+ * to a byte array prior to using this function.
+ *
+ * @param iter the iterator
+ * @param value return location for array values
+ * @param len return location for length of byte array
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_get_byte_array (DBusMessageIter *iter,
+ unsigned char **value,
+ int *len)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ int type, pos;
+
+ _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
+
+ pos = dbus_message_iter_get_data_start (real, &type);
+
+ _dbus_assert (type == DBUS_TYPE_ARRAY);
+
+ type = iter_get_array_type (real, NULL);
+
+ _dbus_assert (type == DBUS_TYPE_BYTE);
+
+ if (!_dbus_demarshal_byte_array (&real->message->body, real->message->byte_order,
+ pos, NULL, value, len))
+ return FALSE;
+ else
+ return TRUE;
+}
+
+/**
+ * Returns the boolean array that the iterator may point to. Note that
+ * you need to check that the iterator points to an array of the
+ * correct type prior to using this function.
+ *
+ * @param iter the iterator
+ * @param value return location for the array
+ * @param len return location for the array length
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_get_boolean_array (DBusMessageIter *iter,
+ unsigned char **value,
+ int *len)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ int type, pos;
+
+ _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
+
+ pos = dbus_message_iter_get_data_start (real, &type);
+
+ _dbus_assert (type == DBUS_TYPE_ARRAY);
+
+ type = iter_get_array_type (real, NULL);
+
+ _dbus_assert (type == DBUS_TYPE_BOOLEAN);
+
+ if (!_dbus_demarshal_byte_array (&real->message->body, real->message->byte_order,
+ pos, NULL, value, len))
+ return FALSE;
+ else
+ return TRUE;
+}
+
+/**
+ * Returns the 32 bit signed integer array that the iterator may point
+ * to. Note that you need to check that the iterator points to an
+ * array of the correct type prior to using this function.
+ *
+ * @param iter the iterator
+ * @param value return location for the array
+ * @param len return location for the array length
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_get_int32_array (DBusMessageIter *iter,
+ dbus_int32_t **value,
+ int *len)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ int type, pos;
+
+ _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
+
+ pos = dbus_message_iter_get_data_start (real, &type);
+
+ _dbus_assert (type == DBUS_TYPE_ARRAY);
+
+ type = iter_get_array_type (real, NULL);
+
+ _dbus_assert (type == DBUS_TYPE_INT32);
+
+ if (!_dbus_demarshal_int32_array (&real->message->body, real->message->byte_order,
+ pos, NULL, value, len))
+ return FALSE;
+ else
+ return TRUE;
+}
+
+/**
+ * Returns the 32 bit unsigned integer array that the iterator may point
+ * to. Note that you need to check that the iterator points to an
+ * array of the correct type prior to using this function.
+ *
+ * @param iter the iterator
+ * @param value return location for the array
+ * @param len return location for the array length
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_get_uint32_array (DBusMessageIter *iter,
+ dbus_uint32_t **value,
+ int *len)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ int type, pos;
+
+ _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
+
+ pos = dbus_message_iter_get_data_start (real, &type);
+
+ _dbus_assert (type == DBUS_TYPE_ARRAY);
+
+ type = iter_get_array_type (real, NULL);
+ _dbus_assert (type == DBUS_TYPE_UINT32);
+
+ if (!_dbus_demarshal_uint32_array (&real->message->body, real->message->byte_order,
+ pos, NULL, value, len))
+ return FALSE;
+ else
+ return TRUE;
+}
+
+#ifdef DBUS_HAVE_INT64
+
+/**
+ * Returns the 64 bit signed integer array that the iterator may point
+ * to. Note that you need to check that the iterator points to an
+ * array of the correct type prior to using this function.
+ *
+ * This function only exists if #DBUS_HAVE_INT64 is defined.
+ *
+ * @param iter the iterator
+ * @param value return location for the array
+ * @param len return location for the array length
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_get_int64_array (DBusMessageIter *iter,
+ dbus_int64_t **value,
+ int *len)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ int type, pos;
+
+ _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
+
+ pos = dbus_message_iter_get_data_start (real, &type);
+
+ _dbus_assert (type == DBUS_TYPE_ARRAY);
+
+ type = iter_get_array_type (real, NULL);
+
+ _dbus_assert (type == DBUS_TYPE_INT64);
+
+ if (!_dbus_demarshal_int64_array (&real->message->body, real->message->byte_order,
+ pos, NULL, value, len))
+ return FALSE;
+ else
+ return TRUE;
+}
+
+/**
+ * Returns the 64 bit unsigned integer array that the iterator may point
+ * to. Note that you need to check that the iterator points to an
+ * array of the correct type prior to using this function.
+ *
+ * This function only exists if #DBUS_HAVE_INT64 is defined.
+ *
+ * @param iter the iterator
+ * @param value return location for the array
+ * @param len return location for the array length
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_get_uint64_array (DBusMessageIter *iter,
+ dbus_uint64_t **value,
+ int *len)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ int type, pos;
+
+ _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
+
+ pos = dbus_message_iter_get_data_start (real, &type);
+
+ _dbus_assert (type == DBUS_TYPE_ARRAY);
+
+ type = iter_get_array_type (real, NULL);
+ _dbus_assert (type == DBUS_TYPE_UINT64);
+
+ if (!_dbus_demarshal_uint64_array (&real->message->body, real->message->byte_order,
+ pos, NULL, value, len))
+ return FALSE;
+ else
+ return TRUE;
+}
+
+#endif /* DBUS_HAVE_INT64 */
+
+/**
+ * Returns the double array that the iterator may point to. Note that
+ * you need to check that the iterator points to an array of the
+ * correct type prior to using this function.
+ *
+ * @param iter the iterator
+ * @param value return location for the array
+ * @param len return location for the array length
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_get_double_array (DBusMessageIter *iter,
+ double **value,
+ int *len)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ int type, pos;
+
+ _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
+
+ pos = dbus_message_iter_get_data_start (real, &type);
+
+ _dbus_assert (type == DBUS_TYPE_ARRAY);
+
+ type = iter_get_array_type (real, NULL);
+ _dbus_assert (type == DBUS_TYPE_DOUBLE);
+
+ if (!_dbus_demarshal_double_array (&real->message->body, real->message->byte_order,
+ pos, NULL, value, len))
+ return FALSE;
+ else
+ return TRUE;
+}
+
+/**
+ * Returns the string array that the iterator may point to.
+ * Note that you need to check that the iterator points
+ * to a string array prior to using this function.
+ *
+ * The returned value is a #NULL-terminated array of strings.
+ * Each string is a separate malloc block, and the array
+ * itself is a malloc block. You can free this type of
+ * string array with dbus_free_string_array().
+ *
+ * @param iter the iterator
+ * @param value return location for string values
+ * @param len return location for length of byte array
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_get_string_array (DBusMessageIter *iter,
+ char ***value,
+ int *len)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ int type, pos;
+
+ _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
+
+ pos = dbus_message_iter_get_data_start (real, &type);
+
+ _dbus_assert (type == DBUS_TYPE_ARRAY);
+
+ type = iter_get_array_type (real, NULL);
+ _dbus_assert (type == DBUS_TYPE_STRING);
+
+ if (!_dbus_demarshal_string_array (&real->message->body, real->message->byte_order,
+ pos, NULL, value, len))
+ return FALSE;
+ else
+ return TRUE;
+}
+
+#if 0
+/**
+ * @todo FIXME to implement this _dbus_demarshal_object_path_array()
+ * needs implementing
+ *
+ * Returns the object path array that the iterator may point to.
+ * Note that you need to check that the iterator points
+ * to an object path array prior to using this function.
+ *
+ * The returned value is a #NULL-terminated array of strings.
+ * Each string is a separate malloc block, and the array
+ * itself is a malloc block. You can free this type of
+ * array with dbus_free_string_array().
+ *
+ * @param iter the iterator
+ * @param value return location for string values
+ * @param len return location for length of byte array
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_get_object_path_array (DBusMessageIter *iter,
+ char ***value,
+ int *len)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ int type, pos;
+
+ _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
+
+ pos = dbus_message_iter_get_data_start (real, &type);
+
+ _dbus_assert (type == DBUS_TYPE_ARRAY);
+
+ type = iter_get_array_type (real, NULL);
+ _dbus_assert (type == DBUS_TYPE_OBJECT_PATH);
+
+ if (!_dbus_demarshal_object_path_array (&real->message->body, real->message->byte_order,
+ pos, NULL, value, len))
+ return FALSE;
+ else
+ return TRUE;
+}
+#endif
+
+/**
+ * Returns the key name fot the dict entry that an iterator
+ * may point to. Note that you need to check that the iterator
+ * points to a dict entry before using this function.
+ *
+ * @see dbus_message_iter_init_dict_iterator
+ * @param iter the message iter
+ * @returns the key name
+ */
+char *
+dbus_message_iter_get_dict_key (DBusMessageIter *iter)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ _dbus_return_val_if_fail (dbus_message_iter_check (real), NULL);
+
+ _dbus_assert (real->type == DBUS_MESSAGE_ITER_TYPE_DICT);
+
+ return _dbus_demarshal_string (&real->message->body, real->message->byte_order,
+ real->pos, NULL);
+}
+
+/**
+ * Initializes a DBusMessageIter pointing to the end of the
+ * message. This iterator can be used to append data to the
+ * message.
+ *
+ * @param message the message
+ * @param iter pointer to an iterator to initialize
+ */
+void
+dbus_message_append_iter_init (DBusMessage *message,
+ DBusMessageIter *iter)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ _dbus_return_if_fail (message != NULL);
+ _dbus_return_if_fail (iter != NULL);
+
+ real->message = message;
+ real->parent_iter = NULL;
+ real->changed_stamp = message->changed_stamp;
+
+ real->type = DBUS_MESSAGE_ITER_TYPE_MESSAGE;
+ real->end = _dbus_string_get_length (&real->message->body);
+ real->pos = real->end;
+
+ real->container_length_pos = 0;
+ real->wrote_dict_key = 0;
+}
+
+#ifndef DBUS_DISABLE_CHECKS
+static dbus_bool_t
+dbus_message_iter_append_check (DBusMessageRealIter *iter)
+{
+ if (iter == NULL)
+ {
+ _dbus_warn ("dbus iterator check failed: NULL iterator\n");
+ return FALSE;
+ }
+
+ if (iter->message->locked)
+ {
+ _dbus_warn ("dbus iterator check failed: message is locked (has already been sent)\n");
+ return FALSE;
+ }
+
+ if (iter->changed_stamp != iter->message->changed_stamp)
+ {
+ _dbus_warn ("dbus iterator check failed: invalid iterator, must re-initialize it after modifying the message");
+ return FALSE;
+ }
+
+ if (iter->pos != iter->end)
+ {
+ _dbus_warn ("dbus iterator check failed: can only append at end of message");
+ return FALSE;
+ }
+
+ if (iter->pos != _dbus_string_get_length (&iter->message->body))
+ {
+ _dbus_warn ("dbus iterator check failed: append pos not at end of message string");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+#endif /* DBUS_DISABLE_CHECKS */
+
+static dbus_bool_t
+dbus_message_iter_append_type (DBusMessageRealIter *iter,
+ int type)
+{
+ const char *data;
+ switch (iter->type)
+ {
+ case DBUS_MESSAGE_ITER_TYPE_MESSAGE:
+ if (!_dbus_string_append_byte (&iter->message->signature, type))
+ return FALSE;
+
+ if (!_dbus_string_append_byte (&iter->message->body, type))
+ {
+ _dbus_string_shorten (&iter->message->signature, 1);
+ return FALSE;
+ }
+ break;
+
+ case DBUS_MESSAGE_ITER_TYPE_ARRAY:
+ data = _dbus_string_get_const_data_len (&iter->message->body,
+ iter->array_type_pos, 1);
+ if (type != *data)
+ {
+ _dbus_warn ("Appended element of wrong type for array\n");
+ return FALSE;
+ }
+ break;
+
+ case DBUS_MESSAGE_ITER_TYPE_DICT:
+ if (!iter->wrote_dict_key)
+ {
+ _dbus_warn ("Appending dict data before key name\n");
+ return FALSE;
+ }
+
+ if (!_dbus_string_append_byte (&iter->message->body, type))
+ return FALSE;
+
+ break;
+
+ default:
+ _dbus_assert_not_reached ("Invalid iter type");
+ break;
+ }
+
+ return TRUE;
+}
+
+static void
+dbus_message_iter_update_after_change (DBusMessageRealIter *iter)
+{
+ iter->changed_stamp = iter->message->changed_stamp;
+
+ /* Set new end of iter */
+ iter->end = _dbus_string_get_length (&iter->message->body);
+ iter->pos = iter->end;
+
+ /* Set container length */
+ if (iter->type == DBUS_MESSAGE_ITER_TYPE_DICT ||
+ (iter->type == DBUS_MESSAGE_ITER_TYPE_ARRAY && iter->array_type_done))
+ _dbus_marshal_set_uint32 (&iter->message->body,
+ iter->message->byte_order,
+ iter->container_length_pos,
+ iter->end - iter->container_start);
+
+ if (iter->parent_iter)
+ dbus_message_iter_update_after_change (iter->parent_iter);
+}
+
+static void
+dbus_message_iter_append_done (DBusMessageRealIter *iter)
+{
+ iter->message->changed_stamp++;
+ dbus_message_iter_update_after_change (iter);
+ iter->wrote_dict_key = FALSE;
+}
+
+/**
+ * Appends a nil value to the message
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_nil (DBusMessageIter *iter)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
+
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_NIL))
+ return FALSE;
+
+ dbus_message_iter_append_done (real);
+
+ return TRUE;
+}
+
+/**
+ * Appends a boolean value to the message
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param value the boolean value
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_boolean (DBusMessageIter *iter,
+ dbus_bool_t value)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
+
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_BOOLEAN))
+ return FALSE;
+
+ if (!_dbus_string_append_byte (&real->message->body, (value != FALSE)))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ dbus_message_iter_append_done (real);
+
+ return TRUE;
+}
+
+/**
+ * Appends a byte to the message
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param value the byte value
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_byte (DBusMessageIter *iter,
+ unsigned char value)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
+
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_BYTE))
+ return FALSE;
+
+ if (!_dbus_string_append_byte (&real->message->body, value))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ dbus_message_iter_append_done (real);
+
+ return TRUE;
+}
+
+
+/**
+ * Appends a 32 bit signed integer to the message.
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param value the integer value
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_int32 (DBusMessageIter *iter,
+ dbus_int32_t value)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
+
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_INT32))
+ return FALSE;
+
+ if (!_dbus_marshal_int32 (&real->message->body, real->message->byte_order, value))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ dbus_message_iter_append_done (real);
+
+ return TRUE;
+}
+
+/**
+ * Appends a 32 bit unsigned integer to the message.
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param value the integer value
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_uint32 (DBusMessageIter *iter,
+ dbus_uint32_t value)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
+
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_UINT32))
+ return FALSE;
+
+ if (!_dbus_marshal_uint32 (&real->message->body, real->message->byte_order, value))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ dbus_message_iter_append_done (real);
+
+ return TRUE;
+}
+
+#ifdef DBUS_HAVE_INT64
+
+/**
+ * Appends a 64 bit signed integer to the message.
+ *
+ * This function only exists if #DBUS_HAVE_INT64 is defined.
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param value the integer value
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_int64 (DBusMessageIter *iter,
+ dbus_int64_t value)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
+
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_INT64))
+ return FALSE;
+
+ if (!_dbus_marshal_int64 (&real->message->body, real->message->byte_order, value))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ dbus_message_iter_append_done (real);
+
+ return TRUE;
+}
+
+/**
+ * Appends a 64 bit unsigned integer to the message.
+ *
+ * This function only exists if #DBUS_HAVE_INT64 is defined.
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param value the integer value
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_uint64 (DBusMessageIter *iter,
+ dbus_uint64_t value)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
+
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_UINT64))
+ return FALSE;
+
+ if (!_dbus_marshal_uint64 (&real->message->body, real->message->byte_order, value))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ dbus_message_iter_append_done (real);
+
+ return TRUE;
+}
+
+#endif /* DBUS_HAVE_INT64 */
+
+/**
+ * Appends a double value to the message.
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param value the double value
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_double (DBusMessageIter *iter,
+ double value)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
+
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_DOUBLE))
+ return FALSE;
+
+ if (!_dbus_marshal_double (&real->message->body, real->message->byte_order, value))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ dbus_message_iter_append_done (real);
+
+ return TRUE;
+}
+
+/**
+ * Appends a UTF-8 string to the message.
+ *
+ * @todo add return_val_if_fail(UTF-8 is valid)
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param value the string
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_string (DBusMessageIter *iter,
+ const char *value)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
+
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_STRING))
+ return FALSE;
+
+ if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, value))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ dbus_message_iter_append_done (real);
+
+ return TRUE;
+}
+
+/**
+ * Appends a custom type data chunk to the message. A custom
+ * type is simply an arbitrary UTF-8 string used as a type
+ * tag, plus an array of arbitrary bytes to be interpreted
+ * according to the type tag.
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param name the name of the type
+ * @param data the binary data used to store the value
+ * @param len the length of the binary data in bytes
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_custom (DBusMessageIter *iter,
+ const char *name,
+ const unsigned char *data,
+ int len)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
+
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_CUSTOM))
+ return FALSE;
+
+ if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, name))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ if (!_dbus_marshal_byte_array (&real->message->body, real->message->byte_order, data, len))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ dbus_message_iter_append_done (real);
+
+ return TRUE;
+}
+
+
+/**
+ * Appends a dict key name to the message. The iterator used
+ * must point to a dict.
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param value the string
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_dict_key (DBusMessageIter *iter,
+ const char *value)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
+ _dbus_assert (real->type == DBUS_MESSAGE_ITER_TYPE_DICT);
+
+ if (real->wrote_dict_key)
+ {
+ _dbus_warn ("Appending multiple dict key names\n");
+ return FALSE;
+ }
+
+ if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, value))
+ {
+ return FALSE;
+ }
+
+ dbus_message_iter_append_done (real);
+ real->wrote_dict_key = TRUE;
+
+ return TRUE;
+}
+
+static dbus_bool_t
+array_iter_type_mark_done (DBusMessageRealIter *iter)
+{
+ int len_pos;
+
+ if (iter->type == DBUS_MESSAGE_ITER_TYPE_ARRAY)
+ array_iter_type_mark_done (iter->parent_iter);
+ else
+ return TRUE;
+
+ len_pos = _DBUS_ALIGN_VALUE (_dbus_string_get_length (&iter->message->body),
+ sizeof (dbus_uint32_t));
+
+ /* Empty length for now, backfill later */
+ if (!_dbus_marshal_uint32 (&iter->message->body, iter->message->byte_order, 0))
+ {
+ _dbus_string_set_length (&iter->message->body, iter->pos);
+ return FALSE;
+ }
+
+ iter->container_start = _dbus_string_get_length (&iter->message->body);
+ iter->container_length_pos = len_pos;
+ iter->array_type_done = TRUE;
+
+ return TRUE;
+}
+
+static dbus_bool_t
+append_array_type (DBusMessageRealIter *real,
+ int element_type,
+ dbus_bool_t *array_type_done,
+ int *array_type_pos)
+{
+ int existing_element_type;
+
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_ARRAY))
+ return FALSE;
+
+ if (real->type == DBUS_MESSAGE_ITER_TYPE_ARRAY &&
+ real->array_type_done)
+ {
+ existing_element_type = iter_get_array_type (real, array_type_pos);
+ if (existing_element_type != element_type)
+ {
+ _dbus_warn ("Appending array of %s, when expecting array of %s\n",
+ _dbus_type_to_string (element_type),
+ _dbus_type_to_string (existing_element_type));
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+ if (array_type_done != NULL)
+ *array_type_done = TRUE;
+ }
+ else
+ {
+ if (array_type_pos != NULL)
+ *array_type_pos = _dbus_string_get_length (&real->message->body);
+
+
+ if (!_dbus_string_append_byte (&real->message->signature, element_type))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ /* Append element type */
+ if (!_dbus_string_append_byte (&real->message->body, element_type))
+ {
+ _dbus_string_shorten (&real->message->signature, 1);
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ if (array_type_done != NULL)
+ *array_type_done = element_type != DBUS_TYPE_ARRAY;
+
+ if (element_type != DBUS_TYPE_ARRAY &&
+ !array_iter_type_mark_done (real))
+ {
+ _dbus_string_shorten (&real->message->signature, 1);
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+/**
+ * Appends an array to the message and initializes an iterator that
+ * can be used to append to the array.
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param array_iter pointer to an iter that will be initialized
+ * @param element_type the type of the array elements
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_array (DBusMessageIter *iter,
+ DBusMessageIter *array_iter,
+ int element_type)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ DBusMessageRealIter *array_real = (DBusMessageRealIter *)array_iter;
+ int len_pos;
+ int array_type_pos;
+ dbus_bool_t array_type_done;
+
+ if (element_type == DBUS_TYPE_NIL)
+ {
+ _dbus_warn ("Can't create NIL arrays\n");
+ return FALSE;
+ }
+
+ _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
+
+ if (!append_array_type (real, element_type, &array_type_done, &array_type_pos))
+ return FALSE;
+
+ len_pos = _DBUS_ALIGN_VALUE (_dbus_string_get_length (&real->message->body), sizeof (dbus_uint32_t));
+
+ if (array_type_done)
+ {
+ /* Empty length for now, backfill later */
+ if (!_dbus_marshal_uint32 (&real->message->body, real->message->byte_order, 0))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+ }
+
+ array_real->parent_iter = real;
+ array_real->message = real->message;
+ array_real->changed_stamp = real->message->changed_stamp;
+
+ array_real->type = DBUS_MESSAGE_ITER_TYPE_ARRAY;
+ array_real->pos = _dbus_string_get_length (&real->message->body);
+ array_real->end = array_real->end;
+
+ array_real->container_start = array_real->pos;
+ array_real->container_length_pos = len_pos;
+ array_real->wrote_dict_key = 0;
+ array_real->array_type_done = array_type_done;
+ array_real->array_type_pos = array_type_pos;
+
+ dbus_message_iter_append_done (array_real);
+
+ return TRUE;
+}
+
+/**
+ * Appends a dict to the message and initializes an iterator that
+ * can be used to append to the dict.
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param dict_iter pointer to an iter that will be initialized
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_dict (DBusMessageIter *iter,
+ DBusMessageIter *dict_iter)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ DBusMessageRealIter *dict_real = (DBusMessageRealIter *)dict_iter;
+ int len_pos;
+
+ _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
+
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_DICT))
+ return FALSE;
+
+ len_pos = _DBUS_ALIGN_VALUE (_dbus_string_get_length (&real->message->body), sizeof (dbus_uint32_t));
+
+ /* Empty length for now, backfill later */
+ if (!_dbus_marshal_uint32 (&real->message->body, real->message->byte_order, 0))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ dict_real->parent_iter = real;
+ dict_real->message = real->message;
+ dict_real->changed_stamp = real->message->changed_stamp;
+
+ dict_real->type = DBUS_MESSAGE_ITER_TYPE_DICT;
+ dict_real->pos = _dbus_string_get_length (&real->message->body);
+ dict_real->end = dict_real->end;
+
+ dict_real->container_start = dict_real->pos;
+ dict_real->container_length_pos = len_pos;
+ dict_real->wrote_dict_key = 0;
+
+ dbus_message_iter_append_done (dict_real);
+
+ real->wrote_dict_key = FALSE;
+
+ return TRUE;
+}
+
+
+/**
+ * Appends a boolean array to the message.
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param value the array
+ * @param len the length of the array
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_boolean_array (DBusMessageIter *iter,
+ unsigned const char *value,
+ int len)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
+
+ if (!append_array_type (real, DBUS_TYPE_BOOLEAN, NULL, NULL))
+ return FALSE;
+
+ if (!_dbus_marshal_byte_array (&real->message->body, real->message->byte_order, value, len))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ dbus_message_iter_append_done (real);
+
+ return TRUE;
+}
+
+/**
+ * Appends a 32 bit signed integer array to the message.
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param value the array
+ * @param len the length of the array
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_int32_array (DBusMessageIter *iter,
+ const dbus_int32_t *value,
+ int len)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
+
+ if (!append_array_type (real, DBUS_TYPE_INT32, NULL, NULL))
+ return FALSE;
+
+ if (!_dbus_marshal_int32_array (&real->message->body, real->message->byte_order, value, len))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ dbus_message_iter_append_done (real);
+
+ return TRUE;
+}
+
+/**
+ * Appends a 32 bit unsigned integer array to the message.
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param value the array
+ * @param len the length of the array
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_uint32_array (DBusMessageIter *iter,
+ const dbus_uint32_t *value,
+ int len)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
+
+ if (!append_array_type (real, DBUS_TYPE_UINT32, NULL, NULL))
+ return FALSE;
+
+ if (!_dbus_marshal_uint32_array (&real->message->body, real->message->byte_order, value, len))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ dbus_message_iter_append_done (real);
+
+ return TRUE;
+}
+
+#ifdef DBUS_HAVE_INT64
+
+/**
+ * Appends a 64 bit signed integer array to the message.
+ *
+ * This function only exists if #DBUS_HAVE_INT64 is defined.
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param value the array
+ * @param len the length of the array
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_int64_array (DBusMessageIter *iter,
+ const dbus_int64_t *value,
+ int len)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
+
+ if (!append_array_type (real, DBUS_TYPE_INT64, NULL, NULL))
+ return FALSE;
+
+ if (!_dbus_marshal_int64_array (&real->message->body, real->message->byte_order, value, len))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ dbus_message_iter_append_done (real);
+
+ return TRUE;
+}
+
+/**
+ * Appends a 64 bit unsigned integer array to the message.
+ *
+ * This function only exists if #DBUS_HAVE_INT64 is defined.
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param value the array
+ * @param len the length of the array
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_uint64_array (DBusMessageIter *iter,
+ const dbus_uint64_t *value,
+ int len)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
+
+ if (!append_array_type (real, DBUS_TYPE_UINT64, NULL, NULL))
+ return FALSE;
+
+ if (!_dbus_marshal_uint64_array (&real->message->body, real->message->byte_order, value, len))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ dbus_message_iter_append_done (real);
+
+ return TRUE;
+}
+#endif /* DBUS_HAVE_INT64 */
+
+/**
+ * Appends a double array to the message.
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param value the array
+ * @param len the length of the array
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_double_array (DBusMessageIter *iter,
+ const double *value,
+ int len)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
+
+ if (!append_array_type (real, DBUS_TYPE_DOUBLE, NULL, NULL))
+ return FALSE;
+
+ if (!_dbus_marshal_double_array (&real->message->body, real->message->byte_order, value, len))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ dbus_message_iter_append_done (real);
+
+ return TRUE;
+}
+
+/**
+ * Appends a byte array to the message.
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param value the array
+ * @param len the length of the array
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_byte_array (DBusMessageIter *iter,
+ unsigned const char *value,
+ int len)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
+
+ if (!append_array_type (real, DBUS_TYPE_BYTE, NULL, NULL))
+ return FALSE;
+
+ if (!_dbus_marshal_byte_array (&real->message->body, real->message->byte_order, value, len))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ dbus_message_iter_append_done (real);
+
+ return TRUE;
+}
+
+/**
+ * Appends a string array to the message.
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param value the array
+ * @param len the length of the array
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_string_array (DBusMessageIter *iter,
+ const char **value,
+ int len)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
+
+ if (!append_array_type (real, DBUS_TYPE_STRING, NULL, NULL))
+ return FALSE;
+
+ if (!_dbus_marshal_string_array (&real->message->body, real->message->byte_order, value, len))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ dbus_message_iter_append_done (real);
+
+ return TRUE;
+}
+
+/**
+ * Sets the message sender.
+ *
+ * @param message the message
+ * @param sender the sender
+ * @returns #FALSE if not enough memory
+ */
+dbus_bool_t
+dbus_message_set_sender (DBusMessage *message,
+ const char *sender)
+{
+ _dbus_return_val_if_fail (message != NULL, FALSE);
+ _dbus_return_val_if_fail (!message->locked, FALSE);
+
+ return set_string_field (message,
+ DBUS_HEADER_FIELD_SENDER_SERVICE,
+ DBUS_TYPE_STRING,
+ sender);
+}
+
+/**
+ * Sets a flag indicating that the message does not want a reply; if
+ * this flag is set, the other end of the connection may (but is not
+ * required to) optimize by not sending method return or error
+ * replies. If this flag is set, there is no way to know whether the
+ * message successfully arrived at the remote end.
+ *
+ * @param message the message
+ * @param no_reply #TRUE if no reply is desired
+ */
+void
+dbus_message_set_no_reply (DBusMessage *message,
+ dbus_bool_t no_reply)
+{
+ char *header;
+
+ _dbus_return_if_fail (message != NULL);
+ _dbus_return_if_fail (!message->locked);
+
+ header = _dbus_string_get_data_len (&message->header, FLAGS_OFFSET, 1);
+
+ if (no_reply)
+ *header |= DBUS_HEADER_FLAG_NO_REPLY_EXPECTED;
+ else
+ *header &= ~DBUS_HEADER_FLAG_NO_REPLY_EXPECTED;
+}
+
+/**
+ * Returns #TRUE if the message does not expect
+ * a reply.
+ *
+ * @param message the message
+ * @returns #TRUE if the message sender isn't waiting for a reply
+ */
+dbus_bool_t
+dbus_message_get_no_reply (DBusMessage *message)
+{
+ const char *header;
+
+ _dbus_return_val_if_fail (message != NULL, FALSE);
+
+ header = _dbus_string_get_const_data_len (&message->header, FLAGS_OFFSET, 1);
+
+ return (*header & DBUS_HEADER_FLAG_NO_REPLY_EXPECTED) != 0;
+}
+
+void
+dbus_message_set_auto_activation (DBusMessage *message,
+ dbus_bool_t auto_activation)
+{
+ char *header;
+
+ _dbus_return_if_fail (message != NULL);
+ _dbus_return_if_fail (!message->locked);
+
+ header = _dbus_string_get_data_len (&message->header, FLAGS_OFFSET, 1);
+
+ if (auto_activation)
+ *header |= DBUS_HEADER_FLAG_AUTO_ACTIVATION;
+ else
+ *header &= ~DBUS_HEADER_FLAG_AUTO_ACTIVATION;
+}
+
+dbus_bool_t
+dbus_message_get_auto_activation (DBusMessage *message)
+{
+ const char *header;
+
+ _dbus_return_val_if_fail (message != NULL, FALSE);
+
+ header = _dbus_string_get_const_data_len (&message->header, FLAGS_OFFSET, 1);
+
+ return (*header & DBUS_HEADER_FLAG_AUTO_ACTIVATION) != 0;
+}
+
+/**
+ * Gets the service which originated this message,
+ * or #NULL if unknown or inapplicable.
+ *
+ * @param message the message
+ * @returns the service name or #NULL
+ */
+const char*
+dbus_message_get_sender (DBusMessage *message)
+{
+ _dbus_return_val_if_fail (message != NULL, NULL);
+
+ return get_string_field (message,
+ DBUS_HEADER_FIELD_SENDER_SERVICE,
+ NULL);
+}
+
+/**
+ * Gets the type signature of the message, i.e. the arguments in the
+ * message payload. The signature includes only "in" arguments for
+ * #DBUS_MESSAGE_TYPE_METHOD_CALL and only "out" arguments for
+ * #DBUS_MESSAGE_TYPE_METHOD_RETURN, so is slightly different from
+ * what you might expect (it does not include the signature of the
+ * entire C++-style method).
+ *
+ * The signature is a string made up of type codes such
+ * as #DBUS_TYPE_STRING. The string is terminated with nul
+ * (nul is also the value of #DBUS_TYPE_INVALID).
+ *
+ * @param message the message
+ * @returns the type signature
+ */
+const char*
+dbus_message_get_signature (DBusMessage *message)
+{
+ _dbus_return_val_if_fail (message != NULL, NULL);
+
+ return _dbus_string_get_const_data (&message->signature);
+}
+
+static dbus_bool_t
+_dbus_message_has_type_interface_member (DBusMessage *message,
+ int type,
+ const char *interface,
+ const char *method)
+{
+ const char *n;
+
+ _dbus_assert (message != NULL);
+ _dbus_assert (interface != NULL);
+ _dbus_assert (method != NULL);
+
+ if (dbus_message_get_type (message) != type)
+ return FALSE;
+
+ /* Optimize by checking the short method name first
+ * instead of the longer interface name
+ */
+
+ n = dbus_message_get_member (message);
+
+ if (n && strcmp (n, method) == 0)
+ {
+ n = dbus_message_get_interface (message);
+
+ if (n && strcmp (n, interface) == 0)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ * Checks whether the message is a method call with the given
+ * interface and member fields. If the message is not
+ * #DBUS_MESSAGE_TYPE_METHOD_CALL, or has a different interface or member field,
+ * returns #FALSE.
+ *
+ * @param message the message
+ * @param interface the name to check (must not be #NULL)
+ * @param method the name to check (must not be #NULL)
+ *
+ * @returns #TRUE if the message is the specified method call
+ */
+dbus_bool_t
+dbus_message_is_method_call (DBusMessage *message,
+ const char *interface,
+ const char *method)
+{
+ _dbus_return_val_if_fail (message != NULL, FALSE);
+ _dbus_return_val_if_fail (interface != NULL, FALSE);
+ _dbus_return_val_if_fail (method != NULL, FALSE);
+
+ return _dbus_message_has_type_interface_member (message,
+ DBUS_MESSAGE_TYPE_METHOD_CALL,
+ interface, method);
+}
+
+/**
+ * Checks whether the message is a signal with the given
+ * interface and member fields. If the message is not
+ * #DBUS_MESSAGE_TYPE_SIGNAL, or has a different interface or member field,
+ * returns #FALSE.
+ *
+ * @param message the message
+ * @param interface the name to check (must not be #NULL)
+ * @param signal_name the name to check (must not be #NULL)
+ *
+ * @returns #TRUE if the message is the specified signal
+ */
+dbus_bool_t
+dbus_message_is_signal (DBusMessage *message,
+ const char *interface,
+ const char *signal_name)
+{
+ _dbus_return_val_if_fail (message != NULL, FALSE);
+ _dbus_return_val_if_fail (interface != NULL, FALSE);
+ _dbus_return_val_if_fail (signal_name != NULL, FALSE);
+
+ return _dbus_message_has_type_interface_member (message,
+ DBUS_MESSAGE_TYPE_SIGNAL,
+ interface, signal_name);
+}
+
+/**
+ * Checks whether the message is an error reply with the given error
+ * name. If the message is not #DBUS_MESSAGE_TYPE_ERROR, or has a
+ * different name, returns #FALSE.
+ *
+ * @param message the message
+ * @param error_name the name to check (must not be #NULL)
+ *
+ * @returns #TRUE if the message is the specified error
+ */
+dbus_bool_t
+dbus_message_is_error (DBusMessage *message,
+ const char *error_name)
+{
+ const char *n;
+
+ _dbus_return_val_if_fail (message != NULL, FALSE);
+ _dbus_return_val_if_fail (error_name != NULL, FALSE);
+
+ if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
+ return FALSE;
+
+ n = dbus_message_get_error_name (message);
+
+ if (n && strcmp (n, error_name) == 0)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+/**
+ * Checks whether the message was sent to the given service. If the
+ * message has no service specified or has a different name, returns
+ * #FALSE.
+ *
+ * @param message the message
+ * @param service the service to check (must not be #NULL)
+ *
+ * @returns #TRUE if the message has the given destination service
+ */
+dbus_bool_t
+dbus_message_has_destination (DBusMessage *message,
+ const char *service)
+{
+ const char *s;
+
+ _dbus_return_val_if_fail (message != NULL, FALSE);
+ _dbus_return_val_if_fail (service != NULL, FALSE);
+
+ s = dbus_message_get_destination (message);
+
+ if (s && strcmp (s, service) == 0)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+/**
+ * Checks whether the message has the given service as its sender. If
+ * the message has no sender specified or has a different sender,
+ * returns #FALSE. Note that if a peer application owns multiple
+ * services, its messages will have only one of those services as the
+ * sender (usually the base service). So you can't use this
+ * function to prove the sender didn't own service Foo, you can
+ * only use it to prove that it did.
+ *
+ * @param message the message
+ * @param service the service to check (must not be #NULL)
+ *
+ * @returns #TRUE if the message has the given origin service
+ */
+dbus_bool_t
+dbus_message_has_sender (DBusMessage *message,
+ const char *service)
+{
+ const char *s;
+
+ _dbus_return_val_if_fail (message != NULL, FALSE);
+ _dbus_return_val_if_fail (service != NULL, FALSE);
+
+ s = dbus_message_get_sender (message);
+
+ if (s && strcmp (s, service) == 0)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+/**
+ * Checks whether the message has the given signature;
+ * see dbus_message_get_signature() for more details on
+ * what the signature looks like.
+ *
+ * @param message the message
+ * @param signature typecode array
+ * @returns #TRUE if message has the given signature
+*/
+dbus_bool_t
+dbus_message_has_signature (DBusMessage *message,
+ const char *signature)
+{
+ _dbus_return_val_if_fail (message != NULL, FALSE);
+ _dbus_return_val_if_fail (signature != NULL, FALSE);
+
+ return _dbus_string_equal_c_str (&message->signature, signature);
+}
+
+/**
+ * Sets a #DBusError based on the contents of the given
+ * message. The error is only set if the message
+ * is an error message, as in DBUS_MESSAGE_TYPE_ERROR.
+ * The name of the error is set to the name of the message,
+ * and the error message is set to the first argument
+ * if the argument exists and is a string.
+ *
+ * The return value indicates whether the error was set (the error is
+ * set if and only if the message is an error message).
+ * So you can check for an error reply and convert it to DBusError
+ * in one go.
+ *
+ * @param error the error to set
+ * @param message the message to set it from
+ * @returns #TRUE if dbus_message_get_is_error() returns #TRUE for the message
+ */
+dbus_bool_t
+dbus_set_error_from_message (DBusError *error,
+ DBusMessage *message)
+{
+ char *str;
+
+ _dbus_return_val_if_fail (message != NULL, FALSE);
+ _dbus_return_val_if_error_is_set (error, FALSE);
+
+ if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
+ return FALSE;
+
+ str = NULL;
+ dbus_message_get_args (message, NULL,
+ DBUS_TYPE_STRING, &str,
+ DBUS_TYPE_INVALID);
+
+ dbus_set_error (error, dbus_message_get_error_name (message),
+ str ? "%s" : NULL, str);
+
+ dbus_free (str);
+
+ return TRUE;
+}
+
+/** @} */
+
+/**
+ * @addtogroup DBusMessageInternals
+ *
+ * @{
+ */
+/**
+ * @typedef DBusMessageLoader
+ *
+ * The DBusMessageLoader object encapsulates the process of converting
+ * a byte stream into a series of DBusMessage. It buffers the incoming
+ * bytes as efficiently as possible, and generates a queue of
+ * messages. DBusMessageLoader is typically used as part of a
+ * DBusTransport implementation. The DBusTransport then hands off
+ * the loaded messages to a DBusConnection, making the messages
+ * visible to the application.
+ *
+ * @todo write tests for break-loader that a) randomly delete header
+ * fields and b) set string fields to zero-length and other funky
+ * values.
+ *
+ */
+
+/* we definitely use signed ints for sizes, so don't exceed
+ * _DBUS_INT_MAX; and add 16 for paranoia, since a message
+ * over 128M is pretty nuts anyhow.
+ */
+
+/**
+ * The maximum sane message size.
+ */
+#define MAX_SANE_MESSAGE_SIZE (_DBUS_INT_MAX/16)
+
+/**
+ * Implementation details of DBusMessageLoader.
+ * All members are private.
+ */
+struct DBusMessageLoader
+{
+ int refcount; /**< Reference count. */
+
+ DBusString data; /**< Buffered data */
+
+ DBusList *messages; /**< Complete messages. */
+
+ long max_message_size; /**< Maximum size of a message */
+
+ unsigned int buffer_outstanding : 1; /**< Someone is using the buffer to read */
+
+ unsigned int corrupted : 1; /**< We got broken data, and are no longer working */
+};
+
+/**
+ * The initial buffer size of the message loader.
+ *
+ * @todo this should be based on min header size plus some average
+ * body size, or something. Or rather, the min header size only, if we
+ * want to try to read only the header, store that in a DBusMessage,
+ * then read only the body and store that, etc., depends on
+ * how we optimize _dbus_message_loader_get_buffer() and what
+ * the exact message format is.