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