* dbus/dbus-message.c: Message counter fix, patch by Christian Hammond <chipx86@gnupd...
[platform/upstream/dbus.git] / dbus / dbus-message.c
index 322e5d0..2e4c9b3 100644 (file)
@@ -1,7 +1,7 @@
 /* -*- mode: C; c-file-style: "gnu" -*- */
 /* dbus-message.c  DBusMessage object
  *
- * Copyright (C) 2002, 2003  Red Hat Inc.
+ * Copyright (C) 2002, 2003, 2004  Red Hat Inc.
  * Copyright (C) 2002, 2003  CodeFactory AB
  *
  * Licensed under the Academic Free License version 2.0
@@ -104,8 +104,6 @@ struct DBusMessage
   unsigned int locked : 1; /**< Message being sent, no modifications allowed. */
 
   DBusDataSlotList slot_list;   /**< Data stored by allocated integer ID */
-
-  DBusString signature; /**< Signature */
 };
 
 enum {
@@ -171,6 +169,23 @@ clear_header_padding (DBusMessage *message)
   message->header_padding = 0;
 }              
 
+#ifdef DBUS_DISABLE_CHECKS
+#define is_valid_error_name(x) TRUE
+#else
+static dbus_bool_t
+is_valid_error_name (const char *error_name)                                          
+{
+  DBusString the_error_name;
+
+  if (error_name == NULL)
+    return FALSE;
+  
+  _dbus_string_init_const (&the_error_name, error_name);
+  return _dbus_string_validate_error_name (&the_error_name, 0,   
+                                           _dbus_string_get_length (&the_error_name));
+}
+#endif
+
 static dbus_bool_t
 append_header_padding (DBusMessage *message)
 {
@@ -377,12 +392,17 @@ append_uint_field (DBusMessage *message,
   return FALSE;
 }
 
-#define MAX_BYTES_OVERHEAD_TO_APPEND_A_STRING (1 + 1 + 3 + 1 + 8)
+/** The maximum number of bytes of overhead to append to a string
+ * (fieldcode + typecode + alignment + length + nul + headerpadding)
+ */
+#define MAX_BYTES_OVERHEAD_TO_APPEND_A_STRING (1 + 1 + 3 + 4 + 1 + 8)
+
 static dbus_bool_t
-append_string_field (DBusMessage *message,
-                     int          field,
-                     int          type,
-                     const char  *value)
+append_string_field_len (DBusMessage *message,
+                         int          field,
+                         int          type,
+                         const char  *value,
+                         int          value_len)
 {
   _dbus_assert (!message->locked);
 
@@ -403,8 +423,8 @@ append_string_field (DBusMessage *message,
   message->header_fields[field].value_offset =
     _dbus_string_get_length (&message->header);
   
-  if (!_dbus_marshal_string (&message->header, message->byte_order,
-                             value))
+  if (!_dbus_marshal_string_len (&message->header, message->byte_order,
+                                 value, value_len))
     goto failed;
 
   if (!append_header_padding (message))
@@ -427,6 +447,19 @@ append_string_field (DBusMessage *message,
   return FALSE;
 }
 
+static dbus_bool_t
+append_string_field (DBusMessage *message,
+                     int          field,
+                     int          type,
+                     const char  *value)
+{
+  int value_len;
+
+  value_len = strlen (value);
+
+  return append_string_field_len (message, field, type, value, value_len);
+}
+
 static int
 get_type_alignment (int type)
 {
@@ -814,13 +847,16 @@ set_string_field (DBusMessage *message,
                   const char  *value)
 {
   int prealloc;
+  int value_len;
   
   _dbus_assert (!message->locked);
 
+  value_len = value ? strlen (value) : 0;
+  
   /* the prealloc is so the append_string_field()
    * below won't fail, leaving us in inconsistent state
    */
-  prealloc = (value ? strlen (value) : 0) + MAX_BYTES_OVERHEAD_TO_APPEND_A_STRING;
+  prealloc = value_len + MAX_BYTES_OVERHEAD_TO_APPEND_A_STRING;
 
   _dbus_verbose ("set_string_field() field %d prealloc %d\n",
                  field, prealloc);
@@ -831,7 +867,7 @@ set_string_field (DBusMessage *message,
   if (value != NULL)
     {
       /* need to append the field */
-      if (!append_string_field (message, field, type, value))
+      if (!append_string_field_len (message, field, type, value, value_len))
         _dbus_assert_not_reached ("Appending string field shouldn't have failed, due to preallocation");
     }
   
@@ -1003,7 +1039,7 @@ _dbus_message_remove_size_counter (DBusMessage  *message,
   else
     _dbus_list_free_link (link);
 
-  _dbus_counter_adjust (counter, message->size_counter_delta);
+  _dbus_counter_adjust (counter, message->size_counter_delta);
 
   _dbus_counter_unref (counter);
 }
@@ -1022,6 +1058,7 @@ dbus_message_create_header (DBusMessage *message,
   _dbus_assert ((interface && member) ||
                 (error_name) ||
                 !(interface || member || error_name));
+  _dbus_assert (error_name == NULL || is_valid_error_name (error_name));
   
   if (!_dbus_string_append_byte (&message->header, message->byte_order))
     return FALSE;
@@ -1062,7 +1099,7 @@ dbus_message_create_header (DBusMessage *message,
   if (service != NULL)
     {
       if (!append_string_field (message,
-                                DBUS_HEADER_FIELD_SERVICE,
+                                DBUS_HEADER_FIELD_DESTINATION,
                                DBUS_TYPE_STRING,
                                 service))
         return FALSE;
@@ -1094,6 +1131,15 @@ dbus_message_create_header (DBusMessage *message,
                                 error_name))
         return FALSE;
     }
+
+  /* @todo if we make signature optional when body is empty, we don't
+   * need to do this here.
+   */
+  if (!append_string_field (message,
+                            DBUS_HEADER_FIELD_SIGNATURE,
+                            DBUS_TYPE_STRING,
+                            ""))
+    return FALSE;
   
   return TRUE;
 }
@@ -1143,6 +1189,141 @@ _dbus_message_lock (DBusMessage  *message)
  */
 
 /**
+ * Sets the 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
+ * @param signature the type signature or #NULL to unset
+ * @returns #FALSE if no memory
+ */
+static dbus_bool_t
+dbus_message_set_signature (DBusMessage *message,
+                            const char  *signature)
+{
+  _dbus_return_val_if_fail (message != NULL, FALSE);
+  _dbus_return_val_if_fail (!message->locked, FALSE);
+  
+  return set_string_field (message,
+                           DBUS_HEADER_FIELD_SIGNATURE,
+                           DBUS_TYPE_STRING,
+                           signature);
+}
+
+/**
+ * Appends to the signature of the message.
+ * (currently a static function, maybe should be public?)
+ * 
+ * @param message the message
+ * @param append_bytes nul-terminated bytes to append to the type signature
+ * @returns #FALSE if no memory
+ */
+static dbus_bool_t
+dbus_message_append_to_signature (DBusMessage *message,
+                                  const char  *append_bytes)
+{
+  const char *signature;
+  DBusString append_str;
+  dbus_bool_t retval;
+  
+  _dbus_return_val_if_fail (append_bytes != NULL, FALSE);
+  _dbus_return_val_if_fail (message != NULL, FALSE);
+  _dbus_return_val_if_fail (!message->locked, FALSE);
+
+  retval = FALSE;
+  
+  /* FIXME Just really inefficient for the moment; later we could
+   * speed it up a lot by poking more directly at the header data
+   */
+  signature = dbus_message_get_signature (message);
+
+  if (!_dbus_string_init (&append_str))
+    return FALSE;
+
+  if (signature && !_dbus_string_append (&append_str, signature))
+    goto out;
+
+  if (!_dbus_string_append (&append_str, append_bytes))
+    goto out;
+  
+  if (!set_string_field (message,
+                         DBUS_HEADER_FIELD_SIGNATURE,
+                         DBUS_TYPE_STRING,
+                         _dbus_string_get_const_data (&append_str)))
+    goto out;
+
+  retval = TRUE;
+  
+ out:
+  
+  _dbus_string_free (&append_str);
+
+  return retval;
+}
+
+/**
+ * Appends one byte to the signature of the message.
+ * Internal function.
+ * 
+ * @param message the message
+ * @param append_byte the byte 
+ * @returns #FALSE if no memory
+ */
+static dbus_bool_t
+_dbus_message_append_byte_to_signature (DBusMessage  *message,
+                                        unsigned char append_byte)
+{
+  char buf[2];
+  
+  _dbus_return_val_if_fail (message != NULL, FALSE);
+  _dbus_return_val_if_fail (!message->locked, FALSE);
+  
+  buf[0] = append_byte;
+  buf[1] = '\0';
+
+  return dbus_message_append_to_signature (message, buf);
+}
+
+/**
+ * Removes the last byte from the signature of the message.
+ * Internal function.
+ * 
+ * @param message the message
+ */
+static void
+_dbus_message_remove_byte_from_signature (DBusMessage  *message)
+{
+  const char *signature;
+  
+  _dbus_return_if_fail (message != NULL);
+  _dbus_return_if_fail (!message->locked);
+
+  signature = dbus_message_get_signature (message);
+
+  _dbus_return_if_fail (signature != NULL);
+  
+  if (!delete_field (message,
+                     DBUS_HEADER_FIELD_SIGNATURE,
+                     0))
+    _dbus_assert_not_reached ("failed to delete signature field");
+
+  /* reappend one shorter (could this be any less efficient? the code will
+   * go away later anyhow)
+   */
+  if (!append_string_field_len (message, DBUS_HEADER_FIELD_SIGNATURE,
+                                DBUS_TYPE_STRING, signature,
+                                strlen (signature) - 1))
+    _dbus_assert_not_reached ("reappending shorter signature shouldn't have failed");
+}
+
+/**
  * @typedef DBusMessage
  *
  * Opaque data type representing a message received from or to be
@@ -1186,14 +1367,6 @@ dbus_message_new_empty_header (void)
       dbus_free (message);
       return NULL;
     }
-
-  if (!_dbus_string_init_preallocated (&message->signature, 4))
-    {
-      _dbus_string_free (&message->header);
-      _dbus_string_free (&message->body);
-      dbus_free (message);
-      return NULL;
-    }
   
   return message;
 }
@@ -1289,7 +1462,7 @@ dbus_message_new_method_return (DBusMessage *method_call)
   _dbus_return_val_if_fail (method_call != NULL, NULL);
   
   sender = get_string_field (method_call,
-                             DBUS_HEADER_FIELD_SENDER_SERVICE,
+                             DBUS_HEADER_FIELD_SENDER,
                             NULL);
   
   /* sender is allowed to be null here in peer-to-peer case */
@@ -1378,9 +1551,10 @@ dbus_message_new_error (DBusMessage *reply_to,
 
   _dbus_return_val_if_fail (reply_to != NULL, NULL);
   _dbus_return_val_if_fail (error_name != NULL, NULL);
+  _dbus_return_val_if_fail (is_valid_error_name (error_name), NULL);
   
   sender = get_string_field (reply_to,
-                             DBUS_HEADER_FIELD_SENDER_SERVICE,
+                             DBUS_HEADER_FIELD_SENDER,
                             NULL);
 
   /* sender may be NULL for non-message-bus case or
@@ -1441,6 +1615,10 @@ dbus_message_new_error_printf (DBusMessage *reply_to,
   DBusString str;
   DBusMessage *message;
 
+  _dbus_return_val_if_fail (reply_to != NULL, NULL);
+  _dbus_return_val_if_fail (error_name != NULL, NULL);
+  _dbus_return_val_if_fail (is_valid_error_name (error_name), NULL);
+  
   if (!_dbus_string_init (&str))
     return NULL;
 
@@ -1500,15 +1678,6 @@ dbus_message_copy (const DBusMessage *message)
       dbus_free (retval);
       return NULL;
     }
-
-  if (!_dbus_string_init_preallocated (&retval->signature,
-                                       _dbus_string_get_length (&message->signature)))
-    {
-      _dbus_string_free (&retval->header);
-      _dbus_string_free (&retval->body);
-      dbus_free (retval);
-      return NULL;
-    }
   
   if (!_dbus_string_copy (&message->header, 0,
                          &retval->header, 0))
@@ -1517,10 +1686,6 @@ dbus_message_copy (const DBusMessage *message)
   if (!_dbus_string_copy (&message->body, 0,
                          &retval->body, 0))
     goto failed_copy;
-
-  if (!_dbus_string_copy (&message->signature, 0,
-                         &retval->signature, 0))
-    goto failed_copy;
   
   for (i = 0; i <= DBUS_HEADER_FIELD_LAST; i++)
     {
@@ -1532,7 +1697,6 @@ dbus_message_copy (const DBusMessage *message)
  failed_copy:
   _dbus_string_free (&retval->header);
   _dbus_string_free (&retval->body);
-  _dbus_string_free (&retval->signature);
   dbus_free (retval);
   
   return NULL;  
@@ -1599,7 +1763,6 @@ dbus_message_unref (DBusMessage *message)
       
       _dbus_string_free (&message->header);
       _dbus_string_free (&message->body);
-      _dbus_string_free (&message->signature);
       
       dbus_free (message);
     }
@@ -1633,7 +1796,7 @@ dbus_message_get_type (DBusMessage *message)
  * emitted from (for DBUS_MESSAGE_TYPE_SIGNAL).
  *
  * @param message the message
- * @param object_path the path
+ * @param object_path the path or #NULL to unset
  * @returns #FALSE if not enough memory
  */
 dbus_bool_t
@@ -1699,7 +1862,7 @@ dbus_message_get_path_decomposed (DBusMessage   *message,
  * (for DBUS_MESSAGE_TYPE_SIGNAL).
  *
  * @param message the message
- * @param interface the interface
+ * @param interface the interface or #NULL to unset
  * @returns #FALSE if not enough memory
  */
 dbus_bool_t
@@ -1739,7 +1902,7 @@ dbus_message_get_interface (DBusMessage *message)
  * The interface name is fully-qualified (namespaced).
  *
  * @param message the message
- * @param member the member
+ * @param member the member or #NULL to unset
  * @returns #FALSE if not enough memory
  */
 dbus_bool_t
@@ -1778,7 +1941,7 @@ dbus_message_get_member (DBusMessage *message)
  * The name is fully-qualified (namespaced).
  *
  * @param message the message
- * @param error_name the name
+ * @param error_name the name or #NULL to unset
  * @returns #FALSE if not enough memory
  */
 dbus_bool_t
@@ -1787,7 +1950,8 @@ dbus_message_set_error_name (DBusMessage  *message,
 {
   _dbus_return_val_if_fail (message != NULL, FALSE);
   _dbus_return_val_if_fail (!message->locked, FALSE);
-
+  _dbus_return_val_if_fail (error_name == NULL || is_valid_error_name (error_name), FALSE);
+  
   return set_string_field (message,
                            DBUS_HEADER_FIELD_ERROR_NAME,
                            DBUS_TYPE_STRING,
@@ -1814,7 +1978,7 @@ dbus_message_get_error_name (DBusMessage *message)
  * Sets the message's destination service.
  *
  * @param message the message
- * @param destination the destination service name
+ * @param destination the destination service name or #NULL to unset
  * @returns #FALSE if not enough memory
  */
 dbus_bool_t
@@ -1825,7 +1989,7 @@ dbus_message_set_destination (DBusMessage  *message,
   _dbus_return_val_if_fail (!message->locked, FALSE);
 
   return set_string_field (message,
-                           DBUS_HEADER_FIELD_SERVICE,
+                           DBUS_HEADER_FIELD_DESTINATION,
                            DBUS_TYPE_STRING,
                            destination);
 }
@@ -1842,7 +2006,7 @@ dbus_message_get_destination (DBusMessage *message)
   _dbus_return_val_if_fail (message != NULL, NULL);
   
   return get_string_field (message,
-                          DBUS_HEADER_FIELD_SERVICE,
+                          DBUS_HEADER_FIELD_DESTINATION,
                           NULL);
 }
 
@@ -1884,537 +2048,110 @@ dbus_message_append_args (DBusMessage *message,
 }
 
 /**
- * This function takes a va_list for use by language bindings.
- * It's otherwise the same as dbus_message_append_args().
+ * 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
+ * stored. The list is terminated with #DBUS_TYPE_INVALID.
  *
- * @todo: Shouldn't this function clean up the changes to the message
- *        on failures? (Yes)
+ * @param message the message
+ * @param error error to be filled in on failure
+ * @param first_arg_type the first argument type
+ * @param ... location for first argument value, then list of type-location pairs
+ * @returns #FALSE if the error was set
+ */
+dbus_bool_t
+dbus_message_get_args (DBusMessage     *message,
+                       DBusError       *error,
+                      int              first_arg_type,
+                      ...)
+{
+  dbus_bool_t retval;
+  va_list var_args;
+
+  _dbus_return_val_if_fail (message != NULL, FALSE);
+  _dbus_return_val_if_error_is_set (error, FALSE);
   
- * @see dbus_message_append_args.  
+  va_start (var_args, first_arg_type);
+  retval = dbus_message_get_args_valist (message, error, first_arg_type, var_args);
+  va_end (var_args);
+
+  return retval;
+}
+
+/**
+ * This function takes a va_list for use by language bindings
+ *
+ * @todo We need to free the argument data when an error occurs.
+ *
+ * @see dbus_message_get_args
  * @param message the message
- * @param first_arg_type type of first argument
- * @param var_args value of first argument, then list of type/value pairs
- * @returns #TRUE on success
+ * @param error error to be filled in
+ * @param first_arg_type type of the first argument
+ * @param var_args return location for first argument, followed by list of type/location pairs
+ * @returns #FALSE if error was set
  */
 dbus_bool_t
-dbus_message_append_args_valist (DBusMessage *message,
-                                int          first_arg_type,
-                                va_list      var_args)
+dbus_message_get_args_valist (DBusMessage     *message,
+                              DBusError       *error,
+                             int              first_arg_type,
+                             va_list          var_args)
 {
-  int type, old_len;
   DBusMessageIter iter;
 
   _dbus_return_val_if_fail (message != NULL, FALSE);
+  _dbus_return_val_if_error_is_set (error, FALSE);
   
-  old_len = _dbus_string_get_length (&message->body);
+  dbus_message_iter_init (message, &iter);
+  return dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args);
+}
+
+/**
+ * Gets arguments from a message iterator 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
+ * stored. The list is terminated with 0.
+ *
+ * @param iter the message iterator 
+ * @param error error to be filled in on failure
+ * @param first_arg_type the first argument type
+ * @param ... location for first argument value, then list of type-location pairs
+ * @returns #FALSE if the error was set
+ */
+dbus_bool_t
+dbus_message_iter_get_args (DBusMessageIter *iter,
+                           DBusError       *error,
+                           int              first_arg_type,
+                           ...)
+{
+  dbus_bool_t retval;
+  va_list var_args;
+
+  _dbus_return_val_if_fail (iter != NULL, FALSE);
+  _dbus_return_val_if_error_is_set (error, FALSE);
   
-  type = first_arg_type;
+  va_start (var_args, first_arg_type);
+  retval = dbus_message_iter_get_args_valist (iter, error, first_arg_type, var_args);
+  va_end (var_args);
 
-  dbus_message_append_iter_init (message, &iter);
-  
-  while (type != DBUS_TYPE_INVALID)
-    {
-      switch (type)
-       {
-       case DBUS_TYPE_NIL:
-         if (!dbus_message_iter_append_nil (&iter))
-           goto errorout;
-         break;
-       case DBUS_TYPE_BYTE:
-         if (!dbus_message_iter_append_byte (&iter, va_arg (var_args, unsigned char)))
-           goto errorout;
-         break;
-       case DBUS_TYPE_BOOLEAN:
-         if (!dbus_message_iter_append_boolean (&iter, va_arg (var_args, dbus_bool_t)))
-           goto errorout;
-         break;
-       case DBUS_TYPE_INT32:
-         if (!dbus_message_iter_append_int32 (&iter, va_arg (var_args, dbus_int32_t)))
-           goto errorout;
-         break;
-       case DBUS_TYPE_UINT32:
-         if (!dbus_message_iter_append_uint32 (&iter, va_arg (var_args, dbus_uint32_t)))
-           goto errorout;          
-         break;
-#ifdef DBUS_HAVE_INT64
-        case DBUS_TYPE_INT64:
-         if (!dbus_message_iter_append_int64 (&iter, va_arg (var_args, dbus_int64_t)))
-           goto errorout;
-         break;
-       case DBUS_TYPE_UINT64:
-         if (!dbus_message_iter_append_uint64 (&iter, va_arg (var_args, dbus_uint64_t)))
-           goto errorout;          
-         break;
-#endif /* DBUS_HAVE_INT64 */
-       case DBUS_TYPE_DOUBLE:
-         if (!dbus_message_iter_append_double (&iter, va_arg (var_args, double)))
-           goto errorout;
-         break;
-       case DBUS_TYPE_STRING:
-         if (!dbus_message_iter_append_string (&iter, va_arg (var_args, const char *)))
-           goto errorout;
-         break;
-        case DBUS_TYPE_OBJECT_PATH:
-         if (!dbus_message_iter_append_object_path (&iter, va_arg (var_args, const char*)))
-           goto errorout;
-          break;
-       case DBUS_TYPE_CUSTOM:
-         {
-           const char *name;
-           unsigned char *data;
-           int len;
-           name = va_arg (var_args, const char *);
-           data = va_arg (var_args, unsigned char *);
-           len = va_arg (var_args, int);
-
-           if (!dbus_message_iter_append_custom (&iter, name, data, len))
-             goto errorout;
-           break;
-         }
-       case DBUS_TYPE_ARRAY:
-         {
-           void *data;
-           int len, type;
-           type = va_arg (var_args, int);
-           data = va_arg (var_args, void *);
-           len = va_arg (var_args, int);
-
-           switch (type)
-             {
-             case DBUS_TYPE_BYTE:
-               if (!dbus_message_iter_append_byte_array (&iter, (unsigned char *)data, len))
-                 goto errorout;
-               break;
-             case DBUS_TYPE_BOOLEAN:
-               if (!dbus_message_iter_append_boolean_array (&iter, (unsigned char *)data, len))
-                 goto errorout;
-               break;
-             case DBUS_TYPE_INT32:
-               if (!dbus_message_iter_append_int32_array (&iter, (dbus_int32_t *)data, len))
-                 goto errorout;
-               break;
-             case DBUS_TYPE_UINT32:
-               if (!dbus_message_iter_append_uint32_array (&iter, (dbus_uint32_t *)data, len))
-                 goto errorout;
-               break;
-#ifdef DBUS_HAVE_INT64
-              case DBUS_TYPE_INT64:
-               if (!dbus_message_iter_append_int64_array (&iter, (dbus_int64_t *)data, len))
-                 goto errorout;
-               break;
-             case DBUS_TYPE_UINT64:
-               if (!dbus_message_iter_append_uint64_array (&iter, (dbus_uint64_t *)data, len))
-                 goto errorout;
-               break;
-#endif /* DBUS_HAVE_INT64 */
-             case DBUS_TYPE_DOUBLE:
-               if (!dbus_message_iter_append_double_array (&iter, (double *)data, len))
-                 goto errorout;
-               break;
-             case DBUS_TYPE_STRING:
-               if (!dbus_message_iter_append_string_array (&iter, (const char **)data, len))
-                 goto errorout;
-               break;
-             case DBUS_TYPE_OBJECT_PATH:
-               if (!dbus_message_iter_append_object_path_array (&iter, (const char **)data, len))
-                 goto errorout;
-               break;
-             case DBUS_TYPE_NIL:
-             case DBUS_TYPE_ARRAY:
-             case DBUS_TYPE_CUSTOM:
-             case DBUS_TYPE_DICT:
-               _dbus_warn ("dbus_message_append_args_valist doesn't support recursive arrays\n");
-               goto errorout;
-             default:
-               _dbus_warn ("Unknown field type %d\n", type);
-               goto errorout;
-             }
-         }
-         break;
-         
-       case DBUS_TYPE_DICT:
-         _dbus_warn ("dbus_message_append_args_valist doesn't support dicts\n");
-         goto errorout;
-       default:
-         _dbus_warn ("Unknown field type %d\n", type);
-         goto errorout;
-       }
-
-      type = va_arg (var_args, int);
-    }
-
-  return TRUE;
-
- errorout:
-  return FALSE;
-}
-
-
-/**
- * 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
- * stored. The list is terminated with #DBUS_TYPE_INVALID.
- *
- * @param message the message
- * @param error error to be filled in on failure
- * @param first_arg_type the first argument type
- * @param ... location for first argument value, then list of type-location pairs
- * @returns #FALSE if the error was set
- */
-dbus_bool_t
-dbus_message_get_args (DBusMessage     *message,
-                       DBusError       *error,
-                      int              first_arg_type,
-                      ...)
-{
-  dbus_bool_t retval;
-  va_list var_args;
-
-  _dbus_return_val_if_fail (message != NULL, FALSE);
-  _dbus_return_val_if_error_is_set (error, FALSE);
-  
-  va_start (var_args, first_arg_type);
-  retval = dbus_message_get_args_valist (message, error, first_arg_type, var_args);
-  va_end (var_args);
-
-  return retval;
-}
-
-/**
- * This function takes a va_list for use by language bindings
- *
- * @todo We need to free the argument data when an error occurs.
- *
- * @see dbus_message_get_args
- * @param message the message
- * @param error error to be filled in
- * @param first_arg_type type of the first argument
- * @param var_args return location for first argument, followed by list of type/location pairs
- * @returns #FALSE if error was set
- */
-dbus_bool_t
-dbus_message_get_args_valist (DBusMessage     *message,
-                              DBusError       *error,
-                             int              first_arg_type,
-                             va_list          var_args)
-{
-  DBusMessageIter iter;
-
-  _dbus_return_val_if_fail (message != NULL, FALSE);
-  _dbus_return_val_if_error_is_set (error, FALSE);
-  
-  dbus_message_iter_init (message, &iter);
-  return dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args);
-}
-
-/**
- * Gets arguments from a message iterator 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
- * stored. The list is terminated with 0.
- *
- * @param iter the message iterator 
- * @param error error to be filled in on failure
- * @param first_arg_type the first argument type
- * @param ... location for first argument value, then list of type-location pairs
- * @returns #FALSE if the error was set
- */
-dbus_bool_t
-dbus_message_iter_get_args (DBusMessageIter *iter,
-                           DBusError       *error,
-                           int              first_arg_type,
-                           ...)
-{
-  dbus_bool_t retval;
-  va_list var_args;
-
-  _dbus_return_val_if_fail (iter != NULL, FALSE);
-  _dbus_return_val_if_error_is_set (error, FALSE);
-  
-  va_start (var_args, first_arg_type);
-  retval = dbus_message_iter_get_args_valist (iter, error, first_arg_type, var_args);
-  va_end (var_args);
-
-  return retval;
-}
-
-/**
- * This function takes a va_list for use by language bindings
- *
- * This function supports #DBUS_TYPE_INT64 and #DBUS_TYPE_UINT64
- * only if #DBUS_HAVE_INT64 is defined.
- *
- * @todo this function (or some lower-level non-convenience function)
- * needs better error handling; should allow the application to
- * distinguish between out of memory, and bad data from the remote
- * app. It also needs to not leak a bunch of args when it gets
- * to the arg that's bad, as that would be a security hole
- * (allow one app to force another to leak memory)
- *
- * @todo We need to free the argument data when an error occurs.
- *
- * @see dbus_message_get_args
- * @param iter the message iter
- * @param error error to be filled in
- * @param first_arg_type type of the first argument
- * @param var_args return location for first argument, followed by list of type/location pairs
- * @returns #FALSE if error was set
- */
-dbus_bool_t
-dbus_message_iter_get_args_valist (DBusMessageIter *iter,
-                                  DBusError       *error,
-                                  int              first_arg_type,
-                                  va_list          var_args)
-{
-  int spec_type, msg_type, i;
-  dbus_bool_t retval;
-
-  _dbus_return_val_if_fail (iter != NULL, FALSE);
-  _dbus_return_val_if_error_is_set (error, FALSE);
-
-  retval = FALSE;
-  
-  spec_type = first_arg_type;
-  i = 0;
-  
-  while (spec_type != 0)
-    {
-      msg_type = dbus_message_iter_get_arg_type (iter);      
-      
-      if (msg_type != spec_type)
-       {
-          dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
-                          "Argument %d is specified to be of type \"%s\", but "
-                          "is actually of type \"%s\"\n", i,
-                          _dbus_type_to_string (spec_type),
-                          _dbus_type_to_string (msg_type));
-
-          goto out;
-       }
-
-      switch (spec_type)
-       {
-       case DBUS_TYPE_NIL:
-         break;
-       case DBUS_TYPE_BYTE:
-         {
-           unsigned char *ptr;
-
-           ptr = va_arg (var_args, unsigned char *);
-
-           *ptr = dbus_message_iter_get_byte (iter);
-           break;
-         }
-       case DBUS_TYPE_BOOLEAN:
-         {
-           dbus_bool_t *ptr;
-
-           ptr = va_arg (var_args, dbus_bool_t *);
-
-           *ptr = dbus_message_iter_get_boolean (iter);
-           break;
-         }
-       case DBUS_TYPE_INT32:
-         {
-           dbus_int32_t *ptr;
-
-           ptr = va_arg (var_args, dbus_int32_t *);
-
-           *ptr = dbus_message_iter_get_int32 (iter);
-           break;
-         }
-       case DBUS_TYPE_UINT32:
-         {
-           dbus_uint32_t *ptr;
-
-           ptr = va_arg (var_args, dbus_uint32_t *);
-
-           *ptr = dbus_message_iter_get_uint32 (iter);
-           break;
-         }
-#ifdef DBUS_HAVE_INT64
-       case DBUS_TYPE_INT64:
-         {
-           dbus_int64_t *ptr;
-
-           ptr = va_arg (var_args, dbus_int64_t *);
-
-           *ptr = dbus_message_iter_get_int64 (iter);
-           break;
-         }
-       case DBUS_TYPE_UINT64:
-         {
-           dbus_uint64_t *ptr;
-
-           ptr = va_arg (var_args, dbus_uint64_t *);
-
-           *ptr = dbus_message_iter_get_uint64 (iter);
-           break;
-         }
-#endif /* DBUS_HAVE_INT64 */
-          
-       case DBUS_TYPE_DOUBLE:
-         {
-           double *ptr;
-
-           ptr = va_arg (var_args, double *);
-
-           *ptr = dbus_message_iter_get_double (iter);
-           break;
-         }
-
-       case DBUS_TYPE_STRING:
-         {
-           char **ptr;
-
-           ptr = va_arg (var_args, char **);
-
-           *ptr = dbus_message_iter_get_string (iter);
-
-           if (!*ptr)
-              {
-                dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
-                goto out;
-              }
-           
-           break;
-         }
-
-       case DBUS_TYPE_CUSTOM:
-         {
-           char **name;
-           unsigned char **data;
-           int *len;
-           name = va_arg (var_args, char **);
-           data = va_arg (var_args, unsigned char **);
-           len = va_arg (var_args, int *);
-
-           if (!dbus_message_iter_get_custom (iter, name, data, len))
-             {
-                dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
-               goto out;
-             }
-         }
-         break;
-       case DBUS_TYPE_ARRAY:
-         {
-           void **data;
-           int *len, type;
-           dbus_bool_t err = FALSE;
-           type = va_arg (var_args, int);
-           data = va_arg (var_args, void *);
-           len = va_arg (var_args, int *);
-
-            _dbus_return_val_if_fail (data != NULL, FALSE);
-            _dbus_return_val_if_fail (len != NULL, FALSE);
-            
-           if (dbus_message_iter_get_array_type (iter) != type)
-             {
-               dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
-                               "Argument %d is specified to be of type \"array of %s\", but "
-                               "is actually of type \"array of %s\"\n", i,
-                               _dbus_type_to_string (type),
-                               _dbus_type_to_string (dbus_message_iter_get_array_type (iter)));
-               goto out;
-             }
-           
-           switch (type)
-             {
-             case DBUS_TYPE_BYTE:
-               err = !dbus_message_iter_get_byte_array (iter, (unsigned char **)data, len);
-               break;
-             case DBUS_TYPE_BOOLEAN:
-               err = !dbus_message_iter_get_boolean_array (iter, (unsigned char **)data, len);
-               break;
-             case DBUS_TYPE_INT32:
-               err = !dbus_message_iter_get_int32_array (iter, (dbus_int32_t **)data, len);
-               break;
-             case DBUS_TYPE_UINT32:
-               err = !dbus_message_iter_get_uint32_array (iter, (dbus_uint32_t **)data, len);
-               break;
-#ifdef DBUS_HAVE_INT64
-              case DBUS_TYPE_INT64:
-               err = !dbus_message_iter_get_int64_array (iter, (dbus_int64_t **)data, len);
-               break;
-             case DBUS_TYPE_UINT64:
-               err = !dbus_message_iter_get_uint64_array (iter, (dbus_uint64_t **)data, len);
-               break;
-#endif /* DBUS_HAVE_INT64 */
-             case DBUS_TYPE_DOUBLE:
-               err = !dbus_message_iter_get_double_array (iter, (double **)data, len);
-               break;
-             case DBUS_TYPE_STRING:
-               err = !dbus_message_iter_get_string_array (iter, (char ***)data, len);
-               break;
-             case DBUS_TYPE_NIL:
-             case DBUS_TYPE_ARRAY:
-             case DBUS_TYPE_CUSTOM:
-             case DBUS_TYPE_DICT:
-               _dbus_warn ("dbus_message_get_args_valist doesn't support recursive arrays\n");
-               dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
-               goto out;
-             default:
-               _dbus_warn ("Unknown field type %d\n", type);
-               dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
-               goto out;
-             }
-           if (err)
-             {
-               dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
-               goto out;
-             }
-         }
-         break;
-       case DBUS_TYPE_DICT:
-         _dbus_warn ("dbus_message_get_args_valist doesn't support dicts\n");
-         dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
-         goto out;
-       default:          
-         dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
-         _dbus_warn ("Unknown field type %d\n", spec_type);
-         goto out;
-       }
-      
-      spec_type = va_arg (var_args, int);
-      if (spec_type != 0 && !dbus_message_iter_next (iter))
-        {
-          dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
-                          "Message has only %d arguments, but more were expected", i);
-          goto out;
-        }
-
-      i++;
-    }
-  
-  retval = TRUE;
-  
- out:
-  
-  return retval;
-}
-
-
-/**
- * Initializes a DBusMessageIter representing the arguments of the
- * message passed in.
- *
- * @param message the message
- * @param iter pointer to an iterator to initialize
- * @returns #FALSE if the message has no arguments
- */
-dbus_bool_t
-dbus_message_iter_init (DBusMessage     *message,
-                       DBusMessageIter *iter)
-{
-  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
-
-  _dbus_return_val_if_fail (message != NULL, FALSE);
-  _dbus_return_val_if_fail (iter != NULL, FALSE);
+  return retval;
+}
+
+/**
+ * Initializes a DBusMessageIter representing the arguments of the
+ * message passed in.
+ *
+ * @param message the message
+ * @param iter pointer to an iterator to initialize
+ * @returns #FALSE if the message has no arguments
+ */
+dbus_bool_t
+dbus_message_iter_init (DBusMessage     *message,
+                       DBusMessageIter *iter)
+{
+  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+  _dbus_return_val_if_fail (message != NULL, FALSE);
+  _dbus_return_val_if_fail (iter != NULL, FALSE);
   
   _dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
   
@@ -2764,28 +2501,283 @@ dbus_message_iter_get_custom (DBusMessageIter   *iter,
   int type, pos;
   char *_name;
 
-  _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
+  _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_CUSTOM);
+  
+  _name = _dbus_demarshal_string (&real->message->body, real->message->byte_order,
+                                 pos, &pos);
+
+  if (_name == NULL)
+    return FALSE;
+  
+  if (!_dbus_demarshal_byte_array (&real->message->body, real->message->byte_order,
+                                  pos, NULL, value, len))
+    {
+      dbus_free (_name);
+      return FALSE;
+    }
+
+  *name = _name;
+  
+  return TRUE;
+}
+
+static void
+_dbus_message_iter_get_basic_type (DBusMessageIter *iter,
+                                  char             type,
+                                  void            *value)
+{
+  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+  int item_type, pos;
+
+  _dbus_return_if_fail (dbus_message_iter_check (real));
+
+  pos = dbus_message_iter_get_data_start (real, &item_type);
+  
+  _dbus_assert (type == item_type);
+  
+  _dbus_demarshal_basic_type (&real->message->body,
+                             type, value,
+                             real->message->byte_order,
+                             &pos);
+}
+
+
+/**
+ * This function takes a va_list for use by language bindings
+ *
+ * This function supports #DBUS_TYPE_INT64 and #DBUS_TYPE_UINT64
+ * only if #DBUS_HAVE_INT64 is defined.
+ *
+ * @todo this function (or some lower-level non-convenience function)
+ * needs better error handling; should allow the application to
+ * distinguish between out of memory, and bad data from the remote
+ * app. It also needs to not leak a bunch of args when it gets
+ * to the arg that's bad, as that would be a security hole
+ * (allow one app to force another to leak memory)
+ *
+ * @todo We need to free the argument data when an error occurs.
+ *
+ * @see dbus_message_get_args
+ * @param iter the message iter
+ * @param error error to be filled in
+ * @param first_arg_type type of the first argument
+ * @param var_args return location for first argument, followed by list of type/location pairs
+ * @returns #FALSE if error was set
+ */
+dbus_bool_t
+dbus_message_iter_get_args_valist (DBusMessageIter *iter,
+                                  DBusError       *error,
+                                  int              first_arg_type,
+                                  va_list          var_args)
+{
+  int spec_type, msg_type, i;
+  dbus_bool_t retval;
+
+  _dbus_return_val_if_fail (iter != NULL, FALSE);
+  _dbus_return_val_if_error_is_set (error, FALSE);
+
+  retval = FALSE;
+  
+  spec_type = first_arg_type;
+  i = 0;
+  
+  while (spec_type != DBUS_TYPE_INVALID)
+    {
+      msg_type = dbus_message_iter_get_arg_type (iter);      
+      
+      if (msg_type != spec_type)
+       {
+          dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
+                          "Argument %d is specified to be of type \"%s\", but "
+                          "is actually of type \"%s\"\n", i,
+                          _dbus_type_to_string (spec_type),
+                          _dbus_type_to_string (msg_type));
+
+          goto out;
+       }
+
+      switch (spec_type)
+       {
+       case DBUS_TYPE_NIL:
+         break;
+       case DBUS_TYPE_BOOLEAN:
+         {
+           dbus_bool_t *ptr;
+
+           ptr = va_arg (var_args, dbus_bool_t *);
+
+           *ptr = dbus_message_iter_get_boolean (iter);
+           break;
+         }
+       case DBUS_TYPE_BYTE:
+       case DBUS_TYPE_INT32:
+       case DBUS_TYPE_UINT32:
+#ifdef DBUS_HAVE_INT64
+       case DBUS_TYPE_INT64:
+       case DBUS_TYPE_UINT64:
+#endif /* DBUS_HAVE_INT64 */
+       case DBUS_TYPE_DOUBLE:
+         {
+           void *ptr = va_arg (var_args, void *);
+           _dbus_message_iter_get_basic_type (iter, spec_type, ptr);
+           break;
+         }
+
+       case DBUS_TYPE_STRING:
+         {
+           char **ptr;
+
+           ptr = va_arg (var_args, char **);
+
+           *ptr = dbus_message_iter_get_string (iter);
+
+           if (!*ptr)
+              {
+                dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+                goto out;
+              }
+           
+           break;
+         }
+
+         case DBUS_TYPE_OBJECT_PATH:
+         {
+           char **ptr;
+
+           ptr = va_arg (var_args, char **);
+
+           *ptr = dbus_message_iter_get_object_path (iter);
+
+           if (!*ptr)
+             {
+               dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+               goto out;
+             }
+
+           break;
+         }
+
+       case DBUS_TYPE_CUSTOM:
+         {
+           char **name;
+           unsigned char **data;
+           int *len;
+           name = va_arg (var_args, char **);
+           data = va_arg (var_args, unsigned char **);
+           len = va_arg (var_args, int *);
+
+           if (!dbus_message_iter_get_custom (iter, name, data, len))
+             {
+                dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+               goto out;
+             }
+         }
+         break;
+       case DBUS_TYPE_ARRAY:
+         {
+           void **data;
+           int *len, type;
+           dbus_bool_t err = FALSE;
+           type = va_arg (var_args, int);
+           data = va_arg (var_args, void *);
+           len = va_arg (var_args, int *);
+
+            _dbus_return_val_if_fail (data != NULL, FALSE);
+            _dbus_return_val_if_fail (len != NULL, FALSE);
+            
+           if (dbus_message_iter_get_array_type (iter) != type)
+             {
+               dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
+                               "Argument %d is specified to be of type \"array of %s\", but "
+                               "is actually of type \"array of %s\"\n", i,
+                               _dbus_type_to_string (type),
+                               _dbus_type_to_string (dbus_message_iter_get_array_type (iter)));
+               goto out;
+             }
+           
+           switch (type)
+             {
+             case DBUS_TYPE_BYTE:
+               err = !dbus_message_iter_get_byte_array (iter, (unsigned char **)data, len);
+               break;
+             case DBUS_TYPE_BOOLEAN:
+               err = !dbus_message_iter_get_boolean_array (iter, (unsigned char **)data, len);
+               break;
+             case DBUS_TYPE_INT32:
+               err = !dbus_message_iter_get_int32_array (iter, (dbus_int32_t **)data, len);
+               break;
+             case DBUS_TYPE_UINT32:
+               err = !dbus_message_iter_get_uint32_array (iter, (dbus_uint32_t **)data, len);
+               break;
+#ifdef DBUS_HAVE_INT64
+              case DBUS_TYPE_INT64:
+               err = !dbus_message_iter_get_int64_array (iter, (dbus_int64_t **)data, len);
+               break;
+             case DBUS_TYPE_UINT64:
+               err = !dbus_message_iter_get_uint64_array (iter, (dbus_uint64_t **)data, len);
+               break;
+#endif /* DBUS_HAVE_INT64 */
+             case DBUS_TYPE_DOUBLE:
+               err = !dbus_message_iter_get_double_array (iter, (double **)data, len);
+               break;
+             case DBUS_TYPE_STRING:
+               err = !dbus_message_iter_get_string_array (iter, (char ***)data, len);
+               break;
+             case DBUS_TYPE_OBJECT_PATH:
+               err = !dbus_message_iter_get_object_path_array (iter, (char ***)data, len);
+               break;
+
+             case DBUS_TYPE_NIL:
+             case DBUS_TYPE_ARRAY:
+             case DBUS_TYPE_CUSTOM:
+             case DBUS_TYPE_DICT:
+               _dbus_warn ("dbus_message_get_args_valist doesn't support recursive arrays\n");
+               dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
+               goto out;
+             default:
+               _dbus_warn ("Unknown field type %d\n", type);
+               dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
+               goto out;
+             }
+           if (err)
+             {
+               dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+               goto out;
+             }
+         }
+         break;
+       case DBUS_TYPE_DICT:
+         _dbus_warn ("dbus_message_get_args_valist doesn't support dicts\n");
+         dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
+         goto out;
+       default:          
+         dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
+         _dbus_warn ("Unknown field type %d\n", spec_type);
+         goto out;
+       }
 
-  pos = dbus_message_iter_get_data_start (real, &type);
-  
-  _dbus_assert (type == DBUS_TYPE_CUSTOM);
-  
-  _name = _dbus_demarshal_string (&real->message->body, real->message->byte_order,
-                                 pos, &pos);
+      spec_type = va_arg (var_args, int);
+      if (!dbus_message_iter_next (iter) && spec_type != DBUS_TYPE_INVALID)
+        {
+          dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
+                          "Message has only %d arguments, but more were expected", i);
+          goto out;
+        }
 
-  if (_name == NULL)
-    return FALSE;
-  
-  if (!_dbus_demarshal_byte_array (&real->message->body, real->message->byte_order,
-                                  pos, NULL, value, len))
-    {
-      dbus_free (_name);
-      return FALSE;
+      i++;
     }
-
-  *name = _name;
   
-  return TRUE;
+  retval = TRUE;
+  
+ out:
+  
+  return retval;
 }
 
 /**
@@ -2800,22 +2792,13 @@ dbus_message_iter_get_custom (DBusMessageIter   *iter,
 unsigned char
 dbus_message_iter_get_byte (DBusMessageIter *iter)
 {
-  unsigned char value;
-  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
-  int type, pos;
-
-  _dbus_return_val_if_fail (dbus_message_iter_check (real), 0);
+  unsigned char value = 0;
 
-  pos = dbus_message_iter_get_data_start (real, &type);
-  
-  _dbus_assert (type == DBUS_TYPE_BYTE);
+  _dbus_message_iter_get_basic_type (iter, DBUS_TYPE_BYTE, &value);
 
-  value = _dbus_string_get_byte (&real->message->body, pos);
-  
   return value;
 }
 
-
 /**
  * Returns the boolean value that an iterator may point to.
  * Note that you need to check that the iterator points to
@@ -2828,19 +2811,11 @@ dbus_message_iter_get_byte (DBusMessageIter *iter)
 dbus_bool_t
 dbus_message_iter_get_boolean (DBusMessageIter *iter)
 {
-  unsigned char value;
-  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
-  int type, pos;
-
-  _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
+  unsigned char value = 0;
 
-  pos = dbus_message_iter_get_data_start (real, &type);
-  
-  _dbus_assert (type == DBUS_TYPE_BOOLEAN);
+  _dbus_message_iter_get_basic_type (iter, DBUS_TYPE_BOOLEAN, &value);
 
-  value = _dbus_string_get_byte (&real->message->body, pos);
-  
-  return value;
+  return (value != FALSE);
 }
 
 /**
@@ -2855,17 +2830,11 @@ dbus_message_iter_get_boolean (DBusMessageIter *iter)
 dbus_int32_t
 dbus_message_iter_get_int32 (DBusMessageIter *iter)
 {
-  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
-  int type, pos;
+  dbus_int32_t value = 0;
 
-  _dbus_return_val_if_fail (dbus_message_iter_check (real), 0);
+  _dbus_message_iter_get_basic_type (iter, DBUS_TYPE_INT32, &value);
 
-  pos = dbus_message_iter_get_data_start (real, &type);
-  
-  _dbus_assert (type == DBUS_TYPE_INT32);
-  
-  return _dbus_demarshal_int32 (&real->message->body, real->message->byte_order,
-                               pos, NULL);
+  return value;
 }
 
 /**
@@ -2880,17 +2849,11 @@ dbus_message_iter_get_int32 (DBusMessageIter *iter)
 dbus_uint32_t
 dbus_message_iter_get_uint32 (DBusMessageIter *iter)
 {
-  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
-  int type, pos;
+  dbus_int32_t value = 0;
 
-  _dbus_return_val_if_fail (dbus_message_iter_check (real), 0);
+  _dbus_message_iter_get_basic_type (iter, DBUS_TYPE_UINT32, &value);
 
-  pos = dbus_message_iter_get_data_start (real, &type);
-  
-  _dbus_assert (type == DBUS_TYPE_UINT32);
-  
-  return _dbus_demarshal_uint32 (&real->message->body, real->message->byte_order,
-                                pos, NULL);
+  return value;
 }
 
 #ifdef DBUS_HAVE_INT64
@@ -2909,17 +2872,11 @@ dbus_message_iter_get_uint32 (DBusMessageIter *iter)
 dbus_int64_t
 dbus_message_iter_get_int64 (DBusMessageIter *iter)
 {
-  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
-  int type, pos;
+  dbus_int64_t value = 0;
 
-  _dbus_return_val_if_fail (dbus_message_iter_check (real), 0);
+  _dbus_message_iter_get_basic_type (iter, DBUS_TYPE_INT64, &value);
 
-  pos = dbus_message_iter_get_data_start (real, &type);
-  
-  _dbus_assert (type == DBUS_TYPE_INT64);
-  
-  return _dbus_demarshal_int64 (&real->message->body, real->message->byte_order,
-                               pos, NULL);
+  return value;
 }
 
 /**
@@ -2936,17 +2893,11 @@ dbus_message_iter_get_int64 (DBusMessageIter *iter)
 dbus_uint64_t
 dbus_message_iter_get_uint64 (DBusMessageIter *iter)
 {
-  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
-  int type, pos;
+  dbus_uint64_t value = 0;
 
-  _dbus_return_val_if_fail (dbus_message_iter_check (real), 0);
+  _dbus_message_iter_get_basic_type (iter, DBUS_TYPE_UINT64, &value);
 
-  pos = dbus_message_iter_get_data_start (real, &type);
-  
-  _dbus_assert (type == DBUS_TYPE_UINT64);
-  
-  return _dbus_demarshal_uint64 (&real->message->body, real->message->byte_order,
-                                pos, NULL);
+  return value;
 }
 
 #endif /* DBUS_HAVE_INT64 */
@@ -2963,17 +2914,11 @@ dbus_message_iter_get_uint64 (DBusMessageIter *iter)
 double
 dbus_message_iter_get_double (DBusMessageIter *iter)
 {
-  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
-  int type, pos;
+  double value = 0.0;
 
-  _dbus_return_val_if_fail (dbus_message_iter_check (real), 0.0);
+  _dbus_message_iter_get_basic_type (iter, DBUS_TYPE_DOUBLE, &value);
 
-  pos = dbus_message_iter_get_data_start (real, &type);
-  
-  _dbus_assert (type == DBUS_TYPE_DOUBLE);
-  
-  return _dbus_demarshal_double (&real->message->body, real->message->byte_order,
-                                pos, NULL);
+  return value;
 }
 
 /**
@@ -3074,6 +3019,30 @@ dbus_message_iter_init_dict_iterator (DBusMessageIter *iter,
   return len > 0;
 }
 
+static dbus_bool_t
+_dbus_message_iter_get_basic_type_array  (DBusMessageIter *iter,
+                                         char             type,
+                                         void           **array,
+                                         int             *array_len)
+{
+  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+  int item_type, pos;
+
+  _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
+
+  pos = dbus_message_iter_get_data_start (real, &item_type);
+  
+  _dbus_assert (item_type == DBUS_TYPE_ARRAY);
+
+  item_type = iter_get_array_type (real, NULL);
+  
+  _dbus_assert (type == item_type);
+
+  return _dbus_demarshal_basic_type_array (&real->message->body,
+                                          item_type, array, array_len,
+                                          real->message->byte_order, &pos);
+}
+
 /**
  * Returns the byte array that the iterator may point to.
  * Note that you need to check that the iterator points
@@ -3089,24 +3058,8 @@ 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;
+  return _dbus_message_iter_get_basic_type_array (iter, DBUS_TYPE_BYTE,
+                                                 (void **) value, len);
 }
 
 /**
@@ -3124,24 +3077,8 @@ 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;
+  return _dbus_message_iter_get_basic_type_array (iter, DBUS_TYPE_BOOLEAN,
+                                                 (void **) value, len);
 }
 
 /**
@@ -3159,24 +3096,8 @@ 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;
+  return _dbus_message_iter_get_basic_type_array (iter, DBUS_TYPE_INT32,
+                                                 (void **) value, len);
 }
 
 /**
@@ -3194,23 +3115,8 @@ 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;
+  return _dbus_message_iter_get_basic_type_array (iter, DBUS_TYPE_UINT32,
+                                                 (void **) value, len);
 }
 
 #ifdef DBUS_HAVE_INT64
@@ -3232,24 +3138,8 @@ 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;
+  return _dbus_message_iter_get_basic_type_array (iter, DBUS_TYPE_INT64,
+                                                 (void **) value, len);
 }
 
 /**
@@ -3269,23 +3159,8 @@ 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;
+  return _dbus_message_iter_get_basic_type_array (iter, DBUS_TYPE_UINT64,
+                                                 (void **) value, len);
 }
 
 #endif /* DBUS_HAVE_INT64 */
@@ -3305,23 +3180,8 @@ 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;
+  return _dbus_message_iter_get_basic_type_array (iter, DBUS_TYPE_DOUBLE,
+                                                 (void **) value, len);
 }
 
 /**
@@ -3496,15 +3356,16 @@ 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))
+        return FALSE;
+
+      if (!_dbus_message_append_byte_to_signature (iter->message, type))
         {
-          _dbus_string_shorten (&iter->message->signature, 1);
+          _dbus_string_shorten (&iter->message->body, 1);
           return FALSE;
         }
       break;
@@ -3589,6 +3450,31 @@ dbus_message_iter_append_nil (DBusMessageIter *iter)
   return TRUE;
 }
 
+static dbus_bool_t
+dbus_message_iter_append_basic (DBusMessageIter *iter,
+                               char             type,
+                               void            *value)
+{
+  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+  _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
+
+  if (!dbus_message_iter_append_type (real, type))
+    return FALSE;
+
+  if (!_dbus_marshal_basic_type (&real->message->body,
+                                type, value,
+                                real->message->byte_order))
+    {
+      _dbus_string_set_length (&real->message->body, real->pos);
+      return FALSE;
+    }
+
+  dbus_message_iter_append_done (real);
+  
+  return TRUE;  
+}
+
 /**
  * Appends a boolean value to the message
  *
@@ -3600,22 +3486,8 @@ 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;
+  unsigned char val = (value != FALSE);
+  return dbus_message_iter_append_basic (iter, DBUS_TYPE_BOOLEAN, &val);
 }
 
 /**
@@ -3629,25 +3501,9 @@ 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;
+  return dbus_message_iter_append_basic (iter, DBUS_TYPE_BYTE, &value);
 }
 
-
 /**
  * Appends a 32 bit signed integer to the message.
  *
@@ -3659,22 +3515,7 @@ 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;
+  return dbus_message_iter_append_basic (iter, DBUS_TYPE_INT32, &value);
 }
 
 /**
@@ -3688,22 +3529,7 @@ 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;
+  return dbus_message_iter_append_basic (iter, DBUS_TYPE_UINT32, &value);
 }
 
 #ifdef DBUS_HAVE_INT64
@@ -3721,22 +3547,7 @@ 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;
+  return dbus_message_iter_append_basic (iter, DBUS_TYPE_INT64, &value);
 }
 
 /**
@@ -3752,22 +3563,7 @@ 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;
+  return dbus_message_iter_append_basic (iter, DBUS_TYPE_UINT64, &value);
 }
 
 #endif /* DBUS_HAVE_INT64 */
@@ -3783,22 +3579,7 @@ 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;
+  return dbus_message_iter_append_basic (iter, DBUS_TYPE_DOUBLE, &value);
 }
 
 /**
@@ -3999,7 +3780,7 @@ append_array_type (DBusMessageRealIter *real,
        *array_type_pos = _dbus_string_get_length (&real->message->body);
 
 
-      if (!_dbus_string_append_byte (&real->message->signature, element_type))
+      if (!_dbus_message_append_byte_to_signature (real->message, element_type))
         {
           _dbus_string_set_length (&real->message->body, real->pos);
           return FALSE;
@@ -4008,7 +3789,7 @@ append_array_type (DBusMessageRealIter *real,
       /* Append element type */
       if (!_dbus_string_append_byte (&real->message->body, element_type))
        {
-          _dbus_string_shorten (&real->message->signature, 1);
+          _dbus_message_remove_byte_from_signature (real->message);
          _dbus_string_set_length (&real->message->body, real->pos);
          return FALSE;
        }
@@ -4019,9 +3800,9 @@ append_array_type (DBusMessageRealIter *real,
       if (element_type != DBUS_TYPE_ARRAY &&
          !array_iter_type_mark_done (real))
         {
-          _dbus_string_shorten (&real->message->signature, 1);
+          _dbus_message_remove_byte_from_signature (real->message);
           return FALSE;
-        }        
+        }
     }
 
   return TRUE;
