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