Main Page | Modules | Data Structures | Directories | 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, 2004  Red Hat Inc.
00005  * Copyright (C) 2002, 2003  CodeFactory AB
00006  *
00007  * Licensed under the Academic Free License version 2.1
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 
00048 typedef struct
00049 {
00050   int name_offset;  
00051   int value_offset; 
00052 } HeaderField;
00053 
00055 #define BYTE_ORDER_OFFSET    0
00056 
00057 #define TYPE_OFFSET          1
00058 
00059 #define FLAGS_OFFSET         2
00060 
00061 #define VERSION_OFFSET       3
00062 
00063 #define HEADER_LENGTH_OFFSET 4
00064 
00065 #define BODY_LENGTH_OFFSET   8
00066 
00067 #define CLIENT_SERIAL_OFFSET 12
00068 
00069 
00077 struct DBusMessage
00078 {
00079   DBusAtomic refcount; 
00081   DBusString header; 
00086   HeaderField header_fields[DBUS_HEADER_FIELD_LAST + 1]; 
00090   dbus_uint32_t client_serial; 
00091   dbus_uint32_t reply_serial;  
00093   int header_padding; 
00095   DBusString body;   
00097   char byte_order; 
00099   unsigned int locked : 1; 
00101   DBusList *size_counters;   
00102   long size_counter_delta;   
00104   dbus_uint32_t changed_stamp; 
00106   DBusDataSlotList slot_list;   
00108 #ifndef DBUS_DISABLE_CHECKS
00109   int generation; 
00110 #endif
00111 };
00112 
00113 enum {
00114   DBUS_MESSAGE_ITER_TYPE_MESSAGE,
00115   DBUS_MESSAGE_ITER_TYPE_ARRAY,
00116   DBUS_MESSAGE_ITER_TYPE_DICT
00117 };
00118 
00120 typedef struct DBusMessageRealIter DBusMessageRealIter;
00121 
00127 struct DBusMessageRealIter
00128 {
00129   DBusMessageRealIter *parent_iter; 
00130   DBusMessage *message; 
00131   dbus_uint32_t changed_stamp; 
00133   /* This is an int instead of an enum to get a guaranteed size for the dummy: */
00134   int type; 
00136   int pos; 
00137   int end; 
00138   int container_start; 
00139   int container_length_pos; 
00141   int wrote_dict_key; 
00143   int array_type_pos; 
00144   int array_type_done; 
00145 };
00146 
00157 void
00158 _dbus_message_get_network_data (DBusMessage          *message,
00159                                 const DBusString    **header,
00160                                 const DBusString    **body)
00161 {
00162   _dbus_assert (message->locked);
00163   
00164   *header = &message->header;
00165   *body = &message->body;
00166 }
00167 
00168 static void
00169 clear_header_padding (DBusMessage *message)
00170 {
00171   _dbus_string_shorten (&message->header,
00172                         message->header_padding);
00173   message->header_padding = 0;
00174 }              
00175 
00176 #ifdef DBUS_DISABLE_CHECKS
00177 #define is_valid_error_name(x) TRUE
00178 #else
00179 static dbus_bool_t
00180 is_valid_error_name (const char *error_name)                                          
00181 {
00182   DBusString the_error_name;
00183 
00184   if (error_name == NULL)
00185     return FALSE;
00186   
00187   _dbus_string_init_const (&the_error_name, error_name);
00188   return _dbus_string_validate_error_name (&the_error_name, 0,   
00189                                            _dbus_string_get_length (&the_error_name));
00190 }
00191 #endif
00192 
00193 static dbus_bool_t
00194 append_header_padding (DBusMessage *message)
00195 {
00196   int old_len;
00197   old_len = _dbus_string_get_length (&message->header);
00198   if (!_dbus_string_align_length (&message->header, 8))
00199     return FALSE;
00200 
00201   message->header_padding = _dbus_string_get_length (&message->header) - old_len;
00202 
00203   return TRUE;
00204 }
00205 
00206 #ifdef DBUS_BUILD_TESTS
00207 /* tests-only until it's actually used */
00208 static dbus_int32_t
00209 get_int_field (DBusMessage *message,
00210                int          field)
00211 {
00212   int offset;
00213 
00214   _dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
00215   
00216   offset = message->header_fields[field].value_offset;
00217   
00218   if (offset < 0)
00219     return -1; /* useless if -1 is a valid value of course */
00220   
00221   return _dbus_demarshal_int32 (&message->header,
00222                                 message->byte_order,
00223                                 offset,
00224                                 NULL);
00225 }
00226 #endif
00227 
00228 static dbus_uint32_t
00229 get_uint_field (DBusMessage *message,
00230                 int          field)
00231 {
00232   int offset;
00233   
00234   _dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
00235   
00236   offset = message->header_fields[field].value_offset;
00237   
00238   if (offset < 0)
00239     return 0; /* useless if 0 is a valid value of course */
00240   
00241   return _dbus_demarshal_uint32 (&message->header,
00242                                  message->byte_order,
00243                                  offset,
00244                                  NULL);
00245 }
00246 
00247 static const char*
00248 get_string_field (DBusMessage *message,
00249                   int          field,
00250                   int         *len)
00251 {
00252   int offset;
00253   const char *data;
00254 
00255   _dbus_return_val_if_fail (message->generation == _dbus_current_generation,
00256                             NULL);
00257   
00258   offset = message->header_fields[field].value_offset;
00259 
00260   _dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
00261   
00262   if (offset < 0)
00263     return NULL;
00264 
00265   /* offset points to string length, string data follows it */
00266   /* FIXME _dbus_demarshal_const_string() that returned
00267    * a reference to the string plus its len might be nice.
00268    */
00269   
00270   if (len)
00271     *len = _dbus_demarshal_uint32 (&message->header,
00272                                    message->byte_order,
00273                                    offset,
00274                                    NULL);
00275 
00276   data = _dbus_string_get_const_data (&message->header);
00277   
00278   return data + (offset + 4); 
00279 }
00280 
00281 /* returns FALSE if no memory, TRUE with NULL path if no field */
00282 static dbus_bool_t
00283 get_path_field_decomposed (DBusMessage  *message,
00284                            int           field,
00285                            char       ***path)
00286 {
00287   int offset;
00288 
00289   offset = message->header_fields[field].value_offset;
00290 
00291   _dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
00292   
00293   if (offset < 0)
00294     {
00295       *path = NULL;
00296       return TRUE;
00297     }
00298 
00299   return _dbus_demarshal_object_path (&message->header,
00300                                       message->byte_order,
00301                                       offset,
00302                                       NULL,
00303                                       path, NULL);
00304 }
00305 
00306 #ifdef DBUS_BUILD_TESTS
00307 static dbus_bool_t
00308 append_int_field (DBusMessage *message,
00309                   int          field,
00310                   int          value)
00311 {
00312   _dbus_assert (!message->locked);
00313 
00314   clear_header_padding (message);
00315   
00316   message->header_fields[field].name_offset =
00317     _dbus_string_get_length (&message->header);
00318   
00319   if (!_dbus_string_append_byte (&message->header, field))
00320     goto failed;
00321 
00322   if (!_dbus_string_append_byte (&message->header, DBUS_TYPE_INT32))
00323     goto failed;
00324 
00325   if (!_dbus_string_align_length (&message->header, 4))
00326     goto failed;
00327   
00328   message->header_fields[field].value_offset =
00329     _dbus_string_get_length (&message->header);
00330   
00331   if (!_dbus_marshal_int32 (&message->header, message->byte_order,
00332                             value))
00333     goto failed;
00334 
00335   if (!append_header_padding (message))
00336     goto failed;
00337   
00338   return TRUE;
00339   
00340  failed:
00341   _dbus_string_set_length (&message->header,
00342                            message->header_fields[field].name_offset);
00343   message->header_fields[field].name_offset  = -1;
00344   message->header_fields[field].value_offset = -1;
00345 
00346   /* this must succeed because it was allocated on function entry and
00347    * DBusString doesn't ever realloc smaller
00348    */
00349   if (!append_header_padding (message))
00350     _dbus_assert_not_reached ("failed to reappend header padding");
00351   return FALSE;
00352 }
00353 #endif
00354 
00355 static dbus_bool_t
00356 append_uint_field (DBusMessage *message,
00357                    int          field,
00358                    int          value)
00359 {
00360   _dbus_assert (!message->locked);
00361 
00362   clear_header_padding (message);
00363   
00364   message->header_fields[field].name_offset =
00365     _dbus_string_get_length (&message->header);
00366   
00367   if (!_dbus_string_append_byte (&message->header, field))
00368     goto failed;
00369 
00370   if (!_dbus_string_append_byte (&message->header, DBUS_TYPE_UINT32))
00371     goto failed;
00372 
00373   if (!_dbus_string_align_length (&message->header, 4))
00374     goto failed;
00375   
00376   message->header_fields[field].value_offset =
00377     _dbus_string_get_length (&message->header);
00378   
00379   if (!_dbus_marshal_uint32 (&message->header, message->byte_order,
00380                              value))
00381     goto failed;
00382 
00383   if (!append_header_padding (message))
00384     goto failed;
00385   
00386   return TRUE;
00387   
00388  failed:
00389   _dbus_string_set_length (&message->header,
00390                            message->header_fields[field].name_offset);
00391   message->header_fields[field].name_offset  = -1;
00392   message->header_fields[field].value_offset = -1;
00393 
00394   /* this must succeed because it was allocated on function entry and
00395    * DBusString doesn't ever realloc smaller
00396    */
00397   if (!append_header_padding (message))
00398     _dbus_assert_not_reached ("failed to reappend header padding");
00399   return FALSE;
00400 }
00401 
00405 #define MAX_BYTES_OVERHEAD_TO_APPEND_A_STRING (1 + 1 + 3 + 4 + 1 + 8)
00406 
00407 static dbus_bool_t
00408 append_string_field_len (DBusMessage *message,
00409                          int          field,
00410                          int          type,
00411                          const char  *value,
00412                          int          value_len)
00413 {
00414   _dbus_assert (!message->locked);
00415 
00416   clear_header_padding (message);
00417   
00418   message->header_fields[field].name_offset =
00419     _dbus_string_get_length (&message->header);
00420   
00421   if (!_dbus_string_append_byte (&message->header, field))
00422     goto failed;
00423   
00424   if (!_dbus_string_append_byte (&message->header, type))
00425     goto failed;
00426 
00427   if (!_dbus_string_align_length (&message->header, 4))
00428     goto failed;
00429   
00430   message->header_fields[field].value_offset =
00431     _dbus_string_get_length (&message->header);
00432   
00433   if (!_dbus_marshal_string_len (&message->header, message->byte_order,
00434                                  value, value_len))
00435     goto failed;
00436 
00437   if (!append_header_padding (message))
00438     goto failed;
00439   
00440   return TRUE;
00441   
00442  failed:
00443   _dbus_string_set_length (&message->header,
00444                            message->header_fields[field].name_offset);
00445   message->header_fields[field].name_offset  = -1;
00446   message->header_fields[field].value_offset = -1;
00447 
00448   /* this must succeed because it was allocated on function entry and
00449    * DBusString doesn't ever realloc smaller
00450    */
00451   if (!append_header_padding (message))
00452     _dbus_assert_not_reached ("failed to reappend header padding");
00453   
00454   return FALSE;
00455 }
00456 
00457 static dbus_bool_t
00458 append_string_field (DBusMessage *message,
00459                      int          field,
00460                      int          type,
00461                      const char  *value)
00462 {
00463   int value_len;
00464 
00465   value_len = strlen (value);
00466 
00467   return append_string_field_len (message, field, type, value, value_len);
00468 }
00469 
00470 static int
00471 get_type_alignment (int type)
00472 {
00473   int alignment;
00474   
00475   switch (type)
00476     {
00477     case DBUS_TYPE_NIL:
00478     case DBUS_TYPE_BYTE:
00479     case DBUS_TYPE_BOOLEAN:
00480       alignment = 0;
00481       break;
00482 
00483     case DBUS_TYPE_INT32:
00484     case DBUS_TYPE_UINT32:
00485     case DBUS_TYPE_STRING:
00486     case DBUS_TYPE_OBJECT_PATH:
00487       /* These are aligned 4 because they have a length as the
00488        * first field;
00489        */
00490     case DBUS_TYPE_CUSTOM:
00491     case DBUS_TYPE_DICT:
00492       alignment = 4;
00493       break;
00494 
00495     case DBUS_TYPE_INT64:
00496     case DBUS_TYPE_UINT64:
00497     case DBUS_TYPE_DOUBLE:
00498       alignment = 8;
00499       break;
00500 
00501     case DBUS_TYPE_ARRAY:
00502       _dbus_assert_not_reached ("passed an ARRAY type to get_type_alignment()");
00503       alignment = 0; /* quiet gcc */
00504       break;
00505 
00506     case DBUS_TYPE_INVALID:
00507     default:
00508       _dbus_assert_not_reached ("passed an invalid or unknown type to get_type_alignment()");
00509       alignment = 0; /* quiet gcc */
00510       break;
00511     }
00512 
00513   return alignment;
00514 }
00515 
00516 static dbus_bool_t
00517 iterate_one_field (const DBusString *str,
00518                    int               byte_order,
00519                    int               name_offset,
00520                    int              *next_offset_p,
00521                    int              *field_name_p,
00522                    DBusString       *append_copy_to,
00523                    int              *copy_name_offset_p,
00524                    int              *copy_value_offset_p)
00525 {
00526   int name, type, array_type;
00527   int alignment;
00528   int type_len;
00529   int type_pos;
00530   int value_pos;
00531   int value_len;
00532   int value_end;
00533   int pos;
00534 
00535 #if 0
00536   _dbus_verbose ("%s: name_offset=%d, append to %p\n",
00537                  _DBUS_FUNCTION_NAME, name_offset, append_copy_to);
00538 #endif
00539   
00540   pos = name_offset;
00541   
00542   name = _dbus_string_get_byte (str, name_offset);
00543   pos++;
00544 
00545   type_pos = pos;
00546   type = _dbus_string_get_byte (str, type_pos);
00547   pos++;
00548   type_len = 1;
00549 
00550   array_type = type;
00551   /* find out the type of our array */
00552   while (array_type == DBUS_TYPE_ARRAY)
00553     {
00554       pos++;
00555       type_len++;
00556       array_type = _dbus_string_get_byte (str, pos);
00557     }
00558 
00559 #if 0
00560   _dbus_verbose ("%s: name %s, type '%c' %d at %d len %d, array type '%c' %d\n",
00561                  _DBUS_FUNCTION_NAME,
00562                  _dbus_header_field_to_string (name),
00563                  type, type, type_pos, type_len, array_type, array_type);
00564 #endif
00565   
00566 #ifndef DBUS_DISABLE_ASSERT
00567   if (!_dbus_type_is_valid (array_type))
00568     {
00569       _dbus_warn ("type '%c' %d is not valid in %s\n",
00570                   array_type, array_type, _DBUS_FUNCTION_NAME);
00571       _dbus_assert_not_reached ("invalid type");
00572     }
00573 #endif
00574       
00575   alignment = get_type_alignment (array_type);
00576       
00577   if (alignment > 0)
00578     pos = _DBUS_ALIGN_VALUE (pos, alignment);
00579 
00580   _dbus_verbose ("%s: alignment %d value at pos %d\n",
00581                  _DBUS_FUNCTION_NAME, alignment, pos);
00582   
00583   /* pos now points to our value */
00584   if (!_dbus_marshal_get_arg_end_pos (str, byte_order,
00585                                       type, pos, &value_end))
00586     _dbus_assert_not_reached ("failed to get the byte after this header");
00587 
00588   value_pos = pos;
00589   value_len = value_end - value_pos;
00590 
00591   _dbus_verbose ("%s: value_pos %d value_len %d value_end %d\n",
00592                  _DBUS_FUNCTION_NAME, value_pos, value_len, value_end);
00593   
00594   if (next_offset_p)
00595     *next_offset_p = pos + value_len;
00596 
00597   if (field_name_p)
00598     *field_name_p = name;
00599 
00600   if (append_copy_to)
00601     {
00602       int orig_len;
00603 
00604       orig_len = _dbus_string_get_length (append_copy_to);
00605 
00606       if (copy_name_offset_p)
00607         *copy_name_offset_p = orig_len;
00608       
00609       if (!_dbus_string_append_byte (append_copy_to, name))
00610         goto failed_copy;
00611 
00612       if (!_dbus_string_copy_len (str, type_pos, type_len,
00613                                   append_copy_to,
00614                                   _dbus_string_get_length (append_copy_to)))
00615         goto failed_copy;
00616 
00617       if (!_dbus_string_align_length (append_copy_to, alignment))
00618         goto failed_copy;
00619 
00620       if (copy_value_offset_p)
00621         *copy_value_offset_p = _dbus_string_get_length (append_copy_to);
00622       
00623       if (!_dbus_string_copy_len (str, value_pos, value_len,
00624                                   append_copy_to,
00625                                   _dbus_string_get_length (append_copy_to)))
00626         goto failed_copy;
00627       
00628       return TRUE;
00629 
00630     failed_copy:
00631       _dbus_verbose ("%s: Failed copying old fields to new string\n",
00632                      _DBUS_FUNCTION_NAME);
00633       _dbus_string_set_length (append_copy_to, orig_len);
00634       return FALSE;
00635     }
00636   else
00637     return TRUE;
00638 }
00639 
00640 #ifndef DBUS_DISABLE_ASSERT
00641 static void
00642 verify_header_fields (DBusMessage *message)
00643 {
00644   int i;
00645   i = 0;
00646   while (i <= DBUS_HEADER_FIELD_LAST)
00647     {
00648       if (message->header_fields[i].name_offset >= 0)
00649         _dbus_assert (_dbus_string_get_byte (&message->header,
00650                                              message->header_fields[i].name_offset) ==
00651                       i);
00652       ++i;
00653     }
00654 }
00655 #else /* DBUS_DISABLE_ASSERT */
00656 #define verify_header_fields(x)
00657 #endif /* DBUS_DISABLE_ASSERT */
00658 
00659 /* In this function we delete one field and re-align all the fields
00660  * following it.
00661  */
00662 static dbus_bool_t
00663 delete_one_and_re_align (DBusMessage *message,
00664                          int          name_offset_to_delete)
00665 {
00666   DBusString copy;
00667   int new_fields_front_padding;
00668   int next_offset;
00669   int field_name;
00670   dbus_bool_t retval;
00671   HeaderField new_header_fields[DBUS_HEADER_FIELD_LAST+1];
00672   
00673   _dbus_assert (name_offset_to_delete < _dbus_string_get_length (&message->header));
00674   verify_header_fields (message);
00675 
00676   _dbus_verbose ("%s: Deleting one field at offset %d\n",
00677                  _DBUS_FUNCTION_NAME,
00678                  name_offset_to_delete);
00679   
00680   retval = FALSE;
00681 
00682   clear_header_padding (message);
00683   
00684   if (!_dbus_string_init_preallocated (&copy,
00685                                        _dbus_string_get_length (&message->header) -
00686                                        name_offset_to_delete + 8))
00687     {
00688       _dbus_verbose ("%s: Failed to init string to hold copy of fields\n",
00689                      _DBUS_FUNCTION_NAME);
00690       goto out_0;
00691     }
00692   
00693   /* Align the name offset of the first field in the same way it's
00694    * aligned in the real header
00695    */
00696   new_fields_front_padding = name_offset_to_delete % 8;
00697 
00698   if (!_dbus_string_insert_bytes (&copy, 0, new_fields_front_padding,
00699                                   '\0'))
00700     _dbus_assert_not_reached ("Should not have failed to insert bytes into preallocated string\n");
00701 
00702   memcpy (new_header_fields, message->header_fields,
00703           sizeof (new_header_fields));
00704   
00705   /* Now just re-marshal each field in the header to our temporary
00706    * buffer, skipping the first one. The tricky part is that the
00707    * fields are padded as if for previous_name_offset, but are in fact
00708    * at unaligned_name_offset
00709    */
00710 
00711   if (!iterate_one_field (&message->header,
00712                           message->byte_order,
00713                           name_offset_to_delete,
00714                           &next_offset,
00715                           &field_name, NULL, NULL, NULL))
00716     _dbus_assert_not_reached ("shouldn't have failed to alloc memory to skip the deleted field");
00717 
00718   _dbus_verbose ("  Skipping %s field which will be deleted; next_offset = %d\n",
00719                  _dbus_header_field_to_string (field_name), next_offset);
00720   
00721   /* This field no longer exists */
00722   if (field_name <= DBUS_HEADER_FIELD_LAST)
00723     {
00724       new_header_fields[field_name].name_offset = -1;
00725       new_header_fields[field_name].value_offset = -1;
00726     }
00727   
00728   while (next_offset < _dbus_string_get_length (&message->header))
00729     {
00730       int copy_name_offset;
00731       int copy_value_offset;
00732 
00733       if (!iterate_one_field (&message->header,
00734                               message->byte_order,
00735                               next_offset,
00736                               &next_offset,
00737                               &field_name,
00738                               &copy,
00739                               &copy_name_offset,
00740                               &copy_value_offset))
00741         {
00742           _dbus_verbose ("%s: OOM iterating one field\n",
00743                          _DBUS_FUNCTION_NAME);
00744           goto out_1;
00745         }
00746       
00747       if (field_name <= DBUS_HEADER_FIELD_LAST)
00748         {
00749           new_header_fields[field_name].name_offset = copy_name_offset - new_fields_front_padding + name_offset_to_delete;
00750           new_header_fields[field_name].value_offset = copy_value_offset - new_fields_front_padding + name_offset_to_delete;
00751           
00752           _dbus_verbose ("  Re-adding %s field at name_offset = %d value_offset = %d; next_offset = %d\n",
00753                          _dbus_header_field_to_string (field_name),
00754                          new_header_fields[field_name].name_offset,
00755                          new_header_fields[field_name].value_offset,
00756                          next_offset);
00757         }
00758     }
00759 
00760   if (!_dbus_string_replace_len (&copy,
00761                                  new_fields_front_padding,
00762                                  _dbus_string_get_length (&copy) - new_fields_front_padding,
00763                                  &message->header,
00764                                  name_offset_to_delete,
00765                                  _dbus_string_get_length (&message->header) - name_offset_to_delete))
00766     {
00767       _dbus_verbose ("%s: OOM moving copy back into header\n",
00768                      _DBUS_FUNCTION_NAME);
00769       goto out_1;
00770     }
00771   
00772   memcpy (message->header_fields, new_header_fields,
00773           sizeof (new_header_fields));
00774   verify_header_fields (message);
00775   
00776   retval = TRUE;
00777   
00778  out_1:
00779   _dbus_string_free (&copy);
00780   
00781  out_0:
00782   if (!append_header_padding (message))
00783     _dbus_assert_not_reached ("Failed to re-append header padding in re_align_field_recurse()");
00784   
00785   return retval;
00786 }
00787 
00788 static dbus_bool_t
00789 delete_field (DBusMessage *message,
00790               int          field,
00791               int          prealloc_header_space)
00792 {
00793   int offset;
00794 
00795   _dbus_assert (!message->locked);
00796 
00797   /* Prealloc */
00798   if (!_dbus_string_lengthen (&message->header, prealloc_header_space))
00799     {
00800       _dbus_verbose ("failed to prealloc %d bytes header space\n",
00801                      prealloc_header_space);
00802       return FALSE;
00803     }
00804   _dbus_string_shorten (&message->header, prealloc_header_space);
00805 
00806   /* Delete */
00807   offset = message->header_fields[field].name_offset;
00808   if (offset < 0)
00809     {
00810       _dbus_verbose ("header field didn't exist, no need to delete\n");
00811       return TRUE; /* field didn't exist */
00812     }
00813 
00814   return delete_one_and_re_align (message, offset);
00815 }
00816 
00817 #ifdef DBUS_BUILD_TESTS
00818 static dbus_bool_t
00819 set_int_field (DBusMessage *message,
00820                int          field,
00821                int          value)
00822 {
00823   int offset = message->header_fields[field].value_offset;
00824 
00825   _dbus_assert (!message->locked);
00826 
00827   _dbus_verbose ("set_int_field() field %d value '%d'\n",
00828                  field, value);
00829   
00830   if (offset < 0)
00831     {
00832       /* need to append the field */
00833       return append_int_field (message, field, value);
00834     }
00835   else
00836     {
00837       _dbus_marshal_set_int32 (&message->header,
00838                                message->byte_order,
00839                                offset, value);
00840 
00841       return TRUE;
00842     }
00843 }
00844 #endif
00845 
00846 static dbus_bool_t
00847 set_uint_field (DBusMessage  *message,
00848                 int           field,
00849                 dbus_uint32_t value)
00850 {
00851   int offset = message->header_fields[field].value_offset;
00852 
00853   _dbus_assert (!message->locked);
00854 
00855   _dbus_verbose ("set_uint_field() field %d value '%u'\n",
00856                  field, value);
00857   
00858   if (offset < 0)
00859     {
00860       /* need to append the field */
00861       return append_uint_field (message, field, value);
00862     }
00863   else
00864     {
00865       _dbus_marshal_set_uint32 (&message->header,
00866                                 message->byte_order,
00867                                 offset, value);
00868 
00869       return TRUE;
00870     }
00871 }
00872 
00873 static dbus_bool_t
00874 set_string_field (DBusMessage *message,
00875                   int          field,
00876                   int          type,
00877                   const char  *value)
00878 {
00879   int prealloc;
00880   int value_len;
00881   
00882   _dbus_assert (!message->locked);
00883 
00884   value_len = value ? strlen (value) : 0;
00885   
00886   /* the prealloc is so the append_string_field()
00887    * below won't fail, leaving us in inconsistent state
00888    */
00889   prealloc = value_len + MAX_BYTES_OVERHEAD_TO_APPEND_A_STRING;
00890 
00891   _dbus_verbose ("set_string_field() field %d prealloc %d value '%s'\n",
00892                  field, prealloc, value);
00893   
00894   if (!delete_field (message, field, prealloc))
00895     return FALSE;
00896 
00897   if (value != NULL)
00898     {
00899       /* need to append the field */
00900       if (!append_string_field_len (message, field, type, value, value_len))
00901         _dbus_assert_not_reached ("Appending string field shouldn't have failed, due to preallocation");
00902     }
00903   
00904   return TRUE;
00905 }
00906 
00914 void
00915 _dbus_message_set_serial (DBusMessage  *message,
00916                           dbus_int32_t  serial)
00917 {
00918   _dbus_assert (!message->locked);
00919   _dbus_assert (dbus_message_get_serial (message) == 0);
00920 
00921   _dbus_marshal_set_uint32 (&message->header,
00922                             message->byte_order,
00923                             CLIENT_SERIAL_OFFSET,
00924                             serial);
00925 
00926   message->client_serial = serial;
00927 }
00928 
00937 dbus_bool_t
00938 dbus_message_set_reply_serial (DBusMessage   *message,
00939                                dbus_uint32_t  reply_serial)
00940 {
00941   _dbus_assert (!message->locked);
00942 
00943   if (set_uint_field (message,
00944                       DBUS_HEADER_FIELD_REPLY_SERIAL,
00945                       reply_serial))
00946     {
00947       message->reply_serial = reply_serial;
00948       return TRUE;
00949     }
00950   else
00951     return FALSE;
00952 }
00953 
00964 dbus_uint32_t
00965 dbus_message_get_serial (DBusMessage *message)
00966 {
00967   return message->client_serial;
00968 }
00969 
00976 dbus_uint32_t
00977 dbus_message_get_reply_serial  (DBusMessage *message)
00978 {
00979   return message->reply_serial;
00980 }
00981 
00994 void
00995 _dbus_message_add_size_counter_link (DBusMessage  *message,
00996                                      DBusList     *link)
00997 {
00998   /* right now we don't recompute the delta when message
00999    * size changes, and that's OK for current purposes
01000    * I think, but could be important to change later.
01001    * Do recompute it whenever there are no outstanding counters,
01002    * since it's basically free.
01003    */
01004   if (message->size_counters == NULL)
01005     {
01006       message->size_counter_delta =
01007         _dbus_string_get_length (&message->header) +
01008         _dbus_string_get_length (&message->body);
01009       
01010 #if 0
01011       _dbus_verbose ("message has size %ld\n",
01012                      message->size_counter_delta);
01013 #endif
01014     }
01015   
01016   _dbus_list_append_link (&message->size_counters, link);
01017   
01018   _dbus_counter_adjust (link->data, message->size_counter_delta);
01019 }
01020 
01030 dbus_bool_t
01031 _dbus_message_add_size_counter (DBusMessage *message,
01032                                 DBusCounter *counter)
01033 {
01034   DBusList *link;
01035 
01036   link = _dbus_list_alloc_link (counter);
01037   if (link == NULL)
01038     return FALSE;
01039 
01040   _dbus_counter_ref (counter);
01041   _dbus_message_add_size_counter_link (message, link);
01042 
01043   return TRUE;
01044 }
01045 
01054 void
01055 _dbus_message_remove_size_counter (DBusMessage  *message,
01056                                    DBusCounter  *counter,
01057                                    DBusList    **link_return)
01058 {
01059   DBusList *link;
01060 
01061   link = _dbus_list_find_last (&message->size_counters,
01062                                counter);
01063   _dbus_assert (link != NULL);
01064 
01065   _dbus_list_unlink (&message->size_counters,
01066                      link);
01067   if (link_return)
01068     *link_return = link;
01069   else
01070     _dbus_list_free_link (link);
01071 
01072   _dbus_counter_adjust (counter, - message->size_counter_delta);
01073 
01074   _dbus_counter_unref (counter);
01075 }
01076 
01077 static dbus_bool_t
01078 dbus_message_create_header (DBusMessage *message,
01079                             int          type,
01080                             const char  *service,
01081                             const char  *path,
01082                             const char  *interface,
01083                             const char  *member,
01084                             const char  *error_name)
01085 {
01086   unsigned int flags;
01087 
01088   _dbus_assert ((interface && member) ||
01089                 (error_name) ||
01090                 !(interface || member || error_name));
01091   _dbus_assert (error_name == NULL || is_valid_error_name (error_name));
01092   
01093   if (!_dbus_string_append_byte (&message->header, message->byte_order))
01094     return FALSE;
01095 
01096   if (!_dbus_string_append_byte (&message->header, type))
01097     return FALSE;
01098   
01099   flags = 0;
01100   if (!_dbus_string_append_byte (&message->header, flags))
01101     return FALSE;
01102 
01103   if (!_dbus_string_append_byte (&message->header, DBUS_MAJOR_PROTOCOL_VERSION))
01104     return FALSE;
01105 
01106   /* header length */
01107   if (!_dbus_marshal_uint32 (&message->header, message->byte_order, 0))
01108     return FALSE;
01109 
01110   /* body length */
01111   if (!_dbus_marshal_uint32 (&message->header, message->byte_order, 0))
01112     return FALSE;
01113 
01114   /* serial */
01115   if (!_dbus_marshal_uint32 (&message->header, message->byte_order, 0))
01116     return FALSE;
01117   
01118   /* Marshal all the fields (Marshall Fields?) */
01119   
01120   if (path != NULL)
01121     {
01122       if (!append_string_field (message,
01123                                 DBUS_HEADER_FIELD_PATH,
01124                                 DBUS_TYPE_OBJECT_PATH,
01125                                 path))
01126         return FALSE;
01127     }
01128   
01129   if (service != NULL)
01130     {
01131       if (!append_string_field (message,
01132                                 DBUS_HEADER_FIELD_DESTINATION,
01133                                 DBUS_TYPE_STRING,
01134                                 service))
01135         return FALSE;
01136     }
01137 
01138   if (interface != NULL)
01139     {
01140       if (!append_string_field (message,
01141                                 DBUS_HEADER_FIELD_INTERFACE,
01142                                 DBUS_TYPE_STRING,
01143                                 interface))
01144         return FALSE;
01145     }
01146 
01147   if (member != NULL)
01148     {
01149       if (!append_string_field (message,
01150                                 DBUS_HEADER_FIELD_MEMBER,
01151                                 DBUS_TYPE_STRING,
01152                                 member))
01153         return FALSE;
01154     }
01155 
01156   if (error_name != NULL)
01157     {
01158       if (!append_string_field (message,
01159                                 DBUS_HEADER_FIELD_ERROR_NAME,
01160                                 DBUS_TYPE_STRING,
01161                                 error_name))
01162         return FALSE;
01163     }
01164 
01165   /* @todo if we make signature optional when body is empty, we don't
01166    * need to do this here.
01167    */
01168   if (!append_string_field (message,
01169                             DBUS_HEADER_FIELD_SIGNATURE,
01170                             DBUS_TYPE_STRING,
01171                             ""))
01172     return FALSE;
01173   
01174   return TRUE;
01175 }
01176 
01186 void
01187 _dbus_message_lock (DBusMessage  *message)
01188 {
01189   if (!message->locked)
01190     {
01191       /* Fill in our lengths */
01192       _dbus_marshal_set_uint32 (&message->header,
01193                                 message->byte_order,
01194                                 HEADER_LENGTH_OFFSET,
01195                                 _dbus_string_get_length (&message->header));
01196 
01197       _dbus_marshal_set_uint32 (&message->header,
01198                                 message->byte_order,
01199                                 BODY_LENGTH_OFFSET,
01200                                 _dbus_string_get_length (&message->body));
01201 
01202       message->locked = TRUE;
01203     }
01204 }
01205 
01237 static dbus_bool_t
01238 dbus_message_set_signature (DBusMessage *message,
01239                             const char  *signature)
01240 {
01241   _dbus_return_val_if_fail (message != NULL, FALSE);
01242   _dbus_return_val_if_fail (!message->locked, FALSE);
01243   
01244   return set_string_field (message,
01245                            DBUS_HEADER_FIELD_SIGNATURE,
01246                            DBUS_TYPE_STRING,
01247                            signature);
01248 }
01249 
01258 static dbus_bool_t
01259 dbus_message_append_to_signature (DBusMessage *message,
01260                                   const char  *append_bytes)
01261 {
01262   const char *signature;
01263   DBusString append_str;
01264   dbus_bool_t retval;
01265   
01266   _dbus_return_val_if_fail (append_bytes != NULL, FALSE);
01267   _dbus_return_val_if_fail (message != NULL, FALSE);
01268   _dbus_return_val_if_fail (!message->locked, FALSE);
01269 
01270   retval = FALSE;
01271   
01272   /* FIXME Just really inefficient for the moment; later we could
01273    * speed it up a lot by poking more directly at the header data
01274    */
01275   signature = dbus_message_get_signature (message);
01276 
01277   if (!_dbus_string_init (&append_str))
01278     return FALSE;
01279 
01280   if (signature && !_dbus_string_append (&append_str, signature))
01281     goto out;
01282 
01283   if (!_dbus_string_append (&append_str, append_bytes))
01284     goto out;
01285   
01286   if (!set_string_field (message,
01287                          DBUS_HEADER_FIELD_SIGNATURE,
01288                          DBUS_TYPE_STRING,
01289                          _dbus_string_get_const_data (&append_str)))
01290     goto out;
01291 
01292   retval = TRUE;
01293   
01294  out:
01295   
01296   _dbus_string_free (&append_str);
01297 
01298   return retval;
01299 }
01300 
01309 static dbus_bool_t
01310 _dbus_message_append_byte_to_signature (DBusMessage  *message,
01311                                         unsigned char append_byte)
01312 {
01313   char buf[2];
01314   
01315   _dbus_return_val_if_fail (message != NULL, FALSE);
01316   _dbus_return_val_if_fail (!message->locked, FALSE);
01317   
01318   buf[0] = append_byte;
01319   buf[1] = '\0';
01320 
01321   return dbus_message_append_to_signature (message, buf);
01322 }
01323 
01330 static void
01331 _dbus_message_remove_byte_from_signature (DBusMessage  *message)
01332 {
01333   const char *signature;
01334   
01335   _dbus_return_if_fail (message != NULL);
01336   _dbus_return_if_fail (!message->locked);
01337 
01338   signature = dbus_message_get_signature (message);
01339 
01340   _dbus_return_if_fail (signature != NULL);
01341   
01342   if (!delete_field (message,
01343                      DBUS_HEADER_FIELD_SIGNATURE,
01344                      0))
01345     _dbus_assert_not_reached ("failed to delete signature field");
01346 
01347   /* reappend one shorter (could this be any less efficient? the code will
01348    * go away later anyhow)
01349    */
01350   if (!append_string_field_len (message, DBUS_HEADER_FIELD_SIGNATURE,
01351                                 DBUS_TYPE_STRING, signature,
01352                                 strlen (signature) - 1))
01353     _dbus_assert_not_reached ("reappending shorter signature shouldn't have failed");
01354 }
01355 
01363 static void
01364 free_size_counter (void *element,
01365                    void *data)
01366 {
01367   DBusCounter *counter = element;
01368   DBusMessage *message = data;
01369   
01370   _dbus_counter_adjust (counter, - message->size_counter_delta);
01371 
01372   _dbus_counter_unref (counter);
01373 }
01374 
01375 static void
01376 dbus_message_finalize (DBusMessage *message)
01377 {
01378   _dbus_assert (message->refcount.value == 0);
01379   
01380   /* This calls application callbacks! */
01381   _dbus_data_slot_list_free (&message->slot_list);
01382   
01383   _dbus_list_foreach (&message->size_counters,
01384                       free_size_counter, message);
01385   _dbus_list_clear (&message->size_counters);
01386   
01387   _dbus_string_free (&message->header);
01388   _dbus_string_free (&message->body);
01389   
01390   dbus_free (message);
01391 }
01392 
01393 /* Message Cache
01394  * 
01395  * We cache some DBusMessage to reduce the overhead of allocating
01396  * them.  In my profiling this consistently made about an 8%
01397  * difference.  It avoids the malloc for the message, the malloc for
01398  * the slot list, the malloc for the header string and body string,
01399  * and the associated free() calls. It does introduce another global
01400  * lock which could be a performance issue in certain cases.
01401  *
01402  * For the echo client/server the round trip time goes from around
01403  * .000077 to .000069 with the message cache on my laptop. The sysprof
01404  * change is as follows (numbers are cumulative percentage):
01405  *
01406  *  with message cache implemented as array as it is now (0.000069 per):
01407  *    new_empty_header           1.46
01408  *      mutex_lock               0.56    # i.e. _DBUS_LOCK(message_cache)
01409  *      mutex_unlock             0.25
01410  *      self                     0.41
01411  *    unref                      2.24
01412  *      self                     0.68
01413  *      list_clear               0.43
01414  *      mutex_lock               0.33    # i.e. _DBUS_LOCK(message_cache)
01415  *      mutex_unlock             0.25
01416  *
01417  *  with message cache implemented as list (0.000070 per roundtrip):
01418  *    new_empty_header           2.72
01419  *      list_pop_first           1.88
01420  *    unref                      3.3
01421  *      list_prepend             1.63
01422  *
01423  * without cache (0.000077 per roundtrip):
01424  *    new_empty_header           6.7
01425  *      string_init_preallocated 3.43
01426  *        dbus_malloc            2.43
01427  *      dbus_malloc0             2.59
01428  * 
01429  *    unref                      4.02
01430  *      string_free              1.82
01431  *        dbus_free              1.63
01432  *      dbus_free                0.71
01433  *
01434  * If you implement the message_cache with a list, the primary reason
01435  * it's slower is that you add another thread lock (on the DBusList
01436  * mempool).
01437  */
01438 
01439 /* Avoid caching huge messages */
01440 #define MAX_MESSAGE_SIZE_TO_CACHE _DBUS_ONE_MEGABYTE
01441 /* Avoid caching too many messages */
01442 #define MAX_MESSAGE_CACHE_SIZE    5
01443 
01444 _DBUS_DEFINE_GLOBAL_LOCK (message_cache);
01445 static DBusMessage *message_cache[MAX_MESSAGE_CACHE_SIZE];
01446 static int message_cache_count = 0;
01447 static dbus_bool_t message_cache_shutdown_registered = FALSE;
01448 
01449 static void
01450 dbus_message_cache_shutdown (void *data)
01451 {
01452   int i;
01453 
01454   _DBUS_LOCK (message_cache);
01455 
01456   i = 0;
01457   while (i < MAX_MESSAGE_CACHE_SIZE)
01458     {
01459       if (message_cache[i])
01460         dbus_message_finalize (message_cache[i]);
01461       
01462       ++i;
01463     }
01464 
01465   message_cache_count = 0;
01466   message_cache_shutdown_registered = FALSE;
01467   
01468   _DBUS_UNLOCK (message_cache);
01469 }
01470 
01478 static DBusMessage*
01479 dbus_message_get_cached (void)
01480 {
01481   DBusMessage *message;
01482   int i;
01483 
01484   message = NULL;
01485   
01486   _DBUS_LOCK (message_cache);
01487 
01488   _dbus_assert (message_cache_count >= 0);
01489   
01490   if (message_cache_count == 0)
01491     {
01492       _DBUS_UNLOCK (message_cache);
01493       return NULL;
01494     }
01495 
01496   /* This is not necessarily true unless count > 0, and
01497    * message_cache is uninitialized until the shutdown is
01498    * registered
01499    */
01500   _dbus_assert (message_cache_shutdown_registered);
01501   
01502   i = 0;
01503   while (i < MAX_MESSAGE_CACHE_SIZE)
01504     {
01505       if (message_cache[i])
01506         {
01507           message = message_cache[i];
01508           message_cache[i] = NULL;
01509           message_cache_count -= 1;
01510           break;
01511         }
01512       ++i;
01513     }
01514   _dbus_assert (message_cache_count >= 0);
01515   _dbus_assert (i < MAX_MESSAGE_CACHE_SIZE);
01516   _dbus_assert (message != NULL);
01517 
01518   _DBUS_UNLOCK (message_cache);
01519 
01520   _dbus_assert (message->refcount.value == 0);
01521   _dbus_assert (message->size_counters == NULL);
01522   
01523   return message;
01524 }
01525 
01531 static void
01532 dbus_message_cache_or_finalize (DBusMessage *message)
01533 {
01534   dbus_bool_t was_cached;
01535   int i;
01536 
01537   _dbus_assert (message->refcount.value == 0);
01538   
01539   /* This calls application code and has to be done first thing
01540    * without holding the lock
01541    */
01542   _dbus_data_slot_list_clear (&message->slot_list);
01543   
01544   _dbus_list_foreach (&message->size_counters,
01545                       free_size_counter, message);
01546   _dbus_list_clear (&message->size_counters);
01547   
01548   was_cached = FALSE;
01549 
01550   _DBUS_LOCK (message_cache);
01551 
01552   if (!message_cache_shutdown_registered)
01553     {
01554       _dbus_assert (message_cache_count == 0);
01555       
01556       if (!_dbus_register_shutdown_func (dbus_message_cache_shutdown, NULL))
01557         goto out;
01558 
01559       i = 0;
01560       while (i < MAX_MESSAGE_CACHE_SIZE)
01561         {
01562           message_cache[i] = NULL;
01563           ++i;
01564         }
01565       
01566       message_cache_shutdown_registered = TRUE;
01567     }
01568 
01569   _dbus_assert (message_cache_count >= 0);
01570   
01571   if ((_dbus_string_get_length (&message->header) +
01572        _dbus_string_get_length (&message->body)) >
01573       MAX_MESSAGE_SIZE_TO_CACHE)
01574     goto out;
01575   
01576   if (message_cache_count >= MAX_MESSAGE_CACHE_SIZE)
01577     goto out;
01578 
01579   /* Find empty slot */
01580   i = 0;
01581   while (message_cache[i] != NULL)
01582     ++i;
01583 
01584   _dbus_assert (i < MAX_MESSAGE_CACHE_SIZE);
01585 
01586   _dbus_assert (message_cache[i] == NULL);
01587   message_cache[i] = message;
01588   message_cache_count += 1;
01589   was_cached = TRUE;
01590   
01591  out:
01592   _DBUS_UNLOCK (message_cache);
01593 
01594   if (!was_cached)
01595     dbus_message_finalize (message);
01596 }
01597 
01598 static DBusMessage*
01599 dbus_message_new_empty_header (void)
01600 {
01601   DBusMessage *message;
01602   int i;
01603   dbus_bool_t from_cache;
01604 
01605   message = dbus_message_get_cached ();
01606 
01607   if (message != NULL)
01608     {
01609       from_cache = TRUE;
01610     }
01611   else
01612     {
01613       from_cache = FALSE;
01614       message = dbus_new (DBusMessage, 1);
01615       if (message == NULL)
01616         return NULL;
01617 #ifndef DBUS_DISABLE_CHECKS
01618       message->generation = _dbus_current_generation;
01619 #endif
01620     }
01621 
01622   message->refcount.value = 1;
01623   message->byte_order = DBUS_COMPILER_BYTE_ORDER;
01624   message->client_serial = 0;
01625   message->reply_serial = 0;
01626   message->locked = FALSE;
01627   message->header_padding = 0;
01628   message->size_counters = NULL;
01629   message->size_counter_delta = 0;
01630   message->changed_stamp = 0;
01631 
01632   if (!from_cache)
01633     _dbus_data_slot_list_init (&message->slot_list);
01634   
01635   i = 0;
01636   while (i <= DBUS_HEADER_FIELD_LAST)
01637     {
01638       message->header_fields[i].name_offset  = -1;
01639       message->header_fields[i].value_offset = -1;
01640       ++i;
01641     }
01642 
01643   if (from_cache)
01644     {
01645       /* These can't fail since they shorten the string */
01646       _dbus_string_set_length (&message->header, 0);
01647       _dbus_string_set_length (&message->body, 0);
01648     }
01649   else
01650     {
01651       if (!_dbus_string_init_preallocated (&message->header, 32))
01652         {
01653           dbus_free (message);
01654           return NULL;
01655         }
01656       
01657       if (!_dbus_string_init_preallocated (&message->body, 32))
01658         {
01659           _dbus_string_free (&message->header);
01660           dbus_free (message);
01661           return NULL;
01662         }
01663     }
01664   
01665   return message;
01666 }
01667 
01676 DBusMessage*
01677 dbus_message_new (int message_type)
01678 {
01679   DBusMessage *message;
01680 
01681   _dbus_return_val_if_fail (message_type != DBUS_MESSAGE_TYPE_INVALID, NULL);
01682   
01683   message = dbus_message_new_empty_header ();
01684   if (message == NULL)
01685     return NULL;
01686   
01687   if (!dbus_message_create_header (message,
01688                                    message_type,
01689                                    NULL, NULL, NULL, NULL, NULL))
01690     {
01691       dbus_message_unref (message);
01692       return NULL;
01693     }
01694   
01695   return message;
01696 }
01697 
01715 DBusMessage*
01716 dbus_message_new_method_call (const char *service,
01717                               const char *path,
01718                               const char *interface,
01719                               const char *method)
01720 {
01721   DBusMessage *message;
01722 
01723   _dbus_return_val_if_fail (path != NULL, NULL);
01724   _dbus_return_val_if_fail (method != NULL, NULL);
01725   
01726   message = dbus_message_new_empty_header ();
01727   if (message == NULL)
01728     return NULL;
01729   
01730   if (!dbus_message_create_header (message,
01731                                    DBUS_MESSAGE_TYPE_METHOD_CALL,
01732                                    service, path, interface, method, NULL))
01733     {
01734       dbus_message_unref (message);
01735       return NULL;
01736     }
01737   
01738   return message;
01739 }
01740 
01750 DBusMessage*
01751 dbus_message_new_method_return (DBusMessage *method_call)
01752 {
01753   DBusMessage *message;
01754   const char *sender;
01755 
01756   _dbus_return_val_if_fail (method_call != NULL, NULL);
01757   
01758   sender = get_string_field (method_call,
01759                              DBUS_HEADER_FIELD_SENDER,
01760                              NULL);
01761   
01762   /* sender is allowed to be null here in peer-to-peer case */
01763 
01764   message = dbus_message_new_empty_header ();
01765   if (message == NULL)
01766     return NULL;
01767   
01768   if (!dbus_message_create_header (message,
01769                                    DBUS_MESSAGE_TYPE_METHOD_RETURN,
01770                                    sender, NULL, NULL, NULL, NULL))
01771     {
01772       dbus_message_unref (message);
01773       return NULL;
01774     }
01775 
01776   dbus_message_set_no_reply (message, TRUE);
01777 
01778   if (!dbus_message_set_reply_serial (message,
01779                                       dbus_message_get_serial (method_call)))
01780     {
01781       dbus_message_unref (message);
01782       return NULL;
01783     }
01784 
01785   return message;
01786 }
01787 
01800 DBusMessage*
01801 dbus_message_new_signal (const char *path,
01802                          const char *interface,
01803                          const char *name)
01804 {
01805   DBusMessage *message;
01806 
01807   _dbus_return_val_if_fail (path != NULL, NULL);
01808   _dbus_return_val_if_fail (interface != NULL, NULL);
01809   _dbus_return_val_if_fail (name != NULL, NULL);
01810   
01811   message = dbus_message_new_empty_header ();
01812   if (message == NULL)
01813     return NULL;
01814   
01815   if (!dbus_message_create_header (message,
01816                                    DBUS_MESSAGE_TYPE_SIGNAL,
01817                                    NULL, path, interface, name, NULL))
01818     {
01819       dbus_message_unref (message);
01820       return NULL;
01821     }
01822 
01823   dbus_message_set_no_reply (message, TRUE);
01824   
01825   return message;
01826 }
01827 
01837 DBusMessage*
01838 dbus_message_new_error (DBusMessage *reply_to,
01839                         const char  *error_name,
01840                         const char  *error_message)
01841 {
01842   DBusMessage *message;
01843   const char *sender;
01844   DBusMessageIter iter;
01845 
01846   _dbus_return_val_if_fail (reply_to != NULL, NULL);
01847   _dbus_return_val_if_fail (error_name != NULL, NULL);
01848   _dbus_return_val_if_fail (is_valid_error_name (error_name), NULL);
01849   
01850   sender = get_string_field (reply_to,
01851                              DBUS_HEADER_FIELD_SENDER,
01852                              NULL);
01853 
01854   /* sender may be NULL for non-message-bus case or
01855    * when the message bus is dealing with an unregistered
01856    * connection.
01857    */
01858   message = dbus_message_new_empty_header ();
01859   if (message == NULL)
01860     return NULL;
01861   
01862   if (!dbus_message_create_header (message,
01863                                    DBUS_MESSAGE_TYPE_ERROR,
01864                                    sender, NULL, NULL, NULL, error_name))
01865     {
01866       dbus_message_unref (message);
01867       return NULL;
01868     }
01869 
01870   dbus_message_set_no_reply (message, TRUE);
01871   
01872   if (!dbus_message_set_reply_serial (message,
01873                                       dbus_message_get_serial (reply_to)))
01874     {
01875       dbus_message_unref (message);
01876       return NULL;
01877     }
01878 
01879   if (error_message != NULL)
01880     {
01881       dbus_message_append_iter_init (message, &iter);
01882       if (!dbus_message_iter_append_string (&iter, error_message))
01883         {
01884           dbus_message_unref (message);
01885           return NULL;
01886         }
01887     }
01888   
01889   return message;
01890 }
01891 
01902 DBusMessage*
01903 dbus_message_new_error_printf (DBusMessage *reply_to,
01904                                const char  *error_name,
01905                                const char  *error_format,
01906                                ...)
01907 {
01908   va_list args;
01909   DBusString str;
01910   DBusMessage *message;
01911 
01912   _dbus_return_val_if_fail (reply_to != NULL, NULL);
01913   _dbus_return_val_if_fail (error_name != NULL, NULL);
01914   _dbus_return_val_if_fail (is_valid_error_name (error_name), NULL);
01915   
01916   if (!_dbus_string_init (&str))
01917     return NULL;
01918 
01919   va_start (args, error_format);
01920 
01921   if (_dbus_string_append_printf_valist (&str, error_format, args))
01922     message = dbus_message_new_error (reply_to, error_name,
01923                                       _dbus_string_get_const_data (&str));
01924   else
01925     message = NULL;
01926   
01927   _dbus_string_free (&str);
01928 
01929   va_end (args);
01930 
01931   return message;
01932 }
01933 
01934 
01942 DBusMessage *
01943 dbus_message_copy (const DBusMessage *message)
01944 {
01945   DBusMessage *retval;
01946   int i;
01947 
01948   _dbus_return_val_if_fail (message != NULL, NULL);
01949   
01950   retval = dbus_new0 (DBusMessage, 1);
01951   if (retval == NULL)
01952     return NULL;
01953   
01954   retval->refcount.value = 1;
01955   retval->byte_order = message->byte_order;
01956   retval->client_serial = message->client_serial;
01957   retval->reply_serial = message->reply_serial;
01958   retval->header_padding = message->header_padding;
01959   retval->locked = FALSE;
01960 #ifndef DBUS_DISABLE_CHECKS
01961   retval->generation = message->generation;
01962 #endif
01963   
01964   if (!_dbus_string_init_preallocated (&retval->header,
01965                                        _dbus_string_get_length (&message->header)))
01966     {
01967       dbus_free (retval);
01968       return NULL;
01969     }
01970   
01971   if (!_dbus_string_init_preallocated (&retval->body,
01972                                        _dbus_string_get_length (&message->body)))
01973     {
01974       _dbus_string_free (&retval->header);
01975       dbus_free (retval);
01976       return NULL;
01977     }
01978   
01979   if (!_dbus_string_copy (&message->header, 0,
01980                           &retval->header, 0))
01981     goto failed_copy;
01982 
01983   if (!_dbus_string_copy (&message->body, 0,
01984                           &retval->body, 0))
01985     goto failed_copy;
01986   
01987   for (i = 0; i <= DBUS_HEADER_FIELD_LAST; i++)
01988     {
01989       retval->header_fields[i] = message->header_fields[i];
01990     }
01991   
01992   return retval;
01993 
01994  failed_copy:
01995   _dbus_string_free (&retval->header);
01996   _dbus_string_free (&retval->body);
01997   dbus_free (retval);
01998   
01999   return NULL;  
02000 }
02001 
02002 
02010 DBusMessage *
02011 dbus_message_ref (DBusMessage *message)
02012 {
02013   dbus_int32_t old_refcount;
02014 
02015   _dbus_return_val_if_fail (message != NULL, NULL);
02016   _dbus_return_val_if_fail (message->generation == _dbus_current_generation, NULL);
02017   
02018   old_refcount = _dbus_atomic_inc (&message->refcount);
02019   _dbus_assert (old_refcount >= 1);
02020 
02021   return message;
02022 }
02023 
02030 void
02031 dbus_message_unref (DBusMessage *message)
02032 {
02033  dbus_int32_t old_refcount;
02034 
02035   _dbus_return_if_fail (message != NULL);
02036   _dbus_return_if_fail (message->generation == _dbus_current_generation);
02037   
02038   old_refcount = _dbus_atomic_dec (&message->refcount);
02039   
02040   _dbus_assert (old_refcount >= 0);
02041 
02042   if (old_refcount == 1)
02043     {
02044       /* Calls application callbacks! */
02045       dbus_message_cache_or_finalize (message);
02046     }
02047 }
02048 
02060 int
02061 dbus_message_get_type (DBusMessage *message)
02062 {
02063   int type;
02064 
02065   type = _dbus_string_get_byte (&message->header, 1);
02066   _dbus_assert (type != DBUS_MESSAGE_TYPE_INVALID);
02067 
02068   return type;
02069 }
02070 
02080 dbus_bool_t
02081 dbus_message_set_path (DBusMessage   *message,
02082                        const char    *object_path)
02083 {
02084   _dbus_return_val_if_fail (message != NULL, FALSE);
02085   _dbus_return_val_if_fail (!message->locked, FALSE);
02086 
02087   return set_string_field (message,
02088                            DBUS_HEADER_FIELD_PATH,
02089                            DBUS_TYPE_OBJECT_PATH,
02090                            object_path);
02091 }
02092 
02101 const char*
02102 dbus_message_get_path (DBusMessage   *message)
02103 {
02104   _dbus_return_val_if_fail (message != NULL, NULL);
02105   
02106   return get_string_field (message, DBUS_HEADER_FIELD_PATH, NULL);
02107 }
02108 
02124 dbus_bool_t
02125 dbus_message_get_path_decomposed (DBusMessage   *message,
02126                                   char        ***path)
02127 {
02128   _dbus_return_val_if_fail (message != NULL, FALSE);
02129   _dbus_return_val_if_fail (path != NULL, FALSE);
02130 
02131   return get_path_field_decomposed (message,
02132                                     DBUS_HEADER_FIELD_PATH,
02133                                     path);
02134 }
02135 
02146 dbus_bool_t
02147 dbus_message_set_interface (DBusMessage  *message,
02148                             const char   *interface)
02149 {
02150   _dbus_return_val_if_fail (message != NULL, FALSE);
02151   _dbus_return_val_if_fail (!message->locked, FALSE);
02152 
02153   return set_string_field (message,
02154                            DBUS_HEADER_FIELD_INTERFACE,
02155                            DBUS_TYPE_STRING,
02156                            interface);
02157 }
02158 
02168 const char*
02169 dbus_message_get_interface (DBusMessage *message)
02170 {
02171   _dbus_return_val_if_fail (message != NULL, NULL);
02172   
02173   return get_string_field (message, DBUS_HEADER_FIELD_INTERFACE, NULL);
02174 }
02175 
02186 dbus_bool_t
02187 dbus_message_set_member (DBusMessage  *message,
02188                        const char   *member)
02189 {
02190   _dbus_return_val_if_fail (message != NULL, FALSE);
02191   _dbus_return_val_if_fail (!message->locked, FALSE);
02192 
02193   return set_string_field (message,
02194                            DBUS_HEADER_FIELD_MEMBER,
02195                            DBUS_TYPE_STRING,
02196                            member);
02197 }
02198 
02207 const char*
02208 dbus_message_get_member (DBusMessage *message)
02209 {
02210   _dbus_return_val_if_fail (message != NULL, NULL);
02211   
02212   return get_string_field (message,
02213                            DBUS_HEADER_FIELD_MEMBER,
02214                            NULL);
02215 }
02216 
02225 dbus_bool_t
02226 dbus_message_set_error_name (DBusMessage  *message,
02227                              const char   *error_name)
02228 {
02229   _dbus_return_val_if_fail (message != NULL, FALSE);
02230   _dbus_return_val_if_fail (!message->locked, FALSE);
02231   _dbus_return_val_if_fail (error_name == NULL || is_valid_error_name (error_name), FALSE);
02232   
02233   return set_string_field (message,
02234                            DBUS_HEADER_FIELD_ERROR_NAME,
02235                            DBUS_TYPE_STRING,
02236                            error_name);
02237 }
02238 
02245 const char*
02246 dbus_message_get_error_name (DBusMessage *message)
02247 {
02248   _dbus_return_val_if_fail (message != NULL, NULL);
02249   
02250   return get_string_field (message,
02251                            DBUS_HEADER_FIELD_ERROR_NAME,
02252                            NULL);
02253 }
02254 
02262 dbus_bool_t
02263 dbus_message_set_destination (DBusMessage  *message,
02264                               const char   *destination)
02265 {
02266   _dbus_return_val_if_fail (message != NULL, FALSE);
02267   _dbus_return_val_if_fail (!message->locked, FALSE);
02268 
02269   return set_string_field (message,
02270                            DBUS_HEADER_FIELD_DESTINATION,
02271                            DBUS_TYPE_STRING,
02272                            destination);
02273 }
02274 
02281 const char*
02282 dbus_message_get_destination (DBusMessage *message)
02283 {
02284   _dbus_return_val_if_fail (message != NULL, NULL);
02285   
02286   return get_string_field (message,
02287                            DBUS_HEADER_FIELD_DESTINATION,
02288                            NULL);
02289 }
02290 
02309 dbus_bool_t
02310 dbus_message_append_args (DBusMessage *message,
02311                           int first_arg_type,
02312                           ...)
02313 {
02314   dbus_bool_t retval;
02315   va_list var_args;
02316 
02317   _dbus_return_val_if_fail (message != NULL, FALSE);
02318   
02319   va_start (var_args, first_arg_type);
02320   retval = dbus_message_append_args_valist (message,
02321                                             first_arg_type,
02322                                             var_args);
02323   va_end (var_args);
02324 
02325   return retval;
02326 }
02327 
02328 /* Swap into our byte order if message isn't already.
02329  * Done only when required, which allows the bus to avoid
02330  * ever doing this as it routes messages.
02331  */
02332 static void
02333 _dbus_message_ensure_our_byte_order (DBusMessage *message)
02334 {
02335   if (message->byte_order == DBUS_COMPILER_BYTE_ORDER)
02336     return;
02337 
02338   
02339 
02340 
02341 }
02342 
02355 dbus_bool_t
02356 dbus_message_get_args (DBusMessage     *message,
02357                        DBusError       *error,
02358                        int              first_arg_type,
02359                        ...)
02360 {
02361   dbus_bool_t retval;
02362   va_list var_args;
02363 
02364   _dbus_return_val_if_fail (message != NULL, FALSE);
02365   _dbus_return_val_if_error_is_set (error, FALSE);
02366   
02367   va_start (var_args, first_arg_type);
02368   retval = dbus_message_get_args_valist (message, error, first_arg_type, var_args);
02369   va_end (var_args);
02370 
02371   return retval;
02372 }
02373 
02386 dbus_bool_t
02387 dbus_message_get_args_valist (DBusMessage     *message,
02388                               DBusError       *error,
02389                               int              first_arg_type,
02390                               va_list          var_args)
02391 {
02392   DBusMessageIter iter;
02393 
02394   _dbus_return_val_if_fail (message != NULL, FALSE);
02395   _dbus_return_val_if_error_is_set (error, FALSE);
02396   
02397   dbus_message_iter_init (message, &iter);
02398   return dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args);
02399 }
02400 
02413 dbus_bool_t
02414 dbus_message_iter_get_args (DBusMessageIter *iter,
02415                             DBusError       *error,
02416                             int              first_arg_type,
02417                             ...)
02418 {
02419   dbus_bool_t retval;
02420   va_list var_args;
02421 
02422   _dbus_return_val_if_fail (iter != NULL, FALSE);
02423   _dbus_return_val_if_error_is_set (error, FALSE);
02424   
02425   va_start (var_args, first_arg_type);
02426   retval = dbus_message_iter_get_args_valist (iter, error, first_arg_type, var_args);
02427   va_end (var_args);
02428 
02429   return retval;
02430 }
02431 
02440 dbus_bool_t
02441 dbus_message_iter_init (DBusMessage     *message,
02442                         DBusMessageIter *iter)
02443 {
02444   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02445 
02446   _dbus_return_val_if_fail (message != NULL, FALSE);
02447   _dbus_return_val_if_fail (iter != NULL, FALSE);
02448   
02449   _dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
02450   
02451   real->message = message;
02452   real->parent_iter = NULL;
02453   real->changed_stamp = message->changed_stamp;
02454   
02455   real->type = DBUS_MESSAGE_ITER_TYPE_MESSAGE;
02456   real->pos = 0;
02457   real->end = _dbus_string_get_length (&message->body);
02458   
02459   real->container_start = 0;
02460   real->container_length_pos = 0;
02461   real->wrote_dict_key = 0;
02462   real->array_type_pos = 0;
02463 
02464   return real->end > real->pos;
02465 }
02466 
02467 #ifndef DBUS_DISABLE_CHECKS
02468 static dbus_bool_t
02469 dbus_message_iter_check (DBusMessageRealIter *iter)
02470 {
02471   if (iter == NULL)
02472     {
02473       _dbus_warn ("dbus iterator check failed: iterator is NULL\n");
02474       return FALSE;
02475     }
02476   
02477   if (iter->changed_stamp != iter->message->changed_stamp)
02478     {
02479       _dbus_warn ("dbus iterator check failed: invalid iterator, must re-initialize it after modifying the message\n");
02480       return FALSE;
02481     }
02482   
02483   if (iter->pos < 0 || iter->pos > iter->end)
02484     {
02485       _dbus_warn ("dbus iterator check failed: invalid position\n");
02486       return FALSE;
02487     }
02488 
02489   return TRUE;
02490 }
02491 #endif /* DBUS_DISABLE_CHECKS */
02492 
02493 static int
02494 skip_array_type (DBusMessageRealIter *iter, int pos)
02495 {
02496   const char *data;
02497 
02498   do
02499     {
02500       data = _dbus_string_get_const_data_len (&iter->message->body,
02501                                               pos++, 1);
02502     }
02503   while (*data == DBUS_TYPE_ARRAY);
02504   
02505   return pos;
02506 }
02507 
02508 /* FIXME what are these _dbus_type_is_valid() checks for?
02509  * haven't we validated the message?
02510  */
02511 static int
02512 dbus_message_iter_get_data_start (DBusMessageRealIter *iter, int *type)
02513 {
02514   const char *data;
02515   int pos, len;
02516   
02517   switch (iter->type)
02518     {
02519     case DBUS_MESSAGE_ITER_TYPE_MESSAGE:
02520       data = _dbus_string_get_const_data_len (&iter->message->body,
02521                                               iter->pos, 1);
02522       if (_dbus_type_is_valid (*data))
02523         *type = *data;
02524       else
02525         *type = DBUS_TYPE_INVALID;
02526       
02527       return skip_array_type (iter, iter->pos);
02528       
02529     case DBUS_MESSAGE_ITER_TYPE_ARRAY:
02530       data = _dbus_string_get_const_data_len (&iter->message->body,
02531                                               iter->array_type_pos, 1);
02532       if (_dbus_type_is_valid (*data))
02533         *type = *data;
02534       else
02535         *type = DBUS_TYPE_INVALID;
02536       
02537       return iter->pos;
02538       
02539     case DBUS_MESSAGE_ITER_TYPE_DICT:
02540       /* Get the length of the string */
02541       len = _dbus_demarshal_uint32 (&iter->message->body,
02542                                     iter->message->byte_order,
02543                                     iter->pos, &pos);
02544       pos = pos + len + 1;
02545 
02546       data = _dbus_string_get_const_data_len (&iter->message->body,
02547                                               pos, 1);
02548       if (_dbus_type_is_valid (*data))
02549         *type = *data;
02550       else
02551         *type = DBUS_TYPE_INVALID;
02552 
02553       return skip_array_type (iter, pos);
02554       
02555     default:
02556       _dbus_assert_not_reached ("Invalid iter type");
02557       break;
02558     }
02559   *type = DBUS_TYPE_INVALID;
02560   return iter->pos;
02561 }
02562 
02563 
02571 dbus_bool_t
02572 dbus_message_iter_has_next (DBusMessageIter *iter)
02573 {
02574   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02575   int end_pos;
02576   int type, pos;
02577 
02578   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
02579 
02580   if (real->pos >= real->end)
02581     return FALSE;
02582   
02583   pos = dbus_message_iter_get_data_start (real, &type);
02584   
02585   if (!_dbus_marshal_get_arg_end_pos (&real->message->body,
02586                                       real->message->byte_order,
02587                                       type, pos, &end_pos))
02588     return FALSE;
02589   
02590   if (end_pos >= real->end)
02591     return FALSE;
02592 
02593   return TRUE;  
02594 }
02595 
02602 dbus_bool_t
02603 dbus_message_iter_next (DBusMessageIter *iter)
02604 {
02605   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02606   int end_pos;
02607   int type, pos;
02608 
02609   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
02610 
02611   pos = dbus_message_iter_get_data_start (real, &type);
02612   
02613   if (!_dbus_marshal_get_arg_end_pos (&real->message->body,
02614                                       real->message->byte_order,
02615                                       type, pos, &end_pos))
02616     return FALSE;
02617 
02618   if (end_pos >= real->end)
02619     return FALSE;
02620 
02621   real->pos = end_pos;
02622 
02623   return TRUE;
02624 }
02625 
02633 int
02634 dbus_message_iter_get_arg_type (DBusMessageIter *iter)
02635 {
02636   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02637   int type, pos;
02638 
02639   _dbus_return_val_if_fail (dbus_message_iter_check (real), DBUS_TYPE_INVALID);
02640 
02641   if (real->pos >= real->end)
02642     {
02643       _dbus_verbose ("  iterator at or beyond end of message\n");
02644       return DBUS_TYPE_INVALID;
02645     }
02646 
02647   pos = dbus_message_iter_get_data_start (real, &type);
02648   
02649   return type;
02650 }
02651 
02652 /* FIXME why do we validate the typecode in here, hasn't the message
02653  * already been verified?
02654  */
02655 static int
02656 iter_get_array_type (DBusMessageRealIter *iter, int *array_type_pos)
02657 {
02658   const char *data;
02659   int _array_type_pos;
02660   int len, pos;
02661   
02662   switch (iter->type)
02663     {
02664     case DBUS_MESSAGE_ITER_TYPE_MESSAGE:
02665       _array_type_pos = iter->pos + 1;
02666       break;
02667     case DBUS_MESSAGE_ITER_TYPE_ARRAY:
02668       _array_type_pos = iter->array_type_pos + 1;
02669       break;
02670     case DBUS_MESSAGE_ITER_TYPE_DICT:
02671       /* Get the length of the string */
02672       len = _dbus_demarshal_uint32 (&iter->message->body,
02673                                     iter->message->byte_order,
02674                                     iter->pos, &pos);
02675       pos = pos + len + 1;
02676       data = _dbus_string_get_const_data_len (&iter->message->body,
02677                                               pos + 1, 1);
02678       _array_type_pos = pos + 1;
02679       break;
02680     default:
02681       _dbus_assert_not_reached ("wrong iter type");
02682       return DBUS_TYPE_INVALID;
02683     }
02684 
02685   if (array_type_pos != NULL)
02686     *array_type_pos = _array_type_pos;
02687   
02688   data = _dbus_string_get_const_data_len (&iter->message->body,
02689                                           _array_type_pos, 1);
02690   if (_dbus_type_is_valid (*data))
02691     return  *data;
02692   
02693   return DBUS_TYPE_INVALID;
02694 }
02695 
02696 
02706 int
02707 dbus_message_iter_get_array_type (DBusMessageIter *iter)
02708 {
02709   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02710   int type, pos;
02711 
02712   _dbus_return_val_if_fail (dbus_message_iter_check (real), DBUS_TYPE_INVALID);
02713 
02714   if (real->pos >= real->end)
02715     return DBUS_TYPE_INVALID;
02716 
02717   pos = dbus_message_iter_get_data_start (real, &type);
02718 
02719   _dbus_assert (type == DBUS_TYPE_ARRAY);
02720 
02721   return iter_get_array_type (real, NULL);
02722 }
02723 
02724 
02734 char *
02735 dbus_message_iter_get_string (DBusMessageIter *iter)
02736 {
02737   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02738   int type, pos;
02739 
02740   _dbus_return_val_if_fail (dbus_message_iter_check (real), NULL);
02741   pos = dbus_message_iter_get_data_start (real, &type);
02742   
02743   _dbus_assert (type == DBUS_TYPE_STRING);
02744 
02745   return _dbus_demarshal_string (&real->message->body, real->message->byte_order,
02746                                  pos, NULL);
02747 }
02748 
02758 char *
02759 dbus_message_iter_get_object_path (DBusMessageIter  *iter)
02760 {
02761   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02762   int type, pos;
02763 
02764   _dbus_return_val_if_fail (dbus_message_iter_check (real), NULL);
02765 
02766   pos = dbus_message_iter_get_data_start (real, &type);
02767   
02768   _dbus_assert (type == DBUS_TYPE_OBJECT_PATH);
02769 
02770   return _dbus_demarshal_string (&real->message->body, real->message->byte_order,
02771                                  pos, NULL);
02772 }
02773 
02787 dbus_bool_t
02788 dbus_message_iter_get_custom (DBusMessageIter   *iter,
02789                               char             **name,
02790                               unsigned char    **value,
02791                               int               *len)
02792 {
02793   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02794   int type, pos;
02795   char *_name;
02796 
02797   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
02798 
02799   pos = dbus_message_iter_get_data_start (real, &type);
02800   
02801   _dbus_assert (type == DBUS_TYPE_CUSTOM);
02802   
02803   _name = _dbus_demarshal_string (&real->message->body, real->message->byte_order,
02804                                   pos, &pos);
02805 
02806   if (_name == NULL)
02807     return FALSE;
02808   
02809   if (!_dbus_demarshal_byte_array (&real->message->body, real->message->byte_order,
02810                                    pos, NULL, value, len))
02811     {
02812       dbus_free (_name);
02813       return FALSE;
02814     }
02815 
02816   *name = _name;
02817   
02818   return TRUE;
02819 }
02820 
02821 static void
02822 _dbus_message_iter_get_basic_type (DBusMessageIter *iter,
02823                                    char             type,
02824                                    void            *value)
02825 {
02826   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02827   int item_type, pos;
02828 
02829   _dbus_return_if_fail (dbus_message_iter_check (real));
02830 
02831   pos = dbus_message_iter_get_data_start (real, &item_type);
02832   
02833   _dbus_assert (type == item_type);
02834   
02835   _dbus_demarshal_basic_type (&real->message->body,
02836                               type, value,
02837                               real->message->byte_order,
02838                               &pos);
02839 }
02840 
02841 
02864 dbus_bool_t
02865 dbus_message_iter_get_args_valist (DBusMessageIter *iter,
02866                                    DBusError       *error,
02867                                    int              first_arg_type,
02868                                    va_list          var_args)
02869 {
02870   int spec_type, msg_type, i;
02871   dbus_bool_t retval;
02872 
02873   _dbus_return_val_if_fail (iter != NULL, FALSE);
02874   _dbus_return_val_if_error_is_set (error, FALSE);
02875 
02876   retval = FALSE;
02877   
02878   spec_type = first_arg_type;
02879   i = 0;
02880   
02881   while (spec_type != DBUS_TYPE_INVALID)
02882     {
02883       msg_type = dbus_message_iter_get_arg_type (iter);      
02884       
02885       if (msg_type != spec_type)
02886         {
02887           dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
02888                           "Argument %d is specified to be of type \"%s\", but "
02889                           "is actually of type \"%s\"\n", i,
02890                           _dbus_type_to_string (spec_type),
02891                           _dbus_type_to_string (msg_type));
02892 
02893           goto out;
02894         }
02895 
02896       switch (spec_type)
02897         {
02898         case DBUS_TYPE_NIL:
02899           break;
02900         case DBUS_TYPE_BOOLEAN:
02901           {
02902             dbus_bool_t *ptr;
02903 
02904             ptr = va_arg (var_args, dbus_bool_t *);
02905 
02906             *ptr = dbus_message_iter_get_boolean (iter);
02907             break;
02908           }
02909         case DBUS_TYPE_BYTE:
02910         case DBUS_TYPE_INT32:
02911         case DBUS_TYPE_UINT32:
02912 #ifdef DBUS_HAVE_INT64
02913         case DBUS_TYPE_INT64:
02914         case DBUS_TYPE_UINT64:
02915 #endif /* DBUS_HAVE_INT64 */
02916         case DBUS_TYPE_DOUBLE:
02917           {
02918             void *ptr = va_arg (var_args, double *);
02919             _dbus_message_iter_get_basic_type (iter, spec_type, ptr);
02920             break;
02921           }
02922 
02923         case DBUS_TYPE_STRING:
02924           {
02925             char **ptr;
02926 
02927             ptr = va_arg (var_args, char **);
02928 
02929             *ptr = dbus_message_iter_get_string (iter);
02930 
02931             if (!*ptr)
02932               {
02933                 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02934                 goto out;
02935               }
02936             
02937             break;
02938           }
02939 
02940           case DBUS_TYPE_OBJECT_PATH:
02941           {
02942             char **ptr;
02943 
02944             ptr = va_arg (var_args, char **);
02945 
02946             *ptr = dbus_message_iter_get_object_path (iter);
02947 
02948             if (!*ptr)
02949               {
02950                 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02951                 goto out;
02952               }
02953 
02954             break;
02955           }
02956 
02957         case DBUS_TYPE_CUSTOM:
02958           {
02959             char **name;
02960             unsigned char **data;
02961             int *len;
02962  
02963             name = va_arg (var_args, char **);
02964             data = va_arg (var_args, unsigned char **);
02965             len = va_arg (var_args, int *);
02966 
02967             if (!dbus_message_iter_get_custom (iter, name, data, len))
02968               {
02969                 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02970                 goto out;
02971               }
02972           }
02973           break;
02974         case DBUS_TYPE_ARRAY:
02975           {
02976             void **data;
02977             int *len, type;
02978             dbus_bool_t err = FALSE;
02979  
02980             type = va_arg (var_args, int);
02981             data = va_arg (var_args, void *);
02982             len = va_arg (var_args, int *);
02983 
02984             _dbus_return_val_if_fail (data != NULL, FALSE);
02985             _dbus_return_val_if_fail (len != NULL, FALSE);
02986             
02987             if (dbus_message_iter_get_array_type (iter) != type)
02988               {
02989                 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
02990                                 "Argument %d is specified to be of type \"array of %s\", but "
02991                                 "is actually of type \"array of %s\"\n", i,
02992                                 _dbus_type_to_string (type),
02993                                 _dbus_type_to_string (dbus_message_iter_get_array_type (iter)));
02994                 goto out;
02995               }
02996             
02997             switch (type)
02998               {
02999               case DBUS_TYPE_BYTE:
03000                 err = !dbus_message_iter_get_byte_array (iter, (unsigned char **)data, len);
03001                 break;
03002               case DBUS_TYPE_BOOLEAN:
03003                 err = !dbus_message_iter_get_boolean_array (iter, (unsigned char **)data, len);
03004                 break;
03005               case DBUS_TYPE_INT32:
03006                 err = !dbus_message_iter_get_int32_array (iter, (dbus_int32_t **)data, len);
03007                 break;
03008               case DBUS_TYPE_UINT32:
03009                 err = !dbus_message_iter_get_uint32_array (iter, (dbus_uint32_t **)data, len);
03010                 break;
03011 #ifdef DBUS_HAVE_INT64
03012               case DBUS_TYPE_INT64:
03013                 err = !dbus_message_iter_get_int64_array (iter, (dbus_int64_t **)data, len);
03014                 break;
03015               case DBUS_TYPE_UINT64:
03016                 err = !dbus_message_iter_get_uint64_array (iter, (dbus_uint64_t **)data, len);
03017                 break;
03018 #endif /* DBUS_HAVE_INT64 */
03019               case DBUS_TYPE_DOUBLE:
03020                 err = !dbus_message_iter_get_double_array (iter, (double **)data, len);
03021                 break;
03022               case DBUS_TYPE_STRING:
03023                 err = !dbus_message_iter_get_string_array (iter, (char ***)data, len);
03024                 break;
03025               case DBUS_TYPE_OBJECT_PATH:
03026                 err = !dbus_message_iter_get_object_path_array (iter, (char ***)data, len);
03027                 break;
03028 
03029               case DBUS_TYPE_NIL:
03030               case DBUS_TYPE_ARRAY:
03031               case DBUS_TYPE_CUSTOM:
03032               case DBUS_TYPE_DICT:
03033                 _dbus_warn ("dbus_message_get_args_valist doesn't support recursive arrays\n");
03034                 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
03035                 goto out;
03036               default:
03037                 _dbus_warn ("Unknown field type %d\n", type);
03038                 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
03039                 goto out;
03040               }
03041             if (err)
03042               {
03043                 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
03044                 goto out;
03045               }
03046           }
03047           break;
03048         case DBUS_TYPE_DICT:
03049           _dbus_warn ("dbus_message_get_args_valist doesn't support dicts\n");
03050           dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
03051           goto out;
03052         default:          
03053           dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
03054           _dbus_warn ("Unknown field type %d\n", spec_type);
03055           goto out;
03056         }
03057 
03058       spec_type = va_arg (var_args, int);
03059       if (!dbus_message_iter_next (iter) && spec_type != DBUS_TYPE_INVALID)
03060         {
03061           dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
03062                           "Message has only %d arguments, but more were expected", i);
03063           goto out;
03064         }
03065 
03066       i++;
03067     }
03068   
03069   retval = TRUE;
03070   
03071  out:
03072   
03073   return retval;
03074 }
03075 
03085 unsigned char
03086 dbus_message_iter_get_byte (DBusMessageIter *iter)
03087 {
03088   unsigned char value = 0;
03089 
03090   _dbus_message_iter_get_basic_type (iter, DBUS_TYPE_BYTE, &value);
03091 
03092   return value;
03093 }
03094 
03104 dbus_bool_t
03105 dbus_message_iter_get_boolean (DBusMessageIter *iter)
03106 {
03107   unsigned char value = 0;
03108 
03109   _dbus_message_iter_get_basic_type (iter, DBUS_TYPE_BOOLEAN, &value);
03110 
03111   return (value != FALSE);
03112 }
03113 
03123 dbus_int32_t
03124 dbus_message_iter_get_int32 (DBusMessageIter *iter)
03125 {
03126   dbus_int32_t value = 0;
03127 
03128   _dbus_message_iter_get_basic_type (iter, DBUS_TYPE_INT32, &value);
03129 
03130   return value;
03131 }
03132 
03142 dbus_uint32_t
03143 dbus_message_iter_get_uint32 (DBusMessageIter *iter)
03144 {
03145   dbus_int32_t value = 0;
03146 
03147   _dbus_message_iter_get_basic_type (iter, DBUS_TYPE_UINT32, &value);
03148 
03149   return value;
03150 }
03151 
03152 #ifdef DBUS_HAVE_INT64
03153 
03165 dbus_int64_t
03166 dbus_message_iter_get_int64 (DBusMessageIter *iter)
03167 {
03168   dbus_int64_t value = 0;
03169 
03170   _dbus_message_iter_get_basic_type (iter, DBUS_TYPE_INT64, &value);
03171 
03172   return value;
03173 }
03174 
03186 dbus_uint64_t
03187 dbus_message_iter_get_uint64 (DBusMessageIter *iter)
03188 {
03189   dbus_uint64_t value = 0;
03190 
03191   _dbus_message_iter_get_basic_type (iter, DBUS_TYPE_UINT64, &value);
03192 
03193   return value;
03194 }
03195 
03196 #endif /* DBUS_HAVE_INT64 */
03197 
03207 double
03208 dbus_message_iter_get_double (DBusMessageIter *iter)
03209 {
03210   double value = 0.0;
03211 
03212   _dbus_message_iter_get_basic_type (iter, DBUS_TYPE_DOUBLE, &value);
03213 
03214   return value;
03215 }
03216 
03230 dbus_bool_t
03231 dbus_message_iter_init_array_iterator (DBusMessageIter *iter,
03232                                        DBusMessageIter *array_iter,
03233                                        int             *array_type)
03234 {
03235   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03236   DBusMessageRealIter *array_real = (DBusMessageRealIter *)array_iter;
03237   int type, pos, len_pos, len, array_type_pos;
03238   int _array_type;
03239 
03240   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
03241 
03242   pos = dbus_message_iter_get_data_start (real, &type);
03243   
03244   _dbus_assert (type == DBUS_TYPE_ARRAY);
03245 
03246   _array_type = iter_get_array_type (real, &array_type_pos);
03247   
03248   len_pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_uint32_t));
03249   len = _dbus_demarshal_uint32 (&real->message->body, real->message->byte_order,
03250                                 pos, &pos);
03251   
03252   array_real->parent_iter = real;
03253   array_real->message = real->message;
03254   array_real->changed_stamp = real->message->changed_stamp;
03255   
03256   array_real->type = DBUS_MESSAGE_ITER_TYPE_ARRAY;
03257   array_real->pos = pos;
03258   array_real->end = pos + len;
03259   
03260   array_real->container_start = pos;
03261   array_real->container_length_pos = len_pos;
03262   array_real->wrote_dict_key = 0;
03263   array_real->array_type_pos = array_type_pos;
03264   array_real->array_type_done = TRUE;
03265   
03266   if (array_type != NULL)
03267     *array_type = _array_type;
03268 
03269   return len > 0;
03270 }
03271 
03272 
03282 dbus_bool_t
03283 dbus_message_iter_init_dict_iterator (DBusMessageIter *iter,
03284                                       DBusMessageIter *dict_iter)
03285 {
03286   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03287   DBusMessageRealIter *dict_real = (DBusMessageRealIter *)dict_iter;
03288   int type, pos, len_pos, len;
03289 
03290   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
03291 
03292   pos = dbus_message_iter_get_data_start (real, &type);
03293   
03294   _dbus_assert (type == DBUS_TYPE_DICT);
03295 
03296   len_pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_uint32_t));
03297   len = _dbus_demarshal_uint32 (&real->message->body, real->message->byte_order,
03298                                 pos, &pos);
03299   
03300   dict_real->parent_iter = real;
03301   dict_real->message = real->message;
03302   dict_real->changed_stamp = real->message->changed_stamp;
03303   
03304   dict_real->type = DBUS_MESSAGE_ITER_TYPE_DICT;
03305   dict_real->pos = pos;
03306   dict_real->end = pos + len;
03307   
03308   dict_real->container_start = pos;
03309   dict_real->container_length_pos = len_pos;
03310   dict_real->wrote_dict_key = 0;
03311 
03312   return len > 0;
03313 }
03314 
03315 static dbus_bool_t
03316 _dbus_message_iter_get_basic_type_array  (DBusMessageIter *iter,
03317                                           char             type,
03318                                           void           **array,
03319                                           int             *array_len)
03320 {
03321   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03322   int item_type, pos;
03323 
03324   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
03325 
03326   pos = dbus_message_iter_get_data_start (real, &item_type);
03327   
03328   _dbus_assert (item_type == DBUS_TYPE_ARRAY);
03329 
03330   item_type = iter_get_array_type (real, NULL);
03331   
03332   _dbus_assert (type == item_type);
03333 
03334   return _dbus_demarshal_basic_type_array (&real->message->body,
03335                                            item_type, array, array_len,
03336                                            real->message->byte_order, &pos);
03337 }
03338 
03349 dbus_bool_t
03350 dbus_message_iter_get_byte_array (DBusMessageIter  *iter,
03351                                   unsigned char   **value,
03352                                   int              *len)
03353 {
03354   return _dbus_message_iter_get_basic_type_array (iter, DBUS_TYPE_BYTE,
03355                                                   (void **) value, len);
03356 }
03357 
03368 dbus_bool_t
03369 dbus_message_iter_get_boolean_array (DBusMessageIter   *iter,
03370                                      unsigned char    **value,
03371                                      int               *len)
03372 {
03373   return _dbus_message_iter_get_basic_type_array (iter, DBUS_TYPE_BOOLEAN,
03374                                                   (void **) value, len);
03375 }
03376 
03387 dbus_bool_t
03388 dbus_message_iter_get_int32_array  (DBusMessageIter *iter,
03389                                     dbus_int32_t   **value,
03390                                     int             *len)
03391 {
03392   return _dbus_message_iter_get_basic_type_array (iter, DBUS_TYPE_INT32,
03393                                                   (void **) value, len);
03394 }
03395 
03406 dbus_bool_t
03407 dbus_message_iter_get_uint32_array  (DBusMessageIter *iter,
03408                                      dbus_uint32_t  **value,
03409                                      int             *len)
03410 {
03411   return _dbus_message_iter_get_basic_type_array (iter, DBUS_TYPE_UINT32,
03412                                                   (void **) value, len);
03413 }
03414 
03415 #ifdef DBUS_HAVE_INT64
03416 
03429 dbus_bool_t
03430 dbus_message_iter_get_int64_array  (DBusMessageIter *iter,
03431                                     dbus_int64_t   **value,
03432                                     int             *len)
03433 {
03434   return _dbus_message_iter_get_basic_type_array (iter, DBUS_TYPE_INT64,
03435                                                   (void **) value, len);
03436 }
03437 
03450 dbus_bool_t
03451 dbus_message_iter_get_uint64_array  (DBusMessageIter *iter,
03452                                      dbus_uint64_t  **value,
03453                                      int             *len)
03454 {
03455   return _dbus_message_iter_get_basic_type_array (iter, DBUS_TYPE_UINT64,
03456                                                   (void **) value, len);
03457 }
03458 
03459 #endif /* DBUS_HAVE_INT64 */
03460 
03471 dbus_bool_t
03472 dbus_message_iter_get_double_array  (DBusMessageIter *iter,
03473                                      double         **value,
03474                                      int             *len)
03475 {
03476   return _dbus_message_iter_get_basic_type_array (iter, DBUS_TYPE_DOUBLE,
03477                                                   (void **) value, len);
03478 }
03479 
03495 dbus_bool_t
03496 dbus_message_iter_get_string_array (DBusMessageIter *iter,
03497                                     char          ***value,
03498                                     int             *len)
03499 {
03500   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03501   int type, pos;
03502 
03503   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
03504 
03505   pos = dbus_message_iter_get_data_start (real, &type);
03506   
03507   _dbus_assert (type == DBUS_TYPE_ARRAY);
03508 
03509   type = iter_get_array_type (real, NULL);
03510   _dbus_assert (type == DBUS_TYPE_STRING);
03511 
03512   if (!_dbus_demarshal_string_array (&real->message->body, real->message->byte_order,
03513                                      pos, NULL, value, len))
03514     return FALSE;
03515   else
03516     return TRUE;
03517 }
03518 
03534 dbus_bool_t
03535 dbus_message_iter_get_object_path_array (DBusMessageIter *iter,
03536                                          char          ***value,
03537                                          int             *len)
03538 {
03539   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03540   int type, pos;
03541 
03542   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
03543 
03544   pos = dbus_message_iter_get_data_start (real, &type);
03545   
03546   _dbus_assert (type == DBUS_TYPE_ARRAY);
03547 
03548   type = iter_get_array_type (real, NULL);
03549   _dbus_assert (type == DBUS_TYPE_OBJECT_PATH);
03550 
03551   if (!_dbus_demarshal_string_array (&real->message->body, real->message->byte_order,
03552                                      pos, NULL, value, len))
03553     return FALSE;
03554   else
03555     return TRUE;
03556 }
03557 
03567 char *
03568 dbus_message_iter_get_dict_key (DBusMessageIter   *iter)
03569 {
03570   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03571 
03572   _dbus_return_val_if_fail (dbus_message_iter_check (real), NULL);
03573 
03574   _dbus_assert (real->type == DBUS_MESSAGE_ITER_TYPE_DICT);
03575 
03576   return _dbus_demarshal_string (&real->message->body, real->message->byte_order,
03577                                  real->pos, NULL);
03578 }
03579 
03588 void
03589 dbus_message_append_iter_init (DBusMessage     *message,
03590                                DBusMessageIter *iter)
03591 {
03592   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03593 
03594   _dbus_return_if_fail (message != NULL);
03595   _dbus_return_if_fail (iter != NULL);
03596   
03597   real->message = message;
03598   real->parent_iter = NULL;
03599   real->changed_stamp = message->changed_stamp;
03600   
03601   real->type = DBUS_MESSAGE_ITER_TYPE_MESSAGE;
03602   real->end = _dbus_string_get_length (&real->message->body);
03603   real->pos = real->end;
03604   
03605   real->container_length_pos = 0;
03606   real->wrote_dict_key = 0;
03607 }
03608 
03609 #ifndef DBUS_DISABLE_CHECKS
03610 static dbus_bool_t
03611 dbus_message_iter_append_check (DBusMessageRealIter *iter)
03612 {
03613   if (iter == NULL)
03614     {
03615       _dbus_warn ("dbus iterator check failed: NULL iterator\n");
03616       return FALSE;
03617     }
03618   
03619   if (iter->message->locked)
03620     {
03621       _dbus_warn ("dbus iterator check failed: message is locked (has already been sent)\n");
03622       return FALSE;
03623     }
03624       
03625   if (iter->changed_stamp != iter->message->changed_stamp)
03626     {
03627       _dbus_warn ("dbus iterator check failed: invalid iterator, must re-initialize it after modifying the message");
03628       return FALSE;
03629     }
03630   
03631   if (iter->pos != iter->end)
03632     {
03633       _dbus_warn ("dbus iterator check failed: can only append at end of message");
03634       return FALSE;
03635     }
03636   
03637   if (iter->pos != _dbus_string_get_length (&iter->message->body))
03638     {
03639       _dbus_warn ("dbus iterator check failed: append pos not at end of message string");
03640       return FALSE;
03641     }
03642 
03643   return TRUE;
03644 }
03645 #endif /* DBUS_DISABLE_CHECKS */
03646 
03647 static dbus_bool_t
03648 dbus_message_iter_append_type (DBusMessageRealIter *iter,
03649                                int                  type)
03650 {
03651   const char *data;
03652 
03653   switch (iter->type)
03654     {
03655     case DBUS_MESSAGE_ITER_TYPE_MESSAGE:
03656       if (!_dbus_string_append_byte (&iter->message->body, type))
03657         return FALSE;
03658 
03659       if (!_dbus_message_append_byte_to_signature (iter->message, type))
03660         {
03661           _dbus_string_shorten (&iter->message->body, 1);
03662           return FALSE;
03663         }
03664       break;
03665       
03666     case DBUS_MESSAGE_ITER_TYPE_ARRAY:
03667       data = _dbus_string_get_const_data_len (&iter->message->body,
03668                                               iter->array_type_pos, 1);
03669       if (type != *data)
03670         {
03671           _dbus_warn ("Appended element of wrong type for array\n");
03672           return FALSE;
03673         }
03674       break;
03675       
03676     case DBUS_MESSAGE_ITER_TYPE_DICT:
03677       if (!iter->wrote_dict_key)
03678         {
03679           _dbus_warn ("Appending dict data before key name\n");
03680           return FALSE;
03681         }
03682       
03683       if (!_dbus_string_append_byte (&iter->message->body, type))
03684         return FALSE;
03685       
03686       break;
03687       
03688     default:
03689       _dbus_assert_not_reached ("Invalid iter type");
03690       break;
03691     }
03692   
03693   return TRUE;
03694 }
03695 
03696 static void
03697 dbus_message_iter_update_after_change (DBusMessageRealIter *iter)
03698 {
03699   iter->changed_stamp = iter->message->changed_stamp;
03700   
03701   /* Set new end of iter */
03702   iter->end = _dbus_string_get_length (&iter->message->body);
03703   iter->pos = iter->end;
03704 
03705   /* Set container length */
03706   if (iter->type == DBUS_MESSAGE_ITER_TYPE_DICT ||
03707       (iter->type == DBUS_MESSAGE_ITER_TYPE_ARRAY && iter->array_type_done))
03708     _dbus_marshal_set_uint32 (&iter->message->body,
03709                               iter->message->byte_order,
03710                               iter->container_length_pos,
03711                               iter->end - iter->container_start);
03712   
03713   if (iter->parent_iter)
03714     dbus_message_iter_update_after_change (iter->parent_iter);
03715 }
03716 
03717 static void
03718 dbus_message_iter_append_done (DBusMessageRealIter *iter)
03719 {
03720   iter->message->changed_stamp++;
03721   dbus_message_iter_update_after_change (iter);
03722   iter->wrote_dict_key = FALSE;
03723 }
03724 
03731 dbus_bool_t
03732 dbus_message_iter_append_nil (DBusMessageIter *iter)
03733 {
03734   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03735 
03736   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03737 
03738   if (!dbus_message_iter_append_type (real, DBUS_TYPE_NIL))
03739     return FALSE;
03740   
03741   dbus_message_iter_append_done (real);
03742   
03743   return TRUE;
03744 }
03745 
03746 static dbus_bool_t
03747 dbus_message_iter_append_basic (DBusMessageIter *iter,
03748                                 char             type,
03749                                 void            *value)
03750 {
03751   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03752 
03753   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03754 
03755   if (!dbus_message_iter_append_type (real, type))
03756     return FALSE;
03757 
03758   if (!_dbus_marshal_basic_type (&real->message->body,
03759                                  type, value,
03760                                  real->message->byte_order))
03761     {
03762       _dbus_string_set_length (&real->message->body, real->pos);
03763       return FALSE;
03764     }
03765 
03766   dbus_message_iter_append_done (real);
03767   
03768   return TRUE;  
03769 }
03770 
03778 dbus_bool_t
03779 dbus_message_iter_append_boolean (DBusMessageIter *iter,
03780                                   dbus_bool_t     value)
03781 {
03782   unsigned char val = (value != FALSE);
03783   return dbus_message_iter_append_basic (iter, DBUS_TYPE_BOOLEAN, &val);
03784 }
03785 
03793 dbus_bool_t
03794 dbus_message_iter_append_byte (DBusMessageIter *iter,
03795                                unsigned char    value)
03796 {
03797   return dbus_message_iter_append_basic (iter, DBUS_TYPE_BYTE, &value);
03798 }
03799 
03807 dbus_bool_t
03808 dbus_message_iter_append_int32   (DBusMessageIter *iter,
03809                                   dbus_int32_t  value)
03810 {
03811   return dbus_message_iter_append_basic (iter, DBUS_TYPE_INT32, &value);
03812 }
03813 
03821 dbus_bool_t
03822 dbus_message_iter_append_uint32 (DBusMessageIter *iter,
03823                                  dbus_uint32_t    value)
03824 {
03825   return dbus_message_iter_append_basic (iter, DBUS_TYPE_UINT32, &value);
03826 }
03827 
03828 #ifdef DBUS_HAVE_INT64
03829 
03839 dbus_bool_t
03840 dbus_message_iter_append_int64   (DBusMessageIter *iter,
03841                                   dbus_int64_t  value)
03842 {
03843   return dbus_message_iter_append_basic (iter, DBUS_TYPE_INT64, &value);
03844 }
03845 
03855 dbus_bool_t
03856 dbus_message_iter_append_uint64 (DBusMessageIter *iter,
03857                                  dbus_uint64_t    value)
03858 {
03859   return dbus_message_iter_append_basic (iter, DBUS_TYPE_UINT64, &value);
03860 }
03861 
03862 #endif /* DBUS_HAVE_INT64 */
03863 
03871 dbus_bool_t
03872 dbus_message_iter_append_double (DBusMessageIter *iter,
03873                                  double           value)
03874 {
03875   return dbus_message_iter_append_basic (iter, DBUS_TYPE_DOUBLE, &value);
03876 }
03877 
03887 dbus_bool_t
03888 dbus_message_iter_append_string (DBusMessageIter *iter,
03889                                  const char      *value)
03890 {
03891   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03892 
03893   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03894   
03895   if (!dbus_message_iter_append_type (real, DBUS_TYPE_STRING))
03896     return FALSE;
03897   
03898   if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, value))
03899     {
03900       _dbus_string_set_length (&real->message->body, real->pos);
03901       return FALSE;
03902     }
03903 
03904   dbus_message_iter_append_done (real);
03905   
03906   return TRUE;
03907 }
03908 
03918 dbus_bool_t
03919 dbus_message_iter_append_object_path (DBusMessageIter *iter,
03920                                       const char      *value)
03921 {
03922   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03923 
03924   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03925   
03926   if (!dbus_message_iter_append_type (real, DBUS_TYPE_OBJECT_PATH))
03927     return FALSE;
03928   
03929   if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, value))
03930     {
03931       _dbus_string_set_length (&real->message->body, real->pos);
03932       return FALSE;
03933     }
03934 
03935   dbus_message_iter_append_done (real);
03936   
03937   return TRUE;
03938 }
03939 
03952 dbus_bool_t
03953 dbus_message_iter_append_custom (DBusMessageIter      *iter,
03954                                  const char           *name,
03955                                  const unsigned char  *data,
03956                                  int                   len)
03957 {
03958   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03959 
03960   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03961 
03962   if (!dbus_message_iter_append_type (real, DBUS_TYPE_CUSTOM))
03963     return FALSE;
03964   
03965    if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, name))
03966     {
03967       _dbus_string_set_length (&real->message->body, real->pos);
03968       return FALSE;
03969     }
03970    
03971   if (!_dbus_marshal_byte_array (&real->message->body, real->message->byte_order, data, len))
03972     {
03973       _dbus_string_set_length (&real->message->body, real->pos);
03974       return FALSE;
03975     }
03976 
03977   dbus_message_iter_append_done (real);
03978   
03979   return TRUE;
03980 }
03981 
03982 
03991 dbus_bool_t
03992 dbus_message_iter_append_dict_key (DBusMessageIter *iter,
03993                                    const char      *value)
03994 {
03995   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03996 
03997   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03998   _dbus_assert (real->type == DBUS_MESSAGE_ITER_TYPE_DICT);
03999   
04000   if (real->wrote_dict_key)
04001     {
04002       _dbus_warn ("Appending multiple dict key names\n");
04003       return FALSE;
04004     }
04005   
04006   if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, value))
04007     {
04008       return FALSE;
04009     }
04010 
04011   dbus_message_iter_append_done (real);
04012   real->wrote_dict_key = TRUE;
04013   
04014   return TRUE;
04015 }
04016 
04017 static dbus_bool_t
04018 array_iter_type_mark_done (DBusMessageRealIter *iter)
04019 {
04020   int len_pos;
04021   
04022   if (iter->type == DBUS_MESSAGE_ITER_TYPE_ARRAY)
04023     array_iter_type_mark_done (iter->parent_iter);
04024   else
04025     return TRUE;
04026 
04027   len_pos = _DBUS_ALIGN_VALUE (_dbus_string_get_length (&iter->message->body),
04028                                sizeof (dbus_uint32_t));
04029 
04030   /* Empty length for now, backfill later */
04031   if (!_dbus_marshal_uint32 (&iter->message->body, iter->message->byte_order, 0))
04032     {
04033       _dbus_string_set_length (&iter->message->body, iter->pos);
04034       return FALSE;
04035     }
04036 
04037   iter->container_start = _dbus_string_get_length (&iter->message->body);
04038   iter->container_length_pos = len_pos;
04039   iter->array_type_done = TRUE;
04040 
04041   return TRUE;
04042 }
04043 
04044 static dbus_bool_t
04045 append_array_type (DBusMessageRealIter *real,
04046                    int                  element_type,
04047                    dbus_bool_t         *array_type_done,
04048                    int                 *array_type_pos)
04049 {
04050   int existing_element_type;
04051   
04052   if (!dbus_message_iter_append_type (real, DBUS_TYPE_ARRAY))
04053     return FALSE;
04054   
04055   if (real->type == DBUS_MESSAGE_ITER_TYPE_ARRAY &&
04056       real->array_type_done)
04057     {
04058       existing_element_type = iter_get_array_type (real, array_type_pos);
04059       if (existing_element_type != element_type)
04060         {
04061           _dbus_warn ("Appending array of %s, when expecting array of %s\n",
04062                       _dbus_type_to_string (element_type),
04063                       _dbus_type_to_string (existing_element_type));
04064           _dbus_string_set_length (&real->message->body, real->pos);
04065           return FALSE;
04066         }
04067       if (array_type_done != NULL)
04068           *array_type_done = TRUE;
04069     }
04070   else
04071     {
04072       if (array_type_pos != NULL)
04073         *array_type_pos = _dbus_string_get_length (&real->message->body);
04074 
04075 
04076       if (!_dbus_message_append_byte_to_signature (real->message, element_type))
04077         {
04078           _dbus_string_set_length (&real->message->body, real->pos);
04079           return FALSE;
04080         }
04081       
04082       /* Append element type */
04083       if (!_dbus_string_append_byte (&real->message->body, element_type))
04084         {
04085           _dbus_message_remove_byte_from_signature (real->message);
04086           _dbus_string_set_length (&real->message->body, real->pos);
04087           return FALSE;
04088         }
04089 
04090       if (array_type_done != NULL)
04091         *array_type_done = element_type != DBUS_TYPE_ARRAY;
04092       
04093       if (element_type != DBUS_TYPE_ARRAY &&
04094           !array_iter_type_mark_done (real))
04095         {
04096           _dbus_message_remove_byte_from_signature (real->message);
04097           return FALSE;
04098         }
04099     }
04100 
04101   return TRUE;
04102 }
04103 
04113 dbus_bool_t
04114 dbus_message_iter_append_array (DBusMessageIter      *iter,
04115                                 DBusMessageIter      *array_iter,
04116                                 int                   element_type)
04117 {
04118   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
04119   DBusMessageRealIter *array_real = (DBusMessageRealIter *)array_iter;
04120   int len_pos;
04121   int array_type_pos;
04122   dbus_bool_t array_type_done;
04123 
04124   if (element_type == DBUS_TYPE_NIL)
04125     {
04126       _dbus_warn ("Can't create NIL arrays\n");
04127       return FALSE;
04128     }
04129   
04130   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
04131 
04132   if (!append_array_type (real, element_type, &array_type_done, &array_type_pos))
04133     return FALSE;
04134 
04135   len_pos = _DBUS_ALIGN_VALUE (_dbus_string_get_length (&real->message->body), sizeof (dbus_uint32_t));
04136 
04137   if (array_type_done)
04138     {
04139       /* Empty length for now, backfill later */
04140       if (!_dbus_marshal_uint32 (&real->message->body, real->message->byte_order, 0))
04141         {
04142           _dbus_string_set_length (&real->message->body, real->pos);
04143           return FALSE;
04144         }
04145     }
04146   
04147   array_real->parent_iter = real;
04148   array_real->message = real->message;
04149   array_real->changed_stamp = real->message->changed_stamp;
04150   
04151   array_real->type = DBUS_MESSAGE_ITER_TYPE_ARRAY;
04152   array_real->pos = _dbus_string_get_length (&real->message->body);
04153   array_real->end = array_real->end;
04154   
04155   array_real->container_start = array_real->pos;
04156   array_real->container_length_pos = len_pos;
04157   array_real->wrote_dict_key = 0;
04158   array_real->array_type_done = array_type_done;
04159   array_real->array_type_pos = array_type_pos;
04160 
04161   dbus_message_iter_append_done (array_real);
04162   
04163   return TRUE;
04164 }
04165 
04174 dbus_bool_t
04175 dbus_message_iter_append_dict (DBusMessageIter      *iter,
04176                                DBusMessageIter      *dict_iter)
04177 {
04178   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
04179   DBusMessageRealIter *dict_real = (DBusMessageRealIter *)dict_iter;
04180   int len_pos;
04181 
04182   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
04183   
04184   if (!dbus_message_iter_append_type (real, DBUS_TYPE_DICT))
04185     return FALSE;  
04186   
04187   len_pos = _DBUS_ALIGN_VALUE (_dbus_string_get_length (&real->message->body), sizeof (dbus_uint32_t));
04188 
04189   /* Empty length for now, backfill later */
04190   if (!_dbus_marshal_uint32 (&real->message->body, real->message->byte_order, 0))
04191     {
04192       _dbus_string_set_length (&real->message->body, real->pos);
04193       return FALSE;
04194     }
04195   
04196   dict_real->parent_iter = real;
04197   dict_real->message = real->message;
04198   dict_real->changed_stamp = real->message->changed_stamp;
04199   
04200   dict_real->type = DBUS_MESSAGE_ITER_TYPE_DICT;
04201   dict_real->pos = _dbus_string_get_length (&real->message->body);
04202   dict_real->end = dict_real->end;
04203   
04204   dict_real->container_start = dict_real->pos;
04205   dict_real->container_length_pos = len_pos;
04206   dict_real->wrote_dict_key = 0;
04207 
04208   dbus_message_iter_append_done (dict_real);
04209   
04210   real->wrote_dict_key = FALSE;
04211   
04212   return TRUE;
04213 }
04214 
04215 static dbus_bool_t
04216 _dbus_message_iter_append_basic_array (DBusMessageIter *iter,
04217                                        char             type,
04218                                        const void      *value,
04219                                        int              len)
04220 {
04221   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
04222 
04223   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
04224 
04225   if (!append_array_type (real, type, NULL, NULL))
04226     return FALSE;
04227   
04228   if (!_dbus_marshal_basic_type_array (&real->message->body,
04229                                        type, value, len,
04230                                        real->message->byte_order))
04231     {
04232       _dbus_string_set_length (&real->message->body, real->pos);
04233       return FALSE;
04234     }
04235 
04236   dbus_message_iter_append_done (real);
04237   
04238   return TRUE;
04239 }
04240 
04241 
04255 dbus_bool_t
04256 dbus_message_append_args_valist (DBusMessage *message,
04257                                  int          first_arg_type,
04258                                  va_list      var_args)
04259 {
04260   int type, old_len;
04261   DBusMessageIter iter;
04262 
04263   _dbus_return_val_if_fail (message != NULL, FALSE);
04264   
04265   old_len = _dbus_string_get_length (&message->body);
04266   
04267   type = first_arg_type;
04268 
04269   dbus_message_append_iter_init (message, &iter);
04270   
04271   while (type != DBUS_TYPE_INVALID)
04272     {
04273       switch (type)
04274         {
04275         case DBUS_TYPE_NIL:
04276           if (!dbus_message_iter_append_nil (&iter))
04277             goto errorout;
04278           break;
04279         case DBUS_TYPE_BYTE:
04280           /* Read an int from varargs, because the original unsigned
04281            * char has been promoted to int. */
04282           if (!dbus_message_iter_append_byte (&iter, va_arg (var_args, int)))
04283             goto errorout;
04284           break;
04285         case DBUS_TYPE_BOOLEAN:
04286           if (!dbus_message_iter_append_boolean (&iter, va_arg (var_args, dbus_bool_t)))
04287             goto errorout;
04288           break;
04289         case DBUS_TYPE_INT32:
04290           /* FIXME this is probably wrong, because an int passed in probably gets
04291            * converted to plain "int" not necessarily 32-bit.
04292            */
04293           if (!dbus_message_iter_append_int32 (&iter, va_arg (var_args, dbus_int32_t)))
04294             goto errorout;
04295           break;
04296         case DBUS_TYPE_UINT32:
04297           /* FIXME this is probably wrong, because an int passed in probably gets
04298            * converted to plain "int" not necessarily 32-bit.
04299            */
04300           if (!dbus_message_iter_append_uint32 (&iter, va_arg (var_args, dbus_uint32_t)))
04301             goto errorout;          
04302           break;
04303 #ifdef DBUS_HAVE_INT64
04304         case DBUS_TYPE_INT64:
04305           if (!dbus_message_iter_append_int64 (&iter, va_arg (var_args, dbus_int64_t)))
04306             goto errorout;
04307           break;
04308         case DBUS_TYPE_UINT64:
04309           if (!dbus_message_iter_append_uint64 (&iter, va_arg (var_args, dbus_uint64_t)))
04310             goto errorout;          
04311           break;
04312 #endif /* DBUS_HAVE_INT64 */
04313         case DBUS_TYPE_DOUBLE:
04314           if (!dbus_message_iter_append_double (&iter, va_arg (var_args, double)))
04315             goto errorout;
04316           break;
04317         case DBUS_TYPE_STRING:
04318           if (!dbus_message_iter_append_string (&iter, va_arg (var_args, const char *)))
04319             goto errorout;
04320           break;
04321         case DBUS_TYPE_OBJECT_PATH:
04322           if (!dbus_message_iter_append_object_path (&iter, va_arg (var_args, const char*)))
04323             goto errorout;
04324           break;
04325         case DBUS_TYPE_CUSTOM:
04326           {
04327             const char *name;
04328             unsigned char *data;
04329             int len;
04330  
04331             name = va_arg (var_args, const char *);
04332             data = va_arg (var_args, unsigned char *);
04333             len = va_arg (var_args, int);
04334 
04335             if (!dbus_message_iter_append_custom (&iter, name, data, len))
04336               goto errorout;
04337             break;
04338           }
04339         case DBUS_TYPE_ARRAY:
04340           {
04341             void *data;
04342             int len, type;
04343  
04344             type = va_arg (var_args, int);
04345             data = va_arg (var_args, void *);
04346             len = va_arg (var_args, int);
04347 
04348             switch (type)
04349               {
04350               case DBUS_TYPE_BYTE:
04351               case DBUS_TYPE_BOOLEAN:
04352               case DBUS_TYPE_INT32:
04353               case DBUS_TYPE_UINT32:
04354 #ifdef DBUS_HAVE_INT64
04355               case DBUS_TYPE_INT64:
04356               case DBUS_TYPE_UINT64:
04357 #endif /* DBUS_HAVE_INT64 */
04358               case DBUS_TYPE_DOUBLE:
04359                 if (!_dbus_message_iter_append_basic_array (&iter, type, data, len))
04360                   goto errorout;
04361                 break;
04362               case DBUS_TYPE_STRING:
04363                 if (!dbus_message_iter_append_string_array (&iter, (const char **)data, len))
04364                   goto errorout;
04365                 break;
04366               case DBUS_TYPE_OBJECT_PATH:
04367                 if (!dbus_message_iter_append_object_path_array (&iter, (const char **)data, len))
04368                   goto errorout;
04369                 break;
04370               case DBUS_TYPE_NIL:
04371               case DBUS_TYPE_ARRAY:
04372               case DBUS_TYPE_CUSTOM:
04373               case DBUS_TYPE_DICT:
04374                 _dbus_warn ("dbus_message_append_args_valist doesn't support recursive arrays\n");
04375                 goto errorout;
04376               default:
04377                 _dbus_warn ("Unknown field type %d\n", type);
04378                 goto errorout;
04379               }
04380           }
04381           break;
04382           
04383         case DBUS_TYPE_DICT:
04384           _dbus_warn ("dbus_message_append_args_valist doesn't support dicts\n");
04385           goto errorout;
04386         default:
04387           _dbus_warn ("Unknown field type %d\n", type);
04388           goto errorout;
04389         }
04390 
04391       type = va_arg (var_args, int);
04392     }
04393 
04394   return TRUE;
04395 
04396  errorout:
04397   return FALSE;
04398 }
04399 
04408 dbus_bool_t
04409 dbus_message_iter_append_boolean_array (DBusMessageIter     *iter,
04410                                         unsigned const char *value,
04411                                         int                  len)
04412 {
04413   return _dbus_message_iter_append_basic_array (iter, DBUS_TYPE_BOOLEAN,
04414                                                 value, len);
04415 }
04416 
04425 dbus_bool_t
04426 dbus_message_iter_append_int32_array (DBusMessageIter    *iter,
04427                                       const dbus_int32_t *value,
04428                                       int                 len)
04429 {
04430   return _dbus_message_iter_append_basic_array (iter, DBUS_TYPE_INT32,
04431                                                 value, len);
04432 }
04433 
04442 dbus_bool_t
04443 dbus_message_iter_append_uint32_array (DBusMessageIter     *iter,
04444                                        const dbus_uint32_t *value,
04445                                        int                  len)
04446 {
04447   return _dbus_message_iter_append_basic_array (iter, DBUS_TYPE_UINT32,
04448                                                 value, len);
04449 }
04450 
04451 #ifdef DBUS_HAVE_INT64
04452 
04463 dbus_bool_t
04464 dbus_message_iter_append_int64_array (DBusMessageIter    *iter,
04465                                       const dbus_int64_t *value,
04466                                       int                 len)
04467 {
04468   return _dbus_message_iter_append_basic_array (iter, DBUS_TYPE_INT64,
04469                                                 value, len);
04470 }
04471 
04482 dbus_bool_t
04483 dbus_message_iter_append_uint64_array (DBusMessageIter     *iter,
04484                                        const dbus_uint64_t *value,
04485                                        int                  len)
04486 {
04487   return _dbus_message_iter_append_basic_array (iter, DBUS_TYPE_UINT64,
04488                                                 value, len);
04489 }
04490 #endif /* DBUS_HAVE_INT64 */
04491 
04500 dbus_bool_t
04501 dbus_message_iter_append_double_array (DBusMessageIter *iter,
04502                                        const double    *value,
04503                                        int              len)
04504 {
04505   return _dbus_message_iter_append_basic_array (iter, DBUS_TYPE_DOUBLE,
04506                                                 value, len);
04507 }
04508 
04517 dbus_bool_t
04518 dbus_message_iter_append_byte_array (DBusMessageIter     *iter,
04519                                      unsigned const char *value,
04520                                      int                  len)
04521 {
04522   return _dbus_message_iter_append_basic_array (iter, DBUS_TYPE_BYTE,
04523                                                 value, len);
04524 }
04525 
04534 dbus_bool_t
04535 dbus_message_iter_append_string_array (DBusMessageIter *iter,
04536                                        const char     **value,
04537                                        int              len)
04538 {
04539   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
04540 
04541   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
04542 
04543   if (!append_array_type (real, DBUS_TYPE_STRING, NULL, NULL))
04544     return FALSE;
04545   
04546   if (!_dbus_marshal_string_array (&real->message->body, real->message->byte_order, value, len))
04547     {
04548       _dbus_string_set_length (&real->message->body, real->pos);
04549       return FALSE;
04550     }
04551 
04552   dbus_message_iter_append_done (real);
04553   
04554   return TRUE;
04555 }
04556 
04565 dbus_bool_t
04566 dbus_message_iter_append_object_path_array (DBusMessageIter *iter,
04567                                             const char     **value,
04568                                             int              len)
04569 {
04570   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
04571 
04572   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
04573 
04574   if (!append_array_type (real, DBUS_TYPE_OBJECT_PATH, NULL, NULL))
04575     return FALSE;
04576   
04577   if (!_dbus_marshal_string_array (&real->message->body, real->message->byte_order, value, len))
04578     {
04579       _dbus_string_set_length (&real->message->body, real->pos);
04580       return FALSE;
04581     }
04582 
04583   dbus_message_iter_append_done (real);
04584   
04585   return TRUE;
04586 }
04587 
04595 dbus_bool_t
04596 dbus_message_set_sender (DBusMessage  *message,
04597                          const char   *sender)
04598 {
04599   _dbus_return_val_if_fail (message != NULL, FALSE);
04600   _dbus_return_val_if_fail (!message->locked, FALSE);
04601 
04602   return set_string_field (message,
04603                            DBUS_HEADER_FIELD_SENDER,
04604                            DBUS_TYPE_STRING,
04605                            sender);
04606 }
04607 
04618 void
04619 dbus_message_set_no_reply (DBusMessage *message,
04620                            dbus_bool_t  no_reply)
04621 {
04622   char *header;
04623 
04624   _dbus_return_if_fail (message != NULL);
04625   _dbus_return_if_fail (!message->locked);
04626   
04627   header = _dbus_string_get_data_len (&message->header, FLAGS_OFFSET, 1);
04628   
04629   if (no_reply)
04630     *header |= DBUS_HEADER_FLAG_NO_REPLY_EXPECTED;
04631   else
04632     *header &= ~DBUS_HEADER_FLAG_NO_REPLY_EXPECTED;    
04633 }
04634 
04642 dbus_bool_t
04643 dbus_message_get_no_reply (DBusMessage *message)
04644 {
04645   const char *header;
04646 
04647   _dbus_return_val_if_fail (message != NULL, FALSE);
04648   
04649   header = _dbus_string_get_const_data_len (&message->header, FLAGS_OFFSET, 1);
04650 
04651   return (*header & DBUS_HEADER_FLAG_NO_REPLY_EXPECTED) != 0;
04652 }
04653 
04654 
04664 void
04665 dbus_message_set_auto_activation (DBusMessage *message,
04666                                   dbus_bool_t  auto_activation)
04667 {
04668   char *header;
04669 
04670   _dbus_return_if_fail (message != NULL);
04671   _dbus_return_if_fail (!message->locked);
04672   
04673   header = _dbus_string_get_data_len (&message->header, FLAGS_OFFSET, 1);
04674   
04675   if (auto_activation)
04676     *header |= DBUS_HEADER_FLAG_AUTO_ACTIVATION;
04677   else
04678     *header &= ~DBUS_HEADER_FLAG_AUTO_ACTIVATION;
04679 }
04680 
04688 dbus_bool_t
04689 dbus_message_get_auto_activation (DBusMessage *message)
04690 {
04691   const char *header;
04692 
04693   _dbus_return_val_if_fail (message != NULL, FALSE);
04694   
04695   header = _dbus_string_get_const_data_len (&message->header, FLAGS_OFFSET, 1);
04696 
04697   return (*header & DBUS_HEADER_FLAG_AUTO_ACTIVATION) != 0;
04698 }
04699 
04707 const char*
04708 dbus_message_get_sender (DBusMessage *message)
04709 {
04710   _dbus_return_val_if_fail (message != NULL, NULL);
04711   
04712   return get_string_field (message, 
04713                            DBUS_HEADER_FIELD_SENDER,
04714                            NULL);
04715 }
04716 
04732 const char*
04733 dbus_message_get_signature (DBusMessage *message)
04734 {
04735   _dbus_return_val_if_fail (message != NULL, NULL);
04736 
04737   return get_string_field (message, 
04738                            DBUS_HEADER_FIELD_SIGNATURE,
04739                            NULL);
04740 }
04741 
04742 static dbus_bool_t
04743 _dbus_message_has_type_interface_member (DBusMessage *message,
04744                                          int          type,
04745                                          const char  *interface,
04746                                          const char  *method)
04747 {
04748   const char *n;
04749 
04750   _dbus_assert (message != NULL);
04751   _dbus_assert (interface != NULL);
04752   _dbus_assert (method != NULL);
04753 
04754   if (dbus_message_get_type (message) != type)
04755     return FALSE;
04756 
04757   /* Optimize by checking the short method name first
04758    * instead of the longer interface name
04759    */  
04760 
04761   n = dbus_message_get_member (message);
04762 
04763   if (n && strcmp (n, method) == 0)
04764     {
04765       n = dbus_message_get_interface (message);
04766       
04767       if (n && strcmp (n, interface) == 0)
04768         return TRUE;
04769     }
04770 
04771   return FALSE;
04772 }
04773 
04786 dbus_bool_t
04787 dbus_message_is_method_call (DBusMessage *message,
04788                              const char  *interface,
04789                              const char  *method)
04790 {
04791   _dbus_return_val_if_fail (message != NULL, FALSE);
04792   _dbus_return_val_if_fail (interface != NULL, FALSE);
04793   _dbus_return_val_if_fail (method != NULL, FALSE);
04794 
04795   return _dbus_message_has_type_interface_member (message,
04796                                                   DBUS_MESSAGE_TYPE_METHOD_CALL,
04797                                                   interface, method);
04798 }
04799 
04812 dbus_bool_t
04813 dbus_message_is_signal (DBusMessage *message,
04814                         const char  *interface,
04815                         const char  *signal_name)
04816 {
04817   _dbus_return_val_if_fail (message != NULL, FALSE);
04818   _dbus_return_val_if_fail (interface != NULL, FALSE);
04819   _dbus_return_val_if_fail (signal_name != NULL, FALSE);
04820 
04821   return _dbus_message_has_type_interface_member (message,
04822                                                   DBUS_MESSAGE_TYPE_SIGNAL,
04823                                                   interface, signal_name);
04824 }
04825 
04836 dbus_bool_t
04837 dbus_message_is_error (DBusMessage *message,
04838                        const char  *error_name)
04839 {
04840   const char *n;
04841   
04842   _dbus_return_val_if_fail (message != NULL, FALSE);
04843   _dbus_return_val_if_fail (error_name != NULL, FALSE);
04844   _dbus_return_val_if_fail (is_valid_error_name (error_name), FALSE);
04845   
04846   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
04847     return FALSE;
04848 
04849   n = dbus_message_get_error_name (message);
04850 
04851   if (n && strcmp (n, error_name) == 0)
04852     return TRUE;
04853   else
04854     return FALSE;
04855 }
04856 
04867 dbus_bool_t
04868 dbus_message_has_destination (DBusMessage  *message,
04869                               const char   *service)
04870 {
04871   const char *s;
04872 
04873   _dbus_return_val_if_fail (message != NULL, FALSE);
04874   _dbus_return_val_if_fail (service != NULL, FALSE);
04875   
04876   s = dbus_message_get_destination (message);
04877 
04878   if (s && strcmp (s, service) == 0)
04879     return TRUE;
04880   else
04881     return FALSE;
04882 }
04883 
04898 dbus_bool_t
04899 dbus_message_has_sender (DBusMessage  *message,
04900                          const char   *service)
04901 {
04902   const char *s;
04903 
04904   _dbus_return_val_if_fail (message != NULL, FALSE);
04905   _dbus_return_val_if_fail (service != NULL, FALSE);
04906   
04907   s = dbus_message_get_sender (message);
04908 
04909   if (s && strcmp (s, service) == 0)
04910     return TRUE;
04911   else
04912     return FALSE;
04913 }
04914 
04924 dbus_bool_t
04925 dbus_message_has_signature (DBusMessage   *message,
04926                             const char    *signature)
04927 {
04928   const char *s;
04929 
04930   _dbus_return_val_if_fail (message != NULL, FALSE);
04931   _dbus_return_val_if_fail (signature != NULL, FALSE);
04932   
04933   s = dbus_message_get_signature (message);
04934 
04935   if (s && strcmp (s, signature) == 0)
04936     return TRUE;
04937   else
04938     return FALSE;
04939 }
04940 
04958 dbus_bool_t
04959 dbus_set_error_from_message (DBusError   *error,
04960                              DBusMessage *message)
04961 {
04962   char *str;
04963 
04964   _dbus_return_val_if_fail (message != NULL, FALSE);
04965   _dbus_return_val_if_error_is_set (error, FALSE);
04966   
04967   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
04968     return FALSE;
04969 
04970   str = NULL;
04971   dbus_message_get_args (message, NULL,
04972                          DBUS_TYPE_STRING, &str,
04973                          DBUS_TYPE_INVALID);
04974 
04975   dbus_set_error (error, dbus_message_get_error_name (message),
04976                   str ? "%s" : NULL, str);
04977 
04978   dbus_free (str);
04979   
04980   return TRUE;
04981 }
04982 
05007 /* we definitely use signed ints for sizes, so don't exceed
05008  * _DBUS_INT_MAX; and add 16 for paranoia, since a message
05009  * over 128M is pretty nuts anyhow.
05010  */
05011 
05015 #define MAX_SANE_MESSAGE_SIZE (_DBUS_INT_MAX/16)
05016 
05021 struct DBusMessageLoader
05022 {
05023   int refcount;        
05025   DBusString data;     
05027   DBusList *messages;  
05029   long max_message_size; 
05031   unsigned int buffer_outstanding : 1; 
05033   unsigned int corrupted : 1; 
05034 };
05035 
05046 #define INITIAL_LOADER_DATA_LEN 32
05047 
05054 DBusMessageLoader*
05055 _dbus_message_loader_new (void)
05056 {
05057   DBusMessageLoader *loader;
05058 
05059   loader = dbus_new0 (DBusMessageLoader, 1);
05060   if (loader == NULL)
05061     return NULL;
05062   
05063   loader->refcount = 1;
05064 
05065   /* Try to cap message size at something that won't *totally* hose
05066    * the system if we have a couple of them.
05067    */
05068   loader->max_message_size = _DBUS_ONE_MEGABYTE * 32;
05069   
05070   if (!_dbus_string_init (&loader->data))
05071     {
05072       dbus_free (loader);
05073       return NULL;
05074     }
05075 
05076   /* preallocate the buffer for speed, ignore failure */
05077   _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN);
05078   _dbus_string_set_length (&loader->data, 0);
05079   
05080   return loader;
05081 }
05082 
05089 DBusMessageLoader *
05090 _dbus_message_loader_ref (DBusMessageLoader *loader)
05091 {
05092   loader->refcount += 1;
05093 
05094   return loader;
05095 }
05096 
05103 void
05104 _dbus_message_loader_unref (DBusMessageLoader *loader)
05105 {
05106   loader->refcount -= 1;
05107   if (loader->refcount == 0)
05108     {
05109       _dbus_list_foreach (&loader->messages,
05110                           (DBusForeachFunction) dbus_message_unref,
05111                           NULL);
05112       _dbus_list_clear (&loader->messages);
05113       _dbus_string_free (&loader->data);
05114       dbus_free (loader);
05115     }
05116 }
05117 
05136 void
05137 _dbus_message_loader_get_buffer (DBusMessageLoader  *loader,
05138                                  DBusString        **buffer)
05139 {
05140   _dbus_assert (!loader->buffer_outstanding);
05141 
05142   *buffer = &loader->data;
05143   
05144   loader->buffer_outstanding = TRUE;
05145 }
05146 
05151 #define DBUS_MINIMUM_HEADER_SIZE 16
05152 
05153 static dbus_bool_t
05154 decode_string_field (const DBusString   *data,
05155                      int                 field,
05156                      HeaderField        *header_field,
05157                      DBusString         *field_data,
05158                      int                 pos,
05159                      int                 type)
05160 {
05161   int string_data_pos;
05162 
05163   _dbus_assert (header_field != NULL);
05164   _dbus_assert (field_data != NULL);
05165   
05166   if (header_field->name_offset >= 0)
05167     {
05168       _dbus_verbose ("%s field provided twice\n",
05169                      _dbus_header_field_to_string (field));
05170       return FALSE;
05171     }
05172 
05173   if (type != DBUS_TYPE_STRING)
05174     {
05175       _dbus_verbose ("%s field has wrong type %s\n",
05176                      _dbus_header_field_to_string (field),
05177                      _dbus_type_to_string (type));
05178       return FALSE;
05179     }
05180 
05181   /* skip padding after typecode, skip string length;
05182    * we assume that the string arg has already been validated
05183    * for sanity and UTF-8
05184    */
05185   string_data_pos = _DBUS_ALIGN_VALUE (pos, 4) + 4;
05186   _dbus_assert (string_data_pos < _dbus_string_get_length (data));
05187   
05188   _dbus_string_init_const (field_data,
05189                            _dbus_string_get_const_data (data) + string_data_pos);
05190 
05191   header_field->name_offset  = pos - 2;
05192   header_field->value_offset = _DBUS_ALIGN_VALUE (pos, 4);
05193   
05194 #if 0
05195   _dbus_verbose ("Found field %s at offset %d\n",
05196                  _dbus_header_field_to_string (field),
05197                  header_field->value_offset);
05198 #endif
05199 
05200   return TRUE;
05201 }
05202 
05203 /* FIXME because the service/interface/member/error names are already
05204  * validated to be in the particular ASCII subset, UTF-8 validating
05205  * them could be skipped as a probably-interesting optimization.
05206  * The UTF-8 validation shows up in callgrind-type profiles but
05207  * not so much in sample/time-based profiles.
05208  */
05209 static dbus_bool_t
05210 decode_header_data (const DBusString   *data,
05211                     int                 header_len,
05212                     int                 byte_order,
05213                     int                 message_type,
05214                     HeaderField         fields[DBUS_HEADER_FIELD_LAST + 1],
05215                     int                *message_padding)
05216 {
05217   DBusString field_data;
05218   int pos, new_pos;
05219   int i;
05220   int field;
05221   int type;
05222   dbus_bool_t signature_required;
05223   
05224   if (header_len < 16)
05225     {
05226       _dbus_verbose ("Header length %d is too short\n", header_len);
05227       return FALSE;
05228     }
05229   
05230   i = 0;
05231   while (i <= DBUS_HEADER_FIELD_LAST)
05232     {
05233       fields[i].name_offset  = -1;
05234       fields[i].value_offset = -1;
05235       ++i;
05236     }
05237   
05238   pos = 16;
05239   while (pos < header_len)
05240     {
05241       field = _dbus_string_get_byte (data, pos);
05242       if (field == DBUS_HEADER_FIELD_INVALID)
05243         break; /* Must be padding */
05244       pos++;
05245 
05246       if (!_dbus_marshal_validate_type (data, pos, &type, &pos))
05247         {
05248           _dbus_verbose ("Failed to validate type of named header field pos = %d\n",
05249                          pos);
05250           return FALSE;
05251         }
05252       
05253       if (!_dbus_marshal_validate_arg (data, byte_order, 0, type, -1, pos, &new_pos))
05254         {
05255           _dbus_verbose ("Failed to validate argument to named header field pos = %d\n",
05256                          pos);
05257           return FALSE;
05258         }
05259 
05260       if (new_pos > header_len)
05261         {
05262           _dbus_verbose ("Named header field tries to extend beyond header length\n");
05263           return FALSE;
05264         }
05265       
05266       switch (field)
05267         {
05268         case DBUS_HEADER_FIELD_DESTINATION:
05269           if (!decode_string_field (data, field, &fields[field],
05270                                     &field_data, pos, type))
05271             return FALSE;
05272 
05273           if (!_dbus_string_validate_service (&field_data, 0,
05274                                               _dbus_string_get_length (&field_data)))
05275             {
05276               _dbus_verbose ("service field has invalid content \"%s\"\n",
05277                              _dbus_string_get_const_data (&field_data));
05278               return FALSE;
05279             }
05280           break;
05281 
05282         case DBUS_HEADER_FIELD_INTERFACE:
05283           if (!decode_string_field (data, field, &fields[field],
05284                                     &field_data, pos, type))
05285             return FALSE;
05286 
05287           if (!_dbus_string_validate_interface (&field_data, 0,
05288                                                 _dbus_string_get_length (&field_data)))
05289             {
05290               _dbus_verbose ("interface field has invalid content \"%s\"\n",
05291                              _dbus_string_get_const_data (&field_data));
05292               return FALSE;
05293             }
05294       
05295           if (_dbus_string_equal_c_str (&field_data,
05296                                         DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL))
05297             {
05298               _dbus_verbose ("Message is on the local interface\n");
05299               return FALSE;
05300             }
05301           break;
05302 
05303         case DBUS_HEADER_FIELD_MEMBER:
05304           if (!decode_string_field (data, field, &fields[field],
05305                                     &field_data, pos, type))
05306             return FALSE;
05307           
05308           if (!_dbus_string_validate_member (&field_data, 0,
05309                                              _dbus_string_get_length (&field_data)))
05310             {
05311               _dbus_verbose ("member field has invalid content \"%s\"\n",
05312                              _dbus_string_get_const_data (&field_data));
05313               return FALSE;
05314             }
05315           break;
05316 
05317         case DBUS_HEADER_FIELD_ERROR_NAME:
05318           if (!decode_string_field (data, field, &fields[field],
05319                                     &field_data, pos, type))
05320             return FALSE;
05321           
05322           if (!_dbus_string_validate_error_name (&field_data, 0,
05323                                                  _dbus_string_get_length (&field_data)))
05324             {
05325               _dbus_verbose ("error-name field has invalid content \"%s\"\n",
05326                              _dbus_string_get_const_data (&field_data));
05327               return FALSE;
05328             }
05329           break;
05330           
05331         case DBUS_HEADER_FIELD_SENDER:
05332           if (!decode_string_field (data, field, &fields[field],
05333                                     &field_data, pos, type))
05334             return FALSE;
05335           
05336           if (!_dbus_string_validate_service (&field_data, 0,
05337                                               _dbus_string_get_length (&field_data)))
05338             {
05339               _dbus_verbose ("sender-service field has invalid content \"%s\"\n",
05340                              _dbus_string_get_const_data (&field_data));
05341               return FALSE;
05342             }
05343           break;
05344 
05345         case DBUS_HEADER_FIELD_PATH:
05346 
05347           /* Path was already validated as part of standard
05348            * type validation, since there's an OBJECT_PATH
05349            * type.
05350            */
05351           
05352           if (fields[field].name_offset >= 0)
05353             {
05354               _dbus_verbose ("path field provided twice\n");
05355               return FALSE;
05356             }
05357           if (type != DBUS_TYPE_OBJECT_PATH)
05358             {
05359               _dbus_verbose ("path field has wrong type\n");
05360               return FALSE;
05361             }
05362 
05363           fields[field].name_offset  = pos - 2;
05364           fields[field].value_offset = _DBUS_ALIGN_VALUE (pos, 4);
05365 
05366           /* No forging signals from the local path */
05367           {
05368             const char *s;
05369             s = _dbus_string_get_const_data_len (data,
05370                                                  fields[field].value_offset,
05371                                                  _dbus_string_get_length (data) -
05372                                                  fields[field].value_offset);
05373             if (strcmp (s, DBUS_PATH_ORG_FREEDESKTOP_LOCAL) == 0)
05374               {
05375                 _dbus_verbose ("Message is on the local path\n");
05376                 return FALSE;
05377               }
05378           }
05379           
05380           _dbus_verbose ("Found path at offset %d\n",
05381                          fields[field].value_offset);
05382           break;
05383           
05384         case DBUS_HEADER_FIELD_REPLY_SERIAL:
05385           if (fields[field].name_offset >= 0)
05386             {
05387               _dbus_verbose ("reply field provided twice\n");
05388               return FALSE;
05389             }
05390 
05391           if (type != DBUS_TYPE_UINT32)
05392             {
05393               _dbus_verbose ("reply field has wrong type\n");
05394               return FALSE;
05395             }
05396           
05397           fields[field].name_offset  = pos - 2;
05398           fields[field].value_offset = _DBUS_ALIGN_VALUE (pos, 4);
05399 
05400           _dbus_verbose ("Found reply serial %u at offset %d\n",
05401                          _dbus_demarshal_uint32 (data,
05402                                                  byte_order,
05403                                                  fields[field].value_offset,
05404                                                  NULL),
05405                          fields[field].value_offset);
05406           break;
05407 
05408         case DBUS_HEADER_FIELD_SIGNATURE:
05409           if (!decode_string_field (data, field, &fields[field],
05410                                     &field_data, pos, type))
05411             return FALSE;
05412 
05413           if (!_dbus_string_validate_signature (&field_data, 0,
05414                                                 _dbus_string_get_length (&field_data)))
05415             {
05416               _dbus_verbose ("signature field has invalid content \"%s\"\n",
05417                              _dbus_string_get_const_data (&field_data));
05418               return FALSE;
05419             }
05420           break;
05421           
05422         default:
05423           _dbus_verbose ("Ignoring an unknown header field: %d at offset %d\n",
05424                          field, pos);
05425         }
05426       
05427       pos = new_pos;
05428     }
05429 
05430   if (pos < header_len)
05431     {
05432       /* Alignment padding, verify that it's nul */
05433       if ((header_len - pos) >= 8)
05434         {
05435           _dbus_verbose ("too much header alignment padding\n");
05436           return FALSE;
05437         }
05438 
05439       if (!_dbus_string_validate_nul (data,
05440                                       pos, (header_len - pos)))
05441         {
05442           _dbus_verbose ("header alignment padding is not nul\n");
05443           return FALSE;
05444         }
05445     }
05446 
05447   /* Depending on message type, enforce presence of certain fields. */
05448   signature_required = TRUE;
05449   
05450   switch (message_type)
05451     {
05452     case DBUS_MESSAGE_TYPE_SIGNAL:
05453     case DBUS_MESSAGE_TYPE_METHOD_CALL:
05454       if (fields[DBUS_HEADER_FIELD_PATH].value_offset < 0)
05455         {
05456           _dbus_verbose ("No path field provided\n");
05457           return FALSE;
05458         }
05459       /* FIXME make this optional, only for method calls */
05460       if (fields[DBUS_HEADER_FIELD_INTERFACE].value_offset < 0)
05461         {
05462           _dbus_verbose ("No interface field provided\n");
05463           return FALSE;
05464         }
05465       if (fields[DBUS_HEADER_FIELD_MEMBER].value_offset < 0)
05466         {
05467           _dbus_verbose ("No member field provided\n");
05468           return FALSE;
05469         }
05470       break;
05471     case DBUS_MESSAGE_TYPE_ERROR:
05472       if (fields[DBUS_HEADER_FIELD_ERROR_NAME].value_offset < 0)
05473         {
05474           _dbus_verbose ("No error-name field provided\n");
05475           return FALSE;
05476         }
05477       if (fields[DBUS_HEADER_FIELD_REPLY_SERIAL].value_offset < 0)
05478         {
05479           _dbus_verbose ("No reply serial field provided in error\n");
05480           return FALSE;
05481         }
05482       break;
05483     case DBUS_MESSAGE_TYPE_METHOD_RETURN:
05484       if (fields[DBUS_HEADER_FIELD_REPLY_SERIAL].value_offset < 0)
05485         {
05486           _dbus_verbose ("No reply serial field provided in method return\n");
05487           return FALSE;
05488         }
05489       break;
05490     default:
05491       /* An unknown type, spec requires us to ignore it */
05492       signature_required = FALSE;
05493       break;
05494     }
05495 
05496   /* FIXME allow omitting signature field for a message with no arguments? */
05497   if (signature_required)
05498     {
05499       if (fields[DBUS_HEADER_FIELD_SIGNATURE].value_offset < 0)
05500         {
05501           _dbus_verbose ("No signature field provided\n");
05502           return FALSE;
05503         }
05504     }
05505   
05506   if (message_padding)
05507     *message_padding = header_len - pos;  
05508   
05509   return TRUE;
05510 }
05511 
05522 void
05523 _dbus_message_loader_return_buffer (DBusMessageLoader  *loader,
05524                                     DBusString         *buffer,
05525                                     int                 bytes_read)
05526 {
05527   _dbus_assert (loader->buffer_outstanding);
05528   _dbus_assert (buffer == &loader->data);
05529 
05530   loader->buffer_outstanding = FALSE;
05531 }
05532 
05533 static dbus_bool_t
05534 load_one_message (DBusMessageLoader *loader,
05535                   int                byte_order,
05536                   int                message_type,
05537                   int                header_len,
05538                   int                body_len)
05539 {
05540   DBusMessage *message;
05541   HeaderField fields[DBUS_HEADER_FIELD_LAST + 1];
05542   int i;
05543   int next_arg;
05544   dbus_bool_t oom;
05545   int header_padding;
05546   
05547   message = NULL;
05548   oom = FALSE;
05549   
05550 #if 0
05551   _dbus_verbose_bytes_of_string (&loader->data, 0, header_len /* + body_len */);
05552 #endif    
05553 
05554   if (!decode_header_data (&loader->data,
05555                            header_len, byte_order,
05556                            message_type,
05557                            fields, &header_padding))
05558     {
05559       _dbus_verbose ("Header was invalid\n");
05560       loader->corrupted = TRUE;
05561       goto failed;
05562     }
05563           
05564   next_arg = header_len;
05565   while (next_arg < (header_len + body_len))
05566     {
05567       int type;
05568       int prev = next_arg;
05569 
05570       if (!_dbus_marshal_validate_type (&loader->data, next_arg,
05571                                         &type, &next_arg))
05572         {
05573           _dbus_verbose ("invalid typecode at offset %d\n", prev);
05574           loader->corrupted = TRUE;
05575           goto failed;
05576         }
05577       
05578       if (!_dbus_marshal_validate_arg (&loader->data,
05579                                        byte_order,
05580                                        0,
05581                                        type, -1,
05582                                        next_arg,
05583                                        &next_arg))
05584         {
05585           _dbus_verbose ("invalid type data at %d, next_arg\n", next_arg);
05586           loader->corrupted = TRUE;
05587           goto failed;
05588         }
05589 
05590       _dbus_assert (next_arg > prev);
05591     }
05592           
05593   if (next_arg > (header_len + body_len))
05594     {
05595       _dbus_verbose ("end of last arg at %d but message has len %d+%d=%d\n",
05596                      next_arg, header_len, body_len,
05597                      header_len + body_len);
05598       loader->corrupted = TRUE;
05599       goto failed;
05600     }
05601 
05602   message = dbus_message_new_empty_header ();
05603   if (message == NULL)
05604     {
05605       _dbus_verbose ("Failed to allocate empty message\n");
05606       oom = TRUE;
05607       goto failed;
05608     }
05609 
05610   message->byte_order = byte_order;
05611   message->header_padding = header_padding;
05612           
05613   /* Copy in the offsets we found */
05614   i = 0;
05615   while (i <= DBUS_HEADER_FIELD_LAST)
05616     {
05617       message->header_fields[i] = fields[i];
05618       ++i;
05619     }
05620           
05621   if (!_dbus_list_append (&loader->messages, message))
05622     {
05623       _dbus_verbose ("Failed to append new message to loader queue\n");
05624       oom = TRUE;
05625       goto failed;
05626     }
05627 
05628   _dbus_assert (_dbus_string_get_length (&message->header) == 0);
05629   _dbus_assert (_dbus_string_get_length (&message->body) == 0);
05630 
05631   _dbus_assert (_dbus_string_get_length (&loader->data) >=
05632                 (header_len + body_len));
05633           
05634   if (!_dbus_string_move_len (&loader->data, 0, header_len, &message->header, 0))
05635     {
05636       _dbus_verbose ("Failed to move header into new message\n");
05637       oom = TRUE;
05638       goto failed;
05639     }
05640           
05641   if (!_dbus_string_move_len (&loader->data, 0, body_len, &message->body, 0))
05642     {
05643       _dbus_verbose ("Failed to move body into new message\n");
05644       
05645       oom = TRUE;
05646       goto failed;
05647     }
05648 
05649   _dbus_assert (_dbus_string_get_length (&message->header) == header_len);
05650   _dbus_assert (_dbus_string_get_length (&message->body) == body_len);
05651 
05652   /* Fill in caches (we checked the types of these fields
05653    * earlier)
05654    */
05655   message->reply_serial = get_uint_field (message,
05656                                           DBUS_HEADER_FIELD_REPLY_SERIAL);
05657   
05658   message->client_serial = _dbus_demarshal_uint32 (&message->header,
05659                                                    message->byte_order,
05660                                                    CLIENT_SERIAL_OFFSET,
05661                                                    NULL);
05662   if (message->client_serial == 0 ||
05663       (message->header_fields[DBUS_HEADER_FIELD_REPLY_SERIAL].value_offset >= 0 && message->reply_serial == 0))
05664     {
05665       _dbus_verbose ("client_serial = %d reply_serial = %d, one of these no good\n",
05666                      message->client_serial,
05667                      message->reply_serial);
05668       
05669       loader->corrupted = TRUE;
05670       goto failed;
05671     }
05672   
05673   _dbus_verbose ("Loaded message %p\n", message);
05674 
05675   _dbus_assert (!oom);
05676   _dbus_assert (!loader->corrupted);
05677 
05678   return TRUE;
05679 
05680  failed:
05681   
05682   /* Clean up */
05683   
05684   if (message != NULL)
05685     {
05686       /* Put the data back so we can try again later if it was an OOM issue */
05687       if (_dbus_string_get_length (&message->body) > 0)
05688         {
05689           dbus_bool_t result;
05690           
05691           result = _dbus_string_copy_len (&message->body, 0, body_len,
05692                                           &loader->data, 0);
05693           
05694           _dbus_assert (result); /* because DBusString never reallocs smaller */
05695         }
05696       
05697       if (_dbus_string_get_length (&message->header) > 0)
05698         {
05699           dbus_bool_t result;
05700           
05701           result = _dbus_string_copy_len (&message->header, 0, header_len,
05702                                           &loader->data, 0);
05703           
05704           _dbus_assert (result); /* because DBusString never reallocs smaller */
05705         }
05706 
05707       /* does nothing if the message isn't in the list */
05708       _dbus_list_remove_last (&loader->messages, message);
05709 
05710       dbus_message_unref (message);
05711     }
05712 
05713   
05714   return !oom;
05715 }
05716 
05730 dbus_bool_t
05731 _dbus_message_loader_queue_messages (DBusMessageLoader *loader)
05732 {
05733   while (!loader->corrupted && _dbus_string_get_length (&loader->data) >= 16)
05734     {
05735       const char *header_data;
05736       int byte_order, message_type, header_len, body_len;
05737       dbus_uint32_t header_len_unsigned, body_len_unsigned;
05738       
05739       header_data = _dbus_string_get_const_data_len (&loader->data, 0, 16);
05740 
05741       _dbus_assert (_DBUS_ALIGN_ADDRESS (header_data, 4) == header_data);
05742 
05743       if (header_data[VERSION_OFFSET] != DBUS_MAJOR_PROTOCOL_VERSION)
05744         {
05745           _dbus_verbose ("Message has protocol version %d ours is %d\n",
05746                          (int) header_data[VERSION_OFFSET], DBUS_MAJOR_PROTOCOL_VERSION);
05747           loader->corrupted = TRUE;
05748           return TRUE;
05749         }
05750       
05751       byte_order = header_data[BYTE_ORDER_OFFSET];
05752 
05753       if (byte_order != DBUS_LITTLE_ENDIAN &&
05754           byte_order != DBUS_BIG_ENDIAN)
05755         {
05756           _dbus_verbose ("Message with bad byte order '%c' received\n",
05757                          byte_order);
05758           loader->corrupted = TRUE;
05759           return TRUE;
05760         }
05761 
05762       /* Unknown types are ignored, but INVALID is
05763        * disallowed
05764        */
05765       message_type = header_data[TYPE_OFFSET];
05766       if (message_type == DBUS_MESSAGE_TYPE_INVALID)
05767         {
05768           _dbus_verbose ("Message with bad type '%d' received\n",
05769                          message_type);
05770           loader->corrupted = TRUE;
05771           return TRUE;
05772         }      
05773       
05774       header_len_unsigned = _dbus_unpack_uint32 (byte_order, 
05775                                                  (const unsigned char *) header_data + 4);
05776       body_len_unsigned = _dbus_unpack_uint32 (byte_order, 
05777                                                (const unsigned char *) header_data + 8);
05778 
05779       if (header_len_unsigned < 16)
05780         {
05781           _dbus_verbose ("Message had broken too-small header length %u\n",
05782                          header_len_unsigned);
05783           loader->corrupted = TRUE;
05784           return TRUE;
05785         }
05786 
05787       if (header_len_unsigned > (unsigned) MAX_SANE_MESSAGE_SIZE ||
05788           body_len_unsigned > (unsigned) MAX_SANE_MESSAGE_SIZE)
05789         {
05790           _dbus_verbose ("Header or body length too large (%u %u)\n",
05791                          header_len_unsigned,
05792                          body_len_unsigned);
05793           loader->corrupted = TRUE;
05794           return TRUE;
05795         }
05796 
05797       /* Now that we know the values are in signed range, get
05798        * rid of stupid unsigned, just causes bugs
05799        */
05800       header_len = header_len_unsigned;
05801       body_len = body_len_unsigned;
05802 
05803       if (_DBUS_ALIGN_VALUE (header_len, 8) != header_len_unsigned)
05804         {
05805           
05806           _dbus_verbose ("header length %d is not aligned to 8 bytes\n",
05807                          header_len);
05808           loader->corrupted = TRUE;
05809           return TRUE;
05810         }
05811       
05812       if (header_len + body_len > loader->max_message_size)
05813         {
05814           _dbus_verbose ("Message claimed length header = %d body = %d exceeds max message length %ld\n",
05815                          header_len, body_len, loader->max_message_size);
05816           loader->corrupted = TRUE;
05817           return TRUE;
05818         }
05819 
05820       if (_dbus_string_get_length (&loader->data) >= (header_len + body_len))
05821         {
05822           if (!load_one_message (loader, byte_order, message_type,
05823                                  header_len, body_len))
05824             return FALSE;
05825         }
05826       else
05827         return TRUE;
05828     }
05829 
05830   return TRUE;
05831 }
05832 
05840 DBusMessage*
05841 _dbus_message_loader_peek_message (DBusMessageLoader *loader)
05842 {
05843   if (loader->messages)
05844     return loader->messages->data;
05845   else
05846     return NULL;
05847 }
05848 
05857 DBusMessage*
05858 _dbus_message_loader_pop_message (DBusMessageLoader *loader)
05859 {
05860   return _dbus_list_pop_first (&loader->messages);
05861 }
05862 
05871 DBusList*
05872 _dbus_message_loader_pop_message_link (DBusMessageLoader *loader)
05873 {
05874   return _dbus_list_pop_first_link (&loader->messages);
05875 }
05876 
05883 void
05884 _dbus_message_loader_putback_message_link (DBusMessageLoader  *loader,
05885                                            DBusList           *link)
05886 {
05887   _dbus_list_prepend_link (&loader->messages, link);
05888 }
05889 
05899 dbus_bool_t
05900 _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader)
05901 {
05902   return loader->corrupted;
05903 }
05904 
05911 void
05912 _dbus_message_loader_set_max_message_size (DBusMessageLoader  *loader,
05913                                            long                size)
05914 {
05915   if (size > MAX_SANE_MESSAGE_SIZE)
05916     {
05917       _dbus_verbose ("clamping requested max message size %ld to %d\n",
05918                      size, MAX_SANE_MESSAGE_SIZE);
05919       size = MAX_SANE_MESSAGE_SIZE;
05920     }
05921   loader->max_message_size = size;
05922 }
05923 
05930 long
05931 _dbus_message_loader_get_max_message_size (DBusMessageLoader  *loader)
05932 {
05933   return loader->max_message_size;
05934 }
05935 
05936 static DBusDataSlotAllocator slot_allocator;
05937 _DBUS_DEFINE_GLOBAL_LOCK (message_slots);
05938 
05953 dbus_bool_t
05954 dbus_message_allocate_data_slot (dbus_int32_t *slot_p)
05955 {
05956   return _dbus_data_slot_allocator_alloc (&slot_allocator,
05957                                           _DBUS_LOCK_NAME (message_slots),
05958                                           slot_p);
05959 }
05960 
05972 void
05973 dbus_message_free_data_slot (dbus_int32_t *slot_p)
05974 {
05975   _dbus_return_if_fail (*slot_p >= 0);
05976   
05977   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
05978 }
05979 
05993 dbus_bool_t
05994 dbus_message_set_data (DBusMessage     *message,
05995                        dbus_int32_t     slot,
05996                        void            *data,
05997                        DBusFreeFunction free_data_func)
05998 {
05999   DBusFreeFunction old_free_func;
06000   void *old_data;
06001   dbus_bool_t retval;
06002 
06003   _dbus_return_val_if_fail (message != NULL, FALSE);
06004   _dbus_return_val_if_fail (slot >= 0, FALSE);
06005 
06006   retval = _dbus_data_slot_list_set (&slot_allocator,
06007                                      &message->slot_list,
06008                                      slot, data, free_data_func,
06009                                      &old_free_func, &old_data);
06010 
06011   if (retval)
06012     {
06013       /* Do the actual free outside the message lock */
06014       if (old_free_func)
06015         (* old_free_func) (old_data);
06016     }
06017 
06018   return retval;
06019 }
06020 
06029 void*
06030 dbus_message_get_data (DBusMessage   *message,
06031                        dbus_int32_t   slot)
06032 {
06033   void *res;
06034 
06035   _dbus_return_val_if_fail (message != NULL, NULL);
06036   
06037   res = _dbus_data_slot_list_get (&slot_allocator,
06038                                   &message->slot_list,
06039                                   slot);
06040 
06041   return res;
06042 }
06043 
06057 int
06058 dbus_message_type_from_string (const char *type_str)
06059 {
06060   if (strcmp (type_str, "method_call") == 0)
06061     return DBUS_MESSAGE_TYPE_METHOD_CALL;
06062   if (strcmp (type_str, "method_return") == 0)
06063     return DBUS_MESSAGE_TYPE_METHOD_RETURN;
06064   else if (strcmp (type_str, "signal") == 0)
06065     return DBUS_MESSAGE_TYPE_SIGNAL;
06066   else if (strcmp (type_str, "error") == 0)
06067     return DBUS_MESSAGE_TYPE_ERROR;
06068   else
06069     return DBUS_MESSAGE_TYPE_INVALID;
06070 }
06071 
06085 const char *
06086 dbus_message_type_to_string (int type)
06087 {
06088   switch (type)
06089     {
06090     case DBUS_MESSAGE_TYPE_METHOD_CALL:
06091       return "method_call";
06092     case DBUS_MESSAGE_TYPE_METHOD_RETURN:
06093       return "method_return";
06094     case DBUS_MESSAGE_TYPE_SIGNAL:
06095       return "signal";
06096     case DBUS_MESSAGE_TYPE_ERROR:
06097       return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return "error";
06098     default:
0609="keywordflow">return