00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <config.h>
00024
00025 #ifdef DBUS_BUILD_TESTS
00026
00027 #include "dbus-message-builder.h"
00028 #include "dbus-hash.h"
00029 #include "dbus-internals.h"
00030 #include "dbus-marshal.h"
00031
00046 typedef struct
00047 {
00048 DBusString name;
00049 int start;
00050 int length;
00051 int offset;
00052 int endian;
00053 } SavedLength;
00054
00055 static void
00056 free_saved_length (void *data)
00057 {
00058 SavedLength *sl = data;
00059
00060 if (sl == NULL)
00061 return;
00062
00063 _dbus_string_free (&sl->name);
00064 dbus_free (sl);
00065 }
00066
00067 static SavedLength*
00068 ensure_saved_length (DBusHashTable *hash,
00069 const DBusString *name)
00070 {
00071 SavedLength *sl;
00072 const char *s;
00073
00074 s = _dbus_string_get_const_data (name);
00075
00076 sl = _dbus_hash_table_lookup_string (hash, s);
00077 if (sl != NULL)
00078 return sl;
00079
00080 sl = dbus_new0 (SavedLength, 1);
00081
00082 if (!_dbus_string_init (&sl->name))
00083 {
00084 dbus_free (sl);
00085 return NULL;
00086 }
00087
00088 if (!_dbus_string_copy (name, 0, &sl->name, 0))
00089 goto failed;
00090
00091 s = _dbus_string_get_const_data (&sl->name);
00092
00093 if (!_dbus_hash_table_insert_string (hash, (char*)s, sl))
00094 goto failed;
00095
00096 sl->start = -1;
00097 sl->length = -1;
00098 sl->offset = -1;
00099 sl->endian = -1;
00100
00101 return sl;
00102
00103 failed:
00104 free_saved_length (sl);
00105 return NULL;
00106 }
00107
00108 static dbus_bool_t
00109 save_start (DBusHashTable *hash,
00110 const DBusString *name,
00111 int start)
00112 {
00113 SavedLength *sl;
00114
00115 sl = ensure_saved_length (hash, name);
00116
00117 if (sl == NULL)
00118 return FALSE;
00119 else if (sl->start >= 0)
00120 {
00121 _dbus_warn ("Same START_LENGTH given twice\n");
00122 return FALSE;
00123 }
00124 else
00125 sl->start = start;
00126
00127 return TRUE;
00128 }
00129
00130 static dbus_bool_t
00131 save_length (DBusHashTable *hash,
00132 const DBusString *name,
00133 int length)
00134 {
00135 SavedLength *sl;
00136
00137 sl = ensure_saved_length (hash, name);
00138
00139 if (sl == NULL)
00140 return FALSE;
00141 else if (sl->length >= 0)
00142 {
00143 _dbus_warn ("Same END_LENGTH given twice\n");
00144 return FALSE;
00145 }
00146 else
00147 sl->length = length;
00148
00149 return TRUE;
00150 }
00151
00152 static dbus_bool_t
00153 save_offset (DBusHashTable *hash,
00154 const DBusString *name,
00155 int offset,
00156 int endian)
00157 {
00158 SavedLength *sl;
00159
00160 sl = ensure_saved_length (hash, name);
00161
00162 if (sl == NULL)
00163 return FALSE;
00164 else if (sl->offset >= 0)
00165 {
00166 _dbus_warn ("Same LENGTH given twice\n");
00167 return FALSE;
00168 }
00169 else
00170 {
00171 sl->offset = offset;
00172 sl->endian = endian;
00173 }
00174
00175 return TRUE;
00176 }
00177
00179 #define SAVE_FOR_UNALIGN(str, boundary) \
00180 int align_pad_start = _dbus_string_get_length (str); \
00181 int align_pad_end = _DBUS_ALIGN_VALUE (align_pad_start, (boundary))
00182
00184 #define PERFORM_UNALIGN(str) \
00185 if (unalign) \
00186 { \
00187 _dbus_string_delete ((str), align_pad_start, \
00188 align_pad_end - align_pad_start); \
00189 unalign = FALSE; \
00190 }
00191
00192
00193 static dbus_bool_t
00194 append_quoted_string (DBusString *dest,
00195 const DBusString *quoted,
00196 int start_pos,
00197 int *new_pos)
00198 {
00199 dbus_bool_t in_quotes = FALSE;
00200 int i;
00201
00202
00203
00204
00205
00206 i = start_pos;
00207 while (i < _dbus_string_get_length (quoted))
00208 {
00209 unsigned char b;
00210
00211 b = _dbus_string_get_byte (quoted, i);
00212
00213 if (in_quotes)
00214 {
00215 if (b == '\'')
00216 break;
00217 else
00218 {
00219 if (!_dbus_string_append_byte (dest, b))
00220 return FALSE;
00221 }
00222 }
00223 else
00224 {
00225 if (b == '\'')
00226 in_quotes = TRUE;
00227 else if (b == ' ' || b == '\n' || b == '\t')
00228 break;
00229 else
00230 {
00231 if (!_dbus_string_append_byte (dest, b))
00232 return FALSE;
00233 }
00234 }
00235
00236 ++i;
00237 }
00238
00239 if (new_pos)
00240 *new_pos = i;
00241
00242 if (!_dbus_string_append_byte (dest, '\0'))
00243 return FALSE;
00244 return TRUE;
00245 }
00246
00247 static dbus_bool_t
00248 append_saved_length (DBusString *dest,
00249 DBusHashTable *length_hash,
00250 const DBusString *name,
00251 int offset,
00252 int endian)
00253 {
00254 if (!save_offset (length_hash, name,
00255 offset, endian))
00256 {
00257 _dbus_warn ("failed to save offset to LENGTH\n");
00258 return FALSE;
00259 }
00260
00261 if (!_dbus_marshal_uint32 (dest, endian,
00262 -1))
00263 {
00264 _dbus_warn ("failed to append a length\n");
00265 return FALSE;
00266 }
00267
00268 return TRUE;
00269 }
00270
00271 static int
00272 message_type_from_string (const DBusString *str,
00273 int start)
00274 {
00275 const char *s;
00276
00277 s = _dbus_string_get_const_data_len (str, start,
00278 _dbus_string_get_length (str) - start);
00279
00280 if (strncmp (s, "method_call", strlen ("method_call")) == 0)
00281 return DBUS_MESSAGE_TYPE_METHOD_CALL;
00282 else if (strncmp (s, "method_return", strlen ("method_return")) == 0)
00283 return DBUS_MESSAGE_TYPE_METHOD_RETURN;
00284 else if (strncmp (s, "signal", strlen ("signal")) == 0)
00285 return DBUS_MESSAGE_TYPE_SIGNAL;
00286 else if (strncmp (s, "error", strlen ("error")) == 0)
00287 return DBUS_MESSAGE_TYPE_ERROR;
00288 else if (strncmp (s, "invalid", strlen ("invalid")) == 0)
00289 return DBUS_MESSAGE_TYPE_INVALID;
00290 else
00291 return -1;
00292 }
00293
00294 static dbus_bool_t
00295 append_string_field (DBusString *dest,
00296 int endian,
00297 int field,
00298 int type,
00299 const char *value)
00300 {
00301 int len;
00302
00303 if (!_dbus_string_append_byte (dest, field))
00304 {
00305 _dbus_warn ("couldn't append field name byte\n");
00306 return FALSE;
00307 }
00308
00309 if (!_dbus_string_append_byte (dest, type))
00310 {
00311 _dbus_warn ("could not append typecode byte\n");
00312 return FALSE;
00313 }
00314
00315 len = strlen (value);
00316
00317 if (!_dbus_marshal_uint32 (dest, endian, len))
00318 {
00319 _dbus_warn ("couldn't append string length\n");
00320 return FALSE;
00321 }
00322
00323 if (!_dbus_string_append (dest, value))
00324 {
00325 _dbus_warn ("couldn't append field value\n");
00326 return FALSE;
00327 }
00328
00329 if (!_dbus_string_append_byte (dest, 0))
00330 {
00331 _dbus_warn ("couldn't append string nul term\n");
00332 return FALSE;
00333 }
00334
00335 return TRUE;
00336 }
00337
00338 static dbus_bool_t
00339 parse_basic_type (DBusString *src, char type,
00340 DBusString *dest, dbus_bool_t *unalign,
00341 int endian)
00342 {
00343 int align;
00344 int align_pad_start, align_pad_end;
00345 unsigned char data[16];
00346
00347 switch (type)
00348 {
00349 case DBUS_TYPE_BYTE:
00350 case DBUS_TYPE_BOOLEAN:
00351 align = 1;
00352 break;
00353 case DBUS_TYPE_UINT32:
00354 case DBUS_TYPE_INT32:
00355 align = 4;
00356 break;
00357 case DBUS_TYPE_DOUBLE:
00358 align = 8;
00359 break;
00360 default:
00361 _dbus_assert_not_reached ("not a basic type");
00362 break;
00363 }
00364
00365 align_pad_start = _dbus_string_get_length (dest);
00366 align_pad_end = _DBUS_ALIGN_VALUE (align_pad_start, align);
00367
00368 _dbus_string_delete_first_word (src);
00369
00370 if (!_dbus_string_parse_basic_type (src, type, 0, data, NULL))
00371 {
00372 _dbus_verbose ("failed to parse type '%c'", type);
00373 return FALSE;
00374 }
00375
00376 if (!_dbus_marshal_basic_type (dest, type, data, endian))
00377 {
00378 _dbus_verbose ("failed to marshal type '%c'", type);
00379 return FALSE;
00380 }
00381
00382 if (*unalign)
00383 {
00384 _dbus_string_delete (dest, align_pad_start,
00385 align_pad_end - align_pad_start);
00386 *unalign = FALSE;
00387 }
00388
00389 return TRUE;
00390 }
00391
00392 static dbus_bool_t
00393 parse_basic_array (DBusString *src, char type,
00394 DBusString *dest, dbus_bool_t *unalign,
00395 int endian)
00396 {
00397 int array_align, elem_size;
00398 int i, len, allocated;
00399 unsigned char *values, b;
00400 int values_offset;
00401 int align_pad_start, align_pad_end;
00402 dbus_bool_t retval = FALSE;
00403
00404 array_align = 4;
00405 switch (type)
00406 {
00407 case DBUS_TYPE_BYTE:
00408 case DBUS_TYPE_BOOLEAN:
00409 elem_size = 1;
00410 break;
00411 case DBUS_TYPE_UINT32:
00412 case DBUS_TYPE_INT32:
00413 elem_size = 4;
00414 break;
00415 case DBUS_TYPE_DOUBLE:
00416 array_align = 8;
00417 elem_size = 8;
00418 break;
00419 default:
00420 _dbus_assert_not_reached ("not a basic type");
00421 break;
00422 }
00423
00424 align_pad_start = _dbus_string_get_length (dest);
00425 align_pad_end = _DBUS_ALIGN_VALUE (align_pad_start, array_align);
00426
00427 len = 0;
00428 allocated = 2;
00429 values = NULL;
00430 values_offset = 0;
00431
00432 _dbus_string_delete_first_word (src);
00433 _dbus_string_skip_blank (src, 0, &i);
00434 b = _dbus_string_get_byte (src, i++);
00435
00436 if (b != '{')
00437 goto failed;
00438
00439 while (i < _dbus_string_get_length (src))
00440 {
00441 _dbus_string_skip_blank (src, i, &i);
00442
00443 if (!values || len == allocated - 1)
00444 {
00445 allocated *= 2;
00446 values = dbus_realloc (values, allocated * elem_size);
00447 if (!values)
00448 {
00449 _dbus_warn ("could not allocate memory for '%c' ARRAY\n", type);
00450 goto failed;
00451 }
00452 }
00453
00454 if (!_dbus_string_parse_basic_type (src, type, i, values + values_offset, &i))
00455 {
00456 _dbus_warn ("could not parse integer element %d of '%c' ARRAY\n", len, type);
00457 goto failed;
00458 }
00459
00460 values_offset += elem_size;
00461 len++;
00462
00463 _dbus_string_skip_blank (src, i, &i);
00464
00465 b = _dbus_string_get_byte (src, i++);
00466
00467 if (b == '}')
00468 break;
00469 else if (b != ',')
00470 goto failed;
00471 }
00472
00473 if (!_dbus_marshal_basic_type_array (dest, type, values, len, endian))
00474 {
00475 _dbus_warn ("failed to append '%c' ARRAY\n", type);
00476 goto failed;
00477 }
00478
00479 if (*unalign)
00480 {
00481 _dbus_string_delete (dest, align_pad_start,
00482 align_pad_end - align_pad_start);
00483 *unalign = FALSE;
00484 }
00485
00486 retval = TRUE;
00487
00488 failed:
00489 dbus_free (values);
00490 return retval;
00491 }
00492
00493 static char
00494 lookup_basic_type (const DBusString *str, dbus_bool_t *is_array)
00495 {
00496 int i;
00497 char type = DBUS_TYPE_INVALID;
00498 static struct {
00499 const char *name;
00500 char type;
00501 } name_to_type[] = {
00502 { "BYTE", DBUS_TYPE_BYTE },
00503 { "BOOLEAN", DBUS_TYPE_BOOLEAN },
00504 { "INT32", DBUS_TYPE_INT32 },
00505 { "UINT32", DBUS_TYPE_UINT32 },
00506 { "DOUBLE", DBUS_TYPE_DOUBLE }
00507 };
00508
00509 for (i = 0; i < _DBUS_N_ELEMENTS(name_to_type); i++)
00510 {
00511 const char *name = name_to_type[i].name;
00512 if (_dbus_string_starts_with_c_str (str, name))
00513 {
00514 int offset = strlen (name);
00515 type = name_to_type[i].type;
00516 if (is_array)
00517 *is_array = _dbus_string_find (str, offset, "_ARRAY", NULL);
00518 break;
00519 }
00520 }
00521
00522 return type;
00523 }
00524
00576 dbus_bool_t
00577 _dbus_message_data_load (DBusString *dest,
00578 const DBusString *filename)
00579 {
00580 DBusString file;
00581 DBusError error;
00582 DBusString line;
00583 dbus_bool_t retval;
00584 int line_no;
00585 dbus_bool_t unalign;
00586 DBusHashTable *length_hash;
00587 int endian;
00588 DBusHashIter iter;
00589 char type;
00590 dbus_bool_t is_array;
00591
00592 retval = FALSE;
00593 length_hash = NULL;
00594
00595 if (!_dbus_string_init (&file))
00596 return FALSE;
00597
00598 if (!_dbus_string_init (&line))
00599 {
00600 _dbus_string_free (&file);
00601 return FALSE;
00602 }
00603
00604 _dbus_verbose ("Loading %s\n", _dbus_string_get_const_data (filename));
00605
00606 dbus_error_init (&error);
00607 if (!_dbus_file_get_contents (&file, filename, &error))
00608 {
00609 _dbus_warn ("Getting contents of %s failed: %s\n",
00610 _dbus_string_get_const_data (filename), error.message);
00611 dbus_error_free (&error);
00612 goto out;
00613 }
00614
00615 length_hash = _dbus_hash_table_new (DBUS_HASH_STRING,
00616 NULL,
00617 free_saved_length);
00618 if (length_hash == NULL)
00619 goto out;
00620
00621 endian = DBUS_COMPILER_BYTE_ORDER;
00622 unalign = FALSE;
00623 line_no = 0;
00624 next_iteration:
00625 while (_dbus_string_pop_line (&file, &line))
00626 {
00627 dbus_bool_t just_set_unalign;
00628
00629 just_set_unalign = FALSE;
00630 line_no += 1;
00631
00632 _dbus_string_delete_leading_blanks (&line);
00633
00634 if (_dbus_string_get_length (&line) == 0)
00635 {
00636
00637 goto next_iteration;
00638 }
00639 else if (_dbus_string_starts_with_c_str (&line,
00640 "#"))
00641 {
00642
00643 goto next_iteration;
00644 }
00645 else if (_dbus_string_starts_with_c_str (&line,
00646 "VALID_HEADER"))
00647 {
00648 int i;
00649 DBusString name;
00650 int message_type;
00651
00652 if (_dbus_string_get_length (&line) < (int) strlen ("VALID_HEADER "))
00653 {
00654 _dbus_warn ("no args to VALID_HEADER\n");
00655 goto parse_failed;
00656 }
00657
00658 if (!_dbus_string_append_byte (dest, endian))
00659 {
00660 _dbus_warn ("could not append endianness\n");
00661 goto parse_failed;
00662 }
00663
00664 message_type = message_type_from_string (&line,
00665 strlen ("VALID_HEADER "));
00666 if (message_type < 0)
00667 {
00668 _dbus_warn ("VALID_HEADER not followed by space then known message type\n");
00669 goto parse_failed;
00670 }
00671
00672 if (!_dbus_string_append_byte (dest, message_type))
00673 {
00674 _dbus_warn ("could not append message type\n");
00675 goto parse_failed;
00676 }
00677
00678 i = 0;
00679 while (i < 2)
00680 {
00681 if (!_dbus_string_append_byte (dest, '\0'))
00682 {
00683 _dbus_warn ("could not append nul pad\n");
00684 goto parse_failed;
00685 }
00686 ++i;
00687 }
00688
00689 _dbus_string_init_const (&name, "Header");
00690 if (!append_saved_length (dest, length_hash,
00691 &name, _dbus_string_get_length (dest),
00692 endian))
00693 goto parse_failed;
00694
00695 _dbus_string_init_const (&name, "Body");
00696 if (!append_saved_length (dest, length_hash,
00697 &name, _dbus_string_get_length (dest),
00698 endian))
00699 goto parse_failed;
00700
00701
00702 if (!_dbus_marshal_uint32 (dest, endian, 1))
00703 {
00704 _dbus_warn ("couldn't append client serial\n");
00705 goto parse_failed;
00706 }
00707 }
00708 else if (_dbus_string_starts_with_c_str (&line,
00709 "REQUIRED_FIELDS"))
00710 {
00711 if (!append_string_field (dest, endian,
00712 DBUS_HEADER_FIELD_INTERFACE,
00713 DBUS_TYPE_STRING,
00714 "org.freedesktop.BlahBlahInterface"))
00715 goto parse_failed;
00716 if (!append_string_field (dest, endian,
00717 DBUS_HEADER_FIELD_MEMBER,
00718 DBUS_TYPE_STRING,
00719 "BlahBlahMethod"))
00720 goto parse_failed;
00721 if (!append_string_field (dest, endian,
00722 DBUS_HEADER_FIELD_PATH,
00723 DBUS_TYPE_OBJECT_PATH,
00724 "/blah/blah/path"))
00725 goto parse_failed;
00726
00727
00728
00729
00730 if (!append_string_field (dest, endian,
00731 DBUS_HEADER_FIELD_SIGNATURE,
00732 DBUS_TYPE_STRING,
00733 "iii"))
00734 goto parse_failed;
00735 }
00736 else if (_dbus_string_starts_with_c_str (&line,
00737 "BIG_ENDIAN"))
00738 {
00739 endian = DBUS_BIG_ENDIAN;
00740 }
00741 else if (_dbus_string_starts_with_c_str (&line,
00742 "LITTLE_ENDIAN"))
00743 {
00744 endian = DBUS_LITTLE_ENDIAN;
00745 }
00746 else if (_dbus_string_starts_with_c_str (&line,
00747 "OPPOSITE_ENDIAN"))
00748 {
00749 if (endian == DBUS_BIG_ENDIAN)
00750 endian = DBUS_LITTLE_ENDIAN;
00751 else
00752 endian = DBUS_BIG_ENDIAN;
00753 }
00754 else if (_dbus_string_starts_with_c_str (&line,
00755 "ALIGN"))
00756 {
00757 long val;
00758 int end;
00759 int orig_len;
00760
00761 _dbus_string_delete_first_word (&line);
00762
00763 if (!_dbus_string_parse_int (&line, 0, &val, &end))
00764 {
00765 _dbus_warn ("Failed to parse integer\n");
00766 goto parse_failed;
00767 }
00768
00769 if (val > 8)
00770 {
00771 _dbus_warn ("Aligning to %ld boundary is crack\n",
00772 val);
00773 goto parse_failed;
00774 }
00775
00776 orig_len = _dbus_string_get_length (dest);
00777
00778 if (!_dbus_string_align_length (dest, val))
00779 goto parse_failed;
00780
00781 if (_dbus_string_parse_int (&line, end, &val, NULL))
00782 {
00783
00784
00785
00786 if (val < 0 || val > 255)
00787 {
00788 _dbus_warn ("can't fill align padding with %ld, must be a byte value\n", val);
00789 goto parse_failed;
00790 }
00791
00792 end = orig_len;
00793 while (end < _dbus_string_get_length (dest))
00794 {
00795 _dbus_string_set_byte (dest, end, val);
00796 ++end;
00797 }
00798 }
00799 }
00800 else if (_dbus_string_starts_with_c_str (&line, "UNALIGN"))
00801 {
00802 unalign = TRUE;
00803 just_set_unalign = TRUE;
00804 }
00805 else if (_dbus_string_starts_with_c_str (&line, "CHOP"))
00806 {
00807 long val;
00808
00809
00810
00811
00812
00813 _dbus_string_delete_first_word (&line);
00814
00815 if (!_dbus_string_parse_int (&line, 0, &val, NULL))
00816 {
00817 _dbus_warn ("Failed to parse integer to chop\n");
00818 goto parse_failed;
00819 }
00820
00821 if (val > _dbus_string_get_length (dest))
00822 {
00823 _dbus_warn ("Trying to chop %ld bytes but we only have %d\n",
00824 val,
00825 _dbus_string_get_length (dest));
00826 goto parse_failed;
00827 }
00828
00829 _dbus_string_shorten (dest, val);
00830 }
00831 else if (_dbus_string_starts_with_c_str (&line,
00832 "START_LENGTH"))
00833 {
00834 _dbus_string_delete_first_word (&line);
00835
00836 if (!save_start (length_hash, &line,
00837 _dbus_string_get_length (dest)))
00838 {
00839 _dbus_warn ("failed to save length start\n");
00840 goto parse_failed;
00841 }
00842 }
00843 else if (_dbus_string_starts_with_c_str (&line,
00844 "END_LENGTH"))
00845 {
00846 _dbus_string_delete_first_word (&line);
00847
00848 if (!save_length (length_hash, &line,
00849 _dbus_string_get_length (dest)))
00850 {
00851 _dbus_warn ("failed to save length end\n");
00852 goto parse_failed;
00853 }
00854 }
00855 else if (_dbus_string_starts_with_c_str (&line,
00856 "LENGTH"))
00857 {
00858 SAVE_FOR_UNALIGN (dest, 4);
00859
00860 _dbus_string_delete_first_word (&line);
00861
00862 if (!append_saved_length (dest, length_hash,
00863 &line,
00864 unalign ? align_pad_start : align_pad_end,
00865 endian))
00866 {
00867 _dbus_warn ("failed to add LENGTH\n");
00868 goto parse_failed;
00869 }
00870
00871 PERFORM_UNALIGN (dest);
00872 }
00873 else if (_dbus_string_starts_with_c_str (&line,
00874 "HEADER_FIELD"))
00875 {
00876 int field;
00877
00878 _dbus_string_delete_first_word (&line);
00879
00880 if (_dbus_string_starts_with_c_str (&line, "INVALID"))
00881 field = DBUS_HEADER_FIELD_INVALID;
00882 else if (_dbus_string_starts_with_c_str (&line, "PATH"))
00883 field = DBUS_HEADER_FIELD_PATH;
00884 else if (_dbus_string_starts_with_c_str (&line, "INTERFACE"))
00885 field = DBUS_HEADER_FIELD_INTERFACE;
00886 else if (_dbus_string_starts_with_c_str (&line, "MEMBER"))
00887 field = DBUS_HEADER_FIELD_MEMBER;
00888 else if (_dbus_string_starts_with_c_str (&line, "ERROR_NAME"))
00889 field = DBUS_HEADER_FIELD_ERROR_NAME;
00890 else if (_dbus_string_starts_with_c_str (&line, "REPLY_SERIAL"))
00891 field = DBUS_HEADER_FIELD_REPLY_SERIAL;
00892 else if (_dbus_string_starts_with_c_str (&line, "DESTINATION"))
00893 field = DBUS_HEADER_FIELD_DESTINATION;
00894 else if (_dbus_string_starts_with_c_str (&line, "SENDER"))
00895 field = DBUS_HEADER_FIELD_SENDER;
00896 else if (_dbus_string_starts_with_c_str (&line, "SIGNATURE"))
00897 field = DBUS_HEADER_FIELD_SIGNATURE;
00898 else if (_dbus_string_starts_with_c_str (&line, "UNKNOWN"))
00899 field = 22;
00900 else
00901 {
00902 _dbus_warn ("%s is not a valid header field name\n",
00903 _dbus_string_get_const_data (&line));
00904 goto parse_failed;
00905 }
00906
00907 if (!_dbus_string_append_byte (dest, field))
00908 {
00909 _dbus_warn ("could not append header field name byte\n");
00910 goto parse_failed;
00911 }
00912 }
00913 else if (_dbus_string_starts_with_c_str (&line,
00914 "TYPE"))
00915 {
00916 int code;
00917
00918 _dbus_string_delete_first_word (&line);
00919
00920 if (_dbus_string_starts_with_c_str (&line, "INVALID"))
00921 code = DBUS_TYPE_INVALID;
00922 else if (_dbus_string_starts_with_c_str (&line, "NIL"))
00923 code = DBUS_TYPE_NIL;
00924 else if ((code = lookup_basic_type (&line, NULL)) != DBUS_TYPE_INVALID)
00925 ;
00926 else if (_dbus_string_starts_with_c_str (&line, "STRING"))
00927 code = DBUS_TYPE_STRING;
00928 else if (_dbus_string_starts_with_c_str (&line, "OBJECT_PATH"))
00929 code = DBUS_TYPE_OBJECT_PATH;
00930 else if (_dbus_string_starts_with_c_str (&line, "CUSTOM"))
00931 code = DBUS_TYPE_CUSTOM;
00932 else if (_dbus_string_starts_with_c_str (&line, "ARRAY"))
00933 code = DBUS_TYPE_ARRAY;
00934 else if (_dbus_string_starts_with_c_str (&line, "DICT"))
00935 code = DBUS_TYPE_DICT;
00936 else
00937 {
00938 _dbus_warn ("%s is not a valid type name\n", _dbus_string_get_const_data (&line));
00939 goto parse_failed;
00940 }
00941
00942 if (!_dbus_string_append_byte (dest, code))
00943 {
00944 _dbus_warn ("could not append typecode byte\n");
00945 goto parse_failed;
00946 }
00947 }
00948 else if (_dbus_string_starts_with_c_str (&line,
00949 "STRING_ARRAY"))
00950 {
00951 SAVE_FOR_UNALIGN (dest, 4);
00952 int i, len, allocated;
00953 char **values;
00954 char *val;
00955 DBusString val_str;
00956 unsigned char b;
00957
00958 allocated = 4;
00959 values = dbus_new (char *, allocated);
00960 if (!values)
00961 {
00962 _dbus_warn ("could not allocate memory for STRING_ARRAY\n");
00963 goto parse_failed;
00964 }
00965
00966 len = 0;
00967
00968 _dbus_string_delete_first_word (&line);
00969 _dbus_string_skip_blank (&line, 0, &i);
00970 b = _dbus_string_get_byte (&line, i++);
00971
00972 if (b != '{')
00973 goto parse_failed;
00974
00975 _dbus_string_init (&val_str);
00976 while (i < _dbus_string_get_length (&line))
00977 {
00978 _dbus_string_skip_blank (&line, i, &i);
00979
00980 if (!append_quoted_string (&val_str, &line, i, &i))
00981 {
00982 _dbus_warn ("could not parse quoted string for STRING_ARRAY\n");
00983 goto parse_failed;
00984 }
00985 i++;
00986
00987 if (!_dbus_string_steal_data (&val_str, &val))
00988 {
00989 _dbus_warn ("could not allocate memory for STRING_ARRAY string\n");
00990 goto parse_failed;
00991 }
00992
00993 values[len++] = val;
00994 if (len == allocated)
00995 {
00996 allocated *= 2;
00997 values = dbus_realloc (values, allocated * sizeof (char *));
00998 if (!values)
00999 {
01000 _dbus_warn ("could not allocate memory for STRING_ARRAY\n");
01001 goto parse_failed;
01002 }
01003 }
01004
01005 _dbus_string_skip_blank (&line, i, &i);
01006
01007 b = _dbus_string_get_byte (&line, i++);
01008
01009 if (b == '}')
01010 break;
01011 else if (b != ',')
01012 {
01013 _dbus_warn ("missing comma when parsing STRING_ARRAY\n");
01014 goto parse_failed;
01015 }
01016 }
01017 _dbus_string_free (&val_str);
01018
01019 if (!_dbus_marshal_string_array (dest, endian, (const char **)values, len))
01020 {
01021 _dbus_warn ("failed to append STRING_ARRAY\n");
01022 goto parse_failed;
01023 }
01024
01025 values[len] = NULL;
01026 dbus_free_string_array (values);
01027
01028 PERFORM_UNALIGN (dest);
01029 }
01030 else if (_dbus_string_starts_with_c_str (&line,
01031 "STRING"))
01032 {
01033 SAVE_FOR_UNALIGN (dest, 4);
01034 int size_offset;
01035 int old_len;
01036
01037 _dbus_string_delete_first_word (&line);
01038
01039 size_offset = _dbus_string_get_length (dest);
01040 size_offset = _DBUS_ALIGN_VALUE (size_offset, 4);
01041 if (!_dbus_marshal_uint32 (dest, endian, 0))
01042 {
01043 _dbus_warn ("Failed to append string size\n");
01044 goto parse_failed;
01045 }
01046
01047 old_len = _dbus_string_get_length (dest);
01048 if (!append_quoted_string (dest, &line, 0, NULL))
01049 {
01050 _dbus_warn ("Failed to append quoted string\n");
01051 goto parse_failed;
01052 }
01053
01054 _dbus_marshal_set_uint32 (dest, endian, size_offset,
01055
01056 _dbus_string_get_length (dest) - old_len - 1);
01057
01058 PERFORM_UNALIGN (dest);
01059 }
01060 else if ((type = lookup_basic_type (&line, &is_array)) != DBUS_TYPE_INVALID)
01061 {
01062 if (is_array)
01063 {
01064 if (!parse_basic_array (&line, type, dest, &unalign, endian))
01065 goto parse_failed;
01066 }
01067 else
01068 {
01069 if (!parse_basic_type (&line, type, dest, &unalign, endian))
01070 goto parse_failed;
01071 }
01072 }
01073 else if (_dbus_string_starts_with_c_str (&line,
01074 "OBJECT_PATH"))
01075 {
01076 SAVE_FOR_UNALIGN (dest, 4);
01077 int size_offset;
01078 int old_len;
01079
01080 _dbus_string_delete_first_word (&line);
01081
01082 size_offset = _dbus_string_get_length (dest);
01083 size_offset = _DBUS_ALIGN_VALUE (size_offset, 4);
01084 if (!_dbus_marshal_uint32 (dest, endian, 0))
01085 {
01086 _dbus_warn ("Failed to append string size\n");
01087 goto parse_failed;
01088 }
01089
01090 old_len = _dbus_string_get_length (dest);
01091 if (!append_quoted_string (dest, &line, 0, NULL))
01092 {
01093 _dbus_warn ("Failed to append quoted string\n");
01094 goto parse_failed;
01095 }
01096
01097 _dbus_marshal_set_uint32 (dest, endian, size_offset,
01098
01099 _dbus_string_get_length (dest) - old_len - 1);
01100
01101 PERFORM_UNALIGN (dest);
01102 }
01103 else
01104 goto parse_failed;
01105
01106 if (!just_set_unalign && unalign)
01107 {
01108 _dbus_warn ("UNALIGN prior to something that isn't aligned\n");
01109 goto parse_failed;
01110 }
01111
01112 goto next_iteration;
01113
01114 parse_failed:
01115 {
01116 _dbus_warn ("couldn't process line %d \"%s\"\n",
01117 line_no, _dbus_string_get_const_data (&line));
01118 goto out;
01119 }
01120 }
01121
01122 _dbus_hash_iter_init (length_hash, &iter);
01123 while (_dbus_hash_iter_next (&iter))
01124 {
01125 SavedLength *sl = _dbus_hash_iter_get_value (&iter);
01126 const char *s;
01127
01128 s = _dbus_string_get_const_data (&sl->name);
01129
01130 if (sl->length < 0)
01131 {
01132 _dbus_warn ("Used LENGTH %s but never did END_LENGTH\n",
01133 s);
01134 goto out;
01135 }
01136 else if (sl->offset < 0)
01137 {
01138 _dbus_warn ("Did END_LENGTH %s but never used LENGTH\n",
01139 s);
01140 goto out;
01141 }
01142 else
01143 {
01144 if (sl->start < 0)
01145 sl->start = 0;
01146
01147 _dbus_verbose ("Filling in length %s endian = %d offset = %d start = %d length = %d\n",
01148 s, sl->endian, sl->offset, sl->start, sl->length);
01149 _dbus_marshal_set_int32 (dest,
01150 sl->endian,
01151 sl->offset,
01152 sl->length - sl->start);
01153 }
01154
01155 _dbus_hash_iter_remove_entry (&iter);
01156 }
01157
01158 retval = TRUE;
01159
01160 _dbus_verbose_bytes_of_string (dest, 0, _dbus_string_get_length (dest));
01161
01162 out:
01163 if (length_hash != NULL)
01164 _dbus_hash_table_unref (length_hash);
01165
01166 _dbus_string_free (&file);
01167 _dbus_string_free (&line);
01168 return retval;
01169 }
01170
01172 #endif