@@ -4089,55 +3870,240 @@ dbus_message_iter_append_array (DBusMessageIter      *iter,
   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;
+/**
+ * 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;
+}
+
+static dbus_bool_t
+_dbus_message_iter_append_basic_array (DBusMessageIter *iter,
+                                      char             type,
+                                      const void      *value,
+                                      int              len)
+{
+  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+  _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
+
+  if (!append_array_type (real, type, NULL, NULL))
+    return FALSE;
+  
+  if (!_dbus_marshal_basic_type_array (&real->message->body,
+                                      type, value, len,
+                                      real->message->byte_order))
+    {
+      _dbus_string_set_length (&real->message->body, real->pos);
+      return FALSE;
+    }
+
+  dbus_message_iter_append_done (real);
+  
+  return TRUE;
+}
+
+
+/**
+ * This function takes a va_list for use by language bindings.
+ * It's otherwise the same as dbus_message_append_args().
+ *
+ * @todo: Shouldn't this function clean up the changes to the message
+ *        on failures? (Yes)
+  
+ * @see dbus_message_append_args.  
+ * @param message the message
+ * @param first_arg_type type of first argument
+ * @param var_args value of first argument, then list of type/value pairs
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_append_args_valist (DBusMessage *message,
+                                int          first_arg_type,
+                                va_list      var_args)
+{
+  int type, old_len;
+  DBusMessageIter iter;
+
+  _dbus_return_val_if_fail (message != NULL, FALSE);
+  
+  old_len = _dbus_string_get_length (&message->body);
+  
+  type = first_arg_type;
+
+  dbus_message_append_iter_init (message, &iter);
+  
+  while (type != DBUS_TYPE_INVALID)
+    {
+      switch (type)
+       {
+       case DBUS_TYPE_NIL:
+         if (!dbus_message_iter_append_nil (&iter))
+           goto errorout;
+         break;
+       case DBUS_TYPE_BYTE:
+          /* FIXME if you pass an unsigned char to varargs it gets promoted to int,
+           * so probably we should read an int here.
+           */
+         if (!dbus_message_iter_append_byte (&iter, va_arg (var_args, unsigned char)))
+           goto errorout;
+         break;
+       case DBUS_TYPE_BOOLEAN:
+         if (!dbus_message_iter_append_boolean (&iter, va_arg (var_args, dbus_bool_t)))
+           goto errorout;
+         break;
+       case DBUS_TYPE_INT32:
+          /* FIXME this is probably wrong, because an int passed in probably gets
+           * converted to plain "int" not necessarily 32-bit.
+           */
+         if (!dbus_message_iter_append_int32 (&iter, va_arg (var_args, dbus_int32_t)))
+           goto errorout;
+         break;
+       case DBUS_TYPE_UINT32:
+          /* FIXME this is probably wrong, because an int passed in probably gets
+           * converted to plain "int" not necessarily 32-bit.
+           */
+         if (!dbus_message_iter_append_uint32 (&iter, va_arg (var_args, dbus_uint32_t)))
+           goto errorout;          
+         break;
+#ifdef DBUS_HAVE_INT64
+        case DBUS_TYPE_INT64:
+         if (!dbus_message_iter_append_int64 (&iter, va_arg (var_args, dbus_int64_t)))
+           goto errorout;
+         break;
+       case DBUS_TYPE_UINT64:
+         if (!dbus_message_iter_append_uint64 (&iter, va_arg (var_args, dbus_uint64_t)))
+           goto errorout;          
+         break;
+#endif /* DBUS_HAVE_INT64 */
+       case DBUS_TYPE_DOUBLE:
+         if (!dbus_message_iter_append_double (&iter, va_arg (var_args, double)))
+           goto errorout;
+         break;
+       case DBUS_TYPE_STRING:
+         if (!dbus_message_iter_append_string (&iter, va_arg (var_args, const char *)))
+           goto errorout;
+         break;
+        case DBUS_TYPE_OBJECT_PATH:
+         if (!dbus_message_iter_append_object_path (&iter, va_arg (var_args, const char*)))
+           goto errorout;
+          break;
+       case DBUS_TYPE_CUSTOM:
+         {
+           const char *name;
+           unsigned char *data;
+           int len;
+           name = va_arg (var_args, const char *);
+           data = va_arg (var_args, unsigned char *);
+           len = va_arg (var_args, int);
+
+           if (!dbus_message_iter_append_custom (&iter, name, data, len))
+             goto errorout;
+           break;
+         }
+       case DBUS_TYPE_ARRAY:
+         {
+           void *data;
+           int len, type;
+           type = va_arg (var_args, int);
+           data = va_arg (var_args, void *);
+           len = va_arg (var_args, int);
 
-  _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));
+           switch (type)
+             {
+             case DBUS_TYPE_BYTE:
+             case DBUS_TYPE_BOOLEAN:
+             case DBUS_TYPE_INT32:
+             case DBUS_TYPE_UINT32:
+#ifdef DBUS_HAVE_INT64
+              case DBUS_TYPE_INT64:
+             case DBUS_TYPE_UINT64:
+#endif /* DBUS_HAVE_INT64 */
+             case DBUS_TYPE_DOUBLE:
+               if (!_dbus_message_iter_append_basic_array (&iter, type, data, len))
+                 goto errorout;
+               break;
+             case DBUS_TYPE_STRING:
+               if (!dbus_message_iter_append_string_array (&iter, (const char **)data, len))
+                 goto errorout;
+               break;
+             case DBUS_TYPE_OBJECT_PATH:
+               if (!dbus_message_iter_append_object_path_array (&iter, (const char **)data, len))
+                 goto errorout;
+               break;
+             case DBUS_TYPE_NIL:
+             case DBUS_TYPE_ARRAY:
+             case DBUS_TYPE_CUSTOM:
+             case DBUS_TYPE_DICT:
+               _dbus_warn ("dbus_message_append_args_valist doesn't support recursive arrays\n");
+               goto errorout;
+             default:
+               _dbus_warn ("Unknown field type %d\n", type);
+               goto errorout;
+             }
+         }
+         break;
+         
+       case DBUS_TYPE_DICT:
+         _dbus_warn ("dbus_message_append_args_valist doesn't support dicts\n");
+         goto errorout;
+       default:
+         _dbus_warn ("Unknown field type %d\n", type);
+         goto errorout;
+       }
 
