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