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