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