Main Page   Modules   Data Structures   File List   Data Fields   Related Pages  

dbus-message.c

00001 /* -*- mode: C; c-file-style: "gnu" -*- */
00002 /* dbus-message.c  DBusMessage object
00003  *
00004  * Copyright (C) 2002, 2003  Red Hat Inc.
00005  * Copyright (C) 2002, 2003  CodeFactory AB
00006  *
00007  * Licensed under the Academic Free License version 1.2
00008  * 
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  * 
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022  *
00023  */
00024 
00025 #include "dbus-internals.h"
00026 #include "dbus-marshal.h"
00027 #include "dbus-message.h"
00028 #include "dbus-message-internal.h"
00029 #include "dbus-memory.h"
00030 #include "dbus-list.h"
00031 #include "dbus-message-builder.h"
00032 #include "dbus-dataslot.h"
00033 #include <string.h>
00034 
00045 enum
00046 {
00047   FIELD_HEADER_LENGTH,
00048   FIELD_BODY_LENGTH,
00049   FIELD_CLIENT_SERIAL,
00050   FIELD_NAME,
00051   FIELD_SERVICE,
00052   FIELD_SENDER,
00053   FIELD_REPLY_SERIAL,
00054 
00055   FIELD_LAST
00056 };
00057 
00058 static dbus_bool_t field_is_named[FIELD_LAST] =
00059 {
00060   FALSE, /* FIELD_HEADER_LENGTH */
00061   FALSE, /* FIELD_BODY_LENGTH */
00062   FALSE, /* FIELD_CLIENT_SERIAL */
00063   TRUE,  /* FIELD_NAME */
00064   TRUE,  /* FIELD_SERVICE */
00065   TRUE,  /* FIELD_SENDER */
00066   TRUE   /* FIELD_REPLY_SERIAL */
00067 };
00068 
00069 typedef struct
00070 {
00071   int offset; 
00074 } HeaderField;
00075 
00083 struct DBusMessage
00084 {
00085   DBusAtomic refcount; 
00087   DBusString header; 
00092   HeaderField header_fields[FIELD_LAST]; 
00096   dbus_uint32_t client_serial; 
00097   dbus_uint32_t reply_serial;  
00099   int header_padding; 
00101   DBusString body;   
00103   char byte_order; 
00105   DBusList *size_counters;   
00106   long size_counter_delta;   
00108   dbus_uint32_t changed_stamp; 
00110   unsigned int locked : 1; 
00112   DBusDataSlotList slot_list;   
00113 };
00114 
00115 enum {
00116   DBUS_MESSAGE_ITER_TYPE_MESSAGE,
00117   DBUS_MESSAGE_ITER_TYPE_ARRAY,
00118   DBUS_MESSAGE_ITER_TYPE_DICT
00119 };
00120 
00122 typedef struct DBusMessageRealIter DBusMessageRealIter;
00123 
00129 struct DBusMessageRealIter
00130 {
00131   DBusMessageRealIter *parent_iter; 
00132   DBusMessage *message; 
00133   dbus_uint32_t changed_stamp; 
00135   /* This is an int instead of an enum to get a guaranteed size for the dummy: */
00136   int type; 
00138   int pos; 
00139   int end; 
00140   int container_start; 
00141   int container_length_pos; 
00143   int wrote_dict_key; 
00145   int array_type_pos; 
00146   int array_type_done; 
00147 };
00148 
00159 void
00160 _dbus_message_get_network_data (DBusMessage          *message,
00161                                 const DBusString    **header,
00162                                 const DBusString    **body)
00163 {
00164   _dbus_assert (message->locked);
00165   
00166   *header = &message->header;
00167   *body = &message->body;
00168 }
00169 
00170 static void
00171 clear_header_padding (DBusMessage *message)
00172 {
00173   _dbus_string_shorten (&message->header,
00174                         message->header_padding);
00175   message->header_padding = 0;
00176 }              
00177 
00178 static dbus_bool_t
00179 append_header_padding (DBusMessage *message)
00180 {
00181   int old_len;
00182   old_len = _dbus_string_get_length (&message->header);
00183   if (!_dbus_string_align_length (&message->header, 8))
00184     return FALSE;
00185 
00186   message->header_padding = _dbus_string_get_length (&message->header) - old_len;
00187 
00188   return TRUE;
00189 }
00190 
00191 static void
00192 adjust_field_offsets (DBusMessage *message,
00193                       int          offsets_after,
00194                       int          delta)
00195 {
00196   int i;
00197 
00198   if (delta == 0)
00199     return;
00200   
00201   i = 0;
00202   while (i < FIELD_LAST)
00203     {
00204       if (message->header_fields[i].offset > offsets_after)
00205         message->header_fields[i].offset += delta;
00206 
00207       ++i;
00208     }
00209 }
00210 
00211 #ifdef DBUS_BUILD_TESTS
00212 /* tests-only until it's actually used */
00213 static dbus_int32_t
00214 get_int_field (DBusMessage *message,
00215                int          field)
00216 {
00217   int offset;
00218 
00219   _dbus_assert (field < FIELD_LAST);
00220   
00221   offset = message->header_fields[field].offset;
00222   
00223   if (offset < 0)
00224     return -1; /* useless if -1 is a valid value of course */
00225   
00226   return _dbus_demarshal_int32 (&message->header,
00227                                 message->byte_order,
00228                                 offset,
00229                                 NULL);
00230 }
00231 #endif
00232 
00233 static dbus_uint32_t
00234 get_uint_field (DBusMessage *message,
00235                 int          field)
00236 {
00237   int offset;
00238   
00239   _dbus_assert (field < FIELD_LAST);
00240   
00241   offset = message->header_fields[field].offset;
00242   
00243   if (offset < 0)
00244     return -1; /* useless if -1 is a valid value of course */
00245   
00246   return _dbus_demarshal_uint32 (&message->header,
00247                                  message->byte_order,
00248                                  offset,
00249                                  NULL);
00250 }
00251 
00252 static const char*
00253 get_string_field (DBusMessage *message,
00254                   int          field,
00255                   int         *len)
00256 {
00257   int offset;
00258   const char *data;
00259 
00260   offset = message->header_fields[field].offset;
00261 
00262   _dbus_assert (field < FIELD_LAST);
00263   
00264   if (offset < 0)
00265     return NULL;
00266 
00267   /* offset points to string length, string data follows it */
00268   /* FIXME _dbus_demarshal_const_string() that returned
00269    * a reference to the string plus its len might be nice.
00270    */
00271   
00272   if (len)
00273     *len = _dbus_demarshal_uint32 (&message->header,
00274                                    message->byte_order,
00275                                    offset,
00276                                    NULL);
00277 
00278   data = _dbus_string_get_const_data (&message->header);
00279   
00280   return data + (offset + 4); 
00281 }
00282 
00283 #ifdef DBUS_BUILD_TESTS
00284 static dbus_bool_t
00285 append_int_field (DBusMessage *message,
00286                   int          field,
00287                   const char  *name,
00288                   int          value)
00289 {
00290   int orig_len;
00291 
00292   _dbus_assert (!message->locked);
00293 
00294   clear_header_padding (message);
00295   
00296   orig_len = _dbus_string_get_length (&message->header);
00297   
00298   if (!_dbus_string_align_length (&message->header, 4))
00299     goto failed;  
00300   
00301   if (!_dbus_string_append_len (&message->header, name, 4))
00302     goto failed;
00303 
00304   if (!_dbus_string_append_byte (&message->header, DBUS_TYPE_INT32))
00305     goto failed;
00306 
00307   if (!_dbus_string_align_length (&message->header, 4))
00308     goto failed;
00309   
00310   message->header_fields[field].offset =
00311     _dbus_string_get_length (&message->header);
00312   
00313   if (!_dbus_marshal_int32 (&message->header, message->byte_order,
00314                             value))
00315     goto failed;
00316 
00317   if (!append_header_padding (message))
00318     goto failed;
00319   
00320   return TRUE;
00321   
00322  failed:
00323   message->header_fields[field].offset = -1;
00324   _dbus_string_set_length (&message->header, orig_len);
00325 
00326   /* this must succeed because it was allocated on function entry and
00327    * DBusString doesn't ever realloc smaller
00328    */
00329   if (!append_header_padding (message))
00330     _dbus_assert_not_reached ("failed to reappend header padding");
00331   return FALSE;
00332 }
00333 #endif
00334 
00335 static dbus_bool_t
00336 append_uint_field (DBusMessage *message,
00337                    int          field,
00338                    const char  *name,
00339                    int          value)
00340 {
00341   int orig_len;
00342 
00343   _dbus_assert (!message->locked);
00344 
00345   clear_header_padding (message);
00346   
00347   orig_len = _dbus_string_get_length (&message->header);
00348   
00349   if (!_dbus_string_align_length (&message->header, 4))
00350     goto failed;  
00351   
00352   if (!_dbus_string_append_len (&message->header, name, 4))
00353     goto failed;
00354 
00355   if (!_dbus_string_append_byte (&message->header, DBUS_TYPE_UINT32))
00356     goto failed;
00357 
00358   if (!_dbus_string_align_length (&message->header, 4))
00359     goto failed;
00360   
00361   message->header_fields[field].offset =
00362     _dbus_string_get_length (&message->header);
00363   
00364   if (!_dbus_marshal_uint32 (&message->header, message->byte_order,
00365                              value))
00366     goto failed;
00367 
00368   if (!append_header_padding (message))
00369     goto failed;
00370   
00371   return TRUE;
00372   
00373  failed:
00374   message->header_fields[field].offset = -1;
00375   _dbus_string_set_length (&message->header, orig_len);
00376 
00377   /* this must succeed because it was allocated on function entry and
00378    * DBusString doesn't ever realloc smaller
00379    */
00380   if (!append_header_padding (message))
00381     _dbus_assert_not_reached ("failed to reappend header padding");
00382   return FALSE;
00383 }
00384 
00385 static dbus_bool_t
00386 append_string_field (DBusMessage *message,
00387                      int          field,
00388                      const char  *name,
00389                      const char  *value)
00390 {
00391   int orig_len;
00392 
00393   _dbus_assert (!message->locked);
00394 
00395   clear_header_padding (message);
00396   
00397   orig_len = _dbus_string_get_length (&message->header);
00398 
00399   if (!_dbus_string_align_length (&message->header, 4))
00400     goto failed;
00401   
00402   if (!_dbus_string_append_len (&message->header, name, 4))
00403     goto failed;
00404   
00405   if (!_dbus_string_append_byte (&message->header, DBUS_TYPE_STRING))
00406     goto failed;
00407 
00408   if (!_dbus_string_align_length (&message->header, 4))
00409     goto failed;
00410   
00411   message->header_fields[field].offset =
00412     _dbus_string_get_length (&message->header);
00413   
00414   if (!_dbus_marshal_string (&message->header, message->byte_order,
00415                              value))
00416     goto failed;
00417 
00418   if (!append_header_padding (message))
00419     goto failed;
00420   
00421   return TRUE;
00422   
00423  failed:
00424   message->header_fields[field].offset = -1;
00425   _dbus_string_set_length (&message->header, orig_len);
00426 
00427   /* this must succeed because it was allocated on function entry and
00428    * DBusString doesn't ever realloc smaller
00429    */
00430   if (!append_header_padding (message))
00431     _dbus_assert_not_reached ("failed to reappend header padding");
00432   
00433   return FALSE;
00434 }
00435 
00436 #ifdef DBUS_BUILD_TESTS
00437 /* This isn't used, but building it when tests are enabled just to
00438  * keep it compiling if we need it in future
00439  */
00440 static void
00441 delete_int_or_uint_field (DBusMessage *message,
00442                           int          field)
00443 {
00444   int offset = message->header_fields[field].offset;
00445 
00446   _dbus_assert (!message->locked);
00447   _dbus_assert (field_is_named[field]);
00448   
00449   if (offset < 0)
00450     return;  
00451 
00452   clear_header_padding (message);
00453   
00454   /* The field typecode and name take up 8 bytes */
00455   _dbus_string_delete (&message->header,
00456                        offset - 8,
00457                        12);
00458 
00459   message->header_fields[field].offset = -1;
00460   
00461   adjust_field_offsets (message,
00462                         offset - 8,
00463                         - 12);
00464 
00465   append_header_padding (message);
00466 }
00467 #endif
00468 
00469 static void
00470 delete_string_field (DBusMessage *message,
00471                      int          field)
00472 {
00473   int offset = message->header_fields[field].offset;
00474   int len;
00475   int delete_len;
00476   
00477   _dbus_assert (!message->locked);
00478   _dbus_assert (field_is_named[field]);
00479   
00480   if (offset < 0)
00481     return;
00482 
00483   clear_header_padding (message);
00484   
00485   get_string_field (message, field, &len);
00486   
00487   /* The field typecode and name take up 8 bytes, and the nul
00488    * termination is 1 bytes, string length integer is 4 bytes
00489    */
00490   delete_len = 8 + 4 + 1 + len;
00491   
00492   _dbus_string_delete (&message->header,
00493                        offset - 8,
00494                        delete_len);
00495 
00496   message->header_fields[field].offset = -1;
00497   
00498   adjust_field_offsets (message,
00499                         offset - 8,
00500                         - delete_len);
00501 
00502   append_header_padding (message);
00503 }
00504 
00505 #ifdef DBUS_BUILD_TESTS
00506 static dbus_bool_t
00507 set_int_field (DBusMessage *message,
00508                int          field,
00509                int          value)
00510 {
00511   int offset = message->header_fields[field].offset;
00512 
00513   _dbus_assert (!message->locked);
00514   
00515   if (offset < 0)
00516     {
00517       /* need to append the field */
00518 
00519       switch (field)
00520         {
00521         default:
00522           _dbus_assert_not_reached ("appending an int field we don't support appending");
00523           return FALSE;
00524         }
00525     }
00526   else
00527     {
00528       _dbus_marshal_set_int32 (&message->header,
00529                                message->byte_order,
00530                                offset, value);
00531 
00532       return TRUE;
00533     }
00534 }
00535 #endif
00536 
00537 static dbus_bool_t
00538 set_uint_field (DBusMessage  *message,
00539                 int           field,
00540                 dbus_uint32_t value)
00541 {
00542   int offset = message->header_fields[field].offset;
00543 
00544   _dbus_assert (!message->locked);
00545   
00546   if (offset < 0)
00547     {
00548       /* need to append the field */
00549 
00550       switch (field)
00551         {
00552         case FIELD_REPLY_SERIAL:
00553           return append_uint_field (message, field,
00554                                     DBUS_HEADER_FIELD_REPLY,
00555                                     value);
00556         default:
00557           _dbus_assert_not_reached ("appending a uint field we don't support appending");
00558           return FALSE;
00559         }
00560     }
00561   else
00562     {
00563       _dbus_marshal_set_uint32 (&message->header,
00564                                 message->byte_order,
00565                                 offset, value);
00566 
00567       return TRUE;
00568     }
00569 }
00570 
00571 static dbus_bool_t
00572 set_string_field (DBusMessage *message,
00573                   int          field,
00574                   const char  *value)
00575 {
00576   int offset = message->header_fields[field].offset;
00577 
00578   _dbus_assert (!message->locked);
00579   _dbus_assert (value != NULL);
00580   
00581   if (offset < 0)
00582     {      
00583       /* need to append the field */
00584 
00585       switch (field)
00586         {
00587         case FIELD_SENDER:
00588           return append_string_field (message, field,
00589                                       DBUS_HEADER_FIELD_SENDER,
00590                                       value);
00591         default:
00592           _dbus_assert_not_reached ("appending a string field we don't support appending");
00593           return FALSE;
00594         }
00595     }
00596   else
00597     {
00598       DBusString v;
00599       int old_len;
00600       int new_len;
00601       int len;
00602       
00603       clear_header_padding (message);
00604       
00605       old_len = _dbus_string_get_length (&message->header);
00606 
00607       len = strlen (value);
00608       
00609       _dbus_string_init_const_len (&v, value,
00610                                    len + 1); /* include nul */
00611       if (!_dbus_marshal_set_string (&message->header,
00612                                      message->byte_order,
00613                                      offset, &v,
00614                                      len))
00615         goto failed;
00616       
00617       new_len = _dbus_string_get_length (&message->header);
00618 
00619       adjust_field_offsets (message,
00620                             offset,
00621                             new_len - old_len);
00622 
00623       if (!append_header_padding (message))
00624         goto failed;
00625       
00626       return TRUE;
00627 
00628     failed:
00629       /* this must succeed because it was allocated on function entry and
00630        * DBusString doesn't ever realloc smaller
00631        */
00632       if (!append_header_padding (message))
00633         _dbus_assert_not_reached ("failed to reappend header padding");
00634 
00635       return FALSE;
00636     }
00637 }
00638 
00646 void
00647 _dbus_message_set_serial (DBusMessage  *message,
00648                           dbus_int32_t  serial)
00649 {
00650   _dbus_assert (!message->locked);
00651   _dbus_assert (dbus_message_get_serial (message) == 0);
00652   
00653   set_uint_field (message, FIELD_CLIENT_SERIAL,
00654                   serial);
00655   message->client_serial = serial;
00656 }
00657 
00666 dbus_bool_t
00667 dbus_message_set_reply_serial (DBusMessage   *message,
00668                                dbus_uint32_t  reply_serial)
00669 {
00670   _dbus_assert (!message->locked);
00671 
00672   if (set_uint_field (message, FIELD_REPLY_SERIAL,
00673                       reply_serial))
00674     {
00675       message->reply_serial = reply_serial;
00676       return TRUE;
00677     }
00678   else
00679     return FALSE;
00680 }
00681 
00690 dbus_uint32_t
00691 dbus_message_get_serial (DBusMessage *message)
00692 {
00693   return message->client_serial;
00694 }
00695 
00703 dbus_uint32_t
00704 dbus_message_get_reply_serial  (DBusMessage *message)
00705 {
00706   return message->reply_serial;
00707 }
00708 
00721 void
00722 _dbus_message_add_size_counter_link (DBusMessage  *message,
00723                                      DBusList     *link)
00724 {
00725   /* right now we don't recompute the delta when message
00726    * size changes, and that's OK for current purposes
00727    * I think, but could be important to change later.
00728    * Do recompute it whenever there are no outstanding counters,
00729    * since it's basically free.
00730    */
00731   if (message->size_counters == NULL)
00732     {
00733       message->size_counter_delta =
00734         _dbus_string_get_length (&message->header) +
00735         _dbus_string_get_length (&message->body);
00736       
00737 #if 0
00738       _dbus_verbose ("message has size %ld\n",
00739                      message->size_counter_delta);
00740 #endif
00741     }
00742   
00743   _dbus_list_append_link (&message->size_counters, link);
00744   
00745   _dbus_counter_adjust (link->data, message->size_counter_delta);
00746 }
00747 
00757 dbus_bool_t
00758 _dbus_message_add_size_counter (DBusMessage *message,
00759                                 DBusCounter *counter)
00760 {
00761   DBusList *link;
00762 
00763   link = _dbus_list_alloc_link (counter);
00764   if (link == NULL)
00765     return FALSE;
00766 
00767   _dbus_counter_ref (counter);
00768   _dbus_message_add_size_counter_link (message, link);
00769 
00770   return TRUE;
00771 }
00772 
00781 void
00782 _dbus_message_remove_size_counter (DBusMessage  *message,
00783                                    DBusCounter  *counter,
00784                                    DBusList    **link_return)
00785 {
00786   DBusList *link;
00787 
00788   link = _dbus_list_find_last (&message->size_counters,
00789                                counter);
00790   _dbus_assert (link != NULL);
00791 
00792   _dbus_list_unlink (&message->size_counters,
00793                      link);
00794   if (link_return)
00795     *link_return = link;
00796   else
00797     _dbus_list_free_link (link);
00798 
00799   _dbus_counter_adjust (counter, message->size_counter_delta);
00800 
00801   _dbus_counter_unref (counter);
00802 }
00803 
00804 static dbus_bool_t
00805 dbus_message_create_header (DBusMessage *message,
00806                             const char  *name,
00807                             const char  *service)
00808 {
00809   unsigned int flags;
00810   
00811   if (!_dbus_string_append_byte (&message->header, message->byte_order))
00812     return FALSE;
00813 
00814   flags = 0;
00815   if (!_dbus_string_append_byte (&message->header, flags))
00816     return FALSE;
00817 
00818   if (!_dbus_string_append_byte (&message->header, DBUS_MAJOR_PROTOCOL_VERSION))
00819     return FALSE;
00820 
00821   if (!_dbus_string_append_byte (&message->header, 0))
00822     return FALSE;
00823 
00824   message->header_fields[FIELD_HEADER_LENGTH].offset = 4;
00825   if (!_dbus_marshal_uint32 (&message->header, message->byte_order, 0))
00826     return FALSE;
00827 
00828   message->header_fields[FIELD_BODY_LENGTH].offset = 8;
00829   if (!_dbus_marshal_uint32 (&message->header, message->byte_order, 0))
00830     return FALSE;
00831 
00832   message->header_fields[FIELD_CLIENT_SERIAL].offset = 12;
00833   if (!_dbus_marshal_int32 (&message->header, message->byte_order, -1))
00834     return FALSE;
00835   
00836   /* Marshal message service */
00837   if (service != NULL)
00838     {
00839       if (!append_string_field (message,
00840                                 FIELD_SERVICE,
00841                                 DBUS_HEADER_FIELD_SERVICE,
00842                                 service))
00843         return FALSE;
00844     }
00845 
00846   _dbus_assert (name != NULL);
00847   if (!append_string_field (message,
00848                             FIELD_NAME,
00849                             DBUS_HEADER_FIELD_NAME,
00850                             name))
00851     return FALSE;
00852   
00853   return TRUE;
00854 }
00855 
00865 void
00866 _dbus_message_lock (DBusMessage  *message)
00867 {
00868   if (!message->locked)
00869     {
00870       /* Fill in our lengths */
00871       set_uint_field (message,
00872                       FIELD_HEADER_LENGTH,
00873                       _dbus_string_get_length (&message->header));
00874 
00875       set_uint_field (message,
00876                       FIELD_BODY_LENGTH,
00877                       _dbus_string_get_length (&message->body));
00878 
00879       message->locked = TRUE;
00880     }
00881 }
00882 
00905 static DBusMessage*
00906 dbus_message_new_empty_header (void)
00907 {
00908   DBusMessage *message;
00909   int i;
00910   
00911   message = dbus_new0 (DBusMessage, 1);
00912   if (message == NULL)
00913     return NULL;
00914   
00915   message->refcount.value = 1;
00916   message->byte_order = DBUS_COMPILER_BYTE_ORDER;
00917   message->client_serial = 0;
00918   message->reply_serial = 0;
00919 
00920   _dbus_data_slot_list_init (&message->slot_list);
00921   
00922   i = 0;
00923   while (i < FIELD_LAST)
00924     {
00925       message->header_fields[i].offset = -1;
00926       ++i;
00927     }
00928   
00929   if (!_dbus_string_init_preallocated (&message->header, 64))
00930     {
00931       dbus_free (message);
00932       return NULL;
00933     }
00934   
00935   if (!_dbus_string_init_preallocated (&message->body, 64))
00936     {
00937       _dbus_string_free (&message->header);
00938       dbus_free (message);
00939       return NULL;
00940     }
00941   
00942   return message;
00943 }
00944 
00945 
00957 DBusMessage*
00958 dbus_message_new (const char *name,
00959                   const char *destination_service)                
00960 {
00961   DBusMessage *message;
00962 
00963   _dbus_return_val_if_fail (name != NULL, NULL);
00964   
00965   message = dbus_message_new_empty_header ();
00966   if (message == NULL)
00967     return NULL;
00968   
00969   if (!dbus_message_create_header (message, name, destination_service))
00970     {
00971       dbus_message_unref (message);
00972       return NULL;
00973     }
00974   
00975   return message;
00976 }
00977 
00988 DBusMessage*
00989 dbus_message_new_reply (DBusMessage *original_message)
00990 {
00991   DBusMessage *message;
00992   const char *sender, *name;
00993 
00994   _dbus_return_val_if_fail (original_message != NULL, NULL);
00995   
00996   sender = get_string_field (original_message,
00997                              FIELD_SENDER, NULL);
00998   name = get_string_field (original_message,
00999                            FIELD_NAME, NULL);
01000 
01001   /* sender is allowed to be null here in peer-to-peer case */
01002   
01003   message = dbus_message_new (name, sender);
01004   
01005   if (message == NULL)
01006     return NULL;
01007 
01008   if (!dbus_message_set_reply_serial (message,
01009                                       dbus_message_get_serial (original_message)))
01010     {
01011       dbus_message_unref (message);
01012       return NULL;
01013     }
01014 
01015   return message;
01016 }
01017 
01026 DBusMessage*
01027 dbus_message_new_error_reply (DBusMessage *original_message,
01028                               const char  *error_name,
01029                               const char  *error_message)
01030 {
01031   DBusMessage *message;
01032   const char *sender;
01033   DBusMessageIter iter;
01034 
01035   _dbus_return_val_if_fail (original_message != NULL, NULL);
01036   _dbus_return_val_if_fail (error_name != NULL, NULL);
01037   
01038   sender = get_string_field (original_message,
01039                              FIELD_SENDER, NULL);
01040 
01041   /* sender may be NULL for non-message-bus case or
01042    * when the message bus is dealing with an unregistered
01043    * connection.
01044    */
01045   
01046   message = dbus_message_new (error_name, sender);
01047   
01048   if (message == NULL)
01049     return NULL;
01050 
01051   if (!dbus_message_set_reply_serial (message,
01052                                       dbus_message_get_serial (original_message)))
01053     {
01054       dbus_message_unref (message);
01055       return NULL;
01056     }
01057 
01058   if (error_message != NULL)
01059     {
01060       dbus_message_append_iter_init (message, &iter);
01061       if (!dbus_message_iter_append_string (&iter, error_message))
01062         {
01063           dbus_message_unref (message);
01064           return NULL;
01065         }
01066     }
01067 
01068   dbus_message_set_is_error (message, TRUE);
01069   
01070   return message;
01071 }
01072 
01080 DBusMessage *
01081 dbus_message_copy (const DBusMessage *message)
01082 {
01083   DBusMessage *retval;
01084   int i;
01085 
01086   _dbus_return_val_if_fail (message != NULL, NULL);
01087   
01088   retval = dbus_new0 (DBusMessage, 1);
01089   if (retval == NULL)
01090     return NULL;
01091   
01092   retval->refcount.value = 1;
01093   retval->byte_order = message->byte_order;
01094   retval->client_serial = message->client_serial;
01095   retval->reply_serial = message->reply_serial;
01096   retval->header_padding = message->header_padding;
01097   retval->locked = FALSE;
01098   
01099   if (!_dbus_string_init (&retval->header))
01100     {
01101       dbus_free (retval);
01102       return NULL;
01103     }
01104   
01105   if (!_dbus_string_init (&retval->body))
01106     {
01107       _dbus_string_free (&retval->header);
01108       dbus_free (retval);
01109       return NULL;
01110     }
01111 
01112   if (!_dbus_string_copy (&message->header, 0,
01113                           &retval->header, 0))
01114     {
01115       _dbus_string_free (&retval->header);
01116       _dbus_string_free (&retval->body);
01117       dbus_free (retval);
01118 
01119       return NULL;
01120     }
01121 
01122   if (!_dbus_string_copy (&message->body, 0,
01123                           &retval->body, 0))
01124     {
01125       _dbus_string_free (&retval->header);
01126       _dbus_string_free (&retval->body);
01127       dbus_free (retval);
01128 
01129       return NULL;
01130     }
01131 
01132   for (i = 0; i < FIELD_LAST; i++)
01133     {
01134       retval->header_fields[i].offset = message->header_fields[i].offset;
01135     }
01136   
01137   return retval;
01138 }
01139 
01140 
01147 void
01148 dbus_message_ref (DBusMessage *message)
01149 {
01150   dbus_int32_t old_refcount;
01151 
01152   _dbus_return_if_fail (message != NULL);
01153   
01154   old_refcount = _dbus_atomic_inc (&message->refcount);
01155   _dbus_assert (old_refcount >= 1);
01156 }
01157 
01158 static void
01159 free_size_counter (void *element,
01160                    void *data)
01161 {
01162   DBusCounter *counter = element;
01163   DBusMessage *message = data;
01164   
01165   _dbus_counter_adjust (counter, - message->size_counter_delta);
01166 
01167   _dbus_counter_unref (counter);
01168 }
01169 
01176 void
01177 dbus_message_unref (DBusMessage *message)
01178 {
01179  dbus_int32_t old_refcount;
01180 
01181   _dbus_return_if_fail (message != NULL);
01182   
01183   old_refcount = _dbus_atomic_dec (&message->refcount);
01184   
01185   _dbus_assert (old_refcount >= 0);
01186 
01187   if (old_refcount == 1)
01188     {
01189       /* This calls application callbacks! */
01190       _dbus_data_slot_list_free (&message->slot_list);
01191       
01192       _dbus_list_foreach (&message->size_counters,
01193                           free_size_counter, message);
01194       _dbus_list_clear (&message->size_counters);
01195       
01196       _dbus_string_free (&message->header);
01197       _dbus_string_free (&message->body);
01198       
01199       dbus_free (message);
01200     }
01201 }
01202 
01209 const char*
01210 dbus_message_get_name (DBusMessage *message)
01211 {
01212   _dbus_return_val_if_fail (message != NULL, NULL);
01213   
01214   return get_string_field (message, FIELD_NAME, NULL);
01215 }
01216 
01223 const char*
01224 dbus_message_get_destination (DBusMessage *message)
01225 {
01226   _dbus_return_val_if_fail (message != NULL, NULL);
01227   
01228   return get_string_field (message, FIELD_SERVICE, NULL);
01229 }
01230 
01249 dbus_bool_t
01250 dbus_message_append_args (DBusMessage *message,
01251                           int first_arg_type,
01252                           ...)
01253 {
01254   dbus_bool_t retval;
01255   va_list var_args;
01256 
01257   _dbus_return_val_if_fail (message != NULL, FALSE);
01258   
01259   va_start (var_args, first_arg_type);
01260   retval = dbus_message_append_args_valist (message,
01261                                             first_arg_type,
01262                                             var_args);
01263   va_end (var_args);
01264 
01265   return retval;
01266 }
01267 
01281 dbus_bool_t
01282 dbus_message_append_args_valist (DBusMessage *message,
01283                                  int          first_arg_type,
01284                                  va_list      var_args)
01285 {
01286   int type, old_len;
01287   DBusMessageIter iter;
01288 
01289   _dbus_return_val_if_fail (message != NULL, FALSE);
01290   
01291   old_len = _dbus_string_get_length (&message->body);
01292   
01293   type = first_arg_type;
01294 
01295   dbus_message_append_iter_init (message, &iter);
01296   
01297   while (type != 0)
01298     {
01299       switch (type)
01300         {
01301         case DBUS_TYPE_NIL:
01302           if (!dbus_message_iter_append_nil (&iter))
01303             goto errorout;
01304           break;
01305         case DBUS_TYPE_BOOLEAN:
01306           if (!dbus_message_iter_append_boolean (&iter, va_arg (var_args, dbus_bool_t)))
01307             goto errorout;
01308           break;
01309         case DBUS_TYPE_INT32:
01310           if (!dbus_message_iter_append_int32 (&iter, va_arg (var_args, dbus_int32_t)))
01311             goto errorout;
01312           break;
01313         case DBUS_TYPE_UINT32:
01314           if (!dbus_message_iter_append_uint32 (&iter, va_arg (var_args, dbus_uint32_t)))
01315             goto errorout;          
01316           break;
01317 #ifdef DBUS_HAVE_INT64
01318         case DBUS_TYPE_INT64:
01319           if (!dbus_message_iter_append_int64 (&iter, va_arg (var_args, dbus_int64_t)))
01320             goto errorout;
01321           break;
01322         case DBUS_TYPE_UINT64:
01323           if (!dbus_message_iter_append_uint64 (&iter, va_arg (var_args, dbus_uint64_t)))
01324             goto errorout;          
01325           break;
01326 #endif /* DBUS_HAVE_INT64 */
01327         case DBUS_TYPE_DOUBLE:
01328           if (!dbus_message_iter_append_double (&iter, va_arg (var_args, double)))
01329             goto errorout;
01330           break;
01331         case DBUS_TYPE_STRING:
01332           if (!dbus_message_iter_append_string (&iter, va_arg (var_args, const char *)))
01333             goto errorout;
01334           break;
01335         case DBUS_TYPE_NAMED:
01336           {
01337             const char *name;
01338             unsigned char *data;
01339             int len;
01340  
01341             name = va_arg (var_args, const char *);
01342             data = va_arg (var_args, unsigned char *);
01343             len = va_arg (var_args, int);
01344 
01345             if (!dbus_message_iter_append_named (&iter, name, data, len))
01346               goto errorout;
01347             break;
01348           }
01349         case DBUS_TYPE_ARRAY:
01350           {
01351             void *data;
01352             int len, type;
01353  
01354             type = va_arg (var_args, int);
01355             data = va_arg (var_args, void *);
01356             len = va_arg (var_args, int);
01357 
01358             switch (type)
01359               {
01360               case DBUS_TYPE_BYTE:
01361                 if (!dbus_message_iter_append_byte_array (&iter, (unsigned char *)data, len))
01362                   goto errorout;
01363                 break;
01364               case DBUS_TYPE_BOOLEAN:
01365                 if (!dbus_message_iter_append_boolean_array (&iter, (unsigned char *)data, len))
01366                   goto errorout;
01367                 break;
01368               case DBUS_TYPE_INT32:
01369                 if (!dbus_message_iter_append_int32_array (&iter, (dbus_int32_t *)data, len))
01370                   goto errorout;
01371                 break;
01372               case DBUS_TYPE_UINT32:
01373                 if (!dbus_message_iter_append_uint32_array (&iter, (dbus_uint32_t *)data, len))
01374                   goto errorout;
01375                 break;
01376 #ifdef DBUS_HAVE_INT64
01377               case DBUS_TYPE_INT64:
01378                 if (!dbus_message_iter_append_int64_array (&iter, (dbus_int64_t *)data, len))
01379                   goto errorout;
01380                 break;
01381               case DBUS_TYPE_UINT64:
01382                 if (!dbus_message_iter_append_uint64_array (&iter, (dbus_uint64_t *)data, len))
01383                   goto errorout;
01384                 break;
01385 #endif /* DBUS_HAVE_INT64 */
01386               case DBUS_TYPE_DOUBLE:
01387                 if (!dbus_message_iter_append_double_array (&iter, (double *)data, len))
01388                   goto errorout;
01389                 break;
01390               case DBUS_TYPE_STRING:
01391                 if (!dbus_message_iter_append_string_array (&iter, (const char **)data, len))
01392                   goto errorout;
01393                 break;
01394               case DBUS_TYPE_NIL:
01395               case DBUS_TYPE_ARRAY:
01396               case DBUS_TYPE_NAMED:
01397               case DBUS_TYPE_DICT:
01398                 _dbus_warn ("dbus_message_append_args_valist doesn't support recursive arrays\n");
01399                 goto errorout;
01400               default:
01401                 _dbus_warn ("Unknown field type %d\n", type);
01402                 goto errorout;
01403               }
01404           }
01405           break;
01406           
01407         case DBUS_TYPE_DICT:
01408           _dbus_warn ("dbus_message_append_args_valist doesn't support dicts\n");
01409           goto errorout;
01410         default:
01411           _dbus_warn ("Unknown field type %d\n", type);
01412           goto errorout;
01413         }
01414 
01415       type = va_arg (var_args, int);
01416     }
01417 
01418   return TRUE;
01419 
01420  errorout:
01421   return FALSE;
01422 }
01423 
01424 
01437 dbus_bool_t
01438 dbus_message_get_args (DBusMessage     *message,
01439                        DBusError       *error,
01440                        int              first_arg_type,
01441                        ...)
01442 {
01443   dbus_bool_t retval;
01444   va_list var_args;
01445 
01446   _dbus_return_val_if_fail (message != NULL, FALSE);
01447   _dbus_return_val_if_error_is_set (error, FALSE);
01448   
01449   va_start (var_args, first_arg_type);
01450   retval = dbus_message_get_args_valist (message, error, first_arg_type, var_args);
01451   va_end (var_args);
01452 
01453   return retval;
01454 }
01455 
01468 dbus_bool_t
01469 dbus_message_get_args_valist (DBusMessage     *message,
01470                               DBusError       *error,
01471                               int              first_arg_type,
01472                               va_list          var_args)
01473 {
01474   DBusMessageIter iter;
01475 
01476   _dbus_return_val_if_fail (message != NULL, FALSE);
01477   _dbus_return_val_if_error_is_set (error, FALSE);
01478   
01479   dbus_message_iter_init (message, &iter);
01480   return dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args);
01481 }
01482 
01495 dbus_bool_t
01496 dbus_message_iter_get_args (DBusMessageIter *iter,
01497                             DBusError       *error,
01498                             int              first_arg_type,
01499                             ...)
01500 {
01501   dbus_bool_t retval;
01502   va_list var_args;
01503 
01504   _dbus_return_val_if_fail (iter != NULL, FALSE);
01505   _dbus_return_val_if_error_is_set (error, FALSE);
01506   
01507   va_start (var_args, first_arg_type);
01508   retval = dbus_message_iter_get_args_valist (iter, error, first_arg_type, var_args);
01509   va_end (var_args);
01510 
01511   return retval;
01512 }
01513 
01536 dbus_bool_t
01537 dbus_message_iter_get_args_valist (DBusMessageIter *iter,
01538                                    DBusError       *error,
01539                                    int              first_arg_type,
01540                                    va_list          var_args)
01541 {
01542   int spec_type, msg_type, i;
01543   dbus_bool_t retval;
01544 
01545   _dbus_return_val_if_fail (iter != NULL, FALSE);
01546   _dbus_return_val_if_error_is_set (error, FALSE);
01547 
01548   retval = FALSE;
01549   
01550   spec_type = first_arg_type;
01551   i = 0;
01552   
01553   while (spec_type != 0)
01554     {
01555       msg_type = dbus_message_iter_get_arg_type (iter);      
01556       
01557       if (msg_type != spec_type)
01558         {
01559           dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
01560                           "Argument %d is specified to be of type \"%s\", but "
01561                           "is actually of type \"%s\"\n", i,
01562                           _dbus_type_to_string (spec_type),
01563                           _dbus_type_to_string (msg_type));
01564 
01565           goto out;
01566         }
01567 
01568       switch (spec_type)
01569         {
01570         case DBUS_TYPE_NIL:
01571           break;
01572         case DBUS_TYPE_BYTE:
01573           {
01574             unsigned char *ptr;
01575 
01576             ptr = va_arg (var_args, unsigned char *);
01577 
01578             *ptr = dbus_message_iter_get_byte (iter);
01579             break;
01580           }
01581         case DBUS_TYPE_BOOLEAN:
01582           {
01583             dbus_bool_t *ptr;
01584 
01585             ptr = va_arg (var_args, dbus_bool_t *);
01586 
01587             *ptr = dbus_message_iter_get_boolean (iter);
01588             break;
01589           }
01590         case DBUS_TYPE_INT32:
01591           {
01592             dbus_int32_t *ptr;
01593 
01594             ptr = va_arg (var_args, dbus_int32_t *);
01595 
01596             *ptr = dbus_message_iter_get_int32 (iter);
01597             break;
01598           }
01599         case DBUS_TYPE_UINT32:
01600           {
01601             dbus_uint32_t *ptr;
01602 
01603             ptr = va_arg (var_args, dbus_uint32_t *);
01604 
01605             *ptr = dbus_message_iter_get_uint32 (iter);
01606             break;
01607           }
01608 #ifdef DBUS_HAVE_INT64
01609         case DBUS_TYPE_INT64:
01610           {
01611             dbus_int64_t *ptr;
01612 
01613             ptr = va_arg (var_args, dbus_int64_t *);
01614 
01615             *ptr = dbus_message_iter_get_int64 (iter);
01616             break;
01617           }
01618         case DBUS_TYPE_UINT64:
01619           {
01620             dbus_uint64_t *ptr;
01621 
01622             ptr = va_arg (var_args, dbus_uint64_t *);
01623 
01624             *ptr = dbus_message_iter_get_uint64 (iter);
01625             break;
01626           }
01627 #endif /* DBUS_HAVE_INT64 */
01628           
01629         case DBUS_TYPE_DOUBLE:
01630           {
01631             double *ptr;
01632 
01633             ptr = va_arg (var_args, double *);
01634 
01635             *ptr = dbus_message_iter_get_double (iter);
01636             break;
01637           }
01638 
01639         case DBUS_TYPE_STRING:
01640           {
01641             char **ptr;
01642 
01643             ptr = va_arg (var_args, char **);
01644 
01645             *ptr = dbus_message_iter_get_string (iter);
01646 
01647             if (!*ptr)
01648               {
01649                 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01650                 goto out;
01651               }
01652             
01653             break;
01654           }
01655 
01656         case DBUS_TYPE_NAMED:
01657           {
01658             char **name;
01659             unsigned char **data;
01660             int *len;
01661  
01662             name = va_arg (var_args, char **);
01663             data = va_arg (var_args, unsigned char **);
01664             len = va_arg (var_args, int *);
01665 
01666             if (!dbus_message_iter_get_named (iter, name, data, len))
01667               {
01668                 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01669                 goto out;
01670               }
01671           }
01672           break;
01673         case DBUS_TYPE_ARRAY:
01674           {
01675             void **data;
01676             int *len, type;
01677  
01678             type = va_arg (var_args, int);
01679             data = va_arg (var_args, void *);
01680             len = va_arg (var_args, int *);
01681 
01682             if (dbus_message_iter_get_array_type (iter) != type)
01683               {
01684                 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
01685                                 "Argument %d is specified to be of type \"array of %s\", but "
01686                                 "is actually of type \"array of %s\"\n", i,
01687                                 _dbus_type_to_string (type),
01688                                 _dbus_type_to_string (dbus_message_iter_get_array_type (iter)));
01689                 goto out;
01690               }
01691             
01692             switch (type)
01693               {
01694               case DBUS_TYPE_BYTE:
01695                 if (!dbus_message_iter_get_byte_array (iter, (unsigned char **)data, len))
01696                   {
01697                     dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01698                     goto out;
01699                   }
01700                 break;
01701               case DBUS_TYPE_BOOLEAN:
01702                 if (!dbus_message_iter_get_boolean_array (iter, (unsigned char **)data, len))
01703                   {
01704                     dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01705                     goto out;
01706                   }
01707                 break;
01708               case DBUS_TYPE_INT32:
01709                 if (!dbus_message_iter_get_int32_array (iter, (dbus_int32_t **)data, len))
01710                   {
01711                     dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01712                     goto out;
01713                   }
01714                 break;
01715               case DBUS_TYPE_UINT32:
01716                 if (!dbus_message_iter_get_uint32_array (iter, (dbus_uint32_t **)data, len))
01717                   {
01718                     dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01719                     goto out;
01720                   }
01721                 break;
01722 #ifdef DBUS_HAVE_INT64
01723               case DBUS_TYPE_INT64:
01724                 if (!dbus_message_iter_get_int64_array (iter, (dbus_int64_t **)data, len))
01725                   {
01726                     dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01727                     goto out;
01728                   }
01729                 break;
01730               case DBUS_TYPE_UINT64:
01731                 if (!dbus_message_iter_get_uint64_array (iter, (dbus_uint64_t **)data, len))
01732                   {
01733                     dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01734                     goto out;
01735                   }
01736                 break;
01737 #endif /* DBUS_HAVE_INT64 */
01738               case DBUS_TYPE_DOUBLE:
01739                 if (!dbus_message_iter_get_double_array (iter, (double **)data, len))
01740                   {
01741                     dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01742                     goto out;
01743                   }
01744                 break;
01745               case DBUS_TYPE_STRING:
01746                 if (!dbus_message_iter_get_string_array (iter, (char ***)data, len))
01747                   {
01748                     dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01749                     goto out;
01750                   }
01751                 break;
01752               case DBUS_TYPE_NIL:
01753               case DBUS_TYPE_ARRAY:
01754               case DBUS_TYPE_NAMED:
01755               case DBUS_TYPE_DICT:
01756                 _dbus_warn ("dbus_message_get_args_valist doesn't support recursive arrays\n");
01757                 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
01758                 goto out;
01759               default:
01760                 _dbus_warn ("Unknown field type %d\n", type);
01761                 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
01762                 goto out;
01763               }
01764           }
01765           break;
01766         case DBUS_TYPE_DICT:
01767           _dbus_warn ("dbus_message_get_args_valist doesn't support dicts\n");
01768           dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
01769           goto out;
01770         default:          
01771           dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
01772           _dbus_warn ("Unknown field type %d\n", spec_type);
01773           goto out;
01774         }
01775       
01776       spec_type = va_arg (var_args, int);
01777       if (spec_type != 0 && !dbus_message_iter_next (iter))
01778         {
01779           dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
01780                           "Message has only %d arguments, but more were expected", i);
01781           goto out;
01782         }
01783 
01784       i++;
01785     }
01786   
01787   retval = TRUE;
01788   
01789  out:
01790   
01791   return retval;
01792 }
01793 
01794 
01802 void
01803 dbus_message_iter_init (DBusMessage     *message,
01804                         DBusMessageIter *iter)
01805 {
01806   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01807 
01808   _dbus_return_if_fail (message != NULL);
01809   _dbus_return_if_fail (iter != NULL);
01810   
01811   _dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
01812   
01813   real->message = message;
01814   real->parent_iter = NULL;
01815   real->changed_stamp = message->changed_stamp;
01816   
01817   real->type = DBUS_MESSAGE_ITER_TYPE_MESSAGE;
01818   real->pos = 0;
01819   real->end = _dbus_string_get_length (&message->body);
01820   
01821   real->container_start = 0;
01822   real->container_length_pos = 0;
01823   real->wrote_dict_key = 0;
01824   real->array_type_pos = 0;
01825 }
01826 
01827 #ifndef DBUS_DISABLE_CHECKS
01828 static dbus_bool_t
01829 dbus_message_iter_check (DBusMessageRealIter *iter)
01830 {
01831   if (iter == NULL)
01832     {
01833       _dbus_warn ("dbus iterator check failed: iterator is NULL\n");
01834       return FALSE;
01835     }
01836   
01837   if (iter->changed_stamp != iter->message->changed_stamp)
01838     {
01839       _dbus_warn ("dbus iterator check failed: invalid iterator, must re-initialize it after modifying the message\n");
01840       return FALSE;
01841     }
01842   
01843   if (iter->pos < 0 || iter->pos > iter->end)
01844     {
01845       _dbus_warn ("dbus iterator check failed: invalid position\n");
01846       return FALSE;
01847     }
01848 
01849   return TRUE;
01850 }
01851 #endif /* DBUS_DISABLE_CHECKS */
01852 
01853 static int
01854 skip_array_type (DBusMessageRealIter *iter, int pos)
01855 {
01856   const char *data;
01857 
01858   do
01859     {
01860       data = _dbus_string_get_const_data_len (&iter->message->body,
01861                                               pos++, 1);
01862     }
01863   while (*data == DBUS_TYPE_ARRAY);
01864   
01865   return pos;
01866 }
01867 
01868 static int
01869 dbus_message_iter_get_data_start (DBusMessageRealIter *iter, int *type)
01870 {
01871   const char *data;
01872   int pos, len;
01873   
01874   switch (iter->type)
01875     {
01876     case DBUS_MESSAGE_ITER_TYPE_MESSAGE:
01877       data = _dbus_string_get_const_data_len (&iter->message->body,
01878                                               iter->pos, 1);
01879       if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_LAST)
01880         *type = *data;
01881       else
01882         *type = DBUS_TYPE_INVALID;
01883       
01884       return skip_array_type (iter, iter->pos);
01885       
01886     case DBUS_MESSAGE_ITER_TYPE_ARRAY:
01887       data = _dbus_string_get_const_data_len (&iter->message->body,
01888                                               iter->array_type_pos, 1);
01889       if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_LAST)
01890         *type = *data;
01891       else
01892         *type = DBUS_TYPE_INVALID;
01893       
01894       return iter->pos;
01895       
01896     case DBUS_MESSAGE_ITER_TYPE_DICT:
01897       /* Get the length of the string */
01898       len = _dbus_demarshal_uint32 (&iter->message->body,
01899                                     iter->message->byte_order,
01900                                     iter->pos, &pos);
01901       pos = pos + len + 1;
01902 
01903       data = _dbus_string_get_const_data_len (&iter->message->body,
01904                                               pos, 1);
01905       if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_LAST)
01906         *type = *data;
01907       else
01908         *type = DBUS_TYPE_INVALID;
01909 
01910       return skip_array_type (iter, pos);
01911       
01912     default:
01913       _dbus_assert_not_reached ("Invalid iter type");
01914       break;
01915     }
01916   *type = DBUS_TYPE_INVALID;
01917   return iter->pos;
01918 }
01919 
01920 
01928 dbus_bool_t
01929 dbus_message_iter_has_next (DBusMessageIter *iter)
01930 {
01931   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01932   int end_pos;
01933   int type, pos;
01934 
01935   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
01936 
01937   if (real->pos >= real->end)
01938     return FALSE;
01939   
01940   pos = dbus_message_iter_get_data_start (real, &type);
01941   
01942   if (!_dbus_marshal_get_arg_end_pos (&real->message->body,
01943                                       real->message->byte_order,
01944                                       type, pos, &end_pos))
01945     return FALSE;
01946   
01947   if (end_pos >= real->end)
01948     return FALSE;
01949 
01950   return TRUE;  
01951 }
01952 
01959 dbus_bool_t
01960 dbus_message_iter_next (DBusMessageIter *iter)
01961 {
01962   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01963   int end_pos;
01964   int type, pos;
01965 
01966   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
01967 
01968   pos = dbus_message_iter_get_data_start (real, &type);
01969   
01970   if (!_dbus_marshal_get_arg_end_pos (&real->message->body,
01971                                       real->message->byte_order,
01972                                       type, pos, &end_pos))
01973     return FALSE;
01974 
01975   if (end_pos >= real->end)
01976     return FALSE;
01977 
01978   real->pos = end_pos;
01979 
01980   return TRUE;
01981 }
01982 
01990 int
01991 dbus_message_iter_get_arg_type (DBusMessageIter *iter)
01992 {
01993   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01994   int type, pos;
01995 
01996   _dbus_return_val_if_fail (dbus_message_iter_check (real), DBUS_TYPE_INVALID);
01997 
01998   if (real->pos >= real->end)
01999     return DBUS_TYPE_INVALID;
02000 
02001   pos = dbus_message_iter_get_data_start (real, &type);
02002   
02003   return type;
02004 }
02005 
02006 static int
02007 iter_get_array_type (DBusMessageRealIter *iter, int *array_type_pos)
02008 {
02009   const char *data;
02010   int _array_type_pos;
02011   int len, pos;
02012   
02013   switch (iter->type)
02014     {
02015     case DBUS_MESSAGE_ITER_TYPE_MESSAGE:
02016       _array_type_pos = iter->pos + 1;
02017       break;
02018     case DBUS_MESSAGE_ITER_TYPE_ARRAY:
02019       _array_type_pos = iter->array_type_pos + 1;
02020       break;
02021     case DBUS_MESSAGE_ITER_TYPE_DICT:
02022       /* Get the length of the string */
02023       len = _dbus_demarshal_uint32 (&iter->message->body,
02024                                     iter->message->byte_order,
02025                                     iter->pos, &pos);
02026       pos = pos + len + 1;
02027       data = _dbus_string_get_const_data_len (&iter->message->body,
02028                                               pos + 1, 1);
02029       _array_type_pos = pos + 1;
02030       break;
02031     default:
02032       _dbus_assert_not_reached ("wrong iter type");
02033       return DBUS_TYPE_INVALID;
02034     }
02035 
02036   if (array_type_pos != NULL)
02037     *array_type_pos = _array_type_pos;
02038   
02039   data = _dbus_string_get_const_data_len (&iter->message->body,
02040                                           _array_type_pos, 1);
02041   if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_LAST)
02042     return  *data;
02043   
02044   return DBUS_TYPE_INVALID;
02045 }
02046 
02047 
02057 int
02058 dbus_message_iter_get_array_type (DBusMessageIter *iter)
02059 {
02060   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02061   int type, pos;
02062 
02063   _dbus_return_val_if_fail (dbus_message_iter_check (real), DBUS_TYPE_INVALID);
02064 
02065   if (real->pos >= real->end)
02066     return DBUS_TYPE_INVALID;
02067 
02068   pos = dbus_message_iter_get_data_start (real, &type);
02069 
02070   _dbus_assert (type == DBUS_TYPE_ARRAY);
02071 
02072   return iter_get_array_type (real, NULL);
02073 }
02074 
02075 
02085 char *
02086 dbus_message_iter_get_string (DBusMessageIter *iter)
02087 {
02088   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02089   int type, pos;
02090 
02091   _dbus_return_val_if_fail (dbus_message_iter_check (real), NULL);
02092 
02093   pos = dbus_message_iter_get_data_start (real, &type);
02094   
02095   _dbus_assert (type == DBUS_TYPE_STRING);
02096 
02097   return _dbus_demarshal_string (&real->message->body, real->message->byte_order,
02098                                  pos, NULL);
02099 }
02100 
02115 dbus_bool_t
02116 dbus_message_iter_get_named (DBusMessageIter   *iter,
02117                              char             **name,
02118                              unsigned char    **value,
02119                              int               *len)
02120 {
02121   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02122   int type, pos;
02123   char *_name;
02124 
02125   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
02126 
02127   pos = dbus_message_iter_get_data_start (real, &type);
02128   
02129   _dbus_assert (type == DBUS_TYPE_NAMED);
02130   
02131   _name = _dbus_demarshal_string (&real->message->body, real->message->byte_order,
02132                                   pos, &pos);
02133 
02134   if (_name == NULL)
02135     return FALSE;
02136   
02137   if (!_dbus_demarshal_byte_array (&real->message->body, real->message->byte_order,
02138                                    pos, NULL, value, len))
02139     {
02140       dbus_free (_name);
02141       return FALSE;
02142     }
02143 
02144   *name = _name;
02145   
02146   return TRUE;
02147 }
02148 
02158 unsigned char
02159 dbus_message_iter_get_byte (DBusMessageIter *iter)
02160 {
02161   unsigned char value;
02162   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02163   int type, pos;
02164 
02165   _dbus_return_val_if_fail (dbus_message_iter_check (real), 0);
02166 
02167   pos = dbus_message_iter_get_data_start (real, &type);
02168   
02169   _dbus_assert (type == DBUS_TYPE_BYTE);
02170 
02171   value = _dbus_string_get_byte (&real->message->body, pos);
02172   
02173   return value;
02174 }
02175 
02176 
02186 dbus_bool_t
02187 dbus_message_iter_get_boolean (DBusMessageIter *iter)
02188 {
02189   unsigned char value;
02190   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02191   int type, pos;
02192 
02193   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
02194 
02195   pos = dbus_message_iter_get_data_start (real, &type);
02196   
02197   _dbus_assert (type == DBUS_TYPE_BOOLEAN);
02198 
02199   value = _dbus_string_get_byte (&real->message->body, pos);
02200   
02201   return value;
02202 }
02203 
02213 dbus_int32_t
02214 dbus_message_iter_get_int32 (DBusMessageIter *iter)
02215 {
02216   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02217   int type, pos;
02218 
02219   _dbus_return_val_if_fail (dbus_message_iter_check (real), 0);
02220 
02221   pos = dbus_message_iter_get_data_start (real, &type);
02222   
02223   _dbus_assert (type == DBUS_TYPE_INT32);
02224   
02225   return _dbus_demarshal_int32 (&real->message->body, real->message->byte_order,
02226                                 pos, NULL);
02227 }
02228 
02238 dbus_uint32_t
02239 dbus_message_iter_get_uint32 (DBusMessageIter *iter)
02240 {
02241   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02242   int type, pos;
02243 
02244   _dbus_return_val_if_fail (dbus_message_iter_check (real), 0);
02245 
02246   pos = dbus_message_iter_get_data_start (real, &type);
02247   
02248   _dbus_assert (type == DBUS_TYPE_UINT32);
02249   
02250   return _dbus_demarshal_uint32 (&real->message->body, real->message->byte_order,
02251                                  pos, NULL);
02252 }
02253 
02254 #ifdef DBUS_HAVE_INT64
02255 
02267 dbus_int64_t
02268 dbus_message_iter_get_int64 (DBusMessageIter *iter)
02269 {
02270   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02271   int type, pos;
02272 
02273   _dbus_return_val_if_fail (dbus_message_iter_check (real), 0);
02274 
02275   pos = dbus_message_iter_get_data_start (real, &type);
02276   
02277   _dbus_assert (type == DBUS_TYPE_INT64);
02278   
02279   return _dbus_demarshal_int64 (&real->message->body, real->message->byte_order,
02280                                 pos, NULL);
02281 }
02282 
02294 dbus_uint64_t
02295 dbus_message_iter_get_uint64 (DBusMessageIter *iter)
02296 {
02297   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02298   int type, pos;
02299 
02300   _dbus_return_val_if_fail (dbus_message_iter_check (real), 0);
02301 
02302   pos = dbus_message_iter_get_data_start (real, &type);
02303   
02304   _dbus_assert (type == DBUS_TYPE_UINT64);
02305   
02306   return _dbus_demarshal_uint64 (&real->message->body, real->message->byte_order,
02307                                  pos, NULL);
02308 }
02309 
02310 #endif /* DBUS_HAVE_INT64 */
02311 
02321 double
02322 dbus_message_iter_get_double (DBusMessageIter *iter)
02323 {
02324   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02325   int type, pos;
02326 
02327   _dbus_return_val_if_fail (dbus_message_iter_check (real), 0.0);
02328 
02329   pos = dbus_message_iter_get_data_start (real, &type);
02330   
02331   _dbus_assert (type == DBUS_TYPE_DOUBLE);
02332   
02333   return _dbus_demarshal_double (&real->message->body, real->message->byte_order,
02334                                  pos, NULL);
02335 }
02336 
02350 dbus_bool_t
02351 dbus_message_iter_init_array_iterator (DBusMessageIter *iter,
02352                                        DBusMessageIter *array_iter,
02353                                        int             *array_type)
02354 {
02355   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02356   DBusMessageRealIter *array_real = (DBusMessageRealIter *)array_iter;
02357   int type, pos, len_pos, len, array_type_pos;
02358   int _array_type;
02359 
02360   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
02361 
02362   pos = dbus_message_iter_get_data_start (real, &type);
02363   
02364   _dbus_assert (type == DBUS_TYPE_ARRAY);
02365 
02366   _array_type = iter_get_array_type (real, &array_type_pos);
02367   
02368   len_pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_uint32_t));
02369   len = _dbus_demarshal_uint32 (&real->message->body, real->message->byte_order,
02370                                 pos, &pos);
02371   
02372   array_real->parent_iter = real;
02373   array_real->message = real->message;
02374   array_real->changed_stamp = real->message->changed_stamp;
02375   
02376   array_real->type = DBUS_MESSAGE_ITER_TYPE_ARRAY;
02377   array_real->pos = pos;
02378   array_real->end = pos + len;
02379   
02380   array_real->container_start = pos;
02381   array_real->container_length_pos = len_pos;
02382   array_real->wrote_dict_key = 0;
02383   array_real->array_type_pos = array_type_pos;
02384   array_real->array_type_done = TRUE;
02385   
02386   if (array_type != NULL)
02387     *array_type = _array_type;
02388   
02389   return TRUE;
02390 }
02391 
02392 
02402 dbus_bool_t
02403 dbus_message_iter_init_dict_iterator (DBusMessageIter *iter,
02404                                       DBusMessageIter *dict_iter)
02405 {
02406   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02407   DBusMessageRealIter *dict_real = (DBusMessageRealIter *)dict_iter;
02408   int type, pos, len_pos, len;
02409 
02410   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
02411 
02412   pos = dbus_message_iter_get_data_start (real, &type);
02413   
02414   _dbus_assert (type == DBUS_TYPE_DICT);
02415 
02416   len_pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_uint32_t));
02417   len = _dbus_demarshal_uint32 (&real->message->body, real->message->byte_order,
02418                                 pos, &pos);
02419   
02420   dict_real->parent_iter = real;
02421   dict_real->message = real->message;
02422   dict_real->changed_stamp = real->message->changed_stamp;
02423   
02424   dict_real->type = DBUS_MESSAGE_ITER_TYPE_DICT;
02425   dict_real->pos = pos;
02426   dict_real->end = pos + len;
02427   
02428   dict_real->container_start = pos;
02429   dict_real->container_length_pos = len_pos;
02430   dict_real->wrote_dict_key = 0;
02431 
02432   return TRUE;
02433 }
02434 
02445 dbus_bool_t
02446 dbus_message_iter_get_byte_array (DBusMessageIter  *iter,
02447                                   unsigned char   **value,
02448                                   int              *len)
02449 {
02450   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02451   int type, pos;
02452 
02453   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
02454 
02455   pos = dbus_message_iter_get_data_start (real, &type);
02456   
02457   _dbus_assert (type == DBUS_TYPE_ARRAY);
02458 
02459   type = iter_get_array_type (real, NULL);
02460 
02461   _dbus_assert (type == DBUS_TYPE_BYTE);
02462 
02463   if (!_dbus_demarshal_byte_array (&real->message->body, real->message->byte_order,
02464                                    pos, NULL, value, len))
02465     return FALSE;
02466   else
02467     return TRUE;
02468 }
02469 
02480 dbus_bool_t
02481 dbus_message_iter_get_boolean_array (DBusMessageIter   *iter,
02482                                      unsigned char    **value,
02483                                      int               *len)
02484 {
02485   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02486   int type, pos;
02487 
02488   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
02489 
02490   pos = dbus_message_iter_get_data_start (real, &type);
02491   
02492   _dbus_assert (type == DBUS_TYPE_ARRAY);
02493 
02494   type = iter_get_array_type (real, NULL);
02495 
02496   _dbus_assert (type == DBUS_TYPE_BOOLEAN);
02497 
02498   if (!_dbus_demarshal_byte_array (&real->message->body, real->message->byte_order,
02499                                    pos, NULL, value, len))
02500     return FALSE;
02501   else
02502     return TRUE;
02503 }
02504 
02515 dbus_bool_t
02516 dbus_message_iter_get_int32_array  (DBusMessageIter *iter,
02517                                     dbus_int32_t   **value,
02518                                     int             *len)
02519 {
02520   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02521   int type, pos;
02522 
02523   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
02524 
02525   pos = dbus_message_iter_get_data_start (real, &type);
02526   
02527   _dbus_assert (type == DBUS_TYPE_ARRAY);
02528 
02529   type = iter_get_array_type (real, NULL);
02530   
02531   _dbus_assert (type == DBUS_TYPE_INT32);
02532 
02533   if (!_dbus_demarshal_int32_array (&real->message->body, real->message->byte_order,
02534                                     pos, NULL, value, len))
02535     return FALSE;
02536   else
02537     return TRUE;
02538 }
02539 
02550 dbus_bool_t
02551 dbus_message_iter_get_uint32_array  (DBusMessageIter *iter,
02552                                      dbus_uint32_t  **value,
02553                                      int             *len)
02554 {
02555   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02556   int type, pos;
02557 
02558   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
02559 
02560   pos = dbus_message_iter_get_data_start (real, &type);
02561   
02562   _dbus_assert (type == DBUS_TYPE_ARRAY);
02563 
02564   type = iter_get_array_type (real, NULL);
02565   _dbus_assert (type == DBUS_TYPE_UINT32);
02566 
02567   if (!_dbus_demarshal_uint32_array (&real->message->body, real->message->byte_order,
02568                                     pos, NULL, value, len))
02569     return FALSE;
02570   else
02571     return TRUE;
02572 }
02573 
02574 #ifdef DBUS_HAVE_INT64
02575 
02588 dbus_bool_t
02589 dbus_message_iter_get_int64_array  (DBusMessageIter *iter,
02590                                     dbus_int64_t   **value,
02591                                     int             *len)
02592 {
02593   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02594   int type, pos;
02595 
02596   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
02597 
02598   pos = dbus_message_iter_get_data_start (real, &type);
02599   
02600   _dbus_assert (type == DBUS_TYPE_ARRAY);
02601 
02602   type = iter_get_array_type (real, NULL);
02603   
02604   _dbus_assert (type == DBUS_TYPE_INT64);
02605 
02606   if (!_dbus_demarshal_int64_array (&real->message->body, real->message->byte_order,
02607                                     pos, NULL, value, len))
02608     return FALSE;
02609   else
02610     return TRUE;
02611 }
02612 
02625 dbus_bool_t
02626 dbus_message_iter_get_uint64_array  (DBusMessageIter *iter,
02627                                      dbus_uint64_t  **value,
02628                                      int             *len)
02629 {
02630   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02631   int type, pos;
02632 
02633   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
02634 
02635   pos = dbus_message_iter_get_data_start (real, &type);
02636   
02637   _dbus_assert (type == DBUS_TYPE_ARRAY);
02638 
02639   type = iter_get_array_type (real, NULL);
02640   _dbus_assert (type == DBUS_TYPE_UINT64);
02641 
02642   if (!_dbus_demarshal_uint64_array (&real->message->body, real->message->byte_order,
02643                                     pos, NULL, value, len))
02644     return FALSE;
02645   else
02646     return TRUE;
02647 }
02648 
02649 #endif /* DBUS_HAVE_INT64 */
02650 
02661 dbus_bool_t
02662 dbus_message_iter_get_double_array  (DBusMessageIter *iter,
02663                                      double         **value,
02664                                      int             *len)
02665 {
02666   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02667   int type, pos;
02668 
02669   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
02670 
02671   pos = dbus_message_iter_get_data_start (real, &type);
02672   
02673   _dbus_assert (type == DBUS_TYPE_ARRAY);
02674 
02675   type = iter_get_array_type (real, NULL);
02676   _dbus_assert (type == DBUS_TYPE_DOUBLE);
02677 
02678   if (!_dbus_demarshal_double_array (&real->message->body, real->message->byte_order,
02679                                      pos, NULL, value, len))
02680     return FALSE;
02681   else
02682     return TRUE;
02683 }
02684 
02700 dbus_bool_t
02701 dbus_message_iter_get_string_array (DBusMessageIter *iter,
02702                                     char          ***value,
02703                                     int             *len)
02704 {
02705   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02706   int type, pos;
02707 
02708   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
02709 
02710   pos = dbus_message_iter_get_data_start (real, &type);
02711   
02712   _dbus_assert (type == DBUS_TYPE_ARRAY);
02713 
02714   type = iter_get_array_type (real, NULL);
02715   _dbus_assert (type == DBUS_TYPE_STRING);
02716 
02717   if (!_dbus_demarshal_string_array (&real->message->body, real->message->byte_order,
02718                                      pos, NULL, value, len))
02719     return FALSE;
02720   else
02721     return TRUE;
02722 }
02723 
02733 char *
02734 dbus_message_iter_get_dict_key (DBusMessageIter   *iter)
02735 {
02736   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02737 
02738   _dbus_return_val_if_fail (dbus_message_iter_check (real), NULL);
02739 
02740   _dbus_assert (real->type == DBUS_MESSAGE_ITER_TYPE_DICT);
02741 
02742   return _dbus_demarshal_string (&real->message->body, real->message->byte_order,
02743                                  real->pos, NULL);
02744 }
02745 
02754 void
02755 dbus_message_append_iter_init (DBusMessage     *message,
02756                                DBusMessageIter *iter)
02757 {
02758   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02759 
02760   _dbus_return_if_fail (message != NULL);
02761   _dbus_return_if_fail (iter != NULL);
02762   
02763   real->message = message;
02764   real->parent_iter = NULL;
02765   real->changed_stamp = message->changed_stamp;
02766   
02767   real->type = DBUS_MESSAGE_ITER_TYPE_MESSAGE;
02768   real->end = _dbus_string_get_length (&real->message->body);
02769   real->pos = real->end;
02770   
02771   real->container_length_pos = 0;
02772   real->wrote_dict_key = 0;
02773 }
02774 
02775 #ifndef DBUS_DISABLE_CHECKS
02776 static dbus_bool_t
02777 dbus_message_iter_append_check (DBusMessageRealIter *iter)
02778 {
02779   if (iter == NULL)
02780     {
02781       _dbus_warn ("dbus iterator check failed: NULL iterator\n");
02782       return FALSE;
02783     }
02784   
02785   if (iter->message->locked)
02786     {
02787       _dbus_warn ("dbus iterator check failed: message is locked (has already been sent)\n");
02788       return FALSE;
02789     }
02790       
02791   if (iter->changed_stamp != iter->message->changed_stamp)
02792     {
02793       _dbus_warn ("dbus iterator check failed: invalid iterator, must re-initialize it after modifying the message");
02794       return FALSE;
02795     }
02796   
02797   if (iter->pos != iter->end)
02798     {
02799       _dbus_warn ("dbus iterator check failed: can only append at end of message");
02800       return FALSE;
02801     }
02802   
02803   if (iter->pos != _dbus_string_get_length (&iter->message->body))
02804     {
02805       _dbus_warn ("dbus iterator check failed: append pos not at end of message string");
02806       return FALSE;
02807     }
02808 
02809   return TRUE;
02810 }
02811 #endif /* DBUS_DISABLE_CHECKS */
02812 
02813 static dbus_bool_t
02814 dbus_message_iter_append_type (DBusMessageRealIter *iter,
02815                                int                  type)
02816 {
02817   const char *data;
02818   switch (iter->type)
02819     {
02820     case DBUS_MESSAGE_ITER_TYPE_MESSAGE:
02821       if (!_dbus_string_append_byte (&iter->message->body, type))
02822         return FALSE;
02823       break;
02824       
02825     case DBUS_MESSAGE_ITER_TYPE_ARRAY:
02826       data = _dbus_string_get_const_data_len (&iter->message->body,
02827                                               iter->array_type_pos, 1);
02828       if (type != *data)
02829         {
02830           _dbus_warn ("Appended element of wrong type for array\n");
02831           return FALSE;
02832         }
02833       break;
02834       
02835     case DBUS_MESSAGE_ITER_TYPE_DICT:
02836       if (!iter->wrote_dict_key)
02837         {
02838           _dbus_warn ("Appending dict data before key name\n");
02839           return FALSE;
02840         }
02841       
02842       if (!_dbus_string_append_byte (&iter->message->body, type))
02843         return FALSE;
02844       
02845       break;
02846       
02847     default:
02848       _dbus_assert_not_reached ("Invalid iter type");
02849       break;
02850     }
02851   
02852   return TRUE;
02853 }
02854 
02855 static void
02856 dbus_message_iter_update_after_change (DBusMessageRealIter *iter)
02857 {
02858   iter->changed_stamp = iter->message->changed_stamp;
02859   
02860   /* Set new end of iter */
02861   iter->end = _dbus_string_get_length (&iter->message->body);
02862   iter->pos = iter->end;
02863 
02864   /* Set container length */
02865   if (iter->type == DBUS_MESSAGE_ITER_TYPE_DICT ||
02866       (iter->type == DBUS_MESSAGE_ITER_TYPE_ARRAY && iter->array_type_done))
02867     _dbus_marshal_set_uint32 (&iter->message->body,
02868                               iter->message->byte_order,
02869                               iter->container_length_pos,
02870                               iter->end - iter->container_start);
02871   
02872   if (iter->parent_iter)
02873     dbus_message_iter_update_after_change (iter->parent_iter);
02874 }
02875 
02876 static void
02877 dbus_message_iter_append_done (DBusMessageRealIter *iter)
02878 {
02879   iter->message->changed_stamp++;
02880   dbus_message_iter_update_after_change (iter);
02881   iter->wrote_dict_key = FALSE;
02882 }
02883 
02890 dbus_bool_t
02891 dbus_message_iter_append_nil (DBusMessageIter *iter)
02892 {
02893   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02894 
02895   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
02896 
02897   if (!dbus_message_iter_append_type (real, DBUS_TYPE_NIL))
02898     return FALSE;
02899   
02900   dbus_message_iter_append_done (real);
02901   
02902   return TRUE;
02903 }
02904 
02912 dbus_bool_t
02913 dbus_message_iter_append_boolean (DBusMessageIter *iter,
02914                                   dbus_bool_t     value)
02915 {
02916   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02917 
02918   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
02919 
02920   if (!dbus_message_iter_append_type (real, DBUS_TYPE_BOOLEAN))
02921     return FALSE;
02922   
02923   if (!_dbus_string_append_byte (&real->message->body, (value != FALSE)))
02924     {
02925       _dbus_string_set_length (&real->message->body, real->pos);
02926       return FALSE;
02927     }
02928 
02929   dbus_message_iter_append_done (real);
02930   
02931   return TRUE;
02932 }
02933 
02941 dbus_bool_t
02942 dbus_message_iter_append_byte (DBusMessageIter *iter,
02943                                unsigned char    value)
02944 {
02945   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02946 
02947   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
02948 
02949   if (!dbus_message_iter_append_type (real, DBUS_TYPE_BYTE))
02950     return FALSE;
02951   
02952   if (!_dbus_string_append_byte (&real->message->body, value))
02953     {
02954       _dbus_string_set_length (&real->message->body, real->pos);
02955       return FALSE;
02956     }
02957 
02958   dbus_message_iter_append_done (real);
02959   
02960   return TRUE;
02961 }
02962 
02963 
02971 dbus_bool_t
02972 dbus_message_iter_append_int32   (DBusMessageIter *iter,
02973                                   dbus_int32_t  value)
02974 {
02975   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02976 
02977   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
02978 
02979   if (!dbus_message_iter_append_type (real, DBUS_TYPE_INT32))
02980     return FALSE;
02981   
02982   if (!_dbus_marshal_int32 (&real->message->body, real->message->byte_order, value))
02983     {
02984       _dbus_string_set_length (&real->message->body, real->pos);
02985       return FALSE;
02986     }
02987 
02988   dbus_message_iter_append_done (real);
02989   
02990   return TRUE;
02991 }
02992 
03000 dbus_bool_t
03001 dbus_message_iter_append_uint32 (DBusMessageIter *iter,
03002                                  dbus_uint32_t    value)
03003 {
03004   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03005 
03006   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03007 
03008   if (!dbus_message_iter_append_type (real, DBUS_TYPE_UINT32))
03009     return FALSE;
03010   
03011   if (!_dbus_marshal_uint32 (&real->message->body, real->message->byte_order, value))
03012     {
03013       _dbus_string_set_length (&real->message->body, real->pos);
03014       return FALSE;
03015     }
03016 
03017   dbus_message_iter_append_done (real);
03018   
03019   return TRUE;
03020 }
03021 
03022 #ifdef DBUS_HAVE_INT64
03023 
03033 dbus_bool_t
03034 dbus_message_iter_append_int64   (DBusMessageIter *iter,
03035                                   dbus_int64_t  value)
03036 {
03037   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03038 
03039   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03040 
03041   if (!dbus_message_iter_append_type (real, DBUS_TYPE_INT64))
03042     return FALSE;
03043   
03044   if (!_dbus_marshal_int64 (&real->message->body, real->message->byte_order, value))
03045     {
03046       _dbus_string_set_length (&real->message->body, real->pos);
03047       return FALSE;
03048     }
03049 
03050   dbus_message_iter_append_done (real);
03051   
03052   return TRUE;
03053 }
03054 
03064 dbus_bool_t
03065 dbus_message_iter_append_uint64 (DBusMessageIter *iter,
03066                                  dbus_uint64_t    value)
03067 {
03068   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03069 
03070   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03071 
03072   if (!dbus_message_iter_append_type (real, DBUS_TYPE_UINT64))
03073     return FALSE;
03074   
03075   if (!_dbus_marshal_uint64 (&real->message->body, real->message->byte_order, value))
03076     {
03077       _dbus_string_set_length (&real->message->body, real->pos);
03078       return FALSE;
03079     }
03080 
03081   dbus_message_iter_append_done (real);
03082   
03083   return TRUE;
03084 }
03085 
03086 #endif /* DBUS_HAVE_INT64 */
03087 
03095 dbus_bool_t
03096 dbus_message_iter_append_double (DBusMessageIter *iter,
03097                                  double           value)
03098 {
03099   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03100 
03101   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03102 
03103   if (!dbus_message_iter_append_type (real, DBUS_TYPE_DOUBLE))
03104     return FALSE;
03105   
03106   if (!_dbus_marshal_double (&real->message->body, real->message->byte_order, value))
03107     {
03108       _dbus_string_set_length (&real->message->body, real->pos);
03109       return FALSE;
03110     }
03111 
03112   dbus_message_iter_append_done (real);
03113   
03114   return TRUE;
03115 }
03116 
03124 dbus_bool_t
03125 dbus_message_iter_append_string (DBusMessageIter *iter,
03126                                  const char      *value)
03127 {
03128   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03129 
03130   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03131 
03132   if (!dbus_message_iter_append_type (real, DBUS_TYPE_STRING))
03133     return FALSE;
03134   
03135   if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, value))
03136     {
03137       _dbus_string_set_length (&real->message->body, real->pos);
03138       return FALSE;
03139     }
03140 
03141   dbus_message_iter_append_done (real);
03142   
03143   return TRUE;
03144 }
03145 
03158 dbus_bool_t
03159 dbus_message_iter_append_named (DBusMessageIter      *iter,
03160                                 const char           *name,
03161                                 const unsigned char  *data,
03162                                 int                   len)
03163 {
03164   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03165 
03166   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03167 
03168   if (!dbus_message_iter_append_type (real, DBUS_TYPE_NAMED))
03169     return FALSE;
03170   
03171    if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, name))
03172     {
03173       _dbus_string_set_length (&real->message->body, real->pos);
03174       return FALSE;
03175     }
03176    
03177   if (!_dbus_marshal_byte_array (&real->message->body, real->message->byte_order, data, len))
03178     {
03179       _dbus_string_set_length (&real->message->body, real->pos);
03180       return FALSE;
03181     }
03182 
03183   dbus_message_iter_append_done (real);
03184   
03185   return TRUE;
03186 }
03187 
03188 
03197 dbus_bool_t
03198 dbus_message_iter_append_dict_key (DBusMessageIter *iter,
03199                                    const char      *value)
03200 {
03201   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03202 
03203   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03204   _dbus_assert (real->type == DBUS_MESSAGE_ITER_TYPE_DICT);
03205   
03206   if (real->wrote_dict_key)
03207     {
03208       _dbus_warn ("Appendinging multiple dict key names\n");
03209       return FALSE;
03210     }
03211   
03212   if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, value))
03213     {
03214       return FALSE;
03215     }
03216 
03217   dbus_message_iter_append_done (real);
03218   real->wrote_dict_key = TRUE;
03219   
03220   return TRUE;
03221 }
03222 
03223 static dbus_bool_t
03224 array_iter_type_mark_done (DBusMessageRealIter *iter)
03225 {
03226   int len_pos;
03227   
03228   if (iter->type == DBUS_MESSAGE_ITER_TYPE_ARRAY)
03229     array_iter_type_mark_done (iter->parent_iter);
03230   else
03231     return TRUE;
03232 
03233   len_pos = _DBUS_ALIGN_VALUE (_dbus_string_get_length (&iter->message->body),
03234                                sizeof (dbus_uint32_t));
03235 
03236   /* Empty length for now, backfill later */
03237   if (!_dbus_marshal_uint32 (&iter->message->body, iter->message->byte_order, 0))
03238     {
03239       _dbus_string_set_length (&iter->message->body, iter->pos);
03240       return FALSE;
03241     }
03242 
03243   iter->container_start = _dbus_string_get_length (&iter->message->body);
03244   iter->container_length_pos = len_pos;
03245   iter->array_type_done = TRUE;
03246 
03247   return TRUE;
03248 }
03249 
03250 static dbus_bool_t
03251 append_array_type (DBusMessageRealIter *real,
03252                    int                  element_type,
03253                    dbus_bool_t         *array_type_done,
03254                    int                 *array_type_pos)
03255 {
03256   int existing_element_type;
03257   
03258   if (!dbus_message_iter_append_type (real, DBUS_TYPE_ARRAY))
03259     return FALSE;
03260   
03261   if (real->type == DBUS_MESSAGE_ITER_TYPE_ARRAY &&
03262       real->array_type_done)
03263     {
03264       existing_element_type = iter_get_array_type (real, array_type_pos);
03265       if (existing_element_type != element_type)
03266         {
03267           _dbus_warn ("Appending array of %s, when expecting array of %s\n",
03268                       _dbus_type_to_string (element_type),
03269                       _dbus_type_to_string (existing_element_type));
03270           _dbus_string_set_length (&real->message->body, real->pos);
03271           return FALSE;
03272         }
03273       if (array_type_done != NULL)
03274           *array_type_done = TRUE;
03275     }
03276   else
03277     {
03278       if (array_type_pos != NULL)
03279         *array_type_pos = _dbus_string_get_length (&real->message->body);
03280       
03281       /* Append element type */
03282       if (!_dbus_string_append_byte (&real->message->body, element_type))
03283         {
03284           _dbus_string_set_length (&real->message->body, real->pos);
03285           return FALSE;
03286         }
03287 
03288       if (array_type_done != NULL)
03289         *array_type_done = element_type != DBUS_TYPE_ARRAY;
03290       
03291       if (element_type != DBUS_TYPE_ARRAY &&
03292           !array_iter_type_mark_done (real))
03293         return FALSE;
03294     }
03295 
03296   return TRUE;
03297 }
03298 
03308 dbus_bool_t
03309 dbus_message_iter_append_array (DBusMessageIter      *iter,
03310                                 DBusMessageIter      *array_iter,
03311                                 int                   element_type)
03312 {
03313   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03314   DBusMessageRealIter *array_real = (DBusMessageRealIter *)array_iter;
03315   int len_pos;
03316   int array_type_pos;
03317   dbus_bool_t array_type_done;
03318 
03319   if (element_type == DBUS_TYPE_NIL)
03320     {
03321       _dbus_warn ("Can't create NIL arrays\n");
03322       return FALSE;
03323     }
03324   
03325   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03326 
03327   if (!append_array_type (real, element_type, &array_type_done, &array_type_pos))
03328     return FALSE;
03329 
03330   len_pos = _DBUS_ALIGN_VALUE (_dbus_string_get_length (&real->message->body), sizeof (dbus_uint32_t));
03331 
03332   if (array_type_done)
03333     {
03334       /* Empty length for now, backfill later */
03335       if (!_dbus_marshal_uint32 (&real->message->body, real->message->byte_order, 0))
03336         {
03337           _dbus_string_set_length (&real->message->body, real->pos);
03338           return FALSE;
03339         }
03340     }
03341   
03342   array_real->parent_iter = real;
03343   array_real->message = real->message;
03344   array_real->changed_stamp = real->message->changed_stamp;
03345   
03346   array_real->type = DBUS_MESSAGE_ITER_TYPE_ARRAY;
03347   array_real->pos = _dbus_string_get_length (&real->message->body);
03348   array_real->end = array_real->end;
03349   
03350   array_real->container_start = array_real->pos;
03351   array_real->container_length_pos = len_pos;
03352   array_real->wrote_dict_key = 0;
03353   array_real->array_type_done = array_type_done;
03354   array_real->array_type_pos = array_type_pos;
03355 
03356   dbus_message_iter_append_done (array_real);
03357   
03358   return TRUE;
03359 }
03360 
03369 dbus_bool_t
03370 dbus_message_iter_append_dict (DBusMessageIter      *iter,
03371                                DBusMessageIter      *dict_iter)
03372 {
03373   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03374   DBusMessageRealIter *dict_real = (DBusMessageRealIter *)dict_iter;
03375   int len_pos;
03376 
03377   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03378 
03379   if (!dbus_message_iter_append_type (real, DBUS_TYPE_DICT))
03380     return FALSE;
03381 
03382   len_pos = _DBUS_ALIGN_VALUE (_dbus_string_get_length (&real->message->body), sizeof (dbus_uint32_t));
03383 
03384   /* Empty length for now, backfill later */
03385   if (!_dbus_marshal_uint32 (&real->message->body, real->message->byte_order, 0))
03386     {
03387       _dbus_string_set_length (&real->message->body, real->pos);
03388       return FALSE;
03389     }
03390   
03391   dict_real->parent_iter = real;
03392   dict_real->message = real->message;
03393   dict_real->changed_stamp = real->message->changed_stamp;
03394   
03395   dict_real->type = DBUS_MESSAGE_ITER_TYPE_DICT;
03396   dict_real->pos = _dbus_string_get_length (&real->message->body);
03397   dict_real->end = dict_real->end;
03398   
03399   dict_real->container_start = dict_real->pos;
03400   dict_real->container_length_pos = len_pos;
03401   dict_real->wrote_dict_key = 0;
03402 
03403   dbus_message_iter_append_done (dict_real);
03404   
03405   return TRUE;
03406 }
03407 
03408 
03417 dbus_bool_t
03418 dbus_message_iter_append_boolean_array (DBusMessageIter     *iter,
03419                                         unsigned const char *value,
03420                                         int                  len)
03421 {
03422   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03423 
03424   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03425 
03426   if (!append_array_type (real, DBUS_TYPE_BOOLEAN, NULL, NULL))
03427     return FALSE;
03428   
03429   if (!_dbus_marshal_byte_array (&real->message->body, real->message->byte_order, value, len))
03430     {
03431       _dbus_string_set_length (&real->message->body, real->pos);
03432       return FALSE;
03433     }
03434 
03435   dbus_message_iter_append_done (real);
03436   
03437   return TRUE;
03438 }
03439 
03448 dbus_bool_t
03449 dbus_message_iter_append_int32_array (DBusMessageIter    *iter,
03450                                       const dbus_int32_t *value,
03451                                       int                 len)
03452 {
03453   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03454 
03455   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03456 
03457   if (!append_array_type (real, DBUS_TYPE_INT32, NULL, NULL))
03458     return FALSE;
03459   
03460   if (!_dbus_marshal_int32_array (&real->message->body, real->message->byte_order, value, len))
03461     {
03462       _dbus_string_set_length (&real->message->body, real->pos);
03463       return FALSE;
03464     }
03465 
03466   dbus_message_iter_append_done (real);
03467   
03468   return TRUE;
03469 }
03470 
03479 dbus_bool_t
03480 dbus_message_iter_append_uint32_array (DBusMessageIter     *iter,
03481                                        const dbus_uint32_t *value,
03482                                        int                  len)
03483 {
03484   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03485 
03486   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03487 
03488   if (!append_array_type (real, DBUS_TYPE_UINT32, NULL, NULL))
03489     return FALSE;
03490   
03491   if (!_dbus_marshal_uint32_array (&real->message->body, real->message->byte_order, value, len))
03492     {
03493       _dbus_string_set_length (&real->message->body, real->pos);
03494       return FALSE;
03495     }
03496 
03497   dbus_message_iter_append_done (real);
03498   
03499   return TRUE;
03500 }
03501 
03502 #ifdef DBUS_HAVE_INT64
03503 
03514 dbus_bool_t
03515 dbus_message_iter_append_int64_array (DBusMessageIter    *iter,
03516                                       const dbus_int64_t *value,
03517                                       int                 len)
03518 {
03519   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03520 
03521   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03522 
03523   if (!append_array_type (real, DBUS_TYPE_INT64, NULL, NULL))
03524     return FALSE;
03525   
03526   if (!_dbus_marshal_int64_array (&real->message->body, real->message->byte_order, value, len))
03527     {
03528       _dbus_string_set_length (&real->message->body, real->pos);
03529       return FALSE;
03530     }
03531 
03532   dbus_message_iter_append_done (real);
03533   
03534   return TRUE;
03535 }
03536 
03547 dbus_bool_t
03548 dbus_message_iter_append_uint64_array (DBusMessageIter     *iter,
03549                                        const dbus_uint64_t *value,
03550                                        int                  len)
03551 {
03552   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03553 
03554   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03555 
03556   if (!append_array_type (real, DBUS_TYPE_UINT64, NULL, NULL))
03557     return FALSE;
03558   
03559   if (!_dbus_marshal_uint64_array (&real->message->body, real->message->byte_order, value, len))
03560     {
03561       _dbus_string_set_length (&real->message->body, real->pos);
03562       return FALSE;
03563     }
03564 
03565   dbus_message_iter_append_done (real);
03566   
03567   return TRUE;
03568 }
03569 #endif /* DBUS_HAVE_INT64 */
03570 
03579 dbus_bool_t
03580 dbus_message_iter_append_double_array (DBusMessageIter *iter,
03581                                        const double    *value,
03582                                        int              len)
03583 {
03584   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03585 
03586   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03587 
03588   if (!append_array_type (real, DBUS_TYPE_DOUBLE, NULL, NULL))
03589     return FALSE;
03590   
03591   if (!_dbus_marshal_double_array (&real->message->body, real->message->byte_order, value, len))
03592     {
03593       _dbus_string_set_length (&real->message->body, real->pos);
03594       return FALSE;
03595     }
03596 
03597   dbus_message_iter_append_done (real);
03598   
03599   return TRUE;
03600 }
03601 
03610 dbus_bool_t
03611 dbus_message_iter_append_byte_array (DBusMessageIter     *iter,
03612                                      unsigned const char *value,
03613                                      int                  len)
03614 {
03615   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03616 
03617   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03618 
03619   if (!append_array_type (real, DBUS_TYPE_BYTE, NULL, NULL))
03620     return FALSE;
03621   
03622   if (!_dbus_marshal_byte_array (&real->message->body, real->message->byte_order, value, len))
03623     {
03624       _dbus_string_set_length (&real->message->body, real->pos);
03625       return FALSE;
03626     }
03627 
03628   dbus_message_iter_append_done (real);
03629   
03630   return TRUE;
03631 }
03632 
03641 dbus_bool_t
03642 dbus_message_iter_append_string_array (DBusMessageIter *iter,
03643                                        const char     **value,
03644                                        int              len)
03645 {
03646   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03647 
03648   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03649 
03650   if (!append_array_type (real, DBUS_TYPE_STRING, NULL, NULL))
03651     return FALSE;
03652   
03653   if (!_dbus_marshal_string_array (&real->message->body, real->message->byte_order, value, len))
03654     {
03655       _dbus_string_set_length (&real->message->body, real->pos);
03656       return FALSE;
03657     }
03658 
03659   dbus_message_iter_append_done (real);
03660   
03661   return TRUE;
03662 }
03663 
03671 dbus_bool_t
03672 dbus_message_set_sender (DBusMessage  *message,
03673                          const char   *sender)
03674 {
03675   _dbus_return_val_if_fail (message != NULL, FALSE);
03676   _dbus_return_val_if_fail (!message->locked, FALSE);
03677 
03678   if (sender == NULL)
03679     {
03680       delete_string_field (message, FIELD_SENDER);
03681       return TRUE;
03682     }
03683   else
03684     {
03685       return set_string_field (message,
03686                                FIELD_SENDER,
03687                                sender);
03688     }
03689 }
03690 
03698 void
03699 dbus_message_set_is_error (DBusMessage *message,
03700                            dbus_bool_t  is_error_reply)
03701 {
03702   char *header;
03703 
03704   _dbus_return_if_fail (message != NULL);
03705   _dbus_return_if_fail (!message->locked);
03706   
03707   header = _dbus_string_get_data_len (&message->header, 1, 1);
03708   
03709   if (is_error_reply)
03710     *header |= DBUS_HEADER_FLAG_ERROR;
03711   else
03712     *header &= ~DBUS_HEADER_FLAG_ERROR;    
03713 }
03714 
03722 dbus_bool_t
03723 dbus_message_get_is_error (DBusMessage *message)
03724 {
03725   const char *header;
03726 
03727   _dbus_return_val_if_fail (message != NULL, FALSE);
03728   
03729   header = _dbus_string_get_const_data_len (&message->header, 1, 1);
03730 
03731   return (*header & DBUS_HEADER_FLAG_ERROR) != 0;
03732 }
03733 
03741 const char*
03742 dbus_message_get_sender (DBusMessage *message)
03743 {
03744   _dbus_return_val_if_fail (message != NULL, NULL);
03745   
03746   return get_string_field (message, FIELD_SENDER, NULL);
03747 }
03748 
03759 dbus_bool_t
03760 dbus_message_has_name (DBusMessage *message,
03761                        const char  *name)
03762 {
03763   const char *n;
03764 
03765   _dbus_return_val_if_fail (message != NULL, FALSE);
03766   _dbus_return_val_if_fail (name != NULL, FALSE);
03767   
03768   n = dbus_message_get_name (message);
03769 
03770   if (n && strcmp (n, name) == 0)
03771     return TRUE;
03772   else
03773     return FALSE;
03774 }
03775 
03786 dbus_bool_t
03787 dbus_message_has_destination (DBusMessage  *message,
03788                               const char   *service)
03789 {
03790   const char *s;
03791 
03792   _dbus_return_val_if_fail (message != NULL, FALSE);
03793   _dbus_return_val_if_fail (service != NULL, FALSE);
03794   
03795   s = dbus_message_get_destination (message);
03796 
03797   if (s && strcmp (s, service) == 0)
03798     return TRUE;
03799   else
03800     return FALSE;
03801 }
03802 
03817 dbus_bool_t
03818 dbus_message_has_sender (DBusMessage  *message,
03819                          const char   *service)
03820 {
03821   const char *s;
03822 
03823   _dbus_assert (service != NULL);
03824   
03825   s = dbus_message_get_sender (message);
03826 
03827   if (s && strcmp (s, service) == 0)
03828     return TRUE;
03829   else
03830     return FALSE;
03831 }
03832 
03850 dbus_bool_t
03851 dbus_set_error_from_message (DBusError   *error,
03852                              DBusMessage *message)
03853 {
03854   char *str;
03855 
03856   _dbus_return_val_if_fail (message != NULL, FALSE);
03857   _dbus_return_val_if_error_is_set (error, FALSE);
03858   
03859   if (!dbus_message_get_is_error (message))
03860     return FALSE;
03861 
03862   str = NULL;
03863   dbus_message_get_args (message, NULL,
03864                          DBUS_TYPE_STRING, &str,
03865                          DBUS_TYPE_INVALID);
03866 
03867   dbus_set_error (error, dbus_message_get_name (message),
03868                   str ? "%s" : NULL, str);
03869 
03870   dbus_free (str);
03871   
03872   return TRUE;
03873 }
03874 
03899 /* we definitely use signed ints for sizes, so don't exceed
03900  * _DBUS_INT_MAX; and add 16 for paranoia, since a message
03901  * over 128M is pretty nuts anyhow.
03902  */
03903 
03907 #define MAX_SANE_MESSAGE_SIZE (_DBUS_INT_MAX/16)
03908 
03913 struct DBusMessageLoader
03914 {
03915   int refcount;        
03917   DBusString data;     
03919   DBusList *messages;  
03921   long max_message_size; 
03923   unsigned int buffer_outstanding : 1; 
03925   unsigned int corrupted : 1; 
03926 };
03927 
03938 #define INITIAL_LOADER_DATA_LEN 32
03939 
03946 DBusMessageLoader*
03947 _dbus_message_loader_new (void)
03948 {
03949   DBusMessageLoader *loader;
03950 
03951   loader = dbus_new0 (DBusMessageLoader, 1);
03952   if (loader == NULL)
03953     return NULL;
03954   
03955   loader->refcount = 1;
03956 
03957   /* Try to cap message size at something that won't *totally* hose
03958    * the system if we have a couple of them.
03959    */
03960   loader->max_message_size = _DBUS_ONE_MEGABYTE * 32;
03961   
03962   if (!_dbus_string_init (&loader->data))
03963     {
03964       dbus_free (loader);
03965       return NULL;
03966     }
03967 
03968   /* preallocate the buffer for speed, ignore failure */
03969   _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN);
03970   _dbus_string_set_length (&loader->data, 0);
03971   
03972   return loader;
03973 }
03974 
03980 void
03981 _dbus_message_loader_ref (DBusMessageLoader *loader)
03982 {
03983   loader->refcount += 1;
03984 }
03985 
03992 void
03993 _dbus_message_loader_unref (DBusMessageLoader *loader)
03994 {
03995   loader->refcount -= 1;
03996   if (loader->refcount == 0)
03997     {
03998       _dbus_list_foreach (&loader->messages,
03999                           (DBusForeachFunction) dbus_message_unref,
04000                           NULL);
04001       _dbus_list_clear (&loader->messages);
04002       _dbus_string_free (&loader->data);
04003       dbus_free (loader);
04004     }
04005 }
04006 
04025 void
04026 _dbus_message_loader_get_buffer (DBusMessageLoader  *loader,
04027                                  DBusString        **buffer)
04028 {
04029   _dbus_assert (!loader->buffer_outstanding);
04030 
04031   *buffer = &loader->data;
04032   
04033   loader->buffer_outstanding = TRUE;
04034 }
04035 
04040 #define DBUS_MINIMUM_HEADER_SIZE 16
04041 
04043 #define FOUR_CHARS_TO_UINT32(a, b, c, d)                \
04044                       ((((dbus_uint32_t)a) << 24) |     \
04045                        (((dbus_uint32_t)b) << 16) |     \
04046                        (((dbus_uint32_t)c) << 8)  |     \
04047                        ((dbus_uint32_t)d))
04048 
04050 #define DBUS_HEADER_FIELD_NAME_AS_UINT32    \
04051   FOUR_CHARS_TO_UINT32 ('n', 'a', 'm', 'e')
04052 
04054 #define DBUS_HEADER_FIELD_SERVICE_AS_UINT32 \
04055   FOUR_CHARS_TO_UINT32 ('s', 'r', 'v', 'c')
04056 
04058 #define DBUS_HEADER_FIELD_REPLY_AS_UINT32   \
04059   FOUR_CHARS_TO_UINT32 ('r', 'p', 'l', 'y')
04060 
04062 #define DBUS_HEADER_FIELD_SENDER_AS_UINT32  \
04063   FOUR_CHARS_TO_UINT32 ('s', 'n', 'd', 'r')
04064 
04065 static dbus_bool_t
04066 decode_string_field (const DBusString   *data,
04067                      HeaderField         fields[FIELD_LAST],
04068                      int                 pos,
04069                      int                 type,
04070                      int                 field,
04071                      const char         *field_name)
04072 {
04073   DBusString tmp;
04074   int string_data_pos;
04075   
04076   if (fields[field].offset >= 0)
04077     {
04078       _dbus_verbose ("%s field provided twice\n",
04079                      field_name);
04080       return FALSE;
04081     }
04082 
04083   if (type != DBUS_TYPE_STRING)
04084     {
04085       _dbus_verbose ("%s field has wrong type %s\n",
04086                      field_name, _dbus_type_to_string (type));
04087       return FALSE;
04088     }
04089 
04090   /* skip padding after typecode, skip string length;
04091    * we assume that the string arg has already been validated
04092    * for sanity and UTF-8
04093    */
04094   string_data_pos = _DBUS_ALIGN_VALUE (pos, 4) + 4;
04095   _dbus_assert (string_data_pos < _dbus_string_get_length (data));
04096   
04097   _dbus_string_init_const (&tmp,
04098                            _dbus_string_get_const_data (data) + string_data_pos);
04099 
04100   if (field == FIELD_NAME)
04101     {
04102       if (!_dbus_string_validate_name (&tmp, 0, _dbus_string_get_length (&tmp)))
04103         {
04104           _dbus_verbose ("%s field has invalid content \"%s\"\n",
04105                          field_name, _dbus_string_get_const_data (&tmp));
04106           return FALSE;
04107         }
04108       
04109       if (_dbus_string_starts_with_c_str (&tmp,
04110                                           DBUS_NAMESPACE_LOCAL_MESSAGE))
04111         {
04112           _dbus_verbose ("Message is in the local namespace\n");
04113           return FALSE;
04114         }
04115     }
04116   else
04117     {
04118       if (!_dbus_string_validate_service (&tmp, 0, _dbus_string_get_length (&tmp)))
04119         {
04120           _dbus_verbose ("%s field has invalid content \"%s\"\n",
04121                          field_name, _dbus_string_get_const_data (&tmp));
04122           return FALSE;
04123         }
04124     }
04125   
04126   fields[field].offset = _DBUS_ALIGN_VALUE (pos, 4);
04127   
04128 #if 0
04129   _dbus_verbose ("Found field %s name at offset %d\n",
04130                  field_name, fields[field].offset);
04131 #endif
04132 
04133   return TRUE;
04134 }
04135 
04136 static dbus_bool_t
04137 decode_header_data (const DBusString   *data,
04138                     int                 header_len,
04139                     int                 byte_order,
04140                     HeaderField         fields[FIELD_LAST],
04141                     int                *message_padding)
04142 {
04143   const char *field;
04144   int pos, new_pos;
04145   int i;
04146   int type;
04147   
04148   if (header_len < 16)
04149     return FALSE;
04150   
04151   i = 0;
04152   while (i < FIELD_LAST)
04153     {
04154       fields[i].offset = -1;
04155       ++i;
04156     }
04157   
04158   fields[FIELD_HEADER_LENGTH].offset = 4;
04159   fields[FIELD_BODY_LENGTH].offset = 8;   
04160   fields[FIELD_CLIENT_SERIAL].offset = 12;
04161   
04162   /* Now handle the named fields. A real named field is at least 4
04163    * bytes for the name, plus a type code (1 byte) plus padding.  So
04164    * if we have less than 8 bytes left, it must be alignment padding,
04165    * not a field. While >= 8 bytes can't be entirely alignment
04166    * padding.
04167    */  
04168   pos = 16;
04169   while ((pos + 7) < header_len)
04170     {
04171       pos = _DBUS_ALIGN_VALUE (pos, 4);
04172       
04173       if ((pos + 4) > header_len)
04174         return FALSE;      
04175       
04176       field =_dbus_string_get_const_data_len (data, pos, 4);
04177       pos += 4;
04178 
04179       _dbus_assert (_DBUS_ALIGN_ADDRESS (field, 4) == field);
04180       
04181       if (!_dbus_marshal_validate_type (data, pos, &type, &pos))
04182         {
04183           _dbus_verbose ("Failed to validate type of named header field\n");
04184           return FALSE;
04185         }
04186       
04187       if (!_dbus_marshal_validate_arg (data, byte_order, 0, type, -1, pos, &new_pos))
04188         {
04189           _dbus_verbose ("Failed to validate argument to named header field\n");
04190           return FALSE;
04191         }
04192 
04193       if (new_pos > header_len)
04194         {
04195           _dbus_verbose ("Named header field tries to extend beyond header length\n");
04196           return FALSE;
04197         }
04198       
04199       switch (DBUS_UINT32_FROM_BE (*(int*)field))
04200         {
04201         case DBUS_HEADER_FIELD_SERVICE_AS_UINT32:
04202           if (!decode_string_field (data, fields, pos, type,
04203                                     FIELD_SERVICE,
04204                                     DBUS_HEADER_FIELD_SERVICE))
04205             return FALSE;
04206           break;
04207 
04208         case DBUS_HEADER_FIELD_NAME_AS_UINT32:
04209           if (!decode_string_field (data, fields, pos, type,
04210                                     FIELD_NAME,
04211                                     DBUS_HEADER_FIELD_NAME))
04212             return FALSE;
04213           break;
04214 
04215         case DBUS_HEADER_FIELD_SENDER_AS_UINT32:
04216           if (!decode_string_field (data, fields, pos, type,
04217                                     FIELD_SENDER,
04218                                     DBUS_HEADER_FIELD_SENDER))
04219             return FALSE;
04220           break;
04221           
04222         case DBUS_HEADER_FIELD_REPLY_AS_UINT32:
04223           if (fields[FIELD_REPLY_SERIAL].offset >= 0)
04224             {
04225               _dbus_verbose ("%s field provided twice\n",
04226                              DBUS_HEADER_FIELD_REPLY);
04227               return FALSE;
04228             }
04229 
04230           if (type != DBUS_TYPE_UINT32)
04231             {
04232               _dbus_verbose ("%s field has wrong type\n", DBUS_HEADER_FIELD_REPLY);
04233               return FALSE;
04234             }
04235           
04236           fields[FIELD_REPLY_SERIAL].offset = _DBUS_ALIGN_VALUE (pos, 4);
04237 
04238           _dbus_verbose ("Found reply serial at offset %d\n",
04239                          fields[FIELD_REPLY_SERIAL].offset);
04240           break;
04241 
04242         default:
04243           _dbus_verbose ("Ignoring an unknown header field: %.4s at offset %d\n",
04244                          field, pos);
04245         }
04246       
04247       pos = new_pos;
04248     }
04249 
04250   if (pos < header_len)
04251     {
04252       /* Alignment padding, verify that it's nul */
04253       _dbus_assert ((header_len - pos) < 8);
04254 
04255       if (!_dbus_string_validate_nul (data,
04256                                       pos, (header_len - pos)))
04257         {
04258           _dbus_verbose ("header alignment padding is not nul\n");
04259           return FALSE;
04260         }
04261     }
04262 
04263   /* Name field is mandatory */
04264   if (fields[FIELD_NAME].offset < 0)
04265     {
04266       _dbus_verbose ("No %s field provided\n",
04267                      DBUS_HEADER_FIELD_NAME);
04268       return FALSE;
04269     }
04270   
04271   if (message_padding)
04272     *message_padding = header_len - pos;  
04273   
04274   return TRUE;
04275 }
04276 
04287 void
04288 _dbus_message_loader_return_buffer (DBusMessageLoader  *loader,
04289                                     DBusString         *buffer,
04290                                     int                 bytes_read)
04291 {
04292   _dbus_assert (loader->buffer_outstanding);
04293   _dbus_assert (buffer == &loader->data);
04294 
04295   loader->buffer_outstanding = FALSE;
04296 }
04297 
04304 dbus_bool_t
04305 _dbus_message_loader_queue_messages (DBusMessageLoader *loader)
04306 {
04307   if (loader->corrupted)
04308     return TRUE;
04309 
04310   while (_dbus_string_get_length (&loader->data) >= 16)
04311     {
04312       DBusMessage *message;      
04313       const char *header_data;
04314       int byte_order, header_len, body_len, header_padding;
04315       dbus_uint32_t header_len_unsigned, body_len_unsigned;
04316       
04317       header_data = _dbus_string_get_const_data_len (&loader->data, 0, 16);
04318 
04319       _dbus_assert (_DBUS_ALIGN_ADDRESS (header_data, 4) == header_data);
04320 
04321       if (header_data[2] != DBUS_MAJOR_PROTOCOL_VERSION)
04322         {
04323           _dbus_verbose ("Message has protocol version %d ours is %d\n",
04324                          (int) header_data[2], DBUS_MAJOR_PROTOCOL_VERSION);
04325           loader->corrupted = TRUE;
04326           return TRUE;
04327         }
04328       
04329       byte_order = header_data[0];
04330 
04331       if (byte_order != DBUS_LITTLE_ENDIAN &&
04332           byte_order != DBUS_BIG_ENDIAN)
04333         {
04334           _dbus_verbose ("Message with bad byte order '%c' received\n",
04335                          byte_order);
04336           loader->corrupted = TRUE;
04337           return TRUE;
04338         }
04339 
04340       header_len_unsigned = _dbus_unpack_uint32 (byte_order, header_data + 4);
04341       body_len_unsigned = _dbus_unpack_uint32 (byte_order, header_data + 8);
04342 
04343       if (header_len_unsigned < 16)
04344         {
04345           _dbus_verbose ("Message had broken too-small header length %u\n",
04346                          header_len_unsigned);
04347           loader->corrupted = TRUE;
04348           return TRUE;
04349         }
04350 
04351       if (header_len_unsigned > (unsigned) MAX_SANE_MESSAGE_SIZE ||
04352           body_len_unsigned > (unsigned) MAX_SANE_MESSAGE_SIZE)
04353         {
04354           _dbus_verbose ("Header or body length too large (%u %u)\n",
04355                          header_len_unsigned,
04356                          body_len_unsigned);
04357           loader->corrupted = TRUE;
04358           return TRUE;
04359         }
04360 
04361       /* Now that we know the values are in signed range, get
04362        * rid of stupid unsigned, just causes bugs
04363        */
04364       header_len = header_len_unsigned;
04365       body_len = body_len_unsigned;
04366 
04367       if (_DBUS_ALIGN_VALUE (header_len, 8) != header_len_unsigned)
04368         {
04369           
04370           _dbus_verbose ("header length %d is not aligned to 8 bytes\n",
04371                          header_len);
04372           loader->corrupted = TRUE;
04373           return TRUE;
04374         }
04375       
04376       if (header_len + body_len > loader->max_message_size)
04377         {
04378           _dbus_verbose ("Message claimed length header = %d body = %d exceeds max message length %ld\n",
04379                          header_len, body_len, loader->max_message_size);
04380           loader->corrupted = TRUE;
04381           return TRUE;
04382         }
04383 
04384       if (_dbus_string_get_length (&loader->data) >= (header_len + body_len))
04385         {
04386           HeaderField fields[FIELD_LAST];
04387           int i;
04388           int next_arg;          
04389 
04390 #if 0
04391           _dbus_verbose_bytes_of_string (&loader->data, 0, header_len + body_len);
04392 #endif    
04393           if (!decode_header_data (&loader->data, header_len, byte_order,
04394                                    fields, &header_padding))
04395             {
04396               _dbus_verbose ("Header was invalid\n");
04397               loader->corrupted = TRUE;
04398               return TRUE;
04399             }
04400           
04401           next_arg = header_len;
04402           while (next_arg < (header_len + body_len))
04403             {
04404               int type;
04405               int prev = next_arg;
04406 
04407               if (!_dbus_marshal_validate_type (&loader->data, next_arg,
04408                                                 &type, &next_arg))
04409                 {
04410                   _dbus_verbose ("invalid typecode at offset %d\n", prev);
04411                   loader->corrupted = TRUE;
04412                   return TRUE;
04413                 }
04414       
04415               if (!_dbus_marshal_validate_arg (&loader->data,
04416                                                byte_order,
04417                                                0,
04418                                                type, -1,
04419                                                next_arg,
04420                                                &next_arg))
04421                 {
04422                   _dbus_verbose ("invalid type data at %d, next_arg\n", next_arg);
04423                   loader->corrupted = TRUE;
04424                   return TRUE;
04425                 }
04426 
04427               _dbus_assert (next_arg > prev);
04428             }
04429           
04430           if (next_arg > (header_len + body_len))
04431             {
04432               _dbus_verbose ("end of last arg at %d but message has len %d+%d=%d\n",
04433                              next_arg, header_len, body_len,
04434                              header_len + body_len);
04435               loader->corrupted = TRUE;
04436               return TRUE;
04437             }
04438 
04439           message = dbus_message_new_empty_header ();
04440           if (message == NULL)
04441             {
04442               _dbus_verbose ("Failed to allocate empty message\n");
04443               return FALSE;
04444             }
04445 
04446           message->byte_order = byte_order;
04447           message->header_padding = header_padding;
04448           
04449           /* Copy in the offsets we found */
04450           i = 0;
04451           while (i < FIELD_LAST)
04452             {
04453               message->header_fields[i] = fields[i];
04454               ++i;
04455             }
04456           
04457           if (!_dbus_list_append (&loader->messages, message))
04458             {
04459               _dbus_verbose ("Failed to append new message to loader queue\n");
04460               dbus_message_unref (message);
04461               return FALSE;
04462             }
04463 
04464           _dbus_assert (_dbus_string_get_length (&message->header) == 0);
04465           _dbus_assert (_dbus_string_get_length (&message->body) == 0);
04466 
04467           _dbus_assert (_dbus_string_get_length (&loader->data) >=
04468                         (header_len + body_len));
04469           
04470           if (!_dbus_string_move_len (&loader->data, 0, header_len, &message->header, 0))
04471             {
04472               _dbus_verbose ("Failed to move header into new message\n");
04473               _dbus_list_remove_last (&loader->messages, message);
04474               dbus_message_unref (message);
04475               return FALSE;
04476             }
04477           
04478           if (!_dbus_string_move_len (&loader->data, 0, body_len, &message->body, 0))
04479             {
04480               dbus_bool_t result;
04481 
04482               _dbus_verbose ("Failed to move body into new message\n");
04483               
04484               /* put the header back, we'll try again later */
04485               result = _dbus_string_copy_len (&message->header, 0, header_len,
04486                                               &loader->data, 0);
04487               _dbus_assert (result); /* because DBusString never reallocs smaller */
04488 
04489               _dbus_list_remove_last (&loader->messages, message);
04490               dbus_message_unref (message);
04491               return FALSE;
04492             }
04493 
04494           _dbus_assert (_dbus_string_get_length (&message->header) == header_len);
04495           _dbus_assert (_dbus_string_get_length (&message->body) == body_len);
04496 
04497           /* Fill in caches (we checked the types of these fields
04498            * earlier)
04499            */
04500           message->reply_serial = get_uint_field (message,
04501                                                   FIELD_REPLY_SERIAL);
04502           message->client_serial = get_uint_field (message,
04503                                                    FIELD_CLIENT_SERIAL);
04504           
04505           _dbus_verbose ("Loaded message %p\n", message);
04506         }
04507       else
04508         return TRUE;
04509     }
04510 
04511   return TRUE;
04512 }
04513 
04521 DBusMessage*
04522 _dbus_message_loader_peek_message (DBusMessageLoader *loader)
04523 {
04524   if (loader->messages)
04525     return loader->messages->data;
04526   else
04527     return NULL;
04528 }
04529 
04538 DBusMessage*
04539 _dbus_message_loader_pop_message (DBusMessageLoader *loader)
04540 {
04541   return _dbus_list_pop_first (&loader->messages);
04542 }
04543 
04552 DBusList*
04553 _dbus_message_loader_pop_message_link (DBusMessageLoader *loader)
04554 {
04555   return _dbus_list_pop_first_link (&loader->messages);
04556 }
04557 
04564 void
04565 _dbus_message_loader_putback_message_link (DBusMessageLoader  *loader,
04566                                            DBusList           *link)
04567 {
04568   _dbus_list_prepend_link (&loader->messages, link);
04569 }
04570 
04580 dbus_bool_t
04581 _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader)
04582 {
04583   return loader->corrupted;
04584 }
04585 
04592 void
04593 _dbus_message_loader_set_max_message_size (DBusMessageLoader  *loader,
04594                                            long                size)
04595 {
04596   if (size > MAX_SANE_MESSAGE_SIZE)
04597     {
04598       _dbus_verbose ("clamping requested max message size %ld to %d\n",
04599                      size, MAX_SANE_MESSAGE_SIZE);
04600       size = MAX_SANE_MESSAGE_SIZE;
04601     }
04602   loader->max_message_size = size;
04603 }
04604 
04611 long
04612 _dbus_message_loader_get_max_message_size (DBusMessageLoader  *loader)
04613 {
04614   return loader->max_message_size;
04615 }
04616 
04617 static DBusDataSlotAllocator slot_allocator;
04618 _DBUS_DEFINE_GLOBAL_LOCK (message_slots);
04619 
04634 dbus_bool_t
04635 dbus_message_allocate_data_slot (dbus_int32_t *slot_p)
04636 {
04637   return _dbus_data_slot_allocator_alloc (&slot_allocator,
04638                                           _DBUS_LOCK_NAME (message_slots),
04639                                           slot_p);
04640 }
04641 
04653 void
04654 dbus_message_free_data_slot (dbus_int32_t *slot_p)
04655 {
04656   _dbus_return_if_fail (*slot_p >= 0);
04657   
04658   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
04659 }
04660 
04674 dbus_bool_t
04675 dbus_message_set_data (DBusMessage     *message,
04676                        dbus_int32_t     slot,
04677                        void            *data,
04678                        DBusFreeFunction free_data_func)
04679 {
04680   DBusFreeFunction old_free_func;
04681   void *old_data;
04682   dbus_bool_t retval;
04683 
04684   _dbus_return_val_if_fail (message != NULL, FALSE);
04685   _dbus_return_val_if_fail (slot >= 0, FALSE);
04686 
04687   retval = _dbus_data_slot_list_set (&slot_allocator,
04688                                      &message->slot_list,
04689                                      slot, data, free_data_func,
04690                                      &old_free_func, &old_data);
04691 
04692   if (retval)
04693     {
04694       /* Do the actual free outside the message lock */
04695       if (old_free_func)
04696         (* old_free_func) (old_data);
04697     }
04698 
04699   return retval;
04700 }
04701 
04710 void*
04711 dbus_message_get_data (DBusMessage   *message,
04712                        dbus_int32_t   slot)
04713 {
04714   void *res;
04715 
04716   _dbus_return_val_if_fail (message != NULL, NULL);
04717   
04718   res = _dbus_data_slot_list_get (&slot_allocator,
04719                                   &message->slot_list,
04720                                   slot);
04721 
04722   return res;
04723 }
04724 
04726 #ifdef DBUS_BUILD_TESTS
04727 #include "dbus-test.h"
04728 #include <stdio.h>
04729 
04730 static void
04731 message_iter_test (DBusMessage *message)
04732 {
04733   DBusMessageIter iter, dict, array, array2;
04734   char *str;
04735   unsigned char *data;
04736   dbus_int32_t *our_int_array;
04737   int len;
04738   
04739   dbus_message_iter_init (message, &iter);
04740 
04741   /* String tests */
04742   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING)
04743     _dbus_assert_not_reached ("Argument type isn't string");
04744 
04745   str = dbus_message_iter_get_string (&iter);
04746   if (strcmp (str, "Test string") != 0)
04747     _dbus_assert_not_reached ("Strings differ");
04748   dbus_free (str);
04749 
04750   if (!dbus_message_iter_next (&iter))
04751     _dbus_assert_not_reached ("Reached end of arguments");
04752 
04753   /* Signed integer tests */
04754   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INT32)
04755     _dbus_assert_not_reached ("Argument type isn't int32");
04756 
04757   if (dbus_message_iter_get_int32 (&iter) != -0x12345678)
04758     _dbus_assert_not_reached ("Signed integers differ");
04759 
04760   if (!dbus_message_iter_next (&iter))
04761     _dbus_assert_not_reached ("Reached end of fields");
04762   
04763   /* Unsigned integer tests */
04764   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_UINT32)
04765     _dbus_assert_not_reached ("Argument type isn't int32");
04766 
04767   if (dbus_message_iter_get_uint32 (&iter) != 0xedd1e)
04768     _dbus_assert_not_reached ("Unsigned integers differ");
04769 
04770   if (!dbus_message_iter_next (&iter))
04771     _dbus_assert_not_reached ("Reached end of arguments");
04772 
04773   /* Double tests */
04774   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_DOUBLE)
04775     _dbus_assert_not_reached ("Argument type isn't double");
04776 
04777   if (dbus_message_iter_get_double (&iter) != 3.14159)
04778     _dbus_assert_not_reached ("Doubles differ");
04779 
04780   if (!dbus_message_iter_next (&iter))
04781     _dbus_assert_not_reached ("Reached end of arguments");
04782 
04783   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY)
04784     _dbus_assert_not_reached ("Argument type not an array");
04785 
04786   if (dbus_message_iter_get_array_type (&iter) != DBUS_TYPE_DOUBLE)
04787     _dbus_assert_not_reached ("Array type not double");
04788 
04789   
04790   if (!dbus_message_iter_init_array_iterator (&iter, &array, NULL))
04791     _dbus_assert_not_reached ("Array init failed");
04792 
04793   if (dbus_message_iter_get_arg_type (&array) != DBUS_TYPE_DOUBLE)
04794     _dbus_assert_not_reached ("Argument type isn't double");
04795 
04796   if (dbus_message_iter_get_double (&array) != 1.5)
04797     _dbus_assert_not_reached ("Unsigned integers differ");
04798 
04799   if (!dbus_message_iter_next (&array))
04800     _dbus_assert_not_reached ("Reached end of arguments");
04801 
04802   if (dbus_message_iter_get_arg_type (&array) != DBUS_TYPE_DOUBLE)
04803     _dbus_assert_not_reached ("Argument type isn't double");
04804 
04805   if (dbus_message_iter_get_double (&array) != 2.5)
04806     _dbus_assert_not_reached ("Unsigned integers differ");
04807 
04808   if (dbus_message_iter_next (&array))
04809     _dbus_assert_not_reached ("Didn't reach end of arguments");
04810   
04811   if (!dbus_message_iter_next (&iter))
04812     _dbus_assert_not_reached ("Reached end of arguments");
04813   
04814 
04815   /* dict */
04816 
04817   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_DICT)
04818     _dbus_assert_not_reached ("not dict type");
04819      
04820   if (!dbus_message_iter_init_dict_iterator (&iter, &dict))
04821     _dbus_assert_not_reached ("dict iter failed");
04822 
04823   str = dbus_message_iter_get_dict_key (&dict);
04824   if (str == NULL || strcmp (str, "test") != 0)
04825     _dbus_assert_not_reached ("wrong dict key");
04826   dbus_free (str);
04827 
04828   if (dbus_message_iter_get_arg_type (&dict) != DBUS_TYPE_UINT32)
04829     _dbus_assert_not_reached ("wrong dict entry type");
04830 
04831   if (dbus_message_iter_get_uint32 (&dict) != 0xDEADBEEF)
04832     _dbus_assert_not_reached ("wrong dict entry value");
04833 
04834   if (!dbus_message_iter_next (&dict))
04835     _dbus_assert_not_reached ("reached end of dict");
04836   
04837   /* array of array of int32 (in dict) */
04838 
04839   str = dbus_message_iter_get_dict_key (&dict);
04840   if (str == NULL || strcmp (str, "array") != 0)
04841     _dbus_assert_not_reached ("wrong dict key");
04842   dbus_free (str);
04843   
04844   if (dbus_message_iter_get_arg_type (&dict) != DBUS_TYPE_ARRAY)
04845     _dbus_assert_not_reached ("Argument type not an array");
04846 
04847   if (dbus_message_iter_get_array_type (&dict) != DBUS_TYPE_ARRAY)
04848     _dbus_assert_not_reached ("Array type not array");
04849 
04850   if (!dbus_message_iter_init_array_iterator (&dict, &array, NULL))
04851     _dbus_assert_not_reached ("Array init failed");
04852 
04853   if (dbus_message_iter_get_arg_type (&array) != DBUS_TYPE_ARRAY)
04854     _dbus_assert_not_reached ("Argument type isn't array");
04855   
04856   if (dbus_message_iter_get_array_type (&array) != DBUS_TYPE_INT32)
04857     _dbus_assert_not_reached ("Array type not int32");
04858   
04859   if (!dbus_message_iter_init_array_iterator (&array, &array2, NULL))
04860     _dbus_assert_not_reached ("Array init failed");
04861 
04862   if (dbus_message_iter_get_arg_type (&array2) != DBUS_TYPE_INT32)
04863     _dbus_assert_not_reached ("Argument type isn't int32");
04864 
04865   if (dbus_message_iter_get_int32 (&array2) != 0x12345678)
04866     _dbus_assert_not_reached ("Signed integers differ");
04867 
04868   if (!dbus_message_iter_next (&array2))
04869     _dbus_assert_not_reached ("Reached end of arguments");
04870 
04871   if (dbus_message_iter_get_int32 (&array2) != 0x23456781)
04872     _dbus_assert_not_reached ("Signed integers differ");
04873 
04874   if (dbus_message_iter_next (&array2))
04875     _dbus_assert_not_reached ("Didn't reached end of arguments");
04876 
04877   if (!dbus_message_iter_next (&array))
04878     _dbus_assert_not_reached ("Reached end of arguments");
04879 
04880   if (dbus_message_iter_get_array_type (&array) != DBUS_TYPE_INT32)
04881     _dbus_assert_not_reached ("Array type not int32");
04882 
04883   if (!dbus_message_iter_get_int32_array (&array,
04884                                           &our_int_array,
04885                                           &len))
04886     _dbus_assert_not_reached ("couldn't get int32 array");
04887 
04888   _dbus_assert (len == 3);
04889   _dbus_assert (our_int_array[0] == 0x34567812 &&
04890                 our_int_array[1] == 0x45678123 &&
04891                 our_int_array[2] == 0x56781234);
04892   dbus_free (our_int_array);
04893   
04894   if (dbus_message_iter_next (&array))
04895     _dbus_assert_not_reached ("Didn't reach end of array");
04896 
04897   if (dbus_message_iter_next (&dict))
04898     _dbus_assert_not_reached ("Didn't reach end of dict");
04899   
04900   if (!dbus_message_iter_next (&iter))
04901     _dbus_assert_not_reached ("Reached end of arguments");
04902   
04903   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_BYTE)
04904     {
04905       _dbus_warn ("type was: %d\n", dbus_message_iter_get_arg_type (&iter));
04906       _dbus_assert_not_reached ("wrong type after dict (should be byte)");
04907     }
04908   
04909   if (dbus_message_iter_get_byte (&iter) != 0xF0)
04910     _dbus_assert_not_reached ("wrong value after dict");
04911 
04912 
04913   if (!dbus_message_iter_next (&iter))
04914     _dbus_assert_not_reached ("Reached end of arguments");
04915   
04916   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_NIL)
04917     _dbus_assert_not_reached ("not a nil type");
04918   
04919   if (!dbus_message_iter_next (&iter))
04920     _dbus_assert_not_reached ("Reached end of arguments");
04921   
04922   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_NAMED)
04923     _dbus_assert_not_reached ("wrong type after dict");
04924 
04925   if (!dbus_message_iter_get_named (&iter, &str, &data, &len))
04926     _dbus_assert_not_reached ("failed to get named");
04927 
04928   _dbus_assert (strcmp (str, "named")==0);
04929   _dbus_assert (len == 5);
04930   _dbus_assert (strcmp (data, "data")==0);
04931   dbus_free (str);
04932   dbus_free (data);
04933   
04934   if (dbus_message_iter_next (&iter))
04935     _dbus_assert_not_reached ("Didn't reach end of arguments");
04936 }
04937 
04938 
04939 static dbus_bool_t
04940 check_message_handling_type (DBusMessageIter *iter,
04941                              int type)
04942 {
04943   DBusMessageIter child_iter;
04944   
04945   switch (type)
04946     {
04947     case DBUS_TYPE_NIL:
04948       break;
04949     case DBUS_TYPE_BYTE:
04950       dbus_message_iter_get_byte (iter);
04951       break;
04952     case DBUS_TYPE_BOOLEAN:
04953       dbus_message_iter_get_boolean (iter);
04954       break;
04955     case DBUS_TYPE_INT32:
04956       dbus_message_iter_get_int32 (iter);
04957       break;
04958     case DBUS_TYPE_UINT32:
04959       dbus_message_iter_get_uint32 (iter);
04960       break;
04961     case DBUS_TYPE_INT64:
04962 #ifdef DBUS_HAVE_INT64
04963       dbus_message_iter_get_int64 (iter);
04964 #endif
04965       break;
04966     case DBUS_TYPE_UINT64:
04967 #ifdef DBUS_HAVE_INT64
04968       dbus_message_iter_get_uint64 (iter);
04969 #endif
04970       break;
04971     case DBUS_TYPE_DOUBLE:
04972       dbus_message_iter_get_double (iter);
04973       break;
04974     case DBUS_TYPE_STRING:
04975       {
04976         char *str;
04977         str = dbus_message_iter_get_string (iter);
04978         if (str == NULL)
04979           {
04980             _dbus_warn ("NULL string in message\n");
04981             return FALSE;
04982           }
04983         dbus_free (str);
04984       }
04985       break;
04986     case DBUS_TYPE_NAMED:
04987       {
04988         char *name;
04989         unsigned char *data;
04990         int len;
04991         
04992         if (!dbus_message_iter_get_named (iter, &name, &data, &len))
04993           {
04994             _dbus_warn ("error reading name from named type\n");
04995             return FALSE;
04996           }
04997         dbus_free (data);
04998         dbus_free (name);
04999       }
05000       break;
05001     case DBUS_TYPE_ARRAY:
05002       {
05003         int array_type;
05004 
05005         if (!dbus_message_iter_init_array_iterator (iter, &child_iter, &array_type))
05006           {
05007             _dbus_warn ("Failed to init array iterator\n");
05008             return FALSE;
05009           }
05010 
05011         while (dbus_message_iter_has_next (&child_iter))
05012           {
05013             if (!check_message_handling_type (&child_iter, array_type))
05014               {
05015                 _dbus_warn ("error in array element\n");
05016                 return FALSE;
05017               }
05018             
05019             if (!dbus_message_iter_next (&child_iter))
05020               break;
05021           }
05022       }
05023       break;
05024     case DBUS_TYPE_DICT:
05025       {
05026         int entry_type;
05027         char *key;
05028         
05029         if (!dbus_message_iter_init_dict_iterator (iter, &child_iter))
05030           {
05031             _dbus_warn ("Failed to init dict iterator\n");
05032             return FALSE;
05033           }
05034 
05035         while ((entry_type = dbus_message_iter_get_arg_type (&child_iter)) != DBUS_TYPE_INVALID)
05036           {
05037             key = dbus_message_iter_get_dict_key (&child_iter);
05038             if (key == NULL)
05039               {
05040                 _dbus_warn ("error reading dict key\n");
05041                 return FALSE;
05042               }
05043             dbus_free (key);
05044             
05045             if (!check_message_handling_type (&child_iter, entry_type))
05046               {
05047                 _dbus_warn ("error in dict value\n");
05048                 return FALSE;
05049               }
05050             
05051             if (!dbus_message_iter_next (&child_iter))
05052               break;
05053           }
05054       }
05055       break;
05056       
05057     default:
05058       _dbus_warn ("unknown type %d\n", type);
05059       return FALSE;
05060       break;
05061     }
05062   return TRUE;
05063 }
05064   
05065   
05066 static dbus_bool_t
05067 check_message_handling (DBusMessage *message)
05068 {
05069   DBusMessageIter iter;
05070   int type;
05071   dbus_bool_t retval;
05072   dbus_uint32_t client_serial;
05073   
05074   retval = FALSE;
05075   
05076   client_serial = dbus_message_get_serial (message);
05077 
05078   /* can't use set_serial due to the assertions at the start of it */
05079   set_uint_field (message, FIELD_CLIENT_SERIAL,
05080                   client_serial);
05081   
05082   if (client_serial != dbus_message_get_serial (message))
05083     {
05084       _dbus_warn ("get/set cycle for client_serial did not succeed\n");
05085       goto failed;
05086     }
05087   
05088   /* If we implement message_set_arg (message, n, value)
05089    * then we would want to test it here
05090    */
05091 
05092   dbus_message_iter_init (message, &iter);
05093   while ((type = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID)
05094     {
05095       if (!check_message_handling_type (&iter, type))
05096         goto failed;
05097 
05098       if (!dbus_message_iter_next (&iter))
05099         break;
05100     }
05101   
05102   retval = TRUE;
05103   
05104  failed:
05105   return retval;
05106 }
05107 
05108 static dbus_bool_t
05109 check_have_valid_message (DBusMessageLoader *loader)
05110 {
05111   DBusMessage *message;
05112   dbus_bool_t retval;
05113 
05114   message = NULL;
05115   retval = FALSE;
05116 
05117   if (!_dbus_message_loader_queue_messages (loader))
05118     _dbus_assert_not_reached ("no memory to queue messages");
05119   
05120   if (_dbus_message_loader_get_is_corrupted (loader))
05121     {
05122       _dbus_warn ("loader corrupted on message that was expected to be valid\n");
05123       goto failed;
05124     }
05125   
05126   message = _dbus_message_loader_pop_message (loader);
05127   if (message == NULL)
05128     {
05129       _dbus_warn ("didn't load message that was expected to be valid (message not popped)\n");
05130       goto failed;
05131     }
05132   
05133   if (_dbus_string_get_length (&loader->data) > 0)
05134     {
05135       _dbus_warn ("had leftover bytes from expected-to-be-valid single message\n");
05136       goto failed;
05137     }
05138 
05139   /* Verify that we're able to properly deal with the message.
05140    * For example, this would detect improper handling of messages
05141    * in nonstandard byte order.
05142    */
05143   if (!check_message_handling (message))
05144     goto failed;  
05145   
05146   retval = TRUE;
05147 
05148  failed:
05149   if (message)
05150     dbus_message_unref (message);
05151 
05152   return retval;
05153 }
05154 
05155 static dbus_bool_t
05156 check_invalid_message (DBusMessageLoader *loader)
05157 {
05158   dbus_bool_t retval;
05159 
05160   retval = FALSE;
05161 
05162   if (!_dbus_message_loader_queue_messages (loader))
05163     _dbus_assert_not_reached ("no memory to queue messages");
05164   
05165   if (!_dbus_message_loader_get_is_corrupted (loader))
05166     {
05167       _dbus_warn ("loader not corrupted on message that was expected to be invalid\n");
05168       goto failed;
05169     }
05170 
05171   retval = TRUE;
05172 
05173  failed:
05174   return retval;
05175 }
05176 
05177 static dbus_bool_t
05178 check_incomplete_message (DBusMessageLoader *loader)
05179 {
05180   DBusMessage *message;
05181   dbus_bool_t retval;
05182 
05183   message = NULL;
05184   retval = FALSE;
05185 
05186   if (!_dbus_message_loader_queue_messages (loader))
05187     _dbus_assert_not_reached ("no memory to queue messages");
05188   
05189   if (_dbus_message_loader_get_is_corrupted (loader))
05190     {
05191       _dbus_warn ("loader corrupted on message that was expected to be valid (but incomplete)\n");
05192       goto failed;
05193     }
05194   
05195   message = _dbus_message_loader_pop_message (loader);
05196   if (message != NULL)
05197     {
05198       _dbus_warn ("loaded message that was expected to be incomplete\n");
05199       goto failed;
05200     }
05201 
05202   retval = TRUE;
05203 
05204  failed:
05205   if (message)
05206     dbus_message_unref (message);
05207   return retval;
05208 }
05209 
05210 static dbus_bool_t
05211 check_loader_results (DBusMessageLoader      *loader,
05212                       DBusMessageValidity     validity)
05213 {
05214   if (!_dbus_message_loader_queue_messages (loader))
05215     _dbus_assert_not_reached ("no memory to queue messages");
05216   
05217   switch (validity)
05218     {
05219     case _DBUS_MESSAGE_VALID:
05220       return check_have_valid_message (loader);
05221     case _DBUS_MESSAGE_INVALID:
05222       return check_invalid_message (loader);
05223     case _DBUS_MESSAGE_INCOMPLETE:
05224       return check_incomplete_message (loader);
05225     case _DBUS_MESSAGE_UNKNOWN:
05226       return TRUE;
05227     }
05228 
05229   _dbus_assert_not_reached ("bad DBusMessageValidity");
05230   return FALSE;
05231 }
05232 
05233 
05242 dbus_bool_t
05243 dbus_internal_do_not_use_load_message_file (const DBusString    *filename,
05244                                             dbus_bool_t          is_raw,
05245                                             DBusString          *data)
05246 {
05247   dbus_bool_t retval;
05248 
05249   retval = FALSE;  
05250 
05251   if (is_raw)
05252     {
05253       DBusError error;
05254 
05255       _dbus_verbose ("Loading raw %s\n", _dbus_string_get_const_data (filename));
05256       dbus_error_init (&error);
05257       if (!_dbus_file_get_contents (data, filename, &error))
05258         {
05259           _dbus_warn ("Could not load message file %s: %s\n",
05260                       _dbus_string_get_const_data (filename),
05261                       error.message);
05262           dbus_error_free (&error);
05263           goto failed;
05264         }
05265     }
05266   else
05267     {
05268       if (!_dbus_message_data_load (data, filename))
05269         {
05270           _dbus_warn ("Could not load message file %s\n",
05271                       _dbus_string_get_const_data (filename));
05272           goto failed;
05273         }
05274     }
05275 
05276   retval = TRUE;
05277   
05278  failed:
05279 
05280   return retval;
05281 }
05282 
05292 dbus_bool_t
05293 dbus_internal_do_not_use_try_message_file (const DBusString    *filename,
05294                                            dbus_bool_t          is_raw,
05295                                            DBusMessageValidity  expected_validity)
05296 {
05297   DBusString data;
05298   dbus_bool_t retval;
05299 
05300   retval = FALSE;
05301   
05302   if (!_dbus_string_init (&data))
05303     _dbus_assert_not_reached ("could not allocate string\n");
05304 
05305   if (!dbus_internal_do_not_use_load_message_file (filename, is_raw,
05306                                                    &data))
05307     goto failed;
05308 
05309   retval = dbus_internal_do_not_use_try_message_data (&data, expected_validity);
05310 
05311  failed:
05312 
05313   if (!retval)
05314     {
05315       if (_dbus_string_get_length (&data) > 0)
05316         _dbus_verbose_bytes_of_string (&data, 0,
05317                                        _dbus_string_get_length (&data));
05318       
05319       _dbus_warn ("Failed message loader test on %s\n",
05320                   _dbus_string_get_const_data (filename));
05321     }
05322   
05323   _dbus_string_free (&data);
05324 
05325   return retval;
05326 }
05327 
05336 dbus_bool_t
05337 dbus_internal_do_not_use_try_message_data (const DBusString    *data,
05338                                            DBusMessageValidity  expected_validity)
05339 {
05340   DBusMessageLoader *loader;
05341   dbus_bool_t retval;
05342   int len;
05343   int i;
05344 
05345   loader = NULL;
05346   retval = FALSE;
05347 
05348   /* Write the data one byte at a time */
05349   
05350   loader = _dbus_message_loader_new ();
05351 
05352   /* check some trivial loader functions */
05353   _dbus_message_loader_ref (loader);
05354   _dbus_message_loader_unref (loader);
05355   _dbus_message_loader_get_max_message_size (loader);
05356   
05357   len = _dbus_string_get_length (data);
05358   for (i = 0; i < len; i++)
05359     {
05360       DBusString *buffer;
05361 
05362       _dbus_message_loader_get_buffer (loader, &buffer);
05363       _dbus_string_append_byte (buffer,
05364                                 _dbus_string_get_byte (data, i));
05365       _dbus_message_loader_return_buffer (loader, buffer, 1);
05366     }
05367   
05368   if (!check_loader_results (loader, expected_validity))
05369     goto failed;
05370 
05371   _dbus_message_loader_unref (loader);
05372   loader = NULL;
05373 
05374   /* Write the data all at once */
05375   
05376   loader = _dbus_message_loader_new ();
05377 
05378   {
05379     DBusString *buffer;
05380     
05381     _dbus_message_loader_get_buffer (loader, &buffer);
05382     _dbus_string_copy (data, 0, buffer,
05383                        _dbus_string_get_length (buffer));
05384     _dbus_message_loader_return_buffer (loader, buffer, 1);
05385   }
05386   
05387   if (!check_loader_results (loader, expected_validity))
05388     goto failed;
05389 
05390   _dbus_message_loader_unref (loader);
05391   loader = NULL;  
05392 
05393   /* Write the data 2 bytes at a time */
05394   
05395   loader = _dbus_message_loader_new ();
05396 
05397   len = _dbus_string_get_length (data);
05398   for (i = 0; i < len; i += 2)
05399     {
05400       DBusString *buffer;
05401 
05402       _dbus_message_loader_get_buffer (loader, &buffer);
05403       _dbus_string_append_byte (buffer,
05404                                 _dbus_string_get_byte (data, i));
05405       if ((i+1) < len)
05406         _dbus_string_append_byte (buffer,
05407                                   _dbus_string_get_byte (data, i+1));
05408       _dbus_message_loader_return_buffer (loader, buffer, 1);
05409     }
05410   
05411   if (!check_loader_results (loader, expected_validity))
05412     goto failed;
05413 
05414   _dbus_message_loader_unref (loader);
05415   loader = NULL;
05416   
05417   retval = TRUE;
05418   
05419  failed:
05420   
05421   if (loader)
05422     _dbus_message_loader_unref (loader);
05423   
05424   return retval;
05425 }
05426 
05427 static dbus_bool_t
05428 process_test_subdir (const DBusString          *test_base_dir,
05429                      const char                *subdir,
05430                      DBusMessageValidity        validity,
05431                      DBusForeachMessageFileFunc function,
05432                      void                      *user_data)
05433 {
05434   DBusString test_directory;
05435   DBusString filename;
05436   DBusDirIter *dir;
05437   dbus_bool_t retval;
05438   DBusError error;
05439 
05440   retval = FALSE;
05441   dir = NULL;
05442   
05443   if (!_dbus_string_init (&test_directory))
05444     _dbus_assert_not_reached ("didn't allocate test_directory\n");
05445 
05446   _dbus_string_init_const (&filename, subdir);
05447   
05448   if (!_dbus_string_copy (test_base_dir, 0,
05449                           &test_directory, 0))
05450     _dbus_assert_not_reached ("couldn't copy test_base_dir to test_directory");
05451   
05452   if (!_dbus_concat_dir_and_file (&test_directory, &filename))    
05453     _dbus_assert_not_reached ("couldn't allocate full path");
05454 
05455   _dbus_string_free (&filename);
05456   if (!_dbus_string_init (&filename))
05457     _dbus_assert_not_reached ("didn't allocate filename string\n");
05458 
05459   dbus_error_init (&error);
05460   dir = _dbus_directory_open (&test_directory, &error);
05461   if (dir == NULL)
05462     {
05463       _dbus_warn ("Could not open %s: %s\n",
05464                   _dbus_string_get_const_data (&test_directory),
05465                   error.message);
05466       dbus_error_free (&error);
05467       goto failed;
05468     }
05469 
05470   printf ("Testing:\n");
05471   
05472  next:
05473   while (_dbus_directory_get_next_file (dir, &filename, &error))
05474     {
05475       DBusString full_path;
05476       dbus_bool_t is_raw;
05477       
05478       if (!_dbus_string_init (&full_path))
05479         _dbus_assert_not_reached ("couldn't init string");
05480 
05481       if (!_dbus_string_copy (&test_directory, 0, &full_path, 0))
05482         _dbus_assert_not_reached ("couldn't copy dir to full_path");
05483 
05484       if (!_dbus_concat_dir_and_file (&full_path, &filename))
05485         _dbus_assert_not_reached ("couldn't concat file to dir");
05486 
05487       if (_dbus_string_ends_with_c_str (&filename, ".message"))
05488         is_raw = FALSE;
05489       else if (_dbus_string_ends_with_c_str (&filename, ".message-raw"))
05490         is_raw = TRUE;
05491       else
05492         {
05493           _dbus_verbose ("Skipping non-.message file %s\n",
05494                          _dbus_string_get_const_data (&filename));
05495           _dbus_string_free (&full_path);
05496           goto next;
05497         }
05498 
05499       printf ("    %s\n",
05500               _dbus_string_get_const_data (&filename));
05501       
05502       _dbus_verbose (" expecting %s\n",
05503                      validity == _DBUS_MESSAGE_VALID ? "valid" :
05504                      (validity == _DBUS_MESSAGE_INVALID ? "invalid" :
05505                       (validity == _DBUS_MESSAGE_INCOMPLETE ? "incomplete" : "unknown")));
05506       
05507       if (! (*function) (&full_path, is_raw, validity, user_data))
05508         {
05509           _dbus_string_free (&full_path);
05510           goto failed;
05511         }
05512       else
05513         _dbus_string_free (&full_path);
05514     }
05515 
05516   if (dbus_error_is_set (&error))
05517     {
05518       _dbus_warn ("Could not get next file in %s: %s\n",
05519                   _dbus_string_get_const_data (&test_directory),
05520                   error.message);
05521       dbus_error_free (&error);
05522       goto failed;
05523     }
05524     
05525   retval = TRUE;
05526   
05527  failed:
05528 
05529   if (dir)
05530     _dbus_directory_close (dir);
05531   _dbus_string_free (&test_directory);
05532   _dbus_string_free (&filename);
05533 
05534   return retval;
05535 }
05536                      
05546 dbus_bool_t
05547 dbus_internal_do_not_use_foreach_message_file (const char                *test_data_dir,
05548                                                DBusForeachMessageFileFunc func,
05549                                                void                      *user_data)
05550 {
05551   DBusString test_directory;
05552   dbus_bool_t retval;
05553 
05554   retval = FALSE;
05555   
05556   _dbus_string_init_const (&test_directory, test_data_dir);
05557 
05558   if (!process_test_subdir (&test_directory, "valid-messages",
05559                             _DBUS_MESSAGE_VALID, func, user_data))
05560     goto failed;
05561 
05562   if (!process_test_subdir (&test_directory, "invalid-messages",
05563                             _DBUS_MESSAGE_INVALID, func, user_data))
05564     goto failed;
05565   
05566   if (!process_test_subdir (&test_directory, "incomplete-messages",
05567                             _DBUS_MESSAGE_INCOMPLETE, func, user_data))
05568     goto failed;
05569 
05570   retval = TRUE;
05571   
05572  failed:
05573 
05574   _dbus_string_free (&test_directory);
05575   
05576   return retval;
05577 }
05578 
05579 static void
05580 verify_test_message (DBusMessage *message)
05581 {
05582   DBusMessageIter iter, dict;
05583   DBusError error;
05584   dbus_int32_t our_int;
05585   char *our_str;
05586   double our_double;
05587   dbus_bool_t our_bool;
05588   dbus_uint32_t our_uint32;
05589   dbus_int32_t *our_uint32_array;
05590   int our_uint32_array_len;
05591   dbus_int32_t *our_int32_array;
05592   int our_int32_array_len;
05593   char **our_string_array;
05594   int our_string_array_len;
05595 #ifdef DBUS_HAVE_INT64
05596   dbus_int64_t our_int64;
05597   dbus_uint64_t our_uint64;
05598   dbus_int64_t *our_uint64_array;
05599   int our_uint64_array_len;
05600   dbus_int64_t *our_int64_array;
05601   int our_int64_array_len;
05602 #endif
05603   double *our_double_array;
05604   int our_double_array_len;
05605   unsigned char *our_byte_array;
05606   int our_byte_array_len;
05607   unsigned char *our_boolean_array;
05608   int our_boolean_array_len;
05609   
05610   dbus_message_iter_init (message, &iter);
05611 
05612   dbus_error_init (&error);
05613   if (!dbus_message_iter_get_args (&iter, &error,
05614                                    DBUS_TYPE_INT32, &our_int,
05615 #ifdef DBUS_HAVE_INT64
05616                                    DBUS_TYPE_INT64, &our_int64,
05617                                    DBUS_TYPE_UINT64, &our_uint64,
05618 #endif
05619                                    DBUS_TYPE_STRING, &our_str,
05620                                    DBUS_TYPE_DOUBLE, &our_double,
05621                                    DBUS_TYPE_BOOLEAN, &our_bool,
05622                                    DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32,
05623                                    &our_uint32_array, &our_uint32_array_len,
05624                                    DBUS_TYPE_ARRAY, DBUS_TYPE_INT32,
05625                                    &our_int32_array, &our_int32_array_len,
05626 #ifdef DBUS_HAVE_INT64
05627                                    DBUS_TYPE_ARRAY, DBUS_TYPE_UINT64,
05628                                    &our_uint64_array, &our_uint64_array_len,
05629                                    DBUS_TYPE_ARRAY, DBUS_TYPE_INT64,
05630                                    &our_int64_array, &our_int64_array_len,
05631 #endif
05632                                    DBUS_TYPE_ARRAY, DBUS_TYPE_STRING,
05633                                    &our_string_array, &our_string_array_len,
05634                                    DBUS_TYPE_ARRAY, DBUS_TYPE_DOUBLE,
05635                                    &our_double_array, &our_double_array_len,
05636                                    DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
05637                                    &our_byte_array, &our_byte_array_len,
05638                                    DBUS_TYPE_ARRAY, DBUS_TYPE_BOOLEAN,
05639                                    &our_boolean_array, &our_boolean_array_len,
05640                                    0))
05641     {
05642       _dbus_warn ("error: %s - %s\n", error.name,
05643                   (error.message != NULL) ? error.message : "no message");
05644       _dbus_assert_not_reached ("Could not get arguments");
05645     }
05646 
05647   if (our_int != -0x12345678)
05648     _dbus_assert_not_reached ("integers differ!");
05649 
05650 #ifdef DBUS_HAVE_INT64
05651   if (our_int64 != -0x123456789abcd)
05652     _dbus_assert_not_reached ("64-bit integers differ!");
05653   if (our_uint64 != 0x123456789abcd)
05654     _dbus_assert_not_reached ("64-bit unsigned integers differ!");
05655 #endif
05656   
05657   if (our_double != 3.14159)
05658     _dbus_assert_not_reached ("doubles differ!");
05659 
05660   if (strcmp (our_str, "Test string") != 0)
05661     _dbus_assert_not_reached ("strings differ!");
05662   dbus_free (our_str);
05663 
05664   if (!our_bool)
05665     _dbus_assert_not_reached ("booleans differ");
05666 
05667   if (our_uint32_array_len != 4 ||
05668       our_uint32_array[0] != 0x12345678 ||
05669       our_uint32_array[1] != 0x23456781 ||
05670       our_uint32_array[2] != 0x34567812 ||
05671       our_uint32_array[3] != 0x45678123)
05672     _dbus_assert_not_reached ("uint array differs");
05673   dbus_free (our_uint32_array);
05674 
05675   if (our_int32_array_len != 4 ||
05676       our_int32_array[0] != 0x12345678 ||
05677       our_int32_array[1] != -0x23456781 ||
05678       our_int32_array[2] != 0x34567812 ||
05679       our_int32_array[3] != -0x45678123)
05680     _dbus_assert_not_reached ("int array differs");
05681   dbus_free (our_int32_array);
05682 
05683 #ifdef DBUS_HAVE_INT64
05684   if (our_uint64_array_len != 4 ||
05685       our_uint64_array[0] != 0x12345678 ||
05686       our_uint64_array[1] != 0x23456781 ||
05687       our_uint64_array[2] != 0x34567812 ||
05688       our_uint64_array[3] != 0x45678123)
05689     _dbus_assert_not_reached ("uint64 array differs");
05690   dbus_free (our_uint64_array);
05691   
05692   if (our_int64_array_len != 4 ||
05693       our_int64_array[0] != 0x12345678 ||
05694       our_int64_array[1] != -0x23456781 ||
05695       our_int64_array[2] != 0x34567812 ||
05696       our_int64_array[3] != -0x45678123)
05697     _dbus_assert_not_reached ("int64 array differs");
05698   dbus_free (our_int64_array);
05699 #endif /* DBUS_HAVE_INT64 */
05700   
05701   if (our_string_array_len != 4)
05702     _dbus_assert_not_reached ("string array has wrong length");
05703 
05704   if (strcmp (our_string_array[0], "Foo") != 0 ||
05705       strcmp (our_string_array[1], "bar") != 0 ||
05706       strcmp (our_string_array[2], "") != 0 ||
05707       strcmp (our_string_array[3], "woo woo woo woo") != 0)
05708     _dbus_assert_not_reached ("string array differs");
05709 
05710   dbus_free_string_array (our_string_array);
05711 
05712   if (our_double_array_len != 3)
05713     _dbus_assert_not_reached ("double array had wrong length");
05714 
05715   /* On all IEEE machines (i.e. everything sane) exact equality
05716    * should be preserved over the wire
05717    */
05718   if (our_double_array[0] != 0.1234 ||
05719       our_double_array[1] != 9876.54321 ||
05720       our_double_array[2] != -300.0)
05721     _dbus_assert_not_reached ("double array had wrong values");
05722 
05723   dbus_free (our_double_array);
05724 
05725   if (our_byte_array_len != 4)
05726     _dbus_assert_not_reached ("byte array had wrong length");
05727 
05728   if (our_byte_array[0] != 'a' ||
05729       our_byte_array[1] != 'b' ||
05730       our_byte_array[2] != 'c' ||
05731       our_byte_array[3] != 234)
05732     _dbus_assert_not_reached ("byte array had wrong values");
05733 
05734   dbus_free (our_byte_array);
05735 
05736   if (our_boolean_array_len != 5)
05737     _dbus_assert_not_reached ("bool array had wrong length");
05738 
05739   if (our_boolean_array[0] != TRUE ||
05740       our_boolean_array[1] != FALSE ||
05741       our_boolean_array[2] != TRUE ||
05742       our_boolean_array[3] != TRUE ||
05743       our_boolean_array[4] != FALSE)
05744     _dbus_assert_not_reached ("bool array had wrong values");
05745 
05746   dbus_free (our_boolean_array);
05747   
05748   if (!dbus_message_iter_next (&iter))
05749     _dbus_assert_not_reached ("Reached end of arguments");
05750 
05751   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_DICT)
05752     _dbus_assert_not_reached ("not dict type");
05753      
05754   if (!dbus_message_iter_init_dict_iterator (&iter, &dict))
05755     _dbus_assert_not_reached ("dict iter failed");
05756 
05757   our_str = dbus_message_iter_get_dict_key (&dict);
05758   if (our_str == NULL || strcmp (our_str, "test") != 0)
05759     _dbus_assert_not_reached ("wrong dict key");
05760   dbus_free (our_str);
05761 
05762   if (dbus_message_iter_get_arg_type (&dict) != DBUS_TYPE_UINT32)
05763     {
05764       _dbus_verbose ("dict entry type: %d\n", dbus_message_iter_get_arg_type (&dict));
05765       _dbus_assert_not_reached ("wrong dict entry type");
05766     }
05767 
05768   if ((our_uint32 = dbus_message_iter_get_uint32 (&dict)) != 0xDEADBEEF)
05769     {
05770       _dbus_verbose ("dict entry val: %x\n", our_uint32);
05771       _dbus_assert_not_reached ("wrong dict entry value");
05772     }
05773 
05774   if (dbus_message_iter_next (&dict))
05775     _dbus_assert_not_reached ("Didn't reach end of dict");
05776   
05777   if (!dbus_message_iter_next (&iter))
05778     _dbus_assert_not_reached ("Reached end of arguments");
05779   
05780   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_UINT32)
05781     _dbus_assert_not_reached ("wrong type after dict");
05782   
05783   if (dbus_message_iter_get_uint32 (&iter) != 0xCAFEBABE)
05784     _dbus_assert_not_reached ("wrong value after dict");
05785 
05786   if (dbus_message_iter_next (&iter))
05787     _dbus_assert_not_reached ("Didn't reach end of arguments");
05788 }
05789 
05796 dbus_bool_t
05797 _dbus_message_test (const char *test_data_dir)
05798 {
05799   DBusMessage *message;
05800   DBusMessageLoader *loader;
05801   DBusMessageIter iter, child_iter, child_iter2, child_iter3;
05802   int i;
05803   const char *data;
05804   DBusMessage *copy;
05805   const char *name1;
05806   const char *name2;
05807   const dbus_uint32_t our_uint32_array[] =
05808     { 0x12345678, 0x23456781, 0x34567812, 0x45678123 };
05809   const dbus_uint32_t our_int32_array[] =
05810     { 0x12345678, -0x23456781, 0x34567812, -0x45678123 };
05811 #ifdef DBUS_HAVE_INT64
05812   const dbus_uint64_t our_uint64_array[] =
05813     { 0x12345678, 0x23456781, 0x34567812, 0x45678123 };
05814   const dbus_uint64_t our_int64_array[] =
05815     { 0x12345678, -0x23456781, 0x34567812, -0x45678123 };
05816 #endif
05817   const char *our_string_array[] = { "Foo", "bar", "", "woo woo woo woo" };
05818   const double our_double_array[] = { 0.1234, 9876.54321, -300.0 };
05819   const unsigned char our_byte_array[] = { 'a', 'b', 'c', 234 };
05820   const unsigned char our_boolean_array[] = { TRUE, FALSE, TRUE, TRUE, FALSE };
05821   
05822   _dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
05823 
05824   message = dbus_message_new ("test.Message", "org.freedesktop.DBus.Test");
05825   _dbus_assert (dbus_message_has_destination (message, "org.freedesktop.DBus.Test"));
05826   _dbus_message_set_serial (message, 1234);
05827   dbus_message_set_sender (message, "org.foo.bar");
05828   _dbus_assert (dbus_message_has_sender (message, "org.foo.bar"));
05829   dbus_message_set_sender (message, NULL);
05830   _dbus_assert (!dbus_message_has_sender (message, "org.foo.bar"));
05831   _dbus_assert (dbus_message_get_serial (message) == 1234);
05832   _dbus_assert (dbus_message_has_destination (message, "org.freedesktop.DBus.Test"));
05833 
05834   _dbus_assert (dbus_message_get_is_error (message) == FALSE);
05835   dbus_message_set_is_error (message, TRUE);
05836   _dbus_assert (dbus_message_get_is_error (message) == TRUE);
05837   dbus_message_set_is_error (message, FALSE);
05838   _dbus_assert (dbus_message_get_is_error (message) == FALSE);
05839   
05840   dbus_message_unref (message);
05841   
05842   /* Test the vararg functions */
05843   message = dbus_message_new ("test.Message", "org.freedesktop.DBus.Test");
05844   _dbus_message_set_serial (message, 1);
05845   dbus_message_append_args (message,
05846                             DBUS_TYPE_INT32, -0x12345678,
05847 #ifdef DBUS_HAVE_INT64
05848                             DBUS_TYPE_INT64, -0x123456789abcd,
05849                             DBUS_TYPE_UINT64, 0x123456789abcd,
05850 #endif
05851                             DBUS_TYPE_STRING, "Test string",
05852                             DBUS_TYPE_DOUBLE, 3.14159,
05853                             DBUS_TYPE_BOOLEAN, TRUE,
05854                             DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, our_uint32_array,
05855                             _DBUS_N_ELEMENTS (our_uint32_array),
05856                             DBUS_TYPE_ARRAY, DBUS_TYPE_INT32, our_int32_array,
05857                             _DBUS_N_ELEMENTS (our_int32_array),
05858                             DBUS_TYPE_ARRAY, DBUS_TYPE_UINT64, our_uint64_array,
05859                             _DBUS_N_ELEMENTS (our_uint64_array),
05860                             DBUS_TYPE_ARRAY, DBUS_TYPE_INT64, our_int64_array,
05861                             _DBUS_N_ELEMENTS (our_int64_array),
05862                             DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, our_string_array,
05863                             _DBUS_N_ELEMENTS (our_string_array),
05864                             DBUS_TYPE_ARRAY, DBUS_TYPE_DOUBLE, our_double_array,
05865                             _DBUS_N_ELEMENTS (our_double_array),
05866                             DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, our_byte_array,
05867                             _DBUS_N_ELEMENTS (our_byte_array),
05868                             DBUS_TYPE_ARRAY, DBUS_TYPE_BOOLEAN, our_boolean_array,
05869                             _DBUS_N_ELEMENTS (our_boolean_array),
05870                             0);
05871   
05872   dbus_message_append_iter_init (message, &iter);
05873   dbus_message_iter_append_dict (&iter, &child_iter);
05874   dbus_message_iter_append_dict_key (&child_iter, "test");
05875   dbus_message_iter_append_uint32 (&child_iter, 0xDEADBEEF);
05876   dbus_message_iter_append_uint32 (&iter, 0xCAFEBABE);
05877   
05878   _dbus_verbose_bytes_of_string (&message->header, 0,
05879                                  _dbus_string_get_length (&message->header));
05880   _dbus_verbose_bytes_of_string (&message->body, 0,
05881                                  _dbus_string_get_length (&message->body));
05882 
05883   verify_test_message (message);
05884 
05885   copy = dbus_message_copy (message);
05886   
05887   _dbus_assert (message->client_serial == copy->client_serial);
05888   _dbus_assert (message->reply_serial == copy->reply_serial);
05889   _dbus_assert (message->header_padding == copy->header_padding);
05890   
05891   _dbus_assert (_dbus_string_get_length (&message->header) ==
05892                 _dbus_string_get_length (&copy->header));
05893 
05894   _dbus_assert (_dbus_string_get_length (&message->body) ==
05895                 _dbus_string_get_length (&copy->body));
05896 
05897   verify_test_message (copy);
05898 
05899   name1 = dbus_message_get_name (message);
05900   name2 = dbus_message_get_name (copy);
05901 
05902   _dbus_assert (strcmp (name1, name2) == 0);
05903   
05904   dbus_message_unref (message);
05905   dbus_message_unref (copy);
05906   
05907   message = dbus_message_new ("test.Message", "org.freedesktop.DBus.Test");
05908   _dbus_message_set_serial (message, 1);
05909   dbus_message_set_reply_serial (message, 0x12345678);
05910 
05911   dbus_message_append_iter_init (message, &iter);
05912   dbus_message_iter_append_string (&iter, "Test string");
05913   dbus_message_iter_append_int32 (&iter, -0x12345678);
05914   dbus_message_iter_append_uint32 (&iter, 0xedd1e);
05915   dbus_message_iter_append_double (&iter, 3.14159);
05916 
05917   dbus_message_iter_append_array (&iter, &child_iter, DBUS_TYPE_DOUBLE);
05918   dbus_message_iter_append_double (&child_iter, 1.5);
05919   dbus_message_iter_append_double (&child_iter, 2.5);
05920 
05921   /* dict */
05922   dbus_message_iter_append_dict (&iter, &child_iter);
05923   dbus_message_iter_append_dict_key (&child_iter, "test");
05924   dbus_message_iter_append_uint32 (&child_iter, 0xDEADBEEF);
05925 
05926   /* array of array of int32  (in dict) */
05927   dbus_message_iter_append_dict_key (&child_iter, "array");
05928   dbus_message_iter_append_array (&child_iter, &child_iter2, DBUS_TYPE_ARRAY);
05929   dbus_message_iter_append_array (&child_iter2, &child_iter3, DBUS_TYPE_INT32);
05930   dbus_message_iter_append_int32 (&child_iter3, 0x12345678);
05931   dbus_message_iter_append_int32 (&child_iter3, 0x23456781);
05932   _dbus_warn ("next call expected to fail with wrong array type\n");
05933   _dbus_assert (!dbus_message_iter_append_array (&child_iter2, &child_iter3, DBUS_TYPE_UINT32));
05934   dbus_message_iter_append_array (&child_iter2, &child_iter3, DBUS_TYPE_INT32);
05935   dbus_message_iter_append_int32 (&child_iter3, 0x34567812);
05936   dbus_message_iter_append_int32 (&child_iter3, 0x45678123);
05937   dbus_message_iter_append_int32 (&child_iter3, 0x56781234);
05938   
05939   dbus_message_iter_append_byte (&iter, 0xF0);
05940 
05941   dbus_message_iter_append_nil (&iter);
05942 
05943   dbus_message_iter_append_named (&iter, "named",
05944                                   "data", 5);
05945   
05946   message_iter_test (message);
05947 
05948   /* Message loader test */
05949   _dbus_message_lock (message);
05950   loader = _dbus_message_loader_new ();
05951 
05952   /* check ref/unref */
05953   _dbus_message_loader_ref (loader);
05954   _dbus_message_loader_unref (loader);
05955   
05956   /* Write the header data one byte at a time */
05957   data = _dbus_string_get_const_data (&message->header);
05958   for (i = 0; i < _dbus_string_get_length (&message->header); i++)
05959     {
05960       DBusString *buffer;
05961 
05962       _dbus_message_loader_get_buffer (loader, &buffer);
05963       _dbus_string_append_byte (buffer, data[i]);
05964       _dbus_message_loader_return_buffer (loader, buffer, 1);
05965     }
05966 
05967   /* Write the body data one byte at a time */
05968   data = _dbus_string_get_const_data (&message->body);
05969   for (i = 0; i < _dbus_string_get_length (&message->body); i++)
05970     {
05971       DBusString *buffer;
05972 
05973       _dbus_message_loader_get_buffer (loader, &buffer);
05974       _dbus_string_append_byte (buffer, data[i]);
05975       _dbus_message_loader_return_buffer (loader, buffer, 1);
05976     }
05977 
05978   dbus_message_unref (message);
05979 
05980   /* Now pop back the message */
05981   if (!_dbus_message_loader_queue_messages (loader))
05982     _dbus_assert_not_reached ("no memory to queue messages");
05983   
05984   if (_dbus_message_loader_get_is_corrupted (loader))
05985     _dbus_assert_not_reached ("message loader corrupted");
05986   
05987   message = _dbus_message_loader_pop_message (loader);
05988   if (!message)
05989     _dbus_assert_not_reached ("received a NULL message");
05990 
05991   if (dbus_message_get_reply_serial (message) != 0x12345678)
05992     _dbus_assert_not_reached ("reply serial fields differ");
05993   
05994   message_iter_test (message);
05995   
05996   dbus_message_unref (message);
05997   _dbus_message_loader_unref (loader);
05998 
05999   /* Now load every message in test_data_dir if we have one */
06000   if (test_data_dir == NULL)
06001     return TRUE;
06002 
06003   return dbus_internal_do_not_use_foreach_message_file (test_data_dir,
06004                                                         (DBusForeachMessageFileFunc)
06005                                                         dbus_internal_do_not_use_try_message_file,
06006                                                         NULL);
06007 }
06008 
06009 #endif /* DBUS_BUILD_TESTS */

Generated on Wed Oct 22 14:05:03 2003 for D-BUS by doxygen1.3-rc3