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