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