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