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             if (!dbus_message_iter_get_named (iter, name, data, len))
1441               {
1442                 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1443                 goto out;
1444               }
1445           }
1446           break;
1447         case DBUS_TYPE_ARRAY:
1448           {
1449             void **data;
1450             int *len, type;
1451  
1452             type = va_arg (var_args, int);
1453             data = va_arg (var_args, void *);
1454             len = va_arg (var_args, int *);
1455
1456             if (dbus_message_iter_get_array_type (iter) != type)
1457               {
1458                 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
1459                                 "Argument %d is specified to be of type \"array of %s\", but "
1460                                 "is actually of type \"array of %s\"\n", i,
1461                                 _dbus_type_to_string (type),
1462                                 _dbus_type_to_string (dbus_message_iter_get_array_type (iter)));
1463                 goto out;
1464               }
1465             
1466             switch (type)
1467               {
1468               case DBUS_TYPE_BYTE:
1469                 if (!dbus_message_iter_get_byte_array (iter, (unsigned char **)data, len))
1470                   {
1471                     dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1472                     goto out;
1473                   }
1474                 break;
1475               case DBUS_TYPE_BOOLEAN:
1476                 if (!dbus_message_iter_get_boolean_array (iter, (unsigned char **)data, len))
1477                   {
1478                     dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1479                     goto out;
1480                   }
1481                 break;
1482               case DBUS_TYPE_INT32:
1483                 if (!dbus_message_iter_get_int32_array (iter, (dbus_int32_t **)data, len))
1484                   {
1485                     dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1486                     goto out;
1487                   }
1488                 break;
1489               case DBUS_TYPE_UINT32:
1490                 if (!dbus_message_iter_get_uint32_array (iter, (dbus_uint32_t **)data, len))
1491                   {
1492                     dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1493                     goto out;
1494                   }
1495                 break;
1496               case DBUS_TYPE_DOUBLE:
1497                 if (!dbus_message_iter_get_double_array (iter, (double **)data, len))
1498                   {
1499                     dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1500                     goto out;
1501                   }
1502                 break;
1503               case DBUS_TYPE_STRING:
1504                 if (!dbus_message_iter_get_string_array (iter, (char ***)data, len))
1505                   {
1506                     dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1507                     goto out;
1508                   }
1509                 break;
1510               case DBUS_TYPE_NIL:
1511               case DBUS_TYPE_ARRAY:
1512               case DBUS_TYPE_NAMED:
1513               case DBUS_TYPE_DICT:
1514                 _dbus_warn ("dbus_message_get_args_valist doesn't support recursive arrays\n");
1515                 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
1516                 goto out;
1517               default:
1518                 _dbus_warn ("Unknown field type %d\n", type);
1519                 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
1520                 goto out;
1521               }
1522           }
1523           break;
1524         case DBUS_TYPE_DICT:
1525           _dbus_warn ("dbus_message_get_args_valist doesn't support dicts\n");
1526           dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
1527           goto out;
1528         default:          
1529           dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
1530           _dbus_warn ("Unknown field type %d\n", spec_type);
1531           goto out;
1532         }
1533       
1534       spec_type = va_arg (var_args, int);
1535       if (spec_type != 0 && !dbus_message_iter_next (iter))
1536         {
1537           dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
1538                           "Message has only %d arguments, but more were expected", i);
1539           goto out;
1540         }
1541
1542       i++;
1543     }
1544   
1545   retval = TRUE;
1546   
1547  out:
1548   
1549   return retval;
1550 }
1551
1552
1553 /**
1554  * Initializes a DBusMessageIter representing the arguments of the
1555  * message passed in.
1556  *
1557  * @param message the message
1558  * @param _iter pointer to an iterator to initialize
1559  */
1560 void
1561 dbus_message_iter_init (DBusMessage *message,
1562                         DBusMessageIter *iter)
1563 {
1564   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
1565
1566   _dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
1567   
1568   real->message = message;
1569   real->parent_iter = NULL;
1570   real->changed_stamp = message->changed_stamp;
1571   
1572   real->type = DBUS_MESSAGE_ITER_TYPE_MESSAGE;
1573   real->pos = 0;
1574   real->end = _dbus_string_get_length (&message->body);
1575   
1576   real->container_start = 0;
1577   real->container_length_pos = 0;
1578   real->wrote_dict_key = 0;
1579   real->array_type_pos = 0;
1580 }
1581
1582 static void
1583 dbus_message_iter_check (DBusMessageRealIter *iter)
1584 {
1585   if (iter->changed_stamp != iter->message->changed_stamp) 
1586     _dbus_warn ("dbus iterator check failed: invalid iterator\n");
1587   if (iter->pos < 0 || iter->pos > iter->end)
1588     _dbus_warn ("dbus iterator check failed: invalid position\n");
1589 }
1590
1591 static int
1592 skip_array_type (DBusMessageRealIter *iter, int pos)
1593 {
1594   const char *data;
1595
1596   do
1597     {
1598       data = _dbus_string_get_const_data_len (&iter->message->body,
1599                                               pos++, 1);
1600     }
1601   while (*data == DBUS_TYPE_ARRAY);
1602   
1603   return pos;
1604 }
1605
1606 static int
1607 dbus_message_iter_get_data_start (DBusMessageRealIter *iter, int *type)
1608 {
1609   const char *data;
1610   int pos, len;
1611   
1612   switch (iter->type)
1613     {
1614     case DBUS_MESSAGE_ITER_TYPE_MESSAGE:
1615       data = _dbus_string_get_const_data_len (&iter->message->body,
1616                                               iter->pos, 1);
1617       if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_LAST)
1618         *type = *data;
1619       else
1620         *type = DBUS_TYPE_INVALID;
1621       
1622       return skip_array_type (iter, iter->pos);
1623       
1624     case DBUS_MESSAGE_ITER_TYPE_ARRAY:
1625       data = _dbus_string_get_const_data_len (&iter->message->body,
1626                                               iter->array_type_pos, 1);
1627       if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_LAST)
1628         *type = *data;
1629       else
1630         *type = DBUS_TYPE_INVALID;
1631       
1632       return iter->pos;
1633       
1634     case DBUS_MESSAGE_ITER_TYPE_DICT:
1635       /* Get the length of the string */
1636       len = _dbus_demarshal_uint32 (&iter->message->body,
1637                                     iter->message->byte_order,
1638                                     iter->pos, &pos);
1639       pos = pos + len + 1;
1640
1641       data = _dbus_string_get_const_data_len (&iter->message->body,
1642                                               pos, 1);
1643       if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_LAST)
1644         *type = *data;
1645       else
1646         *type = DBUS_TYPE_INVALID;
1647
1648       return skip_array_type (iter, pos);
1649       
1650     default:
1651       _dbus_assert_not_reached ("Invalid iter type");
1652       break;
1653     }
1654   *type = DBUS_TYPE_INVALID;
1655   return iter->pos;
1656 }
1657
1658
1659 /**
1660  * Checks if an iterator has any more fields.
1661  *
1662  * @param iter the message iter
1663  * @returns #TRUE if there are more fields
1664  * following
1665  */
1666 dbus_bool_t
1667 dbus_message_iter_has_next (DBusMessageIter *iter)
1668 {
1669   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
1670   int end_pos;
1671   int type, pos;
1672
1673   dbus_message_iter_check (real);
1674
1675   if (real->pos >= real->end)
1676     return FALSE;
1677   
1678   pos = dbus_message_iter_get_data_start (real, &type);
1679   
1680   if (!_dbus_marshal_get_arg_end_pos (&real->message->body,
1681                                       real->message->byte_order,
1682                                       type, pos, &end_pos))
1683     return FALSE;
1684   
1685   if (end_pos >= real->end)
1686     return FALSE;
1687
1688   return TRUE;  
1689 }
1690
1691 /**
1692  * Moves the iterator to the next field.
1693  *
1694  * @param _iter The message iter
1695  * @returns #TRUE if the iterator was moved to the next field
1696  */
1697 dbus_bool_t
1698 dbus_message_iter_next (DBusMessageIter *iter)
1699 {
1700   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
1701   int end_pos;
1702   int type, pos;
1703
1704   dbus_message_iter_check (real);
1705
1706   pos = dbus_message_iter_get_data_start (real, &type);
1707   
1708   if (!_dbus_marshal_get_arg_end_pos (&real->message->body,
1709                                       real->message->byte_order,
1710                                       type, pos, &end_pos))
1711     return FALSE;
1712
1713   if (end_pos >= real->end)
1714     return FALSE;
1715
1716   real->pos = end_pos;
1717
1718   return TRUE;
1719 }
1720
1721 /**
1722  * Returns the argument type of the argument that the
1723  * message iterator points at.
1724  *
1725  * @param iter the message iter
1726  * @returns the field type
1727  */
1728 int
1729 dbus_message_iter_get_arg_type (DBusMessageIter *iter)
1730 {
1731   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
1732   int type, pos;
1733
1734   dbus_message_iter_check (real);
1735
1736   if (real->pos >= real->end)
1737     return DBUS_TYPE_INVALID;
1738
1739   pos = dbus_message_iter_get_data_start (real, &type);
1740   
1741   return type;
1742 }
1743
1744 static int
1745 iter_get_array_type (DBusMessageRealIter *iter, int *array_type_pos)
1746 {
1747   const char *data;
1748   int _array_type_pos;
1749   int len, pos;
1750   
1751   switch (iter->type)
1752     {
1753     case DBUS_MESSAGE_ITER_TYPE_MESSAGE:
1754       _array_type_pos = iter->pos + 1;
1755       break;
1756     case DBUS_MESSAGE_ITER_TYPE_ARRAY:
1757       _array_type_pos = iter->array_type_pos + 1;
1758       break;
1759     case DBUS_MESSAGE_ITER_TYPE_DICT:
1760       /* Get the length of the string */
1761       len = _dbus_demarshal_uint32 (&iter->message->body,
1762                                     iter->message->byte_order,
1763                                     iter->pos, &pos);
1764       pos = pos + len + 1;
1765       data = _dbus_string_get_const_data_len (&iter->message->body,
1766                                               pos + 1, 1);
1767       _array_type_pos = pos + 1;
1768       break;
1769     default:
1770       _dbus_assert_not_reached ("wrong iter type");
1771       return DBUS_TYPE_INVALID;
1772     }
1773
1774   if (array_type_pos != NULL)
1775     *array_type_pos = _array_type_pos;
1776   
1777   data = _dbus_string_get_const_data_len (&iter->message->body,
1778                                           _array_type_pos, 1);
1779   if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_LAST)
1780     return  *data;
1781   
1782   return DBUS_TYPE_INVALID;
1783 }
1784
1785
1786 /**
1787  * Returns the element type of the array that the
1788  * message iterator points at. Note that you need
1789  * to check that the iterator points to an array
1790  * prior to using this function.
1791  *
1792  * @param iter the message iter
1793  * @returns the field type
1794  */
1795 int
1796 dbus_message_iter_get_array_type (DBusMessageIter *iter)
1797 {
1798   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
1799   int type, pos;
1800
1801   dbus_message_iter_check (real);
1802
1803   if (real->pos >= real->end)
1804     return DBUS_TYPE_INVALID;
1805
1806   pos = dbus_message_iter_get_data_start (real, &type);
1807
1808   _dbus_assert (type == DBUS_TYPE_ARRAY);
1809
1810   return iter_get_array_type (real, NULL);
1811 }
1812
1813
1814 /**
1815  * Returns the string value that an iterator may point to.
1816  * Note that you need to check that the iterator points to
1817  * a string value before using this function.
1818  *
1819  * @see dbus_message_iter_get_arg_type
1820  * @param iter the message iter
1821  * @returns the string
1822  */
1823 char *
1824 dbus_message_iter_get_string (DBusMessageIter *iter)
1825 {
1826   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
1827   int type, pos;
1828
1829   dbus_message_iter_check (real);
1830
1831   pos = dbus_message_iter_get_data_start (real, &type);
1832   
1833   _dbus_assert (type == DBUS_TYPE_STRING);
1834
1835   return _dbus_demarshal_string (&real->message->body, real->message->byte_order,
1836                                  pos, NULL);
1837 }
1838
1839 /**
1840  * Returns the name and data from a named type that an
1841  * iterator may point to. Note that you need to check that
1842  * the iterator points to a named type before using this
1843  * function.
1844  *
1845  * @see dbus_message_iter_get_arg_type
1846  * @param iter the message iter
1847  * @param name return location for the name
1848  * @param value return location for data
1849  * @param len return location for length of data
1850  * @returns TRUE if get succeed
1851  * 
1852  */
1853 dbus_bool_t
1854 dbus_message_iter_get_named (DBusMessageIter   *iter,
1855                              char             **name,
1856                              unsigned char    **value,
1857                              int               *len)
1858 {
1859   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
1860   int type, pos;
1861   char *_name;
1862
1863   dbus_message_iter_check (real);
1864
1865   pos = dbus_message_iter_get_data_start (real, &type);
1866   
1867   _dbus_assert (type == DBUS_TYPE_NAMED);
1868   
1869   _name = _dbus_demarshal_string (&real->message->body, real->message->byte_order,
1870                                   pos, &pos);
1871
1872   if (_name == NULL)
1873     return FALSE;
1874   
1875   if (!_dbus_demarshal_byte_array (&real->message->body, real->message->byte_order,
1876                                    pos + 1, NULL, value, len))
1877     {
1878       dbus_free (_name);
1879       return FALSE;
1880     }
1881
1882   *name = _name;
1883   
1884   return TRUE;
1885 }
1886
1887 /**
1888  * Returns the byte value that an iterator may point to.
1889  * Note that you need to check that the iterator points to
1890  * a byte value before using this function.
1891  *
1892  * @see dbus_message_iter_get_arg_type
1893  * @param iter the message iter
1894  * @returns the byte value
1895  */
1896 unsigned char
1897 dbus_message_iter_get_byte (DBusMessageIter *iter)
1898 {
1899   unsigned char value;
1900   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
1901   int type, pos;
1902
1903   dbus_message_iter_check (real);
1904
1905   pos = dbus_message_iter_get_data_start (real, &type);
1906   
1907   _dbus_assert (type == DBUS_TYPE_BYTE);
1908
1909   value = _dbus_string_get_byte (&real->message->body, pos);
1910   
1911   return value;
1912 }
1913
1914
1915 /**
1916  * Returns the boolean value that an iterator may point to.
1917  * Note that you need to check that the iterator points to
1918  * a boolean value before using this function.
1919  *
1920  * @see dbus_message_iter_get_arg_type
1921  * @param iter the message iter
1922  * @returns the boolean value
1923  */
1924 dbus_bool_t
1925 dbus_message_iter_get_boolean (DBusMessageIter *iter)
1926 {
1927   unsigned char value;
1928   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
1929   int type, pos;
1930
1931   dbus_message_iter_check (real);
1932
1933   pos = dbus_message_iter_get_data_start (real, &type);
1934   
1935   _dbus_assert (type == DBUS_TYPE_BOOLEAN);
1936
1937   value = _dbus_string_get_byte (&real->message->body, pos);
1938   
1939   return value;
1940 }
1941
1942 /**
1943  * Returns the 32 bit signed integer value that an iterator may point to.
1944  * Note that you need to check that the iterator points to
1945  * an integer value before using this function.
1946  *
1947  * @see dbus_message_iter_get_arg_type
1948  * @param iter the message iter
1949  * @returns the integer
1950  */
1951 dbus_int32_t
1952 dbus_message_iter_get_int32 (DBusMessageIter *iter)
1953 {
1954   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
1955   int type, pos;
1956
1957   dbus_message_iter_check (real);
1958
1959   pos = dbus_message_iter_get_data_start (real, &type);
1960   
1961   _dbus_assert (type == DBUS_TYPE_INT32);
1962   
1963   return _dbus_demarshal_int32 (&real->message->body, real->message->byte_order,
1964                                 pos, NULL);
1965 }
1966
1967 /**
1968  * Returns the 32 bit unsigned integer value that an iterator may point to.
1969  * Note that you need to check that the iterator points to
1970  * an unsigned integer value before using this function.
1971  *
1972  * @see dbus_message_iter_get_arg_type
1973  * @param iter the message iter
1974  * @returns the integer
1975  */
1976 dbus_uint32_t
1977 dbus_message_iter_get_uint32 (DBusMessageIter *iter)
1978 {
1979   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
1980   int type, pos;
1981
1982   dbus_message_iter_check (real);
1983
1984   pos = dbus_message_iter_get_data_start (real, &type);
1985   
1986   _dbus_assert (type == DBUS_TYPE_UINT32);
1987   
1988   return _dbus_demarshal_uint32 (&real->message->body, real->message->byte_order,
1989                                  pos, NULL);
1990 }
1991
1992 /**
1993  * Returns the double value that an iterator may point to.
1994  * Note that you need to check that the iterator points to
1995  * a string value before using this function.
1996  *
1997  * @see dbus_message_iter_get_arg_type
1998  * @param iter the message iter
1999  * @returns the double
2000  */
2001 double
2002 dbus_message_iter_get_double (DBusMessageIter *iter)
2003 {
2004   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2005   int type, pos;
2006
2007   dbus_message_iter_check (real);
2008
2009   pos = dbus_message_iter_get_data_start (real, &type);
2010   
2011   _dbus_assert (type == DBUS_TYPE_DOUBLE);
2012   
2013   return _dbus_demarshal_double (&real->message->body, real->message->byte_order,
2014                                  pos, NULL);
2015 }
2016
2017 /**
2018  * Initializes an iterator for the array that the iterator
2019  * may point to. Note that you need to check that the iterator
2020  * points to an array prior to using this function.
2021  *
2022  * The array element type is returned in array_type, and the array
2023  * iterator can only be used to get that type of data.
2024  *
2025  * @param iter the iterator
2026  * @param array_iter pointer to an iterator to initialize
2027  * @param array_type gets set to the type of the array elements
2028  * @returns #TRUE on success
2029  */
2030 dbus_bool_t
2031 dbus_message_iter_init_array_iterator (DBusMessageIter *iter,
2032                                        DBusMessageIter *array_iter,
2033                                        int             *array_type)
2034 {
2035   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2036   DBusMessageRealIter *array_real = (DBusMessageRealIter *)array_iter;
2037   int type, pos, len_pos, len, array_type_pos;
2038   int _array_type;
2039
2040   dbus_message_iter_check (real);
2041
2042   pos = dbus_message_iter_get_data_start (real, &type);
2043   
2044   _dbus_assert (type == DBUS_TYPE_ARRAY);
2045
2046   _array_type = iter_get_array_type (real, &array_type_pos);
2047   
2048   len_pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_uint32_t));
2049   len = _dbus_demarshal_uint32 (&real->message->body, real->message->byte_order,
2050                                 pos, &pos);
2051   
2052   array_real->parent_iter = real;
2053   array_real->message = real->message;
2054   array_real->changed_stamp = real->message->changed_stamp;
2055   
2056   array_real->type = DBUS_MESSAGE_ITER_TYPE_ARRAY;
2057   array_real->pos = pos;
2058   array_real->end = pos + len;
2059   
2060   array_real->container_start = pos;
2061   array_real->container_length_pos = len_pos;
2062   array_real->wrote_dict_key = 0;
2063   array_real->array_type_pos = array_type_pos;
2064   array_real->array_type_done = TRUE;
2065   
2066   if (array_type != NULL)
2067     *array_type = _array_type;
2068   
2069   return TRUE;
2070 }
2071
2072
2073 /**
2074  * Initializes an iterator for the dict that the iterator
2075  * may point to. Note that you need to check that the iterator
2076  * points to a dict prior to using this function.
2077  *
2078  * @param iter the iterator
2079  * @param dict_iter pointer to an iterator to initialize
2080  * @returns #TRUE on success
2081  */
2082 dbus_bool_t
2083 dbus_message_iter_init_dict_iterator (DBusMessageIter *iter,
2084                                       DBusMessageIter *dict_iter)
2085 {
2086   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2087   DBusMessageRealIter *dict_real = (DBusMessageRealIter *)dict_iter;
2088   int type, pos, len_pos, len;
2089
2090   dbus_message_iter_check (real);
2091
2092   pos = dbus_message_iter_get_data_start (real, &type);
2093   
2094   _dbus_assert (type == DBUS_TYPE_DICT);
2095
2096   len_pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_uint32_t));
2097   len = _dbus_demarshal_uint32 (&real->message->body, real->message->byte_order,
2098                                 pos, &pos);
2099   
2100   dict_real->parent_iter = real;
2101   dict_real->message = real->message;
2102   dict_real->changed_stamp = real->message->changed_stamp;
2103   
2104   dict_real->type = DBUS_MESSAGE_ITER_TYPE_DICT;
2105   dict_real->pos = pos;
2106   dict_real->end = pos + len;
2107   
2108   dict_real->container_start = pos;
2109   dict_real->container_length_pos = len_pos;
2110   dict_real->wrote_dict_key = 0;
2111
2112   return TRUE;
2113 }
2114
2115 /**
2116  * Returns the byte array that the iterator may point to.
2117  * Note that you need to check that the iterator points
2118  * to a byte array prior to using this function.
2119  *
2120  * @param iter the iterator
2121  * @param value return location for array values
2122  * @param len return location for length of byte array
2123  * @returns #TRUE on success
2124  */
2125 dbus_bool_t
2126 dbus_message_iter_get_byte_array (DBusMessageIter  *iter,
2127                                   unsigned char   **value,
2128                                   int              *len)
2129 {
2130   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2131   int type, pos;
2132
2133   dbus_message_iter_check (real);
2134
2135   pos = dbus_message_iter_get_data_start (real, &type);
2136   
2137   _dbus_assert (type == DBUS_TYPE_ARRAY);
2138
2139   type = iter_get_array_type (real, NULL);
2140
2141   _dbus_assert (type == DBUS_TYPE_BYTE);
2142
2143   if (!_dbus_demarshal_byte_array (&real->message->body, real->message->byte_order,
2144                                    pos, NULL, value, len))
2145     return FALSE;
2146   else
2147     return TRUE;
2148 }
2149
2150 /**
2151  * Returns the boolean array that the iterator may point to. Note that
2152  * you need to check that the iterator points to an array of the
2153  * correct type prior to using this function.
2154  *
2155  * @param iter the iterator
2156  * @param value return location for the array
2157  * @param len return location for the array length
2158  * @returns #TRUE on success
2159  */
2160 dbus_bool_t
2161 dbus_message_iter_get_boolean_array (DBusMessageIter   *iter,
2162                                      unsigned char    **value,
2163                                      int               *len)
2164 {
2165   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2166   int type, pos;
2167
2168   dbus_message_iter_check (real);
2169
2170   pos = dbus_message_iter_get_data_start (real, &type);
2171   
2172   _dbus_assert (type == DBUS_TYPE_ARRAY);
2173
2174   type = iter_get_array_type (real, NULL);
2175
2176   _dbus_assert (type == DBUS_TYPE_BOOLEAN);
2177
2178   if (!_dbus_demarshal_byte_array (&real->message->body, real->message->byte_order,
2179                                    pos, NULL, value, len))
2180     return FALSE;
2181   else
2182     return TRUE;
2183 }
2184
2185 /**
2186  * Returns the 32 bit signed integer array that the iterator may point
2187  * to. Note that you need to check that the iterator points to an
2188  * array of the correct type prior to using this function.
2189  *
2190  * @param iter the iterator
2191  * @param value return location for the array
2192  * @param len return location for the array length
2193  * @returns #TRUE on success
2194  */
2195 dbus_bool_t
2196 dbus_message_iter_get_int32_array  (DBusMessageIter *iter,
2197                                     dbus_int32_t   **value,
2198                                     int             *len)
2199 {
2200   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2201   int type, pos;
2202
2203   dbus_message_iter_check (real);
2204
2205   pos = dbus_message_iter_get_data_start (real, &type);
2206   
2207   _dbus_assert (type == DBUS_TYPE_ARRAY);
2208
2209   type = iter_get_array_type (real, NULL);
2210   
2211   _dbus_assert (type == DBUS_TYPE_INT32);
2212
2213   if (!_dbus_demarshal_int32_array (&real->message->body, real->message->byte_order,
2214                                     pos, NULL, value, len))
2215     return FALSE;
2216   else
2217     return TRUE;
2218 }
2219
2220 /**
2221  * Returns the 32 bit unsigned integer array that the iterator may point
2222  * to. Note that you need to check that the iterator points to an
2223  * array of the correct type prior to using this function.
2224  *
2225  * @param iter the iterator
2226  * @param value return location for the array
2227  * @param len return location for the array length
2228  * @returns #TRUE on success
2229  */
2230 dbus_bool_t
2231 dbus_message_iter_get_uint32_array  (DBusMessageIter *iter,
2232                                      dbus_uint32_t  **value,
2233                                      int             *len)
2234 {
2235   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2236   int type, pos;
2237
2238   dbus_message_iter_check (real);
2239
2240   pos = dbus_message_iter_get_data_start (real, &type);
2241   
2242   _dbus_assert (type == DBUS_TYPE_ARRAY);
2243
2244   type = iter_get_array_type (real, NULL);
2245   _dbus_assert (type == DBUS_TYPE_UINT32);
2246
2247   if (!_dbus_demarshal_uint32_array (&real->message->body, real->message->byte_order,
2248                                     pos, NULL, value, len))
2249     return FALSE;
2250   else
2251     return TRUE;
2252 }
2253
2254 /**
2255  * Returns the double array that the iterator may point to. Note that
2256  * you need to check that the iterator points to an array of the
2257  * correct type prior to using this function.
2258  *
2259  * @param iter the iterator
2260  * @param value return location for the array
2261  * @param len return location for the array length
2262  * @returns #TRUE on success
2263  */
2264 dbus_bool_t
2265 dbus_message_iter_get_double_array  (DBusMessageIter *iter,
2266                                      double         **value,
2267                                      int             *len)
2268 {
2269   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2270   int type, pos;
2271
2272   dbus_message_iter_check (real);
2273
2274   pos = dbus_message_iter_get_data_start (real, &type);
2275   
2276   _dbus_assert (type == DBUS_TYPE_ARRAY);
2277
2278   type = iter_get_array_type (real, NULL);
2279   _dbus_assert (type == DBUS_TYPE_DOUBLE);
2280
2281   if (!_dbus_demarshal_double_array (&real->message->body, real->message->byte_order,
2282                                      pos, NULL, value, len))
2283     return FALSE;
2284   else
2285     return TRUE;
2286 }
2287
2288 /**
2289  * Returns the string array that the iterator may point to.
2290  * Note that you need to check that the iterator points
2291  * to a byte array prior to using this function.
2292  *
2293  * The returned value is a #NULL-terminated array of strings.
2294  * Each string is a separate malloc block, and the array
2295  * itself is a malloc block. You can free this type of
2296  * string array with dbus_free_string_array().
2297  *
2298  * @param iter the iterator
2299  * @param value return location for string values
2300  * @param len return location for length of byte array
2301  * @returns #TRUE on success
2302  */
2303 dbus_bool_t
2304 dbus_message_iter_get_string_array (DBusMessageIter *iter,
2305                                     char          ***value,
2306                                     int             *len)
2307 {
2308   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2309   int type, pos;
2310
2311   dbus_message_iter_check (real);
2312
2313   pos = dbus_message_iter_get_data_start (real, &type);
2314   
2315   _dbus_assert (type == DBUS_TYPE_ARRAY);
2316
2317   type = iter_get_array_type (real, NULL);
2318   _dbus_assert (type == DBUS_TYPE_STRING);
2319
2320   if (!_dbus_demarshal_string_array (&real->message->body, real->message->byte_order,
2321                                      pos, NULL, value, len))
2322     return FALSE;
2323   else
2324     return TRUE;
2325 }
2326
2327 /**
2328  * Returns the key name fot the dict entry that an iterator
2329  * may point to. Note that you need to check that the iterator
2330  * points to a dict entry before using this function.
2331  *
2332  * @see dbus_message_iter_init_dict_iterator
2333  * @param iter the message iter
2334  * @returns the key name
2335  */
2336 char *
2337 dbus_message_iter_get_dict_key (DBusMessageIter   *iter)
2338 {
2339   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2340
2341   dbus_message_iter_check (real);
2342
2343   _dbus_assert (real->type == DBUS_MESSAGE_ITER_TYPE_DICT);
2344
2345   return _dbus_demarshal_string (&real->message->body, real->message->byte_order,
2346                                  real->pos, NULL);
2347 }
2348
2349 /**
2350  * Initializes a DBusMessageIter pointing to the end of the
2351  * message. This iterator can be used to append data to the
2352  * message.
2353  *
2354  * @param message the message
2355  * @param _iter pointer to an iterator to initialize
2356  */
2357 void
2358 dbus_message_append_iter_init (DBusMessage *message,
2359                                DBusMessageIter *iter)
2360 {
2361   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2362   
2363   real->message = message;
2364   real->parent_iter = NULL;
2365   real->changed_stamp = message->changed_stamp;
2366   
2367   real->type = DBUS_MESSAGE_ITER_TYPE_MESSAGE;
2368   real->end = _dbus_string_get_length (&real->message->body);
2369   real->pos = real->end;
2370   
2371   real->container_length_pos = 0;
2372   real->wrote_dict_key = 0;
2373 }
2374
2375 static void
2376 dbus_message_iter_append_check (DBusMessageRealIter *iter)
2377 {
2378   _dbus_assert (!iter->message->locked);
2379   
2380   if (iter->changed_stamp != iter->message->changed_stamp)
2381     _dbus_warn ("dbus iterator check failed: invalid iterator");
2382   
2383   if (iter->pos != iter->end)
2384     _dbus_warn ("dbus iterator check failed: can only append at end of message");
2385   
2386   if (iter->pos != _dbus_string_get_length (&iter->message->body))
2387     _dbus_warn ("dbus iterator check failed: append pos not at end of message string");
2388 }
2389
2390 static dbus_bool_t
2391 dbus_message_iter_append_type (DBusMessageRealIter *iter,
2392                                int type)
2393 {
2394   const char *data;
2395   switch (iter->type)
2396     {
2397     case DBUS_MESSAGE_ITER_TYPE_MESSAGE:
2398       if (!_dbus_string_append_byte (&iter->message->body, type))
2399         return FALSE;
2400       break;
2401       
2402     case DBUS_MESSAGE_ITER_TYPE_ARRAY:
2403       data = _dbus_string_get_const_data_len (&iter->message->body,
2404                                               iter->array_type_pos, 1);
2405       if (type != *data)
2406         {
2407           _dbus_warn ("Appended element of wrong type for array\n");
2408           return FALSE;
2409         }
2410       break;
2411       
2412     case DBUS_MESSAGE_ITER_TYPE_DICT:
2413       if (!iter->wrote_dict_key)
2414         {
2415           _dbus_warn ("Appending dict data before key name\n");
2416           return FALSE;
2417         }
2418       
2419       if (!_dbus_string_append_byte (&iter->message->body, type))
2420         return FALSE;
2421       
2422       break;
2423       
2424     default:
2425       _dbus_assert_not_reached ("Invalid iter type");
2426       break;
2427     }
2428   
2429   return TRUE;
2430 }
2431
2432 static void
2433 dbus_message_iter_update_after_change (DBusMessageRealIter *iter)
2434 {
2435   iter->changed_stamp = iter->message->changed_stamp;
2436   
2437   /* Set new end of iter */
2438   iter->end = _dbus_string_get_length (&iter->message->body);
2439   iter->pos = iter->end;
2440
2441   /* Set container length */
2442   if (iter->type == DBUS_MESSAGE_ITER_TYPE_DICT ||
2443       (iter->type == DBUS_MESSAGE_ITER_TYPE_ARRAY && iter->array_type_done))
2444     _dbus_marshal_set_uint32 (&iter->message->body,
2445                               iter->message->byte_order,
2446                               iter->container_length_pos,
2447                               iter->end - iter->container_start);
2448   
2449   if (iter->parent_iter)
2450     dbus_message_iter_update_after_change (iter->parent_iter);
2451 }
2452
2453 static void
2454 dbus_message_iter_append_done (DBusMessageRealIter *iter)
2455 {
2456   iter->message->changed_stamp++;
2457   dbus_message_iter_update_after_change (iter);
2458   iter->wrote_dict_key = FALSE;
2459 }
2460
2461 /**
2462  * Appends a nil value to the message
2463  *
2464  * @param iter an iterator pointing to the end of the message
2465  * @returns #TRUE on success
2466  */
2467 dbus_bool_t
2468 dbus_message_iter_append_nil (DBusMessageIter *iter)
2469 {
2470   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2471
2472   dbus_message_iter_append_check (real);
2473
2474   if (!dbus_message_iter_append_type (real, DBUS_TYPE_NIL))
2475     return FALSE;
2476   
2477   dbus_message_iter_append_done (real);
2478   
2479   return TRUE;
2480 }
2481
2482 /**
2483  * Appends a boolean value to the message
2484  *
2485  * @param iter an iterator pointing to the end of the message
2486  * @param value the boolean value
2487  * @returns #TRUE on success
2488  */
2489 dbus_bool_t
2490 dbus_message_iter_append_boolean (DBusMessageIter *iter,
2491                                   dbus_bool_t     value)
2492 {
2493   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2494
2495   dbus_message_iter_append_check (real);
2496
2497   if (!dbus_message_iter_append_type (real, DBUS_TYPE_BOOLEAN))
2498     return FALSE;
2499   
2500   if (!_dbus_string_append_byte (&real->message->body, (value != FALSE)))
2501     {
2502       _dbus_string_set_length (&real->message->body, real->pos);
2503       return FALSE;
2504     }
2505
2506   dbus_message_iter_append_done (real);
2507   
2508   return TRUE;
2509 }
2510
2511 /**
2512  * Appends a byte to the message
2513  *
2514  * @param iter an iterator pointing to the end of the message
2515  * @param value the byte value
2516  * @returns #TRUE on success
2517  */
2518 dbus_bool_t
2519 dbus_message_iter_append_byte (DBusMessageIter *iter,
2520                                unsigned char    value)
2521 {
2522   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2523
2524   dbus_message_iter_append_check (real);
2525
2526   if (!dbus_message_iter_append_type (real, DBUS_TYPE_BYTE))
2527     return FALSE;
2528   
2529   if (!_dbus_string_append_byte (&real->message->body, value))
2530     {
2531       _dbus_string_set_length (&real->message->body, real->pos);
2532       return FALSE;
2533     }
2534
2535   dbus_message_iter_append_done (real);
2536   
2537   return TRUE;
2538 }
2539
2540
2541 /**
2542  * Appends a 32 bit signed integer to the message.
2543  *
2544  * @param iter an iterator pointing to the end of the message
2545  * @param value the integer value
2546  * @returns #TRUE on success
2547  */
2548 dbus_bool_t
2549 dbus_message_iter_append_int32   (DBusMessageIter *iter,
2550                                   dbus_int32_t  value)
2551 {
2552   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2553
2554   dbus_message_iter_append_check (real);
2555
2556   if (!dbus_message_iter_append_type (real, DBUS_TYPE_INT32))
2557     return FALSE;
2558   
2559   if (!_dbus_marshal_int32 (&real->message->body, real->message->byte_order, value))
2560     {
2561       _dbus_string_set_length (&real->message->body, real->pos);
2562       return FALSE;
2563     }
2564
2565   dbus_message_iter_append_done (real);
2566   
2567   return TRUE;
2568 }
2569
2570 /**
2571  * Appends a 32 bit unsigned integer to the message.
2572  *
2573  * @param iter an iterator pointing to the end of the message
2574  * @param value the integer value
2575  * @returns #TRUE on success
2576  */
2577 dbus_bool_t
2578 dbus_message_iter_append_uint32 (DBusMessageIter *iter,
2579                                  dbus_uint32_t    value)
2580 {
2581   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2582
2583   dbus_message_iter_append_check (real);
2584
2585   if (!dbus_message_iter_append_type (real, DBUS_TYPE_UINT32))
2586     return FALSE;
2587   
2588   if (!_dbus_marshal_uint32 (&real->message->body, real->message->byte_order, value))
2589     {
2590       _dbus_string_set_length (&real->message->body, real->pos);
2591       return FALSE;
2592     }
2593
2594   dbus_message_iter_append_done (real);
2595   
2596   return TRUE;
2597 }
2598
2599 /**
2600  * Appends a double value to the message.
2601  *
2602  * @param iter an iterator pointing to the end of the message
2603  * @param value the double value
2604  * @returns #TRUE on success
2605  */
2606 dbus_bool_t
2607 dbus_message_iter_append_double (DBusMessageIter *iter,
2608                                  double           value)
2609 {
2610   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2611
2612   dbus_message_iter_append_check (real);
2613
2614   if (!dbus_message_iter_append_type (real, DBUS_TYPE_DOUBLE))
2615     return FALSE;
2616   
2617   if (!_dbus_marshal_double (&real->message->body, real->message->byte_order, value))
2618     {
2619       _dbus_string_set_length (&real->message->body, real->pos);
2620       return FALSE;
2621     }
2622
2623   dbus_message_iter_append_done (real);
2624   
2625   return TRUE;
2626 }
2627
2628 /**
2629  * Appends a UTF-8 string to the message.
2630  *
2631  * @param iter an iterator pointing to the end of the message
2632  * @param value the string
2633  * @returns #TRUE on success
2634  */
2635 dbus_bool_t
2636 dbus_message_iter_append_string (DBusMessageIter *iter,
2637                                  const char      *value)
2638 {
2639   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2640
2641   dbus_message_iter_append_check (real);
2642
2643   if (!dbus_message_iter_append_type (real, DBUS_TYPE_STRING))
2644     return FALSE;
2645   
2646   if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, value))
2647     {
2648       _dbus_string_set_length (&real->message->body, real->pos);
2649       return FALSE;
2650     }
2651
2652   dbus_message_iter_append_done (real);
2653   
2654   return TRUE;
2655 }
2656
2657 /**
2658  * Appends a named type data chunk to the message.
2659  *
2660  * @param iter an iterator pointing to the end of the message
2661  * @param name the name of the type
2662  * @parame
2663  * @returns #TRUE on success
2664  */
2665 dbus_bool_t
2666 dbus_message_iter_append_named (DBusMessageIter      *iter,
2667                                 const char           *name,
2668                                 const unsigned char  *data,
2669                                 int                   len)
2670 {
2671   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2672
2673   dbus_message_iter_append_check (real);
2674
2675   if (!dbus_message_iter_append_type (real, DBUS_TYPE_NAMED))
2676     return FALSE;
2677   
2678    if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, name))
2679     {
2680       _dbus_string_set_length (&real->message->body, real->pos);
2681       return FALSE;
2682     }
2683    
2684   if (!_dbus_marshal_byte_array (&real->message->body, real->message->byte_order, data, len))
2685     {
2686       _dbus_string_set_length (&real->message->body, real->pos);
2687       return FALSE;
2688     }
2689
2690   dbus_message_iter_append_done (real);
2691   
2692   return TRUE;
2693 }
2694
2695
2696 /**
2697  * Appends a dict key name to the message. The iterator used
2698  * must point to a dict.
2699  *
2700  * @param iter an iterator pointing to the end of the message
2701  * @param value the string
2702  * @returns #TRUE on success
2703  */
2704 dbus_bool_t
2705 dbus_message_iter_append_dict_key (DBusMessageIter *iter,
2706                                    const char      *value)
2707 {
2708   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2709
2710   dbus_message_iter_append_check (real);
2711   _dbus_assert (real->type == DBUS_MESSAGE_ITER_TYPE_DICT);
2712   
2713   if (real->wrote_dict_key)
2714     {
2715       _dbus_warn ("Appendinging multiple dict key names\n");
2716       return FALSE;
2717     }
2718   
2719   if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, value))
2720     {
2721       return FALSE;
2722     }
2723
2724   dbus_message_iter_append_done (real);
2725   real->wrote_dict_key = TRUE;
2726   
2727   return TRUE;
2728 }
2729
2730 static dbus_bool_t
2731 array_iter_type_mark_done (DBusMessageRealIter *iter)
2732 {
2733   int len_pos;
2734   
2735   if (iter->type == DBUS_MESSAGE_ITER_TYPE_ARRAY)
2736     array_iter_type_mark_done (iter->parent_iter);
2737   else
2738     return TRUE;
2739
2740   len_pos = _DBUS_ALIGN_VALUE (_dbus_string_get_length (&iter->message->body),
2741                                sizeof (dbus_uint32_t));
2742
2743   /* Empty length for now, backfill later */
2744   if (!_dbus_marshal_uint32 (&iter->message->body, iter->message->byte_order, 0))
2745     {
2746       _dbus_string_set_length (&iter->message->body, iter->pos);
2747       return FALSE;
2748     }
2749
2750   iter->container_start = _dbus_string_get_length (&iter->message->body);
2751   iter->container_length_pos = len_pos;
2752   iter->array_type_done = TRUE;
2753
2754   return TRUE;
2755 }
2756
2757 static dbus_bool_t
2758 append_array_type (DBusMessageRealIter *real,
2759                    int                  element_type,
2760                    dbus_bool_t         *array_type_done,
2761                    int                 *array_type_pos)
2762 {
2763   int existing_element_type;
2764   
2765   if (!dbus_message_iter_append_type (real, DBUS_TYPE_ARRAY))
2766     return FALSE;
2767   
2768   if (real->type == DBUS_MESSAGE_ITER_TYPE_ARRAY &&
2769       real->array_type_done)
2770     {
2771       existing_element_type = iter_get_array_type (real, array_type_pos);
2772       if (existing_element_type != element_type)
2773         {
2774           _dbus_warn ("Appending array of %d, when expecting array of %d\n",
2775                       element_type, existing_element_type);
2776           _dbus_string_set_length (&real->message->body, real->pos);
2777           return FALSE;
2778         }
2779       if (array_type_done != NULL)
2780           *array_type_done = TRUE;
2781     }
2782   else
2783     {
2784       if (array_type_pos != NULL)
2785         *array_type_pos = _dbus_string_get_length (&real->message->body);
2786       
2787       /* Append element type */
2788       if (!_dbus_string_append_byte (&real->message->body, element_type))
2789         {
2790           _dbus_string_set_length (&real->message->body, real->pos);
2791           return FALSE;
2792         }
2793
2794       if (array_type_done != NULL)
2795         *array_type_done = element_type != DBUS_TYPE_ARRAY;
2796       
2797       if (element_type != DBUS_TYPE_ARRAY &&
2798           !array_iter_type_mark_done (real))
2799         return FALSE;
2800     }
2801
2802   return TRUE;
2803 }
2804
2805 /**
2806  * Appends an array to the message and initializes an iterator that
2807  * can be used to append to the array.
2808  *
2809  * @param iter an iterator pointing to the end of the message
2810  * @param array_iter pointer to an iter that will be initialized
2811  * @param element_type the type of the array elements
2812  * @returns #TRUE on success
2813  */
2814 dbus_bool_t
2815 dbus_message_iter_append_array (DBusMessageIter      *iter,
2816                                 DBusMessageIter      *array_iter,
2817                                 int                   element_type)
2818 {
2819   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2820   DBusMessageRealIter *array_real = (DBusMessageRealIter *)array_iter;
2821   int len_pos;
2822   int array_type_pos;
2823   dbus_bool_t array_type_done;
2824
2825   if (element_type == DBUS_TYPE_NIL)
2826     {
2827       _dbus_warn ("Can't create NIL arrays\n");
2828       return FALSE;
2829     }
2830   
2831   dbus_message_iter_append_check (real);
2832
2833   if (!append_array_type (real, element_type, &array_type_done, &array_type_pos))
2834     return FALSE;
2835
2836   len_pos = _DBUS_ALIGN_VALUE (_dbus_string_get_length (&real->message->body), sizeof (dbus_uint32_t));
2837
2838   if (array_type_done)
2839     {
2840       /* Empty length for now, backfill later */
2841       if (!_dbus_marshal_uint32 (&real->message->body, real->message->byte_order, 0))
2842         {
2843           _dbus_string_set_length (&real->message->body, real->pos);
2844           return FALSE;
2845         }
2846     }
2847   
2848   array_real->parent_iter = real;
2849   array_real->message = real->message;
2850   array_real->changed_stamp = real->message->changed_stamp;
2851   
2852   array_real->type = DBUS_MESSAGE_ITER_TYPE_ARRAY;
2853   array_real->pos = _dbus_string_get_length (&real->message->body);
2854   array_real->end = array_real->end;
2855   
2856   array_real->container_start = array_real->pos;
2857   array_real->container_length_pos = len_pos;
2858   array_real->wrote_dict_key = 0;
2859   array_real->array_type_done = array_type_done;
2860   array_real->array_type_pos = array_type_pos;
2861
2862   dbus_message_iter_append_done (array_real);
2863   
2864   return TRUE;
2865 }
2866
2867 /**
2868  * Appends a dict to the message and initializes an iterator that
2869  * can be used to append to the dict.
2870  *
2871  * @param iter an iterator pointing to the end of the message
2872  * @param array_iter pointer to an iter that will be initialized
2873  * @param element_type the type of the array elements
2874  * @returns #TRUE on success
2875  */
2876 dbus_bool_t
2877 dbus_message_iter_append_dict (DBusMessageIter      *iter,
2878                                DBusMessageIter      *dict_iter)
2879 {
2880   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2881   DBusMessageRealIter *dict_real = (DBusMessageRealIter *)dict_iter;
2882   int len_pos;
2883
2884   dbus_message_iter_append_check (real);
2885
2886   if (!dbus_message_iter_append_type (real, DBUS_TYPE_DICT))
2887     return FALSE;
2888
2889   len_pos = _DBUS_ALIGN_VALUE (_dbus_string_get_length (&real->message->body), sizeof (dbus_uint32_t));
2890
2891   /* Empty length for now, backfill later */
2892   if (!_dbus_marshal_uint32 (&real->message->body, real->message->byte_order, 0))
2893     {
2894       _dbus_string_set_length (&real->message->body, real->pos);
2895       return FALSE;
2896     }
2897   
2898   dict_real->parent_iter = real;
2899   dict_real->message = real->message;
2900   dict_real->changed_stamp = real->message->changed_stamp;
2901   
2902   dict_real->type = DBUS_MESSAGE_ITER_TYPE_DICT;
2903   dict_real->pos = _dbus_string_get_length (&real->message->body);
2904   dict_real->end = dict_real->end;
2905   
2906   dict_real->container_start = dict_real->pos;
2907   dict_real->container_length_pos = len_pos;
2908   dict_real->wrote_dict_key = 0;
2909
2910   dbus_message_iter_append_done (dict_real);
2911   
2912   return TRUE;
2913 }
2914
2915
2916 /**
2917  * Appends a boolean array to the message.
2918  *
2919  * @param iter an iterator pointing to the end of the message
2920  * @param value the array
2921  * @param len the length of the array
2922  * @returns #TRUE on success
2923  */
2924 dbus_bool_t
2925 dbus_message_iter_append_boolean_array (DBusMessageIter     *iter,
2926                                         unsigned const char *value,
2927                                         int                  len)
2928 {
2929   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2930
2931   dbus_message_iter_append_check (real);
2932
2933   if (!append_array_type (real, DBUS_TYPE_BOOLEAN, NULL, NULL))
2934     return FALSE;
2935   
2936   if (!_dbus_marshal_byte_array (&real->message->body, real->message->byte_order, value, len))
2937     {
2938       _dbus_string_set_length (&real->message->body, real->pos);
2939       return FALSE;
2940     }
2941
2942   dbus_message_iter_append_done (real);
2943   
2944   return TRUE;
2945 }
2946
2947 /**
2948  * Appends a 32 bit signed integer array to the message.
2949  *
2950  * @param iter an iterator pointing to the end of the message
2951  * @param value the array
2952  * @param len the length of the array
2953  * @returns #TRUE on success
2954  */
2955 dbus_bool_t
2956 dbus_message_iter_append_int32_array (DBusMessageIter    *iter,
2957                                       const dbus_int32_t *value,
2958                                       int                 len)
2959 {
2960   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2961
2962   dbus_message_iter_append_check (real);
2963
2964   if (!append_array_type (real, DBUS_TYPE_INT32, NULL, NULL))
2965     return FALSE;
2966   
2967   if (!_dbus_marshal_int32_array (&real->message->body, real->message->byte_order, value, len))
2968     {
2969       _dbus_string_set_length (&real->message->body, real->pos);
2970       return FALSE;
2971     }
2972
2973   dbus_message_iter_append_done (real);
2974   
2975   return TRUE;
2976 }
2977
2978 /**
2979  * Appends a 32 bit unsigned integer array to the message.
2980  *
2981  * @param iter an iterator pointing to the end of the message
2982  * @param value the array
2983  * @param len the length of the array
2984  * @returns #TRUE on success
2985  */
2986 dbus_bool_t
2987 dbus_message_iter_append_uint32_array (DBusMessageIter     *iter,
2988                                        const dbus_uint32_t *value,
2989                                        int                  len)
2990 {
2991   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2992
2993   dbus_message_iter_append_check (real);
2994
2995   if (!append_array_type (real, DBUS_TYPE_UINT32, NULL, NULL))
2996     return FALSE;
2997   
2998   if (!_dbus_marshal_uint32_array (&real->message->body, real->message->byte_order, value, len))
2999     {
3000       _dbus_string_set_length (&real->message->body, real->pos);
3001       return FALSE;
3002     }
3003
3004   dbus_message_iter_append_done (real);
3005   
3006   return TRUE;
3007 }
3008
3009 /**
3010  * Appends a double array to the message.
3011  *
3012  * @param iter an iterator pointing to the end of the message
3013  * @param value the array
3014  * @param len the length of the array
3015  * @returns #TRUE on success
3016  */
3017 dbus_bool_t
3018 dbus_message_iter_append_double_array (DBusMessageIter *iter,
3019                                        const double    *value,
3020                                        int              len)
3021 {
3022   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3023
3024   dbus_message_iter_append_check (real);
3025
3026   if (!append_array_type (real, DBUS_TYPE_DOUBLE, NULL, NULL))
3027     return FALSE;
3028   
3029   if (!_dbus_marshal_double_array (&real->message->body, real->message->byte_order, value, len))
3030     {
3031       _dbus_string_set_length (&real->message->body, real->pos);
3032       return FALSE;
3033     }
3034
3035   dbus_message_iter_append_done (real);
3036   
3037   return TRUE;
3038 }
3039
3040 /**
3041  * Appends a byte array to the message.
3042  *
3043  * @param iter an iterator pointing to the end of the message
3044  * @param value the array
3045  * @param len the length of the array
3046  * @returns #TRUE on success
3047  */
3048 dbus_bool_t
3049 dbus_message_iter_append_byte_array (DBusMessageIter     *iter,
3050                                      unsigned const char *value,
3051                                      int                  len)
3052 {
3053   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3054
3055   dbus_message_iter_append_check (real);
3056
3057   if (!append_array_type (real, DBUS_TYPE_BYTE, NULL, NULL))
3058     return FALSE;
3059   
3060   if (!_dbus_marshal_byte_array (&real->message->body, real->message->byte_order, value, len))
3061     {
3062       _dbus_string_set_length (&real->message->body, real->pos);
3063       return FALSE;
3064     }
3065
3066   dbus_message_iter_append_done (real);
3067   
3068   return TRUE;
3069 }
3070
3071 /**
3072  * Appends a string array to the message.
3073  *
3074  * @param iter an iterator pointing to the end of the message
3075  * @param value the array
3076  * @param len the length of the array
3077  * @returns #TRUE on success
3078  */
3079 dbus_bool_t
3080 dbus_message_iter_append_string_array (DBusMessageIter *iter,
3081                                        const char     **value,
3082                                        int              len)
3083 {
3084   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3085
3086   dbus_message_iter_append_check (real);
3087
3088   if (!append_array_type (real, DBUS_TYPE_STRING, NULL, NULL))
3089     return FALSE;
3090   
3091   if (!_dbus_marshal_string_array (&real->message->body, real->message->byte_order, value, len))
3092     {
3093       _dbus_string_set_length (&real->message->body, real->pos);
3094       return FALSE;
3095     }
3096
3097   dbus_message_iter_append_done (real);
3098   
3099   return TRUE;
3100 }
3101
3102 /**
3103  * Sets the message sender.
3104  *
3105  * @param message the message
3106  * @param sender the sender
3107  * @returns #FALSE if not enough memory
3108  */
3109 dbus_bool_t
3110 dbus_message_set_sender (DBusMessage  *message,
3111                          const char   *sender)
3112 {
3113   _dbus_assert (!message->locked);
3114
3115   if (sender == NULL)
3116     {
3117       delete_string_field (message, FIELD_SENDER);
3118       return TRUE;
3119     }
3120   else
3121     {
3122       return set_string_field (message,
3123                                FIELD_SENDER,
3124                                sender);
3125     }
3126 }
3127
3128 /**
3129  * Sets a flag indicating that the message is an error reply
3130  * message, i.e. an "exception" rather than a normal response.
3131  *
3132  * @param message the message
3133  * @param is_error_reply #TRUE if this is an error message.
3134  */
3135 void
3136 dbus_message_set_is_error (DBusMessage *message,
3137                            dbus_bool_t  is_error_reply)
3138 {
3139   char *header;
3140   
3141   _dbus_assert (!message->locked);
3142   
3143   header = _dbus_string_get_data_len (&message->header, 1, 1);
3144   
3145   if (is_error_reply)
3146     *header |= DBUS_HEADER_FLAG_ERROR;
3147   else
3148     *header &= ~DBUS_HEADER_FLAG_ERROR;    
3149 }
3150
3151 /**
3152  * Returns #TRUE if the message is an error
3153  * reply to some previous message we sent.
3154  *
3155  * @param message the message
3156  * @returns #TRUE if the message is an error
3157  */
3158 dbus_bool_t
3159 dbus_message_get_is_error (DBusMessage *message)
3160 {
3161   const char *header;
3162
3163   header = _dbus_string_get_const_data_len (&message->header, 1, 1);
3164
3165   return (*header & DBUS_HEADER_FLAG_ERROR) != 0;
3166 }
3167
3168 /**
3169  * Gets the service which originated this message,
3170  * or #NULL if unknown or inapplicable.
3171  *
3172  * @param message the message
3173  * @returns the service name or #NULL
3174  */
3175 const char*
3176 dbus_message_get_sender (DBusMessage *message)
3177 {
3178   return get_string_field (message, FIELD_SENDER, NULL);
3179 }
3180
3181 /**
3182  * Checks whether the message has the given name.
3183  * If the message has no name or has a different
3184  * name, returns #FALSE.
3185  *
3186  * @param message the message
3187  * @param name the name to check (must not be #NULL)
3188  * 
3189  * @returns #TRUE if the message has the given name
3190  */
3191 dbus_bool_t
3192 dbus_message_name_is (DBusMessage *message,
3193                       const char  *name)
3194 {
3195   const char *n;
3196
3197   _dbus_assert (name != NULL);
3198   
3199   n = dbus_message_get_name (message);
3200
3201   if (n && strcmp (n, name) == 0)
3202     return TRUE;
3203   else
3204     return FALSE;
3205 }
3206
3207 /**
3208  * Checks whether the message was sent to the given service.  If the
3209  * message has no service specified or has a different name, returns
3210  * #FALSE.
3211  *
3212  * @param message the message
3213  * @param service the service to check (must not be #NULL)
3214  * 
3215  * @returns #TRUE if the message has the given destination service
3216  */
3217 dbus_bool_t
3218 dbus_message_service_is (DBusMessage  *message,
3219                          const char   *service)
3220 {
3221   const char *s;
3222
3223   _dbus_assert (service != NULL);
3224   
3225   s = dbus_message_get_service (message);
3226
3227   if (s && strcmp (s, service) == 0)
3228     return TRUE;
3229   else
3230     return FALSE;
3231 }
3232
3233 /**
3234  * Checks whether the message has the given service as its sender.  If
3235  * the message has no sender specified or has a different sender,
3236  * returns #FALSE. Note that if a peer application owns multiple
3237  * services, its messages will have only one of those services as the
3238  * sender (usually the base service). So you can't use this
3239  * function to prove the sender didn't own service Foo, you can
3240  * only use it to prove that it did.
3241  *
3242  * @param message the message
3243  * @param service the service to check (must not be #NULL)
3244  * 
3245  * @returns #TRUE if the message has the given origin service
3246  */
3247 dbus_bool_t
3248 dbus_message_sender_is (DBusMessage  *message,
3249                         const char   *service)
3250 {
3251   const char *s;
3252
3253   _dbus_assert (service != NULL);
3254   
3255   s = dbus_message_get_sender (message);
3256
3257   if (s && strcmp (s, service) == 0)
3258     return TRUE;
3259   else
3260     return FALSE;
3261 }
3262
3263 /**
3264  * Sets a #DBusError based on the contents of the given
3265  * message. The error is only set if the message
3266  * is an error message, as in dbus_message_get_is_error().
3267  * The name of the error is set to the name of the message,
3268  * and the error message is set to the first argument
3269  * if the argument exists and is a string.
3270  *
3271  * The return value indicates whether the error was set (the error is
3272  * set if and only if the message is an error message).
3273  * So you can check for an error reply and convert it to DBusError
3274  * in one go.
3275  *
3276  * @param error the error to set
3277  * @param message the message to set it from
3278  * @returns #TRUE if dbus_message_get_is_error() returns #TRUE for the message
3279  */
3280 dbus_bool_t
3281 dbus_set_error_from_message (DBusError   *error,
3282                              DBusMessage *message)
3283 {
3284   char *str;
3285   
3286   if (!dbus_message_get_is_error (message))
3287     return FALSE;
3288
3289   str = NULL;
3290   dbus_message_get_args (message, NULL,
3291                          DBUS_TYPE_STRING, &str,
3292                          DBUS_TYPE_INVALID);
3293
3294   dbus_set_error (error, dbus_message_get_name (message),
3295                   str ? "%s" : NULL, str);
3296
3297   dbus_free (str);
3298   
3299   return TRUE;
3300 }
3301
3302 /** @} */
3303
3304 /**
3305  * @addtogroup DBusMessageInternals
3306  *
3307  * @{
3308  */
3309 /**
3310  * @typedef DBusMessageLoader
3311  *
3312  * The DBusMessageLoader object encapsulates the process of converting
3313  * a byte stream into a series of DBusMessage. It buffers the incoming
3314  * bytes as efficiently as possible, and generates a queue of
3315  * messages. DBusMessageLoader is typically used as part of a
3316  * DBusTransport implementation. The DBusTransport then hands off
3317  * the loaded messages to a DBusConnection, making the messages
3318  * visible to the application.
3319  *
3320  * @todo write tests for break-loader that a) randomly delete header
3321  * fields and b) set string fields to zero-length and other funky
3322  * values.
3323  * 
3324  */
3325
3326 /* we definitely use signed ints for sizes, so don't exceed
3327  * _DBUS_INT_MAX; and add 16 for paranoia, since a message
3328  * over 128M is pretty nuts anyhow.
3329  */
3330
3331 /**
3332  * The maximum sane message size.
3333  */
3334 #define MAX_SANE_MESSAGE_SIZE (_DBUS_INT_MAX/16)
3335
3336 /**
3337  * Implementation details of DBusMessageLoader.
3338  * All members are private.
3339  */
3340 struct DBusMessageLoader
3341 {
3342   int refcount;        /**< Reference count. */
3343
3344   DBusString data;     /**< Buffered data */
3345   
3346   DBusList *messages;  /**< Complete messages. */
3347
3348   long max_message_size; /**< Maximum size of a message */
3349   
3350   unsigned int buffer_outstanding : 1; /**< Someone is using the buffer to read */
3351
3352   unsigned int corrupted : 1; /**< We got broken data, and are no longer working */
3353 };
3354
3355 /**
3356  * The initial buffer size of the message loader.
3357  * 
3358  * @todo this should be based on min header size plus some average
3359  * body size, or something. Or rather, the min header size only, if we
3360  * want to try to read only the header, store that in a DBusMessage,
3361  * then read only the body and store that, etc., depends on
3362  * how we optimize _dbus_message_loader_get_buffer() and what
3363  * the exact message format is.
3364  */
3365 #define INITIAL_LOADER_DATA_LEN 32
3366
3367 /**
3368  * Creates a new message loader. Returns #NULL if memory can't
3369  * be allocated.
3370  *
3371  * @returns new loader, or #NULL.
3372  */
3373 DBusMessageLoader*
3374 _dbus_message_loader_new (void)
3375 {
3376   DBusMessageLoader *loader;
3377
3378   loader = dbus_new0 (DBusMessageLoader, 1);
3379   if (loader == NULL)
3380     return NULL;
3381   
3382   loader->refcount = 1;
3383
3384   /* Try to cap message size at something that won't *totally* hose
3385    * the system if we have a couple of them.
3386    */
3387   loader->max_message_size = _DBUS_ONE_MEGABYTE * 32;
3388   
3389   if (!_dbus_string_init (&loader->data))
3390     {
3391       dbus_free (loader);
3392       return NULL;
3393     }
3394
3395   /* preallocate the buffer for speed, ignore failure */
3396   _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN);
3397   _dbus_string_set_length (&loader->data, 0);
3398   
3399   return loader;
3400 }
3401
3402 /**
3403  * Increments the reference count of the loader.
3404  *
3405  * @param loader the loader.
3406  */
3407 void
3408 _dbus_message_loader_ref (DBusMessageLoader *loader)
3409 {
3410   loader->refcount += 1;
3411 }
3412
3413 /**
3414  * Decrements the reference count of the loader and finalizes the
3415  * loader when the count reaches zero.
3416  *
3417  * @param loader the loader.
3418  */
3419 void
3420 _dbus_message_loader_unref (DBusMessageLoader *loader)
3421 {
3422   loader->refcount -= 1;
3423   if (loader->refcount == 0)
3424     {
3425       _dbus_list_foreach (&loader->messages,
3426                           (DBusForeachFunction) dbus_message_unref,
3427                           NULL);
3428       _dbus_list_clear (&loader->messages);
3429       _dbus_string_free (&loader->data);
3430       dbus_free (loader);
3431     }
3432 }
3433
3434 /**
3435  * Gets the buffer to use for reading data from the network.  Network
3436  * data is read directly into an allocated buffer, which is then used
3437  * in the DBusMessage, to avoid as many extra memcpy's as possible.
3438  * The buffer must always be returned immediately using
3439  * _dbus_message_loader_return_buffer(), even if no bytes are
3440  * successfully read.
3441  *
3442  * @todo this function can be a lot more clever. For example
3443  * it can probably always return a buffer size to read exactly
3444  * the body of the next message, thus avoiding any memory wastage
3445  * or reallocs.
3446  *
3447  * @todo we need to enforce a max length on strings in header fields.
3448  * 
3449  * @param loader the message loader.
3450  * @param buffer the buffer
3451  */
3452 void
3453 _dbus_message_loader_get_buffer (DBusMessageLoader  *loader,
3454                                  DBusString        **buffer)
3455 {
3456   _dbus_assert (!loader->buffer_outstanding);
3457
3458   *buffer = &loader->data;
3459   
3460   loader->buffer_outstanding = TRUE;
3461 }
3462
3463 /**
3464  * The smallest header size that can occur. 
3465  * (It won't be valid)
3466  */
3467 #define DBUS_MINIMUM_HEADER_SIZE 16
3468
3469 /** Pack four characters as in "abcd" into a uint32 */
3470 #define FOUR_CHARS_TO_UINT32(a, b, c, d)                \
3471                       ((((dbus_uint32_t)a) << 24) |     \
3472                        (((dbus_uint32_t)b) << 16) |     \
3473                        (((dbus_uint32_t)c) << 8)  |     \
3474                        ((dbus_uint32_t)d))
3475
3476 /** DBUS_HEADER_FIELD_NAME packed into a dbus_uint32_t */
3477 #define DBUS_HEADER_FIELD_NAME_AS_UINT32    \
3478   FOUR_CHARS_TO_UINT32 ('n', 'a', 'm', 'e')
3479
3480 /** DBUS_HEADER_FIELD_SERVICE packed into a dbus_uint32_t */
3481 #define DBUS_HEADER_FIELD_SERVICE_AS_UINT32 \
3482   FOUR_CHARS_TO_UINT32 ('s', 'r', 'v', 'c')
3483
3484 /** DBUS_HEADER_FIELD_REPLY packed into a dbus_uint32_t */
3485 #define DBUS_HEADER_FIELD_REPLY_AS_UINT32   \
3486   FOUR_CHARS_TO_UINT32 ('r', 'p', 'l', 'y')
3487
3488 /** DBUS_HEADER_FIELD_SENDER Packed into a dbus_uint32_t */
3489 #define DBUS_HEADER_FIELD_SENDER_AS_UINT32  \
3490   FOUR_CHARS_TO_UINT32 ('s', 'n', 'd', 'r')
3491
3492 /* FIXME impose max length on name, srvc, sndr */
3493 static dbus_bool_t
3494 decode_header_data (const DBusString   *data,
3495                     int                 header_len,
3496                     int                 byte_order,
3497                     HeaderField         fields[FIELD_LAST],
3498                     int                *message_padding)
3499 {
3500   const char *field;
3501   int pos, new_pos;
3502   int i;
3503   int type;
3504   
3505   if (header_len < 16)
3506     return FALSE;
3507   
3508   i = 0;
3509   while (i < FIELD_LAST)
3510     {
3511       fields[i].offset = -1;
3512       ++i;
3513     }
3514   
3515   fields[FIELD_HEADER_LENGTH].offset = 4;
3516   fields[FIELD_BODY_LENGTH].offset = 8;   
3517   fields[FIELD_CLIENT_SERIAL].offset = 12;
3518   
3519   /* Now handle the named fields. A real named field is at least 4
3520    * bytes for the name, plus a type code (1 byte) plus padding.  So
3521    * if we have less than 8 bytes left, it must be alignment padding,
3522    * not a field. While >= 8 bytes can't be entirely alignment
3523    * padding.
3524    */  
3525   pos = 16;
3526   while ((pos + 7) < header_len)
3527     {
3528       pos = _DBUS_ALIGN_VALUE (pos, 4);
3529       
3530       if ((pos + 4) > header_len)
3531         return FALSE;      
3532       
3533       field =_dbus_string_get_const_data_len (data, pos, 4);
3534       pos += 4;
3535
3536       _dbus_assert (_DBUS_ALIGN_ADDRESS (field, 4) == field);
3537
3538       switch (DBUS_UINT32_FROM_BE (*(int*)field))
3539         {
3540         case DBUS_HEADER_FIELD_SERVICE_AS_UINT32:
3541           if (fields[FIELD_SERVICE].offset >= 0)
3542             {
3543               _dbus_verbose ("%s field provided twice\n",
3544                              DBUS_HEADER_FIELD_SERVICE);
3545               return FALSE;
3546             }
3547           
3548           fields[FIELD_SERVICE].offset = _DBUS_ALIGN_VALUE (pos + 1, 4);
3549 #if 0
3550           _dbus_verbose ("Found service name at offset %d\n",
3551                          fields[FIELD_SERVICE].offset);
3552 #endif
3553           break;
3554
3555         case DBUS_HEADER_FIELD_NAME_AS_UINT32:
3556           if (fields[FIELD_NAME].offset >= 0)
3557             {              
3558               _dbus_verbose ("%s field provided twice\n",
3559                              DBUS_HEADER_FIELD_NAME);
3560               return FALSE;
3561             }
3562           
3563           fields[FIELD_NAME].offset = _DBUS_ALIGN_VALUE (pos + 1, 4);
3564
3565 #if 0
3566           _dbus_verbose ("Found message name at offset %d\n",
3567                          fields[FIELD_NAME].offset);
3568 #endif
3569           break;
3570         case DBUS_HEADER_FIELD_SENDER_AS_UINT32:
3571           if (fields[FIELD_SENDER].offset >= 0)
3572             {
3573               _dbus_verbose ("%s field provided twice\n",
3574                              DBUS_HEADER_FIELD_SENDER);
3575               return FALSE;
3576             }
3577           
3578           fields[FIELD_SENDER].offset = _DBUS_ALIGN_VALUE (pos + 1, 4);
3579
3580           _dbus_verbose ("Found sender name at offset %d\n",
3581                          fields[FIELD_NAME].offset);
3582           break;
3583           
3584         case DBUS_HEADER_FIELD_REPLY_AS_UINT32:
3585           if (fields[FIELD_REPLY_SERIAL].offset >= 0)
3586             {
3587               _dbus_verbose ("%s field provided twice\n",
3588                              DBUS_HEADER_FIELD_REPLY);
3589               return FALSE;
3590             }
3591           
3592           fields[FIELD_REPLY_SERIAL].offset = _DBUS_ALIGN_VALUE (pos + 1, 4);
3593
3594           _dbus_verbose ("Found reply serial at offset %d\n",
3595                          fields[FIELD_REPLY_SERIAL].offset);
3596           break;
3597
3598         default:
3599           _dbus_verbose ("Ignoring an unknown header field: %c%c%c%c at offset %d\n",
3600                          field[0], field[1], field[2], field[3], pos);
3601         }
3602
3603       if (!_dbus_marshal_validate_type (data, pos, &type, &pos))
3604         {
3605           _dbus_verbose ("Failed to validate type of named header field\n");
3606           return FALSE;
3607         }
3608       
3609       if (!_dbus_marshal_validate_arg (data, byte_order, 0, type, -1, pos, &new_pos))
3610         {
3611           _dbus_verbose ("Failed to validate argument to named header field\n");
3612           return FALSE;
3613         }
3614
3615       if (new_pos > header_len)
3616         {
3617           _dbus_verbose ("Named header field tries to extend beyond header length\n");
3618           return FALSE;
3619         }
3620       
3621       pos = new_pos;
3622     }
3623
3624   if (pos < header_len)
3625     {
3626       /* Alignment padding, verify that it's nul */
3627       _dbus_assert ((header_len - pos) < 8);
3628
3629       if (!_dbus_string_validate_nul (data,
3630                                       pos, (header_len - pos)))
3631         {
3632           _dbus_verbose ("header alignment padding is not nul\n");
3633           return FALSE;
3634         }
3635     }
3636
3637  if (fields[FIELD_NAME].offset < 0)
3638    {
3639      _dbus_verbose ("No %s field provided\n",
3640                     DBUS_HEADER_FIELD_NAME);
3641      return FALSE;
3642    }
3643   
3644   if (message_padding)
3645     *message_padding = header_len - pos;  
3646   
3647   return TRUE;
3648 }
3649
3650 /**
3651  * Returns a buffer obtained from _dbus_message_loader_get_buffer(),
3652  * indicating to the loader how many bytes of the buffer were filled
3653  * in. This function must always be called, even if no bytes were
3654  * successfully read.
3655  *
3656  * @param loader the loader.
3657  * @param buffer the buffer.
3658  * @param bytes_read number of bytes that were read into the buffer.
3659  */
3660 void
3661 _dbus_message_loader_return_buffer (DBusMessageLoader  *loader,
3662                                     DBusString         *buffer,
3663                                     int                 bytes_read)
3664 {
3665   _dbus_assert (loader->buffer_outstanding);
3666   _dbus_assert (buffer == &loader->data);
3667
3668   loader->buffer_outstanding = FALSE;
3669 }
3670
3671 /**
3672  * Converts buffered data into messages.
3673  *
3674  * @param loader the loader.
3675  * @returns #TRUE if we had enough memory to finish.
3676  */
3677 dbus_bool_t
3678 _dbus_message_loader_queue_messages (DBusMessageLoader *loader)
3679 {
3680   if (loader->corrupted)
3681     return TRUE;
3682
3683   while (_dbus_string_get_length (&loader->data) >= 16)
3684     {
3685       DBusMessage *message;      
3686       const char *header_data;
3687       int byte_order, header_len, body_len, header_padding;
3688       dbus_uint32_t header_len_unsigned, body_len_unsigned;
3689       
3690       header_data = _dbus_string_get_const_data_len (&loader->data, 0, 16);
3691
3692       _dbus_assert (_DBUS_ALIGN_ADDRESS (header_data, 4) == header_data);
3693
3694       if (header_data[2] != DBUS_MAJOR_PROTOCOL_VERSION)
3695         {
3696           _dbus_verbose ("Message has protocol version %d ours is %d\n",
3697                          (int) header_data[2], DBUS_MAJOR_PROTOCOL_VERSION);
3698           loader->corrupted = TRUE;
3699           return TRUE;
3700         }
3701       
3702       byte_order = header_data[0];
3703
3704       if (byte_order != DBUS_LITTLE_ENDIAN &&
3705           byte_order != DBUS_BIG_ENDIAN)
3706         {
3707           _dbus_verbose ("Message with bad byte order '%c' received\n",
3708                          byte_order);
3709           loader->corrupted = TRUE;
3710           return TRUE;
3711         }
3712
3713       header_len_unsigned = _dbus_unpack_uint32 (byte_order, header_data + 4);
3714       body_len_unsigned = _dbus_unpack_uint32 (byte_order, header_data + 8);
3715
3716       if (header_len_unsigned < 16)
3717         {
3718           _dbus_verbose ("Message had broken too-small header length %u\n",
3719                          header_len_unsigned);
3720           loader->corrupted = TRUE;
3721           return TRUE;
3722         }
3723
3724       if (header_len_unsigned > (unsigned) MAX_SANE_MESSAGE_SIZE ||
3725           body_len_unsigned > (unsigned) MAX_SANE_MESSAGE_SIZE)
3726         {
3727           _dbus_verbose ("Header or body length too large (%u %u)\n",
3728                          header_len_unsigned,
3729                          body_len_unsigned);
3730           loader->corrupted = TRUE;
3731           return TRUE;
3732         }
3733
3734       /* Now that we know the values are in signed range, get
3735        * rid of stupid unsigned, just causes bugs
3736        */
3737       header_len = header_len_unsigned;
3738       body_len = body_len_unsigned;
3739
3740       if (_DBUS_ALIGN_VALUE (header_len, 8) != header_len_unsigned)
3741         {
3742           
3743           _dbus_verbose ("header length %d is not aligned to 8 bytes\n",
3744                          header_len);
3745           loader->corrupted = TRUE;
3746           return TRUE;
3747         }
3748       
3749       if (header_len + body_len > loader->max_message_size)
3750         {
3751           _dbus_verbose ("Message claimed length header = %d body = %d exceeds max message length %ld\n",
3752                          header_len, body_len, loader->max_message_size);
3753           loader->corrupted = TRUE;
3754           return TRUE;
3755         }
3756
3757       if (_dbus_string_get_length (&loader->data) >= (header_len + body_len))
3758         {
3759           HeaderField fields[FIELD_LAST];
3760           int i;
3761           int next_arg;          
3762
3763 #if 0
3764           _dbus_verbose_bytes_of_string (&loader->data, 0, header_len + body_len);
3765 #endif    
3766           if (!decode_header_data (&loader->data, header_len, byte_order,
3767                                    fields, &header_padding))
3768             {
3769               _dbus_verbose ("Header was invalid\n");
3770               loader->corrupted = TRUE;
3771               return TRUE;
3772             }
3773           
3774           next_arg = header_len;
3775           while (next_arg < (header_len + body_len))
3776             {
3777               int type;
3778               int prev = next_arg;
3779
3780               if (!_dbus_marshal_validate_type (&loader->data, next_arg,
3781                                                 &type, &next_arg))
3782                 {
3783                   _dbus_verbose ("invalid typecode at offset %d\n", prev);
3784                   loader->corrupted = TRUE;
3785                   return TRUE;
3786                 }
3787       
3788               if (!_dbus_marshal_validate_arg (&loader->data,
3789                                                byte_order,
3790                                                0,
3791                                                type, -1,
3792                                                next_arg,
3793                                                &next_arg))
3794                 {
3795                   _dbus_verbose ("invalid type data at %d, next_arg\n", next_arg);
3796                   loader->corrupted = TRUE;
3797                   return TRUE;
3798                 }
3799
3800               _dbus_assert (next_arg > prev);
3801             }
3802           
3803           if (next_arg > (header_len + body_len))
3804             {
3805               _dbus_verbose ("end of last arg at %d but message has len %d+%d=%d\n",
3806                              next_arg, header_len, body_len,
3807                              header_len + body_len);
3808               loader->corrupted = TRUE;
3809               return TRUE;
3810             }
3811
3812           message = dbus_message_new_empty_header ();
3813           if (message == NULL)
3814             {
3815               _dbus_verbose ("Failed to allocate empty message\n");
3816               return FALSE;
3817             }
3818
3819           message->byte_order = byte_order;
3820           message->header_padding = header_padding;
3821           
3822           /* Copy in the offsets we found */
3823           i = 0;
3824           while (i < FIELD_LAST)
3825             {
3826               message->header_fields[i] = fields[i];
3827               ++i;
3828             }
3829           
3830           if (!_dbus_list_append (&loader->messages, message))
3831             {
3832               _dbus_verbose ("Failed to append new message to loader queue\n");
3833               dbus_message_unref (message);
3834               return FALSE;
3835             }
3836
3837           _dbus_assert (_dbus_string_get_length (&message->header) == 0);
3838           _dbus_assert (_dbus_string_get_length (&message->body) == 0);
3839
3840           _dbus_assert (_dbus_string_get_length (&loader->data) >=
3841                         (header_len + body_len));
3842           
3843           if (!_dbus_string_move_len (&loader->data, 0, header_len, &message->header, 0))
3844             {
3845               _dbus_verbose ("Failed to move header into new message\n");
3846               _dbus_list_remove_last (&loader->messages, message);
3847               dbus_message_unref (message);
3848               return FALSE;
3849             }
3850           
3851           if (!_dbus_string_move_len (&loader->data, 0, body_len, &message->body, 0))
3852             {
3853               dbus_bool_t result;
3854
3855               _dbus_verbose ("Failed to move body into new message\n");
3856               
3857               /* put the header back, we'll try again later */
3858               result = _dbus_string_copy_len (&message->header, 0, header_len,
3859                                               &loader->data, 0);
3860               _dbus_assert (result); /* because DBusString never reallocs smaller */
3861
3862               _dbus_list_remove_last (&loader->messages, message);
3863               dbus_message_unref (message);
3864               return FALSE;
3865             }
3866
3867           _dbus_assert (_dbus_string_get_length (&message->header) == header_len);
3868           _dbus_assert (_dbus_string_get_length (&message->body) == body_len);
3869
3870           /* Fill in caches */
3871           message->reply_serial = get_int_field (message,
3872                                                  FIELD_REPLY_SERIAL);
3873           message->client_serial = get_int_field (message,
3874                                                   FIELD_CLIENT_SERIAL);
3875           
3876           _dbus_verbose ("Loaded message %p\n", message);
3877         }
3878       else
3879         return TRUE;
3880     }
3881
3882   return TRUE;
3883 }
3884
3885 /**
3886  * Peeks at first loaded message, returns #NULL if no messages have
3887  * been queued.
3888  *
3889  * @param loader the loader.
3890  * @returns the next message, or #NULL if none.
3891  */
3892 DBusMessage*
3893 _dbus_message_loader_peek_message (DBusMessageLoader *loader)
3894 {
3895   if (loader->messages)
3896     return loader->messages->data;
3897   else
3898     return NULL;
3899 }
3900
3901 /**
3902  * Pops a loaded message (passing ownership of the message
3903  * to the caller). Returns #NULL if no messages have been
3904  * queued.
3905  *
3906  * @param loader the loader.
3907  * @returns the next message, or #NULL if none.
3908  */
3909 DBusMessage*
3910 _dbus_message_loader_pop_message (DBusMessageLoader *loader)
3911 {
3912   return _dbus_list_pop_first (&loader->messages);
3913 }
3914
3915 /**
3916  * Pops a loaded message inside a list link (passing ownership of the
3917  * message and link to the caller). Returns #NULL if no messages have
3918  * been loaded.
3919  *
3920  * @param loader the loader.
3921  * @returns the next message link, or #NULL if none.
3922  */
3923 DBusList*
3924 _dbus_message_loader_pop_message_link (DBusMessageLoader *loader)
3925 {
3926   return _dbus_list_pop_first_link (&loader->messages);
3927 }
3928
3929 /**
3930  * Checks whether the loader is confused due to bad data.
3931  * If messages are received that are invalid, the
3932  * loader gets confused and gives up permanently.
3933  * This state is called "corrupted."
3934  *
3935  * @param loader the loader
3936  * @returns #TRUE if the loader is hosed.
3937  */
3938 dbus_bool_t
3939 _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader)
3940 {
3941   return loader->corrupted;
3942 }
3943
3944 /**
3945  * Sets the maximum size message we allow.
3946  *
3947  * @param loader the loader
3948  * @param size the max message size in bytes
3949  */
3950 void
3951 _dbus_message_loader_set_max_message_size (DBusMessageLoader  *loader,
3952                                            long                size)
3953 {
3954   if (size > MAX_SANE_MESSAGE_SIZE)
3955     {
3956       _dbus_verbose ("clamping requested max message size %ld to %d\n",
3957                      size, MAX_SANE_MESSAGE_SIZE);
3958       size = MAX_SANE_MESSAGE_SIZE;
3959     }
3960   loader->max_message_size = size;
3961 }
3962
3963 /**
3964  * Gets the maximum allowed message size in bytes.
3965  *
3966  * @param loader the loader
3967  * @returns max size in bytes
3968  */
3969 long
3970 _dbus_message_loader_get_max_message_size (DBusMessageLoader  *loader)
3971 {
3972   return loader->max_message_size;
3973 }
3974
3975 /** @} */
3976 #ifdef DBUS_BUILD_TESTS
3977 #include "dbus-test.h"
3978 #include <stdio.h>
3979
3980 static void
3981 message_iter_test (DBusMessage *message)
3982 {
3983   DBusMessageIter iter, dict, array, array2;
3984   char *str;
3985   unsigned char *data;
3986   dbus_int32_t *our_int_array;
3987   int len;
3988   
3989   dbus_message_iter_init (message, &iter);
3990
3991   /* String tests */
3992   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING)
3993     _dbus_assert_not_reached ("Argument type isn't string");
3994
3995   str = dbus_message_iter_get_string (&iter);
3996   if (strcmp (str, "Test string") != 0)
3997     _dbus_assert_not_reached ("Strings differ");
3998   dbus_free (str);
3999
4000   if (!dbus_message_iter_next (&iter))
4001     _dbus_assert_not_reached ("Reached end of arguments");
4002
4003   /* Signed integer tests */
4004   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INT32)
4005     _dbus_assert_not_reached ("Argument type isn't int32");
4006
4007   if (dbus_message_iter_get_int32 (&iter) != -0x12345678)
4008     _dbus_assert_not_reached ("Signed integers differ");
4009
4010   if (!dbus_message_iter_next (&iter))
4011     _dbus_assert_not_reached ("Reached end of fields");
4012   
4013   /* Unsigned integer tests */
4014   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_UINT32)
4015     _dbus_assert_not_reached ("Argument type isn't int32");
4016
4017   if (dbus_message_iter_get_uint32 (&iter) != 0xedd1e)
4018     _dbus_assert_not_reached ("Unsigned integers differ");
4019
4020   if (!dbus_message_iter_next (&iter))
4021     _dbus_assert_not_reached ("Reached end of arguments");
4022
4023   /* Double tests */
4024   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_DOUBLE)
4025     _dbus_assert_not_reached ("Argument type isn't double");
4026
4027   if (dbus_message_iter_get_double (&iter) != 3.14159)
4028     _dbus_assert_not_reached ("Doubles differ");
4029
4030   if (!dbus_message_iter_next (&iter))
4031     _dbus_assert_not_reached ("Reached end of arguments");
4032
4033   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY)
4034     _dbus_assert_not_reached ("Argument type not an array");
4035
4036   if (dbus_message_iter_get_array_type (&iter) != DBUS_TYPE_DOUBLE)
4037     _dbus_assert_not_reached ("Array type not double");
4038
4039   
4040   if (!dbus_message_iter_init_array_iterator (&iter, &array, NULL))
4041     _dbus_assert_not_reached ("Array init failed");
4042
4043   if (dbus_message_iter_get_arg_type (&array) != DBUS_TYPE_DOUBLE)
4044     _dbus_assert_not_reached ("Argument type isn't double");
4045
4046   if (dbus_message_iter_get_double (&array) != 1.5)
4047     _dbus_assert_not_reached ("Unsigned integers differ");
4048
4049   if (!dbus_message_iter_next (&array))
4050     _dbus_assert_not_reached ("Reached end of arguments");
4051
4052   if (dbus_message_iter_get_arg_type (&array) != DBUS_TYPE_DOUBLE)
4053     _dbus_assert_not_reached ("Argument type isn't double");
4054
4055   if (dbus_message_iter_get_double (&array) != 2.5)
4056     _dbus_assert_not_reached ("Unsigned integers differ");
4057
4058   if (dbus_message_iter_next (&array))
4059     _dbus_assert_not_reached ("Didn't reach end of arguments");
4060   
4061   if (!dbus_message_iter_next (&iter))
4062     _dbus_assert_not_reached ("Reached end of arguments");
4063   
4064
4065   /* dict */
4066
4067   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_DICT)
4068     _dbus_assert_not_reached ("not dict type");
4069      
4070   if (!dbus_message_iter_init_dict_iterator (&iter, &dict))
4071     _dbus_assert_not_reached ("dict iter failed");
4072
4073   str = dbus_message_iter_get_dict_key (&dict);
4074   if (str == NULL || strcmp (str, "test") != 0)
4075     _dbus_assert_not_reached ("wrong dict key");
4076   dbus_free (str);
4077
4078   if (dbus_message_iter_get_arg_type (&dict) != DBUS_TYPE_UINT32)
4079     _dbus_assert_not_reached ("wrong dict entry type");
4080
4081   if (dbus_message_iter_get_uint32 (&dict) != 0xDEADBEEF)
4082     _dbus_assert_not_reached ("wrong dict entry value");
4083
4084   if (!dbus_message_iter_next (&dict))
4085     _dbus_assert_not_reached ("reached end of dict");
4086   
4087   /* array of array of int32 (in dict) */
4088
4089   str = dbus_message_iter_get_dict_key (&dict);
4090   if (str == NULL || strcmp (str, "array") != 0)
4091     _dbus_assert_not_reached ("wrong dict key");
4092   dbus_free (str);
4093   
4094   if (dbus_message_iter_get_arg_type (&dict) != DBUS_TYPE_ARRAY)
4095     _dbus_assert_not_reached ("Argument type not an array");
4096
4097   if (dbus_message_iter_get_array_type (&dict) != DBUS_TYPE_ARRAY)
4098     _dbus_assert_not_reached ("Array type not array");
4099
4100   if (!dbus_message_iter_init_array_iterator (&dict, &array, NULL))
4101     _dbus_assert_not_reached ("Array init failed");
4102
4103   if (dbus_message_iter_get_arg_type (&array) != DBUS_TYPE_ARRAY)
4104     _dbus_assert_not_reached ("Argument type isn't array");
4105   
4106   if (dbus_message_iter_get_array_type (&array) != DBUS_TYPE_INT32)
4107     _dbus_assert_not_reached ("Array type not int32");
4108   
4109   if (!dbus_message_iter_init_array_iterator (&array, &array2, NULL))
4110     _dbus_assert_not_reached ("Array init failed");
4111
4112   if (dbus_message_iter_get_arg_type (&array2) != DBUS_TYPE_INT32)
4113     _dbus_assert_not_reached ("Argument type isn't int32");
4114
4115   if (dbus_message_iter_get_int32 (&array2) != 0x12345678)
4116     _dbus_assert_not_reached ("Signed integers differ");
4117
4118   if (!dbus_message_iter_next (&array2))
4119     _dbus_assert_not_reached ("Reached end of arguments");
4120
4121   if (dbus_message_iter_get_int32 (&array2) != 0x23456781)
4122     _dbus_assert_not_reached ("Signed integers differ");
4123
4124   if (dbus_message_iter_next (&array2))
4125     _dbus_assert_not_reached ("Didn't reached end of arguments");
4126
4127   if (!dbus_message_iter_next (&array))
4128     _dbus_assert_not_reached ("Reached end of arguments");
4129
4130   if (dbus_message_iter_get_array_type (&array) != DBUS_TYPE_INT32)
4131     _dbus_assert_not_reached ("Array type not int32");
4132
4133   if (!dbus_message_iter_get_int32_array (&array,
4134                                           &our_int_array,
4135                                           &len))
4136     _dbus_assert_not_reached ("couldn't get int32 array");
4137
4138   _dbus_assert (len == 3);
4139   _dbus_assert (our_int_array[0] == 0x34567812 &&
4140                 our_int_array[1] == 0x45678123 &&
4141                 our_int_array[2] == 0x56781234);
4142   dbus_free (our_int_array);
4143   
4144   if (dbus_message_iter_next (&array))
4145     _dbus_assert_not_reached ("Didn't reach end of array");
4146
4147   if (dbus_message_iter_next (&dict))
4148     _dbus_assert_not_reached ("Didn't reach end of dict");
4149   
4150   if (!dbus_message_iter_next (&iter))
4151     _dbus_assert_not_reached ("Reached end of arguments");
4152   
4153   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_BYTE)
4154     {
4155       _dbus_warn ("type was: %d\n", dbus_message_iter_get_arg_type (&iter));
4156       _dbus_assert_not_reached ("wrong type after dict (should be byte)");
4157     }
4158   
4159   if (dbus_message_iter_get_byte (&iter) != 0xF0)
4160     _dbus_assert_not_reached ("wrong value after dict");
4161
4162
4163   if (!dbus_message_iter_next (&iter))
4164     _dbus_assert_not_reached ("Reached end of arguments");
4165   
4166   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_NIL)
4167     _dbus_assert_not_reached ("not a nil type");
4168   
4169   if (!dbus_message_iter_next (&iter))
4170     _dbus_assert_not_reached ("Reached end of arguments");
4171   
4172   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_NAMED)
4173     _dbus_assert_not_reached ("wrong type after dict");
4174
4175   if (!dbus_message_iter_get_named (&iter, &str, &data, &len))
4176     _dbus_assert_not_reached ("failed to get named");
4177
4178   _dbus_assert (strcmp (str, "named")==0);
4179   _dbus_assert (len == 5);
4180   _dbus_assert (strcmp (data, "data")==0);
4181   dbus_free (str);
4182   dbus_free (data);
4183   
4184   if (dbus_message_iter_next (&iter))
4185     _dbus_assert_not_reached ("Didn't reach end of arguments");
4186 }
4187
4188
4189 static dbus_bool_t
4190 check_message_handling_type (DBusMessageIter *iter,
4191                              int type)
4192 {
4193   DBusMessageIter child_iter;
4194   
4195   switch (type)
4196     {
4197     case DBUS_TYPE_NIL:
4198       break;
4199     case DBUS_TYPE_BYTE:
4200       dbus_message_iter_get_byte (iter);
4201       break;
4202     case DBUS_TYPE_BOOLEAN:
4203       dbus_message_iter_get_boolean (iter);
4204       break;
4205     case DBUS_TYPE_INT32:
4206       dbus_message_iter_get_int32 (iter);
4207       break;
4208     case DBUS_TYPE_UINT32:
4209       dbus_message_iter_get_uint32 (iter);
4210       break;
4211     case DBUS_TYPE_DOUBLE:
4212       dbus_message_iter_get_double (iter);
4213       break;
4214     case DBUS_TYPE_STRING:
4215       {
4216         char *str;
4217         str = dbus_message_iter_get_string (iter);
4218         if (str == NULL)
4219           {
4220             _dbus_warn ("NULL string in message\n");
4221             return FALSE;
4222           }
4223         dbus_free (str);
4224       }
4225       break;
4226     case DBUS_TYPE_NAMED:
4227       {
4228         char *name;
4229         unsigned char *data;
4230         int len;
4231         
4232         if (!dbus_message_iter_get_named (iter, &name, &data, &len))
4233           {
4234             _dbus_warn ("error reading name from named type\n");
4235             return FALSE;
4236           }
4237         dbus_free (data);
4238         dbus_free (name);
4239       }
4240       break;
4241     case DBUS_TYPE_ARRAY:
4242       {
4243         int array_type;
4244
4245         if (!dbus_message_iter_init_array_iterator (iter, &child_iter, &array_type))
4246           {
4247             _dbus_warn ("Failed to init array iterator\n");
4248             return FALSE;
4249           }
4250
4251         while (dbus_message_iter_has_next (&child_iter))
4252           {
4253             if (!check_message_handling_type (&child_iter, array_type))
4254               {
4255                 _dbus_warn ("error in array element\n");
4256                 return FALSE;
4257               }
4258             
4259             if (!dbus_message_iter_next (&child_iter))
4260               break;
4261           }
4262       }
4263       break;
4264     case DBUS_TYPE_DICT:
4265       {
4266         int entry_type;
4267         char *key;
4268         
4269         if (!dbus_message_iter_init_dict_iterator (iter, &child_iter))
4270           {
4271             _dbus_warn ("Failed to init dict iterator\n");
4272             return FALSE;
4273           }
4274
4275         while ((entry_type = dbus_message_iter_get_arg_type (&child_iter)) != DBUS_TYPE_INVALID)
4276           {
4277             key = dbus_message_iter_get_dict_key (&child_iter);
4278             if (key == NULL)
4279               {
4280                 _dbus_warn ("error reading dict key\n");
4281                 return FALSE;
4282               }
4283             dbus_free (key);
4284             
4285             if (!check_message_handling_type (&child_iter, entry_type))
4286               {
4287                 _dbus_warn ("error in dict value\n");
4288                 return FALSE;
4289               }
4290             
4291             if (!dbus_message_iter_next (&child_iter))
4292               break;
4293           }
4294       }
4295       break;
4296       
4297     default:
4298       _dbus_warn ("unknown type %d\n", type);
4299       return FALSE;
4300       break;
4301     }
4302   return TRUE;
4303 }
4304   
4305   
4306 static dbus_bool_t
4307 check_message_handling (DBusMessage *message)
4308 {
4309   DBusMessageIter iter;
4310   int type;
4311   dbus_bool_t retval;
4312   dbus_int32_t client_serial;
4313   
4314   retval = FALSE;
4315   
4316   client_serial = dbus_message_get_serial (message);
4317
4318   /* can't use set_serial due to the assertions at the start of it */
4319   set_int_field (message, FIELD_CLIENT_SERIAL,
4320                  client_serial);
4321   
4322   if (client_serial != dbus_message_get_serial (message))
4323     {
4324       _dbus_warn ("get/set cycle for client_serial did not succeed\n");
4325       goto failed;
4326     }
4327   
4328   /* If we implement message_set_arg (message, n, value)
4329    * then we would want to test it here
4330    */
4331
4332   dbus_message_iter_init (message, &iter);
4333   while ((type = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID)
4334     {
4335       if (!check_message_handling_type (&iter, type))
4336         goto failed;
4337
4338       if (!dbus_message_iter_next (&iter))
4339         break;
4340     }
4341   
4342   retval = TRUE;
4343   
4344  failed:
4345   return retval;
4346 }
4347
4348 static dbus_bool_t
4349 check_have_valid_message (DBusMessageLoader *loader)
4350 {
4351   DBusMessage *message;
4352   dbus_bool_t retval;
4353
4354   message = NULL;
4355   retval = FALSE;
4356
4357   if (!_dbus_message_loader_queue_messages (loader))
4358     _dbus_assert_not_reached ("no memory to queue messages");
4359   
4360   if (_dbus_message_loader_get_is_corrupted (loader))
4361     {
4362       _dbus_warn ("loader corrupted on message that was expected to be valid\n");
4363       goto failed;
4364     }
4365   
4366   message = _dbus_message_loader_pop_message (loader);
4367   if (message == NULL)
4368     {
4369       _dbus_warn ("didn't load message that was expected to be valid (message not popped)\n");
4370       goto failed;
4371     }
4372   
4373   if (_dbus_string_get_length (&loader->data) > 0)
4374     {
4375       _dbus_warn ("had leftover bytes from expected-to-be-valid single message\n");
4376       goto failed;
4377     }
4378
4379   /* Verify that we're able to properly deal with the message.
4380    * For example, this would detect improper handling of messages
4381    * in nonstandard byte order.
4382    */
4383   if (!check_message_handling (message))
4384     goto failed;  
4385   
4386   retval = TRUE;
4387
4388  failed:
4389   if (message)
4390     dbus_message_unref (message);
4391
4392   return retval;
4393 }
4394
4395 static dbus_bool_t
4396 check_invalid_message (DBusMessageLoader *loader)
4397 {
4398   dbus_bool_t retval;
4399
4400   retval = FALSE;
4401
4402   if (!_dbus_message_loader_queue_messages (loader))
4403     _dbus_assert_not_reached ("no memory to queue messages");
4404   
4405   if (!_dbus_message_loader_get_is_corrupted (loader))
4406     {
4407       _dbus_warn ("loader not corrupted on message that was expected to be invalid\n");
4408       goto failed;
4409     }
4410
4411   retval = TRUE;
4412
4413  failed:
4414   return retval;
4415 }
4416
4417 static dbus_bool_t
4418 check_incomplete_message (DBusMessageLoader *loader)
4419 {
4420   DBusMessage *message;
4421   dbus_bool_t retval;
4422
4423   message = NULL;
4424   retval = FALSE;
4425
4426   if (!_dbus_message_loader_queue_messages (loader))
4427     _dbus_assert_not_reached ("no memory to queue messages");
4428   
4429   if (_dbus_message_loader_get_is_corrupted (loader))
4430     {
4431       _dbus_warn ("loader corrupted on message that was expected to be valid (but incomplete)\n");
4432       goto failed;
4433     }
4434   
4435   message = _dbus_message_loader_pop_message (loader);
4436   if (message != NULL)
4437     {
4438       _dbus_warn ("loaded message that was expected to be incomplete\n");
4439       goto failed;
4440     }
4441
4442   retval = TRUE;
4443
4444  failed:
4445   if (message)
4446     dbus_message_unref (message);
4447   return retval;
4448 }
4449
4450 static dbus_bool_t
4451 check_loader_results (DBusMessageLoader      *loader,
4452                       DBusMessageValidity     validity)
4453 {
4454   if (!_dbus_message_loader_queue_messages (loader))
4455     _dbus_assert_not_reached ("no memory to queue messages");
4456   
4457   switch (validity)
4458     {
4459     case _DBUS_MESSAGE_VALID:
4460       return check_have_valid_message (loader);
4461     case _DBUS_MESSAGE_INVALID:
4462       return check_invalid_message (loader);
4463     case _DBUS_MESSAGE_INCOMPLETE:
4464       return check_incomplete_message (loader);
4465     case _DBUS_MESSAGE_UNKNOWN:
4466       return TRUE;
4467     }
4468
4469   _dbus_assert_not_reached ("bad DBusMessageValidity");
4470   return FALSE;
4471 }
4472
4473
4474 /**
4475  * Loads the message in the given message file.
4476  *
4477  * @param filename filename to load
4478  * @param is_raw if #TRUE load as binary data, if #FALSE as message builder language
4479  * @param data string to load message into
4480  * @returns #TRUE if the message was loaded
4481  */
4482 dbus_bool_t
4483 dbus_internal_do_not_use_load_message_file (const DBusString    *filename,
4484                                             dbus_bool_t          is_raw,
4485                                             DBusString          *data)
4486 {
4487   dbus_bool_t retval;
4488
4489   retval = FALSE;  
4490
4491   if (is_raw)
4492     {
4493       DBusError error;
4494
4495       _dbus_verbose ("Loading raw %s\n", _dbus_string_get_const_data (filename));
4496       dbus_error_init (&error);
4497       if (!_dbus_file_get_contents (data, filename, &error))
4498         {
4499           _dbus_warn ("Could not load message file %s: %s\n",
4500                       _dbus_string_get_const_data (filename),
4501                       error.message);
4502           dbus_error_free (&error);
4503           goto failed;
4504         }
4505     }
4506   else
4507     {
4508       if (!_dbus_message_data_load (data, filename))
4509         {
4510           _dbus_warn ("Could not load message file %s\n",
4511                       _dbus_string_get_const_data (filename));
4512           goto failed;
4513         }
4514     }
4515
4516   retval = TRUE;
4517   
4518  failed:
4519
4520   return retval;
4521 }
4522
4523 /**
4524  * Tries loading the message in the given message file
4525  * and verifies that DBusMessageLoader can handle it.
4526  *
4527  * @param filename filename to load
4528  * @param is_raw if #TRUE load as binary data, if #FALSE as message builder language
4529  * @param expected_validity what the message has to be like to return #TRUE
4530  * @returns #TRUE if the message has the expected validity
4531  */
4532 dbus_bool_t
4533 dbus_internal_do_not_use_try_message_file (const DBusString    *filename,
4534                                            dbus_bool_t          is_raw,
4535                                            DBusMessageValidity  expected_validity)
4536 {
4537   DBusString data;
4538   dbus_bool_t retval;
4539
4540   retval = FALSE;
4541   
4542   if (!_dbus_string_init (&data))
4543     _dbus_assert_not_reached ("could not allocate string\n");
4544
4545   if (!dbus_internal_do_not_use_load_message_file (filename, is_raw,
4546                                                    &data))
4547     goto failed;
4548
4549   retval = dbus_internal_do_not_use_try_message_data (&data, expected_validity);
4550
4551  failed:
4552
4553   if (!retval)
4554     {
4555       if (_dbus_string_get_length (&data) > 0)
4556         _dbus_verbose_bytes_of_string (&data, 0,
4557                                        _dbus_string_get_length (&data));
4558       
4559       _dbus_warn ("Failed message loader test on %s\n",
4560                   _dbus_string_get_const_data (filename));
4561     }
4562   
4563   _dbus_string_free (&data);
4564
4565   return retval;
4566 }
4567
4568 /**
4569  * Tries loading the given message data.
4570  *
4571  *
4572  * @param data the message data
4573  * @param expected_validity what the message has to be like to return #TRUE
4574  * @returns #TRUE if the message has the expected validity
4575  */
4576 dbus_bool_t
4577 dbus_internal_do_not_use_try_message_data (const DBusString    *data,
4578                                            DBusMessageValidity  expected_validity)
4579 {
4580   DBusMessageLoader *loader;
4581   dbus_bool_t retval;
4582   int len;
4583   int i;
4584
4585   loader = NULL;
4586   retval = FALSE;
4587
4588   /* Write the data one byte at a time */
4589   
4590   loader = _dbus_message_loader_new ();
4591
4592   len = _dbus_string_get_length (data);
4593   for (i = 0; i < len; i++)
4594     {
4595       DBusString *buffer;
4596
4597       _dbus_message_loader_get_buffer (loader, &buffer);
4598       _dbus_string_append_byte (buffer,
4599                                 _dbus_string_get_byte (data, i));
4600       _dbus_message_loader_return_buffer (loader, buffer, 1);
4601     }
4602   
4603   if (!check_loader_results (loader, expected_validity))
4604     goto failed;
4605
4606   _dbus_message_loader_unref (loader);
4607   loader = NULL;
4608
4609   /* Write the data all at once */
4610   
4611   loader = _dbus_message_loader_new ();
4612
4613   {
4614     DBusString *buffer;
4615     
4616     _dbus_message_loader_get_buffer (loader, &buffer);
4617     _dbus_string_copy (data, 0, buffer,
4618                        _dbus_string_get_length (buffer));
4619     _dbus_message_loader_return_buffer (loader, buffer, 1);
4620   }
4621   
4622   if (!check_loader_results (loader, expected_validity))
4623     goto failed;
4624
4625   _dbus_message_loader_unref (loader);
4626   loader = NULL;  
4627
4628   /* Write the data 2 bytes at a time */
4629   
4630   loader = _dbus_message_loader_new ();
4631
4632   len = _dbus_string_get_length (data);
4633   for (i = 0; i < len; i += 2)
4634     {
4635       DBusString *buffer;
4636
4637       _dbus_message_loader_get_buffer (loader, &buffer);
4638       _dbus_string_append_byte (buffer,
4639                                 _dbus_string_get_byte (data, i));
4640       if ((i+1) < len)
4641         _dbus_string_append_byte (buffer,
4642                                   _dbus_string_get_byte (data, i+1));
4643       _dbus_message_loader_return_buffer (loader, buffer, 1);
4644     }
4645   
4646   if (!check_loader_results (loader, expected_validity))
4647     goto failed;
4648
4649   _dbus_message_loader_unref (loader);
4650   loader = NULL;
4651   
4652   retval = TRUE;
4653   
4654  failed:
4655   
4656   if (loader)
4657     _dbus_message_loader_unref (loader);
4658   
4659   return retval;
4660 }
4661
4662 static dbus_bool_t
4663 process_test_subdir (const DBusString          *test_base_dir,
4664                      const char                *subdir,
4665                      DBusMessageValidity        validity,
4666                      DBusForeachMessageFileFunc function,
4667                      void                      *user_data)
4668 {
4669   DBusString test_directory;
4670   DBusString filename;
4671   DBusDirIter *dir;
4672   dbus_bool_t retval;
4673   DBusError error;
4674
4675   retval = FALSE;
4676   dir = NULL;
4677   
4678   if (!_dbus_string_init (&test_directory))
4679     _dbus_assert_not_reached ("didn't allocate test_directory\n");
4680
4681   _dbus_string_init_const (&filename, subdir);
4682   
4683   if (!_dbus_string_copy (test_base_dir, 0,
4684                           &test_directory, 0))
4685     _dbus_assert_not_reached ("couldn't copy test_base_dir to test_directory");
4686   
4687   if (!_dbus_concat_dir_and_file (&test_directory, &filename))    
4688     _dbus_assert_not_reached ("couldn't allocate full path");
4689
4690   _dbus_string_free (&filename);
4691   if (!_dbus_string_init (&filename))
4692     _dbus_assert_not_reached ("didn't allocate filename string\n");
4693
4694   dbus_error_init (&error);
4695   dir = _dbus_directory_open (&test_directory, &error);
4696   if (dir == NULL)
4697     {
4698       _dbus_warn ("Could not open %s: %s\n",
4699                   _dbus_string_get_const_data (&test_directory),
4700                   error.message);
4701       dbus_error_free (&error);
4702       goto failed;
4703     }
4704
4705   printf ("Testing:\n");
4706   
4707  next:
4708   while (_dbus_directory_get_next_file (dir, &filename, &error))
4709     {
4710       DBusString full_path;
4711       dbus_bool_t is_raw;
4712       
4713       if (!_dbus_string_init (&full_path))
4714         _dbus_assert_not_reached ("couldn't init string");
4715
4716       if (!_dbus_string_copy (&test_directory, 0, &full_path, 0))
4717         _dbus_assert_not_reached ("couldn't copy dir to full_path");
4718
4719       if (!_dbus_concat_dir_and_file (&full_path, &filename))
4720         _dbus_assert_not_reached ("couldn't concat file to dir");
4721
4722       if (_dbus_string_ends_with_c_str (&filename, ".message"))
4723         is_raw = FALSE;
4724       else if (_dbus_string_ends_with_c_str (&filename, ".message-raw"))
4725         is_raw = TRUE;
4726       else
4727         {
4728           _dbus_verbose ("Skipping non-.message file %s\n",
4729                          _dbus_string_get_const_data (&filename));
4730           _dbus_string_free (&full_path);
4731           goto next;
4732         }
4733
4734       printf ("    %s\n",
4735               _dbus_string_get_const_data (&filename));
4736       
4737       _dbus_verbose (" expecting %s\n",
4738                      validity == _DBUS_MESSAGE_VALID ? "valid" :
4739                      (validity == _DBUS_MESSAGE_INVALID ? "invalid" :
4740                       (validity == _DBUS_MESSAGE_INCOMPLETE ? "incomplete" : "unknown")));
4741       
4742       if (! (*function) (&full_path, is_raw, validity, user_data))
4743         {
4744           _dbus_string_free (&full_path);
4745           goto failed;
4746         }
4747       else
4748         _dbus_string_free (&full_path);
4749     }
4750
4751   if (dbus_error_is_set (&error))
4752     {
4753       _dbus_warn ("Could not get next file in %s: %s\n",
4754                   _dbus_string_get_const_data (&test_directory),
4755                   error.message);
4756       dbus_error_free (&error);
4757       goto failed;
4758     }
4759     
4760   retval = TRUE;
4761   
4762  failed:
4763
4764   if (dir)
4765     _dbus_directory_close (dir);
4766   _dbus_string_free (&test_directory);
4767   _dbus_string_free (&filename);
4768
4769   return retval;
4770 }
4771                      
4772 /**
4773  * Runs the given function on every message file in the test suite.
4774  * The function should return #FALSE on test failure or fatal error.
4775  *
4776  * @param test_data_dir root dir of the test suite data files (top_srcdir/test/data)
4777  * @param func the function to run
4778  * @param user_data data for function
4779  * @returns #FALSE if there's a failure
4780  */
4781 dbus_bool_t
4782 dbus_internal_do_not_use_foreach_message_file (const char                *test_data_dir,
4783                                                DBusForeachMessageFileFunc func,
4784                                                void                      *user_data)
4785 {
4786   DBusString test_directory;
4787   dbus_bool_t retval;
4788
4789   retval = FALSE;
4790   
4791   _dbus_string_init_const (&test_directory, test_data_dir);
4792
4793   if (!process_test_subdir (&test_directory, "valid-messages",
4794                             _DBUS_MESSAGE_VALID, func, user_data))
4795     goto failed;
4796
4797   if (!process_test_subdir (&test_directory, "invalid-messages",
4798                             _DBUS_MESSAGE_INVALID, func, user_data))
4799     goto failed;
4800   
4801   if (!process_test_subdir (&test_directory, "incomplete-messages",
4802                             _DBUS_MESSAGE_INCOMPLETE, func, user_data))
4803     goto failed;
4804
4805   retval = TRUE;
4806   
4807  failed:
4808
4809   _dbus_string_free (&test_directory);
4810   
4811   return retval;
4812 }
4813
4814 static void
4815 verify_test_message (DBusMessage *message)
4816 {
4817   dbus_int32_t our_int;
4818   char *our_str;
4819   double our_double;
4820   dbus_bool_t our_bool;
4821   dbus_int32_t *our_int_array;
4822   dbus_uint32_t our_uint32;
4823   int our_int_array_len;
4824   DBusMessageIter iter, dict;
4825   DBusError error;
4826
4827   dbus_message_iter_init (message, &iter);
4828
4829   dbus_error_init (&error);
4830   if (!dbus_message_iter_get_args (&iter, &error,
4831                                    DBUS_TYPE_INT32, &our_int,
4832                                    DBUS_TYPE_STRING, &our_str,
4833                                    DBUS_TYPE_DOUBLE, &our_double,
4834                                    DBUS_TYPE_BOOLEAN, &our_bool,
4835                                    DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &our_int_array, &our_int_array_len,
4836                                    0))
4837     {
4838       _dbus_verbose ("error: %s - %s\n", error.name, (error.message != NULL)?error.message: "no message");
4839       _dbus_assert_not_reached ("Could not get arguments");
4840     }
4841
4842   if (our_int != -0x12345678)
4843     _dbus_assert_not_reached ("integers differ!");
4844
4845   if (our_double != 3.14159)
4846     _dbus_assert_not_reached ("doubles differ!");
4847
4848   if (strcmp (our_str, "Test string") != 0)
4849     _dbus_assert_not_reached ("strings differ!");
4850   dbus_free (our_str);
4851
4852   if (!our_bool)
4853     _dbus_assert_not_reached ("booleans differ");
4854
4855   if (our_int_array_len != 4 ||
4856       our_int_array[0] != 0x12345678 ||
4857       our_int_array[1] != 0x23456781 ||
4858       our_int_array[2] != 0x34567812 ||
4859       our_int_array[3] != 0x45678123)
4860     _dbus_assert_not_reached ("array differ");
4861   dbus_free (our_int_array);
4862
4863   if (!dbus_message_iter_next (&iter))
4864     _dbus_assert_not_reached ("Reached end of arguments");
4865
4866   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_DICT)
4867     _dbus_assert_not_reached ("not dict type");
4868      
4869   if (!dbus_message_iter_init_dict_iterator (&iter, &dict))
4870     _dbus_assert_not_reached ("dict iter failed");
4871
4872   our_str = dbus_message_iter_get_dict_key (&dict);
4873   if (our_str == NULL || strcmp (our_str, "test") != 0)
4874     _dbus_assert_not_reached ("wrong dict key");
4875   dbus_free (our_str);
4876
4877   if (dbus_message_iter_get_arg_type (&dict) != DBUS_TYPE_UINT32)
4878     {
4879       _dbus_verbose ("dict entry type: %d\n", dbus_message_iter_get_arg_type (&dict));
4880       _dbus_assert_not_reached ("wrong dict entry type");
4881     }
4882
4883   if ((our_uint32 = dbus_message_iter_get_uint32 (&dict)) != 0xDEADBEEF)
4884     {
4885       _dbus_verbose ("dict entry val: %x\n", our_uint32);
4886       _dbus_assert_not_reached ("wrong dict entry value");
4887     }
4888
4889   if (dbus_message_iter_next (&dict))
4890     _dbus_assert_not_reached ("Didn't reach end of dict");
4891   
4892   if (!dbus_message_iter_next (&iter))
4893     _dbus_assert_not_reached ("Reached end of arguments");
4894   
4895   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_UINT32)
4896     _dbus_assert_not_reached ("wrong type after dict");
4897   
4898   if (dbus_message_iter_get_uint32 (&iter) != 0xCAFEBABE)
4899     _dbus_assert_not_reached ("wrong value after dict");
4900
4901   if (dbus_message_iter_next (&iter))
4902     _dbus_assert_not_reached ("Didn't reach end of arguments");
4903 }
4904
4905 /**
4906  * @ingroup DBusMessageInternals
4907  * Unit test for DBusMessage.
4908  *
4909  * @returns #TRUE on success.
4910  */
4911 dbus_bool_t
4912 _dbus_message_test (const char *test_data_dir)
4913 {
4914   DBusMessage *message;
4915   DBusMessageLoader *loader;
4916   DBusMessageIter iter, child_iter, child_iter2, child_iter3;
4917   int i;
4918   const char *data;
4919   DBusMessage *copy;
4920   const char *name1;
4921   const char *name2;
4922   const dbus_uint32_t our_int32_array[] = { 0x12345678, 0x23456781, 0x34567812, 0x45678123 };
4923
4924   _dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
4925
4926   /* Test the vararg functions */
4927   message = dbus_message_new ("org.freedesktop.DBus.Test", "testMessage");
4928   _dbus_message_set_serial (message, 1);
4929   dbus_message_append_args (message,
4930                             DBUS_TYPE_INT32, -0x12345678,
4931                             DBUS_TYPE_STRING, "Test string",
4932                             DBUS_TYPE_DOUBLE, 3.14159,
4933                             DBUS_TYPE_BOOLEAN, TRUE,
4934                             DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, our_int32_array, 4,
4935                             0);
4936   
4937   dbus_message_append_iter_init (message, &iter);
4938   dbus_message_iter_append_dict (&iter, &child_iter);
4939   dbus_message_iter_append_dict_key (&child_iter, "test");
4940   dbus_message_iter_append_uint32 (&child_iter, 0xDEADBEEF);
4941   dbus_message_iter_append_uint32 (&iter, 0xCAFEBABE);
4942   
4943   _dbus_verbose_bytes_of_string (&message->header, 0,
4944                                  _dbus_string_get_length (&message->header));
4945   _dbus_verbose_bytes_of_string (&message->body, 0,
4946                                  _dbus_string_get_length (&message->body));
4947
4948   verify_test_message (message);
4949
4950   copy = dbus_message_copy (message);
4951   
4952   _dbus_assert (message->client_serial == copy->client_serial);
4953   _dbus_assert (message->reply_serial == copy->reply_serial);
4954   _dbus_assert (message->header_padding == copy->header_padding);
4955   
4956   _dbus_assert (_dbus_string_get_length (&message->header) ==
4957                 _dbus_string_get_length (&copy->header));
4958
4959   _dbus_assert (_dbus_string_get_length (&message->body) ==
4960                 _dbus_string_get_length (&copy->body));
4961
4962   verify_test_message (copy);
4963
4964   name1 = dbus_message_get_name (message);
4965   name2 = dbus_message_get_name (copy);
4966
4967   _dbus_assert (strcmp (name1, name2) == 0);
4968   
4969   dbus_message_unref (message);
4970   dbus_message_unref (copy);
4971   
4972   message = dbus_message_new ("org.freedesktop.DBus.Test", "testMessage");
4973   _dbus_message_set_serial (message, 1);
4974   dbus_message_set_reply_serial (message, 0x12345678);
4975
4976   dbus_message_append_iter_init (message, &iter);
4977   dbus_message_iter_append_string (&iter, "Test string");
4978   dbus_message_iter_append_int32 (&iter, -0x12345678);
4979   dbus_message_iter_append_uint32 (&iter, 0xedd1e);
4980   dbus_message_iter_append_double (&iter, 3.14159);
4981
4982   dbus_message_iter_append_array (&iter, &child_iter, DBUS_TYPE_DOUBLE);
4983   dbus_message_iter_append_double (&child_iter, 1.5);
4984   dbus_message_iter_append_double (&child_iter, 2.5);
4985
4986   /* dict */
4987   dbus_message_iter_append_dict (&iter, &child_iter);
4988   dbus_message_iter_append_dict_key (&child_iter, "test");
4989   dbus_message_iter_append_uint32 (&child_iter, 0xDEADBEEF);
4990
4991   /* array of array of int32  (in dict) */
4992   dbus_message_iter_append_dict_key (&child_iter, "array");
4993   dbus_message_iter_append_array (&child_iter, &child_iter2, DBUS_TYPE_ARRAY);
4994   dbus_message_iter_append_array (&child_iter2, &child_iter3, DBUS_TYPE_INT32);
4995   dbus_message_iter_append_int32 (&child_iter3, 0x12345678);
4996   dbus_message_iter_append_int32 (&child_iter3, 0x23456781);
4997   _dbus_warn ("next call expected to fail with wrong array type\n");
4998   _dbus_assert (!dbus_message_iter_append_array (&child_iter2, &child_iter3, DBUS_TYPE_UINT32));
4999   dbus_message_iter_append_array (&child_iter2, &child_iter3, DBUS_TYPE_INT32);
5000   dbus_message_iter_append_int32 (&child_iter3, 0x34567812);
5001   dbus_message_iter_append_int32 (&child_iter3, 0x45678123);
5002   dbus_message_iter_append_int32 (&child_iter3, 0x56781234);
5003   
5004   dbus_message_iter_append_byte (&iter, 0xF0);
5005
5006   dbus_message_iter_append_nil (&iter);
5007
5008   dbus_message_iter_append_named (&iter, "named",
5009                                   "data", 5);
5010   
5011   message_iter_test (message);
5012
5013   /* Message loader test */
5014   _dbus_message_lock (message);
5015   loader = _dbus_message_loader_new ();
5016
5017   /* Write the header data one byte at a time */
5018   data = _dbus_string_get_const_data (&message->header);
5019   for (i = 0; i < _dbus_string_get_length (&message->header); i++)
5020     {
5021       DBusString *buffer;
5022
5023       _dbus_message_loader_get_buffer (loader, &buffer);
5024       _dbus_string_append_byte (buffer, data[i]);
5025       _dbus_message_loader_return_buffer (loader, buffer, 1);
5026     }
5027
5028   /* Write the body data one byte at a time */
5029   data = _dbus_string_get_const_data (&message->body);
5030   for (i = 0; i < _dbus_string_get_length (&message->body); i++)
5031     {
5032       DBusString *buffer;
5033
5034       _dbus_message_loader_get_buffer (loader, &buffer);
5035       _dbus_string_append_byte (buffer, data[i]);
5036       _dbus_message_loader_return_buffer (loader, buffer, 1);
5037     }
5038
5039   dbus_message_unref (message);
5040
5041   /* Now pop back the message */
5042   if (!_dbus_message_loader_queue_messages (loader))
5043     _dbus_assert_not_reached ("no memory to queue messages");
5044   
5045   if (_dbus_message_loader_get_is_corrupted (loader))
5046     _dbus_assert_not_reached ("message loader corrupted");
5047   
5048   message = _dbus_message_loader_pop_message (loader);
5049   if (!message)
5050     _dbus_assert_not_reached ("received a NULL message");
5051
5052   if (dbus_message_get_reply_serial (message) != 0x12345678)
5053     _dbus_assert_not_reached ("reply serial fields differ");
5054   
5055   message_iter_test (message);
5056   
5057   dbus_message_unref (message);
5058   _dbus_message_loader_unref (loader);
5059
5060   /* Now load every message in test_data_dir if we have one */
5061   if (test_data_dir == NULL)
5062     return TRUE;
5063
5064   return dbus_internal_do_not_use_foreach_message_file (test_data_dir,
5065                                                         (DBusForeachMessageFileFunc)
5066                                                         dbus_internal_do_not_use_try_message_file,
5067                                                         NULL);
5068 }
5069
5070 #endif /* DBUS_BUILD_TESTS */