DBusMessage: don't redundantly store byte order, ask the DBusHeader
[platform/upstream/dbus.git] / dbus / dbus-marshal-header.c
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* dbus-marshal-header.c  Managing marshaling/demarshaling of message headers
3  *
4  * Copyright (C) 2005  Red Hat, Inc.
5  *
6  * Licensed under the Academic Free License version 2.1
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21  *
22  */
23
24 #include <config.h>
25 #include "dbus/dbus-shared.h"
26 #include "dbus-marshal-header.h"
27 #include "dbus-marshal-recursive.h"
28 #include "dbus-marshal-byteswap.h"
29
30 /**
31  * @addtogroup DBusMarshal
32  *
33  * @{
34  */
35
36
37 /* Not thread locked, but strictly const/read-only so should be OK
38  */
39 /** Static #DBusString containing the signature of a message header */
40 _DBUS_STRING_DEFINE_STATIC(_dbus_header_signature_str, DBUS_HEADER_SIGNATURE);
41 /** Static #DBusString containing the local interface */
42 _DBUS_STRING_DEFINE_STATIC(_dbus_local_interface_str,  DBUS_INTERFACE_LOCAL);
43 /** Static #DBusString containing the local path */
44 _DBUS_STRING_DEFINE_STATIC(_dbus_local_path_str,       DBUS_PATH_LOCAL);
45
46 /** Offset from start of _dbus_header_signature_str to the signature of the fields array */
47 #define FIELDS_ARRAY_SIGNATURE_OFFSET 6
48 /** Offset from start of _dbus_header_signature_str to the signature of an element of the fields array */
49 #define FIELDS_ARRAY_ELEMENT_SIGNATURE_OFFSET 7
50
51
52 /** Offset to byte order from start of header */
53 #define BYTE_ORDER_OFFSET    0
54 /** Offset to type from start of header */
55 #define TYPE_OFFSET          1
56 /** Offset to flags from start of header */
57 #define FLAGS_OFFSET         2
58 /** Offset to version from start of header */
59 #define VERSION_OFFSET       3
60 /** Offset to body length from start of header */
61 #define BODY_LENGTH_OFFSET 4
62 /** Offset to client serial from start of header */
63 #define SERIAL_OFFSET 8
64 /** Offset to fields array length from start of header */
65 #define FIELDS_ARRAY_LENGTH_OFFSET 12
66 /** Offset to first field in header */
67 #define FIRST_FIELD_OFFSET 16
68
69 typedef struct
70 {
71   unsigned char code; /**< the field code */
72   unsigned char type; /**< the value type */
73 } HeaderFieldType;
74
75 static const HeaderFieldType
76 _dbus_header_field_types[DBUS_HEADER_FIELD_LAST+1] = {
77   { DBUS_HEADER_FIELD_INVALID, DBUS_TYPE_INVALID },
78   { DBUS_HEADER_FIELD_PATH, DBUS_TYPE_OBJECT_PATH },
79   { DBUS_HEADER_FIELD_INTERFACE, DBUS_TYPE_STRING },
80   { DBUS_HEADER_FIELD_MEMBER, DBUS_TYPE_STRING },
81   { DBUS_HEADER_FIELD_ERROR_NAME, DBUS_TYPE_STRING },
82   { DBUS_HEADER_FIELD_REPLY_SERIAL, DBUS_TYPE_UINT32 },
83   { DBUS_HEADER_FIELD_DESTINATION, DBUS_TYPE_STRING },
84   { DBUS_HEADER_FIELD_SENDER, DBUS_TYPE_STRING },
85   { DBUS_HEADER_FIELD_SIGNATURE, DBUS_TYPE_SIGNATURE },
86   { DBUS_HEADER_FIELD_UNIX_FDS, DBUS_TYPE_UINT32 }
87 };
88
89 /** Macro to look up the correct type for a field */
90 #define EXPECTED_TYPE_OF_FIELD(field) (_dbus_header_field_types[field].type)
91
92 /** The most padding we could ever need for a header */
93 #define MAX_POSSIBLE_HEADER_PADDING 7
94 static dbus_bool_t
95 reserve_header_padding (DBusHeader *header)
96 {
97   _dbus_assert (header->padding <= MAX_POSSIBLE_HEADER_PADDING);
98
99   if (!_dbus_string_lengthen (&header->data,
100                               MAX_POSSIBLE_HEADER_PADDING - header->padding))
101     return FALSE;
102   header->padding = MAX_POSSIBLE_HEADER_PADDING;
103   return TRUE;
104 }
105
106 static void
107 correct_header_padding (DBusHeader *header)
108 {
109   int unpadded_len;
110
111   _dbus_assert (header->padding == 7);
112
113   _dbus_string_shorten (&header->data, header->padding);
114   unpadded_len = _dbus_string_get_length (&header->data);
115
116   if (!_dbus_string_align_length (&header->data, 8))
117     _dbus_assert_not_reached ("couldn't pad header though enough padding was preallocated");
118
119   header->padding = _dbus_string_get_length (&header->data) - unpadded_len;
120 }
121
122 /** Compute the end of the header, ignoring padding */
123 #define HEADER_END_BEFORE_PADDING(header) \
124   (_dbus_string_get_length (&(header)->data) - (header)->padding)
125
126 /**
127  * Invalidates all fields in the cache. This may be used when the
128  * cache is totally uninitialized (contains junk) so should not
129  * look at what's in there now.
130  *
131  * @param header the header
132  */
133 static void
134 _dbus_header_cache_invalidate_all (DBusHeader *header)
135 {
136   int i;
137
138   i = 0;
139   while (i <= DBUS_HEADER_FIELD_LAST)
140     {
141       header->fields[i].value_pos = _DBUS_HEADER_FIELD_VALUE_UNKNOWN;
142       ++i;
143     }
144 }
145
146 /**
147  * Caches one field
148  *
149  * @param header the header
150  * @param field_code the field
151  * @param variant_reader the reader for the variant in the field
152  */
153 static void
154 _dbus_header_cache_one (DBusHeader     *header,
155                         int             field_code,
156                         DBusTypeReader *variant_reader)
157 {
158   header->fields[field_code].value_pos =
159     _dbus_type_reader_get_value_pos (variant_reader);
160
161 #if 0
162   _dbus_verbose ("cached value_pos %d for field %d\n",
163                  header->fields[field_code].value_pos, field_code)
164 #endif
165 }
166
167 /**
168  * Returns the header's byte order.
169  *
170  * @param header the header
171  * @returns the byte order
172  */
173 char
174 _dbus_header_get_byte_order (const DBusHeader *header)
175 {
176   _dbus_assert (_dbus_string_get_length (&header->data) > BYTE_ORDER_OFFSET);
177
178   return (char) _dbus_string_get_byte (&header->data, BYTE_ORDER_OFFSET);
179 }
180
181 /**
182  * Revalidates the fields cache
183  *
184  * @param header the header
185  */
186 static void
187 _dbus_header_cache_revalidate (DBusHeader *header)
188 {
189   DBusTypeReader array;
190   DBusTypeReader reader;
191   int i;
192
193   i = 0;
194   while (i <= DBUS_HEADER_FIELD_LAST)
195     {
196       header->fields[i].value_pos = _DBUS_HEADER_FIELD_VALUE_NONEXISTENT;
197       ++i;
198     }
199
200   _dbus_type_reader_init (&reader,
201                           header->byte_order,
202                           &_dbus_header_signature_str,
203                           FIELDS_ARRAY_SIGNATURE_OFFSET,
204                           &header->data,
205                           FIELDS_ARRAY_LENGTH_OFFSET);
206
207   _dbus_type_reader_recurse (&reader, &array);
208
209   while (_dbus_type_reader_get_current_type (&array) != DBUS_TYPE_INVALID)
210     {
211       DBusTypeReader sub;
212       DBusTypeReader variant;
213       unsigned char field_code;
214
215       _dbus_type_reader_recurse (&array, &sub);
216
217       _dbus_assert (_dbus_type_reader_get_current_type (&sub) == DBUS_TYPE_BYTE);
218       _dbus_type_reader_read_basic (&sub, &field_code);
219
220       /* Unknown fields should be ignored */
221       if (field_code > DBUS_HEADER_FIELD_LAST)
222         goto next_field;
223
224       _dbus_type_reader_next (&sub);
225
226       _dbus_assert (_dbus_type_reader_get_current_type (&sub) == DBUS_TYPE_VARIANT);
227       _dbus_type_reader_recurse (&sub, &variant);
228
229       _dbus_header_cache_one (header, field_code, &variant);
230
231     next_field:
232       _dbus_type_reader_next (&array);
233     }
234 }
235
236 /**
237  * Checks for a field, updating the cache if required.
238  *
239  * @param header the header
240  * @param field the field to check
241  * @returns #FALSE if the field doesn't exist
242  */
243 static dbus_bool_t
244 _dbus_header_cache_check (DBusHeader    *header,
245                           int            field)
246 {
247   _dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
248
249   if (header->fields[field].value_pos == _DBUS_HEADER_FIELD_VALUE_UNKNOWN)
250     _dbus_header_cache_revalidate (header);
251
252   if (header->fields[field].value_pos == _DBUS_HEADER_FIELD_VALUE_NONEXISTENT)
253     return FALSE;
254
255   return TRUE;
256 }
257
258 /**
259  * Checks whether a field is known not to exist. It may exist
260  * even if it's not known to exist.
261  *
262  * @param header the header
263  * @param field the field to check
264  * @returns #FALSE if the field definitely doesn't exist
265  */
266 static dbus_bool_t
267 _dbus_header_cache_known_nonexistent (DBusHeader    *header,
268                                       int            field)
269 {
270   _dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
271
272   return (header->fields[field].value_pos == _DBUS_HEADER_FIELD_VALUE_NONEXISTENT);
273 }
274
275 /**
276  * Writes a struct of { byte, variant } with the given basic type.
277  *
278  * @param writer the writer (should be ready to write a struct)
279  * @param type the type of the value
280  * @param value the value as for _dbus_marshal_set_basic()
281  * @returns #FALSE if no memory
282  */
283 static dbus_bool_t
284 write_basic_field (DBusTypeWriter *writer,
285                    int             field,
286                    int             type,
287                    const void     *value)
288 {
289   DBusTypeWriter sub;
290   DBusTypeWriter variant;
291   int start;
292   int padding;
293   unsigned char field_byte;
294   DBusString contained_type;
295   char buf[2];
296
297   start = writer->value_pos;
298   padding = _dbus_string_get_length (writer->value_str) - start;
299
300   if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_STRUCT,
301                                   NULL, 0, &sub))
302     goto append_failed;
303
304   field_byte = field;
305   if (!_dbus_type_writer_write_basic (&sub, DBUS_TYPE_BYTE,
306                                       &field_byte))
307     goto append_failed;
308
309   buf[0] = type;
310   buf[1] = '\0';
311   _dbus_string_init_const_len (&contained_type, buf, 1);
312
313   if (!_dbus_type_writer_recurse (&sub, DBUS_TYPE_VARIANT,
314                                   &contained_type, 0, &variant))
315     goto append_failed;
316
317   if (!_dbus_type_writer_write_basic (&variant, type, value))
318     goto append_failed;
319
320   if (!_dbus_type_writer_unrecurse (&sub, &variant))
321     goto append_failed;
322
323   if (!_dbus_type_writer_unrecurse (writer, &sub))
324     goto append_failed;
325
326   return TRUE;
327
328  append_failed:
329   _dbus_string_delete (writer->value_str,
330                        start,
331                        _dbus_string_get_length (writer->value_str) - start - padding);
332   return FALSE;
333 }
334
335 /**
336  * Sets a struct of { byte, variant } with the given basic type.
337  *
338  * @param reader the reader (should be iterating over the array pointing at the field to set)
339  * @param type the type of the value
340  * @param value the value as for _dbus_marshal_set_basic()
341  * @param realign_root where to realign from
342  * @returns #FALSE if no memory
343  */
344 static dbus_bool_t
345 set_basic_field (DBusTypeReader       *reader,
346                  int                   field,
347                  int                   type,
348                  const void           *value,
349                  const DBusTypeReader *realign_root)
350 {
351   DBusTypeReader sub;
352   DBusTypeReader variant;
353
354   _dbus_type_reader_recurse (reader, &sub);
355
356   _dbus_assert (_dbus_type_reader_get_current_type (&sub) == DBUS_TYPE_BYTE);
357 #ifndef DBUS_DISABLE_ASSERT
358  {
359    unsigned char v_BYTE;
360    _dbus_type_reader_read_basic (&sub, &v_BYTE);
361    _dbus_assert (((int) v_BYTE) == field);
362  }
363 #endif
364
365   if (!_dbus_type_reader_next (&sub))
366     _dbus_assert_not_reached ("no variant field?");
367
368   _dbus_type_reader_recurse (&sub, &variant);
369   _dbus_assert (_dbus_type_reader_get_current_type (&variant) == type);
370
371   if (!_dbus_type_reader_set_basic (&variant, value, realign_root))
372     return FALSE;
373
374   return TRUE;
375 }
376
377 /**
378  * Gets the type of the message.
379  *
380  * @param header the header
381  * @returns the type
382  */
383 int
384 _dbus_header_get_message_type (DBusHeader *header)
385 {
386   int type;
387
388   type = _dbus_string_get_byte (&header->data, TYPE_OFFSET);
389   _dbus_assert (type != DBUS_MESSAGE_TYPE_INVALID);
390
391   return type;
392 }
393
394 /**
395  * Sets the serial number of a header.  This can only be done once on
396  * a header.
397  *
398  * @param header the header
399  * @param serial the serial
400  */
401 void
402 _dbus_header_set_serial (DBusHeader    *header,
403                          dbus_uint32_t  serial)
404 {
405   /* we use this function to set the serial on outgoing
406    * messages, and to reset the serial in dbus_message_copy;
407    * this assertion should catch a double-set on outgoing.
408    */
409   _dbus_assert (_dbus_header_get_serial (header) == 0 ||
410                 serial == 0);
411
412   _dbus_marshal_set_uint32 (&header->data,
413                             SERIAL_OFFSET,
414                             serial,
415                             header->byte_order);
416 }
417
418 /**
419  * See dbus_message_get_serial()
420  *
421  * @param header the header
422  * @returns the client serial
423  */
424 dbus_uint32_t
425 _dbus_header_get_serial (DBusHeader *header)
426 {
427   return _dbus_marshal_read_uint32 (&header->data,
428                                     SERIAL_OFFSET,
429                                     header->byte_order,
430                                     NULL);
431 }
432
433 /**
434  * Re-initializes a header that was previously initialized and never
435  * freed.  After this, to make the header valid you have to call
436  * _dbus_header_create().
437  *
438  * @param header header to re-initialize
439  * @param byte_order byte order of the header
440  */
441 void
442 _dbus_header_reinit (DBusHeader *header,
443                      int         byte_order)
444 {
445   _dbus_string_set_length (&header->data, 0);
446
447   header->byte_order = byte_order;
448   header->padding = 0;
449
450   _dbus_header_cache_invalidate_all (header);
451 }
452
453 /**
454  * Initializes a header, but doesn't prepare it for use;
455  * to make the header valid, you have to call _dbus_header_create().
456  *
457  * @param header header to initialize
458  * @param byte_order byte order of the header
459  * @returns #FALSE if not enough memory
460  */
461 dbus_bool_t
462 _dbus_header_init (DBusHeader *header,
463                    int         byte_order)
464 {
465   if (!_dbus_string_init_preallocated (&header->data, 32))
466     return FALSE;
467
468   _dbus_header_reinit (header, byte_order);
469
470   return TRUE;
471 }
472
473 /**
474  * Frees a header.
475  *
476  * @param header the header
477  */
478 void
479 _dbus_header_free (DBusHeader *header)
480 {
481   _dbus_string_free (&header->data);
482 }
483
484 /**
485  * Initializes dest with a copy of the given header.
486  * Resets the message serial to 0 on the copy.
487  *
488  * @param header header to copy
489  * @param dest destination for copy
490  * @returns #FALSE if not enough memory
491  */
492 dbus_bool_t
493 _dbus_header_copy (const DBusHeader *header,
494                    DBusHeader       *dest)
495 {
496   *dest = *header;
497
498   if (!_dbus_string_init_preallocated (&dest->data,
499                                        _dbus_string_get_length (&header->data)))
500     return FALSE;
501
502   if (!_dbus_string_copy (&header->data, 0, &dest->data, 0))
503     {
504       _dbus_string_free (&dest->data);
505       return FALSE;
506     }
507
508   /* Reset the serial */
509   _dbus_header_set_serial (dest, 0);
510
511   return TRUE;
512 }
513
514 /**
515  * Fills in the primary fields of the header, so the header is ready
516  * for use. #NULL may be specified for some or all of the fields to
517  * avoid adding those fields. Some combinations of fields don't make
518  * sense, and passing them in will trigger an assertion failure.
519  *
520  * @param header the header
521  * @param message_type the message type
522  * @param destination destination field or #NULL
523  * @param path path field or #NULL
524  * @param interface interface field or #NULL
525  * @param member member field or #NULL
526  * @param error_name error name or #NULL
527  * @returns #FALSE if not enough memory
528  */
529 dbus_bool_t
530 _dbus_header_create (DBusHeader  *header,
531                      int          message_type,
532                      const char  *destination,
533                      const char  *path,
534                      const char  *interface,
535                      const char  *member,
536                      const char  *error_name)
537 {
538   unsigned char v_BYTE;
539   dbus_uint32_t v_UINT32;
540   DBusTypeWriter writer;
541   DBusTypeWriter array;
542
543   _dbus_assert (((interface || message_type != DBUS_MESSAGE_TYPE_SIGNAL) && member) ||
544                 (error_name) ||
545                 !(interface || member || error_name));
546   _dbus_assert (_dbus_string_get_length (&header->data) == 0);
547
548   if (!reserve_header_padding (header))
549     return FALSE;
550
551   _dbus_type_writer_init_values_only (&writer, header->byte_order,
552                                       &_dbus_header_signature_str, 0,
553                                       &header->data,
554                                       HEADER_END_BEFORE_PADDING (header));
555
556   v_BYTE = header->byte_order;
557   if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_BYTE,
558                                       &v_BYTE))
559     goto oom;
560
561   v_BYTE = message_type;
562   if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_BYTE,
563                                       &v_BYTE))
564     goto oom;
565
566   v_BYTE = 0; /* flags */
567   if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_BYTE,
568                                       &v_BYTE))
569     goto oom;
570
571   v_BYTE = DBUS_MAJOR_PROTOCOL_VERSION;
572   if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_BYTE,
573                                       &v_BYTE))
574     goto oom;
575
576   v_UINT32 = 0; /* body length */
577   if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_UINT32,
578                                       &v_UINT32))
579     goto oom;
580
581   v_UINT32 = 0; /* serial */
582   if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_UINT32,
583                                       &v_UINT32))
584     goto oom;
585
586   if (!_dbus_type_writer_recurse (&writer, DBUS_TYPE_ARRAY,
587                                   &_dbus_header_signature_str,
588                                   FIELDS_ARRAY_SIGNATURE_OFFSET,
589                                   &array))
590     goto oom;
591
592   /* Marshal all the fields (Marshall Fields?) */
593
594   if (path != NULL)
595     {
596       if (!write_basic_field (&array,
597                               DBUS_HEADER_FIELD_PATH,
598                               DBUS_TYPE_OBJECT_PATH,
599                               &path))
600         goto oom;
601     }
602
603   if (destination != NULL)
604     {
605       if (!write_basic_field (&array,
606                               DBUS_HEADER_FIELD_DESTINATION,
607                               DBUS_TYPE_STRING,
608                               &destination))
609         goto oom;
610     }
611
612   if (interface != NULL)
613     {
614       if (!write_basic_field (&array,
615                               DBUS_HEADER_FIELD_INTERFACE,
616                               DBUS_TYPE_STRING,
617                               &interface))
618         goto oom;
619     }
620
621   if (member != NULL)
622     {
623       if (!write_basic_field (&array,
624                               DBUS_HEADER_FIELD_MEMBER,
625                               DBUS_TYPE_STRING,
626                               &member))
627         goto oom;
628     }
629
630   if (error_name != NULL)
631     {
632       if (!write_basic_field (&array,
633                               DBUS_HEADER_FIELD_ERROR_NAME,
634                               DBUS_TYPE_STRING,
635                               &error_name))
636         goto oom;
637     }
638
639   if (!_dbus_type_writer_unrecurse (&writer, &array))
640     goto oom;
641
642   correct_header_padding (header);
643
644   return TRUE;
645
646  oom:
647   _dbus_string_delete (&header->data, 0,
648                        _dbus_string_get_length (&header->data) - header->padding);
649   correct_header_padding (header);
650
651   return FALSE;
652 }
653
654 /**
655  * Given data long enough to contain the length of the message body
656  * and the fields array, check whether the data is long enough to
657  * contain the entire message (assuming the claimed lengths are
658  * accurate). Also checks that the lengths are in sanity parameters.
659  *
660  * @param max_message_length maximum length of a valid message
661  * @param validity return location for why the data is invalid if it is
662  * @param byte_order return location for byte order
663  * @param fields_array_len return location for claimed fields array length
664  * @param header_len return location for claimed header length
665  * @param body_len return location for claimed body length
666  * @param str the data
667  * @param start start of data, 8-aligned
668  * @param len length of data
669  * @returns #TRUE if the data is long enough for the claimed length, and the lengths were valid
670  */
671 dbus_bool_t
672 _dbus_header_have_message_untrusted (int                max_message_length,
673                                      DBusValidity      *validity,
674                                      int               *byte_order,
675                                      int               *fields_array_len,
676                                      int               *header_len,
677                                      int               *body_len,
678                                      const DBusString  *str,
679                                      int                start,
680                                      int                len)
681
682 {
683   dbus_uint32_t header_len_unsigned;
684   dbus_uint32_t fields_array_len_unsigned;
685   dbus_uint32_t body_len_unsigned;
686
687   _dbus_assert (start >= 0);
688   _dbus_assert (start < _DBUS_INT32_MAX / 2);
689   _dbus_assert (len >= 0);
690
691   _dbus_assert (start == (int) _DBUS_ALIGN_VALUE (start, 8));
692
693   *byte_order = _dbus_string_get_byte (str, start + BYTE_ORDER_OFFSET);
694
695   if (*byte_order != DBUS_LITTLE_ENDIAN && *byte_order != DBUS_BIG_ENDIAN)
696     {
697       *validity = DBUS_INVALID_BAD_BYTE_ORDER;
698       return FALSE;
699     }
700
701   _dbus_assert (FIELDS_ARRAY_LENGTH_OFFSET + 4 <= len);
702   fields_array_len_unsigned = _dbus_marshal_read_uint32 (str, start + FIELDS_ARRAY_LENGTH_OFFSET,
703                                                          *byte_order, NULL);
704
705   if (fields_array_len_unsigned > (unsigned) max_message_length)
706     {
707       *validity = DBUS_INVALID_INSANE_FIELDS_ARRAY_LENGTH;
708       return FALSE;
709     }
710
711   _dbus_assert (BODY_LENGTH_OFFSET + 4 < len);
712   body_len_unsigned = _dbus_marshal_read_uint32 (str, start + BODY_LENGTH_OFFSET,
713                                                  *byte_order, NULL);
714
715   if (body_len_unsigned > (unsigned) max_message_length)
716     {
717       *validity = DBUS_INVALID_INSANE_BODY_LENGTH;
718       return FALSE;
719     }
720
721   header_len_unsigned = FIRST_FIELD_OFFSET + fields_array_len_unsigned;
722   header_len_unsigned = _DBUS_ALIGN_VALUE (header_len_unsigned, 8);
723
724   /* overflow should be impossible since the lengths aren't allowed to
725    * be huge.
726    */
727   _dbus_assert (max_message_length < _DBUS_INT32_MAX / 2);
728   if (body_len_unsigned + header_len_unsigned > (unsigned) max_message_length)
729     {
730       *validity = DBUS_INVALID_MESSAGE_TOO_LONG;
731       return FALSE;
732     }
733
734   _dbus_assert (body_len_unsigned < (unsigned) _DBUS_INT32_MAX);
735   _dbus_assert (fields_array_len_unsigned < (unsigned) _DBUS_INT32_MAX);
736   _dbus_assert (header_len_unsigned < (unsigned) _DBUS_INT32_MAX);
737
738   *body_len = body_len_unsigned;
739   *fields_array_len = fields_array_len_unsigned;
740   *header_len = header_len_unsigned;
741
742   *validity = DBUS_VALID;
743
744   _dbus_verbose ("have %d bytes, need body %u + header %u = %u\n",
745                  len, body_len_unsigned, header_len_unsigned,
746                  body_len_unsigned + header_len_unsigned);
747
748   return (body_len_unsigned + header_len_unsigned) <= (unsigned) len;
749 }
750
751 static DBusValidity
752 check_mandatory_fields (DBusHeader *header)
753 {
754 #define REQUIRE_FIELD(name) do { if (header->fields[DBUS_HEADER_FIELD_##name].value_pos < 0) return DBUS_INVALID_MISSING_##name; } while (0)
755
756   switch (_dbus_header_get_message_type (header))
757     {
758     case DBUS_MESSAGE_TYPE_SIGNAL:
759       REQUIRE_FIELD (INTERFACE);
760       /* FALL THRU - signals also require the path and member */
761     case DBUS_MESSAGE_TYPE_METHOD_CALL:
762       REQUIRE_FIELD (PATH);
763       REQUIRE_FIELD (MEMBER);
764       break;
765     case DBUS_MESSAGE_TYPE_ERROR:
766       REQUIRE_FIELD (ERROR_NAME);
767       REQUIRE_FIELD (REPLY_SERIAL);
768       break;
769     case DBUS_MESSAGE_TYPE_METHOD_RETURN:
770       REQUIRE_FIELD (REPLY_SERIAL);
771       break;
772     default:
773       /* other message types allowed but ignored */
774       break;
775     }
776
777   return DBUS_VALID;
778 }
779
780 static DBusValidity
781 load_and_validate_field (DBusHeader     *header,
782                          int             field,
783                          DBusTypeReader *variant_reader)
784 {
785   int type;
786   int expected_type;
787   const DBusString *value_str;
788   int value_pos;
789   int str_data_pos;
790   dbus_uint32_t v_UINT32;
791   int bad_string_code;
792   dbus_bool_t (* string_validation_func) (const DBusString *str,
793                                           int start, int len);
794
795   /* Supposed to have been checked already */
796   _dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
797   _dbus_assert (field != DBUS_HEADER_FIELD_INVALID);
798
799   /* Before we can cache a field, we need to know it has the right type */
800   type = _dbus_type_reader_get_current_type (variant_reader);
801
802   _dbus_assert (_dbus_header_field_types[field].code == field);
803
804   expected_type = EXPECTED_TYPE_OF_FIELD (field);
805   if (type != expected_type)
806     {
807       _dbus_verbose ("Field %d should have type %d but has %d\n",
808                      field, expected_type, type);
809       return DBUS_INVALID_HEADER_FIELD_HAS_WRONG_TYPE;
810     }
811
812   /* If the field was provided twice, we aren't happy */
813   if (header->fields[field].value_pos >= 0)
814     {
815       _dbus_verbose ("Header field %d seen a second time\n", field);
816       return DBUS_INVALID_HEADER_FIELD_APPEARS_TWICE;
817     }
818
819   /* Now we can cache and look at the field content */
820   _dbus_verbose ("initially caching field %d\n", field);
821   _dbus_header_cache_one (header, field, variant_reader);
822
823   string_validation_func = NULL;
824
825   /* make compiler happy that all this is initialized */
826   v_UINT32 = 0;
827   value_str = NULL;
828   value_pos = -1;
829   str_data_pos = -1;
830   bad_string_code = DBUS_VALID;
831
832   if (expected_type == DBUS_TYPE_UINT32)
833     {
834       _dbus_header_get_field_basic (header, field, expected_type,
835                                     &v_UINT32);
836     }
837   else if (expected_type == DBUS_TYPE_STRING ||
838            expected_type == DBUS_TYPE_OBJECT_PATH ||
839            expected_type == DBUS_TYPE_SIGNATURE)
840     {
841       _dbus_header_get_field_raw (header, field,
842                                   &value_str, &value_pos);
843       str_data_pos = _DBUS_ALIGN_VALUE (value_pos, 4) + 4;
844     }
845   else
846     {
847       _dbus_assert_not_reached ("none of the known fields should have this type");
848     }
849
850   switch (field)
851     {
852     case DBUS_HEADER_FIELD_DESTINATION:
853       string_validation_func = _dbus_validate_bus_name;
854       bad_string_code = DBUS_INVALID_BAD_DESTINATION;
855       break;
856     case DBUS_HEADER_FIELD_INTERFACE:
857       string_validation_func = _dbus_validate_interface;
858       bad_string_code = DBUS_INVALID_BAD_INTERFACE;
859
860       if (_dbus_string_equal_substring (&_dbus_local_interface_str,
861                                         0,
862                                         _dbus_string_get_length (&_dbus_local_interface_str),
863                                         value_str, str_data_pos))
864         {
865           _dbus_verbose ("Message is on the local interface\n");
866           return DBUS_INVALID_USES_LOCAL_INTERFACE;
867         }
868       break;
869
870     case DBUS_HEADER_FIELD_MEMBER:
871       string_validation_func = _dbus_validate_member;
872       bad_string_code = DBUS_INVALID_BAD_MEMBER;
873       break;
874
875     case DBUS_HEADER_FIELD_ERROR_NAME:
876       string_validation_func = _dbus_validate_error_name;
877       bad_string_code = DBUS_INVALID_BAD_ERROR_NAME;
878       break;
879
880     case DBUS_HEADER_FIELD_SENDER:
881       string_validation_func = _dbus_validate_bus_name;
882       bad_string_code = DBUS_INVALID_BAD_SENDER;
883       break;
884
885     case DBUS_HEADER_FIELD_PATH:
886       /* OBJECT_PATH was validated generically due to its type */
887       string_validation_func = NULL;
888
889       if (_dbus_string_equal_substring (&_dbus_local_path_str,
890                                         0,
891                                         _dbus_string_get_length (&_dbus_local_path_str),
892                                         value_str, str_data_pos))
893         {
894           _dbus_verbose ("Message is from the local path\n");
895           return DBUS_INVALID_USES_LOCAL_PATH;
896         }
897       break;
898
899     case DBUS_HEADER_FIELD_REPLY_SERIAL:
900       /* Can't be 0 */
901       if (v_UINT32 == 0)
902         {
903           return DBUS_INVALID_BAD_SERIAL;
904         }
905       break;
906
907     case DBUS_HEADER_FIELD_UNIX_FDS:
908       /* Every value makes sense */
909       break;
910
911     case DBUS_HEADER_FIELD_SIGNATURE:
912       /* SIGNATURE validated generically due to its type */
913       string_validation_func = NULL;
914       break;
915
916     default:
917       _dbus_assert_not_reached ("unknown field shouldn't be seen here");
918       break;
919     }
920
921   if (string_validation_func)
922     {
923       dbus_uint32_t len;
924
925       _dbus_assert (bad_string_code != DBUS_VALID);
926
927       len = _dbus_marshal_read_uint32 (value_str, value_pos,
928                                        header->byte_order, NULL);
929
930 #if 0
931       _dbus_verbose ("Validating string header field; code %d if fails\n",
932                      bad_string_code);
933 #endif
934       if (!(*string_validation_func) (value_str, str_data_pos, len))
935         return bad_string_code;
936     }
937
938   return DBUS_VALID;
939 }
940
941 /**
942  * Creates a message header from potentially-untrusted data. The
943  * return value is #TRUE if there was enough memory and the data was
944  * valid. If it returns #TRUE, the header will be created. If it
945  * returns #FALSE and *validity == #DBUS_VALIDITY_UNKNOWN_OOM_ERROR, 
946  * then there wasn't enough memory.  If it returns #FALSE 
947  * and *validity != #DBUS_VALIDITY_UNKNOWN_OOM_ERROR then the data was 
948  * invalid.
949  *
950  * The byte_order, fields_array_len, and body_len args should be from
951  * _dbus_header_have_message_untrusted(). Validation performed in
952  * _dbus_header_have_message_untrusted() is assumed to have been
953  * already done.
954  *
955  * @param header the header (must be initialized)
956  * @param mode whether to do validation
957  * @param validity return location for invalidity reason
958  * @param byte_order byte order from header
959  * @param fields_array_len claimed length of fields array
960  * @param body_len claimed length of body
961  * @param header_len claimed length of header
962  * @param str a string
963  * @param start start of header, 8-aligned
964  * @param len length of string to look at
965  * @returns #FALSE if no memory or data was invalid, #TRUE otherwise
966  */
967 dbus_bool_t
968 _dbus_header_load (DBusHeader        *header,
969                    DBusValidationMode mode,
970                    DBusValidity      *validity,
971                    int                byte_order,
972                    int                fields_array_len,
973                    int                header_len,
974                    int                body_len,
975                    const DBusString  *str,
976                    int                start,
977                    int                len)
978 {
979   int leftover;
980   DBusValidity v;
981   DBusTypeReader reader;
982   DBusTypeReader array_reader;
983   unsigned char v_byte;
984   dbus_uint32_t v_uint32;
985   dbus_uint32_t serial;
986   int padding_start;
987   int padding_len;
988   int i;
989
990   _dbus_assert (start == (int) _DBUS_ALIGN_VALUE (start, 8));
991   _dbus_assert (header_len <= len);
992   _dbus_assert (_dbus_string_get_length (&header->data) == 0);
993
994   if (!_dbus_string_copy_len (str, start, header_len, &header->data, 0))
995     {
996       _dbus_verbose ("Failed to copy buffer into new header\n");
997       *validity = DBUS_VALIDITY_UNKNOWN_OOM_ERROR;
998       return FALSE;
999     }
1000
1001   if (mode == DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
1002     {
1003       leftover = len - header_len - body_len - start;
1004     }
1005   else
1006     {
1007       v = _dbus_validate_body_with_reason (&_dbus_header_signature_str, 0,
1008                                            byte_order,
1009                                            &leftover,
1010                                            str, start, len);
1011       
1012       if (v != DBUS_VALID)
1013         {
1014           *validity = v;
1015           goto invalid;
1016         }
1017     }
1018
1019   _dbus_assert (leftover < len);
1020
1021   padding_len = header_len - (FIRST_FIELD_OFFSET + fields_array_len);
1022   padding_start = start + FIRST_FIELD_OFFSET + fields_array_len;
1023   _dbus_assert (start + header_len == (int) _DBUS_ALIGN_VALUE (padding_start, 8));
1024   _dbus_assert (start + header_len == padding_start + padding_len);
1025
1026   if (mode != DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
1027     {
1028       if (!_dbus_string_validate_nul (str, padding_start, padding_len))
1029         {
1030           *validity = DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL;
1031           goto invalid;
1032         }
1033     }
1034
1035   header->padding = padding_len;
1036
1037   if (mode == DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
1038     {
1039       *validity = DBUS_VALID;
1040       return TRUE;
1041     }
1042
1043   /* We now know the data is well-formed, but we have to check that
1044    * it's valid.
1045    */
1046
1047   _dbus_type_reader_init (&reader,
1048                           byte_order,
1049                           &_dbus_header_signature_str, 0,
1050                           str, start);
1051
1052   /* BYTE ORDER */
1053   _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_BYTE);
1054   _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == BYTE_ORDER_OFFSET);
1055   _dbus_type_reader_read_basic (&reader, &v_byte);
1056   _dbus_type_reader_next (&reader);
1057
1058   _dbus_assert (v_byte == byte_order);
1059   header->byte_order = byte_order;
1060
1061   /* MESSAGE TYPE */
1062   _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_BYTE);
1063   _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == TYPE_OFFSET);
1064   _dbus_type_reader_read_basic (&reader, &v_byte);
1065   _dbus_type_reader_next (&reader);
1066
1067   /* unknown message types are supposed to be ignored, so only validation here is
1068    * that it isn't invalid
1069    */
1070   if (v_byte == DBUS_MESSAGE_TYPE_INVALID)
1071     {
1072       *validity = DBUS_INVALID_BAD_MESSAGE_TYPE;
1073       goto invalid;
1074     }
1075
1076   /* FLAGS */
1077   _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_BYTE);
1078   _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == FLAGS_OFFSET);
1079   _dbus_type_reader_read_basic (&reader, &v_byte);
1080   _dbus_type_reader_next (&reader);
1081
1082   /* unknown flags should be ignored */
1083
1084   /* PROTOCOL VERSION */
1085   _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_BYTE);
1086   _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == VERSION_OFFSET);
1087   _dbus_type_reader_read_basic (&reader, &v_byte);
1088   _dbus_type_reader_next (&reader);
1089
1090   if (v_byte != DBUS_MAJOR_PROTOCOL_VERSION)
1091     {
1092       *validity = DBUS_INVALID_BAD_PROTOCOL_VERSION;
1093       goto invalid;
1094     }
1095
1096   /* BODY LENGTH */
1097   _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_UINT32);
1098   _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == BODY_LENGTH_OFFSET);
1099   _dbus_type_reader_read_basic (&reader, &v_uint32);
1100   _dbus_type_reader_next (&reader);
1101
1102   _dbus_assert (body_len == (signed) v_uint32);
1103
1104   /* SERIAL */
1105   _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_UINT32);
1106   _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == SERIAL_OFFSET);
1107   _dbus_type_reader_read_basic (&reader, &serial);
1108   _dbus_type_reader_next (&reader);
1109
1110   if (serial == 0)
1111     {
1112       *validity = DBUS_INVALID_BAD_SERIAL;
1113       goto invalid;
1114     }
1115
1116   _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_ARRAY);
1117   _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == FIELDS_ARRAY_LENGTH_OFFSET);
1118
1119   _dbus_type_reader_recurse (&reader, &array_reader);
1120   while (_dbus_type_reader_get_current_type (&array_reader) != DBUS_TYPE_INVALID)
1121     {
1122       DBusTypeReader struct_reader;
1123       DBusTypeReader variant_reader;
1124       unsigned char field_code;
1125
1126       _dbus_assert (_dbus_type_reader_get_current_type (&array_reader) == DBUS_TYPE_STRUCT);
1127
1128       _dbus_type_reader_recurse (&array_reader, &struct_reader);
1129
1130       _dbus_assert (_dbus_type_reader_get_current_type (&struct_reader) == DBUS_TYPE_BYTE);
1131       _dbus_type_reader_read_basic (&struct_reader, &field_code);
1132       _dbus_type_reader_next (&struct_reader);
1133
1134       if (field_code == DBUS_HEADER_FIELD_INVALID)
1135         {
1136           _dbus_verbose ("invalid header field code\n");
1137           *validity = DBUS_INVALID_HEADER_FIELD_CODE;
1138           goto invalid;
1139         }
1140
1141       if (field_code > DBUS_HEADER_FIELD_LAST)
1142         {
1143           _dbus_verbose ("unknown header field code %d, skipping\n",
1144                          field_code);
1145           goto next_field;
1146         }
1147
1148       _dbus_assert (_dbus_type_reader_get_current_type (&struct_reader) == DBUS_TYPE_VARIANT);
1149       _dbus_type_reader_recurse (&struct_reader, &variant_reader);
1150
1151       v = load_and_validate_field (header, field_code, &variant_reader);
1152       if (v != DBUS_VALID)
1153         {
1154           _dbus_verbose ("Field %d was invalid\n", field_code);
1155           *validity = v;
1156           goto invalid;
1157         }
1158
1159     next_field:
1160       _dbus_type_reader_next (&array_reader);
1161     }
1162
1163   /* Anything we didn't fill in is now known not to exist */
1164   i = 0;
1165   while (i <= DBUS_HEADER_FIELD_LAST)
1166     {
1167       if (header->fields[i].value_pos == _DBUS_HEADER_FIELD_VALUE_UNKNOWN)
1168         header->fields[i].value_pos = _DBUS_HEADER_FIELD_VALUE_NONEXISTENT;
1169       ++i;
1170     }
1171
1172   v = check_mandatory_fields (header);
1173   if (v != DBUS_VALID)
1174     {
1175       _dbus_verbose ("Mandatory fields were missing, code %d\n", v);
1176       *validity = v;
1177       goto invalid;
1178     }
1179
1180   *validity = DBUS_VALID;
1181   return TRUE;
1182
1183  invalid:
1184   _dbus_string_set_length (&header->data, 0);
1185   return FALSE;
1186 }
1187
1188 /**
1189  * Fills in the correct body length.
1190  *
1191  * @param header the header
1192  * @param body_len the length of the body
1193  */
1194 void
1195 _dbus_header_update_lengths (DBusHeader *header,
1196                              int         body_len)
1197 {
1198   _dbus_marshal_set_uint32 (&header->data,
1199                             BODY_LENGTH_OFFSET,
1200                             body_len,
1201                             header->byte_order);
1202 }
1203
1204 static dbus_bool_t
1205 find_field_for_modification (DBusHeader     *header,
1206                              int             field,
1207                              DBusTypeReader *reader,
1208                              DBusTypeReader *realign_root)
1209 {
1210   dbus_bool_t retval;
1211
1212   retval = FALSE;
1213
1214   _dbus_type_reader_init (realign_root,
1215                           header->byte_order,
1216                           &_dbus_header_signature_str,
1217                           FIELDS_ARRAY_SIGNATURE_OFFSET,
1218                           &header->data,
1219                           FIELDS_ARRAY_LENGTH_OFFSET);
1220
1221   _dbus_type_reader_recurse (realign_root, reader);
1222
1223   while (_dbus_type_reader_get_current_type (reader) != DBUS_TYPE_INVALID)
1224     {
1225       DBusTypeReader sub;
1226       unsigned char field_code;
1227
1228       _dbus_type_reader_recurse (reader, &sub);
1229
1230       _dbus_assert (_dbus_type_reader_get_current_type (&sub) == DBUS_TYPE_BYTE);
1231       _dbus_type_reader_read_basic (&sub, &field_code);
1232
1233       if (field_code == (unsigned) field)
1234         {
1235           _dbus_assert (_dbus_type_reader_get_current_type (reader) == DBUS_TYPE_STRUCT);
1236           retval = TRUE;
1237           goto done;
1238         }
1239
1240       _dbus_type_reader_next (reader);
1241     }
1242
1243  done:
1244   return retval;
1245 }
1246
1247 /**
1248  * Sets the value of a field with basic type. If the value is a string
1249  * value, it isn't allowed to be #NULL. If the field doesn't exist,
1250  * it will be created.
1251  *
1252  * @param header the header
1253  * @param field the field to set
1254  * @param type the type of the value
1255  * @param value the value as for _dbus_marshal_set_basic()
1256  * @returns #FALSE if no memory
1257  */
1258 dbus_bool_t
1259 _dbus_header_set_field_basic (DBusHeader       *header,
1260                               int               field,
1261                               int               type,
1262                               const void       *value)
1263 {
1264   _dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
1265
1266   if (!reserve_header_padding (header))
1267     return FALSE;
1268
1269   /* If the field exists we set, otherwise we append */
1270   if (_dbus_header_cache_check (header, field))
1271     {
1272       DBusTypeReader reader;
1273       DBusTypeReader realign_root;
1274
1275       if (!find_field_for_modification (header, field,
1276                                         &reader, &realign_root))
1277         _dbus_assert_not_reached ("field was marked present in cache but wasn't found");
1278
1279       if (!set_basic_field (&reader, field, type, value, &realign_root))
1280         return FALSE;
1281     }
1282   else
1283     {
1284       DBusTypeWriter writer;
1285       DBusTypeWriter array;
1286
1287       _dbus_type_writer_init_values_only (&writer,
1288                                           header->byte_order,
1289                                           &_dbus_header_signature_str,
1290                                           FIELDS_ARRAY_SIGNATURE_OFFSET,
1291                                           &header->data,
1292                                           FIELDS_ARRAY_LENGTH_OFFSET);
1293
1294       /* recurse into array without creating a new length, and jump to
1295        * end of array.
1296        */
1297       if (!_dbus_type_writer_append_array (&writer,
1298                                            &_dbus_header_signature_str,
1299                                            FIELDS_ARRAY_ELEMENT_SIGNATURE_OFFSET,
1300                                            &array))
1301         _dbus_assert_not_reached ("recurse into ARRAY should not have used memory");
1302
1303       _dbus_assert (array.u.array.len_pos == FIELDS_ARRAY_LENGTH_OFFSET);
1304       _dbus_assert (array.u.array.start_pos == FIRST_FIELD_OFFSET);
1305       _dbus_assert (array.value_pos == HEADER_END_BEFORE_PADDING (header));
1306
1307       if (!write_basic_field (&array,
1308                               field, type, value))
1309         return FALSE;
1310
1311       if (!_dbus_type_writer_unrecurse (&writer, &array))
1312         _dbus_assert_not_reached ("unrecurse from ARRAY should not have used memory");
1313     }
1314
1315   correct_header_padding (header);
1316
1317   /* We could be smarter about this (only invalidate fields after the
1318    * one we modified, or even only if the one we modified changed
1319    * length). But this hack is a start.
1320    */
1321   _dbus_header_cache_invalidate_all (header);
1322
1323   return TRUE;
1324 }
1325
1326 /**
1327  * Gets the value of a field with basic type. If the field
1328  * doesn't exist, returns #FALSE, otherwise returns #TRUE.
1329  *
1330  * @param header the header
1331  * @param field the field to get
1332  * @param type the type of the value
1333  * @param value the value as for _dbus_marshal_read_basic()
1334  * @returns #FALSE if the field doesn't exist
1335  */
1336 dbus_bool_t
1337 _dbus_header_get_field_basic (DBusHeader    *header,
1338                               int            field,
1339                               int            type,
1340                               void          *value)
1341 {
1342   _dbus_assert (field != DBUS_HEADER_FIELD_INVALID);
1343   _dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
1344   _dbus_assert (_dbus_header_field_types[field].code == field);
1345   /* in light of this you might ask why the type is passed in;
1346    * the only rationale I can think of is so the caller has
1347    * to specify its expectation and breaks if we change it
1348    */
1349   _dbus_assert (type == EXPECTED_TYPE_OF_FIELD (field));
1350
1351   if (!_dbus_header_cache_check (header, field))
1352     return FALSE;
1353
1354   _dbus_assert (header->fields[field].value_pos >= 0);
1355
1356   _dbus_marshal_read_basic (&header->data,
1357                             header->fields[field].value_pos,
1358                             type, value, header->byte_order,
1359                             NULL);
1360
1361   return TRUE;
1362 }
1363
1364 /**
1365  * Gets the raw marshaled data for a field. If the field doesn't
1366  * exist, returns #FALSE, otherwise returns #TRUE.  Returns the start
1367  * of the marshaled data, i.e. usually the byte where the length
1368  * starts (for strings and arrays) or for basic types just the value
1369  * itself.
1370  *
1371  * @param header the header
1372  * @param field the field to get
1373  * @param str return location for the data string
1374  * @param pos return location for start of field value
1375  * @returns #FALSE if the field doesn't exist
1376  */
1377 dbus_bool_t
1378 _dbus_header_get_field_raw (DBusHeader        *header,
1379                             int                field,
1380                             const DBusString **str,
1381                             int               *pos)
1382 {
1383   if (!_dbus_header_cache_check (header, field))
1384     return FALSE;
1385
1386   if (str)
1387     *str = &header->data;
1388   if (pos)
1389     *pos = header->fields[field].value_pos;
1390
1391   return TRUE;
1392 }
1393
1394 /**
1395  * Deletes a field, if it exists.
1396  *
1397  * @param header the header
1398  * @param field the field to delete
1399  * @returns #FALSE if no memory
1400  */
1401 dbus_bool_t
1402 _dbus_header_delete_field (DBusHeader *header,
1403                            int         field)
1404 {
1405   DBusTypeReader reader;
1406   DBusTypeReader realign_root;
1407
1408   if (_dbus_header_cache_known_nonexistent (header, field))
1409     return TRUE; /* nothing to do */
1410
1411   /* Scan to the field we want, delete and realign, reappend
1412    * padding. Field may turn out not to exist.
1413    */
1414   if (!find_field_for_modification (header, field,
1415                                     &reader, &realign_root))
1416     return TRUE; /* nothing to do */
1417
1418   if (!reserve_header_padding (header))
1419     return FALSE;
1420
1421   if (!_dbus_type_reader_delete (&reader,
1422                                  &realign_root))
1423     return FALSE;
1424
1425   correct_header_padding (header);
1426
1427   _dbus_header_cache_invalidate_all (header);
1428
1429   _dbus_assert (!_dbus_header_cache_check (header, field)); /* Expensive assertion ... */
1430
1431   return TRUE;
1432 }
1433
1434 /**
1435  * Toggles a message flag bit, turning on the bit if value = TRUE and
1436  * flipping it off if value = FALSE.
1437  *
1438  * @param header the header
1439  * @param flag the message flag to toggle
1440  * @param value toggle on or off
1441  */
1442 void
1443 _dbus_header_toggle_flag (DBusHeader   *header,
1444                           dbus_uint32_t flag,
1445                           dbus_bool_t   value)
1446 {
1447   unsigned char *flags_p;
1448
1449   flags_p = _dbus_string_get_data_len (&header->data, FLAGS_OFFSET, 1);
1450
1451   if (value)
1452     *flags_p |= flag;
1453   else
1454     *flags_p &= ~flag;
1455 }
1456
1457 /**
1458  * Gets a message flag bit, returning TRUE if the bit is set.
1459  *
1460  * @param header the header
1461  * @param flag the message flag to get
1462  * @returns #TRUE if the flag is set
1463  */
1464 dbus_bool_t
1465 _dbus_header_get_flag (DBusHeader   *header,
1466                        dbus_uint32_t flag)
1467 {
1468   const unsigned char *flags_p;
1469
1470   flags_p = _dbus_string_get_const_data_len (&header->data, FLAGS_OFFSET, 1);
1471
1472   return (*flags_p & flag) != 0;
1473 }
1474
1475 /**
1476  * Swaps the header into the given order if required.
1477  *
1478  * @param header the header
1479  * @param new_order the new byte order
1480  */
1481 void
1482 _dbus_header_byteswap (DBusHeader *header,
1483                        int         new_order)
1484 {
1485   char byte_order;
1486
1487   byte_order = _dbus_header_get_byte_order (header);
1488
1489   if (byte_order == new_order)
1490     return;
1491
1492   _dbus_marshal_byteswap (&_dbus_header_signature_str,
1493                           0, byte_order,
1494                           new_order,
1495                           &header->data, 0);
1496
1497   _dbus_string_set_byte (&header->data, BYTE_ORDER_OFFSET, new_order);
1498 }
1499
1500 /** @} */
1501
1502 #ifdef DBUS_BUILD_TESTS
1503 #include "dbus-test.h"
1504 #include <stdio.h>
1505
1506 dbus_bool_t
1507 _dbus_marshal_header_test (void)
1508 {
1509
1510   return TRUE;
1511 }
1512
1513 #endif /* DBUS_BUILD_TESTS */