2003-08-19 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 static dbus_bool_t
4053 _dbus_message_has_type_interface_member (DBusMessage *message,
4054                                          int          type,
4055                                          const char  *interface,
4056                                          const char  *method)
4057 {
4058   const char *n;
4059
4060   _dbus_assert (message != NULL);
4061   _dbus_assert (interface != NULL);
4062   _dbus_assert (method != NULL);
4063
4064   if (dbus_message_get_type (message) != type)
4065     return FALSE;
4066
4067   /* Optimize by checking the short method name first
4068    * instead of the longer interface name
4069    */  
4070
4071   n = dbus_message_get_member (message);
4072
4073   if (n && strcmp (n, method) == 0)
4074     {
4075       n = dbus_message_get_interface (message);
4076       
4077       if (n && strcmp (n, interface) == 0)
4078         return TRUE;
4079     }
4080
4081   return FALSE;
4082 }
4083
4084 /**
4085  * Checks whether the message is a method call with the given
4086  * interface and member fields.  If the message is not
4087  * #DBUS_MESSAGE_TYPE_METHOD_CALL, or has a different interface or member field,
4088  * returns #FALSE.
4089  *
4090  * @param message the message
4091  * @param interface the name to check (must not be #NULL)
4092  * @param method the name to check (must not be #NULL)
4093  * 
4094  * @returns #TRUE if the message is the specified method call
4095  */
4096 dbus_bool_t
4097 dbus_message_is_method_call (DBusMessage *message,
4098                              const char  *interface,
4099                              const char  *method)
4100 {
4101   _dbus_return_val_if_fail (message != NULL, FALSE);
4102   _dbus_return_val_if_fail (interface != NULL, FALSE);
4103   _dbus_return_val_if_fail (method != NULL, FALSE);
4104
4105   return _dbus_message_has_type_interface_member (message,
4106                                                   DBUS_MESSAGE_TYPE_METHOD_CALL,
4107                                                   interface, method);
4108 }
4109
4110 /**
4111  * Checks whether the message is a signal with the given
4112  * interface and member fields.  If the message is not
4113  * #DBUS_MESSAGE_TYPE_SIGNAL, or has a different interface or member field,
4114  * returns #FALSE.
4115  *
4116  * @param message the message
4117  * @param interface the name to check (must not be #NULL)
4118  * @param signal_name the name to check (must not be #NULL)
4119  * 
4120  * @returns #TRUE if the message is the specified signal
4121  */
4122 dbus_bool_t
4123 dbus_message_is_signal (DBusMessage *message,
4124                         const char  *interface,
4125                         const char  *signal_name)
4126 {
4127   _dbus_return_val_if_fail (message != NULL, FALSE);
4128   _dbus_return_val_if_fail (interface != NULL, FALSE);
4129   _dbus_return_val_if_fail (signal_name != NULL, FALSE);
4130
4131   return _dbus_message_has_type_interface_member (message,
4132                                                   DBUS_MESSAGE_TYPE_SIGNAL,
4133                                                   interface, signal_name);
4134 }
4135
4136 /**
4137  * Checks whether the message is an error reply with the given error
4138  * name.  If the message is not #DBUS_MESSAGE_TYPE_ERROR, or has a
4139  * different name, returns #FALSE.
4140  *
4141  * @param message the message
4142  * @param error_name the name to check (must not be #NULL)
4143  * 
4144  * @returns #TRUE if the message is the specified error
4145  */
4146 dbus_bool_t
4147 dbus_message_is_error (DBusMessage *message,
4148                         const char  *error_name)
4149 {
4150   const char *n;
4151   
4152   _dbus_return_val_if_fail (message != NULL, FALSE);
4153   _dbus_return_val_if_fail (error_name != NULL, FALSE);
4154
4155   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
4156     return FALSE;
4157
4158   n = dbus_message_get_error_name (message);
4159
4160   if (n && strcmp (n, error_name) == 0)
4161     return TRUE;
4162   else
4163     return FALSE;
4164 }
4165
4166 /**
4167  * Checks whether the message was sent to the given service.  If the
4168  * message has no service specified or has a different name, returns
4169  * #FALSE.
4170  *
4171  * @param message the message
4172  * @param service the service to check (must not be #NULL)
4173  * 
4174  * @returns #TRUE if the message has the given destination service
4175  */
4176 dbus_bool_t
4177 dbus_message_has_destination (DBusMessage  *message,
4178                               const char   *service)
4179 {
4180   const char *s;
4181
4182   _dbus_return_val_if_fail (message != NULL, FALSE);
4183   _dbus_return_val_if_fail (service != NULL, FALSE);
4184   
4185   s = dbus_message_get_destination (message);
4186
4187   if (s && strcmp (s, service) == 0)
4188     return TRUE;
4189   else
4190     return FALSE;
4191 }
4192
4193 /**
4194  * Checks whether the message has the given service as its sender.  If
4195  * the message has no sender specified or has a different sender,
4196  * returns #FALSE. Note that if a peer application owns multiple
4197  * services, its messages will have only one of those services as the
4198  * sender (usually the base service). So you can't use this
4199  * function to prove the sender didn't own service Foo, you can
4200  * only use it to prove that it did.
4201  *
4202  * @param message the message
4203  * @param service the service to check (must not be #NULL)
4204  * 
4205  * @returns #TRUE if the message has the given origin service
4206  */
4207 dbus_bool_t
4208 dbus_message_has_sender (DBusMessage  *message,
4209                          const char   *service)
4210 {
4211   const char *s;
4212
4213   _dbus_assert (service != NULL);
4214   
4215   s = dbus_message_get_sender (message);
4216
4217   if (s && strcmp (s, service) == 0)
4218     return TRUE;
4219   else
4220     return FALSE;
4221 }
4222
4223 /**
4224  * Sets a #DBusError based on the contents of the given
4225  * message. The error is only set if the message
4226  * is an error message, as in DBUS_MESSAGE_TYPE_ERROR.
4227  * The name of the error is set to the name of the message,
4228  * and the error message is set to the first argument
4229  * if the argument exists and is a string.
4230  *
4231  * The return value indicates whether the error was set (the error is
4232  * set if and only if the message is an error message).
4233  * So you can check for an error reply and convert it to DBusError
4234  * in one go.
4235  *
4236  * @param error the error to set
4237  * @param message the message to set it from
4238  * @returns #TRUE if dbus_message_get_is_error() returns #TRUE for the message
4239  */
4240 dbus_bool_t
4241 dbus_set_error_from_message (DBusError   *error,
4242                              DBusMessage *message)
4243 {
4244   char *str;
4245
4246   _dbus_return_val_if_fail (message != NULL, FALSE);
4247   _dbus_return_val_if_error_is_set (error, FALSE);
4248   
4249   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
4250     return FALSE;
4251
4252   str = NULL;
4253   dbus_message_get_args (message, NULL,
4254                          DBUS_TYPE_STRING, &str,
4255                          DBUS_TYPE_INVALID);
4256
4257   dbus_set_error (error, dbus_message_get_error_name (message),
4258                   str ? "%s" : NULL, str);
4259
4260   dbus_free (str);
4261   
4262   return TRUE;
4263 }
4264
4265 /** @} */
4266
4267 /**
4268  * @addtogroup DBusMessageInternals
4269  *
4270  * @{
4271  */
4272 /**
4273  * @typedef DBusMessageLoader
4274  *
4275  * The DBusMessageLoader object encapsulates the process of converting
4276  * a byte stream into a series of DBusMessage. It buffers the incoming
4277  * bytes as efficiently as possible, and generates a queue of
4278  * messages. DBusMessageLoader is typically used as part of a
4279  * DBusTransport implementation. The DBusTransport then hands off
4280  * the loaded messages to a DBusConnection, making the messages
4281  * visible to the application.
4282  *
4283  * @todo write tests for break-loader that a) randomly delete header
4284  * fields and b) set string fields to zero-length and other funky
4285  * values.
4286  * 
4287  */
4288
4289 /* we definitely use signed ints for sizes, so don't exceed
4290  * _DBUS_INT_MAX; and add 16 for paranoia, since a message
4291  * over 128M is pretty nuts anyhow.
4292  */
4293
4294 /**
4295  * The maximum sane message size.
4296  */
4297 #define MAX_SANE_MESSAGE_SIZE (_DBUS_INT_MAX/16)
4298
4299 /**
4300  * Implementation details of DBusMessageLoader.
4301  * All members are private.
4302  */
4303 struct DBusMessageLoader
4304 {
4305   int refcount;        /**< Reference count. */
4306
4307   DBusString data;     /**< Buffered data */
4308   
4309   DBusList *messages;  /**< Complete messages. */
4310
4311   long max_message_size; /**< Maximum size of a message */
4312   
4313   unsigned int buffer_outstanding : 1; /**< Someone is using the buffer to read */
4314
4315   unsigned int corrupted : 1; /**< We got broken data, and are no longer working */
4316 };
4317
4318 /**
4319  * The initial buffer size of the message loader.
4320  * 
4321  * @todo this should be based on min header size plus some average
4322  * body size, or something. Or rather, the min header size only, if we
4323  * want to try to read only the header, store that in a DBusMessage,
4324  * then read only the body and store that, etc., depends on
4325  * how we optimize _dbus_message_loader_get_buffer() and what
4326  * the exact message format is.
4327  */
4328 #define INITIAL_LOADER_DATA_LEN 32
4329
4330 /**
4331  * Creates a new message loader. Returns #NULL if memory can't
4332  * be allocated.
4333  *
4334  * @returns new loader, or #NULL.
4335  */
4336 DBusMessageLoader*
4337 _dbus_message_loader_new (void)
4338 {
4339   DBusMessageLoader *loader;
4340
4341   loader = dbus_new0 (DBusMessageLoader, 1);
4342   if (loader == NULL)
4343     return NULL;
4344   
4345   loader->refcount = 1;
4346
4347   /* Try to cap message size at something that won't *totally* hose
4348    * the system if we have a couple of them.
4349    */
4350   loader->max_message_size = _DBUS_ONE_MEGABYTE * 32;
4351   
4352   if (!_dbus_string_init (&loader->data))
4353     {
4354       dbus_free (loader);
4355       return NULL;
4356     }
4357
4358   /* preallocate the buffer for speed, ignore failure */
4359   _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN);
4360   _dbus_string_set_length (&loader->data, 0);
4361   
4362   return loader;
4363 }
4364
4365 /**
4366  * Increments the reference count of the loader.
4367  *
4368  * @param loader the loader.
4369  */
4370 void
4371 _dbus_message_loader_ref (DBusMessageLoader *loader)
4372 {
4373   loader->refcount += 1;
4374 }
4375
4376 /**
4377  * Decrements the reference count of the loader and finalizes the
4378  * loader when the count reaches zero.
4379  *
4380  * @param loader the loader.
4381  */
4382 void
4383 _dbus_message_loader_unref (DBusMessageLoader *loader)
4384 {
4385   loader->refcount -= 1;
4386   if (loader->refcount == 0)
4387     {
4388       _dbus_list_foreach (&loader->messages,
4389                           (DBusForeachFunction) dbus_message_unref,
4390                           NULL);
4391       _dbus_list_clear (&loader->messages);
4392       _dbus_string_free (&loader->data);
4393       dbus_free (loader);
4394     }
4395 }
4396
4397 /**
4398  * Gets the buffer to use for reading data from the network.  Network
4399  * data is read directly into an allocated buffer, which is then used
4400  * in the DBusMessage, to avoid as many extra memcpy's as possible.
4401  * The buffer must always be returned immediately using
4402  * _dbus_message_loader_return_buffer(), even if no bytes are
4403  * successfully read.
4404  *
4405  * @todo this function can be a lot more clever. For example
4406  * it can probably always return a buffer size to read exactly
4407  * the body of the next message, thus avoiding any memory wastage
4408  * or reallocs.
4409  *
4410  * @todo we need to enforce a max length on strings in header fields.
4411  * 
4412  * @param loader the message loader.
4413  * @param buffer the buffer
4414  */
4415 void
4416 _dbus_message_loader_get_buffer (DBusMessageLoader  *loader,
4417                                  DBusString        **buffer)
4418 {
4419   _dbus_assert (!loader->buffer_outstanding);
4420
4421   *buffer = &loader->data;
4422   
4423   loader->buffer_outstanding = TRUE;
4424 }
4425
4426 /**
4427  * The smallest header size that can occur. 
4428  * (It won't be valid)
4429  */
4430 #define DBUS_MINIMUM_HEADER_SIZE 16
4431
4432 /** Pack four characters as in "abcd" into a uint32 */
4433 #define FOUR_CHARS_TO_UINT32(a, b, c, d)                \
4434                       ((((dbus_uint32_t)a) << 24) |     \
4435                        (((dbus_uint32_t)b) << 16) |     \
4436                        (((dbus_uint32_t)c) << 8)  |     \
4437                        ((dbus_uint32_t)d))
4438
4439 /** DBUS_HEADER_FIELD_INTERFACE packed into a dbus_uint32_t */
4440 #define DBUS_HEADER_FIELD_INTERFACE_AS_UINT32    \
4441   FOUR_CHARS_TO_UINT32 ('i', 'f', 'c', 'e')
4442
4443 /** DBUS_HEADER_FIELD_MEMBER packed into a dbus_uint32_t */
4444 #define DBUS_HEADER_FIELD_MEMBER_AS_UINT32    \
4445   FOUR_CHARS_TO_UINT32 ('m', 'e', 'b', 'r')
4446
4447 /** DBUS_HEADER_FIELD_ERROR_NAME packed into a dbus_uint32_t */
4448 #define DBUS_HEADER_FIELD_ERROR_NAME_AS_UINT32    \
4449   FOUR_CHARS_TO_UINT32 ('e', 'r', 'n', 'm')
4450
4451 /** DBUS_HEADER_FIELD_SERVICE packed into a dbus_uint32_t */
4452 #define DBUS_HEADER_FIELD_SERVICE_AS_UINT32 \
4453   FOUR_CHARS_TO_UINT32 ('s', 'r', 'v', 'c')
4454
4455 /** DBUS_HEADER_FIELD_REPLY packed into a dbus_uint32_t */
4456 #define DBUS_HEADER_FIELD_REPLY_AS_UINT32   \
4457   FOUR_CHARS_TO_UINT32 ('r', 'p', 'l', 'y')
4458
4459 /** DBUS_HEADER_FIELD_SENDER Packed into a dbus_uint32_t */
4460 #define DBUS_HEADER_FIELD_SENDER_AS_UINT32  \
4461   FOUR_CHARS_TO_UINT32 ('s', 'n', 'd', 'r')
4462
4463 static dbus_bool_t
4464 decode_string_field (const DBusString   *data,
4465                      HeaderField         fields[FIELD_LAST],
4466                      int                 pos,
4467                      int                 type,
4468                      int                 field,
4469                      const char         *field_name)
4470 {
4471   DBusString tmp;
4472   int string_data_pos;
4473   
4474   if (fields[field].offset >= 0)
4475     {
4476       _dbus_verbose ("%s field provided twice\n",
4477                      field_name);
4478       return FALSE;
4479     }
4480
4481   if (type != DBUS_TYPE_STRING)
4482     {
4483       _dbus_verbose ("%s field has wrong type %s\n",
4484                      field_name, _dbus_type_to_string (type));
4485       return FALSE;
4486     }
4487
4488   /* skip padding after typecode, skip string length;
4489    * we assume that the string arg has already been validated
4490    * for sanity and UTF-8
4491    */
4492   string_data_pos = _DBUS_ALIGN_VALUE (pos, 4) + 4;
4493   _dbus_assert (string_data_pos < _dbus_string_get_length (data));
4494   
4495   _dbus_string_init_const (&tmp,
4496                            _dbus_string_get_const_data (data) + string_data_pos);
4497
4498   if (field == FIELD_INTERFACE)
4499     {
4500       if (!_dbus_string_validate_interface (&tmp, 0, _dbus_string_get_length (&tmp)))
4501         {
4502           _dbus_verbose ("%s field has invalid content \"%s\"\n",
4503                          field_name, _dbus_string_get_const_data (&tmp));
4504           return FALSE;
4505         }
4506       
4507       if (_dbus_string_equal_c_str (&tmp,
4508                                     DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL))
4509         {
4510           _dbus_verbose ("Message is on the local interface\n");
4511           return FALSE;
4512         }
4513     }
4514   else if (field == FIELD_MEMBER)
4515     {
4516       if (!_dbus_string_validate_member (&tmp, 0, _dbus_string_get_length (&tmp)))
4517         {
4518           _dbus_verbose ("%s field has invalid content \"%s\"\n",
4519                          field_name, _dbus_string_get_const_data (&tmp));
4520           return FALSE;
4521         }
4522     }
4523   else if (field == FIELD_ERROR_NAME)
4524     {
4525       if (!_dbus_string_validate_error_name (&tmp, 0, _dbus_string_get_length (&tmp)))
4526         {
4527           _dbus_verbose ("%s field has invalid content \"%s\"\n",
4528                          field_name, _dbus_string_get_const_data (&tmp));
4529           return FALSE;
4530         }
4531     }
4532   else if (field == FIELD_SERVICE ||
4533            field == FIELD_SENDER)
4534     {
4535       if (!_dbus_string_validate_service (&tmp, 0, _dbus_string_get_length (&tmp)))
4536         {
4537           _dbus_verbose ("%s field has invalid content \"%s\"\n",
4538                          field_name, _dbus_string_get_const_data (&tmp));
4539           return FALSE;
4540         }
4541     }  
4542   else
4543     {
4544       _dbus_assert_not_reached ("Unknown field\n");
4545     }
4546   
4547   fields[field].offset = _DBUS_ALIGN_VALUE (pos, 4);
4548   
4549 #if 0
4550   _dbus_verbose ("Found field %s name at offset %d\n",
4551                  field_name, fields[field].offset);
4552 #endif
4553
4554   return TRUE;
4555 }
4556
4557 static dbus_bool_t
4558 decode_header_data (const DBusString   *data,
4559                     int                 header_len,
4560                     int                 byte_order,
4561                     int                 message_type,
4562                     HeaderField         fields[FIELD_LAST],
4563                     int                *message_padding)
4564 {
4565   const char *field;
4566   int pos, new_pos;
4567   int i;
4568   int type;
4569   
4570   if (header_len < 16)
4571     {
4572       _dbus_verbose ("Header length %d is too short\n", header_len);
4573       return FALSE;
4574     }
4575   
4576   i = 0;
4577   while (i < FIELD_LAST)
4578     {
4579       fields[i].offset = -1;
4580       ++i;
4581     }
4582   
4583   fields[FIELD_HEADER_LENGTH].offset = 4;
4584   fields[FIELD_BODY_LENGTH].offset = 8;   
4585   fields[FIELD_CLIENT_SERIAL].offset = 12;
4586   
4587   /* Now handle the named fields. A real named field is at least 4
4588    * bytes for the name, plus a type code (1 byte) plus padding.  So
4589    * if we have less than 8 bytes left, it must be alignment padding,
4590    * not a field. While >= 8 bytes can't be entirely alignment
4591    * padding.
4592    */  
4593   pos = 16;
4594   while ((pos + 7) < header_len)
4595     {
4596       pos = _DBUS_ALIGN_VALUE (pos, 4);
4597       
4598       if ((pos + 4) > header_len)
4599         {
4600           _dbus_verbose ("not enough space remains in header for header field value\n");
4601           return FALSE;
4602         }
4603       
4604       field =_dbus_string_get_const_data_len (data, pos, 4);
4605       pos += 4;
4606
4607       _dbus_assert (_DBUS_ALIGN_ADDRESS (field, 4) == field);
4608       
4609       if (!_dbus_marshal_validate_type (data, pos, &type, &pos))
4610         {
4611           _dbus_verbose ("Failed to validate type of named header field\n");
4612           return FALSE;
4613         }
4614       
4615       if (!_dbus_marshal_validate_arg (data, byte_order, 0, type, -1, pos, &new_pos))
4616         {
4617           _dbus_verbose ("Failed to validate argument to named header field\n");
4618           return FALSE;
4619         }
4620
4621       if (new_pos > header_len)
4622         {
4623           _dbus_verbose ("Named header field tries to extend beyond header length\n");
4624           return FALSE;
4625         }
4626       
4627       switch (DBUS_UINT32_FROM_BE (*(int*)field))
4628         {
4629         case DBUS_HEADER_FIELD_SERVICE_AS_UINT32:
4630           if (!decode_string_field (data, fields, pos, type,
4631                                     FIELD_SERVICE,
4632                                     DBUS_HEADER_FIELD_SERVICE))
4633             return FALSE;
4634           break;
4635
4636         case DBUS_HEADER_FIELD_INTERFACE_AS_UINT32:
4637           if (!decode_string_field (data, fields, pos, type,
4638                                     FIELD_INTERFACE,
4639                                     DBUS_HEADER_FIELD_INTERFACE))
4640             return FALSE;
4641           break;
4642
4643         case DBUS_HEADER_FIELD_MEMBER_AS_UINT32:
4644           if (!decode_string_field (data, fields, pos, type,
4645                                     FIELD_MEMBER,
4646                                     DBUS_HEADER_FIELD_MEMBER))
4647             return FALSE;
4648           break;
4649
4650         case DBUS_HEADER_FIELD_ERROR_NAME_AS_UINT32:
4651           if (!decode_string_field (data, fields, pos, type,
4652                                     FIELD_ERROR_NAME,
4653                                     DBUS_HEADER_FIELD_ERROR_NAME))
4654             return FALSE;
4655           break;
4656           
4657         case DBUS_HEADER_FIELD_SENDER_AS_UINT32:
4658           if (!decode_string_field (data, fields, pos, type,
4659                                     FIELD_SENDER,
4660                                     DBUS_HEADER_FIELD_SENDER))
4661             return FALSE;
4662           break;
4663           
4664         case DBUS_HEADER_FIELD_REPLY_AS_UINT32:
4665           if (fields[FIELD_REPLY_SERIAL].offset >= 0)
4666             {
4667               _dbus_verbose ("%s field provided twice\n",
4668                              DBUS_HEADER_FIELD_REPLY);
4669               return FALSE;
4670             }
4671
4672           if (type != DBUS_TYPE_UINT32)
4673             {
4674               _dbus_verbose ("%s field has wrong type\n", DBUS_HEADER_FIELD_REPLY);
4675               return FALSE;
4676             }
4677           
4678           fields[FIELD_REPLY_SERIAL].offset = _DBUS_ALIGN_VALUE (pos, 4);
4679
4680           _dbus_verbose ("Found reply serial at offset %d\n",
4681                          fields[FIELD_REPLY_SERIAL].offset);
4682           break;
4683
4684         default:
4685           _dbus_verbose ("Ignoring an unknown header field: %.4s at offset %d\n",
4686                          field, pos);
4687         }
4688       
4689       pos = new_pos;
4690     }
4691
4692   if (pos < header_len)
4693     {
4694       /* Alignment padding, verify that it's nul */
4695       _dbus_assert ((header_len - pos) < 8);
4696
4697       if (!_dbus_string_validate_nul (data,
4698                                       pos, (header_len - pos)))
4699         {
4700           _dbus_verbose ("header alignment padding is not nul\n");
4701           return FALSE;
4702         }
4703     }
4704
4705   /* Depending on message type, enforce presence of certain fields. */
4706   switch (message_type)
4707     {
4708     case DBUS_MESSAGE_TYPE_SIGNAL:
4709     case DBUS_MESSAGE_TYPE_METHOD_CALL:
4710       if (fields[FIELD_INTERFACE].offset < 0)
4711         {
4712           _dbus_verbose ("No %s field provided\n",
4713                          DBUS_HEADER_FIELD_INTERFACE);
4714           return FALSE;
4715         }
4716       if (fields[FIELD_MEMBER].offset < 0)
4717         {
4718           _dbus_verbose ("No %s field provided\n",
4719                          DBUS_HEADER_FIELD_MEMBER);
4720           return FALSE;
4721         }
4722       break;
4723     case DBUS_MESSAGE_TYPE_ERROR:
4724       if (fields[FIELD_ERROR_NAME].offset < 0)
4725         {
4726           _dbus_verbose ("No %s field provided\n",
4727                          DBUS_HEADER_FIELD_ERROR_NAME);
4728           return FALSE;
4729         }
4730       break;
4731     case DBUS_MESSAGE_TYPE_METHOD_RETURN:
4732       break;
4733     default:
4734       /* An unknown type, spec requires us to ignore it */
4735       break;
4736     }
4737   
4738   if (message_padding)
4739     *message_padding = header_len - pos;  
4740   
4741   return TRUE;
4742 }
4743
4744 /**
4745  * Returns a buffer obtained from _dbus_message_loader_get_buffer(),
4746  * indicating to the loader how many bytes of the buffer were filled
4747  * in. This function must always be called, even if no bytes were
4748  * successfully read.
4749  *
4750  * @param loader the loader.
4751  * @param buffer the buffer.
4752  * @param bytes_read number of bytes that were read into the buffer.
4753  */
4754 void
4755 _dbus_message_loader_return_buffer (DBusMessageLoader  *loader,
4756                                     DBusString         *buffer,
4757                                     int                 bytes_read)
4758 {
4759   _dbus_assert (loader->buffer_outstanding);
4760   _dbus_assert (buffer == &loader->data);
4761
4762   loader->buffer_outstanding = FALSE;
4763 }
4764
4765 /**
4766  * Converts buffered data into messages.
4767  *
4768  * @todo we need to check that the proper named header fields exist
4769  * for each message type.
4770  * 
4771  * @todo If a message has unknown type, we should probably eat it
4772  * right here rather than passing it out to applications.  However
4773  * it's not an error to see messages of unknown type.
4774  * 
4775  * @param loader the loader.
4776  * @returns #TRUE if we had enough memory to finish.
4777  */
4778 dbus_bool_t
4779 _dbus_message_loader_queue_messages (DBusMessageLoader *loader)
4780 {
4781   if (loader->corrupted)
4782     return TRUE;
4783
4784   while (_dbus_string_get_length (&loader->data) >= 16)
4785     {
4786       DBusMessage *message;      
4787       const char *header_data;
4788       int byte_order, message_type, header_len, body_len, header_padding;
4789       dbus_uint32_t header_len_unsigned, body_len_unsigned;
4790       
4791       header_data = _dbus_string_get_const_data_len (&loader->data, 0, 16);
4792
4793       _dbus_assert (_DBUS_ALIGN_ADDRESS (header_data, 4) == header_data);
4794
4795       if (header_data[VERSION_OFFSET] != DBUS_MAJOR_PROTOCOL_VERSION)
4796         {
4797           _dbus_verbose ("Message has protocol version %d ours is %d\n",
4798                          (int) header_data[VERSION_OFFSET], DBUS_MAJOR_PROTOCOL_VERSION);
4799           loader->corrupted = TRUE;
4800           return TRUE;
4801         }
4802       
4803       byte_order = header_data[BYTE_ORDER_OFFSET];
4804
4805       if (byte_order != DBUS_LITTLE_ENDIAN &&
4806           byte_order != DBUS_BIG_ENDIAN)
4807         {
4808           _dbus_verbose ("Message with bad byte order '%c' received\n",
4809                          byte_order);
4810           loader->corrupted = TRUE;
4811           return TRUE;
4812         }
4813
4814       /* Unknown types are ignored, but INVALID is
4815        * disallowed
4816        */
4817       message_type = header_data[TYPE_OFFSET];
4818       if (message_type == DBUS_MESSAGE_TYPE_INVALID)
4819         {
4820           _dbus_verbose ("Message with bad type '%d' received\n",
4821                          message_type);
4822           loader->corrupted = TRUE;
4823           return TRUE;
4824         }      
4825       
4826       header_len_unsigned = _dbus_unpack_uint32 (byte_order, header_data + 4);
4827       body_len_unsigned = _dbus_unpack_uint32 (byte_order, header_data + 8);
4828
4829       if (header_len_unsigned < 16)
4830         {
4831           _dbus_verbose ("Message had broken too-small header length %u\n",
4832                          header_len_unsigned);
4833           loader->corrupted = TRUE;
4834           return TRUE;
4835         }
4836
4837       if (header_len_unsigned > (unsigned) MAX_SANE_MESSAGE_SIZE ||
4838           body_len_unsigned > (unsigned) MAX_SANE_MESSAGE_SIZE)
4839         {
4840           _dbus_verbose ("Header or body length too large (%u %u)\n",
4841                          header_len_unsigned,
4842                          body_len_unsigned);
4843           loader->corrupted = TRUE;
4844           return TRUE;
4845         }
4846
4847       /* Now that we know the values are in signed range, get
4848        * rid of stupid unsigned, just causes bugs
4849        */
4850       header_len = header_len_unsigned;
4851       body_len = body_len_unsigned;
4852
4853       if (_DBUS_ALIGN_VALUE (header_len, 8) != header_len_unsigned)
4854         {
4855           
4856           _dbus_verbose ("header length %d is not aligned to 8 bytes\n",
4857                          header_len);
4858           loader->corrupted = TRUE;
4859           return TRUE;
4860         }
4861       
4862       if (header_len + body_len > loader->max_message_size)
4863         {
4864           _dbus_verbose ("Message claimed length header = %d body = %d exceeds max message length %ld\n",
4865                          header_len, body_len, loader->max_message_size);
4866           loader->corrupted = TRUE;
4867           return TRUE;
4868         }
4869
4870       if (_dbus_string_get_length (&loader->data) >= (header_len + body_len))
4871         {
4872           HeaderField fields[FIELD_LAST];
4873           int i;
4874           int next_arg;          
4875
4876 #if 0
4877           _dbus_verbose_bytes_of_string (&loader->data, 0, header_len + body_len);
4878 #endif    
4879           if (!decode_header_data (&loader->data,
4880                                    header_len, byte_order,
4881                                    message_type,
4882                                    fields, &header_padding))
4883             {
4884               _dbus_verbose ("Header was invalid\n");
4885               loader->corrupted = TRUE;
4886               return TRUE;
4887             }
4888           
4889           next_arg = header_len;
4890           while (next_arg < (header_len + body_len))
4891             {
4892               int type;
4893               int prev = next_arg;
4894
4895               if (!_dbus_marshal_validate_type (&loader->data, next_arg,
4896                                                 &type, &next_arg))
4897                 {
4898                   _dbus_verbose ("invalid typecode at offset %d\n", prev);
4899                   loader->corrupted = TRUE;
4900                   return TRUE;
4901                 }
4902       
4903               if (!_dbus_marshal_validate_arg (&loader->data,
4904                                                byte_order,
4905                                                0,
4906                                                type, -1,
4907                                                next_arg,
4908                                                &next_arg))
4909                 {
4910                   _dbus_verbose ("invalid type data at %d, next_arg\n", next_arg);
4911                   loader->corrupted = TRUE;
4912                   return TRUE;
4913                 }
4914
4915               _dbus_assert (next_arg > prev);
4916             }
4917           
4918           if (next_arg > (header_len + body_len))
4919             {
4920               _dbus_verbose ("end of last arg at %d but message has len %d+%d=%d\n",
4921                              next_arg, header_len, body_len,
4922                              header_len + body_len);
4923               loader->corrupted = TRUE;
4924               return TRUE;
4925             }
4926
4927           message = dbus_message_new_empty_header ();
4928           if (message == NULL)
4929             {
4930               _dbus_verbose ("Failed to allocate empty message\n");
4931               return FALSE;
4932             }
4933
4934           message->byte_order = byte_order;
4935           message->header_padding = header_padding;
4936           
4937           /* Copy in the offsets we found */
4938           i = 0;
4939           while (i < FIELD_LAST)
4940             {
4941               message->header_fields[i] = fields[i];
4942               ++i;
4943             }
4944           
4945           if (!_dbus_list_append (&loader->messages, message))
4946             {
4947               _dbus_verbose ("Failed to append new message to loader queue\n");
4948               dbus_message_unref (message);
4949               return FALSE;
4950             }
4951
4952           _dbus_assert (_dbus_string_get_length (&message->header) == 0);
4953           _dbus_assert (_dbus_string_get_length (&message->body) == 0);
4954
4955           _dbus_assert (_dbus_string_get_length (&loader->data) >=
4956                         (header_len + body_len));
4957           
4958           if (!_dbus_string_move_len (&loader->data, 0, header_len, &message->header, 0))
4959             {
4960               _dbus_verbose ("Failed to move header into new message\n");
4961               _dbus_list_remove_last (&loader->messages, message);
4962               dbus_message_unref (message);
4963               return FALSE;
4964             }
4965           
4966           if (!_dbus_string_move_len (&loader->data, 0, body_len, &message->body, 0))
4967             {
4968               dbus_bool_t result;
4969
4970               _dbus_verbose ("Failed to move body into new message\n");
4971               
4972               /* put the header back, we'll try again later */
4973               result = _dbus_string_copy_len (&message->header, 0, header_len,
4974                                               &loader->data, 0);
4975               _dbus_assert (result); /* because DBusString never reallocs smaller */
4976
4977               _dbus_list_remove_last (&loader->messages, message);
4978               dbus_message_unref (message);
4979               return FALSE;
4980             }
4981
4982           _dbus_assert (_dbus_string_get_length (&message->header) == header_len);
4983           _dbus_assert (_dbus_string_get_length (&message->body) == body_len);
4984
4985           /* Fill in caches (we checked the types of these fields
4986            * earlier)
4987            */
4988           message->reply_serial = get_uint_field (message,
4989                                                   FIELD_REPLY_SERIAL);
4990           message->client_serial = get_uint_field (message,
4991                                                    FIELD_CLIENT_SERIAL);
4992           
4993           _dbus_verbose ("Loaded message %p\n", message);
4994         }
4995       else
4996         return TRUE;
4997     }
4998
4999   return TRUE;
5000 }
5001
5002 /**
5003  * Peeks at first loaded message, returns #NULL if no messages have
5004  * been queued.
5005  *
5006  * @param loader the loader.
5007  * @returns the next message, or #NULL if none.
5008  */
5009 DBusMessage*
5010 _dbus_message_loader_peek_message (DBusMessageLoader *loader)
5011 {
5012   if (loader->messages)
5013     return loader->messages->data;
5014   else
5015     return NULL;
5016 }
5017
5018 /**
5019  * Pops a loaded message (passing ownership of the message
5020  * to the caller). Returns #NULL if no messages have been
5021  * queued.
5022  *
5023  * @param loader the loader.
5024  * @returns the next message, or #NULL if none.
5025  */
5026 DBusMessage*
5027 _dbus_message_loader_pop_message (DBusMessageLoader *loader)
5028 {
5029   return _dbus_list_pop_first (&loader->messages);
5030 }
5031
5032 /**
5033  * Pops a loaded message inside a list link (passing ownership of the
5034  * message and link to the caller). Returns #NULL if no messages have
5035  * been loaded.
5036  *
5037  * @param loader the loader.
5038  * @returns the next message link, or #NULL if none.
5039  */
5040 DBusList*
5041 _dbus_message_loader_pop_message_link (DBusMessageLoader *loader)
5042 {
5043   return _dbus_list_pop_first_link (&loader->messages);
5044 }
5045
5046 /**
5047  * Returns a popped message link, used to undo a pop.
5048  *
5049  * @param loader the loader
5050  * @param link the link with a message in it
5051  */
5052 void
5053 _dbus_message_loader_putback_message_link (DBusMessageLoader  *loader,
5054                                            DBusList           *link)
5055 {
5056   _dbus_list_prepend_link (&loader->messages, link);
5057 }
5058
5059 /**
5060  * Checks whether the loader is confused due to bad data.
5061  * If messages are received that are invalid, the
5062  * loader gets confused and gives up permanently.
5063  * This state is called "corrupted."
5064  *
5065  * @param loader the loader
5066  * @returns #TRUE if the loader is hosed.
5067  */
5068 dbus_bool_t
5069 _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader)
5070 {
5071   return loader->corrupted;
5072 }
5073
5074 /**
5075  * Sets the maximum size message we allow.
5076  *
5077  * @param loader the loader
5078  * @param size the max message size in bytes
5079  */
5080 void
5081 _dbus_message_loader_set_max_message_size (DBusMessageLoader  *loader,
5082                                            long                size)
5083 {
5084   if (size > MAX_SANE_MESSAGE_SIZE)
5085     {
5086       _dbus_verbose ("clamping requested max message size %ld to %d\n",
5087                      size, MAX_SANE_MESSAGE_SIZE);
5088       size = MAX_SANE_MESSAGE_SIZE;
5089     }
5090   loader->max_message_size = size;
5091 }
5092
5093 /**
5094  * Gets the maximum allowed message size in bytes.
5095  *
5096  * @param loader the loader
5097  * @returns max size in bytes
5098  */
5099 long
5100 _dbus_message_loader_get_max_message_size (DBusMessageLoader  *loader)
5101 {
5102   return loader->max_message_size;
5103 }
5104
5105 static DBusDataSlotAllocator slot_allocator;
5106 _DBUS_DEFINE_GLOBAL_LOCK (message_slots);
5107
5108 /**
5109  * Allocates an integer ID to be used for storing application-specific
5110  * data on any DBusMessage. The allocated ID may then be used
5111  * with dbus_message_set_data() and dbus_message_get_data().
5112  * The passed-in slot must be initialized to -1, and is filled in
5113  * with the slot ID. If the passed-in slot is not -1, it's assumed
5114  * to be already allocated, and its refcount is incremented.
5115  * 
5116  * The allocated slot is global, i.e. all DBusMessage objects will
5117  * have a slot with the given integer ID reserved.
5118  *
5119  * @param slot_p address of a global variable storing the slot
5120  * @returns #FALSE on failure (no memory)
5121  */
5122 dbus_bool_t
5123 dbus_message_allocate_data_slot (dbus_int32_t *slot_p)
5124 {
5125   return _dbus_data_slot_allocator_alloc (&slot_allocator,
5126                                           _DBUS_LOCK_NAME (message_slots),
5127                                           slot_p);
5128 }
5129
5130 /**
5131  * Deallocates a global ID for message data slots.
5132  * dbus_message_get_data() and dbus_message_set_data() may no
5133  * longer be used with this slot.  Existing data stored on existing
5134  * DBusMessage objects will be freed when the message is
5135  * finalized, but may not be retrieved (and may only be replaced if
5136  * someone else reallocates the slot).  When the refcount on the
5137  * passed-in slot reaches 0, it is set to -1.
5138  *
5139  * @param slot_p address storing the slot to deallocate
5140  */
5141 void
5142 dbus_message_free_data_slot (dbus_int32_t *slot_p)
5143 {
5144   _dbus_return_if_fail (*slot_p >= 0);
5145   
5146   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
5147 }
5148
5149 /**
5150  * Stores a pointer on a DBusMessage, along
5151  * with an optional function to be used for freeing
5152  * the data when the data is set again, or when
5153  * the message is finalized. The slot number
5154  * must have been allocated with dbus_message_allocate_data_slot().
5155  *
5156  * @param message the message
5157  * @param slot the slot number
5158  * @param data the data to store
5159  * @param free_data_func finalizer function for the data
5160  * @returns #TRUE if there was enough memory to store the data
5161  */
5162 dbus_bool_t
5163 dbus_message_set_data (DBusMessage     *message,
5164                        dbus_int32_t     slot,
5165                        void            *data,
5166                        DBusFreeFunction free_data_func)
5167 {
5168   DBusFreeFunction old_free_func;
5169   void *old_data;
5170   dbus_bool_t retval;
5171
5172   _dbus_return_val_if_fail (message != NULL, FALSE);
5173   _dbus_return_val_if_fail (slot >= 0, FALSE);
5174
5175   retval = _dbus_data_slot_list_set (&slot_allocator,
5176                                      &message->slot_list,
5177                                      slot, data, free_data_func,
5178                                      &old_free_func, &old_data);
5179
5180   if (retval)
5181     {
5182       /* Do the actual free outside the message lock */
5183       if (old_free_func)
5184         (* old_free_func) (old_data);
5185     }
5186
5187   return retval;
5188 }
5189
5190 /**
5191  * Retrieves data previously set with dbus_message_set_data().
5192  * The slot must still be allocated (must not have been freed).
5193  *
5194  * @param message the message
5195  * @param slot the slot to get data from
5196  * @returns the data, or #NULL if not found
5197  */
5198 void*
5199 dbus_message_get_data (DBusMessage   *message,
5200                        dbus_int32_t   slot)
5201 {
5202   void *res;
5203
5204   _dbus_return_val_if_fail (message != NULL, NULL);
5205   
5206   res = _dbus_data_slot_list_get (&slot_allocator,
5207                                   &message->slot_list,
5208                                   slot);
5209
5210   return res;
5211 }
5212
5213 /** @} */
5214 #ifdef DBUS_BUILD_TESTS
5215 #include "dbus-test.h"
5216 #include <stdio.h>
5217
5218 static void
5219 message_iter_test (DBusMessage *message)
5220 {
5221   DBusMessageIter iter, dict, array, array2;
5222   char *str;
5223   unsigned char *data;
5224   dbus_int32_t *our_int_array;
5225   int len;
5226   
5227   dbus_message_iter_init (message, &iter);
5228
5229   /* String tests */
5230   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING)
5231     _dbus_assert_not_reached ("Argument type isn't string");
5232
5233   str = dbus_message_iter_get_string (&iter);
5234   if (strcmp (str, "Test string") != 0)
5235     _dbus_assert_not_reached ("Strings differ");
5236   dbus_free (str);
5237
5238   if (!dbus_message_iter_next (&iter))
5239     _dbus_assert_not_reached ("Reached end of arguments");
5240
5241   /* Signed integer tests */
5242   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INT32)
5243     _dbus_assert_not_reached ("Argument type isn't int32");
5244
5245   if (dbus_message_iter_get_int32 (&iter) != -0x12345678)
5246     _dbus_assert_not_reached ("Signed integers differ");
5247
5248   if (!dbus_message_iter_next (&iter))
5249     _dbus_assert_not_reached ("Reached end of fields");
5250   
5251   /* Unsigned integer tests */
5252   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_UINT32)
5253     _dbus_assert_not_reached ("Argument type isn't int32");
5254
5255   if (dbus_message_iter_get_uint32 (&iter) != 0xedd1e)
5256     _dbus_assert_not_reached ("Unsigned integers differ");
5257
5258   if (!dbus_message_iter_next (&iter))
5259     _dbus_assert_not_reached ("Reached end of arguments");
5260
5261   /* Double tests */
5262   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_DOUBLE)
5263     _dbus_assert_not_reached ("Argument type isn't double");
5264
5265   if (dbus_message_iter_get_double (&iter) != 3.14159)
5266     _dbus_assert_not_reached ("Doubles differ");
5267
5268   if (!dbus_message_iter_next (&iter))
5269     _dbus_assert_not_reached ("Reached end of arguments");
5270
5271   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY)
5272     _dbus_assert_not_reached ("Argument type not an array");
5273
5274   if (dbus_message_iter_get_array_type (&iter) != DBUS_TYPE_DOUBLE)
5275     _dbus_assert_not_reached ("Array type not double");
5276
5277   
5278   if (!dbus_message_iter_init_array_iterator (&iter, &array, NULL))
5279     _dbus_assert_not_reached ("Array init failed");
5280
5281   if (dbus_message_iter_get_arg_type (&array) != DBUS_TYPE_DOUBLE)
5282     _dbus_assert_not_reached ("Argument type isn't double");
5283
5284   if (dbus_message_iter_get_double (&array) != 1.5)
5285     _dbus_assert_not_reached ("Unsigned integers differ");
5286
5287   if (!dbus_message_iter_next (&array))
5288     _dbus_assert_not_reached ("Reached end of arguments");
5289
5290   if (dbus_message_iter_get_arg_type (&array) != DBUS_TYPE_DOUBLE)
5291     _dbus_assert_not_reached ("Argument type isn't double");
5292
5293   if (dbus_message_iter_get_double (&array) != 2.5)
5294     _dbus_assert_not_reached ("Unsigned integers differ");
5295
5296   if (dbus_message_iter_next (&array))
5297     _dbus_assert_not_reached ("Didn't reach end of arguments");
5298   
5299   if (!dbus_message_iter_next (&iter))
5300     _dbus_assert_not_reached ("Reached end of arguments");
5301   
5302
5303   /* dict */
5304
5305   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_DICT)
5306     _dbus_assert_not_reached ("not dict type");
5307      
5308   if (!dbus_message_iter_init_dict_iterator (&iter, &dict))
5309     _dbus_assert_not_reached ("dict iter failed");
5310
5311   str = dbus_message_iter_get_dict_key (&dict);
5312   if (str == NULL || strcmp (str, "test") != 0)
5313     _dbus_assert_not_reached ("wrong dict key");
5314   dbus_free (str);
5315
5316   if (dbus_message_iter_get_arg_type (&dict) != DBUS_TYPE_UINT32)
5317     _dbus_assert_not_reached ("wrong dict entry type");
5318
5319   if (dbus_message_iter_get_uint32 (&dict) != 0xDEADBEEF)
5320     _dbus_assert_not_reached ("wrong dict entry value");
5321
5322   if (!dbus_message_iter_next (&dict))
5323     _dbus_assert_not_reached ("reached end of dict");
5324   
5325   /* array of array of int32 (in dict) */
5326
5327   str = dbus_message_iter_get_dict_key (&dict);
5328   if (str == NULL || strcmp (str, "array") != 0)
5329     _dbus_assert_not_reached ("wrong dict key");
5330   dbus_free (str);
5331   
5332   if (dbus_message_iter_get_arg_type (&dict) != DBUS_TYPE_ARRAY)
5333     _dbus_assert_not_reached ("Argument type not an array");
5334
5335   if (dbus_message_iter_get_array_type (&dict) != DBUS_TYPE_ARRAY)
5336     _dbus_assert_not_reached ("Array type not array");
5337
5338   if (!dbus_message_iter_init_array_iterator (&dict, &array, NULL))
5339     _dbus_assert_not_reached ("Array init failed");
5340
5341   if (dbus_message_iter_get_arg_type (&array) != DBUS_TYPE_ARRAY)
5342     _dbus_assert_not_reached ("Argument type isn't array");
5343   
5344   if (dbus_message_iter_get_array_type (&array) != DBUS_TYPE_INT32)
5345     _dbus_assert_not_reached ("Array type not int32");
5346   
5347   if (!dbus_message_iter_init_array_iterator (&array, &array2, NULL))
5348     _dbus_assert_not_reached ("Array init failed");
5349
5350   if (dbus_message_iter_get_arg_type (&array2) != DBUS_TYPE_INT32)
5351     _dbus_assert_not_reached ("Argument type isn't int32");
5352
5353   if (dbus_message_iter_get_int32 (&array2) != 0x12345678)
5354     _dbus_assert_not_reached ("Signed integers differ");
5355
5356   if (!dbus_message_iter_next (&array2))
5357     _dbus_assert_not_reached ("Reached end of arguments");
5358
5359   if (dbus_message_iter_get_int32 (&array2) != 0x23456781)
5360     _dbus_assert_not_reached ("Signed integers differ");
5361
5362   if (dbus_message_iter_next (&array2))
5363     _dbus_assert_not_reached ("Didn't reached end of arguments");
5364
5365   if (!dbus_message_iter_next (&array))
5366     _dbus_assert_not_reached ("Reached end of arguments");
5367
5368   if (dbus_message_iter_get_array_type (&array) != DBUS_TYPE_INT32)
5369     _dbus_assert_not_reached ("Array type not int32");
5370
5371   if (!dbus_message_iter_get_int32_array (&array,
5372                                           &our_int_array,
5373                                           &len))
5374     _dbus_assert_not_reached ("couldn't get int32 array");
5375
5376   _dbus_assert (len == 3);
5377   _dbus_assert (our_int_array[0] == 0x34567812 &&
5378                 our_int_array[1] == 0x45678123 &&
5379                 our_int_array[2] == 0x56781234);
5380   dbus_free (our_int_array);
5381   
5382   if (dbus_message_iter_next (&array))
5383     _dbus_assert_not_reached ("Didn't reach end of array");
5384
5385   if (dbus_message_iter_next (&dict))
5386     _dbus_assert_not_reached ("Didn't reach end of dict");
5387   
5388   if (!dbus_message_iter_next (&iter))
5389     _dbus_assert_not_reached ("Reached end of arguments");
5390   
5391   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_BYTE)
5392     {
5393       _dbus_warn ("type was: %d\n", dbus_message_iter_get_arg_type (&iter));
5394       _dbus_assert_not_reached ("wrong type after dict (should be byte)");
5395     }
5396   
5397   if (dbus_message_iter_get_byte (&iter) != 0xF0)
5398     _dbus_assert_not_reached ("wrong value after dict");
5399
5400
5401   if (!dbus_message_iter_next (&iter))
5402     _dbus_assert_not_reached ("Reached end of arguments");
5403   
5404   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_NIL)
5405     _dbus_assert_not_reached ("not a nil type");
5406   
5407   if (!dbus_message_iter_next (&iter))
5408     _dbus_assert_not_reached ("Reached end of arguments");
5409   
5410   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_NAMED)
5411     _dbus_assert_not_reached ("wrong type after dict");
5412
5413   if (!dbus_message_iter_get_named (&iter, &str, &data, &len))
5414     _dbus_assert_not_reached ("failed to get named");
5415
5416   _dbus_assert (strcmp (str, "named")==0);
5417   _dbus_assert (len == 5);
5418   _dbus_assert (strcmp (data, "data")==0);
5419   dbus_free (str);
5420   dbus_free (data);
5421   
5422   if (dbus_message_iter_next (&iter))
5423     _dbus_assert_not_reached ("Didn't reach end of arguments");
5424 }
5425
5426
5427 static dbus_bool_t
5428 check_message_handling_type (DBusMessageIter *iter,
5429                              int type)
5430 {
5431   DBusMessageIter child_iter;
5432   
5433   switch (type)
5434     {
5435     case DBUS_TYPE_NIL:
5436       break;
5437     case DBUS_TYPE_BYTE:
5438       dbus_message_iter_get_byte (iter);
5439       break;
5440     case DBUS_TYPE_BOOLEAN:
5441       dbus_message_iter_get_boolean (iter);
5442       break;
5443     case DBUS_TYPE_INT32:
5444       dbus_message_iter_get_int32 (iter);
5445       break;
5446     case DBUS_TYPE_UINT32:
5447       dbus_message_iter_get_uint32 (iter);
5448       break;
5449     case DBUS_TYPE_INT64:
5450 #ifdef DBUS_HAVE_INT64
5451       dbus_message_iter_get_int64 (iter);
5452 #endif
5453       break;
5454     case DBUS_TYPE_UINT64:
5455 #ifdef DBUS_HAVE_INT64
5456       dbus_message_iter_get_uint64 (iter);
5457 #endif
5458       break;
5459     case DBUS_TYPE_DOUBLE:
5460       dbus_message_iter_get_double (iter);
5461       break;
5462     case DBUS_TYPE_STRING:
5463       {
5464         char *str;
5465         str = dbus_message_iter_get_string (iter);
5466         if (str == NULL)
5467           {
5468             _dbus_warn ("NULL string in message\n");
5469             return FALSE;
5470           }
5471         dbus_free (str);
5472       }
5473       break;
5474     case DBUS_TYPE_NAMED:
5475       {
5476         char *name;
5477         unsigned char *data;
5478         int len;
5479         
5480         if (!dbus_message_iter_get_named (iter, &name, &data, &len))
5481           {
5482             _dbus_warn ("error reading name from named type\n");
5483             return FALSE;
5484           }
5485         dbus_free (data);
5486         dbus_free (name);
5487       }
5488       break;
5489     case DBUS_TYPE_ARRAY:
5490       {
5491         int array_type;
5492
5493         if (!dbus_message_iter_init_array_iterator (iter, &child_iter, &array_type))
5494           {
5495             _dbus_warn ("Failed to init array iterator\n");
5496             return FALSE;
5497           }
5498
5499         while (dbus_message_iter_has_next (&child_iter))
5500           {
5501             if (!check_message_handling_type (&child_iter, array_type))
5502               {
5503                 _dbus_warn ("error in array element\n");
5504                 return FALSE;
5505               }
5506             
5507             if (!dbus_message_iter_next (&child_iter))
5508               break;
5509           }
5510       }
5511       break;
5512     case DBUS_TYPE_DICT:
5513       {
5514         int entry_type;
5515         char *key;
5516         
5517         if (!dbus_message_iter_init_dict_iterator (iter, &child_iter))
5518           {
5519             _dbus_warn ("Failed to init dict iterator\n");
5520             return FALSE;
5521           }
5522
5523         while ((entry_type = dbus_message_iter_get_arg_type (&child_iter)) != DBUS_TYPE_INVALID)
5524           {
5525             key = dbus_message_iter_get_dict_key (&child_iter);
5526             if (key == NULL)
5527               {
5528                 _dbus_warn ("error reading dict key\n");
5529                 return FALSE;
5530               }
5531             dbus_free (key);
5532             
5533             if (!check_message_handling_type (&child_iter, entry_type))
5534               {
5535                 _dbus_warn ("error in dict value\n");
5536                 return FALSE;
5537               }
5538             
5539             if (!dbus_message_iter_next (&child_iter))
5540               break;
5541           }
5542       }
5543       break;
5544       
5545     default:
5546       _dbus_warn ("unknown type %d\n", type);
5547       return FALSE;
5548       break;
5549     }
5550   return TRUE;
5551 }
5552   
5553   
5554 static dbus_bool_t
5555 check_message_handling (DBusMessage *message)
5556 {
5557   DBusMessageIter iter;
5558   int type;
5559   dbus_bool_t retval;
5560   dbus_uint32_t client_serial;
5561   
5562   retval = FALSE;
5563   
5564   client_serial = dbus_message_get_serial (message);
5565
5566   /* can't use set_serial due to the assertions at the start of it */
5567   set_uint_field (message, FIELD_CLIENT_SERIAL,
5568                   client_serial);
5569   
5570   if (client_serial != dbus_message_get_serial (message))
5571     {
5572       _dbus_warn ("get/set cycle for client_serial did not succeed\n");
5573       goto failed;
5574     }
5575   
5576   /* If we implement message_set_arg (message, n, value)
5577    * then we would want to test it here
5578    */
5579
5580   dbus_message_iter_init (message, &iter);
5581   while ((type = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID)
5582     {
5583       if (!check_message_handling_type (&iter, type))
5584         goto failed;
5585
5586       if (!dbus_message_iter_next (&iter))
5587         break;
5588     }
5589   
5590   retval = TRUE;
5591   
5592  failed:
5593   return retval;
5594 }
5595
5596 static dbus_bool_t
5597 check_have_valid_message (DBusMessageLoader *loader)
5598 {
5599   DBusMessage *message;
5600   dbus_bool_t retval;
5601
5602   message = NULL;
5603   retval = FALSE;
5604
5605   if (!_dbus_message_loader_queue_messages (loader))
5606     _dbus_assert_not_reached ("no memory to queue messages");
5607   
5608   if (_dbus_message_loader_get_is_corrupted (loader))
5609     {
5610       _dbus_warn ("loader corrupted on message that was expected to be valid\n");
5611       goto failed;
5612     }
5613   
5614   message = _dbus_message_loader_pop_message (loader);
5615   if (message == NULL)
5616     {
5617       _dbus_warn ("didn't load message that was expected to be valid (message not popped)\n");
5618       goto failed;
5619     }
5620   
5621   if (_dbus_string_get_length (&loader->data) > 0)
5622     {
5623       _dbus_warn ("had leftover bytes from expected-to-be-valid single message\n");
5624       goto failed;
5625     }
5626
5627   /* Verify that we're able to properly deal with the message.
5628    * For example, this would detect improper handling of messages
5629    * in nonstandard byte order.
5630    */
5631   if (!check_message_handling (message))
5632     goto failed;  
5633   
5634   retval = TRUE;
5635
5636  failed:
5637   if (message)
5638     dbus_message_unref (message);
5639
5640   return retval;
5641 }
5642
5643 static dbus_bool_t
5644 check_invalid_message (DBusMessageLoader *loader)
5645 {
5646   dbus_bool_t retval;
5647
5648   retval = FALSE;
5649
5650   if (!_dbus_message_loader_queue_messages (loader))
5651     _dbus_assert_not_reached ("no memory to queue messages");
5652   
5653   if (!_dbus_message_loader_get_is_corrupted (loader))
5654     {
5655       _dbus_warn ("loader not corrupted on message that was expected to be invalid\n");
5656       goto failed;
5657     }
5658
5659   retval = TRUE;
5660
5661  failed:
5662   return retval;
5663 }
5664
5665 static dbus_bool_t
5666 check_incomplete_message (DBusMessageLoader *loader)
5667 {
5668   DBusMessage *message;
5669   dbus_bool_t retval;
5670
5671   message = NULL;
5672   retval = FALSE;
5673
5674   if (!_dbus_message_loader_queue_messages (loader))
5675     _dbus_assert_not_reached ("no memory to queue messages");
5676   
5677   if (_dbus_message_loader_get_is_corrupted (loader))
5678     {
5679       _dbus_warn ("loader corrupted on message that was expected to be valid (but incomplete)\n");
5680       goto failed;
5681     }
5682   
5683   message = _dbus_message_loader_pop_message (loader);
5684   if (message != NULL)
5685     {
5686       _dbus_warn ("loaded message that was expected to be incomplete\n");
5687       goto failed;
5688     }
5689
5690   retval = TRUE;
5691
5692  failed:
5693   if (message)
5694     dbus_message_unref (message);
5695   return retval;
5696 }
5697
5698 static dbus_bool_t
5699 check_loader_results (DBusMessageLoader      *loader,
5700                       DBusMessageValidity     validity)
5701 {
5702   if (!_dbus_message_loader_queue_messages (loader))
5703     _dbus_assert_not_reached ("no memory to queue messages");
5704   
5705   switch (validity)
5706     {
5707     case _DBUS_MESSAGE_VALID:
5708       return check_have_valid_message (loader);
5709     case _DBUS_MESSAGE_INVALID:
5710       return check_invalid_message (loader);
5711     case _DBUS_MESSAGE_INCOMPLETE:
5712       return check_incomplete_message (loader);
5713     case _DBUS_MESSAGE_UNKNOWN:
5714       return TRUE;
5715     }
5716
5717   _dbus_assert_not_reached ("bad DBusMessageValidity");
5718   return FALSE;
5719 }
5720
5721
5722 /**
5723  * Loads the message in the given message file.
5724  *
5725  * @param filename filename to load
5726  * @param is_raw if #TRUE load as binary data, if #FALSE as message builder language
5727  * @param data string to load message into
5728  * @returns #TRUE if the message was loaded
5729  */
5730 dbus_bool_t
5731 dbus_internal_do_not_use_load_message_file (const DBusString    *filename,
5732                                             dbus_bool_t          is_raw,
5733                                             DBusString          *data)
5734 {
5735   dbus_bool_t retval;
5736
5737   retval = FALSE;  
5738
5739   if (is_raw)
5740     {
5741       DBusError error;
5742
5743       _dbus_verbose ("Loading raw %s\n", _dbus_string_get_const_data (filename));
5744       dbus_error_init (&error);
5745       if (!_dbus_file_get_contents (data, filename, &error))
5746         {
5747           _dbus_warn ("Could not load message file %s: %s\n",
5748                       _dbus_string_get_const_data (filename),
5749                       error.message);
5750           dbus_error_free (&error);
5751           goto failed;
5752         }
5753     }
5754   else
5755     {
5756       if (!_dbus_message_data_load (data, filename))
5757         {
5758           _dbus_warn ("Could not load message file %s\n",
5759                       _dbus_string_get_const_data (filename));
5760           goto failed;
5761         }
5762     }
5763
5764   retval = TRUE;
5765   
5766  failed:
5767
5768   return retval;
5769 }
5770
5771 /**
5772  * Tries loading the message in the given message file
5773  * and verifies that DBusMessageLoader can handle it.
5774  *
5775  * @param filename filename to load
5776  * @param is_raw if #TRUE load as binary data, if #FALSE as message builder language
5777  * @param expected_validity what the message has to be like to return #TRUE
5778  * @returns #TRUE if the message has the expected validity
5779  */
5780 dbus_bool_t
5781 dbus_internal_do_not_use_try_message_file (const DBusString    *filename,
5782                                            dbus_bool_t          is_raw,
5783                                            DBusMessageValidity  expected_validity)
5784 {
5785   DBusString data;
5786   dbus_bool_t retval;
5787
5788   retval = FALSE;
5789   
5790   if (!_dbus_string_init (&data))
5791     _dbus_assert_not_reached ("could not allocate string\n");
5792
5793   if (!dbus_internal_do_not_use_load_message_file (filename, is_raw,
5794                                                    &data))
5795     goto failed;
5796
5797   retval = dbus_internal_do_not_use_try_message_data (&data, expected_validity);
5798
5799  failed:
5800
5801   if (!retval)
5802     {
5803       if (_dbus_string_get_length (&data) > 0)
5804         _dbus_verbose_bytes_of_string (&data, 0,
5805                                        _dbus_string_get_length (&data));
5806       
5807       _dbus_warn ("Failed message loader test on %s\n",
5808                   _dbus_string_get_const_data (filename));
5809     }
5810   
5811   _dbus_string_free (&data);
5812
5813   return retval;
5814 }
5815
5816 /**
5817  * Tries loading the given message data.
5818  *
5819  *
5820  * @param data the message data
5821  * @param expected_validity what the message has to be like to return #TRUE
5822  * @returns #TRUE if the message has the expected validity
5823  */
5824 dbus_bool_t
5825 dbus_internal_do_not_use_try_message_data (const DBusString    *data,
5826                                            DBusMessageValidity  expected_validity)
5827 {
5828   DBusMessageLoader *loader;
5829   dbus_bool_t retval;
5830   int len;
5831   int i;
5832
5833   loader = NULL;
5834   retval = FALSE;
5835
5836   /* Write the data one byte at a time */
5837   
5838   loader = _dbus_message_loader_new ();
5839
5840   /* check some trivial loader functions */
5841   _dbus_message_loader_ref (loader);
5842   _dbus_message_loader_unref (loader);
5843   _dbus_message_loader_get_max_message_size (loader);
5844   
5845   len = _dbus_string_get_length (data);
5846   for (i = 0; i < len; i++)
5847     {
5848       DBusString *buffer;
5849
5850       _dbus_message_loader_get_buffer (loader, &buffer);
5851       _dbus_string_append_byte (buffer,
5852                                 _dbus_string_get_byte (data, i));
5853       _dbus_message_loader_return_buffer (loader, buffer, 1);
5854     }
5855   
5856   if (!check_loader_results (loader, expected_validity))
5857     goto failed;
5858
5859   _dbus_message_loader_unref (loader);
5860   loader = NULL;
5861
5862   /* Write the data all at once */
5863   
5864   loader = _dbus_message_loader_new ();
5865
5866   {
5867     DBusString *buffer;
5868     
5869     _dbus_message_loader_get_buffer (loader, &buffer);
5870     _dbus_string_copy (data, 0, buffer,
5871                        _dbus_string_get_length (buffer));
5872     _dbus_message_loader_return_buffer (loader, buffer, 1);
5873   }
5874   
5875   if (!check_loader_results (loader, expected_validity))
5876     goto failed;
5877
5878   _dbus_message_loader_unref (loader);
5879   loader = NULL;  
5880
5881   /* Write the data 2 bytes at a time */
5882   
5883   loader = _dbus_message_loader_new ();
5884
5885   len = _dbus_string_get_length (data);
5886   for (i = 0; i < len; i += 2)
5887     {
5888       DBusString *buffer;
5889
5890       _dbus_message_loader_get_buffer (loader, &buffer);
5891       _dbus_string_append_byte (buffer,
5892                                 _dbus_string_get_byte (data, i));
5893       if ((i+1) < len)
5894         _dbus_string_append_byte (buffer,
5895                                   _dbus_string_get_byte (data, i+1));
5896       _dbus_message_loader_return_buffer (loader, buffer, 1);
5897     }
5898   
5899   if (!check_loader_results (loader, expected_validity))
5900     goto failed;
5901
5902   _dbus_message_loader_unref (loader);
5903   loader = NULL;
5904   
5905   retval = TRUE;
5906   
5907  failed:
5908   
5909   if (loader)
5910     _dbus_message_loader_unref (loader);
5911   
5912   return retval;
5913 }
5914
5915 static dbus_bool_t
5916 process_test_subdir (const DBusString          *test_base_dir,
5917                      const char                *subdir,
5918                      DBusMessageValidity        validity,
5919                      DBusForeachMessageFileFunc function,
5920                      void                      *user_data)
5921 {
5922   DBusString test_directory;
5923   DBusString filename;
5924   DBusDirIter *dir;
5925   dbus_bool_t retval;
5926   DBusError error;
5927
5928   retval = FALSE;
5929   dir = NULL;
5930   
5931   if (!_dbus_string_init (&test_directory))
5932     _dbus_assert_not_reached ("didn't allocate test_directory\n");
5933
5934   _dbus_string_init_const (&filename, subdir);
5935   
5936   if (!_dbus_string_copy (test_base_dir, 0,
5937                           &test_directory, 0))
5938     _dbus_assert_not_reached ("couldn't copy test_base_dir to test_directory");
5939   
5940   if (!_dbus_concat_dir_and_file (&test_directory, &filename))    
5941     _dbus_assert_not_reached ("couldn't allocate full path");
5942
5943   _dbus_string_free (&filename);
5944   if (!_dbus_string_init (&filename))
5945     _dbus_assert_not_reached ("didn't allocate filename string\n");
5946
5947   dbus_error_init (&error);
5948   dir = _dbus_directory_open (&test_directory, &error);
5949   if (dir == NULL)
5950     {
5951       _dbus_warn ("Could not open %s: %s\n",
5952                   _dbus_string_get_const_data (&test_directory),
5953                   error.message);
5954       dbus_error_free (&error);
5955       goto failed;
5956     }
5957
5958   printf ("Testing:\n");
5959   
5960  next:
5961   while (_dbus_directory_get_next_file (dir, &filename, &error))
5962     {
5963       DBusString full_path;
5964       dbus_bool_t is_raw;
5965       
5966       if (!_dbus_string_init (&full_path))
5967         _dbus_assert_not_reached ("couldn't init string");
5968
5969       if (!_dbus_string_copy (&test_directory, 0, &full_path, 0))
5970         _dbus_assert_not_reached ("couldn't copy dir to full_path");
5971
5972       if (!_dbus_concat_dir_and_file (&full_path, &filename))
5973         _dbus_assert_not_reached ("couldn't concat file to dir");
5974
5975       if (_dbus_string_ends_with_c_str (&filename, ".message"))
5976         is_raw = FALSE;
5977       else if (_dbus_string_ends_with_c_str (&filename, ".message-raw"))
5978         is_raw = TRUE;
5979       else
5980         {
5981           _dbus_verbose ("Skipping non-.message file %s\n",
5982                          _dbus_string_get_const_data (&filename));
5983           _dbus_string_free (&full_path);
5984           goto next;
5985         }
5986
5987       printf ("    %s\n",
5988               _dbus_string_get_const_data (&filename));
5989       
5990       _dbus_verbose (" expecting %s for %s\n",
5991                      validity == _DBUS_MESSAGE_VALID ? "valid" :
5992                      (validity == _DBUS_MESSAGE_INVALID ? "invalid" :
5993                       (validity == _DBUS_MESSAGE_INCOMPLETE ? "incomplete" : "unknown")),
5994                      _dbus_string_get_const_data (&filename));
5995       
5996       if (! (*function) (&full_path, is_raw, validity, user_data))
5997         {
5998           _dbus_string_free (&full_path);
5999           goto failed;
6000         }
6001       else
6002         _dbus_string_free (&full_path);
6003     }
6004
6005   if (dbus_error_is_set (&error))
6006     {
6007       _dbus_warn ("Could not get next file in %s: %s\n",
6008                   _dbus_string_get_const_data (&test_directory),
6009                   error.message);
6010       dbus_error_free (&error);
6011       goto failed;
6012     }
6013     
6014   retval = TRUE;
6015   
6016  failed:
6017
6018   if (dir)
6019     _dbus_directory_close (dir);
6020   _dbus_string_free (&test_directory);
6021   _dbus_string_free (&filename);
6022
6023   return retval;
6024 }
6025                      
6026 /**
6027  * Runs the given function on every message file in the test suite.
6028  * The function should return #FALSE on test failure or fatal error.
6029  *
6030  * @param test_data_dir root dir of the test suite data files (top_srcdir/test/data)
6031  * @param func the function to run
6032  * @param user_data data for function
6033  * @returns #FALSE if there's a failure
6034  */
6035 dbus_bool_t
6036 dbus_internal_do_not_use_foreach_message_file (const char                *test_data_dir,
6037                                                DBusForeachMessageFileFunc func,
6038                                                void                      *user_data)
6039 {
6040   DBusString test_directory;
6041   dbus_bool_t retval;
6042
6043   retval = FALSE;
6044   
6045   _dbus_string_init_const (&test_directory, test_data_dir);
6046
6047   if (!process_test_subdir (&test_directory, "valid-messages",
6048                             _DBUS_MESSAGE_VALID, func, user_data))
6049     goto failed;
6050
6051   if (!process_test_subdir (&test_directory, "invalid-messages",
6052                             _DBUS_MESSAGE_INVALID, func, user_data))
6053     goto failed;
6054   
6055   if (!process_test_subdir (&test_directory, "incomplete-messages",
6056                             _DBUS_MESSAGE_INCOMPLETE, func, user_data))
6057     goto failed;
6058
6059   retval = TRUE;
6060   
6061  failed:
6062
6063   _dbus_string_free (&test_directory);
6064   
6065   return retval;
6066 }
6067
6068 static void
6069 verify_test_message (DBusMessage *message)
6070 {
6071   DBusMessageIter iter, dict;
6072   DBusError error;
6073   dbus_int32_t our_int;
6074   char *our_str;
6075   double our_double;
6076   dbus_bool_t our_bool;
6077   dbus_uint32_t our_uint32;
6078   dbus_int32_t *our_uint32_array;
6079   int our_uint32_array_len;
6080   dbus_int32_t *our_int32_array;
6081   int our_int32_array_len;
6082   char **our_string_array;
6083   int our_string_array_len;
6084 #ifdef DBUS_HAVE_INT64
6085   dbus_int64_t our_int64;
6086   dbus_uint64_t our_uint64;
6087   dbus_int64_t *our_uint64_array;
6088   int our_uint64_array_len;
6089   dbus_int64_t *our_int64_array;
6090   int our_int64_array_len;
6091 #endif
6092   double *our_double_array;
6093   int our_double_array_len;
6094   unsigned char *our_byte_array;
6095   int our_byte_array_len;
6096   unsigned char *our_boolean_array;
6097   int our_boolean_array_len;
6098   
6099   dbus_message_iter_init (message, &iter);
6100
6101   dbus_error_init (&error);
6102   if (!dbus_message_iter_get_args (&iter, &error,
6103                                    DBUS_TYPE_INT32, &our_int,
6104 #ifdef DBUS_HAVE_INT64
6105                                    DBUS_TYPE_INT64, &our_int64,
6106                                    DBUS_TYPE_UINT64, &our_uint64,
6107 #endif
6108                                    DBUS_TYPE_STRING, &our_str,
6109                                    DBUS_TYPE_DOUBLE, &our_double,
6110                                    DBUS_TYPE_BOOLEAN, &our_bool,
6111                                    DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32,
6112                                    &our_uint32_array, &our_uint32_array_len,
6113                                    DBUS_TYPE_ARRAY, DBUS_TYPE_INT32,
6114                                    &our_int32_array, &our_int32_array_len,
6115 #ifdef DBUS_HAVE_INT64
6116                                    DBUS_TYPE_ARRAY, DBUS_TYPE_UINT64,
6117                                    &our_uint64_array, &our_uint64_array_len,
6118                                    DBUS_TYPE_ARRAY, DBUS_TYPE_INT64,
6119                                    &our_int64_array, &our_int64_array_len,
6120 #endif
6121                                    DBUS_TYPE_ARRAY, DBUS_TYPE_STRING,
6122                                    &our_string_array, &our_string_array_len,
6123                                    DBUS_TYPE_ARRAY, DBUS_TYPE_DOUBLE,
6124                                    &our_double_array, &our_double_array_len,
6125                                    DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
6126                                    &our_byte_array, &our_byte_array_len,
6127                                    DBUS_TYPE_ARRAY, DBUS_TYPE_BOOLEAN,
6128                                    &our_boolean_array, &our_boolean_array_len,
6129                                    0))
6130     {
6131       _dbus_warn ("error: %s - %s\n", error.name,
6132                   (error.message != NULL) ? error.message : "no message");
6133       _dbus_assert_not_reached ("Could not get arguments");
6134     }
6135
6136   if (our_int != -0x12345678)
6137     _dbus_assert_not_reached ("integers differ!");
6138
6139 #ifdef DBUS_HAVE_INT64
6140   if (our_int64 != -0x123456789abcd)
6141     _dbus_assert_not_reached ("64-bit integers differ!");
6142   if (our_uint64 != 0x123456789abcd)
6143     _dbus_assert_not_reached ("64-bit unsigned integers differ!");
6144 #endif
6145   
6146   if (our_double != 3.14159)
6147     _dbus_assert_not_reached ("doubles differ!");
6148
6149   if (strcmp (our_str, "Test string") != 0)
6150     _dbus_assert_not_reached ("strings differ!");
6151   dbus_free (our_str);
6152
6153   if (!our_bool)
6154     _dbus_assert_not_reached ("booleans differ");
6155
6156   if (our_uint32_array_len != 4 ||
6157       our_uint32_array[0] != 0x12345678 ||
6158       our_uint32_array[1] != 0x23456781 ||
6159       our_uint32_array[2] != 0x34567812 ||
6160       our_uint32_array[3] != 0x45678123)
6161     _dbus_assert_not_reached ("uint array differs");
6162   dbus_free (our_uint32_array);
6163
6164   if (our_int32_array_len != 4 ||
6165       our_int32_array[0] != 0x12345678 ||
6166       our_int32_array[1] != -0x23456781 ||
6167       our_int32_array[2] != 0x34567812 ||
6168       our_int32_array[3] != -0x45678123)
6169     _dbus_assert_not_reached ("int array differs");
6170   dbus_free (our_int32_array);
6171
6172 #ifdef DBUS_HAVE_INT64
6173   if (our_uint64_array_len != 4 ||
6174       our_uint64_array[0] != 0x12345678 ||
6175       our_uint64_array[1] != 0x23456781 ||
6176       our_uint64_array[2] != 0x34567812 ||
6177       our_uint64_array[3] != 0x45678123)
6178     _dbus_assert_not_reached ("uint64 array differs");
6179   dbus_free (our_uint64_array);
6180   
6181   if (our_int64_array_len != 4 ||
6182       our_int64_array[0] != 0x12345678 ||
6183       our_int64_array[1] != -0x23456781 ||
6184       our_int64_array[2] != 0x34567812 ||
6185       our_int64_array[3] != -0x45678123)
6186     _dbus_assert_not_reached ("int64 array differs");
6187   dbus_free (our_int64_array);
6188 #endif /* DBUS_HAVE_INT64 */
6189   
6190   if (our_string_array_len != 4)
6191     _dbus_assert_not_reached ("string array has wrong length");
6192
6193   if (strcmp (our_string_array[0], "Foo") != 0 ||
6194       strcmp (our_string_array[1], "bar") != 0 ||
6195       strcmp (our_string_array[2], "") != 0 ||
6196       strcmp (our_string_array[3], "woo woo woo woo") != 0)
6197     _dbus_assert_not_reached ("string array differs");
6198
6199   dbus_free_string_array (our_string_array);
6200
6201   if (our_double_array_len != 3)
6202     _dbus_assert_not_reached ("double array had wrong length");
6203
6204   /* On all IEEE machines (i.e. everything sane) exact equality
6205    * should be preserved over the wire
6206    */
6207   if (our_double_array[0] != 0.1234 ||
6208       our_double_array[1] != 9876.54321 ||
6209       our_double_array[2] != -300.0)
6210     _dbus_assert_not_reached ("double array had wrong values");
6211
6212   dbus_free (our_double_array);
6213
6214   if (our_byte_array_len != 4)
6215     _dbus_assert_not_reached ("byte array had wrong length");
6216
6217   if (our_byte_array[0] != 'a' ||
6218       our_byte_array[1] != 'b' ||
6219       our_byte_array[2] != 'c' ||
6220       our_byte_array[3] != 234)
6221     _dbus_assert_not_reached ("byte array had wrong values");
6222
6223   dbus_free (our_byte_array);
6224
6225   if (our_boolean_array_len != 5)
6226     _dbus_assert_not_reached ("bool array had wrong length");
6227
6228   if (our_boolean_array[0] != TRUE ||
6229       our_boolean_array[1] != FALSE ||
6230       our_boolean_array[2] != TRUE ||
6231       our_boolean_array[3] != TRUE ||
6232       our_boolean_array[4] != FALSE)
6233     _dbus_assert_not_reached ("bool array had wrong values");
6234
6235   dbus_free (our_boolean_array);
6236   
6237   if (!dbus_message_iter_next (&iter))
6238     _dbus_assert_not_reached ("Reached end of arguments");
6239
6240   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_DICT)
6241     _dbus_assert_not_reached ("not dict type");
6242      
6243   if (!dbus_message_iter_init_dict_iterator (&iter, &dict))
6244     _dbus_assert_not_reached ("dict iter failed");
6245
6246   our_str = dbus_message_iter_get_dict_key (&dict);
6247   if (our_str == NULL || strcmp (our_str, "test") != 0)
6248     _dbus_assert_not_reached ("wrong dict key");
6249   dbus_free (our_str);
6250
6251   if (dbus_message_iter_get_arg_type (&dict) != DBUS_TYPE_UINT32)
6252     {
6253       _dbus_verbose ("dict entry type: %d\n", dbus_message_iter_get_arg_type (&dict));
6254       _dbus_assert_not_reached ("wrong dict entry type");
6255     }
6256
6257   if ((our_uint32 = dbus_message_iter_get_uint32 (&dict)) != 0xDEADBEEF)
6258     {
6259       _dbus_verbose ("dict entry val: %x\n", our_uint32);
6260       _dbus_assert_not_reached ("wrong dict entry value");
6261     }
6262
6263   if (dbus_message_iter_next (&dict))
6264     _dbus_assert_not_reached ("Didn't reach end of dict");
6265   
6266   if (!dbus_message_iter_next (&iter))
6267     _dbus_assert_not_reached ("Reached end of arguments");
6268   
6269   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_UINT32)
6270     _dbus_assert_not_reached ("wrong type after dict");
6271   
6272   if (dbus_message_iter_get_uint32 (&iter) != 0xCAFEBABE)
6273     _dbus_assert_not_reached ("wrong value after dict");
6274
6275   if (dbus_message_iter_next (&iter))
6276     _dbus_assert_not_reached ("Didn't reach end of arguments");
6277 }
6278
6279 /**
6280  * @ingroup DBusMessageInternals
6281  * Unit test for DBusMessage.
6282  *
6283  * @returns #TRUE on success.
6284  */
6285 dbus_bool_t
6286 _dbus_message_test (const char *test_data_dir)
6287 {
6288   DBusMessage *message;
6289   DBusMessageLoader *loader;
6290   DBusMessageIter iter, child_iter, child_iter2, child_iter3;
6291   int i;
6292   const char *data;
6293   DBusMessage *copy;
6294   const char *name1;
6295   const char *name2;
6296   const dbus_uint32_t our_uint32_array[] =
6297     { 0x12345678, 0x23456781, 0x34567812, 0x45678123 };
6298   const dbus_uint32_t our_int32_array[] =
6299     { 0x12345678, -0x23456781, 0x34567812, -0x45678123 };
6300 #ifdef DBUS_HAVE_INT64
6301   const dbus_uint64_t our_uint64_array[] =
6302     { 0x12345678, 0x23456781, 0x34567812, 0x45678123 };
6303   const dbus_uint64_t our_int64_array[] =
6304     { 0x12345678, -0x23456781, 0x34567812, -0x45678123 };
6305 #endif
6306   const char *our_string_array[] = { "Foo", "bar", "", "woo woo woo woo" };
6307   const double our_double_array[] = { 0.1234, 9876.54321, -300.0 };
6308   const unsigned char our_byte_array[] = { 'a', 'b', 'c', 234 };
6309   const unsigned char our_boolean_array[] = { TRUE, FALSE, TRUE, TRUE, FALSE };
6310   
6311   _dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
6312
6313   message = dbus_message_new_method_call ("Foo.TestInterface",
6314                                           "TestMethod",
6315                                           "org.freedesktop.DBus.TestService");
6316   _dbus_assert (dbus_message_has_destination (message, "org.freedesktop.DBus.TestService"));
6317   _dbus_assert (dbus_message_is_method_call (message, "Foo.TestInterface",
6318                                              "TestMethod"));
6319   _dbus_message_set_serial (message, 1234);
6320   dbus_message_set_sender (message, "org.foo.bar");
6321   _dbus_assert (dbus_message_has_sender (message, "org.foo.bar"));
6322   dbus_message_set_sender (message, NULL);
6323   _dbus_assert (!dbus_message_has_sender (message, "org.foo.bar"));
6324   _dbus_assert (dbus_message_get_serial (message) == 1234);
6325   _dbus_assert (dbus_message_has_destination (message, "org.freedesktop.DBus.TestService"));
6326
6327   _dbus_assert (dbus_message_get_no_reply (message) == FALSE);
6328   dbus_message_set_no_reply (message, TRUE);
6329   _dbus_assert (dbus_message_get_no_reply (message) == TRUE);
6330   dbus_message_set_no_reply (message, FALSE);
6331   _dbus_assert (dbus_message_get_no_reply (message) == FALSE);
6332   
6333   dbus_message_unref (message);
6334   
6335   /* Test the vararg functions */
6336   message = dbus_message_new_method_call ("Foo.TestInterface",
6337                                           "TestMethod",
6338                                           "org.freedesktop.DBus.TestService");
6339   _dbus_message_set_serial (message, 1);
6340   dbus_message_append_args (message,
6341                             DBUS_TYPE_INT32, -0x12345678,
6342 #ifdef DBUS_HAVE_INT64
6343                             DBUS_TYPE_INT64, -0x123456789abcd,
6344                             DBUS_TYPE_UINT64, 0x123456789abcd,
6345 #endif
6346                             DBUS_TYPE_STRING, "Test string",
6347                             DBUS_TYPE_DOUBLE, 3.14159,
6348                             DBUS_TYPE_BOOLEAN, TRUE,
6349                             DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, our_uint32_array,
6350                             _DBUS_N_ELEMENTS (our_uint32_array),
6351                             DBUS_TYPE_ARRAY, DBUS_TYPE_INT32, our_int32_array,
6352                             _DBUS_N_ELEMENTS (our_int32_array),
6353 #ifdef DBUS_HAVE_INT64
6354                             DBUS_TYPE_ARRAY, DBUS_TYPE_UINT64, our_uint64_array,
6355                             _DBUS_N_ELEMENTS (our_uint64_array),
6356                             DBUS_TYPE_ARRAY, DBUS_TYPE_INT64, our_int64_array,
6357                             _DBUS_N_ELEMENTS (our_int64_array),
6358 #endif
6359                             DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, our_string_array,
6360                             _DBUS_N_ELEMENTS (our_string_array),
6361                             DBUS_TYPE_ARRAY, DBUS_TYPE_DOUBLE, our_double_array,
6362                             _DBUS_N_ELEMENTS (our_double_array),
6363                             DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, our_byte_array,
6364                             _DBUS_N_ELEMENTS (our_byte_array),
6365                             DBUS_TYPE_ARRAY, DBUS_TYPE_BOOLEAN, our_boolean_array,
6366                             _DBUS_N_ELEMENTS (our_boolean_array),
6367                             0);
6368   
6369   dbus_message_append_iter_init (message, &iter);
6370   dbus_message_iter_append_dict (&iter, &child_iter);
6371   dbus_message_iter_append_dict_key (&child_iter, "test");
6372   dbus_message_iter_append_uint32 (&child_iter, 0xDEADBEEF);
6373   dbus_message_iter_append_uint32 (&iter, 0xCAFEBABE);
6374   
6375   _dbus_verbose_bytes_of_string (&message->header, 0,
6376                                  _dbus_string_get_length (&message->header));
6377   _dbus_verbose_bytes_of_string (&message->body, 0,
6378                                  _dbus_string_get_length (&message->body));
6379
6380   verify_test_message (message);
6381
6382   copy = dbus_message_copy (message);
6383   
6384   _dbus_assert (message->client_serial == copy->client_serial);
6385   _dbus_assert (message->reply_serial == copy->reply_serial);
6386   _dbus_assert (message->header_padding == copy->header_padding);
6387   
6388   _dbus_assert (_dbus_string_get_length (&message->header) ==
6389                 _dbus_string_get_length (&copy->header));
6390
6391   _dbus_assert (_dbus_string_get_length (&message->body) ==
6392                 _dbus_string_get_length (&copy->body));
6393
6394   verify_test_message (copy);
6395
6396   name1 = dbus_message_get_interface (message);
6397   name2 = dbus_message_get_interface (copy);
6398
6399   _dbus_assert (strcmp (name1, name2) == 0);
6400
6401   name1 = dbus_message_get_member (message);
6402   name2 = dbus_message_get_member (copy);
6403
6404   _dbus_assert (strcmp (name1, name2) == 0);
6405   
6406   dbus_message_unref (message);
6407   dbus_message_unref (copy);
6408
6409   message = dbus_message_new_method_call ("Foo.TestInterface",
6410                                           "TestMethod",
6411                                           "org.freedesktop.DBus.TestService");
6412   _dbus_message_set_serial (message, 1);
6413   dbus_message_set_reply_serial (message, 0x12345678);
6414
6415   dbus_message_append_iter_init (message, &iter);
6416   dbus_message_iter_append_string (&iter, "Test string");
6417   dbus_message_iter_append_int32 (&iter, -0x12345678);
6418   dbus_message_iter_append_uint32 (&iter, 0xedd1e);
6419   dbus_message_iter_append_double (&iter, 3.14159);
6420
6421   dbus_message_iter_append_array (&iter, &child_iter, DBUS_TYPE_DOUBLE);
6422   dbus_message_iter_append_double (&child_iter, 1.5);
6423   dbus_message_iter_append_double (&child_iter, 2.5);
6424
6425   /* dict */
6426   dbus_message_iter_append_dict (&iter, &child_iter);
6427   dbus_message_iter_append_dict_key (&child_iter, "test");
6428   dbus_message_iter_append_uint32 (&child_iter, 0xDEADBEEF);
6429
6430   /* array of array of int32  (in dict) */
6431   dbus_message_iter_append_dict_key (&child_iter, "array");
6432   dbus_message_iter_append_array (&child_iter, &child_iter2, DBUS_TYPE_ARRAY);
6433   dbus_message_iter_append_array (&child_iter2, &child_iter3, DBUS_TYPE_INT32);
6434   dbus_message_iter_append_int32 (&child_iter3, 0x12345678);
6435   dbus_message_iter_append_int32 (&child_iter3, 0x23456781);
6436   _dbus_warn ("next call expected to fail with wrong array type\n");
6437   _dbus_assert (!dbus_message_iter_append_array (&child_iter2, &child_iter3, DBUS_TYPE_UINT32));
6438   dbus_message_iter_append_array (&child_iter2, &child_iter3, DBUS_TYPE_INT32);
6439   dbus_message_iter_append_int32 (&child_iter3, 0x34567812);
6440   dbus_message_iter_append_int32 (&child_iter3, 0x45678123);
6441   dbus_message_iter_append_int32 (&child_iter3, 0x56781234);
6442   
6443   dbus_message_iter_append_byte (&iter, 0xF0);
6444
6445   dbus_message_iter_append_nil (&iter);
6446
6447   dbus_message_iter_append_named (&iter, "named",
6448                                   "data", 5);
6449   
6450   message_iter_test (message);
6451
6452   /* Message loader test */
6453   _dbus_message_lock (message);
6454   loader = _dbus_message_loader_new ();
6455
6456   /* check ref/unref */
6457   _dbus_message_loader_ref (loader);
6458   _dbus_message_loader_unref (loader);
6459   
6460   /* Write the header data one byte at a time */
6461   data = _dbus_string_get_const_data (&message->header);
6462   for (i = 0; i < _dbus_string_get_length (&message->header); i++)
6463     {
6464       DBusString *buffer;
6465
6466       _dbus_message_loader_get_buffer (loader, &buffer);
6467       _dbus_string_append_byte (buffer, data[i]);
6468       _dbus_message_loader_return_buffer (loader, buffer, 1);
6469     }
6470
6471   /* Write the body data one byte at a time */
6472   data = _dbus_string_get_const_data (&message->body);
6473   for (i = 0; i < _dbus_string_get_length (&message->body); i++)
6474     {
6475       DBusString *buffer;
6476
6477       _dbus_message_loader_get_buffer (loader, &buffer);
6478       _dbus_string_append_byte (buffer, data[i]);
6479       _dbus_message_loader_return_buffer (loader, buffer, 1);
6480     }
6481
6482   dbus_message_unref (message);
6483
6484   /* Now pop back the message */
6485   if (!_dbus_message_loader_queue_messages (loader))
6486     _dbus_assert_not_reached ("no memory to queue messages");
6487   
6488   if (_dbus_message_loader_get_is_corrupted (loader))
6489     _dbus_assert_not_reached ("message loader corrupted");
6490   
6491   message = _dbus_message_loader_pop_message (loader);
6492   if (!message)
6493     _dbus_assert_not_reached ("received a NULL message");
6494
6495   if (dbus_message_get_reply_serial (message) != 0x12345678)
6496     _dbus_assert_not_reached ("reply serial fields differ");
6497   
6498   message_iter_test (message);
6499   
6500   dbus_message_unref (message);
6501   _dbus_message_loader_unref (loader);
6502
6503   /* Now load every message in test_data_dir if we have one */
6504   if (test_data_dir == NULL)
6505     return TRUE;
6506
6507   return dbus_internal_do_not_use_foreach_message_file (test_data_dir,
6508                                                         (DBusForeachMessageFileFunc)
6509                                                         dbus_internal_do_not_use_try_message_file,
6510                                                         NULL);
6511 }
6512
6513 #endif /* DBUS_BUILD_TESTS */