-  /* 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;
+      type = va_arg (var_args, int);
     }
-  
-  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;
-}
 
+ errorout:
+  return FALSE;
+}
 
 /**
  * Appends a boolean array to the message.
@@ -4152,22 +4118,8 @@ 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;
+  return _dbus_message_iter_append_basic_array (iter, DBUS_TYPE_BOOLEAN,
+                                               value, len);
 }
 
 /**
@@ -4183,22 +4135,8 @@ 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;
+  return _dbus_message_iter_append_basic_array (iter, DBUS_TYPE_INT32,
+                                               value, len);
 }
 
 /**
@@ -4214,22 +4152,8 @@ 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;
+  return _dbus_message_iter_append_basic_array (iter, DBUS_TYPE_UINT32,
+                                               value, len);
 }
 
 #ifdef DBUS_HAVE_INT64
@@ -4249,22 +4173,8 @@ 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;
+  return _dbus_message_iter_append_basic_array (iter, DBUS_TYPE_INT64,
+                                               value, len);
 }
 
 /**
@@ -4282,22 +4192,8 @@ 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;
+  return _dbus_message_iter_append_basic_array (iter, DBUS_TYPE_UINT64,
+                                               value, len);
 }
 #endif /* DBUS_HAVE_INT64 */
 
@@ -4314,22 +4210,8 @@ 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;
+  return _dbus_message_iter_append_basic_array (iter, DBUS_TYPE_DOUBLE,
+                                               value, len);
 }
 
 /**
@@ -4345,22 +4227,8 @@ 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;
+  return _dbus_message_iter_append_basic_array (iter, DBUS_TYPE_BYTE,
+                                               value, len);
 }
 
 /**
@@ -4429,7 +4297,7 @@ dbus_message_iter_append_object_path_array (DBusMessageIter *iter,
  * Sets the message sender.
  *
  * @param message the message
- * @param sender the sender
+ * @param sender the sender or #NULL to unset
  * @returns #FALSE if not enough memory
  */
 dbus_bool_t
