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