2004-11-13 Havoc Pennington <hp@redhat.com>
[platform/upstream/dbus.git] / dbus / dbus-message.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-message.c  DBusMessage object
3  *
4  * Copyright (C) 2002, 2003, 2004  Red Hat Inc.
5  * Copyright (C) 2002, 2003  CodeFactory AB
6  *
7  * Licensed under the Academic Free License version 2.1
8  * 
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  * 
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  *
23  */
24
25 #include "dbus-internals.h"
26 #include "dbus-marshal.h"
27 #include "dbus-message.h"
28 #include "dbus-message-internal.h"
29 #include "dbus-memory.h"
30 #include "dbus-list.h"
31 #include "dbus-message-builder.h"
32 #include "dbus-dataslot.h"
33 #include <string.h>
34
35 /**
36  * @defgroup DBusMessageInternals DBusMessage implementation details
37  * @ingroup DBusInternals
38  * @brief DBusMessage private implementation details.
39  *
40  * The guts of DBusMessage and its methods.
41  *
42  * @{
43  */
44
45 /**
46  * Cached information about a header field in the message
47  */
48 typedef struct
49 {
50   int name_offset;  /**< Offset to name of field */
51   int value_offset; /**< Offset to value of field */
52 } HeaderField;
53
54 /** Offset to byte order from start of header */
55 #define BYTE_ORDER_OFFSET    0
56 /** Offset to type from start of header */
57 #define TYPE_OFFSET          1
58 /** Offset to flags from start of header */
59 #define FLAGS_OFFSET         2
60 /** Offset to version from start of header */
61 #define VERSION_OFFSET       3
62 /** Offset to header length from start of header */
63 #define HEADER_LENGTH_OFFSET 4
64 /** Offset to body length from start of header */
65 #define BODY_LENGTH_OFFSET   8
66 /** Offset to client serial from start of header */
67 #define CLIENT_SERIAL_OFFSET 12
68
69
70 /**
71  * @brief Internals of DBusMessage
72  * 
73  * Object representing a message received from or to be sent to
74  * another application. This is an opaque object, all members
75  * are private.
76  */
77 struct DBusMessage
78 {
79   DBusAtomic refcount; /**< Reference count */
80
81   DBusString header; /**< Header network data, stored
82                       * separately from body so we can
83                       * independently realloc it.
84                       */
85
86   HeaderField header_fields[DBUS_HEADER_FIELD_LAST + 1]; /**< Track the location
87                                                           * of each field in "header"
88                                                           */
89
90   dbus_uint32_t client_serial; /**< Cached client serial value for speed */
91   dbus_uint32_t reply_serial;  /**< Cached reply serial value for speed */
92   
93   int header_padding; /**< bytes of alignment in header */
94   
95   DBusString body;   /**< Body network data. */
96
97   char byte_order; /**< Message byte order. */
98
99   DBusList *size_counters;   /**< 0-N DBusCounter used to track message size. */
100   long size_counter_delta;   /**< Size we incremented the size counters by.   */
101
102   dbus_uint32_t changed_stamp; /**< Incremented when iterators are invalidated. */
103   
104   unsigned int locked : 1; /**< Message being sent, no modifications allowed. */
105
106   DBusDataSlotList slot_list;   /**< Data stored by allocated integer ID */
107 };
108
109 enum {
110   DBUS_MESSAGE_ITER_TYPE_MESSAGE,
111   DBUS_MESSAGE_ITER_TYPE_ARRAY,
112   DBUS_MESSAGE_ITER_TYPE_DICT
113 };
114
115 /** typedef for internals of message iterator */
116 typedef struct DBusMessageRealIter DBusMessageRealIter;
117
118 /**
119  * @brief Internals of DBusMessageIter
120  * 
121  * Object representing a position in a message. All fields are internal.
122  */
123 struct DBusMessageRealIter
124 {
125   DBusMessageRealIter *parent_iter; /**< parent iter, or NULL */
126   DBusMessage *message; /**< Message used */
127   dbus_uint32_t changed_stamp; /**< stamp to detect invalid iters */
128   
129   /* This is an int instead of an enum to get a guaranteed size for the dummy: */
130   int type; /**< type of iter */
131   
132   int pos; /**< Current position in the string */
133   int end; /**< position right after the container */
134   int container_start; /**< offset of the start of the container */
135   int container_length_pos; /**< offset of the length of the container */
136   
137   int wrote_dict_key; /**< whether we wrote the dict key for the current dict element */
138
139   int array_type_pos; /**< pointer to the position of the array element type */
140   int array_type_done; /**< TRUE if the array type is fully finished */
141 };
142
143 /**
144  * Gets the data to be sent over the network for this message.
145  * The header and then the body should be written out.
146  * This function is guaranteed to always return the same
147  * data once a message is locked (with _dbus_message_lock()).
148  *
149  * @param message the message.
150  * @param header return location for message header data.
151  * @param body return location for message body data.
152  */
153 void
154 _dbus_message_get_network_data (DBusMessage          *message,
155                                 const DBusString    **header,
156                                 const DBusString    **body)
157 {
158   _dbus_assert (message->locked);
159   
160   *header = &message->header;
161   *body = &message->body;
162 }
163
164 static void
165 clear_header_padding (DBusMessage *message)
166 {
167   _dbus_string_shorten (&message->header,
168                         message->header_padding);
169   message->header_padding = 0;
170 }              
171
172 #ifdef DBUS_DISABLE_CHECKS
173 #define is_valid_error_name(x) TRUE
174 #else
175 static dbus_bool_t
176 is_valid_error_name (const char *error_name)                                          
177 {
178   DBusString the_error_name;
179
180   if (error_name == NULL)
181     return FALSE;
182   
183   _dbus_string_init_const (&the_error_name, error_name);
184   return _dbus_string_validate_error_name (&the_error_name, 0,   
185                                            _dbus_string_get_length (&the_error_name));
186 }
187 #endif
188
189 static dbus_bool_t
190 append_header_padding (DBusMessage *message)
191 {
192   int old_len;
193   old_len = _dbus_string_get_length (&message->header);
194   if (!_dbus_string_align_length (&message->header, 8))
195     return FALSE;
196
197   message->header_padding = _dbus_string_get_length (&message->header) - old_len;
198
199   return TRUE;
200 }
201
202 #ifdef DBUS_BUILD_TESTS
203 /* tests-only until it's actually used */
204 static dbus_int32_t
205 get_int_field (DBusMessage *message,
206                int          field)
207 {
208   int offset;
209
210   _dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
211   
212   offset = message->header_fields[field].value_offset;
213   
214   if (offset < 0)
215     return -1; /* useless if -1 is a valid value of course */
216   
217   return _dbus_demarshal_int32 (&message->header,
218                                 message->byte_order,
219                                 offset,
220                                 NULL);
221 }
222 #endif
223
224 static dbus_uint32_t
225 get_uint_field (DBusMessage *message,
226                 int          field)
227 {
228   int offset;
229   
230   _dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
231   
232   offset = message->header_fields[field].value_offset;
233   
234   if (offset < 0)
235     return 0; /* useless if 0 is a valid value of course */
236   
237   return _dbus_demarshal_uint32 (&message->header,
238                                  message->byte_order,
239                                  offset,
240                                  NULL);
241 }
242
243 static const char*
244 get_string_field (DBusMessage *message,
245                   int          field,
246                   int         *len)
247 {
248   int offset;
249   const char *data;
250
251   offset = message->header_fields[field].value_offset;
252
253   _dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
254   
255   if (offset < 0)
256     return NULL;
257
258   /* offset points to string length, string data follows it */
259   /* FIXME _dbus_demarshal_const_string() that returned
260    * a reference to the string plus its len might be nice.
261    */
262   
263   if (len)
264     *len = _dbus_demarshal_uint32 (&message->header,
265                                    message->byte_order,
266                                    offset,
267                                    NULL);
268
269   data = _dbus_string_get_const_data (&message->header);
270   
271   return data + (offset + 4); 
272 }
273
274 /* returns FALSE if no memory, TRUE with NULL path if no field */
275 static dbus_bool_t
276 get_path_field_decomposed (DBusMessage  *message,
277                            int           field,
278                            char       ***path)
279 {
280   int offset;
281
282   offset = message->header_fields[field].value_offset;
283
284   _dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
285   
286   if (offset < 0)
287     {
288       *path = NULL;
289       return TRUE;
290     }
291
292   return _dbus_demarshal_object_path (&message->header,
293                                       message->byte_order,
294                                       offset,
295                                       NULL,
296                                       path, NULL);
297 }
298
299 #ifdef DBUS_BUILD_TESTS
300 static dbus_bool_t
301 append_int_field (DBusMessage *message,
302                   int          field,
303                   int          value)
304 {
305   _dbus_assert (!message->locked);
306
307   clear_header_padding (message);
308   
309   message->header_fields[field].name_offset =
310     _dbus_string_get_length (&message->header);
311   
312   if (!_dbus_string_append_byte (&message->header, field))
313     goto failed;
314
315   if (!_dbus_string_append_byte (&message->header, DBUS_TYPE_INT32))
316     goto failed;
317
318   if (!_dbus_string_align_length (&message->header, 4))
319     goto failed;
320   
321   message->header_fields[field].value_offset =
322     _dbus_string_get_length (&message->header);
323   
324   if (!_dbus_marshal_int32 (&message->header, message->byte_order,
325                             value))
326     goto failed;
327
328   if (!append_header_padding (message))
329     goto failed;
330   
331   return TRUE;
332   
333  failed:
334   _dbus_string_set_length (&message->header,
335                            message->header_fields[field].name_offset);
336   message->header_fields[field].name_offset  = -1;
337   message->header_fields[field].value_offset = -1;
338
339   /* this must succeed because it was allocated on function entry and
340    * DBusString doesn't ever realloc smaller
341    */
342   if (!append_header_padding (message))
343     _dbus_assert_not_reached ("failed to reappend header padding");
344   return FALSE;
345 }
346 #endif
347
348 static dbus_bool_t
349 append_uint_field (DBusMessage *message,
350                    int          field,
351                    int          value)
352 {
353   _dbus_assert (!message->locked);
354
355   clear_header_padding (message);
356   
357   message->header_fields[field].name_offset =
358     _dbus_string_get_length (&message->header);
359   
360   if (!_dbus_string_append_byte (&message->header, field))
361     goto failed;
362
363   if (!_dbus_string_append_byte (&message->header, DBUS_TYPE_UINT32))
364     goto failed;
365
366   if (!_dbus_string_align_length (&message->header, 4))
367     goto failed;
368   
369   message->header_fields[field].value_offset =
370     _dbus_string_get_length (&message->header);
371   
372   if (!_dbus_marshal_uint32 (&message->header, message->byte_order,
373                              value))
374     goto failed;
375
376   if (!append_header_padding (message))
377     goto failed;
378   
379   return TRUE;
380   
381  failed:
382   _dbus_string_set_length (&message->header,
383                            message->header_fields[field].name_offset);
384   message->header_fields[field].name_offset  = -1;
385   message->header_fields[field].value_offset = -1;
386
387   /* this must succeed because it was allocated on function entry and
388    * DBusString doesn't ever realloc smaller
389    */
390   if (!append_header_padding (message))
391     _dbus_assert_not_reached ("failed to reappend header padding");
392   return FALSE;
393 }
394
395 /** The maximum number of bytes of overhead to append to a string
396  * (fieldcode + typecode + alignment + length + nul + headerpadding)
397  */
398 #define MAX_BYTES_OVERHEAD_TO_APPEND_A_STRING (1 + 1 + 3 + 4 + 1 + 8)
399
400 static dbus_bool_t
401 append_string_field_len (DBusMessage *message,
402                          int          field,
403                          int          type,
404                          const char  *value,
405                          int          value_len)
406 {
407   _dbus_assert (!message->locked);
408
409   clear_header_padding (message);
410   
411   message->header_fields[field].name_offset =
412     _dbus_string_get_length (&message->header);
413   
414   if (!_dbus_string_append_byte (&message->header, field))
415     goto failed;
416   
417   if (!_dbus_string_append_byte (&message->header, type))
418     goto failed;
419
420   if (!_dbus_string_align_length (&message->header, 4))
421     goto failed;
422   
423   message->header_fields[field].value_offset =
424     _dbus_string_get_length (&message->header);
425   
426   if (!_dbus_marshal_string_len (&message->header, message->byte_order,
427                                  value, value_len))
428     goto failed;
429
430   if (!append_header_padding (message))
431     goto failed;
432   
433   return TRUE;
434   
435  failed:
436   _dbus_string_set_length (&message->header,
437                            message->header_fields[field].name_offset);
438   message->header_fields[field].name_offset  = -1;
439   message->header_fields[field].value_offset = -1;
440
441   /* this must succeed because it was allocated on function entry and
442    * DBusString doesn't ever realloc smaller
443    */
444   if (!append_header_padding (message))
445     _dbus_assert_not_reached ("failed to reappend header padding");
446   
447   return FALSE;
448 }
449
450 static dbus_bool_t
451 append_string_field (DBusMessage *message,
452                      int          field,
453                      int          type,
454                      const char  *value)
455 {
456   int value_len;
457
458   value_len = strlen (value);
459
460   return append_string_field_len (message, field, type, value, value_len);
461 }
462
463 static int
464 get_type_alignment (int type)
465 {
466   int alignment;
467   
468   switch (type)
469     {
470     case DBUS_TYPE_NIL:
471     case DBUS_TYPE_BYTE:
472     case DBUS_TYPE_BOOLEAN:
473       alignment = 0;
474       break;
475
476     case DBUS_TYPE_INT32:
477     case DBUS_TYPE_UINT32:
478     case DBUS_TYPE_STRING:
479     case DBUS_TYPE_OBJECT_PATH:
480       /* These are aligned 4 because they have a length as the
481        * first field;
482        */
483     case DBUS_TYPE_CUSTOM:
484     case DBUS_TYPE_DICT:
485       alignment = 4;
486       break;
487
488     case DBUS_TYPE_INT64:
489     case DBUS_TYPE_UINT64:
490     case DBUS_TYPE_DOUBLE:
491       alignment = 8;
492       break;
493
494     case DBUS_TYPE_ARRAY:
495       _dbus_assert_not_reached ("passed an ARRAY type to get_type_alignment()");
496       alignment = 0; /* quiet gcc */
497       break;
498
499     case DBUS_TYPE_INVALID:
500     default:
501       _dbus_assert_not_reached ("passed an invalid or unknown type to get_type_alignment()");
502       alignment = 0; /* quiet gcc */
503       break;
504     }
505
506   return alignment;
507 }
508
509 static dbus_bool_t
510 iterate_one_field (const DBusString *str,
511                    int               byte_order,
512                    int               name_offset,
513                    int              *next_offset_p,
514                    int              *field_name_p,
515                    DBusString       *append_copy_to,
516                    int              *copy_name_offset_p,
517                    int              *copy_value_offset_p)
518 {
519   int name, type, array_type;
520   int alignment;
521   int type_len;
522   int type_pos;
523   int value_pos;
524   int value_len;
525   int value_end;
526   int pos;
527
528   _dbus_verbose ("%s: name_offset=%d, append to %p\n",
529                  _DBUS_FUNCTION_NAME, name_offset, append_copy_to);
530   
531   pos = name_offset;
532   
533   name = _dbus_string_get_byte (str, name_offset);
534   pos++;
535
536   type_pos = pos;
537   type = _dbus_string_get_byte (str, type_pos);
538   pos++;
539   type_len = 1;
540
541   array_type = type;
542   /* find out the type of our array */
543   while (array_type == DBUS_TYPE_ARRAY)
544     {
545       pos++;
546       type_len++;
547       array_type = _dbus_string_get_byte (str, pos);
548     }
549
550   _dbus_verbose ("%s: name %d, type '%c' %d at %d len %d, array type '%c' %d\n",
551                  _DBUS_FUNCTION_NAME,
552                  name, type, type, type_pos, type_len, array_type, array_type);
553   
554 #ifndef DBUS_DISABLE_ASSERT
555   if (!_dbus_type_is_valid (array_type))
556     {
557       _dbus_warn ("type '%c' %d is not valid in %s\n",
558                   array_type, array_type, _DBUS_FUNCTION_NAME);
559       _dbus_assert_not_reached ("invalid type");
560     }
561 #endif
562       
563   alignment = get_type_alignment (array_type);
564       
565   if (alignment > 0)
566     pos = _DBUS_ALIGN_VALUE (pos, alignment);
567
568   _dbus_verbose ("%s: alignment %d value at pos %d\n",
569                  _DBUS_FUNCTION_NAME, alignment, pos);
570   
571   /* pos now points to our value */
572   if (!_dbus_marshal_get_arg_end_pos (str, byte_order,
573                                       type, pos, &value_end))
574     _dbus_assert_not_reached ("failed to get the byte after this header");
575
576   value_pos = pos;
577   value_len = value_end - value_pos;
578
579   _dbus_verbose ("%s: value_pos %d value_len %d value_end %d\n",
580                  _DBUS_FUNCTION_NAME, value_pos, value_len, value_end);
581   
582   if (next_offset_p)
583     *next_offset_p = pos + value_len;
584
585   if (field_name_p)
586     *field_name_p = name;
587
588   if (append_copy_to)
589     {
590       int orig_len;
591
592       orig_len = _dbus_string_get_length (append_copy_to);
593
594       if (copy_name_offset_p)
595         *copy_name_offset_p = orig_len;
596       
597       if (!_dbus_string_append_byte (append_copy_to, name))
598         goto failed_copy;
599
600       if (!_dbus_string_copy_len (str, type_pos, type_len,
601                                   append_copy_to,
602                                   _dbus_string_get_length (append_copy_to)))
603         goto failed_copy;
604
605       if (!_dbus_string_align_length (append_copy_to, alignment))
606         goto failed_copy;
607
608       if (copy_value_offset_p)
609         *copy_value_offset_p = _dbus_string_get_length (append_copy_to);
610       
611       if (!_dbus_string_copy_len (str, value_pos, value_len,
612                                   append_copy_to,
613                                   _dbus_string_get_length (append_copy_to)))
614         goto failed_copy;
615       
616       return TRUE;
617
618     failed_copy:
619       _dbus_verbose ("%s: Failed copying old fields to new string\n",
620                      _DBUS_FUNCTION_NAME);
621       _dbus_string_set_length (append_copy_to, orig_len);
622       return FALSE;
623     }
624   else
625     return TRUE;
626 }
627
628 #ifndef DBUS_DISABLE_ASSERT
629 static void
630 verify_header_fields (DBusMessage *message)
631 {
632   int i;
633   i = 0;
634   while (i < DBUS_HEADER_FIELD_LAST)
635     {
636       if (message->header_fields[i].name_offset >= 0)
637         _dbus_assert (_dbus_string_get_byte (&message->header,
638                                              message->header_fields[i].name_offset) ==
639                       i);
640       ++i;
641     }
642 }
643 #else /* DBUS_DISABLE_ASSERT */
644 #define verify_header_fields(x)
645 #endif /* DBUS_DISABLE_ASSERT */
646
647 /* In this function we delete one field and re-align all the fields
648  * following it.
649  */
650 static dbus_bool_t
651 delete_one_and_re_align (DBusMessage *message,
652                          int          name_offset_to_delete)
653 {
654   DBusString copy;
655   int new_fields_front_padding;
656   int next_offset;
657   int field_name;
658   dbus_bool_t retval;
659   HeaderField new_header_fields[DBUS_HEADER_FIELD_LAST];
660   
661   _dbus_assert (name_offset_to_delete < _dbus_string_get_length (&message->header));
662   verify_header_fields (message);
663
664   _dbus_verbose ("%s: Deleting one field at offset %d\n",
665                  _DBUS_FUNCTION_NAME,
666                  name_offset_to_delete);
667   
668   retval = FALSE;
669
670   clear_header_padding (message);
671   
672   if (!_dbus_string_init_preallocated (&copy,
673                                        _dbus_string_get_length (&message->header) -
674                                        name_offset_to_delete + 8))
675     {
676       _dbus_verbose ("%s: Failed to init string to hold copy of fields\n",
677                      _DBUS_FUNCTION_NAME);
678       goto out_0;
679     }
680   
681   /* Align the name offset of the first field in the same way it's
682    * aligned in the real header
683    */
684   new_fields_front_padding = name_offset_to_delete % 8;
685
686   if (!_dbus_string_insert_bytes (&copy, 0, new_fields_front_padding,
687                                   '\0'))
688     _dbus_assert_not_reached ("Should not have failed to insert bytes into preallocated string\n");
689
690   memcpy (new_header_fields, message->header_fields,
691           sizeof (new_header_fields));
692   
693   /* Now just re-marshal each field in the header to our temporary
694    * buffer, skipping the first one. The tricky part is that the
695    * fields are padded as if for previous_name_offset, but are in fact
696    * at unaligned_name_offset
697    */
698
699   if (!iterate_one_field (&message->header,
700                           message->byte_order,
701                           name_offset_to_delete,
702                           &next_offset,
703                           &field_name, NULL, NULL, NULL))
704     _dbus_assert_not_reached ("shouldn't have failed to alloc memory to skip the deleted field");
705
706   if (field_name < DBUS_HEADER_FIELD_LAST)
707     {
708       new_header_fields[field_name].name_offset = -1;
709       new_header_fields[field_name].value_offset = -1;
710     }
711   
712   while (next_offset < _dbus_string_get_length (&message->header))
713     {
714       int copy_name_offset;
715       int copy_value_offset;
716
717       if (!iterate_one_field (&message->header,
718                               message->byte_order,
719                               next_offset,
720                               &next_offset,
721                               &field_name,
722                               &copy,
723                               &copy_name_offset,
724                               &copy_value_offset))
725         {
726           _dbus_verbose ("%s: OOM iterating one field\n",
727                          _DBUS_FUNCTION_NAME);
728           goto out_1;
729         }
730       
731       if (field_name < DBUS_HEADER_FIELD_LAST)
732         {
733           new_header_fields[field_name].name_offset = copy_name_offset - new_fields_front_padding + name_offset_to_delete;
734           new_header_fields[field_name].value_offset = copy_value_offset - new_fields_front_padding + name_offset_to_delete;
735         }
736     }
737
738   if (!_dbus_string_replace_len (&copy,
739                                  new_fields_front_padding,
740                                  _dbus_string_get_length (&copy) - new_fields_front_padding,
741                                  &message->header,
742                                  name_offset_to_delete,
743                                  _dbus_string_get_length (&message->header) - name_offset_to_delete))
744     {
745       _dbus_verbose ("%s: OOM moving copy back into header\n",
746                      _DBUS_FUNCTION_NAME);
747       goto out_1;
748     }
749   
750   memcpy (message->header_fields, new_header_fields,
751           sizeof (new_header_fields));
752   verify_header_fields (message);
753   
754   retval = TRUE;
755   
756  out_1:
757   _dbus_string_free (&copy);
758   
759  out_0:
760   if (!append_header_padding (message))
761     _dbus_assert_not_reached ("Failed to re-append header padding in re_align_field_recurse()");
762   
763   return retval;
764 }
765
766 static dbus_bool_t
767 delete_field (DBusMessage *message,
768               int          field,
769               int          prealloc_header_space)
770 {
771   int offset;
772
773   _dbus_assert (!message->locked);
774
775   /* Prealloc */
776   if (!_dbus_string_lengthen (&message->header, prealloc_header_space))
777     {
778       _dbus_verbose ("failed to prealloc %d bytes header space\n",
779                      prealloc_header_space);
780       return FALSE;
781     }
782   _dbus_string_shorten (&message->header, prealloc_header_space);
783
784   /* Delete */
785   offset = message->header_fields[field].name_offset;
786   if (offset < 0)
787     {
788       _dbus_verbose ("header field didn't exist, no need to delete\n");
789       return TRUE; /* field didn't exist */
790     }
791
792   return delete_one_and_re_align (message, offset);
793 }
794
795 #ifdef DBUS_BUILD_TESTS
796 static dbus_bool_t
797 set_int_field (DBusMessage *message,
798                int          field,
799                int          value)
800 {
801   int offset = message->header_fields[field].value_offset;
802
803   _dbus_assert (!message->locked);
804   
805   if (offset < 0)
806     {
807       /* need to append the field */
808       return append_int_field (message, field, value);
809     }
810   else
811     {
812       _dbus_marshal_set_int32 (&message->header,
813                                message->byte_order,
814                                offset, value);
815
816       return TRUE;
817     }
818 }
819 #endif
820
821 static dbus_bool_t
822 set_uint_field (DBusMessage  *message,
823                 int           field,
824                 dbus_uint32_t value)
825 {
826   int offset = message->header_fields[field].value_offset;
827
828   _dbus_assert (!message->locked);
829   
830   if (offset < 0)
831     {
832       /* need to append the field */
833       return append_uint_field (message, field, value);
834     }
835   else
836     {
837       _dbus_marshal_set_uint32 (&message->header,
838                                 message->byte_order,
839                                 offset, value);
840
841       return TRUE;
842     }
843 }
844
845 static dbus_bool_t
846 set_string_field (DBusMessage *message,
847                   int          field,
848                   int          type,
849                   const char  *value)
850 {
851   int prealloc;
852   int value_len;
853   
854   _dbus_assert (!message->locked);
855
856   value_len = value ? strlen (value) : 0;
857   
858   /* the prealloc is so the append_string_field()
859    * below won't fail, leaving us in inconsistent state
860    */
861   prealloc = value_len + MAX_BYTES_OVERHEAD_TO_APPEND_A_STRING;
862
863   _dbus_verbose ("set_string_field() field %d prealloc %d\n",
864                  field, prealloc);
865   
866   if (!delete_field (message, field, prealloc))
867     return FALSE;
868
869   if (value != NULL)
870     {
871       /* need to append the field */
872       if (!append_string_field_len (message, field, type, value, value_len))
873         _dbus_assert_not_reached ("Appending string field shouldn't have failed, due to preallocation");
874     }
875   
876   return TRUE;
877 }
878
879 /**
880  * Sets the serial number of a message. 
881  * This can only be done once on a message.
882  * 
883  * @param message the message
884  * @param serial the serial
885  */
886 void
887 _dbus_message_set_serial (DBusMessage  *message,
888                           dbus_int32_t  serial)
889 {
890   _dbus_assert (!message->locked);
891   _dbus_assert (dbus_message_get_serial (message) == 0);
892
893   _dbus_marshal_set_uint32 (&message->header,
894                             message->byte_order,
895                             CLIENT_SERIAL_OFFSET,
896                             serial);
897
898   message->client_serial = serial;
899 }
900
901 /**
902  * Sets the reply serial of a message (the client serial
903  * of the message this is a reply to).
904  *
905  * @param message the message
906  * @param reply_serial the client serial
907  * @returns #FALSE if not enough memory
908  */
909 dbus_bool_t
910 dbus_message_set_reply_serial (DBusMessage   *message,
911                                dbus_uint32_t  reply_serial)
912 {
913   _dbus_assert (!message->locked);
914
915   if (set_uint_field (message,
916                       DBUS_HEADER_FIELD_REPLY_SERIAL,
917                       reply_serial))
918     {
919       message->reply_serial = reply_serial;
920       return TRUE;
921     }
922   else
923     return FALSE;
924 }
925
926 /**
927  * Returns the serial of a message or 0 if none has been specified.
928  * The message's serial number is provided by the application sending
929  * the message and is used to identify replies to this message.  All
930  * messages received on a connection will have a serial, but messages
931  * you haven't sent yet may return 0.
932  *
933  * @param message the message
934  * @returns the client serial
935  */
936 dbus_uint32_t
937 dbus_message_get_serial (DBusMessage *message)
938 {
939   return message->client_serial;
940 }
941
942 /**
943  * Returns the serial that the message is a reply to or 0 if none.
944  *
945  * @param message the message
946  * @returns the reply serial
947  */
948 dbus_uint32_t
949 dbus_message_get_reply_serial  (DBusMessage *message)
950 {
951   return message->reply_serial;
952 }
953
954 /**
955  * Adds a counter to be incremented immediately with the
956  * size of this message, and decremented by the size
957  * of this message when this message if finalized.
958  * The link contains a counter with its refcount already
959  * incremented, but the counter itself not incremented.
960  * Ownership of link and counter refcount is passed to
961  * the message.
962  *
963  * @param message the message
964  * @param link link with counter as data
965  */
966 void
967 _dbus_message_add_size_counter_link (DBusMessage  *message,
968                                      DBusList     *link)
969 {
970   /* right now we don't recompute the delta when message
971    * size changes, and that's OK for current purposes
972    * I think, but could be important to change later.
973    * Do recompute it whenever there are no outstanding counters,
974    * since it's basically free.
975    */
976   if (message->size_counters == NULL)
977     {
978       message->size_counter_delta =
979         _dbus_string_get_length (&message->header) +
980         _dbus_string_get_length (&message->body);
981       
982 #if 0
983       _dbus_verbose ("message has size %ld\n",
984                      message->size_counter_delta);
985 #endif
986     }
987   
988   _dbus_list_append_link (&message->size_counters, link);
989   
990   _dbus_counter_adjust (link->data, message->size_counter_delta);
991 }
992
993 /**
994  * Adds a counter to be incremented immediately with the
995  * size of this message, and decremented by the size
996  * of this message when this message if finalized.
997  *
998  * @param message the message
999  * @param counter the counter
1000  * @returns #FALSE if no memory
1001  */
1002 dbus_bool_t
1003 _dbus_message_add_size_counter (DBusMessage *message,
1004                                 DBusCounter *counter)
1005 {
1006   DBusList *link;
1007
1008   link = _dbus_list_alloc_link (counter);
1009   if (link == NULL)
1010     return FALSE;
1011
1012   _dbus_counter_ref (counter);
1013   _dbus_message_add_size_counter_link (message, link);
1014
1015   return TRUE;
1016 }
1017
1018 /**
1019  * Removes a counter tracking the size of this message, and decrements
1020  * the counter by the size of this message.
1021  *
1022  * @param message the message
1023  * @param link_return return the link used
1024  * @param counter the counter
1025  */
1026 void
1027 _dbus_message_remove_size_counter (DBusMessage  *message,
1028                                    DBusCounter  *counter,
1029                                    DBusList    **link_return)
1030 {
1031   DBusList *link;
1032
1033   link = _dbus_list_find_last (&message->size_counters,
1034                                counter);
1035   _dbus_assert (link != NULL);
1036
1037   _dbus_list_unlink (&message->size_counters,
1038                      link);
1039   if (link_return)
1040     *link_return = link;
1041   else
1042     _dbus_list_free_link (link);
1043
1044   _dbus_counter_adjust (counter, - message->size_counter_delta);
1045
1046   _dbus_counter_unref (counter);
1047 }
1048
1049 static dbus_bool_t
1050 dbus_message_create_header (DBusMessage *message,
1051                             int          type,
1052                             const char  *service,
1053                             const char  *path,
1054                             const char  *interface,
1055                             const char  *member,
1056                             const char  *error_name)
1057 {
1058   unsigned int flags;
1059
1060   _dbus_assert ((interface && member) ||
1061                 (error_name) ||
1062                 !(interface || member || error_name));
1063   _dbus_assert (error_name == NULL || is_valid_error_name (error_name));
1064   
1065   if (!_dbus_string_append_byte (&message->header, message->byte_order))
1066     return FALSE;
1067
1068   if (!_dbus_string_append_byte (&message->header, type))
1069     return FALSE;
1070   
1071   flags = 0;
1072   if (!_dbus_string_append_byte (&message->header, flags))
1073     return FALSE;
1074
1075   if (!_dbus_string_append_byte (&message->header, DBUS_MAJOR_PROTOCOL_VERSION))
1076     return FALSE;
1077
1078   /* header length */
1079   if (!_dbus_marshal_uint32 (&message->header, message->byte_order, 0))
1080     return FALSE;
1081
1082   /* body length */
1083   if (!_dbus_marshal_uint32 (&message->header, message->byte_order, 0))
1084     return FALSE;
1085
1086   /* serial */
1087   if (!_dbus_marshal_uint32 (&message->header, message->byte_order, 0))
1088     return FALSE;
1089   
1090   /* Marshal all the fields (Marshall Fields?) */
1091   
1092   if (path != NULL)
1093     {
1094       if (!append_string_field (message,
1095                                 DBUS_HEADER_FIELD_PATH,
1096                                 DBUS_TYPE_OBJECT_PATH,
1097                                 path))
1098         return FALSE;
1099     }
1100   
1101   if (service != NULL)
1102     {
1103       if (!append_string_field (message,
1104                                 DBUS_HEADER_FIELD_DESTINATION,
1105                                 DBUS_TYPE_STRING,
1106                                 service))
1107         return FALSE;
1108     }
1109
1110   if (interface != NULL)
1111     {
1112       if (!append_string_field (message,
1113                                 DBUS_HEADER_FIELD_INTERFACE,
1114                                 DBUS_TYPE_STRING,
1115                                 interface))
1116         return FALSE;
1117     }
1118
1119   if (member != NULL)
1120     {
1121       if (!append_string_field (message,
1122                                 DBUS_HEADER_FIELD_MEMBER,
1123                                 DBUS_TYPE_STRING,
1124                                 member))
1125         return FALSE;
1126     }
1127
1128   if (error_name != NULL)
1129     {
1130       if (!append_string_field (message,
1131                                 DBUS_HEADER_FIELD_ERROR_NAME,
1132                                 DBUS_TYPE_STRING,
1133                                 error_name))
1134         return FALSE;
1135     }
1136
1137   /* @todo if we make signature optional when body is empty, we don't
1138    * need to do this here.
1139    */
1140   if (!append_string_field (message,
1141                             DBUS_HEADER_FIELD_SIGNATURE,
1142                             DBUS_TYPE_STRING,
1143                             ""))
1144     return FALSE;
1145   
1146   return TRUE;
1147 }
1148
1149 /**
1150  * Locks a message. Allows checking that applications don't keep a
1151  * reference to a message in the outgoing queue and change it
1152  * underneath us. Messages are locked when they enter the outgoing
1153  * queue (dbus_connection_send_message()), and the library complains
1154  * if the message is modified while locked.
1155  *
1156  * @param message the message to lock.
1157  */
1158 void
1159 _dbus_message_lock (DBusMessage  *message)
1160 {
1161   if (!message->locked)
1162     {
1163       /* Fill in our lengths */
1164       _dbus_marshal_set_uint32 (&message->header,
1165                                 message->byte_order,
1166                                 HEADER_LENGTH_OFFSET,
1167                                 _dbus_string_get_length (&message->header));
1168
1169       _dbus_marshal_set_uint32 (&message->header,
1170                                 message->byte_order,
1171                                 BODY_LENGTH_OFFSET,
1172                                 _dbus_string_get_length (&message->body));
1173
1174       message->locked = TRUE;
1175     }
1176 }
1177
1178 /** @} */
1179
1180 /**
1181  * @defgroup DBusMessage DBusMessage
1182  * @ingroup  DBus
1183  * @brief Message to be sent or received over a DBusConnection.
1184  *
1185  * A DBusMessage is the most basic unit of communication over a
1186  * DBusConnection. A DBusConnection represents a stream of messages
1187  * received from a remote application, and a stream of messages
1188  * sent to a remote application.
1189  *
1190  * @{
1191  */
1192
1193 /**
1194  * Sets the signature of the message, i.e. the arguments in the
1195  * message payload. The signature includes only "in" arguments for
1196  * #DBUS_MESSAGE_TYPE_METHOD_CALL and only "out" arguments for
1197  * #DBUS_MESSAGE_TYPE_METHOD_RETURN, so is slightly different from
1198  * what you might expect (it does not include the signature of the
1199  * entire C++-style method).
1200  *
1201  * The signature is a string made up of type codes such
1202  * as #DBUS_TYPE_STRING. The string is terminated with nul
1203  * (nul is also the value of #DBUS_TYPE_INVALID).
1204  * 
1205  * @param message the message
1206  * @param signature the type signature or #NULL to unset
1207  * @returns #FALSE if no memory
1208  */
1209 static dbus_bool_t
1210 dbus_message_set_signature (DBusMessage *message,
1211                             const char  *signature)
1212 {
1213   _dbus_return_val_if_fail (message != NULL, FALSE);
1214   _dbus_return_val_if_fail (!message->locked, FALSE);
1215   
1216   return set_string_field (message,
1217                            DBUS_HEADER_FIELD_SIGNATURE,
1218                            DBUS_TYPE_STRING,
1219                            signature);
1220 }
1221
1222 /**
1223  * Appends to the signature of the message.
1224  * (currently a static function, maybe should be public?)
1225  * 
1226  * @param message the message
1227  * @param append_bytes nul-terminated bytes to append to the type signature
1228  * @returns #FALSE if no memory
1229  */
1230 static dbus_bool_t
1231 dbus_message_append_to_signature (DBusMessage *message,
1232                                   const char  *append_bytes)
1233 {
1234   const char *signature;
1235   DBusString append_str;
1236   dbus_bool_t retval;
1237   
1238   _dbus_return_val_if_fail (append_bytes != NULL, FALSE);
1239   _dbus_return_val_if_fail (message != NULL, FALSE);
1240   _dbus_return_val_if_fail (!message->locked, FALSE);
1241
1242   retval = FALSE;
1243   
1244   /* FIXME Just really inefficient for the moment; later we could
1245    * speed it up a lot by poking more directly at the header data
1246    */
1247   signature = dbus_message_get_signature (message);
1248
1249   if (!_dbus_string_init (&append_str))
1250     return FALSE;
1251
1252   if (signature && !_dbus_string_append (&append_str, signature))
1253     goto out;
1254
1255   if (!_dbus_string_append (&append_str, append_bytes))
1256     goto out;
1257   
1258   if (!set_string_field (message,
1259                          DBUS_HEADER_FIELD_SIGNATURE,
1260                          DBUS_TYPE_STRING,
1261                          _dbus_string_get_const_data (&append_str)))
1262     goto out;
1263
1264   retval = TRUE;
1265   
1266  out:
1267   
1268   _dbus_string_free (&append_str);
1269
1270   return retval;
1271 }
1272
1273 /**
1274  * Appends one byte to the signature of the message.
1275  * Internal function.
1276  * 
1277  * @param message the message
1278  * @param append_byte the byte 
1279  * @returns #FALSE if no memory
1280  */
1281 static dbus_bool_t
1282 _dbus_message_append_byte_to_signature (DBusMessage  *message,
1283                                         unsigned char append_byte)
1284 {
1285   char buf[2];
1286   
1287   _dbus_return_val_if_fail (message != NULL, FALSE);
1288   _dbus_return_val_if_fail (!message->locked, FALSE);
1289   
1290   buf[0] = append_byte;
1291   buf[1] = '\0';
1292
1293   return dbus_message_append_to_signature (message, buf);
1294 }
1295
1296 /**
1297  * Removes the last byte from the signature of the message.
1298  * Internal function.
1299  * 
1300  * @param message the message
1301  */
1302 static void
1303 _dbus_message_remove_byte_from_signature (DBusMessage  *message)
1304 {
1305   const char *signature;
1306   
1307   _dbus_return_if_fail (message != NULL);
1308   _dbus_return_if_fail (!message->locked);
1309
1310   signature = dbus_message_get_signature (message);
1311
1312   _dbus_return_if_fail (signature != NULL);
1313   
1314   if (!delete_field (message,
1315                      DBUS_HEADER_FIELD_SIGNATURE,
1316                      0))
1317     _dbus_assert_not_reached ("failed to delete signature field");
1318
1319   /* reappend one shorter (could this be any less efficient? the code will
1320    * go away later anyhow)
1321    */
1322   if (!append_string_field_len (message, DBUS_HEADER_FIELD_SIGNATURE,
1323                                 DBUS_TYPE_STRING, signature,
1324                                 strlen (signature) - 1))
1325     _dbus_assert_not_reached ("reappending shorter signature shouldn't have failed");
1326 }
1327
1328 /**
1329  * @typedef DBusMessage
1330  *
1331  * Opaque data type representing a message received from or to be
1332  * sent to another application.
1333  */
1334
1335 static DBusMessage*
1336 dbus_message_new_empty_header (void)
1337 {
1338   DBusMessage *message;
1339   int i;
1340   
1341   message = dbus_new0 (DBusMessage, 1);
1342   if (message == NULL)
1343     return NULL;
1344   
1345   message->refcount.value = 1;
1346   message->byte_order = DBUS_COMPILER_BYTE_ORDER;
1347   message->client_serial = 0;
1348   message->reply_serial = 0;
1349
1350   _dbus_data_slot_list_init (&message->slot_list);
1351   
1352   i = 0;
1353   while (i <= DBUS_HEADER_FIELD_LAST)
1354     {
1355       message->header_fields[i].name_offset  = -1;
1356       message->header_fields[i].value_offset = -1;
1357       ++i;
1358     }
1359   
1360   if (!_dbus_string_init_preallocated (&message->header, 256))
1361     {
1362       dbus_free (message);
1363       return NULL;
1364     }
1365   
1366   if (!_dbus_string_init_preallocated (&message->body, 64))
1367     {
1368       _dbus_string_free (&message->header);
1369       dbus_free (message);
1370       return NULL;
1371     }
1372   
1373   return message;
1374 }
1375
1376 /**
1377  * Constructs a new message of the given message type.
1378  * Types include #DBUS_MESSAGE_TYPE_METHOD_CALL,
1379  * #DBUS_MESSAGE_TYPE_SIGNAL, and so forth.
1380  *
1381  * @param message_type type of message
1382  * @returns new message or #NULL If no memory
1383  */
1384 DBusMessage*
1385 dbus_message_new (int message_type)
1386 {
1387   DBusMessage *message;
1388
1389   _dbus_return_val_if_fail (message_type != DBUS_MESSAGE_TYPE_INVALID, NULL);
1390   
1391   message = dbus_message_new_empty_header ();
1392   if (message == NULL)
1393     return NULL;
1394   
1395   if (!dbus_message_create_header (message,
1396                                    message_type,
1397                                    NULL, NULL, NULL, NULL, NULL))
1398     {
1399       dbus_message_unref (message);
1400       return NULL;
1401     }
1402   
1403   return message;
1404 }
1405
1406 /**
1407  * Constructs a new message to invoke a method on a remote
1408  * object. Returns #NULL if memory can't be allocated for the
1409  * message. The service may be #NULL in which case no service is set;
1410  * this is appropriate when using D-BUS in a peer-to-peer context (no
1411  * message bus). The interface may be #NULL, which means that
1412  * if multiple methods with the given name exist it is undefined
1413  * which one will be invoked.
1414   *
1415  * @param service service that the message should be sent to or #NULL
1416  * @param path object path the message should be sent to
1417  * @param interface interface to invoke method on
1418  * @param method method to invoke
1419  * 
1420  * @returns a new DBusMessage, free with dbus_message_unref()
1421  * @see dbus_message_unref()
1422  */
1423 DBusMessage*
1424 dbus_message_new_method_call (const char *service,
1425                               const char *path,
1426                               const char *interface,
1427                               const char *method)
1428 {
1429   DBusMessage *message;
1430
1431   _dbus_return_val_if_fail (path != NULL, NULL);
1432   _dbus_return_val_if_fail (method != NULL, NULL);
1433   
1434   message = dbus_message_new_empty_header ();
1435   if (message == NULL)
1436     return NULL;
1437   
1438   if (!dbus_message_create_header (message,
1439                                    DBUS_MESSAGE_TYPE_METHOD_CALL,
1440                                    service, path, interface, method, NULL))
1441     {
1442       dbus_message_unref (message);
1443       return NULL;
1444     }
1445   
1446   return message;
1447 }
1448
1449 /**
1450  * Constructs a message that is a reply to a method call. Returns
1451  * #NULL if memory can't be allocated for the message.
1452  *
1453  * @param method_call the message which the created
1454  * message is a reply to.
1455  * @returns a new DBusMessage, free with dbus_message_unref()
1456  * @see dbus_message_new_method_call(), dbus_message_unref()
1457  */ 
1458 DBusMessage*
1459 dbus_message_new_method_return (DBusMessage *method_call)
1460 {
1461   DBusMessage *message;
1462   const char *sender;
1463
1464   _dbus_return_val_if_fail (method_call != NULL, NULL);
1465   
1466   sender = get_string_field (method_call,
1467                              DBUS_HEADER_FIELD_SENDER,
1468                              NULL);
1469   
1470   /* sender is allowed to be null here in peer-to-peer case */
1471
1472   message = dbus_message_new_empty_header ();
1473   if (message == NULL)
1474     return NULL;
1475   
1476   if (!dbus_message_create_header (message,
1477                                    DBUS_MESSAGE_TYPE_METHOD_RETURN,
1478                                    sender, NULL, NULL, NULL, NULL))
1479     {
1480       dbus_message_unref (message);
1481       return NULL;
1482     }
1483
1484   dbus_message_set_no_reply (message, TRUE);
1485
1486   if (!dbus_message_set_reply_serial (message,
1487                                       dbus_message_get_serial (method_call)))
1488     {
1489       dbus_message_unref (message);
1490       return NULL;
1491     }
1492
1493   return message;
1494 }
1495
1496 /**
1497  * Constructs a new message representing a signal emission. Returns
1498  * #NULL if memory can't be allocated for the message.
1499  * A signal is identified by its originating interface, and
1500  * the name of the signal.
1501  *
1502  * @param path the path to the object emitting the signal
1503  * @param interface the interface the signal is emitted from
1504  * @param name name of the signal
1505  * @returns a new DBusMessage, free with dbus_message_unref()
1506  * @see dbus_message_unref()
1507  */
1508 DBusMessage*
1509 dbus_message_new_signal (const char *path,
1510                          const char *interface,
1511                          const char *name)
1512 {
1513   DBusMessage *message;
1514
1515   _dbus_return_val_if_fail (path != NULL, NULL);
1516   _dbus_return_val_if_fail (interface != NULL, NULL);
1517   _dbus_return_val_if_fail (name != NULL, NULL);
1518   
1519   message = dbus_message_new_empty_header ();
1520   if (message == NULL)
1521     return NULL;
1522   
1523   if (!dbus_message_create_header (message,
1524                                    DBUS_MESSAGE_TYPE_SIGNAL,
1525                                    NULL, path, interface, name, NULL))
1526     {
1527       dbus_message_unref (message);
1528       return NULL;
1529     }
1530
1531   dbus_message_set_no_reply (message, TRUE);
1532   
1533   return message;
1534 }
1535
1536 /**
1537  * Creates a new message that is an error reply to a certain message.
1538  * Error replies are possible in response to method calls primarily.
1539  *
1540  * @param reply_to the original message
1541  * @param error_name the error name
1542  * @param error_message the error message string or #NULL for none
1543  * @returns a new error message
1544  */
1545 DBusMessage*
1546 dbus_message_new_error (DBusMessage *reply_to,
1547                         const char  *error_name,
1548                         const char  *error_message)
1549 {
1550   DBusMessage *message;
1551   const char *sender;
1552   DBusMessageIter iter;
1553
1554   _dbus_return_val_if_fail (reply_to != NULL, NULL);
1555   _dbus_return_val_if_fail (error_name != NULL, NULL);
1556   _dbus_return_val_if_fail (is_valid_error_name (error_name), NULL);
1557   
1558   sender = get_string_field (reply_to,
1559                              DBUS_HEADER_FIELD_SENDER,
1560                              NULL);
1561
1562   /* sender may be NULL for non-message-bus case or
1563    * when the message bus is dealing with an unregistered
1564    * connection.
1565    */
1566   message = dbus_message_new_empty_header ();
1567   if (message == NULL)
1568     return NULL;
1569   
1570   if (!dbus_message_create_header (message,
1571                                    DBUS_MESSAGE_TYPE_ERROR,
1572                                    sender, NULL, NULL, NULL, error_name))
1573     {
1574       dbus_message_unref (message);
1575       return NULL;
1576     }
1577
1578   dbus_message_set_no_reply (message, TRUE);
1579   
1580   if (!dbus_message_set_reply_serial (message,
1581                                       dbus_message_get_serial (reply_to)))
1582     {
1583       dbus_message_unref (message);
1584       return NULL;
1585     }
1586
1587   if (error_message != NULL)
1588     {
1589       dbus_message_append_iter_init (message, &iter);
1590       if (!dbus_message_iter_append_string (&iter, error_message))
1591         {
1592           dbus_message_unref (message);
1593           return NULL;
1594         }
1595     }
1596   
1597   return message;
1598 }
1599
1600 /**
1601  * Creates a new message that is an error reply to a certain message.
1602  * Error replies are possible in response to method calls primarily.
1603  *
1604  * @param reply_to the original message
1605  * @param error_name the error name
1606  * @param error_format the error message string to be printed
1607  * @param ... value of first argument, list of additional values to print
1608  * @returns a new error message
1609  */
1610 DBusMessage*
1611 dbus_message_new_error_printf (DBusMessage *reply_to,
1612                                const char  *error_name,
1613                                const char  *error_format,
1614                                ...)
1615 {
1616   va_list args;
1617   DBusString str;
1618   DBusMessage *message;
1619
1620   _dbus_return_val_if_fail (reply_to != NULL, NULL);
1621   _dbus_return_val_if_fail (error_name != NULL, NULL);
1622   _dbus_return_val_if_fail (is_valid_error_name (error_name), NULL);
1623   
1624   if (!_dbus_string_init (&str))
1625     return NULL;
1626
1627   va_start (args, error_format);
1628
1629   if (_dbus_string_append_printf_valist (&str, error_format, args))
1630     message = dbus_message_new_error (reply_to, error_name,
1631                                       _dbus_string_get_const_data (&str));
1632   else
1633     message = NULL;
1634   
1635   _dbus_string_free (&str);
1636
1637   va_end (args);
1638
1639   return message;
1640 }
1641
1642
1643 /**
1644  * Creates a new message that is an exact replica of the message
1645  * specified, except that its refcount is set to 1.
1646  *
1647  * @param message the message.
1648  * @returns the new message.
1649  */
1650 DBusMessage *
1651 dbus_message_copy (const DBusMessage *message)
1652 {
1653   DBusMessage *retval;
1654   int i;
1655
1656   _dbus_return_val_if_fail (message != NULL, NULL);
1657   
1658   retval = dbus_new0 (DBusMessage, 1);
1659   if (retval == NULL)
1660     return NULL;
1661   
1662   retval->refcount.value = 1;
1663   retval->byte_order = message->byte_order;
1664   retval->client_serial = message->client_serial;
1665   retval->reply_serial = message->reply_serial;
1666   retval->header_padding = message->header_padding;
1667   retval->locked = FALSE;
1668   
1669   if (!_dbus_string_init_preallocated (&retval->header,
1670                                        _dbus_string_get_length (&message->header)))
1671     {
1672       dbus_free (retval);
1673       return NULL;
1674     }
1675   
1676   if (!_dbus_string_init_preallocated (&retval->body,
1677                                        _dbus_string_get_length (&message->body)))
1678     {
1679       _dbus_string_free (&retval->header);
1680       dbus_free (retval);
1681       return NULL;
1682     }
1683   
1684   if (!_dbus_string_copy (&message->header, 0,
1685                           &retval->header, 0))
1686     goto failed_copy;
1687
1688   if (!_dbus_string_copy (&message->body, 0,
1689                           &retval->body, 0))
1690     goto failed_copy;
1691   
1692   for (i = 0; i <= DBUS_HEADER_FIELD_LAST; i++)
1693     {
1694       retval->header_fields[i] = message->header_fields[i];
1695     }
1696   
1697   return retval;
1698
1699  failed_copy:
1700   _dbus_string_free (&retval->header);
1701   _dbus_string_free (&retval->body);
1702   dbus_free (retval);
1703   
1704   return NULL;  
1705 }
1706
1707
1708 /**
1709  * Increments the reference count of a DBusMessage.
1710  *
1711  * @param message The message
1712  * @returns the message
1713  * @see dbus_message_unref
1714  */
1715 DBusMessage *
1716 dbus_message_ref (DBusMessage *message)
1717 {
1718   dbus_int32_t old_refcount;
1719
1720   _dbus_return_val_if_fail (message != NULL, NULL);
1721   
1722   old_refcount = _dbus_atomic_inc (&message->refcount);
1723   _dbus_assert (old_refcount >= 1);
1724
1725   return message;
1726 }
1727
1728 static void
1729 free_size_counter (void *element,
1730                    void *data)
1731 {
1732   DBusCounter *counter = element;
1733   DBusMessage *message = data;
1734   
1735   _dbus_counter_adjust (counter, - message->size_counter_delta);
1736
1737   _dbus_counter_unref (counter);
1738 }
1739
1740 /**
1741  * Decrements the reference count of a DBusMessage.
1742  *
1743  * @param message The message
1744  * @see dbus_message_ref
1745  */
1746 void
1747 dbus_message_unref (DBusMessage *message)
1748 {
1749  dbus_int32_t old_refcount;
1750
1751   _dbus_return_if_fail (message != NULL);
1752   
1753   old_refcount = _dbus_atomic_dec (&message->refcount);
1754   
1755   _dbus_assert (old_refcount >= 0);
1756
1757   if (old_refcount == 1)
1758     {
1759       /* This calls application callbacks! */
1760       _dbus_data_slot_list_free (&message->slot_list);
1761       
1762       _dbus_list_foreach (&message->size_counters,
1763                           free_size_counter, message);
1764       _dbus_list_clear (&message->size_counters);
1765       
1766       _dbus_string_free (&message->header);
1767       _dbus_string_free (&message->body);
1768       
1769       dbus_free (message);
1770     }
1771 }
1772
1773 /**
1774  * Gets the type of a message. Types include
1775  * DBUS_MESSAGE_TYPE_METHOD_CALL, DBUS_MESSAGE_TYPE_METHOD_RETURN,
1776  * DBUS_MESSAGE_TYPE_ERROR, DBUS_MESSAGE_TYPE_SIGNAL, but other types
1777  * are allowed and all code must silently ignore messages of unknown
1778  * type. DBUS_MESSAGE_TYPE_INVALID will never be returned, however.
1779  *
1780  *
1781  * @param message the message
1782  * @returns the type of the message
1783  */
1784 int
1785 dbus_message_get_type (DBusMessage *message)
1786 {
1787   int type;
1788
1789   type = _dbus_string_get_byte (&message->header, 1);
1790   _dbus_assert (type != DBUS_MESSAGE_TYPE_INVALID);
1791
1792   return type;
1793 }
1794
1795 /**
1796  * Sets the object path this message is being sent to (for
1797  * DBUS_MESSAGE_TYPE_METHOD_CALL) or the one a signal is being
1798  * emitted from (for DBUS_MESSAGE_TYPE_SIGNAL).
1799  *
1800  * @param message the message
1801  * @param object_path the path or #NULL to unset
1802  * @returns #FALSE if not enough memory
1803  */
1804 dbus_bool_t
1805 dbus_message_set_path (DBusMessage   *message,
1806                        const char    *object_path)
1807 {
1808   _dbus_return_val_if_fail (message != NULL, FALSE);
1809   _dbus_return_val_if_fail (!message->locked, FALSE);
1810
1811   return set_string_field (message,
1812                            DBUS_HEADER_FIELD_PATH,
1813                            DBUS_TYPE_OBJECT_PATH,
1814                            object_path);
1815 }
1816
1817 /**
1818  * Gets the object path this message is being sent to
1819  * (for DBUS_MESSAGE_TYPE_METHOD_CALL) or being emitted
1820  * from (for DBUS_MESSAGE_TYPE_SIGNAL).
1821  *
1822  * @param message the message
1823  * @returns the path (should not be freed)
1824  */
1825 const char*
1826 dbus_message_get_path (DBusMessage   *message)
1827 {
1828   _dbus_return_val_if_fail (message != NULL, NULL);
1829   
1830   return get_string_field (message, DBUS_HEADER_FIELD_PATH, NULL);
1831 }
1832
1833 /**
1834  * Gets the object path this message is being sent to
1835  * (for DBUS_MESSAGE_TYPE_METHOD_CALL) or being emitted
1836  * from (for DBUS_MESSAGE_TYPE_SIGNAL) in a decomposed
1837  * format (one array element per path component).
1838  * Free the returned array with dbus_free_string_array().
1839  *
1840  * An empty but non-NULL path array means the path "/".
1841  * So the path "/foo/bar" becomes { "foo", "bar", NULL }
1842  * and the path "/" becomes { NULL }.
1843  *
1844  * @param message the message
1845  * @param path place to store allocated array of path components; #NULL set here if no path field exists
1846  * @returns #FALSE if no memory to allocate the array
1847  */
1848 dbus_bool_t
1849 dbus_message_get_path_decomposed (DBusMessage   *message,
1850                                   char        ***path)
1851 {
1852   _dbus_return_val_if_fail (message != NULL, FALSE);
1853   _dbus_return_val_if_fail (path != NULL, FALSE);
1854
1855   return get_path_field_decomposed (message,
1856                                     DBUS_HEADER_FIELD_PATH,
1857                                     path);
1858 }
1859
1860 /**
1861  * Sets the interface this message is being sent to
1862  * (for DBUS_MESSAGE_TYPE_METHOD_CALL) or
1863  * the interface a signal is being emitted from
1864  * (for DBUS_MESSAGE_TYPE_SIGNAL).
1865  *
1866  * @param message the message
1867  * @param interface the interface or #NULL to unset
1868  * @returns #FALSE if not enough memory
1869  */
1870 dbus_bool_t
1871 dbus_message_set_interface (DBusMessage  *message,
1872                             const char   *interface)
1873 {
1874   _dbus_return_val_if_fail (message != NULL, FALSE);
1875   _dbus_return_val_if_fail (!message->locked, FALSE);
1876
1877   return set_string_field (message,
1878                            DBUS_HEADER_FIELD_INTERFACE,
1879                            DBUS_TYPE_STRING,
1880                            interface);
1881 }
1882
1883 /**
1884  * Gets the interface this message is being sent to
1885  * (for DBUS_MESSAGE_TYPE_METHOD_CALL) or being emitted
1886  * from (for DBUS_MESSAGE_TYPE_SIGNAL).
1887  * The interface name is fully-qualified (namespaced).
1888  *
1889  * @param message the message
1890  * @returns the message interface (should not be freed)
1891  */
1892 const char*
1893 dbus_message_get_interface (DBusMessage *message)
1894 {
1895   _dbus_return_val_if_fail (message != NULL, NULL);
1896   
1897   return get_string_field (message, DBUS_HEADER_FIELD_INTERFACE, NULL);
1898 }
1899
1900 /**
1901  * Sets the interface member being invoked
1902  * (DBUS_MESSAGE_TYPE_METHOD_CALL) or emitted
1903  * (DBUS_MESSAGE_TYPE_SIGNAL).
1904  * The interface name is fully-qualified (namespaced).
1905  *
1906  * @param message the message
1907  * @param member the member or #NULL to unset
1908  * @returns #FALSE if not enough memory
1909  */
1910 dbus_bool_t
1911 dbus_message_set_member (DBusMessage  *message,
1912                        const char   *member)
1913 {
1914   _dbus_return_val_if_fail (message != NULL, FALSE);
1915   _dbus_return_val_if_fail (!message->locked, FALSE);
1916
1917   return set_string_field (message,
1918                            DBUS_HEADER_FIELD_MEMBER,
1919                            DBUS_TYPE_STRING,
1920                            member);
1921 }
1922
1923 /**
1924  * Gets the interface member being invoked
1925  * (DBUS_MESSAGE_TYPE_METHOD_CALL) or emitted
1926  * (DBUS_MESSAGE_TYPE_SIGNAL).
1927  * 
1928  * @param message the message
1929  * @returns the member name (should not be freed)
1930  */
1931 const char*
1932 dbus_message_get_member (DBusMessage *message)
1933 {
1934   _dbus_return_val_if_fail (message != NULL, NULL);
1935   
1936   return get_string_field (message,
1937                            DBUS_HEADER_FIELD_MEMBER,
1938                            NULL);
1939 }
1940
1941 /**
1942  * Sets the name of the error (DBUS_MESSAGE_TYPE_ERROR).
1943  * The name is fully-qualified (namespaced).
1944  *
1945  * @param message the message
1946  * @param error_name the name or #NULL to unset
1947  * @returns #FALSE if not enough memory
1948  */
1949 dbus_bool_t
1950 dbus_message_set_error_name (DBusMessage  *message,
1951                              const char   *error_name)
1952 {
1953   _dbus_return_val_if_fail (message != NULL, FALSE);
1954   _dbus_return_val_if_fail (!message->locked, FALSE);
1955   _dbus_return_val_if_fail (error_name == NULL || is_valid_error_name (error_name), FALSE);
1956   
1957   return set_string_field (message,
1958                            DBUS_HEADER_FIELD_ERROR_NAME,
1959                            DBUS_TYPE_STRING,
1960                            error_name);
1961 }
1962
1963 /**
1964  * Gets the error name (DBUS_MESSAGE_TYPE_ERROR only).
1965  * 
1966  * @param message the message
1967  * @returns the error name (should not be freed)
1968  */
1969 const char*
1970 dbus_message_get_error_name (DBusMessage *message)
1971 {
1972   _dbus_return_val_if_fail (message != NULL, NULL);
1973   
1974   return get_string_field (message,
1975                            DBUS_HEADER_FIELD_ERROR_NAME,
1976                            NULL);
1977 }
1978
1979 /**
1980  * Sets the message's destination service.
1981  *
1982  * @param message the message
1983  * @param destination the destination service name or #NULL to unset
1984  * @returns #FALSE if not enough memory
1985  */
1986 dbus_bool_t
1987 dbus_message_set_destination (DBusMessage  *message,
1988                               const char   *destination)
1989 {
1990   _dbus_return_val_if_fail (message != NULL, FALSE);
1991   _dbus_return_val_if_fail (!message->locked, FALSE);
1992
1993   return set_string_field (message,
1994                            DBUS_HEADER_FIELD_DESTINATION,
1995                            DBUS_TYPE_STRING,
1996                            destination);
1997 }
1998
1999 /**
2000  * Gets the destination service of a message.
2001  * 
2002  * @param message the message
2003  * @returns the message destination service (should not be freed)
2004  */
2005 const char*
2006 dbus_message_get_destination (DBusMessage *message)
2007 {
2008   _dbus_return_val_if_fail (message != NULL, NULL);
2009   
2010   return get_string_field (message,
2011                            DBUS_HEADER_FIELD_DESTINATION,
2012                            NULL);
2013 }
2014
2015 /**
2016  * Appends fields to a message given a variable argument list. The
2017  * variable argument list should contain the type of the argument
2018  * followed by the value to add.  Array values are specified by an int
2019  * typecode followed by a pointer to the array followed by an int
2020  * giving the length of the array.  The argument list must be
2021  * terminated with #DBUS_TYPE_INVALID.
2022  *
2023  * This function doesn't support dicts or non-fundamental arrays.
2024  *
2025  * This function supports #DBUS_TYPE_INT64 and #DBUS_TYPE_UINT64
2026  * only if #DBUS_HAVE_INT64 is defined.
2027  *
2028  * @param message the message
2029  * @param first_arg_type type of the first argument
2030  * @param ... value of first argument, list of additional type-value pairs
2031  * @returns #TRUE on success
2032  */
2033 dbus_bool_t
2034 dbus_message_append_args (DBusMessage *message,
2035                           int first_arg_type,
2036                           ...)
2037 {
2038   dbus_bool_t retval;
2039   va_list var_args;
2040
2041   _dbus_return_val_if_fail (message != NULL, FALSE);
2042   
2043   va_start (var_args, first_arg_type);
2044   retval = dbus_message_append_args_valist (message,
2045                                             first_arg_type,
2046                                             var_args);
2047   va_end (var_args);
2048
2049   return retval;
2050 }
2051
2052 /**
2053  * Gets arguments from a message given a variable argument list.
2054  * The variable argument list should contain the type of the
2055  * argumen followed by a pointer to where the value should be
2056  * stored. The list is terminated with #DBUS_TYPE_INVALID.
2057  *
2058  * @param message the message
2059  * @param error error to be filled in on failure
2060  * @param first_arg_type the first argument type
2061  * @param ... location for first argument value, then list of type-location pairs
2062  * @returns #FALSE if the error was set
2063  */
2064 dbus_bool_t
2065 dbus_message_get_args (DBusMessage     *message,
2066                        DBusError       *error,
2067                        int              first_arg_type,
2068                        ...)
2069 {
2070   dbus_bool_t retval;
2071   va_list var_args;
2072
2073   _dbus_return_val_if_fail (message != NULL, FALSE);
2074   _dbus_return_val_if_error_is_set (error, FALSE);
2075   
2076   va_start (var_args, first_arg_type);
2077   retval = dbus_message_get_args_valist (message, error, first_arg_type, var_args);
2078   va_end (var_args);
2079
2080   return retval;
2081 }
2082
2083 /**
2084  * This function takes a va_list for use by language bindings
2085  *
2086  * @todo We need to free the argument data when an error occurs.
2087  *
2088  * @see dbus_message_get_args
2089  * @param message the message
2090  * @param error error to be filled in
2091  * @param first_arg_type type of the first argument
2092  * @param var_args return location for first argument, followed by list of type/location pairs
2093  * @returns #FALSE if error was set
2094  */
2095 dbus_bool_t
2096 dbus_message_get_args_valist (DBusMessage     *message,
2097                               DBusError       *error,
2098                               int              first_arg_type,
2099                               va_list          var_args)
2100 {
2101   DBusMessageIter iter;
2102
2103   _dbus_return_val_if_fail (message != NULL, FALSE);
2104   _dbus_return_val_if_error_is_set (error, FALSE);
2105   
2106   dbus_message_iter_init (message, &iter);
2107   return dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args);
2108 }
2109
2110 /**
2111  * Gets arguments from a message iterator given a variable argument list.
2112  * The variable argument list should contain the type of the
2113  * argumen followed by a pointer to where the value should be
2114  * stored. The list is terminated with 0.
2115  *
2116  * @param iter the message iterator 
2117  * @param error error to be filled in on failure
2118  * @param first_arg_type the first argument type
2119  * @param ... location for first argument value, then list of type-location pairs
2120  * @returns #FALSE if the error was set
2121  */
2122 dbus_bool_t
2123 dbus_message_iter_get_args (DBusMessageIter *iter,
2124                             DBusError       *error,
2125                             int              first_arg_type,
2126                             ...)
2127 {
2128   dbus_bool_t retval;
2129   va_list var_args;
2130
2131   _dbus_return_val_if_fail (iter != NULL, FALSE);
2132   _dbus_return_val_if_error_is_set (error, FALSE);
2133   
2134   va_start (var_args, first_arg_type);
2135   retval = dbus_message_iter_get_args_valist (iter, error, first_arg_type, var_args);
2136   va_end (var_args);
2137
2138   return retval;
2139 }
2140
2141 /**
2142  * Initializes a DBusMessageIter representing the arguments of the
2143  * message passed in.
2144  *
2145  * @param message the message
2146  * @param iter pointer to an iterator to initialize
2147  * @returns #FALSE if the message has no arguments
2148  */
2149 dbus_bool_t
2150 dbus_message_iter_init (DBusMessage     *message,
2151                         DBusMessageIter *iter)
2152 {
2153   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2154
2155   _dbus_return_val_if_fail (message != NULL, FALSE);
2156   _dbus_return_val_if_fail (iter != NULL, FALSE);
2157   
2158   _dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
2159   
2160   real->message = message;
2161   real->parent_iter = NULL;
2162   real->changed_stamp = message->changed_stamp;
2163   
2164   real->type = DBUS_MESSAGE_ITER_TYPE_MESSAGE;
2165   real->pos = 0;
2166   real->end = _dbus_string_get_length (&message->body);
2167   
2168   real->container_start = 0;
2169   real->container_length_pos = 0;
2170   real->wrote_dict_key = 0;
2171   real->array_type_pos = 0;
2172
2173   return real->end > real->pos;
2174 }
2175
2176 #ifndef DBUS_DISABLE_CHECKS
2177 static dbus_bool_t
2178 dbus_message_iter_check (DBusMessageRealIter *iter)
2179 {
2180   if (iter == NULL)
2181     {
2182       _dbus_warn ("dbus iterator check failed: iterator is NULL\n");
2183       return FALSE;
2184     }
2185   
2186   if (iter->changed_stamp != iter->message->changed_stamp)
2187     {
2188       _dbus_warn ("dbus iterator check failed: invalid iterator, must re-initialize it after modifying the message\n");
2189       return FALSE;
2190     }
2191   
2192   if (iter->pos < 0 || iter->pos > iter->end)
2193     {
2194       _dbus_warn ("dbus iterator check failed: invalid position\n");
2195       return FALSE;
2196     }
2197
2198   return TRUE;
2199 }
2200 #endif /* DBUS_DISABLE_CHECKS */
2201
2202 static int
2203 skip_array_type (DBusMessageRealIter *iter, int pos)
2204 {
2205   const char *data;
2206
2207   do
2208     {
2209       data = _dbus_string_get_const_data_len (&iter->message->body,
2210                                               pos++, 1);
2211     }
2212   while (*data == DBUS_TYPE_ARRAY);
2213   
2214   return pos;
2215 }
2216
2217 /* FIXME what are these _dbus_type_is_valid() checks for?
2218  * haven't we validated the message?
2219  */
2220 static int
2221 dbus_message_iter_get_data_start (DBusMessageRealIter *iter, int *type)
2222 {
2223   const char *data;
2224   int pos, len;
2225   
2226   switch (iter->type)
2227     {
2228     case DBUS_MESSAGE_ITER_TYPE_MESSAGE:
2229       data = _dbus_string_get_const_data_len (&iter->message->body,
2230                                               iter->pos, 1);
2231       if (_dbus_type_is_valid (*data))
2232         *type = *data;
2233       else
2234         *type = DBUS_TYPE_INVALID;
2235       
2236       return skip_array_type (iter, iter->pos);
2237       
2238     case DBUS_MESSAGE_ITER_TYPE_ARRAY:
2239       data = _dbus_string_get_const_data_len (&iter->message->body,
2240                                               iter->array_type_pos, 1);
2241       if (_dbus_type_is_valid (*data))
2242         *type = *data;
2243       else
2244         *type = DBUS_TYPE_INVALID;
2245       
2246       return iter->pos;
2247       
2248     case DBUS_MESSAGE_ITER_TYPE_DICT:
2249       /* Get the length of the string */
2250       len = _dbus_demarshal_uint32 (&iter->message->body,
2251                                     iter->message->byte_order,
2252                                     iter->pos, &pos);
2253       pos = pos + len + 1;
2254
2255       data = _dbus_string_get_const_data_len (&iter->message->body,
2256                                               pos, 1);
2257       if (_dbus_type_is_valid (*data))
2258         *type = *data;
2259       else
2260         *type = DBUS_TYPE_INVALID;
2261
2262       return skip_array_type (iter, pos);
2263       
2264     default:
2265       _dbus_assert_not_reached ("Invalid iter type");
2266       break;
2267     }
2268   *type = DBUS_TYPE_INVALID;
2269   return iter->pos;
2270 }
2271
2272
2273 /**
2274  * Checks if an iterator has any more fields.
2275  *
2276  * @param iter the message iter
2277  * @returns #TRUE if there are more fields
2278  * following
2279  */
2280 dbus_bool_t
2281 dbus_message_iter_has_next (DBusMessageIter *iter)
2282 {
2283   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2284   int end_pos;
2285   int type, pos;
2286
2287   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
2288
2289   if (real->pos >= real->end)
2290     return FALSE;
2291   
2292   pos = dbus_message_iter_get_data_start (real, &type);
2293   
2294   if (!_dbus_marshal_get_arg_end_pos (&real->message->body,
2295                                       real->message->byte_order,
2296                                       type, pos, &end_pos))
2297     return FALSE;
2298   
2299   if (end_pos >= real->end)
2300     return FALSE;
2301
2302   return TRUE;  
2303 }
2304
2305 /**
2306  * Moves the iterator to the next field.
2307  *
2308  * @param iter The message iter
2309  * @returns #TRUE if the iterator was moved to the next field
2310  */
2311 dbus_bool_t
2312 dbus_message_iter_next (DBusMessageIter *iter)
2313 {
2314   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2315   int end_pos;
2316   int type, pos;
2317
2318   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
2319
2320   pos = dbus_message_iter_get_data_start (real, &type);
2321   
2322   if (!_dbus_marshal_get_arg_end_pos (&real->message->body,
2323                                       real->message->byte_order,
2324                                       type, pos, &end_pos))
2325     return FALSE;
2326
2327   if (end_pos >= real->end)
2328     return FALSE;
2329
2330   real->pos = end_pos;
2331
2332   return TRUE;
2333 }
2334
2335 /**
2336  * Returns the argument type of the argument that the
2337  * message iterator points at.
2338  *
2339  * @param iter the message iter
2340  * @returns the field type
2341  */
2342 int
2343 dbus_message_iter_get_arg_type (DBusMessageIter *iter)
2344 {
2345   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2346   int type, pos;
2347
2348   _dbus_return_val_if_fail (dbus_message_iter_check (real), DBUS_TYPE_INVALID);
2349
2350   if (real->pos >= real->end)
2351     {
2352       _dbus_verbose ("  iterator at or beyond end of message\n");
2353       return DBUS_TYPE_INVALID;
2354     }
2355
2356   pos = dbus_message_iter_get_data_start (real, &type);
2357   
2358   return type;
2359 }
2360
2361 /* FIXME why do we validate the typecode in here, hasn't the message
2362  * already been verified?
2363  */
2364 static int
2365 iter_get_array_type (DBusMessageRealIter *iter, int *array_type_pos)
2366 {
2367   const char *data;
2368   int _array_type_pos;
2369   int len, pos;
2370   
2371   switch (iter->type)
2372     {
2373     case DBUS_MESSAGE_ITER_TYPE_MESSAGE:
2374       _array_type_pos = iter->pos + 1;
2375       break;
2376     case DBUS_MESSAGE_ITER_TYPE_ARRAY:
2377       _array_type_pos = iter->array_type_pos + 1;
2378       break;
2379     case DBUS_MESSAGE_ITER_TYPE_DICT:
2380       /* Get the length of the string */
2381       len = _dbus_demarshal_uint32 (&iter->message->body,
2382                                     iter->message->byte_order,
2383                                     iter->pos, &pos);
2384       pos = pos + len + 1;
2385       data = _dbus_string_get_const_data_len (&iter->message->body,
2386                                               pos + 1, 1);
2387       _array_type_pos = pos + 1;
2388       break;
2389     default:
2390       _dbus_assert_not_reached ("wrong iter type");
2391       return DBUS_TYPE_INVALID;
2392     }
2393
2394   if (array_type_pos != NULL)
2395     *array_type_pos = _array_type_pos;
2396   
2397   data = _dbus_string_get_const_data_len (&iter->message->body,
2398                                           _array_type_pos, 1);
2399   if (_dbus_type_is_valid (*data))
2400     return  *data;
2401   
2402   return DBUS_TYPE_INVALID;
2403 }
2404
2405
2406 /**
2407  * Returns the element type of the array that the
2408  * message iterator points at. Note that you need
2409  * to check that the iterator points to an array
2410  * prior to using this function.
2411  *
2412  * @param iter the message iter
2413  * @returns the field type
2414  */
2415 int
2416 dbus_message_iter_get_array_type (DBusMessageIter *iter)
2417 {
2418   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2419   int type, pos;
2420
2421   _dbus_return_val_if_fail (dbus_message_iter_check (real), DBUS_TYPE_INVALID);
2422
2423   if (real->pos >= real->end)
2424     return DBUS_TYPE_INVALID;
2425
2426   pos = dbus_message_iter_get_data_start (real, &type);
2427
2428   _dbus_assert (type == DBUS_TYPE_ARRAY);
2429
2430   return iter_get_array_type (real, NULL);
2431 }
2432
2433
2434 /**
2435  * Returns the string value that an iterator may point to.
2436  * Note that you need to check that the iterator points to
2437  * a string value before using this function.
2438  *
2439  * @see dbus_message_iter_get_arg_type
2440  * @param iter the message iter
2441  * @returns the string
2442  */
2443 char *
2444 dbus_message_iter_get_string (DBusMessageIter *iter)
2445 {
2446   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2447   int type, pos;
2448
2449   _dbus_return_val_if_fail (dbus_message_iter_check (real), NULL);
2450   pos = dbus_message_iter_get_data_start (real, &type);
2451   
2452   _dbus_assert (type == DBUS_TYPE_STRING);
2453
2454   return _dbus_demarshal_string (&real->message->body, real->message->byte_order,
2455                                  pos, NULL);
2456 }
2457
2458 /**
2459  * Returns the object path value that an iterator may point to.
2460  * Note that you need to check that the iterator points to
2461  * an object path value before using this function.
2462  *
2463  * @see dbus_message_iter_get_arg_type
2464  * @param iter the message iter
2465  * @returns the path
2466  */
2467 char *
2468 dbus_message_iter_get_object_path (DBusMessageIter  *iter)
2469 {
2470   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2471   int type, pos;
2472
2473   _dbus_return_val_if_fail (dbus_message_iter_check (real), NULL);
2474
2475   pos = dbus_message_iter_get_data_start (real, &type);
2476   
2477   _dbus_assert (type == DBUS_TYPE_OBJECT_PATH);
2478
2479   return _dbus_demarshal_string (&real->message->body, real->message->byte_order,
2480                                  pos, NULL);
2481 }
2482
2483 /**
2484  * Returns the name and data from a custom type that an iterator may
2485  * point to. Note that you need to check that the iterator points to a
2486  * custom type before using this function.
2487  *
2488  * @see dbus_message_iter_get_arg_type
2489  * @param iter the message iter
2490  * @param name return location for the name of the custom type
2491  * @param value return location for data
2492  * @param len return location for length of data
2493  * @returns TRUE if get succeed
2494  * 
2495  */
2496 dbus_bool_t
2497 dbus_message_iter_get_custom (DBusMessageIter   *iter,
2498                               char             **name,
2499                               unsigned char    **value,
2500                               int               *len)
2501 {
2502   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2503   int type, pos;
2504   char *_name;
2505
2506   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
2507
2508   pos = dbus_message_iter_get_data_start (real, &type);
2509   
2510   _dbus_assert (type == DBUS_TYPE_CUSTOM);
2511   
2512   _name = _dbus_demarshal_string (&real->message->body, real->message->byte_order,
2513                                   pos, &pos);
2514
2515   if (_name == NULL)
2516     return FALSE;
2517   
2518   if (!_dbus_demarshal_byte_array (&real->message->body, real->message->byte_order,
2519                                    pos, NULL, value, len))
2520     {
2521       dbus_free (_name);
2522       return FALSE;
2523     }
2524
2525   *name = _name;
2526   
2527   return TRUE;
2528 }
2529
2530 static void
2531 _dbus_message_iter_get_basic_type (DBusMessageIter *iter,
2532                                    char             type,
2533                                    void            *value)
2534 {
2535   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2536   int item_type, pos;
2537
2538   _dbus_return_if_fail (dbus_message_iter_check (real));
2539
2540   pos = dbus_message_iter_get_data_start (real, &item_type);
2541   
2542   _dbus_assert (type == item_type);
2543   
2544   _dbus_demarshal_basic_type (&real->message->body,
2545                               type, value,
2546                               real->message->byte_order,
2547                               &pos);
2548 }
2549
2550
2551 /**
2552  * This function takes a va_list for use by language bindings
2553  *
2554  * This function supports #DBUS_TYPE_INT64 and #DBUS_TYPE_UINT64
2555  * only if #DBUS_HAVE_INT64 is defined.
2556  *
2557  * @todo this function (or some lower-level non-convenience function)
2558  * needs better error handling; should allow the application to
2559  * distinguish between out of memory, and bad data from the remote
2560  * app. It also needs to not leak a bunch of args when it gets
2561  * to the arg that's bad, as that would be a security hole
2562  * (allow one app to force another to leak memory)
2563  *
2564  * @todo We need to free the argument data when an error occurs.
2565  *
2566  * @see dbus_message_get_args
2567  * @param iter the message iter
2568  * @param error error to be filled in
2569  * @param first_arg_type type of the first argument
2570  * @param var_args return location for first argument, followed by list of type/location pairs
2571  * @returns #FALSE if error was set
2572  */
2573 dbus_bool_t
2574 dbus_message_iter_get_args_valist (DBusMessageIter *iter,
2575                                    DBusError       *error,
2576                                    int              first_arg_type,
2577                                    va_list          var_args)
2578 {
2579   int spec_type, msg_type, i;
2580   dbus_bool_t retval;
2581
2582   _dbus_return_val_if_fail (iter != NULL, FALSE);
2583   _dbus_return_val_if_error_is_set (error, FALSE);
2584
2585   retval = FALSE;
2586   
2587   spec_type = first_arg_type;
2588   i = 0;
2589   
2590   while (spec_type != DBUS_TYPE_INVALID)
2591     {
2592       msg_type = dbus_message_iter_get_arg_type (iter);      
2593       
2594       if (msg_type != spec_type)
2595         {
2596           dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
2597                           "Argument %d is specified to be of type \"%s\", but "
2598                           "is actually of type \"%s\"\n", i,
2599                           _dbus_type_to_string (spec_type),
2600                           _dbus_type_to_string (msg_type));
2601
2602           goto out;
2603         }
2604
2605       switch (spec_type)
2606         {
2607         case DBUS_TYPE_NIL:
2608           break;
2609         case DBUS_TYPE_BOOLEAN:
2610           {
2611             dbus_bool_t *ptr;
2612
2613             ptr = va_arg (var_args, dbus_bool_t *);
2614
2615             *ptr = dbus_message_iter_get_boolean (iter);
2616             break;
2617           }
2618         case DBUS_TYPE_BYTE:
2619         case DBUS_TYPE_INT32:
2620         case DBUS_TYPE_UINT32:
2621 #ifdef DBUS_HAVE_INT64
2622         case DBUS_TYPE_INT64:
2623         case DBUS_TYPE_UINT64:
2624 #endif /* DBUS_HAVE_INT64 */
2625         case DBUS_TYPE_DOUBLE:
2626           {
2627             void *ptr = va_arg (var_args, double *);
2628             _dbus_message_iter_get_basic_type (iter, spec_type, ptr);
2629             break;
2630           }
2631
2632         case DBUS_TYPE_STRING:
2633           {
2634             char **ptr;
2635
2636             ptr = va_arg (var_args, char **);
2637
2638             *ptr = dbus_message_iter_get_string (iter);
2639
2640             if (!*ptr)
2641               {
2642                 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2643                 goto out;
2644               }
2645             
2646             break;
2647           }
2648
2649           case DBUS_TYPE_OBJECT_PATH:
2650           {
2651             char **ptr;
2652
2653             ptr = va_arg (var_args, char **);
2654
2655             *ptr = dbus_message_iter_get_object_path (iter);
2656
2657             if (!*ptr)
2658               {
2659                 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2660                 goto out;
2661               }
2662
2663             break;
2664           }
2665
2666         case DBUS_TYPE_CUSTOM:
2667           {
2668             char **name;
2669             unsigned char **data;
2670             int *len;
2671  
2672             name = va_arg (var_args, char **);
2673             data = va_arg (var_args, unsigned char **);
2674             len = va_arg (var_args, int *);
2675
2676             if (!dbus_message_iter_get_custom (iter, name, data, len))
2677               {
2678                 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2679                 goto out;
2680               }
2681           }
2682           break;
2683         case DBUS_TYPE_ARRAY:
2684           {
2685             void **data;
2686             int *len, type;
2687             dbus_bool_t err = FALSE;
2688  
2689             type = va_arg (var_args, int);
2690             data = va_arg (var_args, void *);
2691             len = va_arg (var_args, int *);
2692
2693             _dbus_return_val_if_fail (data != NULL, FALSE);
2694             _dbus_return_val_if_fail (len != NULL, FALSE);
2695             
2696             if (dbus_message_iter_get_array_type (iter) != type)
2697               {
2698                 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
2699                                 "Argument %d is specified to be of type \"array of %s\", but "
2700                                 "is actually of type \"array of %s\"\n", i,
2701                                 _dbus_type_to_string (type),
2702                                 _dbus_type_to_string (dbus_message_iter_get_array_type (iter)));
2703                 goto out;
2704               }
2705             
2706             switch (type)
2707               {
2708               case DBUS_TYPE_BYTE:
2709                 err = !dbus_message_iter_get_byte_array (iter, (unsigned char **)data, len);
2710                 break;
2711               case DBUS_TYPE_BOOLEAN:
2712                 err = !dbus_message_iter_get_boolean_array (iter, (unsigned char **)data, len);
2713                 break;
2714               case DBUS_TYPE_INT32:
2715                 err = !dbus_message_iter_get_int32_array (iter, (dbus_int32_t **)data, len);
2716                 break;
2717               case DBUS_TYPE_UINT32:
2718                 err = !dbus_message_iter_get_uint32_array (iter, (dbus_uint32_t **)data, len);
2719                 break;
2720 #ifdef DBUS_HAVE_INT64
2721               case DBUS_TYPE_INT64:
2722                 err = !dbus_message_iter_get_int64_array (iter, (dbus_int64_t **)data, len);
2723                 break;
2724               case DBUS_TYPE_UINT64:
2725                 err = !dbus_message_iter_get_uint64_array (iter, (dbus_uint64_t **)data, len);
2726                 break;
2727 #endif /* DBUS_HAVE_INT64 */
2728               case DBUS_TYPE_DOUBLE:
2729                 err = !dbus_message_iter_get_double_array (iter, (double **)data, len);
2730                 break;
2731               case DBUS_TYPE_STRING:
2732                 err = !dbus_message_iter_get_string_array (iter, (char ***)data, len);
2733                 break;
2734               case DBUS_TYPE_OBJECT_PATH:
2735                 err = !dbus_message_iter_get_object_path_array (iter, (char ***)data, len);
2736                 break;
2737
2738               case DBUS_TYPE_NIL:
2739               case DBUS_TYPE_ARRAY:
2740               case DBUS_TYPE_CUSTOM:
2741               case DBUS_TYPE_DICT:
2742                 _dbus_warn ("dbus_message_get_args_valist doesn't support recursive arrays\n");
2743                 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
2744                 goto out;
2745               default:
2746                 _dbus_warn ("Unknown field type %d\n", type);
2747                 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
2748                 goto out;
2749               }
2750             if (err)
2751               {
2752                 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2753                 goto out;
2754               }
2755           }
2756           break;
2757         case DBUS_TYPE_DICT:
2758           _dbus_warn ("dbus_message_get_args_valist doesn't support dicts\n");
2759           dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
2760           goto out;
2761         default:          
2762           dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
2763           _dbus_warn ("Unknown field type %d\n", spec_type);
2764           goto out;
2765         }
2766
2767       spec_type = va_arg (var_args, int);
2768       if (!dbus_message_iter_next (iter) && spec_type != DBUS_TYPE_INVALID)
2769         {
2770           dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
2771                           "Message has only %d arguments, but more were expected", i);
2772           goto out;
2773         }
2774
2775       i++;
2776     }
2777   
2778   retval = TRUE;
2779   
2780  out:
2781   
2782   return retval;
2783 }
2784
2785 /**
2786  * Returns the byte value that an iterator may point to.
2787  * Note that you need to check that the iterator points to
2788  * a byte value before using this function.
2789  *
2790  * @see dbus_message_iter_get_arg_type
2791  * @param iter the message iter
2792  * @returns the byte value
2793  */
2794 unsigned char
2795 dbus_message_iter_get_byte (DBusMessageIter *iter)
2796 {
2797   unsigned char value = 0;
2798
2799   _dbus_message_iter_get_basic_type (iter, DBUS_TYPE_BYTE, &value);
2800
2801   return value;
2802 }
2803
2804 /**
2805  * Returns the boolean value that an iterator may point to.
2806  * Note that you need to check that the iterator points to
2807  * a boolean value before using this function.
2808  *
2809  * @see dbus_message_iter_get_arg_type
2810  * @param iter the message iter
2811  * @returns the boolean value
2812  */
2813 dbus_bool_t
2814 dbus_message_iter_get_boolean (DBusMessageIter *iter)
2815 {
2816   unsigned char value = 0;
2817
2818   _dbus_message_iter_get_basic_type (iter, DBUS_TYPE_BOOLEAN, &value);
2819
2820   return (value != FALSE);
2821 }
2822
2823 /**
2824  * Returns the 32 bit signed integer value that an iterator may point to.
2825  * Note that you need to check that the iterator points to
2826  * a 32-bit integer value before using this function.
2827  *
2828  * @see dbus_message_iter_get_arg_type
2829  * @param iter the message iter
2830  * @returns the integer
2831  */
2832 dbus_int32_t
2833 dbus_message_iter_get_int32 (DBusMessageIter *iter)
2834 {
2835   dbus_int32_t value = 0;
2836
2837   _dbus_message_iter_get_basic_type (iter, DBUS_TYPE_INT32, &value);
2838
2839   return value;
2840 }
2841
2842 /**
2843  * Returns the 32 bit unsigned integer value that an iterator may point to.
2844  * Note that you need to check that the iterator points to
2845  * a 32-bit unsigned integer value before using this function.
2846  *
2847  * @see dbus_message_iter_get_arg_type
2848  * @param iter the message iter
2849  * @returns the integer
2850  */
2851 dbus_uint32_t
2852 dbus_message_iter_get_uint32 (DBusMessageIter *iter)
2853 {
2854   dbus_int32_t value = 0;
2855
2856   _dbus_message_iter_get_basic_type (iter, DBUS_TYPE_UINT32, &value);
2857
2858   return value;
2859 }
2860
2861 #ifdef DBUS_HAVE_INT64
2862
2863 /**
2864  * Returns the 64 bit signed integer value that an iterator may point
2865  * to.  Note that you need to check that the iterator points to a
2866  * 64-bit integer value before using this function.
2867  *
2868  * This function only exists if #DBUS_HAVE_INT64 is defined.
2869  *
2870  * @see dbus_message_iter_get_arg_type
2871  * @param iter the message iter
2872  * @returns the integer
2873  */
2874 dbus_int64_t
2875 dbus_message_iter_get_int64 (DBusMessageIter *iter)
2876 {
2877   dbus_int64_t value = 0;
2878
2879   _dbus_message_iter_get_basic_type (iter, DBUS_TYPE_INT64, &value);
2880
2881   return value;
2882 }
2883
2884 /**
2885  * Returns the 64 bit unsigned integer value that an iterator may point to.
2886  * Note that you need to check that the iterator points to
2887  * a 64-bit unsigned integer value before using this function.
2888  * 
2889  * This function only exists if #DBUS_HAVE_INT64 is defined.
2890  * 
2891  * @see dbus_message_iter_get_arg_type
2892  * @param iter the message iter
2893  * @returns the integer
2894  */
2895 dbus_uint64_t
2896 dbus_message_iter_get_uint64 (DBusMessageIter *iter)
2897 {
2898   dbus_uint64_t value = 0;
2899
2900   _dbus_message_iter_get_basic_type (iter, DBUS_TYPE_UINT64, &value);
2901
2902   return value;
2903 }
2904
2905 #endif /* DBUS_HAVE_INT64 */
2906
2907 /**
2908  * Returns the double value that an iterator may point to.
2909  * Note that you need to check that the iterator points to
2910  * a string value before using this function.
2911  *
2912  * @see dbus_message_iter_get_arg_type
2913  * @param iter the message iter
2914  * @returns the double
2915  */
2916 double
2917 dbus_message_iter_get_double (DBusMessageIter *iter)
2918 {
2919   double value = 0.0;
2920
2921   _dbus_message_iter_get_basic_type (iter, DBUS_TYPE_DOUBLE, &value);
2922
2923   return value;
2924 }
2925
2926 /**
2927  * Initializes an iterator for the array that the iterator
2928  * may point to. Note that you need to check that the iterator
2929  * points to an array prior to using this function.
2930  *
2931  * The array element type is returned in array_type, and the array
2932  * iterator can only be used to get that type of data.
2933  *
2934  * @param iter the iterator
2935  * @param array_iter pointer to an iterator to initialize
2936  * @param array_type gets set to the type of the array elements
2937  * @returns #FALSE if the array is empty
2938  */
2939 dbus_bool_t
2940 dbus_message_iter_init_array_iterator (DBusMessageIter *iter,
2941                                        DBusMessageIter *array_iter,
2942                                        int             *array_type)
2943 {
2944   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2945   DBusMessageRealIter *array_real = (DBusMessageRealIter *)array_iter;
2946   int type, pos, len_pos, len, array_type_pos;
2947   int _array_type;
2948
2949   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
2950
2951   pos = dbus_message_iter_get_data_start (real, &type);
2952   
2953   _dbus_assert (type == DBUS_TYPE_ARRAY);
2954
2955   _array_type = iter_get_array_type (real, &array_type_pos);
2956   
2957   len_pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_uint32_t));
2958   len = _dbus_demarshal_uint32 (&real->message->body, real->message->byte_order,
2959                                 pos, &pos);
2960   
2961   array_real->parent_iter = real;
2962   array_real->message = real->message;
2963   array_real->changed_stamp = real->message->changed_stamp;
2964   
2965   array_real->type = DBUS_MESSAGE_ITER_TYPE_ARRAY;
2966   array_real->pos = pos;
2967   array_real->end = pos + len;
2968   
2969   array_real->container_start = pos;
2970   array_real->container_length_pos = len_pos;
2971   array_real->wrote_dict_key = 0;
2972   array_real->array_type_pos = array_type_pos;
2973   array_real->array_type_done = TRUE;
2974   
2975   if (array_type != NULL)
2976     *array_type = _array_type;
2977
2978   return len > 0;
2979 }
2980
2981
2982 /**
2983  * Initializes an iterator for the dict that the iterator
2984  * may point to. Note that you need to check that the iterator
2985  * points to a dict prior to using this function.
2986  *
2987  * @param iter the iterator
2988  * @param dict_iter pointer to an iterator to initialize
2989  * @returns #FALSE if the dict is empty
2990  */
2991 dbus_bool_t
2992 dbus_message_iter_init_dict_iterator (DBusMessageIter *iter,
2993                                       DBusMessageIter *dict_iter)
2994 {
2995   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2996   DBusMessageRealIter *dict_real = (DBusMessageRealIter *)dict_iter;
2997   int type, pos, len_pos, len;
2998
2999   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
3000
3001   pos = dbus_message_iter_get_data_start (real, &type);
3002   
3003   _dbus_assert (type == DBUS_TYPE_DICT);
3004
3005   len_pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_uint32_t));
3006   len = _dbus_demarshal_uint32 (&real->message->body, real->message->byte_order,
3007                                 pos, &pos);
3008   
3009   dict_real->parent_iter = real;
3010   dict_real->message = real->message;
3011   dict_real->changed_stamp = real->message->changed_stamp;
3012   
3013   dict_real->type = DBUS_MESSAGE_ITER_TYPE_DICT;
3014   dict_real->pos = pos;
3015   dict_real->end = pos + len;
3016   
3017   dict_real->container_start = pos;
3018   dict_real->container_length_pos = len_pos;
3019   dict_real->wrote_dict_key = 0;
3020
3021   return len > 0;
3022 }
3023
3024 static dbus_bool_t
3025 _dbus_message_iter_get_basic_type_array  (DBusMessageIter *iter,
3026                                           char             type,
3027                                           void           **array,
3028                                           int             *array_len)
3029 {
3030   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3031   int item_type, pos;
3032
3033   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
3034
3035   pos = dbus_message_iter_get_data_start (real, &item_type);
3036   
3037   _dbus_assert (item_type == DBUS_TYPE_ARRAY);
3038
3039   item_type = iter_get_array_type (real, NULL);
3040   
3041   _dbus_assert (type == item_type);
3042
3043   return _dbus_demarshal_basic_type_array (&real->message->body,
3044                                            item_type, array, array_len,
3045                                            real->message->byte_order, &pos);
3046 }
3047
3048 /**
3049  * Returns the byte array that the iterator may point to.
3050  * Note that you need to check that the iterator points
3051  * to a byte array prior to using this function.
3052  *
3053  * @param iter the iterator
3054  * @param value return location for array values
3055  * @param len return location for length of byte array
3056  * @returns #TRUE on success
3057  */
3058 dbus_bool_t
3059 dbus_message_iter_get_byte_array (DBusMessageIter  *iter,
3060                                   unsigned char   **value,
3061                                   int              *len)
3062 {
3063   return _dbus_message_iter_get_basic_type_array (iter, DBUS_TYPE_BYTE,
3064                                                   (void **) value, len);
3065 }
3066
3067 /**
3068  * Returns the boolean array that the iterator may point to. Note that
3069  * you need to check that the iterator points to an array of the
3070  * correct type prior to using this function.
3071  *
3072  * @param iter the iterator
3073  * @param value return location for the array
3074  * @param len return location for the array length
3075  * @returns #TRUE on success
3076  */
3077 dbus_bool_t
3078 dbus_message_iter_get_boolean_array (DBusMessageIter   *iter,
3079                                      unsigned char    **value,
3080                                      int               *len)
3081 {
3082   return _dbus_message_iter_get_basic_type_array (iter, DBUS_TYPE_BOOLEAN,
3083                                                   (void **) value, len);
3084 }
3085
3086 /**
3087  * Returns the 32 bit signed integer array that the iterator may point
3088  * to. Note that you need to check that the iterator points to an
3089  * array of the correct type prior to using this function.
3090  *
3091  * @param iter the iterator
3092  * @param value return location for the array
3093  * @param len return location for the array length
3094  * @returns #TRUE on success
3095  */
3096 dbus_bool_t
3097 dbus_message_iter_get_int32_array  (DBusMessageIter *iter,
3098                                     dbus_int32_t   **value,
3099                                     int             *len)
3100 {
3101   return _dbus_message_iter_get_basic_type_array (iter, DBUS_TYPE_INT32,
3102                                                   (void **) value, len);
3103 }
3104
3105 /**
3106  * Returns the 32 bit unsigned integer array that the iterator may point
3107  * to. Note that you need to check that the iterator points to an
3108  * array of the correct type prior to using this function.
3109  *
3110  * @param iter the iterator
3111  * @param value return location for the array
3112  * @param len return location for the array length
3113  * @returns #TRUE on success
3114  */
3115 dbus_bool_t
3116 dbus_message_iter_get_uint32_array  (DBusMessageIter *iter,
3117                                      dbus_uint32_t  **value,
3118                                      int             *len)
3119 {
3120   return _dbus_message_iter_get_basic_type_array (iter, DBUS_TYPE_UINT32,
3121                                                   (void **) value, len);
3122 }
3123
3124 #ifdef DBUS_HAVE_INT64
3125
3126 /**
3127  * Returns the 64 bit signed integer array that the iterator may point
3128  * to. Note that you need to check that the iterator points to an
3129  * array of the correct type prior to using this function.
3130  * 
3131  * This function only exists if #DBUS_HAVE_INT64 is defined.
3132  *
3133  * @param iter the iterator
3134  * @param value return location for the array
3135  * @param len return location for the array length
3136  * @returns #TRUE on success
3137  */
3138 dbus_bool_t
3139 dbus_message_iter_get_int64_array  (DBusMessageIter *iter,
3140                                     dbus_int64_t   **value,
3141                                     int             *len)
3142 {
3143   return _dbus_message_iter_get_basic_type_array (iter, DBUS_TYPE_INT64,
3144                                                   (void **) value, len);
3145 }
3146
3147 /**
3148  * Returns the 64 bit unsigned integer array that the iterator may point
3149  * to. Note that you need to check that the iterator points to an
3150  * array of the correct type prior to using this function.
3151  *
3152  * This function only exists if #DBUS_HAVE_INT64 is defined.
3153  *
3154  * @param iter the iterator
3155  * @param value return location for the array
3156  * @param len return location for the array length
3157  * @returns #TRUE on success
3158  */
3159 dbus_bool_t
3160 dbus_message_iter_get_uint64_array  (DBusMessageIter *iter,
3161                                      dbus_uint64_t  **value,
3162                                      int             *len)
3163 {
3164   return _dbus_message_iter_get_basic_type_array (iter, DBUS_TYPE_UINT64,
3165                                                   (void **) value, len);
3166 }
3167
3168 #endif /* DBUS_HAVE_INT64 */
3169
3170 /**
3171  * Returns the double array that the iterator may point to. Note that
3172  * you need to check that the iterator points to an array of the
3173  * correct type prior to using this function.
3174  *
3175  * @param iter the iterator
3176  * @param value return location for the array
3177  * @param len return location for the array length
3178  * @returns #TRUE on success
3179  */
3180 dbus_bool_t
3181 dbus_message_iter_get_double_array  (DBusMessageIter *iter,
3182                                      double         **value,
3183                                      int             *len)
3184 {
3185   return _dbus_message_iter_get_basic_type_array (iter, DBUS_TYPE_DOUBLE,
3186                                                   (void **) value, len);
3187 }
3188
3189 /**
3190  * Returns the string array that the iterator may point to.
3191  * Note that you need to check that the iterator points
3192  * to a string array prior to using this function.
3193  *
3194  * The returned value is a #NULL-terminated array of strings.
3195  * Each string is a separate malloc block, and the array
3196  * itself is a malloc block. You can free this type of
3197  * string array with dbus_free_string_array().
3198  *
3199  * @param iter the iterator
3200  * @param value return location for string values
3201  * @param len return location for length of byte array
3202  * @returns #TRUE on success
3203  */
3204 dbus_bool_t
3205 dbus_message_iter_get_string_array (DBusMessageIter *iter,
3206                                     char          ***value,
3207                                     int             *len)
3208 {
3209   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3210   int type, pos;
3211
3212   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
3213
3214   pos = dbus_message_iter_get_data_start (real, &type);
3215   
3216   _dbus_assert (type == DBUS_TYPE_ARRAY);
3217
3218   type = iter_get_array_type (real, NULL);
3219   _dbus_assert (type == DBUS_TYPE_STRING);
3220
3221   if (!_dbus_demarshal_string_array (&real->message->body, real->message->byte_order,
3222                                      pos, NULL, value, len))
3223     return FALSE;
3224   else
3225     return TRUE;
3226 }
3227
3228 /**
3229  * Returns the object path array that the iterator may point to.
3230  * Note that you need to check that the iterator points
3231  * to an object path array prior to using this function.
3232  *
3233  * The returned value is a #NULL-terminated array of strings.
3234  * Each string is a separate malloc block, and the array
3235  * itself is a malloc block. You can free this type of
3236  * array with dbus_free_string_array().
3237  *
3238  * @param iter the iterator
3239  * @param value return location for string values
3240  * @param len return location for length of byte array
3241  * @returns #TRUE on success
3242  */
3243 dbus_bool_t
3244 dbus_message_iter_get_object_path_array (DBusMessageIter *iter,
3245                                          char          ***value,
3246                                          int             *len)
3247 {
3248   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3249   int type, pos;
3250
3251   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
3252
3253   pos = dbus_message_iter_get_data_start (real, &type);
3254   
3255   _dbus_assert (type == DBUS_TYPE_ARRAY);
3256
3257   type = iter_get_array_type (real, NULL);
3258   _dbus_assert (type == DBUS_TYPE_OBJECT_PATH);
3259
3260   if (!_dbus_demarshal_string_array (&real->message->body, real->message->byte_order,
3261                                      pos, NULL, value, len))
3262     return FALSE;
3263   else
3264     return TRUE;
3265 }
3266
3267 /**
3268  * Returns the key name fot the dict entry that an iterator
3269  * may point to. Note that you need to check that the iterator
3270  * points to a dict entry before using this function.
3271  *
3272  * @see dbus_message_iter_init_dict_iterator
3273  * @param iter the message iter
3274  * @returns the key name
3275  */
3276 char *
3277 dbus_message_iter_get_dict_key (DBusMessageIter   *iter)
3278 {
3279   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3280
3281   _dbus_return_val_if_fail (dbus_message_iter_check (real), NULL);
3282
3283   _dbus_assert (real->type == DBUS_MESSAGE_ITER_TYPE_DICT);
3284
3285   return _dbus_demarshal_string (&real->message->body, real->message->byte_order,
3286                                  real->pos, NULL);
3287 }
3288
3289 /**
3290  * Initializes a DBusMessageIter pointing to the end of the
3291  * message. This iterator can be used to append data to the
3292  * message.
3293  *
3294  * @param message the message
3295  * @param iter pointer to an iterator to initialize
3296  */
3297 void
3298 dbus_message_append_iter_init (DBusMessage     *message,
3299                                DBusMessageIter *iter)
3300 {
3301   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3302
3303   _dbus_return_if_fail (message != NULL);
3304   _dbus_return_if_fail (iter != NULL);
3305   
3306   real->message = message;
3307   real->parent_iter = NULL;
3308   real->changed_stamp = message->changed_stamp;
3309   
3310   real->type = DBUS_MESSAGE_ITER_TYPE_MESSAGE;
3311   real->end = _dbus_string_get_length (&real->message->body);
3312   real->pos = real->end;
3313   
3314   real->container_length_pos = 0;
3315   real->wrote_dict_key = 0;
3316 }
3317
3318 #ifndef DBUS_DISABLE_CHECKS
3319 static dbus_bool_t
3320 dbus_message_iter_append_check (DBusMessageRealIter *iter)
3321 {
3322   if (iter == NULL)
3323     {
3324       _dbus_warn ("dbus iterator check failed: NULL iterator\n");
3325       return FALSE;
3326     }
3327   
3328   if (iter->message->locked)
3329     {
3330       _dbus_warn ("dbus iterator check failed: message is locked (has already been sent)\n");
3331       return FALSE;
3332     }
3333       
3334   if (iter->changed_stamp != iter->message->changed_stamp)
3335     {
3336       _dbus_warn ("dbus iterator check failed: invalid iterator, must re-initialize it after modifying the message");
3337       return FALSE;
3338     }
3339   
3340   if (iter->pos != iter->end)
3341     {
3342       _dbus_warn ("dbus iterator check failed: can only append at end of message");
3343       return FALSE;
3344     }
3345   
3346   if (iter->pos != _dbus_string_get_length (&iter->message->body))
3347     {
3348       _dbus_warn ("dbus iterator check failed: append pos not at end of message string");
3349       return FALSE;
3350     }
3351
3352   return TRUE;
3353 }
3354 #endif /* DBUS_DISABLE_CHECKS */
3355
3356 static dbus_bool_t
3357 dbus_message_iter_append_type (DBusMessageRealIter *iter,
3358                                int                  type)
3359 {
3360   const char *data;
3361
3362   switch (iter->type)
3363     {
3364     case DBUS_MESSAGE_ITER_TYPE_MESSAGE:
3365       if (!_dbus_string_append_byte (&iter->message->body, type))
3366         return FALSE;
3367
3368       if (!_dbus_message_append_byte_to_signature (iter->message, type))
3369         {
3370           _dbus_string_shorten (&iter->message->body, 1);
3371           return FALSE;
3372         }
3373       break;
3374       
3375     case DBUS_MESSAGE_ITER_TYPE_ARRAY:
3376       data = _dbus_string_get_const_data_len (&iter->message->body,
3377                                               iter->array_type_pos, 1);
3378       if (type != *data)
3379         {
3380           _dbus_warn ("Appended element of wrong type for array\n");
3381           return FALSE;
3382         }
3383       break;
3384       
3385     case DBUS_MESSAGE_ITER_TYPE_DICT:
3386       if (!iter->wrote_dict_key)
3387         {
3388           _dbus_warn ("Appending dict data before key name\n");
3389           return FALSE;
3390         }
3391       
3392       if (!_dbus_string_append_byte (&iter->message->body, type))
3393         return FALSE;
3394       
3395       break;
3396       
3397     default:
3398       _dbus_assert_not_reached ("Invalid iter type");
3399       break;
3400     }
3401   
3402   return TRUE;
3403 }
3404
3405 static void
3406 dbus_message_iter_update_after_change (DBusMessageRealIter *iter)
3407 {
3408   iter->changed_stamp = iter->message->changed_stamp;
3409   
3410   /* Set new end of iter */
3411   iter->end = _dbus_string_get_length (&iter->message->body);
3412   iter->pos = iter->end;
3413
3414   /* Set container length */
3415   if (iter->type == DBUS_MESSAGE_ITER_TYPE_DICT ||
3416       (iter->type == DBUS_MESSAGE_ITER_TYPE_ARRAY && iter->array_type_done))
3417     _dbus_marshal_set_uint32 (&iter->message->body,
3418                               iter->message->byte_order,
3419                               iter->container_length_pos,
3420                               iter->end - iter->container_start);
3421   
3422   if (iter->parent_iter)
3423     dbus_message_iter_update_after_change (iter->parent_iter);
3424 }
3425
3426 static void
3427 dbus_message_iter_append_done (DBusMessageRealIter *iter)
3428 {
3429   iter->message->changed_stamp++;
3430   dbus_message_iter_update_after_change (iter);
3431   iter->wrote_dict_key = FALSE;
3432 }
3433
3434 /**
3435  * Appends a nil value to the message
3436  *
3437  * @param iter an iterator pointing to the end of the message
3438  * @returns #TRUE on success
3439  */
3440 dbus_bool_t
3441 dbus_message_iter_append_nil (DBusMessageIter *iter)
3442 {
3443   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3444
3445   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
3446
3447   if (!dbus_message_iter_append_type (real, DBUS_TYPE_NIL))
3448     return FALSE;
3449   
3450   dbus_message_iter_append_done (real);
3451   
3452   return TRUE;
3453 }
3454
3455 static dbus_bool_t
3456 dbus_message_iter_append_basic (DBusMessageIter *iter,
3457                                 char             type,
3458                                 void            *value)
3459 {
3460   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3461
3462   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
3463
3464   if (!dbus_message_iter_append_type (real, type))
3465     return FALSE;
3466
3467   if (!_dbus_marshal_basic_type (&real->message->body,
3468                                  type, value,
3469                                  real->message->byte_order))
3470     {
3471       _dbus_string_set_length (&real->message->body, real->pos);
3472       return FALSE;
3473     }
3474
3475   dbus_message_iter_append_done (real);
3476   
3477   return TRUE;  
3478 }
3479
3480 /**
3481  * Appends a boolean value to the message
3482  *
3483  * @param iter an iterator pointing to the end of the message
3484  * @param value the boolean value
3485  * @returns #TRUE on success
3486  */
3487 dbus_bool_t
3488 dbus_message_iter_append_boolean (DBusMessageIter *iter,
3489                                   dbus_bool_t     value)
3490 {
3491   unsigned char val = (value != FALSE);
3492   return dbus_message_iter_append_basic (iter, DBUS_TYPE_BOOLEAN, &val);
3493 }
3494
3495 /**
3496  * Appends a byte to the message
3497  *
3498  * @param iter an iterator pointing to the end of the message
3499  * @param value the byte value
3500  * @returns #TRUE on success
3501  */
3502 dbus_bool_t
3503 dbus_message_iter_append_byte (DBusMessageIter *iter,
3504                                unsigned char    value)
3505 {
3506   return dbus_message_iter_append_basic (iter, DBUS_TYPE_BYTE, &value);
3507 }
3508
3509 /**
3510  * Appends a 32 bit signed integer to the message.
3511  *
3512  * @param iter an iterator pointing to the end of the message
3513  * @param value the integer value
3514  * @returns #TRUE on success
3515  */
3516 dbus_bool_t
3517 dbus_message_iter_append_int32   (DBusMessageIter *iter,
3518                                   dbus_int32_t  value)
3519 {
3520   return dbus_message_iter_append_basic (iter, DBUS_TYPE_INT32, &value);
3521 }
3522
3523 /**
3524  * Appends a 32 bit unsigned integer to the message.
3525  *
3526  * @param iter an iterator pointing to the end of the message
3527  * @param value the integer value
3528  * @returns #TRUE on success
3529  */
3530 dbus_bool_t
3531 dbus_message_iter_append_uint32 (DBusMessageIter *iter,
3532                                  dbus_uint32_t    value)
3533 {
3534   return dbus_message_iter_append_basic (iter, DBUS_TYPE_UINT32, &value);
3535 }
3536
3537 #ifdef DBUS_HAVE_INT64
3538
3539 /**
3540  * Appends a 64 bit signed integer to the message.
3541  *
3542  * This function only exists if #DBUS_HAVE_INT64 is defined.
3543  *
3544  * @param iter an iterator pointing to the end of the message
3545  * @param value the integer value
3546  * @returns #TRUE on success
3547  */
3548 dbus_bool_t
3549 dbus_message_iter_append_int64   (DBusMessageIter *iter,
3550                                   dbus_int64_t  value)
3551 {
3552   return dbus_message_iter_append_basic (iter, DBUS_TYPE_INT64, &value);
3553 }
3554
3555 /**
3556  * Appends a 64 bit unsigned integer to the message.
3557  *
3558  * This function only exists if #DBUS_HAVE_INT64 is defined.
3559  *
3560  * @param iter an iterator pointing to the end of the message
3561  * @param value the integer value
3562  * @returns #TRUE on success
3563  */
3564 dbus_bool_t
3565 dbus_message_iter_append_uint64 (DBusMessageIter *iter,
3566                                  dbus_uint64_t    value)
3567 {
3568   return dbus_message_iter_append_basic (iter, DBUS_TYPE_UINT64, &value);
3569 }
3570
3571 #endif /* DBUS_HAVE_INT64 */
3572
3573 /**
3574  * Appends a double value to the message.
3575  *
3576  * @param iter an iterator pointing to the end of the message
3577  * @param value the double value
3578  * @returns #TRUE on success
3579  */
3580 dbus_bool_t
3581 dbus_message_iter_append_double (DBusMessageIter *iter,
3582                                  double           value)
3583 {
3584   return dbus_message_iter_append_basic (iter, DBUS_TYPE_DOUBLE, &value);
3585 }
3586
3587 /**
3588  * Appends a UTF-8 string to the message.
3589  *
3590  * @todo add return_val_if_fail(UTF-8 is valid)
3591  *
3592  * @param iter an iterator pointing to the end of the message
3593  * @param value the string
3594  * @returns #TRUE on success
3595  */
3596 dbus_bool_t
3597 dbus_message_iter_append_string (DBusMessageIter *iter,
3598                                  const char      *value)
3599 {
3600   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3601
3602   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
3603   
3604   if (!dbus_message_iter_append_type (real, DBUS_TYPE_STRING))
3605     return FALSE;
3606   
3607   if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, value))
3608     {
3609       _dbus_string_set_length (&real->message->body, real->pos);
3610       return FALSE;
3611     }
3612
3613   dbus_message_iter_append_done (real);
3614   
3615   return TRUE;
3616 }
3617
3618 /**
3619  * Appends an object path to the message.
3620  *
3621  * @todo add return_val_if_fail(UTF-8 is valid)
3622  *
3623  * @param iter an iterator pointing to the end of the message
3624  * @param value the object path
3625  * @returns #TRUE on success
3626  */
3627 dbus_bool_t
3628 dbus_message_iter_append_object_path (DBusMessageIter *iter,
3629                                       const char      *value)
3630 {
3631   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3632
3633   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
3634   
3635   if (!dbus_message_iter_append_type (real, DBUS_TYPE_OBJECT_PATH))
3636     return FALSE;
3637   
3638   if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, value))
3639     {
3640       _dbus_string_set_length (&real->message->body, real->pos);
3641       return FALSE;
3642     }
3643
3644   dbus_message_iter_append_done (real);
3645   
3646   return TRUE;
3647 }
3648
3649 /**
3650  * Appends a custom type data chunk to the message. A custom
3651  * type is simply an arbitrary UTF-8 string used as a type
3652  * tag, plus an array of arbitrary bytes to be interpreted
3653  * according to the type tag.
3654  *
3655  * @param iter an iterator pointing to the end of the message
3656  * @param name the name of the type
3657  * @param data the binary data used to store the value
3658  * @param len the length of the binary data in bytes
3659  * @returns #TRUE on success
3660  */
3661 dbus_bool_t
3662 dbus_message_iter_append_custom (DBusMessageIter      *iter,
3663                                  const char           *name,
3664                                  const unsigned char  *data,
3665                                  int                   len)
3666 {
3667   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3668
3669   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
3670
3671   if (!dbus_message_iter_append_type (real, DBUS_TYPE_CUSTOM))
3672     return FALSE;
3673   
3674    if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, name))
3675     {
3676       _dbus_string_set_length (&real->message->body, real->pos);
3677       return FALSE;
3678     }
3679    
3680   if (!_dbus_marshal_byte_array (&real->message->body, real->message->byte_order, data, len))
3681     {
3682       _dbus_string_set_length (&real->message->body, real->pos);
3683       return FALSE;
3684     }
3685
3686   dbus_message_iter_append_done (real);
3687   
3688   return TRUE;
3689 }
3690
3691
3692 /**
3693  * Appends a dict key name to the message. The iterator used
3694  * must point to a dict.
3695  *
3696  * @param iter an iterator pointing to the end of the message
3697  * @param value the string
3698  * @returns #TRUE on success
3699  */
3700 dbus_bool_t
3701 dbus_message_iter_append_dict_key (DBusMessageIter *iter,
3702                                    const char      *value)
3703 {
3704   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3705
3706   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
3707   _dbus_assert (real->type == DBUS_MESSAGE_ITER_TYPE_DICT);
3708   
3709   if (real->wrote_dict_key)
3710     {
3711       _dbus_warn ("Appending multiple dict key names\n");
3712       return FALSE;
3713     }
3714   
3715   if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, value))
3716     {
3717       return FALSE;
3718     }
3719
3720   dbus_message_iter_append_done (real);
3721   real->wrote_dict_key = TRUE;
3722   
3723   return TRUE;
3724 }
3725
3726 static dbus_bool_t
3727 array_iter_type_mark_done (DBusMessageRealIter *iter)
3728 {
3729   int len_pos;
3730   
3731   if (iter->type == DBUS_MESSAGE_ITER_TYPE_ARRAY)
3732     array_iter_type_mark_done (iter->parent_iter);
3733   else
3734     return TRUE;
3735
3736   len_pos = _DBUS_ALIGN_VALUE (_dbus_string_get_length (&iter->message->body),
3737                                sizeof (dbus_uint32_t));
3738
3739   /* Empty length for now, backfill later */
3740   if (!_dbus_marshal_uint32 (&iter->message->body, iter->message->byte_order, 0))
3741     {
3742       _dbus_string_set_length (&iter->message->body, iter->pos);
3743       return FALSE;
3744     }
3745
3746   iter->container_start = _dbus_string_get_length (&iter->message->body);
3747   iter->container_length_pos = len_pos;
3748   iter->array_type_done = TRUE;
3749
3750   return TRUE;
3751 }
3752
3753 static dbus_bool_t
3754 append_array_type (DBusMessageRealIter *real,
3755                    int                  element_type,
3756                    dbus_bool_t         *array_type_done,
3757                    int                 *array_type_pos)
3758 {
3759   int existing_element_type;
3760   
3761   if (!dbus_message_iter_append_type (real, DBUS_TYPE_ARRAY))
3762     return FALSE;
3763   
3764   if (real->type == DBUS_MESSAGE_ITER_TYPE_ARRAY &&
3765       real->array_type_done)
3766     {
3767       existing_element_type = iter_get_array_type (real, array_type_pos);
3768       if (existing_element_type != element_type)
3769         {
3770           _dbus_warn ("Appending array of %s, when expecting array of %s\n",
3771                       _dbus_type_to_string (element_type),
3772                       _dbus_type_to_string (existing_element_type));
3773           _dbus_string_set_length (&real->message->body, real->pos);
3774           return FALSE;
3775         }
3776       if (array_type_done != NULL)
3777           *array_type_done = TRUE;
3778     }
3779   else
3780     {
3781       if (array_type_pos != NULL)
3782         *array_type_pos = _dbus_string_get_length (&real->message->body);
3783
3784
3785       if (!_dbus_message_append_byte_to_signature (real->message, element_type))
3786         {
3787           _dbus_string_set_length (&real->message->body, real->pos);
3788           return FALSE;
3789         }
3790       
3791       /* Append element type */
3792       if (!_dbus_string_append_byte (&real->message->body, element_type))
3793         {
3794           _dbus_message_remove_byte_from_signature (real->message);
3795           _dbus_string_set_length (&real->message->body, real->pos);
3796           return FALSE;
3797         }
3798
3799       if (array_type_done != NULL)
3800         *array_type_done = element_type != DBUS_TYPE_ARRAY;
3801       
3802       if (element_type != DBUS_TYPE_ARRAY &&
3803           !array_iter_type_mark_done (real))
3804         {
3805           _dbus_message_remove_byte_from_signature (real->message);
3806           return FALSE;
3807         }
3808     }
3809
3810   return TRUE;
3811 }
3812
3813 /**
3814  * Appends an array to the message and initializes an iterator that
3815  * can be used to append to the array.
3816  *
3817  * @param iter an iterator pointing to the end of the message
3818  * @param array_iter pointer to an iter that will be initialized
3819  * @param element_type the type of the array elements
3820  * @returns #TRUE on success
3821  */
3822 dbus_bool_t
3823 dbus_message_iter_append_array (DBusMessageIter      *iter,
3824                                 DBusMessageIter      *array_iter,
3825                                 int                   element_type)
3826 {
3827   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3828   DBusMessageRealIter *array_real = (DBusMessageRealIter *)array_iter;
3829   int len_pos;
3830   int array_type_pos;
3831   dbus_bool_t array_type_done;
3832
3833   if (element_type == DBUS_TYPE_NIL)
3834     {
3835       _dbus_warn ("Can't create NIL arrays\n");
3836       return FALSE;
3837     }
3838   
3839   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
3840
3841   if (!append_array_type (real, element_type, &array_type_done, &array_type_pos))
3842     return FALSE;
3843
3844   len_pos = _DBUS_ALIGN_VALUE (_dbus_string_get_length (&real->message->body), sizeof (dbus_uint32_t));
3845
3846   if (array_type_done)
3847     {
3848       /* Empty length for now, backfill later */
3849       if (!_dbus_marshal_uint32 (&real->message->body, real->message->byte_order, 0))
3850         {
3851           _dbus_string_set_length (&real->message->body, real->pos);
3852           return FALSE;
3853         }
3854     }
3855   
3856   array_real->parent_iter = real;
3857   array_real->message = real->message;
3858   array_real->changed_stamp = real->message->changed_stamp;
3859   
3860   array_real->type = DBUS_MESSAGE_ITER_TYPE_ARRAY;
3861   array_real->pos = _dbus_string_get_length (&real->message->body);
3862   array_real->end = array_real->end;
3863   
3864   array_real->container_start = array_real->pos;
3865   array_real->container_length_pos = len_pos;
3866   array_real->wrote_dict_key = 0;
3867   array_real->array_type_done = array_type_done;
3868   array_real->array_type_pos = array_type_pos;
3869
3870   dbus_message_iter_append_done (array_real);
3871   
3872   return TRUE;
3873 }
3874
3875 /**
3876  * Appends a dict to the message and initializes an iterator that
3877  * can be used to append to the dict.
3878  *
3879  * @param iter an iterator pointing to the end of the message
3880  * @param dict_iter pointer to an iter that will be initialized
3881  * @returns #TRUE on success
3882  */
3883 dbus_bool_t
3884 dbus_message_iter_append_dict (DBusMessageIter      *iter,
3885                                DBusMessageIter      *dict_iter)
3886 {
3887   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3888   DBusMessageRealIter *dict_real = (DBusMessageRealIter *)dict_iter;
3889   int len_pos;
3890
3891   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
3892   
3893   if (!dbus_message_iter_append_type (real, DBUS_TYPE_DICT))
3894     return FALSE;  
3895   
3896   len_pos = _DBUS_ALIGN_VALUE (_dbus_string_get_length (&real->message->body), sizeof (dbus_uint32_t));
3897
3898   /* Empty length for now, backfill later */
3899   if (!_dbus_marshal_uint32 (&real->message->body, real->message->byte_order, 0))
3900     {
3901       _dbus_string_set_length (&real->message->body, real->pos);
3902       return FALSE;
3903     }
3904   
3905   dict_real->parent_iter = real;
3906   dict_real->message = real->message;
3907   dict_real->changed_stamp = real->message->changed_stamp;
3908   
3909   dict_real->type = DBUS_MESSAGE_ITER_TYPE_DICT;
3910   dict_real->pos = _dbus_string_get_length (&real->message->body);
3911   dict_real->end = dict_real->end;
3912   
3913   dict_real->container_start = dict_real->pos;
3914   dict_real->container_length_pos = len_pos;
3915   dict_real->wrote_dict_key = 0;
3916
3917   dbus_message_iter_append_done (dict_real);
3918   
3919   real->wrote_dict_key = FALSE;
3920   
3921   return TRUE;
3922 }
3923
3924 static dbus_bool_t
3925 _dbus_message_iter_append_basic_array (DBusMessageIter *iter,
3926                                        char             type,
3927                                        const void      *value,
3928                                        int              len)
3929 {
3930   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3931
3932   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
3933
3934   if (!append_array_type (real, type, NULL, NULL))
3935     return FALSE;
3936   
3937   if (!_dbus_marshal_basic_type_array (&real->message->body,
3938                                        type, value, len,
3939                                        real->message->byte_order))
3940     {
3941       _dbus_string_set_length (&real->message->body, real->pos);
3942       return FALSE;
3943     }
3944
3945   dbus_message_iter_append_done (real);
3946   
3947   return TRUE;
3948 }
3949
3950
3951 /**
3952  * This function takes a va_list for use by language bindings.
3953  * It's otherwise the same as dbus_message_append_args().
3954  *
3955  * @todo: Shouldn't this function clean up the changes to the message
3956  *        on failures? (Yes)
3957   
3958  * @see dbus_message_append_args.  
3959  * @param message the message
3960  * @param first_arg_type type of first argument
3961  * @param var_args value of first argument, then list of type/value pairs
3962  * @returns #TRUE on success
3963  */
3964 dbus_bool_t
3965 dbus_message_append_args_valist (DBusMessage *message,
3966                                  int          first_arg_type,
3967                                  va_list      var_args)
3968 {
3969   int type, old_len;
3970   DBusMessageIter iter;
3971
3972   _dbus_return_val_if_fail (message != NULL, FALSE);
3973   
3974   old_len = _dbus_string_get_length (&message->body);
3975   
3976   type = first_arg_type;
3977
3978   dbus_message_append_iter_init (message, &iter);
3979   
3980   while (type != DBUS_TYPE_INVALID)
3981     {
3982       switch (type)
3983         {
3984         case DBUS_TYPE_NIL:
3985           if (!dbus_message_iter_append_nil (&iter))
3986             goto errorout;
3987           break;
3988         case DBUS_TYPE_BYTE:
3989           /* Read an int from varargs, because the original unsigned
3990            * char has been promoted to int. */
3991           if (!dbus_message_iter_append_byte (&iter, va_arg (var_args, int)))
3992             goto errorout;
3993           break;
3994         case DBUS_TYPE_BOOLEAN:
3995           if (!dbus_message_iter_append_boolean (&iter, va_arg (var_args, dbus_bool_t)))
3996             goto errorout;
3997           break;
3998         case DBUS_TYPE_INT32:
3999           /* FIXME this is probably wrong, because an int passed in probably gets
4000            * converted to plain "int" not necessarily 32-bit.
4001            */
4002           if (!dbus_message_iter_append_int32 (&iter, va_arg (var_args, dbus_int32_t)))
4003             goto errorout;
4004           break;
4005         case DBUS_TYPE_UINT32:
4006           /* FIXME this is probably wrong, because an int passed in probably gets
4007            * converted to plain "int" not necessarily 32-bit.
4008            */
4009           if (!dbus_message_iter_append_uint32 (&iter, va_arg (var_args, dbus_uint32_t)))
4010             goto errorout;          
4011           break;
4012 #ifdef DBUS_HAVE_INT64
4013         case DBUS_TYPE_INT64:
4014           if (!dbus_message_iter_append_int64 (&iter, va_arg (var_args, dbus_int64_t)))
4015             goto errorout;
4016           break;
4017         case DBUS_TYPE_UINT64:
4018           if (!dbus_message_iter_append_uint64 (&iter, va_arg (var_args, dbus_uint64_t)))
4019             goto errorout;          
4020           break;
4021 #endif /* DBUS_HAVE_INT64 */
4022         case DBUS_TYPE_DOUBLE:
4023           if (!dbus_message_iter_append_double (&iter, va_arg (var_args, double)))
4024             goto errorout;
4025           break;
4026         case DBUS_TYPE_STRING:
4027           if (!dbus_message_iter_append_string (&iter, va_arg (var_args, const char *)))
4028             goto errorout;
4029           break;
4030         case DBUS_TYPE_OBJECT_PATH:
4031           if (!dbus_message_iter_append_object_path (&iter, va_arg (var_args, const char*)))
4032             goto errorout;
4033           break;
4034         case DBUS_TYPE_CUSTOM:
4035           {
4036             const char *name;
4037             unsigned char *data;
4038             int len;
4039  
4040             name = va_arg (var_args, const char *);
4041             data = va_arg (var_args, unsigned char *);
4042             len = va_arg (var_args, int);
4043
4044             if (!dbus_message_iter_append_custom (&iter, name, data, len))
4045               goto errorout;
4046             break;
4047           }
4048         case DBUS_TYPE_ARRAY:
4049           {
4050             void *data;
4051             int len, type;
4052  
4053             type = va_arg (var_args, int);
4054             data = va_arg (var_args, void *);
4055             len = va_arg (var_args, int);
4056
4057             switch (type)
4058               {
4059               case DBUS_TYPE_BYTE:
4060               case DBUS_TYPE_BOOLEAN:
4061               case DBUS_TYPE_INT32:
4062               case DBUS_TYPE_UINT32:
4063 #ifdef DBUS_HAVE_INT64
4064               case DBUS_TYPE_INT64:
4065               case DBUS_TYPE_UINT64:
4066 #endif /* DBUS_HAVE_INT64 */
4067               case DBUS_TYPE_DOUBLE:
4068                 if (!_dbus_message_iter_append_basic_array (&iter, type, data, len))
4069                   goto errorout;
4070                 break;
4071               case DBUS_TYPE_STRING:
4072                 if (!dbus_message_iter_append_string_array (&iter, (const char **)data, len))
4073                   goto errorout;
4074                 break;
4075               case DBUS_TYPE_OBJECT_PATH:
4076                 if (!dbus_message_iter_append_object_path_array (&iter, (const char **)data, len))
4077                   goto errorout;
4078                 break;
4079               case DBUS_TYPE_NIL:
4080               case DBUS_TYPE_ARRAY:
4081               case DBUS_TYPE_CUSTOM:
4082               case DBUS_TYPE_DICT:
4083                 _dbus_warn ("dbus_message_append_args_valist doesn't support recursive arrays\n");
4084                 goto errorout;
4085               default:
4086                 _dbus_warn ("Unknown field type %d\n", type);
4087                 goto errorout;
4088               }
4089           }
4090           break;
4091           
4092         case DBUS_TYPE_DICT:
4093           _dbus_warn ("dbus_message_append_args_valist doesn't support dicts\n");
4094           goto errorout;
4095         default:
4096           _dbus_warn ("Unknown field type %d\n", type);
4097           goto errorout;
4098         }
4099
4100       type = va_arg (var_args, int);
4101     }
4102
4103   return TRUE;
4104
4105  errorout:
4106   return FALSE;
4107 }
4108
4109 /**
4110  * Appends a boolean array to the message.
4111  *
4112  * @param iter an iterator pointing to the end of the message
4113  * @param value the array
4114  * @param len the length of the array
4115  * @returns #TRUE on success
4116  */
4117 dbus_bool_t
4118 dbus_message_iter_append_boolean_array (DBusMessageIter     *iter,
4119                                         unsigned const char *value,
4120                                         int                  len)
4121 {
4122   return _dbus_message_iter_append_basic_array (iter, DBUS_TYPE_BOOLEAN,
4123                                                 value, len);
4124 }
4125
4126 /**
4127  * Appends a 32 bit signed integer array to the message.
4128  *
4129  * @param iter an iterator pointing to the end of the message
4130  * @param value the array
4131  * @param len the length of the array
4132  * @returns #TRUE on success
4133  */
4134 dbus_bool_t
4135 dbus_message_iter_append_int32_array (DBusMessageIter    *iter,
4136                                       const dbus_int32_t *value,
4137                                       int                 len)
4138 {
4139   return _dbus_message_iter_append_basic_array (iter, DBUS_TYPE_INT32,
4140                                                 value, len);
4141 }
4142
4143 /**
4144  * Appends a 32 bit unsigned integer array to the message.
4145  *
4146  * @param iter an iterator pointing to the end of the message
4147  * @param value the array
4148  * @param len the length of the array
4149  * @returns #TRUE on success
4150  */
4151 dbus_bool_t
4152 dbus_message_iter_append_uint32_array (DBusMessageIter     *iter,
4153                                        const dbus_uint32_t *value,
4154                                        int                  len)
4155 {
4156   return _dbus_message_iter_append_basic_array (iter, DBUS_TYPE_UINT32,
4157                                                 value, len);
4158 }
4159
4160 #ifdef DBUS_HAVE_INT64
4161
4162 /**
4163  * Appends a 64 bit signed integer array to the message.
4164  *
4165  * This function only exists if #DBUS_HAVE_INT64 is defined.
4166  *
4167  * @param iter an iterator pointing to the end of the message
4168  * @param value the array
4169  * @param len the length of the array
4170  * @returns #TRUE on success
4171  */
4172 dbus_bool_t
4173 dbus_message_iter_append_int64_array (DBusMessageIter    *iter,
4174                                       const dbus_int64_t *value,
4175                                       int                 len)
4176 {
4177   return _dbus_message_iter_append_basic_array (iter, DBUS_TYPE_INT64,
4178                                                 value, len);
4179 }
4180
4181 /**
4182  * Appends a 64 bit unsigned integer array to the message.
4183  *
4184  * This function only exists if #DBUS_HAVE_INT64 is defined.
4185  *
4186  * @param iter an iterator pointing to the end of the message
4187  * @param value the array
4188  * @param len the length of the array
4189  * @returns #TRUE on success
4190  */
4191 dbus_bool_t
4192 dbus_message_iter_append_uint64_array (DBusMessageIter     *iter,
4193                                        const dbus_uint64_t *value,
4194                                        int                  len)
4195 {
4196   return _dbus_message_iter_append_basic_array (iter, DBUS_TYPE_UINT64,
4197                                                 value, len);
4198 }
4199 #endif /* DBUS_HAVE_INT64 */
4200
4201 /**
4202  * Appends a double array to the message.
4203  *
4204  * @param iter an iterator pointing to the end of the message
4205  * @param value the array
4206  * @param len the length of the array
4207  * @returns #TRUE on success
4208  */
4209 dbus_bool_t
4210 dbus_message_iter_append_double_array (DBusMessageIter *iter,
4211                                        const double    *value,
4212                                        int              len)
4213 {
4214   return _dbus_message_iter_append_basic_array (iter, DBUS_TYPE_DOUBLE,
4215                                                 value, len);
4216 }
4217
4218 /**
4219  * Appends a byte array to the message.
4220  *
4221  * @param iter an iterator pointing to the end of the message
4222  * @param value the array
4223  * @param len the length of the array
4224  * @returns #TRUE on success
4225  */
4226 dbus_bool_t
4227 dbus_message_iter_append_byte_array (DBusMessageIter     *iter,
4228                                      unsigned const char *value,
4229                                      int                  len)
4230 {
4231   return _dbus_message_iter_append_basic_array (iter, DBUS_TYPE_BYTE,
4232                                                 value, len);
4233 }
4234
4235 /**
4236  * Appends a string array to the message.
4237  *
4238  * @param iter an iterator pointing to the end of the message
4239  * @param value the array
4240  * @param len the length of the array
4241  * @returns #TRUE on success
4242  */
4243 dbus_bool_t
4244 dbus_message_iter_append_string_array (DBusMessageIter *iter,
4245                                        const char     **value,
4246                                        int              len)
4247 {
4248   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
4249
4250   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
4251
4252   if (!append_array_type (real, DBUS_TYPE_STRING, NULL, NULL))
4253     return FALSE;
4254   
4255   if (!_dbus_marshal_string_array (&real->message->body, real->message->byte_order, value, len))
4256     {
4257       _dbus_string_set_length (&real->message->body, real->pos);
4258       return FALSE;
4259     }
4260
4261   dbus_message_iter_append_done (real);
4262   
4263   return TRUE;
4264 }
4265
4266 /**
4267  * Appends an object path array to the message.
4268  *
4269  * @param iter an iterator pointing to the end of the message
4270  * @param value the array
4271  * @param len the length of the array
4272  * @returns #TRUE on success
4273  */
4274 dbus_bool_t
4275 dbus_message_iter_append_object_path_array (DBusMessageIter *iter,
4276                                             const char     **value,
4277                                             int              len)
4278 {
4279   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
4280
4281   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
4282
4283   if (!append_array_type (real, DBUS_TYPE_OBJECT_PATH, NULL, NULL))
4284     return FALSE;
4285   
4286   if (!_dbus_marshal_string_array (&real->message->body, real->message->byte_order, value, len))
4287     {
4288       _dbus_string_set_length (&real->message->body, real->pos);
4289       return FALSE;
4290     }
4291
4292   dbus_message_iter_append_done (real);
4293   
4294   return TRUE;
4295 }
4296
4297 /**
4298  * Sets the message sender.
4299  *
4300  * @param message the message
4301  * @param sender the sender or #NULL to unset
4302  * @returns #FALSE if not enough memory
4303  */
4304 dbus_bool_t
4305 dbus_message_set_sender (DBusMessage  *message,
4306                          const char   *sender)
4307 {
4308   _dbus_return_val_if_fail (message != NULL, FALSE);
4309   _dbus_return_val_if_fail (!message->locked, FALSE);
4310
4311   return set_string_field (message,
4312                            DBUS_HEADER_FIELD_SENDER,
4313                            DBUS_TYPE_STRING,
4314                            sender);
4315 }
4316
4317 /**
4318  * Sets a flag indicating that the message does not want a reply; if
4319  * this flag is set, the other end of the connection may (but is not
4320  * required to) optimize by not sending method return or error
4321  * replies. If this flag is set, there is no way to know whether the
4322  * message successfully arrived at the remote end.
4323  *
4324  * @param message the message
4325  * @param no_reply #TRUE if no reply is desired
4326  */
4327 void
4328 dbus_message_set_no_reply (DBusMessage *message,
4329                            dbus_bool_t  no_reply)
4330 {
4331   char *header;
4332
4333   _dbus_return_if_fail (message != NULL);
4334   _dbus_return_if_fail (!message->locked);
4335   
4336   header = _dbus_string_get_data_len (&message->header, FLAGS_OFFSET, 1);
4337   
4338   if (no_reply)
4339     *header |= DBUS_HEADER_FLAG_NO_REPLY_EXPECTED;
4340   else
4341     *header &= ~DBUS_HEADER_FLAG_NO_REPLY_EXPECTED;    
4342 }
4343
4344 /**
4345  * Returns #TRUE if the message does not expect
4346  * a reply.
4347  *
4348  * @param message the message
4349  * @returns #TRUE if the message sender isn't waiting for a reply
4350  */
4351 dbus_bool_t
4352 dbus_message_get_no_reply (DBusMessage *message)
4353 {
4354   const char *header;
4355
4356   _dbus_return_val_if_fail (message != NULL, FALSE);
4357   
4358   header = _dbus_string_get_const_data_len (&message->header, FLAGS_OFFSET, 1);
4359
4360   return (*header & DBUS_HEADER_FLAG_NO_REPLY_EXPECTED) != 0;
4361 }
4362
4363
4364 /**
4365  * Sets a flag indicating that the addressed service will be auto-activated
4366  * before the message is delivered. When this flag is set, the message is held
4367  * until the service is succesfully activated or fail to activate. In case of
4368  * failure, the reply will be an activation error.
4369  *
4370  * @param message the message
4371  * @param auto_activation #TRUE if auto-activation is desired
4372  */
4373 void
4374 dbus_message_set_auto_activation (DBusMessage *message,
4375                                   dbus_bool_t  auto_activation)
4376 {
4377   char *header;
4378
4379   _dbus_return_if_fail (message != NULL);
4380   _dbus_return_if_fail (!message->locked);
4381   
4382   header = _dbus_string_get_data_len (&message->header, FLAGS_OFFSET, 1);
4383   
4384   if (auto_activation)
4385     *header |= DBUS_HEADER_FLAG_AUTO_ACTIVATION;
4386   else
4387     *header &= ~DBUS_HEADER_FLAG_AUTO_ACTIVATION;
4388 }
4389
4390 /**
4391  * Returns #TRUE if the message will cause the addressed service to be
4392  * auto-activated.
4393  *
4394  * @param message the message
4395  * @returns #TRUE if the message will use auto-activation
4396  */
4397 dbus_bool_t
4398 dbus_message_get_auto_activation (DBusMessage *message)
4399 {
4400   const char *header;
4401
4402   _dbus_return_val_if_fail (message != NULL, FALSE);
4403   
4404   header = _dbus_string_get_const_data_len (&message->header, FLAGS_OFFSET, 1);
4405
4406   return (*header & DBUS_HEADER_FLAG_AUTO_ACTIVATION) != 0;
4407 }
4408
4409 /**
4410  * Gets the service which originated this message,
4411  * or #NULL if unknown or inapplicable.
4412  *
4413  * @param message the message
4414  * @returns the service name or #NULL
4415  */
4416 const char*
4417 dbus_message_get_sender (DBusMessage *message)
4418 {
4419   _dbus_return_val_if_fail (message != NULL, NULL);
4420   
4421   return get_string_field (message, 
4422                            DBUS_HEADER_FIELD_SENDER,
4423                            NULL);
4424 }
4425
4426 /**
4427  * Gets the type signature of the message, i.e. the arguments in the
4428  * message payload. The signature includes only "in" arguments for
4429  * #DBUS_MESSAGE_TYPE_METHOD_CALL and only "out" arguments for
4430  * #DBUS_MESSAGE_TYPE_METHOD_RETURN, so is slightly different from
4431  * what you might expect (it does not include the signature of the
4432  * entire C++-style method).
4433  *
4434  * The signature is a string made up of type codes such
4435  * as #DBUS_TYPE_STRING. The string is terminated with nul
4436  * (nul is also the value of #DBUS_TYPE_INVALID).
4437  * 
4438  * @param message the message
4439  * @returns the type signature
4440  */
4441 const char*
4442 dbus_message_get_signature (DBusMessage *message)
4443 {
4444   _dbus_return_val_if_fail (message != NULL, NULL);
4445
4446   return get_string_field (message, 
4447                            DBUS_HEADER_FIELD_SIGNATURE,
4448                            NULL);
4449 }
4450
4451 static dbus_bool_t
4452 _dbus_message_has_type_interface_member (DBusMessage *message,
4453                                          int          type,
4454                                          const char  *interface,
4455                                          const char  *method)
4456 {
4457   const char *n;
4458
4459   _dbus_assert (message != NULL);
4460   _dbus_assert (interface != NULL);
4461   _dbus_assert (method != NULL);
4462
4463   if (dbus_message_get_type (message) != type)
4464     return FALSE;
4465
4466   /* Optimize by checking the short method name first
4467    * instead of the longer interface name
4468    */  
4469
4470   n = dbus_message_get_member (message);
4471
4472   if (n && strcmp (n, method) == 0)
4473     {
4474       n = dbus_message_get_interface (message);
4475       
4476       if (n && strcmp (n, interface) == 0)
4477         return TRUE;
4478     }
4479
4480   return FALSE;
4481 }
4482
4483 /**
4484  * Checks whether the message is a method call with the given
4485  * interface and member fields.  If the message is not
4486  * #DBUS_MESSAGE_TYPE_METHOD_CALL, or has a different interface or member field,
4487  * returns #FALSE.
4488  *
4489  * @param message the message
4490  * @param interface the name to check (must not be #NULL)
4491  * @param method the name to check (must not be #NULL)
4492  * 
4493  * @returns #TRUE if the message is the specified method call
4494  */
4495 dbus_bool_t
4496 dbus_message_is_method_call (DBusMessage *message,
4497                              const char  *interface,
4498                              const char  *method)
4499 {
4500   _dbus_return_val_if_fail (message != NULL, FALSE);
4501   _dbus_return_val_if_fail (interface != NULL, FALSE);
4502   _dbus_return_val_if_fail (method != NULL, FALSE);
4503
4504   return _dbus_message_has_type_interface_member (message,
4505                                                   DBUS_MESSAGE_TYPE_METHOD_CALL,
4506                                                   interface, method);
4507 }
4508
4509 /**
4510  * Checks whether the message is a signal with the given
4511  * interface and member fields.  If the message is not
4512  * #DBUS_MESSAGE_TYPE_SIGNAL, or has a different interface or member field,
4513  * returns #FALSE.
4514  *
4515  * @param message the message
4516  * @param interface the name to check (must not be #NULL)
4517  * @param signal_name the name to check (must not be #NULL)
4518  * 
4519  * @returns #TRUE if the message is the specified signal
4520  */
4521 dbus_bool_t
4522 dbus_message_is_signal (DBusMessage *message,
4523                         const char  *interface,
4524                         const char  *signal_name)
4525 {
4526   _dbus_return_val_if_fail (message != NULL, FALSE);
4527   _dbus_return_val_if_fail (interface != NULL, FALSE);
4528   _dbus_return_val_if_fail (signal_name != NULL, FALSE);
4529
4530   return _dbus_message_has_type_interface_member (message,
4531                                                   DBUS_MESSAGE_TYPE_SIGNAL,
4532                                                   interface, signal_name);
4533 }
4534
4535 /**
4536  * Checks whether the message is an error reply with the given error
4537  * name.  If the message is not #DBUS_MESSAGE_TYPE_ERROR, or has a
4538  * different name, returns #FALSE.
4539  *
4540  * @param message the message
4541  * @param error_name the name to check (must not be #NULL)
4542  * 
4543  * @returns #TRUE if the message is the specified error
4544  */
4545 dbus_bool_t
4546 dbus_message_is_error (DBusMessage *message,
4547                        const char  *error_name)
4548 {
4549   const char *n;
4550   
4551   _dbus_return_val_if_fail (message != NULL, FALSE);
4552   _dbus_return_val_if_fail (error_name != NULL, FALSE);
4553   _dbus_return_val_if_fail (is_valid_error_name (error_name), FALSE);
4554   
4555   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
4556     return FALSE;
4557
4558   n = dbus_message_get_error_name (message);
4559
4560   if (n && strcmp (n, error_name) == 0)
4561     return TRUE;
4562   else
4563     return FALSE;
4564 }
4565
4566 /**
4567  * Checks whether the message was sent to the given service.  If the
4568  * message has no service specified or has a different name, returns
4569  * #FALSE.
4570  *
4571  * @param message the message
4572  * @param service the service to check (must not be #NULL)
4573  * 
4574  * @returns #TRUE if the message has the given destination service
4575  */
4576 dbus_bool_t
4577 dbus_message_has_destination (DBusMessage  *message,
4578                               const char   *service)
4579 {
4580   const char *s;
4581
4582   _dbus_return_val_if_fail (message != NULL, FALSE);
4583   _dbus_return_val_if_fail (service != NULL, FALSE);
4584   
4585   s = dbus_message_get_destination (message);
4586
4587   if (s && strcmp (s, service) == 0)
4588     return TRUE;
4589   else
4590     return FALSE;
4591 }
4592
4593 /**
4594  * Checks whether the message has the given service as its sender.  If
4595  * the message has no sender specified or has a different sender,
4596  * returns #FALSE. Note that if a peer application owns multiple
4597  * services, its messages will have only one of those services as the
4598  * sender (usually the base service). So you can't use this
4599  * function to prove the sender didn't own service Foo, you can
4600  * only use it to prove that it did.
4601  *
4602  * @param message the message
4603  * @param service the service to check (must not be #NULL)
4604  * 
4605  * @returns #TRUE if the message has the given origin service
4606  */
4607 dbus_bool_t
4608 dbus_message_has_sender (DBusMessage  *message,
4609                          const char   *service)
4610 {
4611   const char *s;
4612
4613   _dbus_return_val_if_fail (message != NULL, FALSE);
4614   _dbus_return_val_if_fail (service != NULL, FALSE);
4615   
4616   s = dbus_message_get_sender (message);
4617
4618   if (s && strcmp (s, service) == 0)
4619     return TRUE;
4620   else
4621     return FALSE;
4622 }
4623
4624 /**
4625  * Checks whether the message has the given signature;
4626  * see dbus_message_get_signature() for more details on
4627  * what the signature looks like.
4628  *
4629  * @param message the message
4630  * @param signature typecode array
4631  * @returns #TRUE if message has the given signature
4632 */
4633 dbus_bool_t
4634 dbus_message_has_signature (DBusMessage   *message,
4635                             const char    *signature)
4636 {
4637   const char *s;
4638
4639   _dbus_return_val_if_fail (message != NULL, FALSE);
4640   _dbus_return_val_if_fail (signature != NULL, FALSE);
4641   
4642   s = dbus_message_get_signature (message);
4643
4644   if (s && strcmp (s, signature) == 0)
4645     return TRUE;
4646   else
4647     return FALSE;
4648 }
4649
4650 /**
4651  * Sets a #DBusError based on the contents of the given
4652  * message. The error is only set if the message
4653  * is an error message, as in DBUS_MESSAGE_TYPE_ERROR.
4654  * The name of the error is set to the name of the message,
4655  * and the error message is set to the first argument
4656  * if the argument exists and is a string.
4657  *
4658  * The return value indicates whether the error was set (the error is
4659  * set if and only if the message is an error message).
4660  * So you can check for an error reply and convert it to DBusError
4661  * in one go.
4662  *
4663  * @param error the error to set
4664  * @param message the message to set it from
4665  * @returns #TRUE if dbus_message_get_is_error() returns #TRUE for the message
4666  */
4667 dbus_bool_t
4668 dbus_set_error_from_message (DBusError   *error,
4669                              DBusMessage *message)
4670 {
4671   char *str;
4672
4673   _dbus_return_val_if_fail (message != NULL, FALSE);
4674   _dbus_return_val_if_error_is_set (error, FALSE);
4675   
4676   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
4677     return FALSE;
4678
4679   str = NULL;
4680   dbus_message_get_args (message, NULL,
4681                          DBUS_TYPE_STRING, &str,
4682                          DBUS_TYPE_INVALID);
4683
4684   dbus_set_error (error, dbus_message_get_error_name (message),
4685                   str ? "%s" : NULL, str);
4686
4687   dbus_free (str);
4688   
4689   return TRUE;
4690 }
4691
4692 /** @} */
4693
4694 /**
4695  * @addtogroup DBusMessageInternals
4696  *
4697  * @{
4698  */
4699 /**
4700  * @typedef DBusMessageLoader
4701  *
4702  * The DBusMessageLoader object encapsulates the process of converting
4703  * a byte stream into a series of DBusMessage. It buffers the incoming
4704  * bytes as efficiently as possible, and generates a queue of
4705  * messages. DBusMessageLoader is typically used as part of a
4706  * DBusTransport implementation. The DBusTransport then hands off
4707  * the loaded messages to a DBusConnection, making the messages
4708  * visible to the application.
4709  *
4710  * @todo write tests for break-loader that a) randomly delete header
4711  * fields and b) set string fields to zero-length and other funky
4712  * values.
4713  * 
4714  */
4715
4716 /* we definitely use signed ints for sizes, so don't exceed
4717  * _DBUS_INT_MAX; and add 16 for paranoia, since a message
4718  * over 128M is pretty nuts anyhow.
4719  */
4720
4721 /**
4722  * The maximum sane message size.
4723  */
4724 #define MAX_SANE_MESSAGE_SIZE (_DBUS_INT_MAX/16)
4725
4726 /**
4727  * Implementation details of DBusMessageLoader.
4728  * All members are private.
4729  */
4730 struct DBusMessageLoader
4731 {
4732   int refcount;        /**< Reference count. */
4733
4734   DBusString data;     /**< Buffered data */
4735   
4736   DBusList *messages;  /**< Complete messages. */
4737
4738   long max_message_size; /**< Maximum size of a message */
4739   
4740   unsigned int buffer_outstanding : 1; /**< Someone is using the buffer to read */
4741
4742   unsigned int corrupted : 1; /**< We got broken data, and are no longer working */
4743 };
4744
4745 /**
4746  * The initial buffer size of the message loader.
4747  * 
4748  * @todo this should be based on min header size plus some average
4749  * body size, or something. Or rather, the min header size only, if we
4750  * want to try to read only the header, store that in a DBusMessage,
4751  * then read only the body and store that, etc., depends on
4752  * how we optimize _dbus_message_loader_get_buffer() and what
4753  * the exact message format is.
4754  */
4755 #define INITIAL_LOADER_DATA_LEN 32
4756
4757 /**
4758  * Creates a new message loader. Returns #NULL if memory can't
4759  * be allocated.
4760  *
4761  * @returns new loader, or #NULL.
4762  */
4763 DBusMessageLoader*
4764 _dbus_message_loader_new (void)
4765 {
4766   DBusMessageLoader *loader;
4767
4768   loader = dbus_new0 (DBusMessageLoader, 1);
4769   if (loader == NULL)
4770     return NULL;
4771   
4772   loader->refcount = 1;
4773
4774   /* Try to cap message size at something that won't *totally* hose
4775    * the system if we have a couple of them.
4776    */
4777   loader->max_message_size = _DBUS_ONE_MEGABYTE * 32;
4778   
4779   if (!_dbus_string_init (&loader->data))
4780     {
4781       dbus_free (loader);
4782       return NULL;
4783     }
4784
4785   /* preallocate the buffer for speed, ignore failure */
4786   _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN);
4787   _dbus_string_set_length (&loader->data, 0);
4788   
4789   return loader;
4790 }
4791
4792 /**
4793  * Increments the reference count of the loader.
4794  *
4795  * @param loader the loader.
4796  * @returns the loader
4797  */
4798 DBusMessageLoader *
4799 _dbus_message_loader_ref (DBusMessageLoader *loader)
4800 {
4801   loader->refcount += 1;
4802
4803   return loader;
4804 }
4805
4806 /**
4807  * Decrements the reference count of the loader and finalizes the
4808  * loader when the count reaches zero.
4809  *
4810  * @param loader the loader.
4811  */
4812 void
4813 _dbus_message_loader_unref (DBusMessageLoader *loader)
4814 {
4815   loader->refcount -= 1;
4816   if (loader->refcount == 0)
4817     {
4818       _dbus_list_foreach (&loader->messages,
4819                           (DBusForeachFunction) dbus_message_unref,
4820                           NULL);
4821       _dbus_list_clear (&loader->messages);
4822       _dbus_string_free (&loader->data);
4823       dbus_free (loader);
4824     }
4825 }
4826
4827 /**
4828  * Gets the buffer to use for reading data from the network.  Network
4829  * data is read directly into an allocated buffer, which is then used
4830  * in the DBusMessage, to avoid as many extra memcpy's as possible.
4831  * The buffer must always be returned immediately using
4832  * _dbus_message_loader_return_buffer(), even if no bytes are
4833  * successfully read.
4834  *
4835  * @todo this function can be a lot more clever. For example
4836  * it can probably always return a buffer size to read exactly
4837  * the body of the next message, thus avoiding any memory wastage
4838  * or reallocs.
4839  *
4840  * @todo we need to enforce a max length on strings in header fields.
4841  * 
4842  * @param loader the message loader.
4843  * @param buffer the buffer
4844  */
4845 void
4846 _dbus_message_loader_get_buffer (DBusMessageLoader  *loader,
4847                                  DBusString        **buffer)
4848 {
4849   _dbus_assert (!loader->buffer_outstanding);
4850
4851   *buffer = &loader->data;
4852   
4853   loader->buffer_outstanding = TRUE;
4854 }
4855
4856 /**
4857  * The smallest header size that can occur. 
4858  * (It won't be valid)
4859  */
4860 #define DBUS_MINIMUM_HEADER_SIZE 16
4861
4862 static dbus_bool_t
4863 decode_string_field (const DBusString   *data,
4864                      int                 field,
4865                      HeaderField        *header_field,
4866                      DBusString         *field_data,
4867                      int                 pos,
4868                      int                 type)
4869 {
4870   int string_data_pos;
4871
4872   _dbus_assert (header_field != NULL);
4873   _dbus_assert (field_data != NULL);
4874   
4875   if (header_field->name_offset >= 0)
4876     {
4877       _dbus_verbose ("%s field provided twice\n",
4878                      _dbus_header_field_to_string (field));
4879       return FALSE;
4880     }
4881
4882   if (type != DBUS_TYPE_STRING)
4883     {
4884       _dbus_verbose ("%s field has wrong type %s\n",
4885                      _dbus_header_field_to_string (field),
4886                      _dbus_type_to_string (type));
4887       return FALSE;
4888     }
4889
4890   /* skip padding after typecode, skip string length;
4891    * we assume that the string arg has already been validated
4892    * for sanity and UTF-8
4893    */
4894   string_data_pos = _DBUS_ALIGN_VALUE (pos, 4) + 4;
4895   _dbus_assert (string_data_pos < _dbus_string_get_length (data));
4896   
4897   _dbus_string_init_const (field_data,
4898                            _dbus_string_get_const_data (data) + string_data_pos);
4899
4900   header_field->name_offset  = pos - 2;
4901   header_field->value_offset = _DBUS_ALIGN_VALUE (pos, 4);
4902   
4903 #if 0
4904   _dbus_verbose ("Found field %s at offset %d\n",
4905                  _dbus_header_field_to_string (field),
4906                  header_field->value_offset);
4907 #endif
4908
4909   return TRUE;
4910 }
4911
4912 /* FIXME because the service/interface/member/error names are already
4913  * validated to be in the particular ASCII subset, UTF-8 validating
4914  * them could be skipped as a probably-interesting optimization.
4915  * The UTF-8 validation definitely shows up in profiles.
4916  */
4917 static dbus_bool_t
4918 decode_header_data (const DBusString   *data,
4919                     int                 header_len,
4920                     int                 byte_order,
4921                     int                 message_type,
4922                     HeaderField         fields[DBUS_HEADER_FIELD_LAST + 1],
4923                     int                *message_padding)
4924 {
4925   DBusString field_data;
4926   int pos, new_pos;
4927   int i;
4928   int field;
4929   int type;
4930   dbus_bool_t signature_required;
4931   
4932   if (header_len < 16)
4933     {
4934       _dbus_verbose ("Header length %d is too short\n", header_len);
4935       return FALSE;
4936     }
4937   
4938   i = 0;
4939   while (i <= DBUS_HEADER_FIELD_LAST)
4940     {
4941       fields[i].name_offset  = -1;
4942       fields[i].value_offset = -1;
4943       ++i;
4944     }
4945   
4946   pos = 16;
4947   while (pos < header_len)
4948     {
4949       field = _dbus_string_get_byte (data, pos);
4950       if (field == DBUS_HEADER_FIELD_INVALID)
4951         break; /* Must be padding */
4952       pos++;
4953
4954       if (!_dbus_marshal_validate_type (data, pos, &type, &pos))
4955         {
4956           _dbus_verbose ("Failed to validate type of named header field pos = %d\n",
4957                          pos);
4958           return FALSE;
4959         }
4960       
4961       if (!_dbus_marshal_validate_arg (data, byte_order, 0, type, -1, pos, &new_pos))
4962         {
4963           _dbus_verbose ("Failed to validate argument to named header field pos = %d\n",
4964                          pos);
4965           return FALSE;
4966         }
4967
4968       if (new_pos > header_len)
4969         {
4970           _dbus_verbose ("Named header field tries to extend beyond header length\n");
4971           return FALSE;
4972         }
4973       
4974       switch (field)
4975         {
4976         case DBUS_HEADER_FIELD_DESTINATION:
4977           if (!decode_string_field (data, field, &fields[field],
4978                                     &field_data, pos, type))
4979             return FALSE;
4980
4981           if (!_dbus_string_validate_service (&field_data, 0,
4982                                               _dbus_string_get_length (&field_data)))
4983             {
4984               _dbus_verbose ("service field has invalid content \"%s\"\n",
4985                              _dbus_string_get_const_data (&field_data));
4986               return FALSE;
4987             }
4988           break;
4989
4990         case DBUS_HEADER_FIELD_INTERFACE:
4991           if (!decode_string_field (data, field, &fields[field],
4992                                     &field_data, pos, type))
4993             return FALSE;
4994
4995           if (!_dbus_string_validate_interface (&field_data, 0,
4996                                                 _dbus_string_get_length (&field_data)))
4997             {
4998               _dbus_verbose ("interface field has invalid content \"%s\"\n",
4999                              _dbus_string_get_const_data (&field_data));
5000               return FALSE;
5001             }
5002       
5003           if (_dbus_string_equal_c_str (&field_data,
5004                                         DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL))
5005             {
5006               _dbus_verbose ("Message is on the local interface\n");
5007               return FALSE;
5008             }
5009           break;
5010
5011         case DBUS_HEADER_FIELD_MEMBER:
5012           if (!decode_string_field (data, field, &fields[field],
5013                                     &field_data, pos, type))
5014             return FALSE;
5015           
5016           if (!_dbus_string_validate_member (&field_data, 0,
5017                                              _dbus_string_get_length (&field_data)))
5018             {
5019               _dbus_verbose ("member field has invalid content \"%s\"\n",
5020                              _dbus_string_get_const_data (&field_data));
5021               return FALSE;
5022             }
5023           break;
5024
5025         case DBUS_HEADER_FIELD_ERROR_NAME:
5026           if (!decode_string_field (data, field, &fields[field],
5027                                     &field_data, pos, type))
5028             return FALSE;
5029           
5030           if (!_dbus_string_validate_error_name (&field_data, 0,
5031                                                  _dbus_string_get_length (&field_data)))
5032             {
5033               _dbus_verbose ("error-name field has invalid content \"%s\"\n",
5034                              _dbus_string_get_const_data (&field_data));
5035               return FALSE;
5036             }
5037           break;
5038           
5039         case DBUS_HEADER_FIELD_SENDER:
5040           if (!decode_string_field (data, field, &fields[field],
5041                                     &field_data, pos, type))
5042             return FALSE;
5043           
5044           if (!_dbus_string_validate_service (&field_data, 0,
5045                                               _dbus_string_get_length (&field_data)))
5046             {
5047               _dbus_verbose ("sender-service field has invalid content \"%s\"\n",
5048                              _dbus_string_get_const_data (&field_data));
5049               return FALSE;
5050             }
5051           break;
5052
5053         case DBUS_HEADER_FIELD_PATH:
5054
5055           /* Path was already validated as part of standard
5056            * type validation, since there's an OBJECT_PATH
5057            * type.
5058            */
5059           
5060           if (fields[field].name_offset >= 0)
5061             {
5062               _dbus_verbose ("path field provided twice\n");
5063               return FALSE;
5064             }
5065           if (type != DBUS_TYPE_OBJECT_PATH)
5066             {
5067               _dbus_verbose ("path field has wrong type\n");
5068               return FALSE;
5069             }
5070
5071           fields[field].name_offset  = pos - 2;
5072           fields[field].value_offset = _DBUS_ALIGN_VALUE (pos, 4);
5073
5074           /* No forging signals from the local path */
5075           {
5076             const char *s;
5077             s = _dbus_string_get_const_data_len (data,
5078                                                  fields[field].value_offset,
5079                                                  _dbus_string_get_length (data) -
5080                                                  fields[field].value_offset);
5081             if (strcmp (s, DBUS_PATH_ORG_FREEDESKTOP_LOCAL) == 0)
5082               {
5083                 _dbus_verbose ("Message is on the local path\n");
5084                 return FALSE;
5085               }
5086           }
5087           
5088           _dbus_verbose ("Found path at offset %d\n",
5089                          fields[field].value_offset);
5090           break;
5091           
5092         case DBUS_HEADER_FIELD_REPLY_SERIAL:
5093           if (fields[field].name_offset >= 0)
5094             {
5095               _dbus_verbose ("reply field provided twice\n");
5096               return FALSE;
5097             }
5098
5099           if (type != DBUS_TYPE_UINT32)
5100             {
5101               _dbus_verbose ("reply field has wrong type\n");
5102               return FALSE;
5103             }
5104           
5105           fields[field].name_offset  = pos - 2;
5106           fields[field].value_offset = _DBUS_ALIGN_VALUE (pos, 4);
5107
5108           _dbus_verbose ("Found reply serial %u at offset %d\n",
5109                          _dbus_demarshal_uint32 (data,
5110                                                  byte_order,
5111                                                  fields[field].value_offset,
5112                                                  NULL),
5113                          fields[field].value_offset);
5114           break;
5115
5116         case DBUS_HEADER_FIELD_SIGNATURE:
5117           if (!decode_string_field (data, field, &fields[field],
5118                                     &field_data, pos, type))
5119             return FALSE;
5120
5121 #if 0
5122           /* FIXME */
5123           if (!_dbus_string_validate_signature (&field_data, 0,
5124                                                 _dbus_string_get_length (&field_data)))
5125             {
5126               _dbus_verbose ("signature field has invalid content \"%s\"\n",
5127                              _dbus_string_get_const_data (&field_data));
5128               return FALSE;
5129             }
5130 #endif
5131           break;
5132           
5133         default:
5134           _dbus_verbose ("Ignoring an unknown header field: %d at offset %d\n",
5135                          field, pos);
5136         }
5137       
5138       pos = new_pos;
5139     }
5140
5141   if (pos < header_len)
5142     {
5143       /* Alignment padding, verify that it's nul */
5144       if ((header_len - pos) >= 8)
5145         {
5146           _dbus_verbose ("too much header alignment padding\n");
5147           return FALSE;
5148         }
5149
5150       if (!_dbus_string_validate_nul (data,
5151                                       pos, (header_len - pos)))
5152         {
5153           _dbus_verbose ("header alignment padding is not nul\n");
5154           return FALSE;
5155         }
5156     }
5157
5158   /* Depending on message type, enforce presence of certain fields. */
5159   signature_required = TRUE;
5160   
5161   switch (message_type)
5162     {
5163     case DBUS_MESSAGE_TYPE_SIGNAL:
5164     case DBUS_MESSAGE_TYPE_METHOD_CALL:
5165       if (fields[DBUS_HEADER_FIELD_PATH].value_offset < 0)
5166         {
5167           _dbus_verbose ("No path field provided\n");
5168           return FALSE;
5169         }
5170       /* FIXME make this optional, only for method calls */
5171       if (fields[DBUS_HEADER_FIELD_INTERFACE].value_offset < 0)
5172         {
5173           _dbus_verbose ("No interface field provided\n");
5174           return FALSE;
5175         }
5176       if (fields[DBUS_HEADER_FIELD_MEMBER].value_offset < 0)
5177         {
5178           _dbus_verbose ("No member field provided\n");
5179           return FALSE;
5180         }
5181       break;
5182     case DBUS_MESSAGE_TYPE_ERROR:
5183       if (fields[DBUS_HEADER_FIELD_ERROR_NAME].value_offset < 0)
5184         {
5185           _dbus_verbose ("No error-name field provided\n");
5186           return FALSE;
5187         }
5188       if (fields[DBUS_HEADER_FIELD_REPLY_SERIAL].value_offset < 0)
5189         {
5190           _dbus_verbose ("No reply serial field provided in error\n");
5191           return FALSE;
5192         }
5193       break;
5194     case DBUS_MESSAGE_TYPE_METHOD_RETURN:
5195       if (fields[DBUS_HEADER_FIELD_REPLY_SERIAL].value_offset < 0)
5196         {
5197           _dbus_verbose ("No reply serial field provided in method return\n");
5198           return FALSE;
5199         }
5200       break;
5201     default:
5202       /* An unknown type, spec requires us to ignore it */
5203       signature_required = FALSE;
5204       break;
5205     }
5206
5207   /* FIXME allow omitting signature field for a message with no arguments? */
5208   if (signature_required)
5209     {
5210       if (fields[DBUS_HEADER_FIELD_SIGNATURE].value_offset < 0)
5211         {
5212           _dbus_verbose ("No signature field provided\n");
5213           return FALSE;
5214         }
5215     }
5216   
5217   if (message_padding)
5218     *message_padding = header_len - pos;  
5219   
5220   return TRUE;
5221 }
5222
5223 /**
5224  * Returns a buffer obtained from _dbus_message_loader_get_buffer(),
5225  * indicating to the loader how many bytes of the buffer were filled
5226  * in. This function must always be called, even if no bytes were
5227  * successfully read.
5228  *
5229  * @param loader the loader.
5230  * @param buffer the buffer.
5231  * @param bytes_read number of bytes that were read into the buffer.
5232  */
5233 void
5234 _dbus_message_loader_return_buffer (DBusMessageLoader  *loader,
5235                                     DBusString         *buffer,
5236                                     int                 bytes_read)
5237 {
5238   _dbus_assert (loader->buffer_outstanding);
5239   _dbus_assert (buffer == &loader->data);
5240
5241   loader->buffer_outstanding = FALSE;
5242 }
5243
5244 static dbus_bool_t
5245 load_one_message (DBusMessageLoader *loader,
5246                   int                byte_order,
5247                   int                message_type,
5248                   int                header_len,
5249                   int                body_len)
5250 {
5251   DBusMessage *message;
5252   HeaderField fields[DBUS_HEADER_FIELD_LAST + 1];
5253   int i;
5254   int next_arg;
5255   dbus_bool_t oom;
5256   int header_padding;
5257   
5258   message = NULL;
5259   oom = FALSE;
5260   
5261 #if 0
5262   _dbus_verbose_bytes_of_string (&loader->data, 0, header_len /* + body_len */);
5263 #endif    
5264
5265   if (!decode_header_data (&loader->data,
5266                            header_len, byte_order,
5267                            message_type,
5268                            fields, &header_padding))
5269     {
5270       _dbus_verbose ("Header was invalid\n");
5271       loader->corrupted = TRUE;
5272       goto failed;
5273     }
5274           
5275   next_arg = header_len;
5276   while (next_arg < (header_len + body_len))
5277     {
5278       int type;
5279       int prev = next_arg;
5280
5281       if (!_dbus_marshal_validate_type (&loader->data, next_arg,
5282                                         &type, &next_arg))
5283         {
5284           _dbus_verbose ("invalid typecode at offset %d\n", prev);
5285           loader->corrupted = TRUE;
5286           goto failed;
5287         }
5288       
5289       if (!_dbus_marshal_validate_arg (&loader->data,
5290                                        byte_order,
5291                                        0,
5292                                        type, -1,
5293                                        next_arg,
5294                                        &next_arg))
5295         {
5296           _dbus_verbose ("invalid type data at %d, next_arg\n", next_arg);
5297           loader->corrupted = TRUE;
5298           goto failed;
5299         }
5300
5301       _dbus_assert (next_arg > prev);
5302     }
5303           
5304   if (next_arg > (header_len + body_len))
5305     {
5306       _dbus_verbose ("end of last arg at %d but message has len %d+%d=%d\n",
5307                      next_arg, header_len, body_len,
5308                      header_len + body_len);
5309       loader->corrupted = TRUE;
5310       goto failed;
5311     }
5312
5313   message = dbus_message_new_empty_header ();
5314   if (message == NULL)
5315     {
5316       _dbus_verbose ("Failed to allocate empty message\n");
5317       oom = TRUE;
5318       goto failed;
5319     }
5320
5321   message->byte_order = byte_order;
5322   message->header_padding = header_padding;
5323           
5324   /* Copy in the offsets we found */
5325   i = 0;
5326   while (i <= DBUS_HEADER_FIELD_LAST)
5327     {
5328       message->header_fields[i] = fields[i];
5329       ++i;
5330     }
5331           
5332   if (!_dbus_list_append (&loader->messages, message))
5333     {
5334       _dbus_verbose ("Failed to append new message to loader queue\n");
5335       oom = TRUE;
5336       goto failed;
5337     }
5338
5339   _dbus_assert (_dbus_string_get_length (&message->header) == 0);
5340   _dbus_assert (_dbus_string_get_length (&message->body) == 0);
5341
5342   _dbus_assert (_dbus_string_get_length (&loader->data) >=
5343                 (header_len + body_len));
5344           
5345   if (!_dbus_string_move_len (&loader->data, 0, header_len, &message->header, 0))
5346     {
5347       _dbus_verbose ("Failed to move header into new message\n");
5348       oom = TRUE;
5349       goto failed;
5350     }
5351           
5352   if (!_dbus_string_move_len (&loader->data, 0, body_len, &message->body, 0))
5353     {
5354       _dbus_verbose ("Failed to move body into new message\n");
5355       
5356       oom = TRUE;
5357       goto failed;
5358     }
5359
5360   _dbus_assert (_dbus_string_get_length (&message->header) == header_len);
5361   _dbus_assert (_dbus_string_get_length (&message->body) == body_len);
5362
5363   /* Fill in caches (we checked the types of these fields
5364    * earlier)
5365    */
5366   message->reply_serial = get_uint_field (message,
5367                                           DBUS_HEADER_FIELD_REPLY_SERIAL);
5368   
5369   message->client_serial = _dbus_demarshal_uint32 (&message->header,
5370                                                    message->byte_order,
5371                                                    CLIENT_SERIAL_OFFSET,
5372                                                    NULL);
5373   if (message->client_serial == 0 ||
5374       (message->header_fields[DBUS_HEADER_FIELD_REPLY_SERIAL].value_offset >= 0 && message->reply_serial == 0))
5375     {
5376       _dbus_verbose ("client_serial = %d reply_serial = %d, one of these no good\n",
5377                      message->client_serial,
5378                      message->reply_serial);
5379       
5380       loader->corrupted = TRUE;
5381       goto failed;
5382     }
5383   
5384   _dbus_verbose ("Loaded message %p\n", message);
5385
5386   _dbus_assert (!oom);
5387   _dbus_assert (!loader->corrupted);
5388
5389   return TRUE;
5390
5391  failed:
5392   
5393   /* Clean up */
5394   
5395   if (message != NULL)
5396     {
5397       /* Put the data back so we can try again later if it was an OOM issue */
5398       if (_dbus_string_get_length (&message->body) > 0)
5399         {
5400           dbus_bool_t result;
5401           
5402           result = _dbus_string_copy_len (&message->body, 0, body_len,
5403                                           &loader->data, 0);
5404           
5405           _dbus_assert (result); /* because DBusString never reallocs smaller */
5406         }
5407       
5408       if (_dbus_string_get_length (&message->header) > 0)
5409         {
5410           dbus_bool_t result;
5411           
5412           result = _dbus_string_copy_len (&message->header, 0, header_len,
5413                                           &loader->data, 0);
5414           
5415           _dbus_assert (result); /* because DBusString never reallocs smaller */
5416         }
5417
5418       /* does nothing if the message isn't in the list */
5419       _dbus_list_remove_last (&loader->messages, message);
5420
5421       dbus_message_unref (message);
5422     }
5423
5424   
5425   return !oom;
5426 }
5427
5428 /**
5429  * Converts buffered data into messages.
5430  *
5431  * @todo we need to check that the proper named header fields exist
5432  * for each message type.
5433  * 
5434  * @todo If a message has unknown type, we should probably eat it
5435  * right here rather than passing it out to applications.  However
5436  * it's not an error to see messages of unknown type.
5437  * 
5438  * @param loader the loader.
5439  * @returns #TRUE if we had enough memory to finish.
5440  */
5441 dbus_bool_t
5442 _dbus_message_loader_queue_messages (DBusMessageLoader *loader)
5443 {
5444   while (!loader->corrupted && _dbus_string_get_length (&loader->data) >= 16)
5445     {
5446       const char *header_data;
5447       int byte_order, message_type, header_len, body_len;
5448       dbus_uint32_t header_len_unsigned, body_len_unsigned;
5449       
5450       header_data = _dbus_string_get_const_data_len (&loader->data, 0, 16);
5451
5452       _dbus_assert (_DBUS_ALIGN_ADDRESS (header_data, 4) == header_data);
5453
5454       if (header_data[VERSION_OFFSET] != DBUS_MAJOR_PROTOCOL_VERSION)
5455         {
5456           _dbus_verbose ("Message has protocol version %d ours is %d\n",
5457                          (int) header_data[VERSION_OFFSET], DBUS_MAJOR_PROTOCOL_VERSION);
5458           loader->corrupted = TRUE;
5459           return TRUE;
5460         }
5461       
5462       byte_order = header_data[BYTE_ORDER_OFFSET];
5463
5464       if (byte_order != DBUS_LITTLE_ENDIAN &&
5465           byte_order != DBUS_BIG_ENDIAN)
5466         {
5467           _dbus_verbose ("Message with bad byte order '%c' received\n",
5468                          byte_order);
5469           loader->corrupted = TRUE;
5470           return TRUE;
5471         }
5472
5473       /* Unknown types are ignored, but INVALID is
5474        * disallowed
5475        */
5476       message_type = header_data[TYPE_OFFSET];
5477       if (message_type == DBUS_MESSAGE_TYPE_INVALID)
5478         {
5479           _dbus_verbose ("Message with bad type '%d' received\n",
5480                          message_type);
5481           loader->corrupted = TRUE;
5482           return TRUE;
5483         }      
5484       
5485       header_len_unsigned = _dbus_unpack_uint32 (byte_order, 
5486                                                  (const unsigned char *) header_data + 4);
5487       body_len_unsigned = _dbus_unpack_uint32 (byte_order, 
5488                                                (const unsigned char *) header_data + 8);
5489
5490       if (header_len_unsigned < 16)
5491         {
5492           _dbus_verbose ("Message had broken too-small header length %u\n",
5493                          header_len_unsigned);
5494           loader->corrupted = TRUE;
5495           return TRUE;
5496         }
5497
5498       if (header_len_unsigned > (unsigned) MAX_SANE_MESSAGE_SIZE ||
5499           body_len_unsigned > (unsigned) MAX_SANE_MESSAGE_SIZE)
5500         {
5501           _dbus_verbose ("Header or body length too large (%u %u)\n",
5502                          header_len_unsigned,
5503                          body_len_unsigned);
5504           loader->corrupted = TRUE;
5505           return TRUE;
5506         }
5507
5508       /* Now that we know the values are in signed range, get
5509        * rid of stupid unsigned, just causes bugs
5510        */
5511       header_len = header_len_unsigned;
5512       body_len = body_len_unsigned;
5513
5514       if (_DBUS_ALIGN_VALUE (header_len, 8) != header_len_unsigned)
5515         {
5516           
5517           _dbus_verbose ("header length %d is not aligned to 8 bytes\n",
5518                          header_len);
5519           loader->corrupted = TRUE;
5520           return TRUE;
5521         }
5522       
5523       if (header_len + body_len > loader->max_message_size)
5524         {
5525           _dbus_verbose ("Message claimed length header = %d body = %d exceeds max message length %ld\n",
5526                          header_len, body_len, loader->max_message_size);
5527           loader->corrupted = TRUE;
5528           return TRUE;
5529         }
5530
5531       if (_dbus_string_get_length (&loader->data) >= (header_len + body_len))
5532         {
5533           if (!load_one_message (loader, byte_order, message_type,
5534                                  header_len, body_len))
5535             return FALSE;
5536         }
5537       else
5538         return TRUE;
5539     }
5540
5541   return TRUE;
5542 }
5543
5544 /**
5545  * Peeks at first loaded message, returns #NULL if no messages have
5546  * been queued.
5547  *
5548  * @param loader the loader.
5549  * @returns the next message, or #NULL if none.
5550  */
5551 DBusMessage*
5552 _dbus_message_loader_peek_message (DBusMessageLoader *loader)
5553 {
5554   if (loader->messages)
5555     return loader->messages->data;
5556   else
5557     return NULL;
5558 }
5559
5560 /**
5561  * Pops a loaded message (passing ownership of the message
5562  * to the caller). Returns #NULL if no messages have been
5563  * queued.
5564  *
5565  * @param loader the loader.
5566  * @returns the next message, or #NULL if none.
5567  */
5568 DBusMessage*
5569 _dbus_message_loader_pop_message (DBusMessageLoader *loader)
5570 {
5571   return _dbus_list_pop_first (&loader->messages);
5572 }
5573
5574 /**
5575  * Pops a loaded message inside a list link (passing ownership of the
5576  * message and link to the caller). Returns #NULL if no messages have
5577  * been loaded.
5578  *
5579  * @param loader the loader.
5580  * @returns the next message link, or #NULL if none.
5581  */
5582 DBusList*
5583 _dbus_message_loader_pop_message_link (DBusMessageLoader *loader)
5584 {
5585   return _dbus_list_pop_first_link (&loader->messages);
5586 }
5587
5588 /**
5589  * Returns a popped message link, used to undo a pop.
5590  *
5591  * @param loader the loader
5592  * @param link the link with a message in it
5593  */
5594 void
5595 _dbus_message_loader_putback_message_link (DBusMessageLoader  *loader,
5596                                            DBusList           *link)
5597 {
5598   _dbus_list_prepend_link (&loader->messages, link);
5599 }
5600
5601 /**
5602  * Checks whether the loader is confused due to bad data.
5603  * If messages are received that are invalid, the
5604  * loader gets confused and gives up permanently.
5605  * This state is called "corrupted."
5606  *
5607  * @param loader the loader
5608  * @returns #TRUE if the loader is hosed.
5609  */
5610 dbus_bool_t
5611 _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader)
5612 {
5613   return loader->corrupted;
5614 }
5615
5616 /**
5617  * Sets the maximum size message we allow.
5618  *
5619  * @param loader the loader
5620  * @param size the max message size in bytes
5621  */
5622 void
5623 _dbus_message_loader_set_max_message_size (DBusMessageLoader  *loader,
5624                                            long                size)
5625 {
5626   if (size > MAX_SANE_MESSAGE_SIZE)
5627     {
5628       _dbus_verbose ("clamping requested max message size %ld to %d\n",
5629                      size, MAX_SANE_MESSAGE_SIZE);
5630       size = MAX_SANE_MESSAGE_SIZE;
5631     }
5632   loader->max_message_size = size;
5633 }
5634
5635 /**
5636  * Gets the maximum allowed message size in bytes.
5637  *
5638  * @param loader the loader
5639  * @returns max size in bytes
5640  */
5641 long
5642 _dbus_message_loader_get_max_message_size (DBusMessageLoader  *loader)
5643 {
5644   return loader->max_message_size;
5645 }
5646
5647 static DBusDataSlotAllocator slot_allocator;
5648 _DBUS_DEFINE_GLOBAL_LOCK (message_slots);
5649
5650 /**
5651  * Allocates an integer ID to be used for storing application-specific
5652  * data on any DBusMessage. The allocated ID may then be used
5653  * with dbus_message_set_data() and dbus_message_get_data().
5654  * The passed-in slot must be initialized to -1, and is filled in
5655  * with the slot ID. If the passed-in slot is not -1, it's assumed
5656  * to be already allocated, and its refcount is incremented.
5657  * 
5658  * The allocated slot is global, i.e. all DBusMessage objects will
5659  * have a slot with the given integer ID reserved.
5660  *
5661  * @param slot_p address of a global variable storing the slot
5662  * @returns #FALSE on failure (no memory)
5663  */
5664 dbus_bool_t
5665 dbus_message_allocate_data_slot (dbus_int32_t *slot_p)
5666 {
5667   return _dbus_data_slot_allocator_alloc (&slot_allocator,
5668                                           _DBUS_LOCK_NAME (message_slots),
5669                                           slot_p);
5670 }
5671
5672 /**
5673  * Deallocates a global ID for message data slots.
5674  * dbus_message_get_data() and dbus_message_set_data() may no
5675  * longer be used with this slot.  Existing data stored on existing
5676  * DBusMessage objects will be freed when the message is
5677  * finalized, but may not be retrieved (and may only be replaced if
5678  * someone else reallocates the slot).  When the refcount on the
5679  * passed-in slot reaches 0, it is set to -1.
5680  *
5681  * @param slot_p address storing the slot to deallocate
5682  */
5683 void
5684 dbus_message_free_data_slot (dbus_int32_t *slot_p)
5685 {
5686   _dbus_return_if_fail (*slot_p >= 0);
5687   
5688   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
5689 }
5690
5691 /**
5692  * Stores a pointer on a DBusMessage, along
5693  * with an optional function to be used for freeing
5694  * the data when the data is set again, or when
5695  * the message is finalized. The slot number
5696  * must have been allocated with dbus_message_allocate_data_slot().
5697  *
5698  * @param message the message
5699  * @param slot the slot number
5700  * @param data the data to store
5701  * @param free_data_func finalizer function for the data
5702  * @returns #TRUE if there was enough memory to store the data
5703  */
5704 dbus_bool_t
5705 dbus_message_set_data (DBusMessage     *message,
5706                        dbus_int32_t     slot,
5707                        void            *data,
5708                        DBusFreeFunction free_data_func)
5709 {
5710   DBusFreeFunction old_free_func;
5711   void *old_data;
5712   dbus_bool_t retval;
5713
5714   _dbus_return_val_if_fail (message != NULL, FALSE);
5715   _dbus_return_val_if_fail (slot >= 0, FALSE);
5716
5717   retval = _dbus_data_slot_list_set (&slot_allocator,
5718                                      &message->slot_list,
5719                                      slot, data, free_data_func,
5720                                      &old_free_func, &old_data);
5721
5722   if (retval)
5723     {
5724       /* Do the actual free outside the message lock */
5725       if (old_free_func)
5726         (* old_free_func) (old_data);
5727     }
5728
5729   return retval;
5730 }
5731
5732 /**
5733  * Retrieves data previously set with dbus_message_set_data().
5734  * The slot must still be allocated (must not have been freed).
5735  *
5736  * @param message the message
5737  * @param slot the slot to get data from
5738  * @returns the data, or #NULL if not found
5739  */
5740 void*
5741 dbus_message_get_data (DBusMessage   *message,
5742                        dbus_int32_t   slot)
5743 {
5744   void *res;
5745
5746   _dbus_return_val_if_fail (message != NULL, NULL);
5747   
5748   res = _dbus_data_slot_list_get (&slot_allocator,
5749                                   &message->slot_list,
5750                                   slot);
5751
5752   return res;
5753 }
5754
5755 /**
5756  * Utility function to convert a machine-readable (not translated)
5757  * string into a D-BUS message type.
5758  *
5759  * @code
5760  *   "method_call"    -> DBUS_MESSAGE_TYPE_METHOD_CALL
5761  *   "method_return"  -> DBUS_MESSAGE_TYPE_METHOD_RETURN
5762  *   "signal"         -> DBUS_MESSAGE_TYPE_SIGNAL
5763  *   "error"          -> DBUS_MESSAGE_TYPE_ERROR
5764  *   anything else    -> DBUS_MESSAGE_TYPE_INVALID
5765  * @endcode
5766  * 
5767  */
5768 int
5769 dbus_message_type_from_string (const char *type_str)
5770 {
5771   if (strcmp (type_str, "method_call") == 0)
5772     return DBUS_MESSAGE_TYPE_METHOD_CALL;
5773   if (strcmp (type_str, "method_return") == 0)
5774     return DBUS_MESSAGE_TYPE_METHOD_RETURN;
5775   else if (strcmp (type_str, "signal") == 0)
5776     return DBUS_MESSAGE_TYPE_SIGNAL;
5777   else if (strcmp (type_str, "error") == 0)
5778     return DBUS_MESSAGE_TYPE_ERROR;
5779   else
5780     return DBUS_MESSAGE_TYPE_INVALID;
5781 }
5782
5783 /**
5784  * Utility function to convert a D-BUS message type into a
5785  * machine-readable string (not translated).
5786  *
5787  * @code
5788  *   DBUS_MESSAGE_TYPE_METHOD_CALL    -> "method_call"
5789  *   DBUS_MESSAGE_TYPE_METHOD_RETURN  -> "method_return"
5790  *   DBUS_MESSAGE_TYPE_SIGNAL         -> "signal"
5791  *   DBUS_MESSAGE_TYPE_ERROR          -> "error"
5792  *   DBUS_MESSAGE_TYPE_INVALID        -> "invalid"
5793  * @endcode
5794  * 
5795  */
5796 const char *
5797 dbus_message_type_to_string (int type)
5798 {
5799   switch (type)
5800     {
5801     case DBUS_MESSAGE_TYPE_METHOD_CALL:
5802       return "method_call";
5803     case DBUS_MESSAGE_TYPE_METHOD_RETURN:
5804       return "method_return";
5805     case DBUS_MESSAGE_TYPE_SIGNAL:
5806       return "signal";
5807     case DBUS_MESSAGE_TYPE_ERROR:
5808       return "error";
5809     default:
5810       return "invalid";
5811     }
5812 }
5813
5814 /** @} */
5815 #ifdef DBUS_BUILD_TESTS
5816 #include "dbus-test.h"
5817 #include <stdio.h>
5818 #include <stdlib.h>
5819
5820 static void
5821 message_iter_test (DBusMessage *message)
5822 {
5823   DBusMessageIter iter, dict, dict2, array, array2;
5824   char *str;
5825   unsigned char *data;
5826   dbus_int32_t *our_int_array;
5827   int len;
5828   
5829   dbus_message_iter_init (message, &iter);
5830
5831   /* String tests */
5832   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING)
5833     _dbus_assert_not_reached ("Argument type isn't string");
5834
5835   str = dbus_message_iter_get_string (&iter);
5836   if (strcmp (str, "Test string") != 0)
5837     _dbus_assert_not_reached ("Strings differ");
5838   dbus_free (str);
5839
5840   if (!dbus_message_iter_next (&iter))
5841     _dbus_assert_not_reached ("Reached end of arguments");
5842
5843   /* Signed integer tests */
5844   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INT32)
5845     _dbus_assert_not_reached ("Argument type isn't int32");
5846
5847   if (dbus_message_iter_get_int32 (&iter) != -0x12345678)
5848     _dbus_assert_not_reached ("Signed integers differ");
5849
5850   if (!dbus_message_iter_next (&iter))
5851     _dbus_assert_not_reached ("Reached end of fields");
5852   
5853   /* Unsigned integer tests */
5854   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_UINT32)
5855     _dbus_assert_not_reached ("Argument type isn't int32");
5856
5857   if (dbus_message_iter_get_uint32 (&iter) != 0xedd1e)
5858     _dbus_assert_not_reached ("Unsigned integers differ");
5859
5860   if (!dbus_message_iter_next (&iter))
5861     _dbus_assert_not_reached ("Reached end of arguments");
5862
5863   /* Double tests */
5864   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_DOUBLE)
5865     _dbus_assert_not_reached ("Argument type isn't double");
5866
5867   if (dbus_message_iter_get_double (&iter) != 3.14159)
5868     _dbus_assert_not_reached ("Doubles differ");
5869
5870   if (!dbus_message_iter_next (&iter))
5871     _dbus_assert_not_reached ("Reached end of arguments");
5872
5873   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY)
5874     _dbus_assert_not_reached ("Argument type not an array");
5875
5876   if (dbus_message_iter_get_array_type (&iter) != DBUS_TYPE_DOUBLE)
5877     _dbus_assert_not_reached ("Array type not double");
5878
5879   
5880   dbus_message_iter_init_array_iterator (&iter, &array, NULL);
5881
5882   if (dbus_message_iter_get_arg_type (&array) != DBUS_TYPE_DOUBLE)
5883     _dbus_assert_not_reached ("Argument type isn't double");
5884
5885   if (dbus_message_iter_get_double (&array) != 1.5)
5886     _dbus_assert_not_reached ("Unsigned integers differ");
5887
5888   if (!dbus_message_iter_next (&array))
5889     _dbus_assert_not_reached ("Reached end of arguments");
5890
5891   if (dbus_message_iter_get_arg_type (&array) != DBUS_TYPE_DOUBLE)
5892     _dbus_assert_not_reached ("Argument type isn't double");
5893
5894   if (dbus_message_iter_get_double (&array) != 2.5)
5895     _dbus_assert_not_reached ("Unsigned integers differ");
5896
5897   if (dbus_message_iter_next (&array))
5898     _dbus_assert_not_reached ("Didn't reach end of arguments");
5899   
5900   if (!dbus_message_iter_next (&iter))
5901     _dbus_assert_not_reached ("Reached end of arguments");
5902   
5903
5904   /* dict */
5905
5906   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_DICT)
5907     _dbus_assert_not_reached ("not dict type");
5908      
5909   dbus_message_iter_init_dict_iterator (&iter, &dict);
5910
5911   str = dbus_message_iter_get_dict_key (&dict);
5912   if (str == NULL || strcmp (str, "test") != 0)
5913     _dbus_assert_not_reached ("wrong dict key");
5914   dbus_free (str);
5915
5916   if (dbus_message_iter_get_arg_type (&dict) != DBUS_TYPE_UINT32)
5917     _dbus_assert_not_reached ("wrong dict entry type");
5918
5919   if (dbus_message_iter_get_uint32 (&dict) != 0xDEADBEEF)
5920     _dbus_assert_not_reached ("wrong dict entry value");
5921
5922   /* dict (in dict) */
5923
5924   if (!dbus_message_iter_next (&dict))
5925     _dbus_assert_not_reached ("reached end of dict");
5926   
5927   if (dbus_message_iter_get_arg_type (&dict) != DBUS_TYPE_DICT)
5928     _dbus_assert_not_reached ("not dict type");
5929     
5930   dbus_message_iter_init_dict_iterator (&dict, &dict2);
5931   
5932   str = dbus_message_iter_get_dict_key (&dict2);
5933   if (str == NULL || strcmp (str, "dictkey") != 0)
5934     _dbus_assert_not_reached ("wrong dict key");
5935   dbus_free (str);
5936   
5937   if (dbus_message_iter_get_arg_type (&dict2) != DBUS_TYPE_STRING)
5938     _dbus_assert_not_reached ("wrong dict entry type");
5939   
5940   str = dbus_message_iter_get_string (&dict2);
5941   if (str == NULL || strcmp (str, "dictvalue") != 0)
5942     _dbus_assert_not_reached ("wrong dict entry value");
5943   dbus_free (str);
5944   
5945   if (dbus_message_iter_next (&dict2))
5946     _dbus_assert_not_reached ("didn't reach end of dict");
5947
5948   if (!dbus_message_iter_next (&dict))
5949     _dbus_assert_not_reached ("reached end of dict");
5950   
5951   /* array of array of int32 (in dict) */
5952
5953   str = dbus_message_iter_get_dict_key (&dict);
5954   if (str == NULL || strcmp (str, "array") != 0)
5955     _dbus_assert_not_reached ("wrong dict key");
5956   dbus_free (str);
5957   
5958   if (dbus_message_iter_get_arg_type (&dict) != DBUS_TYPE_ARRAY)
5959     _dbus_assert_not_reached ("Argument type not an array");
5960
5961   if (dbus_message_iter_get_array_type (&dict) != DBUS_TYPE_ARRAY)
5962     _dbus_assert_not_reached ("Array type not array");
5963
5964   dbus_message_iter_init_array_iterator (&dict, &array, NULL);
5965
5966   if (dbus_message_iter_get_arg_type (&array) != DBUS_TYPE_ARRAY)
5967     _dbus_assert_not_reached ("Argument type isn't array");
5968   
5969   if (dbus_message_iter_get_array_type (&array) != DBUS_TYPE_INT32)
5970     _dbus_assert_not_reached ("Array type not int32");
5971   
5972   dbus_message_iter_init_array_iterator (&array, &array2, NULL);
5973
5974   if (dbus_message_iter_get_arg_type (&array2) != DBUS_TYPE_INT32)
5975     _dbus_assert_not_reached ("Argument type isn't int32");
5976
5977   if (dbus_message_iter_get_int32 (&array2) != 0x12345678)
5978     _dbus_assert_not_reached ("Signed integers differ");
5979
5980   if (!dbus_message_iter_next (&array2))
5981     _dbus_assert_not_reached ("Reached end of arguments");
5982
5983   if (dbus_message_iter_get_int32 (&array2) != 0x23456781)
5984     _dbus_assert_not_reached ("Signed integers differ");
5985
5986   if (dbus_message_iter_next (&array2))
5987     _dbus_assert_not_reached ("Didn't reached end of arguments");
5988
5989   if (!dbus_message_iter_next (&array))
5990     _dbus_assert_not_reached ("Reached end of arguments");
5991
5992   if (dbus_message_iter_get_array_type (&array) != DBUS_TYPE_INT32)
5993     _dbus_assert_not_reached ("Array type not int32");
5994
5995   if (!dbus_message_iter_get_int32_array (&array,
5996                                           &our_int_array,
5997                                           &len))
5998     _dbus_assert_not_reached ("couldn't get int32 array");
5999
6000   _dbus_assert (len == 3);
6001   _dbus_assert (our_int_array[0] == 0x34567812 &&
6002                 our_int_array[1] == 0x45678123 &&
6003                 our_int_array[2] == 0x56781234);
6004   dbus_free (our_int_array);
6005   
6006   if (dbus_message_iter_next (&array))
6007     _dbus_assert_not_reached ("Didn't reach end of array");
6008
6009   if (dbus_message_iter_next (&dict))
6010     _dbus_assert_not_reached ("Didn't reach end of dict");
6011   
6012   if (!dbus_message_iter_next (&iter))
6013     _dbus_assert_not_reached ("Reached end of arguments");
6014   
6015   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_BYTE)
6016     {
6017       _dbus_warn ("type was: %d\n", dbus_message_iter_get_arg_type (&iter));
6018       _dbus_assert_not_reached ("wrong type after dict (should be byte)");
6019     }
6020   
6021   if (dbus_message_iter_get_byte (&iter) != 0xF0)
6022     _dbus_assert_not_reached ("wrong value after dict");
6023
6024
6025   if (!dbus_message_iter_next (&iter))
6026     _dbus_assert_not_reached ("Reached end of arguments");
6027   
6028   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_NIL)
6029     _dbus_assert_not_reached ("not a nil type");
6030   
6031   if (!dbus_message_iter_next (&iter))
6032     _dbus_assert_not_reached ("Reached end of arguments");
6033   
6034   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_CUSTOM)
6035     _dbus_assert_not_reached ("wrong type after dict");
6036
6037   if (!dbus_message_iter_get_custom (&iter, &str, &data, &len))
6038     _dbus_assert_not_reached ("failed to get custom type");
6039
6040   _dbus_assert (strcmp (str, "MyTypeName")==0);
6041   _dbus_assert (len == 5);
6042   _dbus_assert (strcmp (data, "data")==0);
6043   dbus_free (str);
6044   dbus_free (data);
6045   
6046   if (!dbus_message_iter_next (&iter))
6047     _dbus_assert_not_reached ("Reached end of arguments");
6048
6049   if (dbus_message_iter_get_byte (&iter) != 0xF0)
6050     _dbus_assert_not_reached ("wrong value after custom");
6051
6052   if (!dbus_message_iter_next (&iter))
6053     _dbus_assert_not_reached ("Reached end of arguments");
6054
6055   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY)
6056     _dbus_assert_not_reached ("no array");
6057
6058   if (dbus_message_iter_get_array_type (&iter) != DBUS_TYPE_INT32)
6059     _dbus_assert_not_reached ("Array type not int32");
6060
6061   if (dbus_message_iter_init_array_iterator (&iter, &array, NULL))
6062     _dbus_assert_not_reached ("non empty array");
6063   
6064   if (!dbus_message_iter_next (&iter))
6065     _dbus_assert_not_reached ("Reached end of arguments");
6066
6067   if (dbus_message_iter_get_byte (&iter) != 0xF0)
6068     _dbus_assert_not_reached ("wrong value after empty array");
6069
6070   if (!dbus_message_iter_next (&iter))
6071     _dbus_assert_not_reached ("Reached end of arguments");
6072
6073   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_DICT)
6074     _dbus_assert_not_reached ("non dict");
6075
6076   if (dbus_message_iter_init_dict_iterator (&iter, &dict))
6077     _dbus_assert_not_reached ("non empty dict");
6078
6079   if (!dbus_message_iter_next (&iter))
6080     _dbus_assert_not_reached ("Reached end of arguments");
6081
6082   if (dbus_message_iter_get_byte (&iter) != 0xF0)
6083     _dbus_assert_not_reached ("wrong value after empty dict");
6084
6085   if (dbus_message_iter_next (&iter))
6086     _dbus_assert_not_reached ("Didn't reach end of arguments");
6087 }
6088
6089
6090 static dbus_bool_t
6091 check_message_handling_type (DBusMessageIter *iter,
6092                              int type)
6093 {
6094   DBusMessageIter child_iter;
6095   
6096   switch (type)
6097     {
6098     case DBUS_TYPE_NIL:
6099       break;
6100     case DBUS_TYPE_BYTE:
6101       dbus_message_iter_get_byte (iter);
6102       break;
6103     case DBUS_TYPE_BOOLEAN:
6104       dbus_message_iter_get_boolean (iter);
6105       break;
6106     case DBUS_TYPE_INT32:
6107       dbus_message_iter_get_int32 (iter);
6108       break;
6109     case DBUS_TYPE_UINT32:
6110       dbus_message_iter_get_uint32 (iter);
6111       break;
6112     case DBUS_TYPE_INT64:
6113 #ifdef DBUS_HAVE_INT64
6114       dbus_message_iter_get_int64 (iter);
6115 #endif
6116       break;
6117     case DBUS_TYPE_UINT64:
6118 #ifdef DBUS_HAVE_INT64
6119       dbus_message_iter_get_uint64 (iter);
6120 #endif
6121       break;
6122     case DBUS_TYPE_DOUBLE:
6123       dbus_message_iter_get_double (iter);
6124       break;
6125     case DBUS_TYPE_STRING:
6126       {
6127         char *str;
6128         str = dbus_message_iter_get_string (iter);
6129         if (str == NULL)
6130           {
6131             _dbus_warn ("NULL string in message\n");
6132             return FALSE;
6133           }
6134         dbus_free (str);
6135       }
6136       break;
6137     case DBUS_TYPE_CUSTOM:
6138       {
6139         char *name;
6140         unsigned char *data;
6141         int len;
6142         
6143         if (!dbus_message_iter_get_custom (iter, &name, &data, &len))
6144           {
6145             _dbus_warn ("error reading name from custom type\n");
6146             return FALSE;
6147           }
6148         dbus_free (data);
6149         dbus_free (name);
6150       }
6151       break;
6152     case DBUS_TYPE_ARRAY:
6153       {
6154         int array_type;
6155
6156         dbus_message_iter_init_array_iterator (iter, &child_iter, &array_type);
6157
6158         while (dbus_message_iter_has_next (&child_iter))
6159           {
6160             if (!check_message_handling_type (&child_iter, array_type))
6161               {
6162                 _dbus_warn ("error in array element\n");
6163                 return FALSE;
6164               }
6165             
6166             if (!dbus_message_iter_next (&child_iter))
6167               break;
6168           }
6169       }
6170       break;
6171     case DBUS_TYPE_DICT:
6172       {
6173         int entry_type;
6174         char *key;
6175         
6176         dbus_message_iter_init_dict_iterator (iter, &child_iter);
6177
6178         while ((entry_type = dbus_message_iter_get_arg_type (&child_iter)) != DBUS_TYPE_INVALID)
6179           {
6180             key = dbus_message_iter_get_dict_key (&child_iter);
6181             if (key == NULL)
6182               {
6183                 _dbus_warn ("error reading dict key\n");
6184                 return FALSE;
6185               }
6186             dbus_free (key);
6187             
6188             if (!check_message_handling_type (&child_iter, entry_type))
6189               {
6190                 _dbus_warn ("error in dict value\n");
6191                 return FALSE;
6192               }
6193             
6194             if (!dbus_message_iter_next (&child_iter))
6195               break;
6196           }
6197       }
6198       break;
6199       
6200     default:
6201       _dbus_warn ("unknown type %d\n", type);
6202       return FALSE;
6203       break;
6204     }
6205   return TRUE;
6206 }
6207   
6208   
6209 static dbus_bool_t
6210 check_message_handling (DBusMessage *message)
6211 {
6212   DBusMessageIter iter;
6213   int type;
6214   dbus_bool_t retval;
6215   dbus_uint32_t client_serial;
6216   
6217   retval = FALSE;
6218   
6219   client_serial = dbus_message_get_serial (message);
6220
6221   /* can't use set_serial due to the assertions at the start of it */
6222   _dbus_marshal_set_uint32 (&message->header,
6223                             message->byte_order,
6224                             CLIENT_SERIAL_OFFSET,
6225                             client_serial);
6226   
6227   if (client_serial != dbus_message_get_serial (message))
6228     {
6229       _dbus_warn ("get/set cycle for client_serial did not succeed\n");
6230       goto failed;
6231     }
6232   
6233   /* If we implement message_set_arg (message, n, value)
6234    * then we would want to test it here
6235    */
6236
6237   dbus_message_iter_init (message, &iter);
6238   while ((type = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID)
6239     {
6240       if (!check_message_handling_type (&iter, type))
6241         goto failed;
6242
6243       if (!dbus_message_iter_next (&iter))
6244         break;
6245     }
6246   
6247   retval = TRUE;
6248   
6249  failed:
6250   return retval;
6251 }
6252
6253 static dbus_bool_t
6254 check_have_valid_message (DBusMessageLoader *loader)
6255 {
6256   DBusMessage *message;
6257   dbus_bool_t retval;
6258
6259   message = NULL;
6260   retval = FALSE;
6261
6262   if (!_dbus_message_loader_queue_messages (loader))
6263     _dbus_assert_not_reached ("no memory to queue messages");
6264   
6265   if (_dbus_message_loader_get_is_corrupted (loader))
6266     {
6267       _dbus_warn ("loader corrupted on message that was expected to be valid\n");
6268       goto failed;
6269     }
6270   
6271   message = _dbus_message_loader_pop_message (loader);
6272   if (message == NULL)
6273     {
6274       _dbus_warn ("didn't load message that was expected to be valid (message not popped)\n");
6275       goto failed;
6276     }
6277   
6278   if (_dbus_string_get_length (&loader->data) > 0)
6279     {
6280       _dbus_warn ("had leftover bytes from expected-to-be-valid single message\n");
6281       goto failed;
6282     }
6283
6284   /* Verify that we're able to properly deal with the message.
6285    * For example, this would detect improper handling of messages
6286    * in nonstandard byte order.
6287    */
6288   if (!check_message_handling (message))
6289     goto failed;  
6290   
6291   retval = TRUE;
6292
6293  failed:
6294   if (message)
6295     dbus_message_unref (message);
6296
6297   return retval;
6298 }
6299
6300 static dbus_bool_t
6301 check_invalid_message (DBusMessageLoader *loader)
6302 {
6303   dbus_bool_t retval;
6304
6305   retval = FALSE;
6306
6307   if (!_dbus_message_loader_queue_messages (loader))
6308     _dbus_assert_not_reached ("no memory to queue messages");
6309   
6310   if (!_dbus_message_loader_get_is_corrupted (loader))
6311     {
6312       _dbus_warn ("loader not corrupted on message that was expected to be invalid\n");
6313       goto failed;
6314     }
6315
6316   retval = TRUE;
6317
6318  failed:
6319   return retval;
6320 }
6321
6322 static dbus_bool_t
6323 check_incomplete_message (DBusMessageLoader *loader)
6324 {
6325   DBusMessage *message;
6326   dbus_bool_t retval;
6327
6328   message = NULL;
6329   retval = FALSE;
6330
6331   if (!_dbus_message_loader_queue_messages (loader))
6332     _dbus_assert_not_reached ("no memory to queue messages");
6333   
6334   if (_dbus_message_loader_get_is_corrupted (loader))
6335     {
6336       _dbus_warn ("loader corrupted on message that was expected to be valid (but incomplete)\n");
6337       goto failed;
6338     }
6339   
6340   message = _dbus_message_loader_pop_message (loader);
6341   if (message != NULL)
6342     {
6343       _dbus_warn ("loaded message that was expected to be incomplete\n");
6344       goto failed;
6345     }
6346
6347   retval = TRUE;
6348
6349  failed:
6350   if (message)
6351     dbus_message_unref (message);
6352   return retval;
6353 }
6354
6355 static dbus_bool_t
6356 check_loader_results (DBusMessageLoader      *loader,
6357                       DBusMessageValidity     validity)
6358 {
6359   if (!_dbus_message_loader_queue_messages (loader))
6360     _dbus_assert_not_reached ("no memory to queue messages");
6361   
6362   switch (validity)
6363     {
6364     case _DBUS_MESSAGE_VALID:
6365       return check_have_valid_message (loader);
6366     case _DBUS_MESSAGE_INVALID:
6367       return check_invalid_message (loader);
6368     case _DBUS_MESSAGE_INCOMPLETE:
6369       return check_incomplete_message (loader);
6370     case _DBUS_MESSAGE_UNKNOWN:
6371       return TRUE;
6372     }
6373
6374   _dbus_assert_not_reached ("bad DBusMessageValidity");
6375   return FALSE;
6376 }
6377
6378
6379 /**
6380  * Loads the message in the given message file.
6381  *
6382  * @param filename filename to load
6383  * @param is_raw if #TRUE load as binary data, if #FALSE as message builder language
6384  * @param data string to load message into
6385  * @returns #TRUE if the message was loaded
6386  */
6387 dbus_bool_t
6388 dbus_internal_do_not_use_load_message_file (const DBusString    *filename,
6389                                             dbus_bool_t          is_raw,
6390                                             DBusString          *data)
6391 {
6392   dbus_bool_t retval;
6393
6394   retval = FALSE;  
6395
6396   if (is_raw)
6397     {
6398       DBusError error;
6399
6400       _dbus_verbose ("Loading raw %s\n", _dbus_string_get_const_data (filename));
6401       dbus_error_init (&error);
6402       if (!_dbus_file_get_contents (data, filename, &error))
6403         {
6404           _dbus_warn ("Could not load message file %s: %s\n",
6405                       _dbus_string_get_const_data (filename),
6406                       error.message);
6407           dbus_error_free (&error);
6408           goto failed;
6409         }
6410     }
6411   else
6412     {
6413       if (!_dbus_message_data_load (data, filename))
6414         {
6415           _dbus_warn ("Could not load message file %s\n",
6416                       _dbus_string_get_const_data (filename));
6417           goto failed;
6418         }
6419     }
6420
6421   retval = TRUE;
6422   
6423  failed:
6424
6425   return retval;
6426 }
6427
6428 /**
6429  * Tries loading the message in the given message file
6430  * and verifies that DBusMessageLoader can handle it.
6431  *
6432  * @param filename filename to load
6433  * @param is_raw if #TRUE load as binary data, if #FALSE as message builder language
6434  * @param expected_validity what the message has to be like to return #TRUE
6435  * @returns #TRUE if the message has the expected validity
6436  */
6437 dbus_bool_t
6438 dbus_internal_do_not_use_try_message_file (const DBusString    *filename,
6439                                            dbus_bool_t          is_raw,
6440                                            DBusMessageValidity  expected_validity)
6441 {
6442   DBusString data;
6443   dbus_bool_t retval;
6444
6445   retval = FALSE;
6446   
6447   if (!_dbus_string_init (&data))
6448     _dbus_assert_not_reached ("could not allocate string\n");
6449
6450   if (!dbus_internal_do_not_use_load_message_file (filename, is_raw,
6451                                                    &data))
6452     goto failed;
6453
6454   retval = dbus_internal_do_not_use_try_message_data (&data, expected_validity);
6455
6456  failed:
6457
6458   if (!retval)
6459     {
6460       if (_dbus_string_get_length (&data) > 0)
6461         _dbus_verbose_bytes_of_string (&data, 0,
6462                                        _dbus_string_get_length (&data));
6463       
6464       _dbus_warn ("Failed message loader test on %s\n",
6465                   _dbus_string_get_const_data (filename));
6466     }
6467   
6468   _dbus_string_free (&data);
6469
6470   return retval;
6471 }
6472
6473 /**
6474  * Tries loading the given message data.
6475  *
6476  *
6477  * @param data the message data
6478  * @param expected_validity what the message has to be like to return #TRUE
6479  * @returns #TRUE if the message has the expected validity
6480  */
6481 dbus_bool_t
6482 dbus_internal_do_not_use_try_message_data (const DBusString    *data,
6483                                            DBusMessageValidity  expected_validity)
6484 {
6485   DBusMessageLoader *loader;
6486   dbus_bool_t retval;
6487   int len;
6488   int i;
6489
6490   loader = NULL;
6491   retval = FALSE;
6492
6493   /* Write the data one byte at a time */
6494   
6495   loader = _dbus_message_loader_new ();
6496
6497   /* check some trivial loader functions */
6498   _dbus_message_loader_ref (loader);
6499   _dbus_message_loader_unref (loader);
6500   _dbus_message_loader_get_max_message_size (loader);
6501   
6502   len = _dbus_string_get_length (data);
6503   for (i = 0; i < len; i++)
6504     {
6505       DBusString *buffer;
6506
6507       _dbus_message_loader_get_buffer (loader, &buffer);
6508       _dbus_string_append_byte (buffer,
6509                                 _dbus_string_get_byte (data, i));
6510       _dbus_message_loader_return_buffer (loader, buffer, 1);
6511     }
6512   
6513   if (!check_loader_results (loader, expected_validity))
6514     goto failed;
6515
6516   _dbus_message_loader_unref (loader);
6517   loader = NULL;
6518
6519   /* Write the data all at once */
6520   
6521   loader = _dbus_message_loader_new ();
6522
6523   {
6524     DBusString *buffer;
6525     
6526     _dbus_message_loader_get_buffer (loader, &buffer);
6527     _dbus_string_copy (data, 0, buffer,
6528                        _dbus_string_get_length (buffer));
6529     _dbus_message_loader_return_buffer (loader, buffer, 1);
6530   }
6531   
6532   if (!check_loader_results (loader, expected_validity))
6533     goto failed;
6534
6535   _dbus_message_loader_unref (loader);
6536   loader = NULL;  
6537
6538   /* Write the data 2 bytes at a time */
6539   
6540   loader = _dbus_message_loader_new ();
6541
6542   len = _dbus_string_get_length (data);
6543   for (i = 0; i < len; i += 2)
6544     {
6545       DBusString *buffer;
6546
6547       _dbus_message_loader_get_buffer (loader, &buffer);
6548       _dbus_string_append_byte (buffer,
6549                                 _dbus_string_get_byte (data, i));
6550       if ((i+1) < len)
6551         _dbus_string_append_byte (buffer,
6552                                   _dbus_string_get_byte (data, i+1));
6553       _dbus_message_loader_return_buffer (loader, buffer, 1);
6554     }
6555   
6556   if (!check_loader_results (loader, expected_validity))
6557     goto failed;
6558
6559   _dbus_message_loader_unref (loader);
6560   loader = NULL;
6561   
6562   retval = TRUE;
6563   
6564  failed:
6565   
6566   if (loader)
6567     _dbus_message_loader_unref (loader);
6568   
6569   return retval;
6570 }
6571
6572 static dbus_bool_t
6573 process_test_subdir (const DBusString          *test_base_dir,
6574                      const char                *subdir,
6575                      DBusMessageValidity        validity,
6576                      DBusForeachMessageFileFunc function,
6577                      void                      *user_data)
6578 {
6579   DBusString test_directory;
6580   DBusString filename;
6581   DBusDirIter *dir;
6582   dbus_bool_t retval;
6583   DBusError error;
6584
6585   retval = FALSE;
6586   dir = NULL;
6587   
6588   if (!_dbus_string_init (&test_directory))
6589     _dbus_assert_not_reached ("didn't allocate test_directory\n");
6590
6591   _dbus_string_init_const (&filename, subdir);
6592   
6593   if (!_dbus_string_copy (test_base_dir, 0,
6594                           &test_directory, 0))
6595     _dbus_assert_not_reached ("couldn't copy test_base_dir to test_directory");
6596   
6597   if (!_dbus_concat_dir_and_file (&test_directory, &filename))    
6598     _dbus_assert_not_reached ("couldn't allocate full path");
6599
6600   _dbus_string_free (&filename);
6601   if (!_dbus_string_init (&filename))
6602     _dbus_assert_not_reached ("didn't allocate filename string\n");
6603
6604   dbus_error_init (&error);
6605   dir = _dbus_directory_open (&test_directory, &error);
6606   if (dir == NULL)
6607     {
6608       _dbus_warn ("Could not open %s: %s\n",
6609                   _dbus_string_get_const_data (&test_directory),
6610                   error.message);
6611       dbus_error_free (&error);
6612       goto failed;
6613     }
6614
6615   printf ("Testing %s:\n", subdir);
6616   
6617  next:
6618   while (_dbus_directory_get_next_file (dir, &filename, &error))
6619     {
6620       DBusString full_path;
6621       dbus_bool_t is_raw;
6622       
6623       if (!_dbus_string_init (&full_path))
6624         _dbus_assert_not_reached ("couldn't init string");
6625
6626       if (!_dbus_string_copy (&test_directory, 0, &full_path, 0))
6627         _dbus_assert_not_reached ("couldn't copy dir to full_path");
6628
6629       if (!_dbus_concat_dir_and_file (&full_path, &filename))
6630         _dbus_assert_not_reached ("couldn't concat file to dir");
6631
6632       if (_dbus_string_ends_with_c_str (&filename, ".message"))
6633         is_raw = FALSE;
6634       else if (_dbus_string_ends_with_c_str (&filename, ".message-raw"))
6635         is_raw = TRUE;
6636       else
6637         {
6638           _dbus_verbose ("Skipping non-.message file %s\n",
6639                          _dbus_string_get_const_data (&filename));
6640           _dbus_string_free (&full_path);
6641           goto next;
6642         }
6643
6644       printf ("    %s\n",
6645               _dbus_string_get_const_data (&filename));
6646       
6647       _dbus_verbose (" expecting %s for %s\n",
6648                      validity == _DBUS_MESSAGE_VALID ? "valid" :
6649                      (validity == _DBUS_MESSAGE_INVALID ? "invalid" :
6650                       (validity == _DBUS_MESSAGE_INCOMPLETE ? "incomplete" : "unknown")),
6651                      _dbus_string_get_const_data (&filename));
6652       
6653       if (! (*function) (&full_path, is_raw, validity, user_data))
6654         {
6655           _dbus_string_free (&full_path);
6656           goto failed;
6657         }
6658       else
6659         _dbus_string_free (&full_path);
6660     }
6661
6662   if (dbus_error_is_set (&error))
6663     {
6664       _dbus_warn ("Could not get next file in %s: %s\n",
6665                   _dbus_string_get_const_data (&test_directory),
6666                   error.message);
6667       dbus_error_free (&error);
6668       goto failed;
6669     }
6670     
6671   retval = TRUE;
6672   
6673  failed:
6674
6675   if (dir)
6676     _dbus_directory_close (dir);
6677   _dbus_string_free (&test_directory);
6678   _dbus_string_free (&filename);
6679
6680   return retval;
6681 }
6682                      
6683 /**
6684  * Runs the given function on every message file in the test suite.
6685  * The function should return #FALSE on test failure or fatal error.
6686  *
6687  * @param test_data_dir root dir of the test suite data files (top_srcdir/test/data)
6688  * @param func the function to run
6689  * @param user_data data for function
6690  * @returns #FALSE if there's a failure
6691  */
6692 dbus_bool_t
6693 dbus_internal_do_not_use_foreach_message_file (const char                *test_data_dir,
6694                                                DBusForeachMessageFileFunc func,
6695                                                void                      *user_data)
6696 {
6697   DBusString test_directory;
6698   dbus_bool_t retval;
6699
6700   retval = FALSE;
6701   
6702   _dbus_string_init_const (&test_directory, test_data_dir);
6703
6704   if (!process_test_subdir (&test_directory, "valid-messages",
6705                             _DBUS_MESSAGE_VALID, func, user_data))
6706     goto failed;
6707
6708   if (!process_test_subdir (&test_directory, "invalid-messages",
6709                             _DBUS_MESSAGE_INVALID, func, user_data))
6710     goto failed;
6711   
6712   if (!process_test_subdir (&test_directory, "incomplete-messages",
6713                             _DBUS_MESSAGE_INCOMPLETE, func, user_data))
6714     goto failed;
6715
6716   retval = TRUE;
6717   
6718  failed:
6719
6720   _dbus_string_free (&test_directory);
6721   
6722   return retval;
6723 }
6724
6725 static void
6726 verify_test_message (DBusMessage *message)
6727 {
6728   DBusMessageIter iter, dict;
6729   DBusError error;
6730   dbus_int32_t our_int;
6731   char *our_str;
6732   double our_double;
6733   dbus_bool_t our_bool;
6734   unsigned char our_byte_1, our_byte_2;
6735   dbus_uint32_t our_uint32;
6736   dbus_int32_t *our_uint32_array;
6737   int our_uint32_array_len;
6738   dbus_int32_t *our_int32_array;
6739   int our_int32_array_len;
6740   char **our_string_array;
6741   int our_string_array_len;
6742 #ifdef DBUS_HAVE_INT64
6743   dbus_int64_t our_int64;
6744   dbus_uint64_t our_uint64;
6745   dbus_int64_t *our_uint64_array;
6746   int our_uint64_array_len;
6747   dbus_int64_t *our_int64_array;
6748   int our_int64_array_len;
6749 #endif
6750   double *our_double_array;
6751   int our_double_array_len;
6752   unsigned char *our_byte_array;
6753   int our_byte_array_len;
6754   unsigned char *our_boolean_array;
6755   int our_boolean_array_len;
6756   
6757   dbus_message_iter_init (message, &iter);
6758
6759   dbus_error_init (&error);
6760   if (!dbus_message_iter_get_args (&iter, &error,
6761                                    DBUS_TYPE_INT32, &our_int,
6762 #ifdef DBUS_HAVE_INT64
6763                                    DBUS_TYPE_INT64, &our_int64,
6764                                    DBUS_TYPE_UINT64, &our_uint64,
6765 #endif
6766                                    DBUS_TYPE_STRING, &our_str,
6767                                    DBUS_TYPE_DOUBLE, &our_double,
6768                                    DBUS_TYPE_BOOLEAN, &our_bool,
6769                                    DBUS_TYPE_BYTE, &our_byte_1,
6770                                    DBUS_TYPE_BYTE, &our_byte_2,
6771                                    DBUS_TYPE_NIL,
6772                                    DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32,
6773                                    &our_uint32_array, &our_uint32_array_len,
6774                                    DBUS_TYPE_ARRAY, DBUS_TYPE_INT32,
6775                                    &our_int32_array, &our_int32_array_len,
6776 #ifdef DBUS_HAVE_INT64
6777                                    DBUS_TYPE_ARRAY, DBUS_TYPE_UINT64,
6778                                    &our_uint64_array, &our_uint64_array_len,
6779                                    DBUS_TYPE_ARRAY, DBUS_TYPE_INT64,
6780                                    &our_int64_array, &our_int64_array_len,
6781 #endif
6782                                    DBUS_TYPE_ARRAY, DBUS_TYPE_STRING,
6783                                    &our_string_array, &our_string_array_len,
6784                                    DBUS_TYPE_ARRAY, DBUS_TYPE_DOUBLE,
6785                                    &our_double_array, &our_double_array_len,
6786                                    DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
6787                                    &our_byte_array, &our_byte_array_len,
6788                                    DBUS_TYPE_ARRAY, DBUS_TYPE_BOOLEAN,
6789                                    &our_boolean_array, &our_boolean_array_len,
6790                                    0))
6791     {
6792       _dbus_warn ("error: %s - %s\n", error.name,
6793                   (error.message != NULL) ? error.message : "no message");
6794       _dbus_assert_not_reached ("Could not get arguments");
6795     }
6796
6797   if (our_int != -0x12345678)
6798     _dbus_assert_not_reached ("integers differ!");
6799
6800 #ifdef DBUS_HAVE_INT64
6801   if (our_int64 != DBUS_INT64_CONSTANT (-0x123456789abcd))
6802     _dbus_assert_not_reached ("64-bit integers differ!");
6803   if (our_uint64 != DBUS_UINT64_CONSTANT (0x123456789abcd))
6804     _dbus_assert_not_reached ("64-bit unsigned integers differ!");
6805 #endif
6806   
6807   if (our_double != 3.14159)
6808     _dbus_assert_not_reached ("doubles differ!");
6809
6810   if (strcmp (our_str, "Test string") != 0)
6811     _dbus_assert_not_reached ("strings differ!");
6812   dbus_free (our_str);
6813
6814   if (!our_bool)
6815     _dbus_assert_not_reached ("booleans differ");
6816
6817   if (our_byte_1 != 42)
6818     _dbus_assert_not_reached ("bytes differ!");
6819
6820   if (our_byte_2 != 24)
6821     _dbus_assert_not_reached ("bytes differ!");
6822
6823   if (our_uint32_array_len != 4 ||
6824       our_uint32_array[0] != 0x12345678 ||
6825       our_uint32_array[1] != 0x23456781 ||
6826       our_uint32_array[2] != 0x34567812 ||
6827       our_uint32_array[3] != 0x45678123)
6828     _dbus_assert_not_reached ("uint array differs");
6829   dbus_free (our_uint32_array);
6830
6831   if (our_int32_array_len != 4 ||
6832       our_int32_array[0] != 0x12345678 ||
6833       our_int32_array[1] != -0x23456781 ||
6834       our_int32_array[2] != 0x34567812 ||
6835       our_int32_array[3] != -0x45678123)
6836     _dbus_assert_not_reached ("int array differs");
6837   dbus_free (our_int32_array);
6838
6839 #ifdef DBUS_HAVE_INT64
6840   if (our_uint64_array_len != 4 ||
6841       our_uint64_array[0] != 0x12345678 ||
6842       our_uint64_array[1] != 0x23456781 ||
6843       our_uint64_array[2] != 0x34567812 ||
6844       our_uint64_array[3] != 0x45678123)
6845     _dbus_assert_not_reached ("uint64 array differs");
6846   dbus_free (our_uint64_array);
6847   
6848   if (our_int64_array_len != 4 ||
6849       our_int64_array[0] != 0x12345678 ||
6850       our_int64_array[1] != -0x23456781 ||
6851       our_int64_array[2] != 0x34567812 ||
6852       our_int64_array[3] != -0x45678123)
6853     _dbus_assert_not_reached ("int64 array differs");
6854   dbus_free (our_int64_array);
6855 #endif /* DBUS_HAVE_INT64 */
6856   
6857   if (our_string_array_len != 4)
6858     _dbus_assert_not_reached ("string array has wrong length");
6859
6860   if (strcmp (our_string_array[0], "Foo") != 0 ||
6861       strcmp (our_string_array[1], "bar") != 0 ||
6862       strcmp (our_string_array[2], "") != 0 ||
6863       strcmp (our_string_array[3], "woo woo woo woo") != 0)
6864     _dbus_assert_not_reached ("string array differs");
6865
6866   dbus_free_string_array (our_string_array);
6867
6868   if (our_double_array_len != 3)
6869     _dbus_assert_not_reached ("double array had wrong length");
6870
6871   /* On all IEEE machines (i.e. everything sane) exact equality
6872    * should be preserved over the wire
6873    */
6874   if (our_double_array[0] != 0.1234 ||
6875       our_double_array[1] != 9876.54321 ||
6876       our_double_array[2] != -300.0)
6877     _dbus_assert_not_reached ("double array had wrong values");
6878
6879   dbus_free (our_double_array);
6880
6881   if (our_byte_array_len != 4)
6882     _dbus_assert_not_reached ("byte array had wrong length");
6883
6884   if (our_byte_array[0] != 'a' ||
6885       our_byte_array[1] != 'b' ||
6886       our_byte_array[2] != 'c' ||
6887       our_byte_array[3] != 234)
6888     _dbus_assert_not_reached ("byte array had wrong values");
6889
6890   dbus_free (our_byte_array);
6891
6892   if (our_boolean_array_len != 5)
6893     _dbus_assert_not_reached ("bool array had wrong length");
6894
6895   if (our_boolean_array[0] != TRUE ||
6896       our_boolean_array[1] != FALSE ||
6897       our_boolean_array[2] != TRUE ||
6898       our_boolean_array[3] != TRUE ||
6899       our_boolean_array[4] != FALSE)
6900     _dbus_assert_not_reached ("bool array had wrong values");
6901
6902   dbus_free (our_boolean_array);
6903
6904   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_DICT)
6905     _dbus_assert_not_reached ("not dict type");
6906      
6907   dbus_message_iter_init_dict_iterator (&iter, &dict);
6908
6909   our_str = dbus_message_iter_get_dict_key (&dict);
6910   if (our_str == NULL || strcmp (our_str, "test") != 0)
6911     _dbus_assert_not_reached ("wrong dict key");
6912   dbus_free (our_str);
6913
6914   if (dbus_message_iter_get_arg_type (&dict) != DBUS_TYPE_UINT32)
6915     {
6916       _dbus_verbose ("dict entry type: %d\n", dbus_message_iter_get_arg_type (&dict));
6917       _dbus_assert_not_reached ("wrong dict entry type");
6918     }
6919
6920   if ((our_uint32 = dbus_message_iter_get_uint32 (&dict)) != 0xDEADBEEF)
6921     {
6922       _dbus_verbose ("dict entry val: %x\n", our_uint32);
6923       _dbus_assert_not_reached ("wrong dict entry value");
6924     }
6925
6926   if (dbus_message_iter_next (&dict))
6927     _dbus_assert_not_reached ("Didn't reach end of dict");
6928   
6929   if (!dbus_message_iter_next (&iter))
6930     _dbus_assert_not_reached ("Reached end of arguments");
6931   
6932   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_UINT32)
6933     _dbus_assert_not_reached ("wrong type after dict");
6934   
6935   if (dbus_message_iter_get_uint32 (&iter) != 0xCAFEBABE)
6936     _dbus_assert_not_reached ("wrong value after dict");
6937
6938   if (dbus_message_iter_next (&iter))
6939     _dbus_assert_not_reached ("Didn't reach end of arguments");
6940 }
6941
6942 /**
6943  * @ingroup DBusMessageInternals
6944  * Unit test for DBusMessage.
6945  *
6946  * @returns #TRUE on success.
6947  */
6948 dbus_bool_t
6949 _dbus_message_test (const char *test_data_dir)
6950 {
6951   DBusMessage *message;
6952   DBusMessageLoader *loader;
6953   DBusMessageIter iter, child_iter, child_iter2, child_iter3;
6954   int i;
6955   const char *data;
6956   DBusMessage *copy;
6957   const char *name1;
6958   const char *name2;
6959   const dbus_uint32_t our_uint32_array[] =
6960     { 0x12345678, 0x23456781, 0x34567812, 0x45678123 };
6961   const dbus_uint32_t our_int32_array[] =
6962     { 0x12345678, -0x23456781, 0x34567812, -0x45678123 };
6963 #ifdef DBUS_HAVE_INT64
6964   const dbus_uint64_t our_uint64_array[] =
6965     { 0x12345678, 0x23456781, 0x34567812, 0x45678123 };
6966   const dbus_uint64_t our_int64_array[] =
6967     { 0x12345678, -0x23456781, 0x34567812, -0x45678123 };
6968 #endif
6969   const char *our_string_array[] = { "Foo", "bar", "", "woo woo woo woo" };
6970   const double our_double_array[] = { 0.1234, 9876.54321, -300.0 };
6971   const unsigned char our_byte_array[] = { 'a', 'b', 'c', 234 };
6972   const unsigned char our_boolean_array[] = { TRUE, FALSE, TRUE, TRUE, FALSE };
6973   char sig[64];
6974   const char *s;
6975   char *t;
6976   DBusError error;
6977   
6978   _dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
6979
6980   message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService",
6981                                           "/org/freedesktop/TestPath",
6982                                           "Foo.TestInterface",
6983                                           "TestMethod");
6984   _dbus_assert (dbus_message_has_destination (message, "org.freedesktop.DBus.TestService"));
6985   _dbus_assert (dbus_message_is_method_call (message, "Foo.TestInterface",
6986                                              "TestMethod"));
6987   _dbus_assert (strcmp (dbus_message_get_path (message),
6988                         "/org/freedesktop/TestPath") == 0);
6989   _dbus_message_set_serial (message, 1234);
6990   /* string length including nul byte not a multiple of 4 */
6991   if (!dbus_message_set_sender (message, "org.foo.bar1"))
6992     _dbus_assert_not_reached ("out of memory");
6993   _dbus_assert (dbus_message_has_sender (message, "org.foo.bar1"));
6994   dbus_message_set_reply_serial (message, 5678);
6995   if (!dbus_message_set_sender (message, NULL))
6996     _dbus_assert_not_reached ("out of memory");
6997   _dbus_assert (!dbus_message_has_sender (message, "org.foo.bar1"));
6998   _dbus_assert (dbus_message_get_serial (message) == 1234);
6999   _dbus_assert (dbus_message_get_reply_serial (message) == 5678);
7000   _dbus_assert (dbus_message_has_destination (message, "org.freedesktop.DBus.TestService"));
7001
7002   _dbus_assert (dbus_message_get_no_reply (message) == FALSE);
7003   dbus_message_set_no_reply (message, TRUE);
7004   _dbus_assert (dbus_message_get_no_reply (message) == TRUE);
7005   dbus_message_set_no_reply (message, FALSE);
7006   _dbus_assert (dbus_message_get_no_reply (message) == FALSE);
7007
7008   /* Set/get some header fields */
7009   
7010   if (!dbus_message_set_path (message, "/foo"))
7011     _dbus_assert_not_reached ("out of memory");
7012   _dbus_assert (strcmp (dbus_message_get_path (message),
7013                         "/foo") == 0);
7014
7015   if (!dbus_message_set_interface (message, "org.Foo"))
7016     _dbus_assert_not_reached ("out of memory");
7017   _dbus_assert (strcmp (dbus_message_get_interface (message),
7018                         "org.Foo") == 0);
7019   
7020   if (!dbus_message_set_member (message, "Bar"))
7021     _dbus_assert_not_reached ("out of memory");
7022   _dbus_assert (strcmp (dbus_message_get_member (message),
7023                         "Bar") == 0);
7024
7025   /* Set/get them with longer values */
7026   if (!dbus_message_set_path (message, "/foo/bar"))
7027     _dbus_assert_not_reached ("out of memory");
7028   _dbus_assert (strcmp (dbus_message_get_path (message),
7029                         "/foo/bar") == 0);
7030
7031   if (!dbus_message_set_interface (message, "org.Foo.Bar"))
7032     _dbus_assert_not_reached ("out of memory");
7033   _dbus_assert (strcmp (dbus_message_get_interface (message),
7034                         "org.Foo.Bar") == 0);
7035   
7036   if (!dbus_message_set_member (message, "BarFoo"))
7037     _dbus_assert_not_reached ("out of memory");
7038   _dbus_assert (strcmp (dbus_message_get_member (message),
7039                         "BarFoo") == 0);
7040
7041   /* Realloc shorter again */
7042   
7043   if (!dbus_message_set_path (message, "/foo"))
7044     _dbus_assert_not_reached ("out of memory");
7045   _dbus_assert (strcmp (dbus_message_get_path (message),
7046                         "/foo") == 0);
7047
7048   if (!dbus_message_set_interface (message, "org.Foo"))
7049     _dbus_assert_not_reached ("out of memory");
7050   _dbus_assert (strcmp (dbus_message_get_interface (message),
7051                         "org.Foo") == 0);
7052   
7053   if (!dbus_message_set_member (message, "Bar"))
7054     _dbus_assert_not_reached ("out of memory");
7055   _dbus_assert (strcmp (dbus_message_get_member (message),
7056                         "Bar") == 0);
7057   
7058   dbus_message_unref (message);
7059   
7060   /* Test the vararg functions */
7061   message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService",
7062                                           "/org/freedesktop/TestPath",
7063                                           "Foo.TestInterface",
7064                                           "TestMethod");
7065   _dbus_message_set_serial (message, 1);
7066   dbus_message_append_args (message,
7067                             DBUS_TYPE_INT32, -0x12345678,
7068 #ifdef DBUS_HAVE_INT64
7069                             DBUS_TYPE_INT64, DBUS_INT64_CONSTANT (-0x123456789abcd),
7070                             DBUS_TYPE_UINT64, DBUS_UINT64_CONSTANT (0x123456789abcd),
7071 #endif
7072                             DBUS_TYPE_STRING, "Test string",
7073                             DBUS_TYPE_DOUBLE, 3.14159,
7074                             DBUS_TYPE_BOOLEAN, TRUE,
7075                             DBUS_TYPE_BYTE, (unsigned char) 42,
7076                             DBUS_TYPE_BYTE, 24,
7077                             DBUS_TYPE_NIL,
7078                             DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, our_uint32_array,
7079                             _DBUS_N_ELEMENTS (our_uint32_array),
7080                             DBUS_TYPE_ARRAY, DBUS_TYPE_INT32, our_int32_array,
7081                             _DBUS_N_ELEMENTS (our_int32_array),
7082 #ifdef DBUS_HAVE_INT64
7083                             DBUS_TYPE_ARRAY, DBUS_TYPE_UINT64, our_uint64_array,
7084                             _DBUS_N_ELEMENTS (our_uint64_array),
7085                             DBUS_TYPE_ARRAY, DBUS_TYPE_INT64, our_int64_array,
7086                             _DBUS_N_ELEMENTS (our_int64_array),
7087 #endif
7088                             DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, our_string_array,
7089                             _DBUS_N_ELEMENTS (our_string_array),
7090                             DBUS_TYPE_ARRAY, DBUS_TYPE_DOUBLE, our_double_array,
7091                             _DBUS_N_ELEMENTS (our_double_array),
7092                             DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, our_byte_array,
7093                             _DBUS_N_ELEMENTS (our_byte_array),
7094                             DBUS_TYPE_ARRAY, DBUS_TYPE_BOOLEAN, our_boolean_array,
7095                             _DBUS_N_ELEMENTS (our_boolean_array),
7096                             0);
7097   
7098   dbus_message_append_iter_init (message, &iter);
7099   dbus_message_iter_append_dict (&iter, &child_iter);
7100   dbus_message_iter_append_dict_key (&child_iter, "test");
7101   dbus_message_iter_append_uint32 (&child_iter, 0xDEADBEEF);
7102   dbus_message_iter_append_uint32 (&iter, 0xCAFEBABE);
7103
7104   i = 0;
7105   sig[i++] = DBUS_TYPE_INT32;
7106 #ifdef DBUS_HAVE_INT64
7107   sig[i++] = DBUS_TYPE_INT64;
7108   sig[i++] = DBUS_TYPE_UINT64;
7109 #endif
7110   sig[i++] = DBUS_TYPE_STRING;
7111   sig[i++] = DBUS_TYPE_DOUBLE;
7112   sig[i++] = DBUS_TYPE_BOOLEAN;
7113   sig[i++] = DBUS_TYPE_BYTE;
7114   sig[i++] = DBUS_TYPE_BYTE;
7115   sig[i++] = DBUS_TYPE_NIL;
7116   sig[i++] = DBUS_TYPE_ARRAY;
7117   sig[i++] = DBUS_TYPE_UINT32;
7118   sig[i++] = DBUS_TYPE_ARRAY;
7119   sig[i++] = DBUS_TYPE_INT32;
7120 #ifdef DBUS_HAVE_INT64
7121   sig[i++] = DBUS_TYPE_ARRAY;
7122   sig[i++] = DBUS_TYPE_UINT64;
7123   sig[i++] = DBUS_TYPE_ARRAY;
7124   sig[i++] = DBUS_TYPE_INT64;
7125 #endif
7126   sig[i++] = DBUS_TYPE_ARRAY;
7127   sig[i++] = DBUS_TYPE_STRING;
7128   sig[i++] = DBUS_TYPE_ARRAY;
7129   sig[i++] = DBUS_TYPE_DOUBLE;
7130   sig[i++] = DBUS_TYPE_ARRAY;
7131   sig[i++] = DBUS_TYPE_BYTE;
7132   sig[i++] = DBUS_TYPE_ARRAY;
7133   sig[i++] = DBUS_TYPE_BOOLEAN;
7134   sig[i++] = DBUS_TYPE_DICT;
7135   sig[i++] = DBUS_TYPE_UINT32;
7136   sig[i++] = DBUS_TYPE_INVALID;
7137
7138   _dbus_assert (i < (int) _DBUS_N_ELEMENTS (sig));
7139   
7140   _dbus_verbose_bytes_of_string (&message->header, 0,
7141                                  _dbus_string_get_length (&message->header));
7142   _dbus_verbose_bytes_of_string (&message->body, 0,
7143                                  _dbus_string_get_length (&message->body));
7144   
7145   _dbus_verbose ("Signature expected \"%s\" actual \"%s\"\n",
7146                  sig, dbus_message_get_signature (message));
7147   
7148   s = dbus_message_get_signature (message);
7149   
7150   _dbus_assert (dbus_message_has_signature (message, sig));
7151   _dbus_assert (strcmp (s, sig) == 0);
7152   
7153   verify_test_message (message);
7154
7155   copy = dbus_message_copy (message);
7156   
7157   _dbus_assert (message->client_serial == copy->client_serial);
7158   _dbus_assert (message->reply_serial == copy->reply_serial);
7159   _dbus_assert (message->header_padding == copy->header_padding);
7160   
7161   _dbus_assert (_dbus_string_get_length (&message->header) ==
7162                 _dbus_string_get_length (&copy->header));
7163
7164   _dbus_assert (_dbus_string_get_length (&message->body) ==
7165                 _dbus_string_get_length (&copy->body));
7166   
7167   verify_test_message (copy);
7168
7169   name1 = dbus_message_get_interface (message);
7170   name2 = dbus_message_get_interface (copy);
7171
7172   _dbus_assert (strcmp (name1, name2) == 0);
7173
7174   name1 = dbus_message_get_member (message);
7175   name2 = dbus_message_get_member (copy);
7176
7177   _dbus_assert (strcmp (name1, name2) == 0);
7178   
7179   dbus_message_unref (message);  
7180   dbus_message_unref (copy);
7181
7182   message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService",
7183                                           "/org/freedesktop/TestPath",
7184                                           "Foo.TestInterface",
7185                                           "TestMethod");
7186
7187   _dbus_message_set_serial (message, 1);
7188   dbus_message_set_reply_serial (message, 0x12345678);
7189
7190   dbus_message_append_iter_init (message, &iter);
7191   dbus_message_iter_append_string (&iter, "Test string");
7192   dbus_message_iter_append_int32 (&iter, -0x12345678);
7193   dbus_message_iter_append_uint32 (&iter, 0xedd1e);
7194   dbus_message_iter_append_double (&iter, 3.14159);
7195
7196   dbus_message_iter_append_array (&iter, &child_iter, DBUS_TYPE_DOUBLE);
7197   dbus_message_iter_append_double (&child_iter, 1.5);
7198   dbus_message_iter_append_double (&child_iter, 2.5);
7199
7200   /* dict */
7201   dbus_message_iter_append_dict (&iter, &child_iter);
7202   dbus_message_iter_append_dict_key (&child_iter, "test");
7203   dbus_message_iter_append_uint32 (&child_iter, 0xDEADBEEF);
7204
7205   /* dict (in dict) */
7206   dbus_message_iter_append_dict_key (&child_iter, "testdict");
7207   dbus_message_iter_append_dict (&child_iter, &child_iter2);
7208
7209   dbus_message_iter_append_dict_key (&child_iter2, "dictkey");
7210   dbus_message_iter_append_string (&child_iter2, "dictvalue");
7211
7212   /* array of array of int32  (in dict) */
7213   dbus_message_iter_append_dict_key (&child_iter, "array");
7214   dbus_message_iter_append_array (&child_iter, &child_iter2, DBUS_TYPE_ARRAY);
7215   dbus_message_iter_append_array (&child_iter2, &child_iter3, DBUS_TYPE_INT32);
7216   dbus_message_iter_append_int32 (&child_iter3, 0x12345678);
7217   dbus_message_iter_append_int32 (&child_iter3, 0x23456781);
7218   _dbus_warn ("next call expected to fail with wrong array type\n");
7219   _dbus_assert (!dbus_message_iter_append_array (&child_iter2, &child_iter3, DBUS_TYPE_UINT32));
7220   dbus_message_iter_append_array (&child_iter2, &child_iter3, DBUS_TYPE_INT32);
7221   dbus_message_iter_append_int32 (&child_iter3, 0x34567812);
7222   dbus_message_iter_append_int32 (&child_iter3, 0x45678123);
7223   dbus_message_iter_append_int32 (&child_iter3, 0x56781234);
7224   
7225   dbus_message_iter_append_byte (&iter, 0xF0);
7226
7227   dbus_message_iter_append_nil (&iter);
7228
7229   dbus_message_iter_append_custom (&iter, "MyTypeName",
7230                                    "data", 5);
7231   
7232   dbus_message_iter_append_byte (&iter, 0xF0);
7233
7234   dbus_message_iter_append_array (&iter, &child_iter, DBUS_TYPE_INT32);
7235
7236   dbus_message_iter_append_byte (&iter, 0xF0);
7237
7238   dbus_message_iter_append_dict (&iter, &child_iter);
7239
7240   dbus_message_iter_append_byte (&iter, 0xF0);
7241
7242   message_iter_test (message);
7243   
7244   /* Message loader test */
7245   _dbus_message_lock (message);
7246   loader = _dbus_message_loader_new ();
7247
7248   /* check ref/unref */
7249   _dbus_message_loader_ref (loader);
7250   _dbus_message_loader_unref (loader);
7251   
7252   /* Write the header data one byte at a time */
7253   data = _dbus_string_get_const_data (&message->header);
7254   for (i = 0; i < _dbus_string_get_length (&message->header); i++)
7255     {
7256       DBusString *buffer;
7257
7258       _dbus_message_loader_get_buffer (loader, &buffer);
7259       _dbus_string_append_byte (buffer, data[i]);
7260       _dbus_message_loader_return_buffer (loader, buffer, 1);
7261     }
7262
7263   /* Write the body data one byte at a time */
7264   data = _dbus_string_get_const_data (&message->body);
7265   for (i = 0; i < _dbus_string_get_length (&message->body); i++)
7266     {
7267       DBusString *buffer;
7268
7269       _dbus_message_loader_get_buffer (loader, &buffer);
7270       _dbus_string_append_byte (buffer, data[i]);
7271       _dbus_message_loader_return_buffer (loader, buffer, 1);
7272     }
7273
7274   copy = dbus_message_copy (message); /* save for tests below */
7275   dbus_message_unref (message);
7276
7277   /* Now pop back the message */
7278   if (!_dbus_message_loader_queue_messages (loader))
7279     _dbus_assert_not_reached ("no memory to queue messages");
7280   
7281   if (_dbus_message_loader_get_is_corrupted (loader))
7282     _dbus_assert_not_reached ("message loader corrupted");
7283   
7284   message = _dbus_message_loader_pop_message (loader);
7285   if (!message)
7286     _dbus_assert_not_reached ("received a NULL message");
7287
7288   if (dbus_message_get_reply_serial (message) != 0x12345678)
7289     _dbus_assert_not_reached ("reply serial fields differ");
7290   
7291   message_iter_test (message);
7292   
7293   dbus_message_unref (message);
7294   _dbus_message_loader_unref (loader);
7295
7296   message = dbus_message_new_method_return (copy);
7297   if (message == NULL)
7298     _dbus_assert_not_reached ("out of memory\n");
7299   dbus_message_unref (copy);
7300
7301   if (!dbus_message_append_args (message,
7302                                  DBUS_TYPE_STRING, "hello",
7303                                  DBUS_TYPE_INVALID))
7304     _dbus_assert_not_reached ("no memory");
7305
7306   if (!dbus_message_has_signature (message, "s"))
7307     _dbus_assert_not_reached ("method return has wrong signature");
7308
7309   dbus_error_init (&error);
7310   if (!dbus_message_get_args (message, &error, DBUS_TYPE_STRING,
7311                               &t, DBUS_TYPE_INVALID))
7312     
7313     {
7314       _dbus_warn ("Failed to get expected string arg: %s\n", error.message);
7315       exit (1);
7316     }
7317   dbus_free (t);
7318   
7319   dbus_message_unref (message);
7320   
7321   /* Now load every message in test_data_dir if we have one */
7322   if (test_data_dir == NULL)
7323     return TRUE;
7324
7325   return dbus_internal_do_not_use_foreach_message_file (test_data_dir,
7326                                                         (DBusForeachMessageFileFunc)
7327                                                         dbus_internal_do_not_use_try_message_file,
7328                                                         NULL);
7329 }
7330
7331 #endif /* DBUS_BUILD_TESTS */