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