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