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