@@ -4440,7 +4308,7 @@ dbus_message_set_sender (DBusMessage  *message,
   _dbus_return_val_if_fail (!message->locked, FALSE);
 
   return set_string_field (message,
-                           DBUS_HEADER_FIELD_SENDER_SERVICE,
+                           DBUS_HEADER_FIELD_SENDER,
                            DBUS_TYPE_STRING,
                            sender);
 }
@@ -4550,7 +4418,7 @@ dbus_message_get_sender (DBusMessage *message)
   _dbus_return_val_if_fail (message != NULL, NULL);
   
   return get_string_field (message, 
-                          DBUS_HEADER_FIELD_SENDER_SERVICE,
+                          DBUS_HEADER_FIELD_SENDER,
                           NULL);
 }
 
@@ -4573,8 +4441,10 @@ const char*
 dbus_message_get_signature (DBusMessage *message)
 {
   _dbus_return_val_if_fail (message != NULL, NULL);
-  
-  return _dbus_string_get_const_data (&message->signature);
+
+  return get_string_field (message, 
+                          DBUS_HEADER_FIELD_SIGNATURE,
+                          NULL);
 }
 
 static dbus_bool_t
@@ -4673,13 +4543,14 @@ dbus_message_is_signal (DBusMessage *message,
  */
 dbus_bool_t
 dbus_message_is_error (DBusMessage *message,
-                        const char  *error_name)
+                       const char  *error_name)
 {
   const char *n;
   
   _dbus_return_val_if_fail (message != NULL, FALSE);
   _dbus_return_val_if_fail (error_name != NULL, FALSE);
-
+  _dbus_return_val_if_fail (is_valid_error_name (error_name), FALSE);
+  
   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
     return FALSE;
 
@@ -4762,10 +4633,17 @@ dbus_bool_t
 dbus_message_has_signature (DBusMessage   *message,
                             const char    *signature)
 {
+  const char *s;
+
   _dbus_return_val_if_fail (message != NULL, FALSE);
   _dbus_return_val_if_fail (signature != NULL, FALSE);
+  
+  s = dbus_message_get_signature (message);
 
-  return _dbus_string_equal_c_str (&message->signature, signature);
+  if (s && strcmp (s, signature) == 0)
+    return TRUE;
+  else
+    return FALSE;
 }
 
 /**
@@ -5018,7 +4896,7 @@ decode_string_field (const DBusString   *data,
   _dbus_string_init_const (field_data,
                            _dbus_string_get_const_data (data) + string_data_pos);
 
-  header_field->name_offset  = pos;
+  header_field->name_offset  = pos - 2;
   header_field->value_offset = _DBUS_ALIGN_VALUE (pos, 4);
   
 #if 0
@@ -5048,6 +4926,7 @@ decode_header_data (const DBusString   *data,
   int i;
   int field;
   int type;
+  dbus_bool_t signature_required;
   
   if (header_len < 16)
     {
@@ -5093,7 +4972,7 @@ decode_header_data (const DBusString   *data,
       
       switch (field)
         {
-        case DBUS_HEADER_FIELD_SERVICE:
+        case DBUS_HEADER_FIELD_DESTINATION:
           if (!decode_string_field (data, field, &fields[field],
                                    &field_data, pos, type))
             return FALSE;
@@ -5156,7 +5035,7 @@ decode_header_data (const DBusString   *data,
            }
           break;
           
-       case DBUS_HEADER_FIELD_SENDER_SERVICE:
+       case DBUS_HEADER_FIELD_SENDER:
           if (!decode_string_field (data, field, &fields[field],
                                    &field_data, pos, type))
             return FALSE;
@@ -5188,7 +5067,7 @@ decode_header_data (const DBusString   *data,
               return FALSE;
             }
 
-          fields[field].name_offset  = pos;
+          fields[field].name_offset  = pos - 2;
           fields[field].value_offset = _DBUS_ALIGN_VALUE (pos, 4);
 
           /* No forging signals from the local path */
@@ -5222,7 +5101,7 @@ decode_header_data (const DBusString   *data,
               return FALSE;
             }
           
-          fields[field].name_offset  = pos;
+          fields[field].name_offset  = pos - 2;
           fields[field].value_offset = _DBUS_ALIGN_VALUE (pos, 4);
 
           _dbus_verbose ("Found reply serial %u at offset %d\n",
@@ -5233,6 +5112,23 @@ decode_header_data (const DBusString   *data,
                          fields[field].value_offset);
          break;
 
+       case DBUS_HEADER_FIELD_SIGNATURE:
+          if (!decode_string_field (data, field, &fields[field],
+                                   &field_data, pos, type))
+            return FALSE;
+
+#if 0
+          /* FIXME */
+         if (!_dbus_string_validate_signature (&field_data, 0,
+                                                _dbus_string_get_length (&field_data)))
+           {
+             _dbus_verbose ("signature field has invalid content \"%s\"\n",
+                            _dbus_string_get_const_data (&field_data));
+             return FALSE;
+           }
+#endif
+         break;
+          
         default:
          _dbus_verbose ("Ignoring an unknown header field: %d at offset %d\n",
                         field, pos);
@@ -5259,6 +5155,8 @@ decode_header_data (const DBusString   *data,
     }
 
   /* Depending on message type, enforce presence of certain fields. */
+  signature_required = TRUE;
+  
   switch (message_type)
     {
     case DBUS_MESSAGE_TYPE_SIGNAL:
@@ -5301,8 +5199,19 @@ decode_header_data (const DBusString   *data,
       break;
     default:
       /* An unknown type, spec requires us to ignore it */
+      signature_required = FALSE;
       break;
     }
+
+  /* FIXME allow omitting signature field for a message with no arguments? */
+  if (signature_required)
+    {
+      if (fields[DBUS_HEADER_FIELD_SIGNATURE].value_offset < 0)
+        {
+          _dbus_verbose ("No signature field provided\n");
+          return FALSE;
+        }
+    }
   
   if (message_padding)
     *message_padding = header_len - pos;  
@@ -5470,60 +5379,7 @@ load_one_message (DBusMessageLoader *loader,
       loader->corrupted = TRUE;
       goto failed;
     }
-          
-  /* Fill in signature (FIXME should do this during validation,
-   * but I didn't want to spend time on it since we want to change
-   * the wire format to contain the signature anyway)
-   */
-  {
-    DBusMessageIter iter;
-
-    dbus_message_iter_init (message, &iter);
-
-    do
-      {
-        int t;
-
-        t = dbus_message_iter_get_arg_type (&iter);
-        if (t == DBUS_TYPE_INVALID)
-          break;
-
-        if (!_dbus_string_append_byte (&message->signature,
-                                       t))
-          {
-            _dbus_verbose ("failed to append type byte to signature\n");
-            oom = TRUE;
-            goto failed;
-          }
-
-        if (t == DBUS_TYPE_ARRAY)
-          {
-            DBusMessageIter child_iter;
-            int array_type = t;
-
-            child_iter = iter;
-                    
-            while (array_type == DBUS_TYPE_ARRAY)
-              {
-                DBusMessageIter parent_iter = child_iter;
-                dbus_message_iter_init_array_iterator (&parent_iter,
-                                                       &child_iter,
-                                                       &array_type);
-                                            
-                if (!_dbus_string_append_byte (&message->signature,
-                                               array_type))
-                  {
-                    _dbus_verbose ("failed to append array type byte to signature\n");
-
-                    oom = TRUE;
-                    goto failed;
-                  }
-              }
-          }
-      }
-    while (dbus_message_iter_next (&iter));
-  }
-          
+  
   _dbus_verbose ("Loaded message %p\n", message);
 
   _dbus_assert (!oom);
@@ -7000,9 +6856,6 @@ verify_test_message (DBusMessage *message)
     _dbus_assert_not_reached ("bool array had wrong values");
 
   dbus_free (our_boolean_array);
-  
-  if (!dbus_message_iter_next (&iter))
-    _dbus_assert_not_reached ("Reached end of arguments");
 
   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_DICT)
     _dbus_assert_not_reached ("not dict type");
@@ -7260,9 +7113,6 @@ _dbus_message_test (const char *test_data_dir)
 
   _dbus_assert (_dbus_string_get_length (&message->body) ==
                 _dbus_string_get_length (&copy->body));
-
-  _dbus_assert (_dbus_string_get_length (&message->signature) ==
-                _dbus_string_get_length (&copy->signature));
   
   verify_test_message (copy);