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