Fix g_autoptr_cleanup_gstring_free( ) argument to avoid of confliting arument name
[platform/upstream/glib.git] / gio / gdbusmessage.c
1 /* GDBus - GLib D-Bus Library
2  *
3  * Copyright (C) 2008-2010 Red Hat, Inc.
4  *
5  * SPDX-License-Identifier: LGPL-2.1-or-later
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General
18  * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
19  *
20  * Author: David Zeuthen <davidz@redhat.com>
21  */
22
23 /* Uncomment to debug serializer code */
24 /* #define DEBUG_SERIALIZER */
25
26 #include "config.h"
27
28 #include <string.h>
29 #include <errno.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32
33 #if MAJOR_IN_MKDEV
34 #include <sys/mkdev.h>
35 #elif MAJOR_IN_SYSMACROS
36 #include <sys/sysmacros.h>
37 #elif MAJOR_IN_TYPES
38 #include <sys/types.h>
39 #else
40 #define MAJOR_MINOR_NOT_FOUND 1
41 #endif
42
43 #include "gdbusutils.h"
44 #include "gdbusmessage.h"
45 #include "gdbuserror.h"
46 #include "gioenumtypes.h"
47 #include "ginputstream.h"
48 #include "gdatainputstream.h"
49 #include "gmemoryinputstream.h"
50 #include "goutputstream.h"
51 #include "gdataoutputstream.h"
52 #include "gmemoryoutputstream.h"
53 #include "gseekable.h"
54 #include "gioerror.h"
55 #include "gdbusprivate.h"
56 #include "gutilsprivate.h"
57
58 #ifdef G_OS_UNIX
59 #include "gunixfdlist.h"
60 #endif
61
62 #include "glibintl.h"
63
64 /* See https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-marshaling-signature
65  * This is 64 containers plus 1 value within them. */
66 #define G_DBUS_MAX_TYPE_DEPTH (64 + 1)
67
68 typedef struct _GMemoryBuffer GMemoryBuffer;
69 struct _GMemoryBuffer
70 {
71   gsize len;
72   gsize valid_len;
73   gsize pos;
74   gchar *data;
75   GDataStreamByteOrder byte_order;
76 };
77
78 static gboolean
79 g_memory_buffer_is_byteswapped (GMemoryBuffer *mbuf)
80 {
81 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
82   return mbuf->byte_order == G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN;
83 #else
84   return mbuf->byte_order == G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN;
85 #endif
86 }
87
88 static guchar
89 g_memory_buffer_read_byte (GMemoryBuffer  *mbuf,
90                            GError        **error)
91 {
92   g_return_val_if_fail (error == NULL || *error == NULL, 0);
93
94   if (mbuf->pos >= mbuf->valid_len)
95     {
96       g_set_error (error,
97                    G_IO_ERROR,
98                    G_IO_ERROR_INVALID_ARGUMENT,
99                    "Unexpected end of message while reading byte.");
100       return 0;
101     }
102   return mbuf->data [mbuf->pos++];
103 }
104
105 static gint16
106 g_memory_buffer_read_int16 (GMemoryBuffer  *mbuf,
107                             GError        **error)
108 {
109   gint16 v;
110
111   g_return_val_if_fail (error == NULL || *error == NULL, -1);
112
113   if (mbuf->pos > mbuf->valid_len - 2)
114     {
115       g_set_error (error,
116                    G_IO_ERROR,
117                    G_IO_ERROR_INVALID_ARGUMENT,
118                    "Unexpected end of message while reading int16.");
119       return 0;
120     }
121
122   memcpy (&v, mbuf->data + mbuf->pos, 2);
123   mbuf->pos += 2;
124
125   if (g_memory_buffer_is_byteswapped (mbuf))
126     v = GUINT16_SWAP_LE_BE (v);
127
128   return v;
129 }
130
131 static guint16
132 g_memory_buffer_read_uint16 (GMemoryBuffer  *mbuf,
133                              GError        **error)
134 {
135   guint16 v;
136
137   g_return_val_if_fail (error == NULL || *error == NULL, 0);
138
139   if (mbuf->pos > mbuf->valid_len - 2)
140     {
141       g_set_error (error,
142                    G_IO_ERROR,
143                    G_IO_ERROR_INVALID_ARGUMENT,
144                    "Unexpected end of message while reading uint16.");
145       return 0;
146     }
147
148   memcpy (&v, mbuf->data + mbuf->pos, 2);
149   mbuf->pos += 2;
150
151   if (g_memory_buffer_is_byteswapped (mbuf))
152     v = GUINT16_SWAP_LE_BE (v);
153
154   return v;
155 }
156
157 static gint32
158 g_memory_buffer_read_int32 (GMemoryBuffer  *mbuf,
159                             GError        **error)
160 {
161   gint32 v;
162
163   g_return_val_if_fail (error == NULL || *error == NULL, -1);
164
165   if (mbuf->pos > mbuf->valid_len - 4)
166     {
167       g_set_error (error,
168                    G_IO_ERROR,
169                    G_IO_ERROR_INVALID_ARGUMENT,
170                    "Unexpected end of message while reading int32.");
171       return 0;
172     }
173
174   memcpy (&v, mbuf->data + mbuf->pos, 4);
175   mbuf->pos += 4;
176
177   if (g_memory_buffer_is_byteswapped (mbuf))
178     v = GUINT32_SWAP_LE_BE (v);
179
180   return v;
181 }
182
183 static guint32
184 g_memory_buffer_read_uint32 (GMemoryBuffer  *mbuf,
185                              GError        **error)
186 {
187   guint32 v;
188
189   g_return_val_if_fail (error == NULL || *error == NULL, 0);
190
191   if (mbuf->pos > mbuf->valid_len - 4)
192     {
193       g_set_error (error,
194                    G_IO_ERROR,
195                    G_IO_ERROR_INVALID_ARGUMENT,
196                    "Unexpected end of message while reading uint32.");
197       return 0;
198     }
199
200   memcpy (&v, mbuf->data + mbuf->pos, 4);
201   mbuf->pos += 4;
202
203   if (g_memory_buffer_is_byteswapped (mbuf))
204     v = GUINT32_SWAP_LE_BE (v);
205
206   return v;
207 }
208
209 static gint64
210 g_memory_buffer_read_int64 (GMemoryBuffer  *mbuf,
211                             GError        **error)
212 {
213   gint64 v;
214
215   g_return_val_if_fail (error == NULL || *error == NULL, -1);
216
217   if (mbuf->pos > mbuf->valid_len - 8)
218     {
219       g_set_error (error,
220                    G_IO_ERROR,
221                    G_IO_ERROR_INVALID_ARGUMENT,
222                    "Unexpected end of message while reading int64.");
223       return 0;
224     }
225
226   memcpy (&v, mbuf->data + mbuf->pos, 8);
227   mbuf->pos += 8;
228
229   if (g_memory_buffer_is_byteswapped (mbuf))
230     v = GUINT64_SWAP_LE_BE (v);
231
232   return v;
233 }
234
235 static guint64
236 g_memory_buffer_read_uint64 (GMemoryBuffer  *mbuf,
237                              GError        **error)
238 {
239   guint64 v;
240
241   g_return_val_if_fail (error == NULL || *error == NULL, 0);
242
243   if (mbuf->pos > mbuf->valid_len - 8)
244     {
245       g_set_error (error,
246                    G_IO_ERROR,
247                    G_IO_ERROR_INVALID_ARGUMENT,
248                    "Unexpected end of message while reading uint64.");
249       return 0;
250     }
251
252   memcpy (&v, mbuf->data + mbuf->pos, 8);
253   mbuf->pos += 8;
254
255   if (g_memory_buffer_is_byteswapped (mbuf))
256     v = GUINT64_SWAP_LE_BE (v);
257
258   return v;
259 }
260
261 #define MIN_ARRAY_SIZE  128
262
263 static void
264 array_resize (GMemoryBuffer  *mbuf,
265               gsize           size)
266 {
267   gpointer data;
268   gsize len;
269
270   if (mbuf->len == size)
271     return;
272
273   len = mbuf->len;
274   data = g_realloc (mbuf->data, size);
275
276   if (size > len)
277     memset ((guint8 *)data + len, 0, size - len);
278
279   mbuf->data = data;
280   mbuf->len = size;
281
282   if (mbuf->len < mbuf->valid_len)
283     mbuf->valid_len = mbuf->len;
284 }
285
286 static gboolean
287 g_memory_buffer_write (GMemoryBuffer  *mbuf,
288                        const void     *buffer,
289                        gsize           count)
290 {
291   guint8   *dest;
292   gsize new_size;
293
294   if (count == 0)
295     return TRUE;
296
297   /* Check for address space overflow, but only if the buffer is resizable.
298      Otherwise we just do a short write and don't worry. */
299   if (mbuf->pos + count < mbuf->pos)
300     return FALSE;
301
302   if (mbuf->pos + count > mbuf->len)
303     {
304       /* At least enough to fit the write, rounded up
305              for greater than linear growth.
306          TODO: This wastes a lot of memory at large buffer sizes.
307                Figure out a more rational allocation strategy. */
308       new_size = g_nearest_pow (mbuf->pos + count);
309       /* Check for overflow again. We have checked if
310          pos + count > G_MAXSIZE, but now check if g_nearest_pow () has
311          overflowed */
312       if (new_size == 0)
313         return FALSE;
314
315       new_size = MAX (new_size, MIN_ARRAY_SIZE);
316       array_resize (mbuf, new_size);
317     }
318
319   dest = (guint8 *)mbuf->data + mbuf->pos;
320   memcpy (dest, buffer, count);
321   mbuf->pos += count;
322
323   if (mbuf->pos > mbuf->valid_len)
324     mbuf->valid_len = mbuf->pos;
325
326   return TRUE;
327 }
328
329 static gboolean
330 g_memory_buffer_put_byte (GMemoryBuffer  *mbuf,
331                           guchar          data)
332 {
333   return g_memory_buffer_write (mbuf, &data, 1);
334 }
335
336 static gboolean
337 g_memory_buffer_put_int16 (GMemoryBuffer  *mbuf,
338                            gint16          data)
339 {
340   switch (mbuf->byte_order)
341     {
342     case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
343       data = GINT16_TO_BE (data);
344       break;
345     case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
346       data = GINT16_TO_LE (data);
347       break;
348     case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
349     default:
350       break;
351     }
352   
353   return g_memory_buffer_write (mbuf, &data, 2);
354 }
355
356 static gboolean
357 g_memory_buffer_put_uint16 (GMemoryBuffer  *mbuf,
358                             guint16         data)
359 {
360   switch (mbuf->byte_order)
361     {
362     case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
363       data = GUINT16_TO_BE (data);
364       break;
365     case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
366       data = GUINT16_TO_LE (data);
367       break;
368     case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
369     default:
370       break;
371     }
372   
373   return g_memory_buffer_write (mbuf, &data, 2);
374 }
375
376 static gboolean
377 g_memory_buffer_put_int32 (GMemoryBuffer  *mbuf,
378                            gint32          data)
379 {
380   switch (mbuf->byte_order)
381     {
382     case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
383       data = GINT32_TO_BE (data);
384       break;
385     case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
386       data = GINT32_TO_LE (data);
387       break;
388     case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
389     default:
390       break;
391     }
392   
393   return g_memory_buffer_write (mbuf, &data, 4);
394 }
395
396 static gboolean
397 g_memory_buffer_put_uint32 (GMemoryBuffer  *mbuf,
398                             guint32         data)
399 {
400   switch (mbuf->byte_order)
401     {
402     case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
403       data = GUINT32_TO_BE (data);
404       break;
405     case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
406       data = GUINT32_TO_LE (data);
407       break;
408     case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
409     default:
410       break;
411     }
412   
413   return g_memory_buffer_write (mbuf, &data, 4);
414 }
415
416 static gboolean
417 g_memory_buffer_put_int64 (GMemoryBuffer  *mbuf,
418                            gint64          data)
419 {
420   switch (mbuf->byte_order)
421     {
422     case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
423       data = GINT64_TO_BE (data);
424       break;
425     case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
426       data = GINT64_TO_LE (data);
427       break;
428     case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
429     default:
430       break;
431     }
432   
433   return g_memory_buffer_write (mbuf, &data, 8);
434 }
435
436 static gboolean
437 g_memory_buffer_put_uint64 (GMemoryBuffer  *mbuf,
438                             guint64         data)
439 {
440   switch (mbuf->byte_order)
441     {
442     case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
443       data = GUINT64_TO_BE (data);
444       break;
445     case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
446       data = GUINT64_TO_LE (data);
447       break;
448     case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
449     default:
450       break;
451     }
452   
453   return g_memory_buffer_write (mbuf, &data, 8);
454 }
455
456 static gboolean
457 g_memory_buffer_put_string (GMemoryBuffer  *mbuf,
458                             const char     *str)
459 {
460   g_return_val_if_fail (str != NULL, FALSE);
461
462   return g_memory_buffer_write (mbuf, str, strlen (str));
463 }
464
465 typedef struct _GDBusMessageClass GDBusMessageClass;
466
467 /**
468  * GDBusMessageClass:
469  *
470  * Class structure for #GDBusMessage.
471  *
472  * Since: 2.26
473  */
474 struct _GDBusMessageClass
475 {
476   /*< private >*/
477   GObjectClass parent_class;
478 };
479
480 /**
481  * GDBusMessage:
482  *
483  * A type for representing D-Bus messages that can be sent or received
484  * on a [class@Gio.DBusConnection].
485  *
486  * Since: 2.26
487  */
488 struct _GDBusMessage
489 {
490   /*< private >*/
491   GObject parent_instance;
492
493   GDBusMessageType type;
494   GDBusMessageFlags flags;
495   gboolean locked;
496   GDBusMessageByteOrder byte_order;
497   guchar major_protocol_version;
498   guint32 serial;
499   GHashTable *headers;
500   GVariant *body;
501   GVariant *arg0_cache;  /* (nullable) (owned) */
502 #ifdef G_OS_UNIX
503   GUnixFDList *fd_list;
504 #endif
505 };
506
507 enum
508 {
509   PROP_0,
510   PROP_LOCKED
511 };
512
513 G_DEFINE_TYPE (GDBusMessage, g_dbus_message, G_TYPE_OBJECT)
514
515 static void
516 g_dbus_message_finalize (GObject *object)
517 {
518   GDBusMessage *message = G_DBUS_MESSAGE (object);
519
520   if (message->headers != NULL)
521     g_hash_table_unref (message->headers);
522   if (message->body != NULL)
523     g_variant_unref (message->body);
524   g_clear_pointer (&message->arg0_cache, g_variant_unref);
525 #ifdef G_OS_UNIX
526   if (message->fd_list != NULL)
527     g_object_unref (message->fd_list);
528 #endif
529
530   if (G_OBJECT_CLASS (g_dbus_message_parent_class)->finalize != NULL)
531     G_OBJECT_CLASS (g_dbus_message_parent_class)->finalize (object);
532 }
533
534 static void
535 g_dbus_message_get_property (GObject    *object,
536                              guint       prop_id,
537                              GValue     *value,
538                              GParamSpec *pspec)
539 {
540   GDBusMessage *message = G_DBUS_MESSAGE (object);
541
542   switch (prop_id)
543     {
544     case PROP_LOCKED:
545       g_value_set_boolean (value, g_dbus_message_get_locked (message));
546       break;
547
548     default:
549       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
550       break;
551     }
552 }
553
554 static void
555 g_dbus_message_class_init (GDBusMessageClass *klass)
556 {
557   GObjectClass *gobject_class;
558
559   gobject_class = G_OBJECT_CLASS (klass);
560   gobject_class->finalize     = g_dbus_message_finalize;
561   gobject_class->get_property = g_dbus_message_get_property;
562
563   /**
564    * GDBusConnection:locked:
565    *
566    * A boolean specifying whether the message is locked.
567    *
568    * Since: 2.26
569    */
570   g_object_class_install_property (gobject_class,
571                                    PROP_LOCKED,
572                                    g_param_spec_boolean ("locked", NULL, NULL,
573                                                          FALSE,
574                                                          G_PARAM_READABLE |
575                                                          G_PARAM_STATIC_NAME |
576                                                          G_PARAM_STATIC_BLURB |
577                                                          G_PARAM_STATIC_NICK));
578 }
579
580 static void
581 g_dbus_message_init (GDBusMessage *message)
582 {
583   /* Any D-Bus implementation is supposed to handle both Big and
584    * Little Endian encodings and the Endianness is part of the D-Bus
585    * message - we prefer to use Big Endian (since it's Network Byte
586    * Order and just easier to read for humans) but if the machine is
587    * Little Endian we use that for performance reasons.
588    */
589 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
590   message->byte_order = G_DBUS_MESSAGE_BYTE_ORDER_LITTLE_ENDIAN;
591 #else
592   /* this could also be G_PDP_ENDIAN */
593   message->byte_order = G_DBUS_MESSAGE_BYTE_ORDER_BIG_ENDIAN;
594 #endif
595   message->headers = g_hash_table_new_full (g_direct_hash,
596                                             g_direct_equal,
597                                             NULL,
598                                             (GDestroyNotify) g_variant_unref);
599 }
600
601 /**
602  * g_dbus_message_new:
603  *
604  * Creates a new empty #GDBusMessage.
605  *
606  * Returns: A #GDBusMessage. Free with g_object_unref().
607  *
608  * Since: 2.26
609  */
610 GDBusMessage *
611 g_dbus_message_new (void)
612 {
613   return g_object_new (G_TYPE_DBUS_MESSAGE, NULL);
614 }
615
616 /**
617  * g_dbus_message_new_method_call:
618  * @name: (nullable): A valid D-Bus name or %NULL.
619  * @path: A valid object path.
620  * @interface_: (nullable): A valid D-Bus interface name or %NULL.
621  * @method: A valid method name.
622  *
623  * Creates a new #GDBusMessage for a method call.
624  *
625  * Returns: A #GDBusMessage. Free with g_object_unref().
626  *
627  * Since: 2.26
628  */
629 GDBusMessage *
630 g_dbus_message_new_method_call (const gchar *name,
631                                 const gchar *path,
632                                 const gchar *interface_,
633                                 const gchar *method)
634 {
635   GDBusMessage *message;
636
637   g_return_val_if_fail (name == NULL || g_dbus_is_name (name), NULL);
638   g_return_val_if_fail (g_variant_is_object_path (path), NULL);
639   g_return_val_if_fail (g_dbus_is_member_name (method), NULL);
640   g_return_val_if_fail (interface_ == NULL || g_dbus_is_interface_name (interface_), NULL);
641
642   message = g_dbus_message_new ();
643   message->type = G_DBUS_MESSAGE_TYPE_METHOD_CALL;
644
645   if (name != NULL)
646     g_dbus_message_set_destination (message, name);
647   g_dbus_message_set_path (message, path);
648   g_dbus_message_set_member (message, method);
649   if (interface_ != NULL)
650     g_dbus_message_set_interface (message, interface_);
651
652   return message;
653 }
654
655 /**
656  * g_dbus_message_new_signal:
657  * @path: A valid object path.
658  * @interface_: A valid D-Bus interface name.
659  * @signal: A valid signal name.
660  *
661  * Creates a new #GDBusMessage for a signal emission.
662  *
663  * Returns: A #GDBusMessage. Free with g_object_unref().
664  *
665  * Since: 2.26
666  */
667 GDBusMessage *
668 g_dbus_message_new_signal (const gchar  *path,
669                            const gchar  *interface_,
670                            const gchar  *signal)
671 {
672   GDBusMessage *message;
673
674   g_return_val_if_fail (g_variant_is_object_path (path), NULL);
675   g_return_val_if_fail (g_dbus_is_member_name (signal), NULL);
676   g_return_val_if_fail (g_dbus_is_interface_name (interface_), NULL);
677
678   message = g_dbus_message_new ();
679   message->type = G_DBUS_MESSAGE_TYPE_SIGNAL;
680   message->flags = G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED;
681
682   g_dbus_message_set_path (message, path);
683   g_dbus_message_set_member (message, signal);
684   g_dbus_message_set_interface (message, interface_);
685
686   return message;
687 }
688
689
690 /**
691  * g_dbus_message_new_method_reply:
692  * @method_call_message: A message of type %G_DBUS_MESSAGE_TYPE_METHOD_CALL to
693  * create a reply message to.
694  *
695  * Creates a new #GDBusMessage that is a reply to @method_call_message.
696  *
697  * Returns: (transfer full):  #GDBusMessage. Free with g_object_unref().
698  *
699  * Since: 2.26
700  */
701 GDBusMessage *
702 g_dbus_message_new_method_reply (GDBusMessage *method_call_message)
703 {
704   GDBusMessage *message;
705   const gchar *sender;
706
707   g_return_val_if_fail (G_IS_DBUS_MESSAGE (method_call_message), NULL);
708   g_return_val_if_fail (g_dbus_message_get_message_type (method_call_message) == G_DBUS_MESSAGE_TYPE_METHOD_CALL, NULL);
709   g_return_val_if_fail (g_dbus_message_get_serial (method_call_message) != 0, NULL);
710
711   message = g_dbus_message_new ();
712   message->type = G_DBUS_MESSAGE_TYPE_METHOD_RETURN;
713   message->flags = G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED;
714   /* reply with same endianness */
715   message->byte_order = method_call_message->byte_order;
716
717   g_dbus_message_set_reply_serial (message, g_dbus_message_get_serial (method_call_message));
718   sender = g_dbus_message_get_sender (method_call_message);
719   if (sender != NULL)
720     g_dbus_message_set_destination (message, sender);
721
722   return message;
723 }
724
725 /**
726  * g_dbus_message_new_method_error:
727  * @method_call_message: A message of type %G_DBUS_MESSAGE_TYPE_METHOD_CALL to
728  * create a reply message to.
729  * @error_name: A valid D-Bus error name.
730  * @error_message_format: The D-Bus error message in a printf() format.
731  * @...: Arguments for @error_message_format.
732  *
733  * Creates a new #GDBusMessage that is an error reply to @method_call_message.
734  *
735  * Returns: (transfer full): A #GDBusMessage. Free with g_object_unref().
736  *
737  * Since: 2.26
738  */
739 GDBusMessage *
740 g_dbus_message_new_method_error (GDBusMessage             *method_call_message,
741                                  const gchar              *error_name,
742                                  const gchar              *error_message_format,
743                                  ...)
744 {
745   GDBusMessage *ret;
746   va_list var_args;
747
748   va_start (var_args, error_message_format);
749   ret = g_dbus_message_new_method_error_valist (method_call_message,
750                                                 error_name,
751                                                 error_message_format,
752                                                 var_args);
753   va_end (var_args);
754
755   return ret;
756 }
757
758 /**
759  * g_dbus_message_new_method_error_literal:
760  * @method_call_message: A message of type %G_DBUS_MESSAGE_TYPE_METHOD_CALL to
761  * create a reply message to.
762  * @error_name: A valid D-Bus error name.
763  * @error_message: The D-Bus error message.
764  *
765  * Creates a new #GDBusMessage that is an error reply to @method_call_message.
766  *
767  * Returns: (transfer full): A #GDBusMessage. Free with g_object_unref().
768  *
769  * Since: 2.26
770  */
771 GDBusMessage *
772 g_dbus_message_new_method_error_literal (GDBusMessage  *method_call_message,
773                                          const gchar   *error_name,
774                                          const gchar   *error_message)
775 {
776   GDBusMessage *message;
777   const gchar *sender;
778
779   g_return_val_if_fail (G_IS_DBUS_MESSAGE (method_call_message), NULL);
780   g_return_val_if_fail (g_dbus_message_get_message_type (method_call_message) == G_DBUS_MESSAGE_TYPE_METHOD_CALL, NULL);
781   g_return_val_if_fail (g_dbus_message_get_serial (method_call_message) != 0, NULL);
782   g_return_val_if_fail (g_dbus_is_name (error_name), NULL);
783   g_return_val_if_fail (error_message != NULL, NULL);
784
785   message = g_dbus_message_new ();
786   message->type = G_DBUS_MESSAGE_TYPE_ERROR;
787   message->flags = G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED;
788   /* reply with same endianness */
789   message->byte_order = method_call_message->byte_order;
790
791   g_dbus_message_set_reply_serial (message, g_dbus_message_get_serial (method_call_message));
792   g_dbus_message_set_error_name (message, error_name);
793   g_dbus_message_set_body (message, g_variant_new ("(s)", error_message));
794
795   sender = g_dbus_message_get_sender (method_call_message);
796   if (sender != NULL)
797     g_dbus_message_set_destination (message, sender);
798
799   return message;
800 }
801
802 /**
803  * g_dbus_message_new_method_error_valist:
804  * @method_call_message: A message of type %G_DBUS_MESSAGE_TYPE_METHOD_CALL to
805  * create a reply message to.
806  * @error_name: A valid D-Bus error name.
807  * @error_message_format: The D-Bus error message in a printf() format.
808  * @var_args: Arguments for @error_message_format.
809  *
810  * Like g_dbus_message_new_method_error() but intended for language bindings.
811  *
812  * Returns: (transfer full): A #GDBusMessage. Free with g_object_unref().
813  *
814  * Since: 2.26
815  */
816 G_GNUC_PRINTF(3, 0)
817 GDBusMessage *
818 g_dbus_message_new_method_error_valist (GDBusMessage             *method_call_message,
819                                         const gchar              *error_name,
820                                         const gchar              *error_message_format,
821                                         va_list                   var_args)
822 {
823   GDBusMessage *ret;
824   gchar *error_message;
825   error_message = g_strdup_vprintf (error_message_format, var_args);
826   ret = g_dbus_message_new_method_error_literal (method_call_message,
827                                                  error_name,
828                                                  error_message);
829   g_free (error_message);
830   return ret;
831 }
832
833 /* ---------------------------------------------------------------------------------------------------- */
834
835 /**
836  * g_dbus_message_get_byte_order:
837  * @message: A #GDBusMessage.
838  *
839  * Gets the byte order of @message.
840  *
841  * Returns: The byte order.
842  */
843 GDBusMessageByteOrder
844 g_dbus_message_get_byte_order (GDBusMessage *message)
845 {
846   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), (GDBusMessageByteOrder) 0);
847   return message->byte_order;
848 }
849
850 /**
851  * g_dbus_message_set_byte_order:
852  * @message: A #GDBusMessage.
853  * @byte_order: The byte order.
854  *
855  * Sets the byte order of @message.
856  */
857 void
858 g_dbus_message_set_byte_order (GDBusMessage          *message,
859                                GDBusMessageByteOrder  byte_order)
860 {
861   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
862
863   if (message->locked)
864     {
865       g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
866       return;
867     }
868
869   message->byte_order = byte_order;
870 }
871
872 /* ---------------------------------------------------------------------------------------------------- */
873
874 /* TODO: need GI annotations to specify that any guchar value goes for the type */
875
876 /**
877  * g_dbus_message_get_message_type:
878  * @message: A #GDBusMessage.
879  *
880  * Gets the type of @message.
881  *
882  * Returns: A 8-bit unsigned integer (typically a value from the #GDBusMessageType enumeration).
883  *
884  * Since: 2.26
885  */
886 GDBusMessageType
887 g_dbus_message_get_message_type (GDBusMessage  *message)
888 {
889   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), G_DBUS_MESSAGE_TYPE_INVALID);
890   return message->type;
891 }
892
893 /**
894  * g_dbus_message_set_message_type:
895  * @message: A #GDBusMessage.
896  * @type: A 8-bit unsigned integer (typically a value from the #GDBusMessageType enumeration).
897  *
898  * Sets @message to be of @type.
899  *
900  * Since: 2.26
901  */
902 void
903 g_dbus_message_set_message_type (GDBusMessage      *message,
904                                  GDBusMessageType   type)
905 {
906   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
907   g_return_if_fail ((guint) type < 256);
908
909   if (message->locked)
910     {
911       g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
912       return;
913     }
914
915   message->type = type;
916 }
917
918 /* ---------------------------------------------------------------------------------------------------- */
919
920 /* TODO: need GI annotations to specify that any guchar value goes for flags */
921
922 /**
923  * g_dbus_message_get_flags:
924  * @message: A #GDBusMessage.
925  *
926  * Gets the flags for @message.
927  *
928  * Returns: Flags that are set (typically values from the #GDBusMessageFlags enumeration bitwise ORed together).
929  *
930  * Since: 2.26
931  */
932 GDBusMessageFlags
933 g_dbus_message_get_flags (GDBusMessage  *message)
934 {
935   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), G_DBUS_MESSAGE_FLAGS_NONE);
936   return message->flags;
937 }
938
939 /**
940  * g_dbus_message_set_flags:
941  * @message: A #GDBusMessage.
942  * @flags: Flags for @message that are set (typically values from the #GDBusMessageFlags
943  * enumeration bitwise ORed together).
944  *
945  * Sets the flags to set on @message.
946  *
947  * Since: 2.26
948  */
949 void
950 g_dbus_message_set_flags (GDBusMessage       *message,
951                           GDBusMessageFlags   flags)
952 {
953   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
954   g_return_if_fail ((guint) flags < 256);
955
956   if (message->locked)
957     {
958       g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
959       return;
960     }
961
962   message->flags = flags;
963 }
964
965 /* ---------------------------------------------------------------------------------------------------- */
966
967 /**
968  * g_dbus_message_get_serial:
969  * @message: A #GDBusMessage.
970  *
971  * Gets the serial for @message.
972  *
973  * Returns: A #guint32.
974  *
975  * Since: 2.26
976  */
977 guint32
978 g_dbus_message_get_serial (GDBusMessage *message)
979 {
980   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), 0);
981   return message->serial;
982 }
983
984 /**
985  * g_dbus_message_set_serial:
986  * @message: A #GDBusMessage.
987  * @serial: A #guint32.
988  *
989  * Sets the serial for @message.
990  *
991  * Since: 2.26
992  */
993 void
994 g_dbus_message_set_serial (GDBusMessage  *message,
995                            guint32        serial)
996 {
997   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
998
999   if (message->locked)
1000     {
1001       g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
1002       return;
1003     }
1004
1005   message->serial = serial;
1006 }
1007
1008 /* ---------------------------------------------------------------------------------------------------- */
1009
1010 /* TODO: need GI annotations to specify that any guchar value goes for header_field */
1011
1012 /**
1013  * g_dbus_message_get_header:
1014  * @message: A #GDBusMessage.
1015  * @header_field: A 8-bit unsigned integer (typically a value from the #GDBusMessageHeaderField enumeration)
1016  *
1017  * Gets a header field on @message.
1018  *
1019  * The caller is responsible for checking the type of the returned #GVariant
1020  * matches what is expected.
1021  *
1022  * Returns: (transfer none) (nullable): A #GVariant with the value if the header was found, %NULL
1023  * otherwise. Do not free, it is owned by @message.
1024  *
1025  * Since: 2.26
1026  */
1027 GVariant *
1028 g_dbus_message_get_header (GDBusMessage             *message,
1029                            GDBusMessageHeaderField   header_field)
1030 {
1031   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
1032   g_return_val_if_fail ((guint) header_field < 256, NULL);
1033   return g_hash_table_lookup (message->headers, GUINT_TO_POINTER (header_field));
1034 }
1035
1036 /**
1037  * g_dbus_message_set_header:
1038  * @message: A #GDBusMessage.
1039  * @header_field: A 8-bit unsigned integer (typically a value from the #GDBusMessageHeaderField enumeration)
1040  * @value: (nullable): A #GVariant to set the header field or %NULL to clear the header field.
1041  *
1042  * Sets a header field on @message.
1043  *
1044  * If @value is floating, @message assumes ownership of @value.
1045  *
1046  * Since: 2.26
1047  */
1048 void
1049 g_dbus_message_set_header (GDBusMessage             *message,
1050                            GDBusMessageHeaderField   header_field,
1051                            GVariant                 *value)
1052 {
1053   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
1054   g_return_if_fail ((guint) header_field < 256);
1055
1056   if (message->locked)
1057     {
1058       g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
1059       return;
1060     }
1061
1062   if (value == NULL)
1063     {
1064       g_hash_table_remove (message->headers, GUINT_TO_POINTER (header_field));
1065     }
1066   else
1067     {
1068       g_hash_table_insert (message->headers, GUINT_TO_POINTER (header_field), g_variant_ref_sink (value));
1069     }
1070 }
1071
1072 /**
1073  * g_dbus_message_get_header_fields:
1074  * @message: A #GDBusMessage.
1075  *
1076  * Gets an array of all header fields on @message that are set.
1077  *
1078  * Returns: (array zero-terminated=1): An array of header fields
1079  * terminated by %G_DBUS_MESSAGE_HEADER_FIELD_INVALID.  Each element
1080  * is a #guchar. Free with g_free().
1081  *
1082  * Since: 2.26
1083  */
1084 guchar *
1085 g_dbus_message_get_header_fields (GDBusMessage  *message)
1086 {
1087   GPtrArray *keys;
1088   GArray *array;
1089
1090   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
1091
1092   keys = g_hash_table_get_keys_as_ptr_array (message->headers);
1093   array = g_array_sized_new (FALSE, FALSE, sizeof (guchar), keys->len + 1);
1094
1095   for (guint i = 0; i < keys->len; ++i)
1096     {
1097       guchar val = GPOINTER_TO_UINT (g_ptr_array_index (keys, i));
1098       g_array_append_val (array, val);
1099     }
1100
1101   g_assert (array->len == keys->len);
1102   g_clear_pointer (&keys, g_ptr_array_unref);
1103
1104   guchar invalid_field = G_DBUS_MESSAGE_HEADER_FIELD_INVALID;
1105   g_array_append_val (array, invalid_field);
1106
1107   return (guchar *) g_array_free (array, FALSE);
1108 }
1109
1110 /* ---------------------------------------------------------------------------------------------------- */
1111
1112 /**
1113  * g_dbus_message_get_body:
1114  * @message: A #GDBusMessage.
1115  *
1116  * Gets the body of a message.
1117  *
1118  * Returns: (nullable) (transfer none): A #GVariant or %NULL if the body is
1119  * empty. Do not free, it is owned by @message.
1120  *
1121  * Since: 2.26
1122  */
1123 GVariant *
1124 g_dbus_message_get_body (GDBusMessage  *message)
1125 {
1126   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
1127   return message->body;
1128 }
1129
1130 /**
1131  * g_dbus_message_set_body:
1132  * @message: A #GDBusMessage.
1133  * @body: Either %NULL or a #GVariant that is a tuple.
1134  *
1135  * Sets the body @message. As a side-effect the
1136  * %G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE header field is set to the
1137  * type string of @body (or cleared if @body is %NULL).
1138  *
1139  * If @body is floating, @message assumes ownership of @body.
1140  *
1141  * Since: 2.26
1142  */
1143 void
1144 g_dbus_message_set_body (GDBusMessage  *message,
1145                          GVariant      *body)
1146 {
1147   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
1148   g_return_if_fail ((body == NULL) || g_variant_is_of_type (body, G_VARIANT_TYPE_TUPLE));
1149
1150   if (message->locked)
1151     {
1152       g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
1153       return;
1154     }
1155
1156   if (message->body != NULL)
1157     g_variant_unref (message->body);
1158
1159   g_clear_pointer (&message->arg0_cache, g_variant_unref);
1160
1161   if (body == NULL)
1162     {
1163       message->body = NULL;
1164       g_dbus_message_set_signature (message, NULL);
1165     }
1166   else
1167     {
1168       const gchar *type_string;
1169       gsize type_string_len;
1170       gchar *signature;
1171
1172       message->body = g_variant_ref_sink (body);
1173
1174       if (g_variant_is_of_type (message->body, G_VARIANT_TYPE_TUPLE) &&
1175           g_variant_n_children (message->body) > 0)
1176         message->arg0_cache = g_variant_get_child_value (message->body, 0);
1177
1178       type_string = g_variant_get_type_string (body);
1179       type_string_len = strlen (type_string);
1180       g_assert (type_string_len >= 2);
1181       signature = g_strndup (type_string + 1, type_string_len - 2);
1182       g_dbus_message_set_signature (message, signature);
1183       g_free (signature);
1184     }
1185 }
1186
1187 /* ---------------------------------------------------------------------------------------------------- */
1188
1189 #ifdef G_OS_UNIX
1190 /**
1191  * g_dbus_message_get_unix_fd_list:
1192  * @message: A #GDBusMessage.
1193  *
1194  * Gets the UNIX file descriptors associated with @message, if any.
1195  *
1196  * This method is only available on UNIX.
1197  *
1198  * The file descriptors normally correspond to %G_VARIANT_TYPE_HANDLE
1199  * values in the body of the message. For example,
1200  * if g_variant_get_handle() returns 5, that is intended to be a reference
1201  * to the file descriptor that can be accessed by
1202  * `g_unix_fd_list_get (list, 5, ...)`.
1203  *
1204  * Returns: (nullable) (transfer none): A #GUnixFDList or %NULL if no file descriptors are
1205  * associated. Do not free, this object is owned by @message.
1206  *
1207  * Since: 2.26
1208  */
1209 GUnixFDList *
1210 g_dbus_message_get_unix_fd_list (GDBusMessage  *message)
1211 {
1212   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
1213   return message->fd_list;
1214 }
1215
1216 /**
1217  * g_dbus_message_set_unix_fd_list:
1218  * @message: A #GDBusMessage.
1219  * @fd_list: (nullable): A #GUnixFDList or %NULL.
1220  *
1221  * Sets the UNIX file descriptors associated with @message. As a
1222  * side-effect the %G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS header
1223  * field is set to the number of fds in @fd_list (or cleared if
1224  * @fd_list is %NULL).
1225  *
1226  * This method is only available on UNIX.
1227  *
1228  * When designing D-Bus APIs that are intended to be interoperable,
1229  * please note that non-GDBus implementations of D-Bus can usually only
1230  * access file descriptors if they are referenced by a value of type
1231  * %G_VARIANT_TYPE_HANDLE in the body of the message.
1232  *
1233  * Since: 2.26
1234  */
1235 void
1236 g_dbus_message_set_unix_fd_list (GDBusMessage  *message,
1237                                  GUnixFDList   *fd_list)
1238 {
1239   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
1240   g_return_if_fail (fd_list == NULL || G_IS_UNIX_FD_LIST (fd_list));
1241
1242   if (message->locked)
1243     {
1244       g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
1245       return;
1246     }
1247
1248   if (message->fd_list != NULL)
1249     g_object_unref (message->fd_list);
1250   if (fd_list != NULL)
1251     {
1252       message->fd_list = g_object_ref (fd_list);
1253       g_dbus_message_set_num_unix_fds (message, g_unix_fd_list_get_length (fd_list));
1254     }
1255   else
1256     {
1257       message->fd_list = NULL;
1258       g_dbus_message_set_num_unix_fds (message, 0);
1259     }
1260 }
1261 #endif
1262
1263 /* ---------------------------------------------------------------------------------------------------- */
1264
1265 static guint
1266 get_type_fixed_size (const GVariantType *type)
1267 {
1268   /* NB: we do not treat 'b' as fixed-size here because GVariant and
1269    * D-Bus disagree about the size.
1270    */
1271   switch (*g_variant_type_peek_string (type))
1272     {
1273     case 'y':
1274       return 1;
1275     case 'n': case 'q':
1276       return 2;
1277     case 'i': case 'u': case 'h':
1278       return 4;
1279     case 'x': case 't': case 'd':
1280       return 8;
1281     default:
1282       return 0;
1283     }
1284 }
1285
1286 static const char *
1287 message_type_to_string (GDBusMessageType message_type)
1288 {
1289   switch (message_type)
1290     {
1291     case G_DBUS_MESSAGE_TYPE_INVALID:
1292       return "INVALID";
1293     case G_DBUS_MESSAGE_TYPE_METHOD_CALL:
1294       return "METHOD_CALL";
1295     case G_DBUS_MESSAGE_TYPE_METHOD_RETURN:
1296       return "METHOD_RETURN";
1297     case G_DBUS_MESSAGE_TYPE_ERROR:
1298       return "ERROR";
1299     case G_DBUS_MESSAGE_TYPE_SIGNAL:
1300       return "SIGNAL";
1301     default:
1302       return "unknown-type";
1303     }
1304 }
1305
1306 static const char *
1307 message_header_field_to_string (GDBusMessageHeaderField field)
1308 {
1309   switch (field)
1310     {
1311     case G_DBUS_MESSAGE_HEADER_FIELD_INVALID:
1312       return "INVALID";
1313     case G_DBUS_MESSAGE_HEADER_FIELD_PATH:
1314       return "PATH";
1315     case G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE:
1316       return "INTERFACE";
1317     case G_DBUS_MESSAGE_HEADER_FIELD_MEMBER:
1318       return "MEMBER";
1319     case G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME:
1320       return "ERROR_NAME";
1321     case G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL:
1322       return "REPLY_SERIAL";
1323     case G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION:
1324       return "DESTINATION";
1325     case G_DBUS_MESSAGE_HEADER_FIELD_SENDER:
1326       return "SENDER";
1327     case G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE:
1328       return "SIGNATURE";
1329     case G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS:
1330       return "NUM_UNIX_FDS";
1331     default:
1332       return "unknown-field";
1333     }
1334 }
1335
1336 static gboolean
1337 validate_header (GDBusMessage             *message,
1338                  GDBusMessageHeaderField   field,
1339                  GVariant                 *header_value,
1340                  const GVariantType       *expected_type,
1341                  GError                  **error)
1342 {
1343   g_assert (header_value != NULL);
1344
1345   if (!g_variant_is_of_type (header_value, expected_type))
1346     {
1347       char *expected_type_string = g_variant_type_dup_string (expected_type);
1348       g_set_error (error,
1349                    G_IO_ERROR,
1350                    G_IO_ERROR_INVALID_ARGUMENT,
1351                    _("%s message: %s header field is invalid; expected a value of type ‘%s’"),
1352                    message_type_to_string (message->type),
1353                    message_header_field_to_string (field),
1354                    expected_type_string);
1355       g_free (expected_type_string);
1356       return FALSE;
1357     }
1358
1359   return TRUE;
1360 }
1361
1362 static gboolean
1363 require_header (GDBusMessage             *message,
1364                 GDBusMessageHeaderField   field,
1365                 GError                  **error)
1366 {
1367   GVariant *header_value = g_dbus_message_get_header (message, field);
1368
1369   if (header_value == NULL)
1370     {
1371       g_set_error (error,
1372                    G_IO_ERROR,
1373                    G_IO_ERROR_INVALID_ARGUMENT,
1374                    _("%s message: %s header field is missing or invalid"),
1375                    message_type_to_string (message->type),
1376                    message_header_field_to_string (field));
1377       return FALSE;
1378     }
1379
1380   return TRUE;
1381 }
1382
1383 /* Implement the validation rules given in
1384  * https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-header-fields */
1385 static gboolean
1386 validate_headers (GDBusMessage  *message,
1387                   GError       **error)
1388 {
1389   gboolean ret;
1390   GHashTableIter headers_iter;
1391   gpointer key;
1392   GVariant *header_value;
1393
1394   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), FALSE);
1395   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1396
1397   ret = FALSE;
1398
1399   /* Validate the types of all known headers. */
1400   g_hash_table_iter_init (&headers_iter, message->headers);
1401   while (g_hash_table_iter_next (&headers_iter, &key, (gpointer) &header_value))
1402     {
1403       GDBusMessageHeaderField field_type = GPOINTER_TO_INT (key);
1404
1405       switch (field_type)
1406         {
1407         case G_DBUS_MESSAGE_HEADER_FIELD_INVALID:
1408           /* The invalid header must be rejected as per
1409            * https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-header-fields */
1410           g_set_error (error,
1411                        G_IO_ERROR,
1412                        G_IO_ERROR_INVALID_ARGUMENT,
1413                        _("%s message: INVALID header field supplied"),
1414                        message_type_to_string (message->type));
1415           goto out;
1416         case G_DBUS_MESSAGE_HEADER_FIELD_PATH:
1417           if (!validate_header (message, field_type, header_value, G_VARIANT_TYPE_OBJECT_PATH, error))
1418             goto out;
1419           if (g_strcmp0 (g_variant_get_string (header_value, NULL), "/org/freedesktop/DBus/Local") == 0)
1420             {
1421               g_set_error (error,
1422                            G_IO_ERROR,
1423                            G_IO_ERROR_INVALID_ARGUMENT,
1424                            _("%s message: PATH header field is using the reserved value /org/freedesktop/DBus/Local"),
1425                            message_type_to_string (message->type));
1426               goto out;
1427             }
1428           break;
1429         case G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE:
1430           if (!validate_header (message, field_type, header_value, G_VARIANT_TYPE_STRING, error))
1431             goto out;
1432           if (!g_dbus_is_interface_name (g_variant_get_string (header_value, NULL)))
1433             {
1434               g_set_error (error,
1435                            G_IO_ERROR,
1436                            G_IO_ERROR_INVALID_ARGUMENT,
1437                            _("%s message: INTERFACE header field does not contain a valid interface name"),
1438                            message_type_to_string (message->type));
1439               goto out;
1440             }
1441           if (g_strcmp0 (g_variant_get_string (header_value, NULL), "org.freedesktop.DBus.Local") == 0)
1442             {
1443               g_set_error (error,
1444                            G_IO_ERROR,
1445                            G_IO_ERROR_INVALID_ARGUMENT,
1446                            _("%s message: INTERFACE header field is using the reserved value org.freedesktop.DBus.Local"),
1447                            message_type_to_string (message->type));
1448               goto out;
1449             }
1450           break;
1451         case G_DBUS_MESSAGE_HEADER_FIELD_MEMBER:
1452           if (!validate_header (message, field_type, header_value, G_VARIANT_TYPE_STRING, error))
1453             goto out;
1454           if (!g_dbus_is_member_name (g_variant_get_string (header_value, NULL)))
1455             {
1456               g_set_error (error,
1457                            G_IO_ERROR,
1458                            G_IO_ERROR_INVALID_ARGUMENT,
1459                            _("%s message: MEMBER header field does not contain a valid member name"),
1460                            message_type_to_string (message->type));
1461               goto out;
1462             }
1463           break;
1464         case G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME:
1465           if (!validate_header (message, field_type, header_value, G_VARIANT_TYPE_STRING, error))
1466             goto out;
1467           if (!g_dbus_is_error_name (g_variant_get_string (header_value, NULL)))
1468             {
1469               g_set_error (error,
1470                            G_IO_ERROR,
1471                            G_IO_ERROR_INVALID_ARGUMENT,
1472                            _("%s message: ERROR_NAME header field does not contain a valid error name"),
1473                            message_type_to_string (message->type));
1474               goto out;
1475             }
1476           break;
1477         case G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL:
1478           if (!validate_header (message, field_type, header_value, G_VARIANT_TYPE_UINT32, error))
1479             goto out;
1480           break;
1481         case G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION:
1482           if (!validate_header (message, field_type, header_value, G_VARIANT_TYPE_STRING, error))
1483             goto out;
1484           break;
1485         case G_DBUS_MESSAGE_HEADER_FIELD_SENDER:
1486           if (!validate_header (message, field_type, header_value, G_VARIANT_TYPE_STRING, error))
1487             goto out;
1488           break;
1489         case G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE:
1490           if (!validate_header (message, field_type, header_value, G_VARIANT_TYPE_SIGNATURE, error))
1491             goto out;
1492           break;
1493         case G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS:
1494           if (!validate_header (message, field_type, header_value, G_VARIANT_TYPE_UINT32, error))
1495             goto out;
1496           break;
1497         default:
1498           /* Ignore unknown fields as per
1499            * https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-header-fields. */
1500           continue;
1501         }
1502     }
1503
1504   /* Check for message-type-specific required headers. */
1505   switch (message->type)
1506     {
1507     case G_DBUS_MESSAGE_TYPE_INVALID:
1508       g_set_error_literal (error,
1509                            G_IO_ERROR,
1510                            G_IO_ERROR_INVALID_ARGUMENT,
1511                            _("type is INVALID"));
1512       goto out;
1513
1514     case G_DBUS_MESSAGE_TYPE_METHOD_CALL:
1515       if (!require_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH, error) ||
1516           !require_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER, error))
1517         goto out;
1518       break;
1519
1520     case G_DBUS_MESSAGE_TYPE_METHOD_RETURN:
1521       if (!require_header (message, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL, error))
1522         goto out;
1523       break;
1524
1525     case G_DBUS_MESSAGE_TYPE_ERROR:
1526       if (!require_header (message, G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME, error) ||
1527           !require_header (message, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL, error))
1528         goto out;
1529       break;
1530
1531     case G_DBUS_MESSAGE_TYPE_SIGNAL:
1532       if (!require_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH, error) ||
1533           !require_header (message, G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE, error) ||
1534           !require_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER, error))
1535         goto out;
1536       break;
1537
1538     default:
1539       /* hitherto unknown type - nothing to check */
1540       break;
1541     }
1542
1543   ret = TRUE;
1544
1545  out:
1546   g_assert (ret || (error == NULL || *error != NULL));
1547   return ret;
1548 }
1549
1550 /* ---------------------------------------------------------------------------------------------------- */
1551
1552 static gboolean
1553 ensure_input_padding (GMemoryBuffer  *buf,
1554                       gsize           padding_size)
1555 {
1556   gsize offset;
1557   gsize wanted_offset;
1558
1559   offset = buf->pos;
1560   wanted_offset = ((offset + padding_size - 1) / padding_size) * padding_size;
1561   buf->pos = wanted_offset;
1562   return TRUE;
1563 }
1564
1565 static const gchar *
1566 read_string (GMemoryBuffer  *mbuf,
1567              gsize           len,
1568              GError        **error)
1569 {
1570   gchar *str;
1571   const gchar *end_valid;
1572
1573   if G_UNLIKELY (mbuf->pos + len >= mbuf->valid_len || mbuf->pos + len < mbuf->pos)
1574     {
1575       mbuf->pos = mbuf->valid_len;
1576       /* G_GSIZE_FORMAT doesn't work with gettext, so we use %lu */
1577       g_set_error (error,
1578                    G_IO_ERROR,
1579                    G_IO_ERROR_INVALID_ARGUMENT,
1580                    g_dngettext (GETTEXT_PACKAGE,
1581                                 "Wanted to read %lu byte but only got %lu",
1582                                 "Wanted to read %lu bytes but only got %lu",
1583                                 (gulong)len),
1584                                 (gulong)len,
1585                    (gulong)(mbuf->valid_len - mbuf->pos));
1586       return NULL;
1587     }
1588
1589   if G_UNLIKELY (mbuf->data[mbuf->pos + len] != '\0')
1590     {
1591       str = g_strndup (mbuf->data + mbuf->pos, len);
1592       g_set_error (error,
1593                    G_IO_ERROR,
1594                    G_IO_ERROR_INVALID_ARGUMENT,
1595                    _("Expected NUL byte after the string “%s” but found byte %d"),
1596                    str, mbuf->data[mbuf->pos + len]);
1597       g_free (str);
1598       mbuf->pos += len + 1;
1599       return NULL;
1600     }
1601
1602   str = mbuf->data + mbuf->pos;
1603   mbuf->pos += len + 1;
1604
1605   if G_UNLIKELY (!g_utf8_validate (str, -1, &end_valid))
1606     {
1607       gint offset;
1608       gchar *valid_str;
1609       offset = (gint) (end_valid - str);
1610       valid_str = g_strndup (str, offset);
1611       g_set_error (error,
1612                    G_IO_ERROR,
1613                    G_IO_ERROR_INVALID_ARGUMENT,
1614                    _("Expected valid UTF-8 string but found invalid bytes at byte offset %d (length of string is %d). "
1615                      "The valid UTF-8 string up until that point was “%s”"),
1616                    offset,
1617                    (gint) len,
1618                    valid_str);
1619       g_free (valid_str);
1620       return NULL;
1621     }
1622
1623   return str;
1624 }
1625
1626 static gconstpointer
1627 read_bytes (GMemoryBuffer  *mbuf,
1628             gsize           len,
1629             GError        **error)
1630 {
1631   gconstpointer result;
1632
1633   if G_UNLIKELY (mbuf->pos + len > mbuf->valid_len || mbuf->pos + len < mbuf->pos)
1634     {
1635       mbuf->pos = mbuf->valid_len;
1636       /* G_GSIZE_FORMAT doesn't work with gettext, so we use %lu */
1637       g_set_error (error,
1638                    G_IO_ERROR,
1639                    G_IO_ERROR_INVALID_ARGUMENT,
1640                    g_dngettext (GETTEXT_PACKAGE,
1641                                 "Wanted to read %lu byte but only got %lu",
1642                                 "Wanted to read %lu bytes but only got %lu",
1643                                 (gulong)len),
1644                                 (gulong)len,
1645                    (gulong)(mbuf->valid_len - mbuf->pos));
1646       return NULL;
1647     }
1648
1649   result = mbuf->data + mbuf->pos;
1650   mbuf->pos += len;
1651
1652   return result;
1653 }
1654
1655 /* if just_align==TRUE, don't read a value, just align the input stream wrt padding */
1656
1657 /* returns a non-floating GVariant! */
1658 static GVariant *
1659 parse_value_from_blob (GMemoryBuffer       *buf,
1660                        const GVariantType  *type,
1661                        guint                max_depth,
1662                        gboolean             just_align,
1663                        guint                indent,
1664                        GError             **error)
1665 {
1666   GVariant *ret = NULL;
1667   GError *local_error = NULL;
1668 #ifdef DEBUG_SERIALIZER
1669   gboolean is_leaf;
1670 #endif /* DEBUG_SERIALIZER */
1671   const gchar *type_string;
1672
1673   if (max_depth == 0)
1674     {
1675       g_set_error_literal (&local_error,
1676                            G_IO_ERROR,
1677                            G_IO_ERROR_INVALID_ARGUMENT,
1678                            _("Value nested too deeply"));
1679       goto fail;
1680     }
1681
1682   type_string = g_variant_type_peek_string (type);
1683
1684 #ifdef DEBUG_SERIALIZER
1685     {
1686       gchar *s;
1687       s = g_variant_type_dup_string (type);
1688       g_print ("%*s%s type %s from offset 0x%04x",
1689                indent, "",
1690                just_align ? "Aligning" : "Reading",
1691                s,
1692                (gint) buf->pos);
1693       g_free (s);
1694     }
1695 #endif /* DEBUG_SERIALIZER */
1696
1697 #ifdef DEBUG_SERIALIZER
1698   is_leaf = TRUE;
1699 #endif /* DEBUG_SERIALIZER */
1700   switch (type_string[0])
1701     {
1702     case 'b': /* G_VARIANT_TYPE_BOOLEAN */
1703       ensure_input_padding (buf, 4);
1704       if (!just_align)
1705         {
1706           gboolean v;
1707           v = g_memory_buffer_read_uint32 (buf, &local_error);
1708           if (local_error)
1709             goto fail;
1710           ret = g_variant_new_boolean (v);
1711         }
1712       break;
1713
1714     case 'y': /* G_VARIANT_TYPE_BYTE */
1715       if (!just_align)
1716         {
1717           guchar v;
1718           v = g_memory_buffer_read_byte (buf, &local_error);
1719           if (local_error)
1720             goto fail;
1721           ret = g_variant_new_byte (v);
1722         }
1723       break;
1724
1725     case 'n': /* G_VARIANT_TYPE_INT16 */
1726       ensure_input_padding (buf, 2);
1727       if (!just_align)
1728         {
1729           gint16 v;
1730           v = g_memory_buffer_read_int16 (buf, &local_error);
1731           if (local_error)
1732             goto fail;
1733           ret = g_variant_new_int16 (v);
1734         }
1735       break;
1736
1737     case 'q': /* G_VARIANT_TYPE_UINT16 */
1738       ensure_input_padding (buf, 2);
1739       if (!just_align)
1740         {
1741           guint16 v;
1742           v = g_memory_buffer_read_uint16 (buf, &local_error);
1743           if (local_error)
1744             goto fail;
1745           ret = g_variant_new_uint16 (v);
1746         }
1747       break;
1748
1749     case 'i': /* G_VARIANT_TYPE_INT32 */
1750       ensure_input_padding (buf, 4);
1751       if (!just_align)
1752         {
1753           gint32 v;
1754           v = g_memory_buffer_read_int32 (buf, &local_error);
1755           if (local_error)
1756             goto fail;
1757           ret = g_variant_new_int32 (v);
1758         }
1759       break;
1760
1761     case 'u': /* G_VARIANT_TYPE_UINT32 */
1762       ensure_input_padding (buf, 4);
1763       if (!just_align)
1764         {
1765           guint32 v;
1766           v = g_memory_buffer_read_uint32 (buf, &local_error);
1767           if (local_error)
1768             goto fail;
1769           ret = g_variant_new_uint32 (v);
1770         }
1771       break;
1772
1773     case 'x': /* G_VARIANT_TYPE_INT64 */
1774       ensure_input_padding (buf, 8);
1775       if (!just_align)
1776         {
1777           gint64 v;
1778           v = g_memory_buffer_read_int64 (buf, &local_error);
1779           if (local_error)
1780             goto fail;
1781           ret = g_variant_new_int64 (v);
1782         }
1783       break;
1784
1785     case 't': /* G_VARIANT_TYPE_UINT64 */
1786       ensure_input_padding (buf, 8);
1787       if (!just_align)
1788         {
1789           guint64 v;
1790           v = g_memory_buffer_read_uint64 (buf, &local_error);
1791           if (local_error)
1792             goto fail;
1793           ret = g_variant_new_uint64 (v);
1794         }
1795       break;
1796
1797     case 'd': /* G_VARIANT_TYPE_DOUBLE */
1798       ensure_input_padding (buf, 8);
1799       if (!just_align)
1800         {
1801           union {
1802             guint64 v_uint64;
1803             gdouble v_double;
1804           } u;
1805           G_STATIC_ASSERT (sizeof (gdouble) == sizeof (guint64));
1806           u.v_uint64 = g_memory_buffer_read_uint64 (buf, &local_error);
1807           if (local_error)
1808             goto fail;
1809           ret = g_variant_new_double (u.v_double);
1810         }
1811       break;
1812
1813     case 's': /* G_VARIANT_TYPE_STRING */
1814       ensure_input_padding (buf, 4);
1815       if (!just_align)
1816         {
1817           guint32 len;
1818           const gchar *v;
1819           len = g_memory_buffer_read_uint32 (buf, &local_error);
1820           if (local_error)
1821             goto fail;
1822           v = read_string (buf, (gsize) len, &local_error);
1823           if (v == NULL)
1824             goto fail;
1825           ret = g_variant_new_string (v);
1826         }
1827       break;
1828
1829     case 'o': /* G_VARIANT_TYPE_OBJECT_PATH */
1830       ensure_input_padding (buf, 4);
1831       if (!just_align)
1832         {
1833           guint32 len;
1834           const gchar *v;
1835           len = g_memory_buffer_read_uint32 (buf, &local_error);
1836           if (local_error)
1837             goto fail;
1838           v = read_string (buf, (gsize) len, &local_error);
1839           if (v == NULL)
1840             goto fail;
1841           if (!g_variant_is_object_path (v))
1842             {
1843               g_set_error (&local_error,
1844                            G_IO_ERROR,
1845                            G_IO_ERROR_INVALID_ARGUMENT,
1846                            _("Parsed value “%s” is not a valid D-Bus object path"),
1847                            v);
1848               goto fail;
1849             }
1850           ret = g_variant_new_object_path (v);
1851         }
1852       break;
1853
1854     case 'g': /* G_VARIANT_TYPE_SIGNATURE */
1855       if (!just_align)
1856         {
1857           guchar len;
1858           const gchar *v;
1859           len = g_memory_buffer_read_byte (buf, &local_error);
1860           if (local_error)
1861             goto fail;
1862           v = read_string (buf, (gsize) len, &local_error);
1863           if (v == NULL)
1864             goto fail;
1865           if (!g_variant_is_signature (v))
1866             {
1867               g_set_error (&local_error,
1868                            G_IO_ERROR,
1869                            G_IO_ERROR_INVALID_ARGUMENT,
1870                            _("Parsed value “%s” is not a valid D-Bus signature"),
1871                        v);
1872               goto fail;
1873             }
1874           ret = g_variant_new_signature (v);
1875         }
1876       break;
1877
1878     case 'h': /* G_VARIANT_TYPE_HANDLE */
1879       ensure_input_padding (buf, 4);
1880       if (!just_align)
1881         {
1882           gint32 v;
1883           v = g_memory_buffer_read_int32 (buf, &local_error);
1884           if (local_error)
1885             goto fail;
1886           ret = g_variant_new_handle (v);
1887         }
1888       break;
1889
1890     case 'a': /* G_VARIANT_TYPE_ARRAY */
1891       ensure_input_padding (buf, 4);
1892
1893       /* If we are only aligning for this array type, it is the child type of
1894        * another array, which is empty. So, we do not need to add padding for
1895        * this nonexistent array's elements: we only need to align for this
1896        * array itself (4 bytes). See
1897        * <https://bugzilla.gnome.org/show_bug.cgi?id=673612>.
1898        */
1899       if (!just_align)
1900         {
1901           guint32 array_len;
1902           const GVariantType *element_type;
1903           guint fixed_size;
1904
1905           array_len = g_memory_buffer_read_uint32 (buf, &local_error);
1906           if (local_error)
1907             goto fail;
1908
1909 #ifdef DEBUG_SERIALIZER
1910           is_leaf = FALSE;
1911           g_print (": array spans 0x%04x bytes\n", array_len);
1912 #endif /* DEBUG_SERIALIZER */
1913
1914           if (array_len > (2<<26))
1915             {
1916               /* G_GUINT32_FORMAT doesn't work with gettext, so use u */
1917               g_set_error (&local_error,
1918                            G_IO_ERROR,
1919                            G_IO_ERROR_INVALID_ARGUMENT,
1920                            g_dngettext (GETTEXT_PACKAGE,
1921                                         "Encountered array of length %u byte. Maximum length is 2<<26 bytes (64 MiB).",
1922                                         "Encountered array of length %u bytes. Maximum length is 2<<26 bytes (64 MiB).",
1923                                         array_len),
1924                            array_len);
1925               goto fail;
1926             }
1927
1928           element_type = g_variant_type_element (type);
1929           fixed_size = get_type_fixed_size (element_type);
1930
1931           /* Fast-path the cases like 'ay', etc. */
1932           if (fixed_size != 0)
1933             {
1934               gconstpointer array_data;
1935
1936               if (array_len % fixed_size != 0)
1937                 {
1938                   g_set_error (&local_error,
1939                                G_IO_ERROR,
1940                                G_IO_ERROR_INVALID_ARGUMENT,
1941                                _("Encountered array of type “a%c”, expected to have a length a multiple "
1942                                  "of %u bytes, but found to be %u bytes in length"),
1943                                g_variant_type_peek_string (element_type)[0], fixed_size, array_len);
1944                   goto fail;
1945                 }
1946
1947               if (max_depth == 1)
1948                 {
1949                   /* If we had recursed into parse_value_from_blob() again to
1950                    * parse the array values, this would have been emitted. */
1951                   g_set_error_literal (&local_error,
1952                                        G_IO_ERROR,
1953                                        G_IO_ERROR_INVALID_ARGUMENT,
1954                                        _("Value nested too deeply"));
1955                   goto fail;
1956                 }
1957
1958               ensure_input_padding (buf, fixed_size);
1959               array_data = read_bytes (buf, array_len, &local_error);
1960               if (array_data == NULL)
1961                 goto fail;
1962
1963               ret = g_variant_new_fixed_array (element_type, array_data, array_len / fixed_size, fixed_size);
1964
1965               if (g_memory_buffer_is_byteswapped (buf))
1966                 {
1967                   GVariant *tmp = g_variant_ref_sink (ret);
1968                   ret = g_variant_byteswap (tmp);
1969                   g_variant_unref (tmp);
1970                 }
1971             }
1972           else
1973             {
1974               GVariantBuilder builder;
1975               goffset offset;
1976               goffset target;
1977
1978               g_variant_builder_init (&builder, type);
1979
1980               if (array_len == 0)
1981                 {
1982                   GVariant *item G_GNUC_UNUSED  /* when compiling with G_DISABLE_ASSERT */;
1983                   item = parse_value_from_blob (buf,
1984                                                 element_type,
1985                                                 max_depth - 1,
1986                                                 TRUE,
1987                                                 indent + 2,
1988                                                 NULL);
1989                   g_assert (item == NULL);
1990                 }
1991               else
1992                 {
1993                   offset = buf->pos;
1994                   target = offset + array_len;
1995                   while (offset < target)
1996                     {
1997                       GVariant *item;
1998                       item = parse_value_from_blob (buf,
1999                                                     element_type,
2000                                                     max_depth - 1,
2001                                                     FALSE,
2002                                                     indent + 2,
2003                                                     &local_error);
2004                       if (item == NULL)
2005                         {
2006                           g_variant_builder_clear (&builder);
2007                           goto fail;
2008                         }
2009                       g_variant_builder_add_value (&builder, item);
2010                       g_variant_unref (item);
2011
2012                       /* Array elements must not be zero-length. There are no
2013                        * valid zero-length serialisations of any types which
2014                        * can be array elements in the D-Bus wire format, so this
2015                        * assertion should always hold.
2016                        *
2017                        * See https://gitlab.gnome.org/GNOME/glib/-/issues/2557
2018                        */
2019                       g_assert (buf->pos > (gsize) offset);
2020
2021                       offset = buf->pos;
2022                     }
2023                 }
2024
2025               ret = g_variant_builder_end (&builder);
2026             }
2027         }
2028       break;
2029
2030     default:
2031       if (g_variant_type_is_dict_entry (type))
2032         {
2033           const GVariantType *key_type;
2034           const GVariantType *value_type;
2035           GVariant *key;
2036           GVariant *value;
2037
2038           ensure_input_padding (buf, 8);
2039
2040 #ifdef DEBUG_SERIALIZER
2041           is_leaf = FALSE;
2042           g_print ("\n");
2043 #endif /* DEBUG_SERIALIZER */
2044
2045           if (!just_align)
2046             {
2047               key_type = g_variant_type_key (type);
2048               key = parse_value_from_blob (buf,
2049                                            key_type,
2050                                            max_depth - 1,
2051                                            FALSE,
2052                                            indent + 2,
2053                                            &local_error);
2054               if (key == NULL)
2055                 goto fail;
2056               value_type = g_variant_type_value (type);
2057               value = parse_value_from_blob (buf,
2058                                              value_type,
2059                                              max_depth - 1,
2060                                              FALSE,
2061                                              indent + 2,
2062                                              &local_error);
2063               if (value == NULL)
2064                 {
2065                   g_variant_unref (key);
2066                   goto fail;
2067                 }
2068               ret = g_variant_new_dict_entry (key, value);
2069               g_variant_unref (key);
2070               g_variant_unref (value);
2071             }
2072         }
2073       else if (g_variant_type_is_tuple (type))
2074         {
2075           ensure_input_padding (buf, 8);
2076
2077 #ifdef DEBUG_SERIALIZER
2078           is_leaf = FALSE;
2079           g_print ("\n");
2080 #endif /* DEBUG_SERIALIZER */
2081
2082           if (!just_align)
2083             {
2084               const GVariantType *element_type;
2085               GVariantBuilder builder;
2086
2087               g_variant_builder_init (&builder, type);
2088               element_type = g_variant_type_first (type);
2089               if (!element_type)
2090                 {
2091                   g_variant_builder_clear (&builder);
2092                   g_set_error_literal (&local_error,
2093                                        G_IO_ERROR,
2094                                        G_IO_ERROR_INVALID_ARGUMENT,
2095                                        _("Empty structures (tuples) are not allowed in D-Bus"));
2096                   goto fail;
2097                 }
2098
2099               while (element_type != NULL)
2100                 {
2101                   GVariant *item;
2102                   item = parse_value_from_blob (buf,
2103                                                 element_type,
2104                                                 max_depth - 1,
2105                                                 FALSE,
2106                                                 indent + 2,
2107                                                 &local_error);
2108                   if (item == NULL)
2109                     {
2110                       g_variant_builder_clear (&builder);
2111                       goto fail;
2112                     }
2113                   g_variant_builder_add_value (&builder, item);
2114                   g_variant_unref (item);
2115
2116                   element_type = g_variant_type_next (element_type);
2117                 }
2118               ret = g_variant_builder_end (&builder);
2119             }
2120         }
2121       else if (g_variant_type_is_variant (type))
2122         {
2123 #ifdef DEBUG_SERIALIZER
2124           is_leaf = FALSE;
2125           g_print ("\n");
2126 #endif /* DEBUG_SERIALIZER */
2127
2128           if (!just_align)
2129             {
2130               guchar siglen;
2131               const gchar *sig;
2132               GVariantType *variant_type;
2133               GVariant *value;
2134
2135               siglen = g_memory_buffer_read_byte (buf, &local_error);
2136               if (local_error)
2137                 goto fail;
2138               sig = read_string (buf, (gsize) siglen, &local_error);
2139               if (sig == NULL)
2140                 goto fail;
2141               if (!g_variant_is_signature (sig) ||
2142                   !g_variant_type_string_is_valid (sig))
2143                 {
2144                   /* A D-Bus signature can contain zero or more complete types,
2145                    * but a GVariant has to be exactly one complete type. */
2146                   g_set_error (&local_error,
2147                                G_IO_ERROR,
2148                                G_IO_ERROR_INVALID_ARGUMENT,
2149                                _("Parsed value “%s” for variant is not a valid D-Bus signature"),
2150                                sig);
2151                   goto fail;
2152                 }
2153
2154               if (max_depth <= g_variant_type_string_get_depth_ (sig))
2155                 {
2156                   /* Catch the type nesting being too deep without having to
2157                    * parse the data. We don’t have to check this for static
2158                    * container types (like arrays and tuples, above) because
2159                    * the g_variant_type_string_is_valid() check performed before
2160                    * the initial parse_value_from_blob() call should check the
2161                    * static type nesting. */
2162                   g_set_error_literal (&local_error,
2163                                        G_IO_ERROR,
2164                                        G_IO_ERROR_INVALID_ARGUMENT,
2165                                        _("Value nested too deeply"));
2166                   goto fail;
2167                 }
2168
2169               variant_type = g_variant_type_new (sig);
2170               value = parse_value_from_blob (buf,
2171                                              variant_type,
2172                                              max_depth - 1,
2173                                              FALSE,
2174                                              indent + 2,
2175                                              &local_error);
2176               g_variant_type_free (variant_type);
2177               if (value == NULL)
2178                 goto fail;
2179               ret = g_variant_new_variant (value);
2180               g_variant_unref (value);
2181             }
2182         }
2183       else
2184         {
2185           gchar *s;
2186           s = g_variant_type_dup_string (type);
2187           g_set_error (&local_error,
2188                        G_IO_ERROR,
2189                        G_IO_ERROR_INVALID_ARGUMENT,
2190                        _("Error deserializing GVariant with type string “%s” from the D-Bus wire format"),
2191                        s);
2192           g_free (s);
2193           goto fail;
2194         }
2195       break;
2196     }
2197
2198   g_assert ((just_align && ret == NULL) || (!just_align && ret != NULL));
2199
2200 #ifdef DEBUG_SERIALIZER
2201   if (ret != NULL)
2202     {
2203       if (is_leaf)
2204         {
2205           gchar *s;
2206           if (g_variant_type_equal (type, G_VARIANT_TYPE_BYTE))
2207             {
2208               s = g_strdup_printf ("0x%02x '%c'", g_variant_get_byte (ret), g_variant_get_byte (ret));
2209             }
2210           else
2211             {
2212               s = g_variant_print (ret, FALSE);
2213             }
2214           g_print (": %s\n", s);
2215           g_free (s);
2216         }
2217     }
2218 #endif /* DEBUG_SERIALIZER */
2219
2220   /* sink the reference, if floating */
2221   if (ret != NULL)
2222     g_variant_take_ref (ret);
2223   return ret;
2224
2225  fail:
2226 #ifdef DEBUG_SERIALIZER
2227   g_print ("\n"
2228            "%*sFAILURE: %s (%s, %d)\n",
2229            indent, "",
2230            local_error->message,
2231            g_quark_to_string (local_error->domain),
2232            local_error->code);
2233 #endif /* DEBUG_SERIALIZER */
2234   g_propagate_error (error, local_error);
2235   return NULL;
2236 }
2237
2238 /* ---------------------------------------------------------------------------------------------------- */
2239
2240 /* message_header must be at least 16 bytes */
2241
2242 /**
2243  * g_dbus_message_bytes_needed:
2244  * @blob: (array length=blob_len) (element-type guint8): A blob representing a binary D-Bus message.
2245  * @blob_len: The length of @blob (must be at least 16).
2246  * @error: Return location for error or %NULL.
2247  *
2248  * Utility function to calculate how many bytes are needed to
2249  * completely deserialize the D-Bus message stored at @blob.
2250  *
2251  * Returns: Number of bytes needed or -1 if @error is set (e.g. if
2252  * @blob contains invalid data or not enough data is available to
2253  * determine the size).
2254  *
2255  * Since: 2.26
2256  */
2257 gssize
2258 g_dbus_message_bytes_needed (guchar  *blob,
2259                              gsize    blob_len,
2260                              GError **error)
2261 {
2262   gssize ret;
2263
2264   ret = -1;
2265
2266   g_return_val_if_fail (blob != NULL, -1);
2267   g_return_val_if_fail (error == NULL || *error == NULL, -1);
2268   g_return_val_if_fail (blob_len >= 16, -1);
2269
2270   if (blob[0] == 'l')
2271     {
2272       /* core header (12 bytes) + ARRAY of STRUCT of (BYTE,VARIANT) */
2273       ret = 12 + 4 + GUINT32_FROM_LE (((guint32 *) blob)[3]);
2274       /* round up so it's a multiple of 8 */
2275       ret = 8 * ((ret + 7)/8);
2276       /* finally add the body size */
2277       ret += GUINT32_FROM_LE (((guint32 *) blob)[1]);
2278     }
2279   else if (blob[0] == 'B')
2280     {
2281       /* core header (12 bytes) + ARRAY of STRUCT of (BYTE,VARIANT) */
2282       ret = 12 + 4 + GUINT32_FROM_BE (((guint32 *) blob)[3]);
2283       /* round up so it's a multiple of 8 */
2284       ret = 8 * ((ret + 7)/8);
2285       /* finally add the body size */
2286       ret += GUINT32_FROM_BE (((guint32 *) blob)[1]);
2287     }
2288   else
2289     {
2290       g_set_error (error,
2291                    G_IO_ERROR,
2292                    G_IO_ERROR_INVALID_ARGUMENT,
2293                    "Unable to determine message blob length - given blob is malformed");
2294     }
2295
2296   if (ret > (1<<27))
2297     {
2298       g_set_error (error,
2299                    G_IO_ERROR,
2300                    G_IO_ERROR_INVALID_ARGUMENT,
2301                    "Blob indicates that message exceeds maximum message length (128MiB)");
2302       ret = -1;
2303     }
2304
2305   return ret;
2306 }
2307
2308 /* ---------------------------------------------------------------------------------------------------- */
2309
2310 /**
2311  * g_dbus_message_new_from_blob:
2312  * @blob: (array length=blob_len) (element-type guint8): A blob representing a binary D-Bus message.
2313  * @blob_len: The length of @blob.
2314  * @capabilities: A #GDBusCapabilityFlags describing what protocol features are supported.
2315  * @error: Return location for error or %NULL.
2316  *
2317  * Creates a new #GDBusMessage from the data stored at @blob. The byte
2318  * order that the message was in can be retrieved using
2319  * g_dbus_message_get_byte_order().
2320  *
2321  * If the @blob cannot be parsed, contains invalid fields, or contains invalid
2322  * headers, %G_IO_ERROR_INVALID_ARGUMENT will be returned.
2323  *
2324  * Returns: A new #GDBusMessage or %NULL if @error is set. Free with
2325  * g_object_unref().
2326  *
2327  * Since: 2.26
2328  */
2329 GDBusMessage *
2330 g_dbus_message_new_from_blob (guchar                *blob,
2331                               gsize                  blob_len,
2332                               GDBusCapabilityFlags   capabilities,
2333                               GError               **error)
2334 {
2335   GError *local_error = NULL;
2336   GMemoryBuffer mbuf;
2337   GDBusMessage *message;
2338   guchar endianness;
2339   guchar major_protocol_version;
2340   guint32 message_body_len;
2341   GVariant *headers;
2342   GVariant *item;
2343   GVariantIter iter;
2344   GVariant *signature;
2345
2346   /* TODO: check against @capabilities */
2347
2348   g_return_val_if_fail (blob != NULL, NULL);
2349   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2350
2351   message = g_dbus_message_new ();
2352
2353   memset (&mbuf, 0, sizeof (mbuf));
2354   mbuf.data = (gchar *)blob;
2355   mbuf.len = mbuf.valid_len = blob_len;
2356
2357   endianness = g_memory_buffer_read_byte (&mbuf, &local_error);
2358   if (local_error)
2359     goto fail;
2360
2361   switch (endianness)
2362     {
2363     case 'l':
2364       mbuf.byte_order = G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN;
2365       message->byte_order = G_DBUS_MESSAGE_BYTE_ORDER_LITTLE_ENDIAN;
2366       break;
2367     case 'B':
2368       mbuf.byte_order = G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN;
2369       message->byte_order = G_DBUS_MESSAGE_BYTE_ORDER_BIG_ENDIAN;
2370       break;
2371     default:
2372       g_set_error (&local_error,
2373                    G_IO_ERROR,
2374                    G_IO_ERROR_INVALID_ARGUMENT,
2375                    _("Invalid endianness value. Expected 0x6c (“l”) or 0x42 (“B”) but found value 0x%02x"),
2376                    endianness);
2377       goto fail;
2378     }
2379
2380   message->type = g_memory_buffer_read_byte (&mbuf, &local_error);
2381   if (local_error)
2382     goto fail;
2383   message->flags = g_memory_buffer_read_byte (&mbuf, &local_error);
2384   if (local_error)
2385     goto fail;
2386   major_protocol_version = g_memory_buffer_read_byte (&mbuf, &local_error);
2387   if (local_error)
2388     goto fail;
2389   if (major_protocol_version != 1)
2390     {
2391       g_set_error (&local_error,
2392                    G_IO_ERROR,
2393                    G_IO_ERROR_INVALID_ARGUMENT,
2394                    _("Invalid major protocol version. Expected 1 but found %d"),
2395                    major_protocol_version);
2396       goto fail;
2397     }
2398   message_body_len = g_memory_buffer_read_uint32 (&mbuf, &local_error);
2399   if (local_error)
2400     goto fail;
2401   message->serial = g_memory_buffer_read_uint32 (&mbuf, &local_error);
2402   if (local_error)
2403     goto fail;
2404
2405 #ifdef DEBUG_SERIALIZER
2406   g_print ("Parsing blob (blob_len = 0x%04x bytes)\n", (gint) blob_len);
2407   {
2408     gchar *s;
2409     s = _g_dbus_hexdump ((const gchar *) blob, blob_len, 2);
2410     g_print ("%s\n", s);
2411     g_free (s);
2412   }
2413 #endif /* DEBUG_SERIALIZER */
2414
2415 #ifdef DEBUG_SERIALIZER
2416   g_print ("Parsing headers (blob_len = 0x%04x bytes)\n", (gint) blob_len);
2417 #endif /* DEBUG_SERIALIZER */
2418   headers = parse_value_from_blob (&mbuf,
2419                                    G_VARIANT_TYPE ("a{yv}"),
2420                                    G_DBUS_MAX_TYPE_DEPTH + 2 /* for the a{yv} */,
2421                                    FALSE,
2422                                    2,
2423                                    &local_error);
2424   if (headers == NULL)
2425     goto fail;
2426   g_variant_iter_init (&iter, headers);
2427   while ((item = g_variant_iter_next_value (&iter)) != NULL)
2428     {
2429       guchar header_field;
2430       GVariant *value;
2431       g_variant_get (item,
2432                      "{yv}",
2433                      &header_field,
2434                      &value);
2435       g_dbus_message_set_header (message, header_field, value);
2436       g_variant_unref (value);
2437       g_variant_unref (item);
2438     }
2439   g_variant_unref (headers);
2440
2441   signature = g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE);
2442   if (signature != NULL)
2443     {
2444       const gchar *signature_str;
2445       gsize signature_str_len;
2446
2447       if (!g_variant_is_of_type (signature, G_VARIANT_TYPE_SIGNATURE))
2448         {
2449           g_set_error_literal (&local_error,
2450                                G_IO_ERROR,
2451                                G_IO_ERROR_INVALID_ARGUMENT,
2452                                _("Signature header found but is not of type signature"));
2453           goto fail;
2454         }
2455
2456       signature_str = g_variant_get_string (signature, &signature_str_len);
2457
2458       /* signature but no body */
2459       if (message_body_len == 0 && signature_str_len > 0)
2460         {
2461           g_set_error (&local_error,
2462                        G_IO_ERROR,
2463                        G_IO_ERROR_INVALID_ARGUMENT,
2464                        _("Signature header with signature “%s” found but message body is empty"),
2465                        signature_str);
2466           goto fail;
2467         }
2468       else if (signature_str_len > 0)
2469         {
2470           GVariantType *variant_type;
2471           gchar *tupled_signature_str = g_strdup_printf ("(%s)", signature_str);
2472
2473           if (!g_variant_is_signature (signature_str) ||
2474               !g_variant_type_string_is_valid (tupled_signature_str))
2475             {
2476               g_set_error (&local_error,
2477                            G_IO_ERROR,
2478                            G_IO_ERROR_INVALID_ARGUMENT,
2479                            _("Parsed value “%s” is not a valid D-Bus signature (for body)"),
2480                            signature_str);
2481               g_free (tupled_signature_str);
2482               goto fail;
2483             }
2484
2485           variant_type = g_variant_type_new (tupled_signature_str);
2486           g_free (tupled_signature_str);
2487 #ifdef DEBUG_SERIALIZER
2488           g_print ("Parsing body (blob_len = 0x%04x bytes)\n", (gint) blob_len);
2489 #endif /* DEBUG_SERIALIZER */
2490           message->body = parse_value_from_blob (&mbuf,
2491                                                  variant_type,
2492                                                  G_DBUS_MAX_TYPE_DEPTH + 1 /* for the surrounding tuple */,
2493                                                  FALSE,
2494                                                  2,
2495                                                  &local_error);
2496           g_variant_type_free (variant_type);
2497
2498           if (message->body != NULL &&
2499               g_variant_is_of_type (message->body, G_VARIANT_TYPE_TUPLE) &&
2500               g_variant_n_children (message->body) > 0)
2501             message->arg0_cache = g_variant_get_child_value (message->body, 0);
2502           else
2503             message->arg0_cache = NULL;
2504
2505           if (message->body == NULL)
2506             goto fail;
2507         }
2508     }
2509   else
2510     {
2511       /* no signature, this is only OK if the body is empty */
2512       if (message_body_len != 0)
2513         {
2514           /* G_GUINT32_FORMAT doesn't work with gettext, just use %u */
2515           g_set_error (&local_error,
2516                        G_IO_ERROR,
2517                        G_IO_ERROR_INVALID_ARGUMENT,
2518                        g_dngettext (GETTEXT_PACKAGE,
2519                                     "No signature header in message but the message body is %u byte",
2520                                     "No signature header in message but the message body is %u bytes",
2521                                     message_body_len),
2522                        message_body_len);
2523           goto fail;
2524         }
2525     }
2526
2527   if (!validate_headers (message, &local_error))
2528     {
2529       g_prefix_error (&local_error, _("Cannot deserialize message: "));
2530       goto fail;
2531     }
2532
2533   return message;
2534
2535 fail:
2536   g_clear_object (&message);
2537   g_propagate_error (error, local_error);
2538   return NULL;
2539 }
2540
2541 /* ---------------------------------------------------------------------------------------------------- */
2542
2543 static gsize
2544 ensure_output_padding (GMemoryBuffer  *mbuf,
2545                        gsize           padding_size)
2546 {
2547   gsize offset;
2548   gsize wanted_offset;
2549   gsize padding_needed;
2550   guint n;
2551
2552   offset = mbuf->pos;
2553   wanted_offset = ((offset + padding_size - 1) / padding_size) * padding_size;
2554   padding_needed = wanted_offset - offset;
2555
2556   for (n = 0; n < padding_needed; n++)
2557     g_memory_buffer_put_byte (mbuf, '\0');
2558
2559   return padding_needed;
2560 }
2561
2562 /* note that value can be NULL for e.g. empty arrays - type is never NULL */
2563 static gboolean
2564 append_value_to_blob (GVariant            *value,
2565                       const GVariantType  *type,
2566                       GMemoryBuffer       *mbuf,
2567                       gsize               *out_padding_added,
2568                       GError             **error)
2569 {
2570   gsize padding_added;
2571   const gchar *type_string;
2572
2573   type_string = g_variant_type_peek_string (type);
2574
2575   padding_added = 0;
2576
2577   switch (type_string[0])
2578     {
2579     case 'b': /* G_VARIANT_TYPE_BOOLEAN */
2580       padding_added = ensure_output_padding (mbuf, 4);
2581       if (value != NULL)
2582         {
2583           gboolean v = g_variant_get_boolean (value);
2584           g_memory_buffer_put_uint32 (mbuf, v);
2585         }
2586       break;
2587
2588     case 'y': /* G_VARIANT_TYPE_BYTE */
2589       if (value != NULL)
2590         {
2591           guint8 v = g_variant_get_byte (value);
2592           g_memory_buffer_put_byte (mbuf, v);
2593         }
2594       break;
2595
2596     case 'n': /* G_VARIANT_TYPE_INT16 */
2597       padding_added = ensure_output_padding (mbuf, 2);
2598       if (value != NULL)
2599         {
2600           gint16 v = g_variant_get_int16 (value);
2601           g_memory_buffer_put_int16 (mbuf, v);
2602         }
2603       break;
2604
2605     case 'q': /* G_VARIANT_TYPE_UINT16 */
2606       padding_added = ensure_output_padding (mbuf, 2);
2607       if (value != NULL)
2608         {
2609           guint16 v = g_variant_get_uint16 (value);
2610           g_memory_buffer_put_uint16 (mbuf, v);
2611         }
2612       break;
2613
2614     case 'i': /* G_VARIANT_TYPE_INT32 */
2615       padding_added = ensure_output_padding (mbuf, 4);
2616       if (value != NULL)
2617         {
2618           gint32 v = g_variant_get_int32 (value);
2619           g_memory_buffer_put_int32 (mbuf, v);
2620         }
2621       break;
2622
2623     case 'u': /* G_VARIANT_TYPE_UINT32 */
2624       padding_added = ensure_output_padding (mbuf, 4);
2625       if (value != NULL)
2626         {
2627           guint32 v = g_variant_get_uint32 (value);
2628           g_memory_buffer_put_uint32 (mbuf, v);
2629         }
2630       break;
2631
2632     case 'x': /* G_VARIANT_TYPE_INT64 */
2633       padding_added = ensure_output_padding (mbuf, 8);
2634       if (value != NULL)
2635         {
2636           gint64 v = g_variant_get_int64 (value);
2637           g_memory_buffer_put_int64 (mbuf, v);
2638         }
2639       break;
2640
2641     case 't': /* G_VARIANT_TYPE_UINT64 */
2642       padding_added = ensure_output_padding (mbuf, 8);
2643       if (value != NULL)
2644         {
2645           guint64 v = g_variant_get_uint64 (value);
2646           g_memory_buffer_put_uint64 (mbuf, v);
2647         }
2648       break;
2649
2650     case 'd': /* G_VARIANT_TYPE_DOUBLE */
2651       padding_added = ensure_output_padding (mbuf, 8);
2652       if (value != NULL)
2653         {
2654           union {
2655             guint64 v_uint64;
2656             gdouble v_double;
2657           } u;
2658           G_STATIC_ASSERT (sizeof (gdouble) == sizeof (guint64));
2659           u.v_double = g_variant_get_double (value);
2660           g_memory_buffer_put_uint64 (mbuf, u.v_uint64);
2661         }
2662       break;
2663
2664     case 's': /* G_VARIANT_TYPE_STRING */
2665       padding_added = ensure_output_padding (mbuf, 4);
2666       if (value != NULL)
2667         {
2668           gsize len;
2669           const gchar *v;
2670 #ifndef G_DISABLE_ASSERT
2671           const gchar *end;
2672 #endif
2673
2674           v = g_variant_get_string (value, &len);
2675           g_assert (g_utf8_validate (v, -1, &end) && (end == v + len));
2676           g_memory_buffer_put_uint32 (mbuf, len);
2677           g_memory_buffer_put_string (mbuf, v);
2678           g_memory_buffer_put_byte (mbuf, '\0');
2679         }
2680       break;
2681
2682     case 'o': /* G_VARIANT_TYPE_OBJECT_PATH */
2683       padding_added = ensure_output_padding (mbuf, 4);
2684       if (value != NULL)
2685         {
2686           gsize len;
2687           const gchar *v = g_variant_get_string (value, &len);
2688           g_assert (g_variant_is_object_path (v));
2689           g_memory_buffer_put_uint32 (mbuf, len);
2690           g_memory_buffer_put_string (mbuf, v);
2691           g_memory_buffer_put_byte (mbuf, '\0');
2692         }
2693       break;
2694
2695     case 'g': /* G_VARIANT_TYPE_SIGNATURE */
2696       if (value != NULL)
2697         {
2698           gsize len;
2699           const gchar *v = g_variant_get_string (value, &len);
2700           g_assert (g_variant_is_signature (v));
2701           g_memory_buffer_put_byte (mbuf, len);
2702           g_memory_buffer_put_string (mbuf, v);
2703           g_memory_buffer_put_byte (mbuf, '\0');
2704         }
2705       break;
2706
2707     case 'h': /* G_VARIANT_TYPE_HANDLE */
2708       padding_added = ensure_output_padding (mbuf, 4);
2709       if (value != NULL)
2710         {
2711           gint32 v = g_variant_get_handle (value);
2712           g_memory_buffer_put_int32 (mbuf, v);
2713         }
2714       break;
2715
2716     case 'a': /* G_VARIANT_TYPE_ARRAY */
2717       {
2718         const GVariantType *element_type;
2719         GVariant *item;
2720         GVariantIter iter;
2721         goffset array_len_offset;
2722         goffset array_payload_begin_offset;
2723         goffset cur_offset;
2724         gsize array_len;
2725         guint fixed_size;
2726
2727         padding_added = ensure_output_padding (mbuf, 4);
2728         if (value != NULL)
2729           {
2730             /* array length - will be filled in later */
2731             array_len_offset = mbuf->valid_len;
2732             g_memory_buffer_put_uint32 (mbuf, 0xF00DFACE);
2733
2734             /* From the D-Bus spec:
2735              *
2736              *   "A UINT32 giving the length of the array data in bytes,
2737              *    followed by alignment padding to the alignment boundary of
2738              *    the array element type, followed by each array element. The
2739              *    array length is from the end of the alignment padding to
2740              *    the end of the last element, i.e. it does not include the
2741              *    padding after the length, or any padding after the last
2742              *    element."
2743              *
2744              * Thus, we need to count how much padding the first element
2745              * contributes and subtract that from the array length.
2746              */
2747             array_payload_begin_offset = mbuf->valid_len;
2748
2749             element_type = g_variant_type_element (type);
2750             fixed_size = get_type_fixed_size (element_type);
2751
2752             if (g_variant_n_children (value) == 0)
2753               {
2754                 gsize padding_added_for_item;
2755                 if (!append_value_to_blob (NULL,
2756                                            element_type,
2757                                            mbuf,
2758                                            &padding_added_for_item,
2759                                            error))
2760                   goto fail;
2761                 array_payload_begin_offset += padding_added_for_item;
2762               }
2763             else if (fixed_size != 0)
2764               {
2765                 GVariant *use_value;
2766
2767                 if (g_memory_buffer_is_byteswapped (mbuf))
2768                   use_value = g_variant_byteswap (value);
2769                 else
2770                   use_value = g_variant_ref (value);
2771
2772                 array_payload_begin_offset += ensure_output_padding (mbuf, fixed_size);
2773
2774                 array_len = g_variant_get_size (use_value);
2775                 g_memory_buffer_write (mbuf, g_variant_get_data (use_value), array_len);
2776                 g_variant_unref (use_value);
2777               }
2778             else
2779               {
2780                 guint n;
2781                 n = 0;
2782                 g_variant_iter_init (&iter, value);
2783                 while ((item = g_variant_iter_next_value (&iter)) != NULL)
2784                   {
2785                     gsize padding_added_for_item;
2786                     if (!append_value_to_blob (item,
2787                                                g_variant_get_type (item),
2788                                                mbuf,
2789                                                &padding_added_for_item,
2790                                                error))
2791                       {
2792                         g_variant_unref (item);
2793                         goto fail;
2794                       }
2795                     g_variant_unref (item);
2796                     if (n == 0)
2797                       {
2798                         array_payload_begin_offset += padding_added_for_item;
2799                       }
2800                     n++;
2801                   }
2802               }
2803
2804             cur_offset = mbuf->valid_len;
2805             array_len = cur_offset - array_payload_begin_offset;
2806             mbuf->pos = array_len_offset;
2807
2808             g_memory_buffer_put_uint32 (mbuf, array_len);
2809             mbuf->pos = cur_offset;
2810           }
2811       }
2812       break;
2813
2814     default:
2815       if (g_variant_type_is_dict_entry (type) || g_variant_type_is_tuple (type))
2816         {
2817           if (!g_variant_type_first (type))
2818             {
2819               g_set_error_literal (error,
2820                                    G_IO_ERROR,
2821                                    G_IO_ERROR_INVALID_ARGUMENT,
2822                                    _("Empty structures (tuples) are not allowed in D-Bus"));
2823               goto fail;
2824             }
2825
2826           padding_added = ensure_output_padding (mbuf, 8);
2827           if (value != NULL)
2828             {
2829               GVariant *item;
2830               GVariantIter iter;
2831               g_variant_iter_init (&iter, value);
2832               while ((item = g_variant_iter_next_value (&iter)) != NULL)
2833                 {
2834                   if (!append_value_to_blob (item,
2835                                              g_variant_get_type (item),
2836                                              mbuf,
2837                                              NULL,
2838                                              error))
2839                     {
2840                       g_variant_unref (item);
2841                       goto fail;
2842                     }
2843                   g_variant_unref (item);
2844                 }
2845             }
2846         }
2847       else if (g_variant_type_is_variant (type))
2848         {
2849           if (value != NULL)
2850             {
2851               GVariant *child;
2852               const gchar *signature;
2853               child = g_variant_get_child_value (value, 0);
2854               signature = g_variant_get_type_string (child);
2855               g_memory_buffer_put_byte (mbuf, strlen (signature));
2856               g_memory_buffer_put_string (mbuf, signature);
2857               g_memory_buffer_put_byte (mbuf, '\0');
2858               if (!append_value_to_blob (child,
2859                                          g_variant_get_type (child),
2860                                          mbuf,
2861                                          NULL,
2862                                          error))
2863                 {
2864                   g_variant_unref (child);
2865                   goto fail;
2866                 }
2867               g_variant_unref (child);
2868             }
2869         }
2870       else
2871         {
2872           g_set_error (error,
2873                        G_IO_ERROR,
2874                        G_IO_ERROR_INVALID_ARGUMENT,
2875                        _("Error serializing GVariant with type string “%s” to the D-Bus wire format"),
2876                        g_variant_get_type_string (value));
2877           goto fail;
2878         }
2879       break;
2880     }
2881
2882   if (out_padding_added != NULL)
2883     *out_padding_added = padding_added;
2884
2885   return TRUE;
2886
2887  fail:
2888   return FALSE;
2889 }
2890
2891 static gboolean
2892 append_body_to_blob (GVariant       *value,
2893                      GMemoryBuffer  *mbuf,
2894                      GError        **error)
2895 {
2896   GVariant *item;
2897   GVariantIter iter;
2898
2899   if (!g_variant_is_of_type (value, G_VARIANT_TYPE_TUPLE))
2900     {
2901       g_set_error (error,
2902                    G_IO_ERROR,
2903                    G_IO_ERROR_INVALID_ARGUMENT,
2904                    "Expected a tuple for the body of the GDBusMessage.");
2905       goto fail;
2906     }
2907
2908   g_variant_iter_init (&iter, value);
2909   while ((item = g_variant_iter_next_value (&iter)) != NULL)
2910     {
2911       if (!append_value_to_blob (item,
2912                                  g_variant_get_type (item),
2913                                  mbuf,
2914                                  NULL,
2915                                  error))
2916         {
2917           g_variant_unref (item);
2918           goto fail;
2919         }
2920       g_variant_unref (item);
2921     }
2922   return TRUE;
2923
2924  fail:
2925   return FALSE;
2926 }
2927
2928 /* ---------------------------------------------------------------------------------------------------- */
2929
2930 /**
2931  * g_dbus_message_to_blob:
2932  * @message: A #GDBusMessage.
2933  * @out_size: Return location for size of generated blob.
2934  * @capabilities: A #GDBusCapabilityFlags describing what protocol features are supported.
2935  * @error: Return location for error.
2936  *
2937  * Serializes @message to a blob. The byte order returned by
2938  * g_dbus_message_get_byte_order() will be used.
2939  *
2940  * Returns: (array length=out_size) (transfer full): A pointer to a
2941  * valid binary D-Bus message of @out_size bytes generated by @message
2942  * or %NULL if @error is set. Free with g_free().
2943  *
2944  * Since: 2.26
2945  */
2946 guchar *
2947 g_dbus_message_to_blob (GDBusMessage          *message,
2948                         gsize                 *out_size,
2949                         GDBusCapabilityFlags   capabilities,
2950                         GError               **error)
2951 {
2952   GMemoryBuffer mbuf;
2953   guchar *ret;
2954   gsize size;
2955   goffset body_len_offset;
2956   goffset body_start_offset;
2957   gsize body_size;
2958   GVariant *header_fields;
2959   GVariantBuilder builder;
2960   GHashTableIter hash_iter;
2961   gpointer key;
2962   GVariant *header_value;
2963   GVariant *signature;
2964   const gchar *signature_str;
2965   gint num_fds_in_message;
2966   gint num_fds_according_to_header;
2967
2968   /* TODO: check against @capabilities */
2969
2970   ret = NULL;
2971
2972   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2973   g_return_val_if_fail (out_size != NULL, NULL);
2974   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2975
2976   memset (&mbuf, 0, sizeof (mbuf));
2977   mbuf.len = MIN_ARRAY_SIZE;
2978   mbuf.data = g_malloc (mbuf.len);
2979
2980   mbuf.byte_order = G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN;
2981   switch (message->byte_order)
2982     {
2983     case G_DBUS_MESSAGE_BYTE_ORDER_BIG_ENDIAN:
2984       mbuf.byte_order = G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN;
2985       break;
2986     case G_DBUS_MESSAGE_BYTE_ORDER_LITTLE_ENDIAN:
2987       mbuf.byte_order = G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN;
2988       break;
2989     }
2990
2991   /* Core header */
2992   g_memory_buffer_put_byte (&mbuf, (guchar) message->byte_order);
2993   g_memory_buffer_put_byte (&mbuf, message->type);
2994   g_memory_buffer_put_byte (&mbuf, message->flags);
2995   g_memory_buffer_put_byte (&mbuf, 1); /* major protocol version */
2996   body_len_offset = mbuf.valid_len;
2997   /* body length - will be filled in later */
2998   g_memory_buffer_put_uint32 (&mbuf, 0xF00DFACE);
2999   g_memory_buffer_put_uint32 (&mbuf, message->serial);
3000
3001   num_fds_in_message = 0;
3002 #ifdef G_OS_UNIX
3003   if (message->fd_list != NULL)
3004     num_fds_in_message = g_unix_fd_list_get_length (message->fd_list);
3005 #endif
3006   num_fds_according_to_header = g_dbus_message_get_num_unix_fds (message);
3007   if (num_fds_in_message != num_fds_according_to_header)
3008     {
3009       g_set_error (error,
3010                    G_IO_ERROR,
3011                    G_IO_ERROR_INVALID_ARGUMENT,
3012                    _("Number of file descriptors in message (%d) differs from header field (%d)"),
3013                    num_fds_in_message,
3014                    num_fds_according_to_header);
3015       goto out;
3016     }
3017
3018   if (!validate_headers (message, error))
3019     {
3020       g_prefix_error (error, _("Cannot serialize message: "));
3021       goto out;
3022     }
3023
3024   g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{yv}"));
3025   g_hash_table_iter_init (&hash_iter, message->headers);
3026   while (g_hash_table_iter_next (&hash_iter, &key, (gpointer) &header_value))
3027     {
3028       g_variant_builder_add (&builder,
3029                              "{yv}",
3030                              (guchar) GPOINTER_TO_UINT (key),
3031                              header_value);
3032     }
3033   header_fields = g_variant_builder_end (&builder);
3034
3035   if (!append_value_to_blob (header_fields,
3036                              g_variant_get_type (header_fields),
3037                              &mbuf,
3038                              NULL,
3039                              error))
3040     {
3041       g_variant_unref (header_fields);
3042       goto out;
3043     }
3044   g_variant_unref (header_fields);
3045
3046   /* header size must be a multiple of 8 */
3047   ensure_output_padding (&mbuf, 8);
3048
3049   body_start_offset = mbuf.valid_len;
3050
3051   signature = g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE);
3052
3053   if (signature != NULL && !g_variant_is_of_type (signature, G_VARIANT_TYPE_SIGNATURE))
3054     {
3055       g_set_error_literal (error,
3056                            G_IO_ERROR,
3057                            G_IO_ERROR_INVALID_ARGUMENT,
3058                            _("Signature header found but is not of type signature"));
3059       goto out;
3060     }
3061
3062   signature_str = NULL;
3063   if (signature != NULL)
3064       signature_str = g_variant_get_string (signature, NULL);
3065   if (message->body != NULL)
3066     {
3067       gchar *tupled_signature_str;
3068       if (signature == NULL)
3069         {
3070           g_set_error (error,
3071                        G_IO_ERROR,
3072                        G_IO_ERROR_INVALID_ARGUMENT,
3073                        _("Message body has signature “%s” but there is no signature header"),
3074                        g_variant_get_type_string (message->body));
3075           goto out;
3076         }
3077       tupled_signature_str = g_strdup_printf ("(%s)", signature_str);
3078       if (g_strcmp0 (tupled_signature_str, g_variant_get_type_string (message->body)) != 0)
3079         {
3080           g_set_error (error,
3081                        G_IO_ERROR,
3082                        G_IO_ERROR_INVALID_ARGUMENT,
3083                        _("Message body has type signature “%s” but signature in the header field is “%s”"),
3084                        g_variant_get_type_string (message->body), tupled_signature_str);
3085           g_free (tupled_signature_str);
3086           goto out;
3087         }
3088       g_free (tupled_signature_str);
3089       if (!append_body_to_blob (message->body, &mbuf, error))
3090         goto out;
3091     }
3092   else
3093     {
3094       if (signature != NULL && strlen (signature_str) > 0)
3095         {
3096           g_set_error (error,
3097                        G_IO_ERROR,
3098                        G_IO_ERROR_INVALID_ARGUMENT,
3099                        _("Message body is empty but signature in the header field is “(%s)”"),
3100                        signature_str);
3101           goto out;
3102         }
3103     }
3104
3105   /* OK, we're done writing the message - set the body length */
3106   size = mbuf.valid_len;
3107   body_size = size - body_start_offset;
3108
3109   mbuf.pos = body_len_offset;
3110
3111   g_memory_buffer_put_uint32 (&mbuf, body_size);
3112
3113   *out_size = size;
3114   ret = (guchar *)mbuf.data;
3115
3116  out:
3117   if (ret == NULL)
3118     g_free (mbuf.data);
3119
3120   return ret;
3121 }
3122
3123 /* ---------------------------------------------------------------------------------------------------- */
3124
3125 static guint32
3126 get_uint32_header (GDBusMessage            *message,
3127                    GDBusMessageHeaderField  header_field)
3128 {
3129   GVariant *value;
3130   guint32 ret;
3131
3132   ret = 0;
3133   value = g_hash_table_lookup (message->headers, GUINT_TO_POINTER (header_field));
3134   if (value != NULL && g_variant_is_of_type (value, G_VARIANT_TYPE_UINT32))
3135     ret = g_variant_get_uint32 (value);
3136
3137   return ret;
3138 }
3139
3140 static const gchar *
3141 get_string_header (GDBusMessage            *message,
3142                    GDBusMessageHeaderField  header_field)
3143 {
3144   GVariant *value;
3145   const gchar *ret;
3146
3147   ret = NULL;
3148   value = g_hash_table_lookup (message->headers, GUINT_TO_POINTER (header_field));
3149   if (value != NULL && g_variant_is_of_type (value, G_VARIANT_TYPE_STRING))
3150     ret = g_variant_get_string (value, NULL);
3151
3152   return ret;
3153 }
3154
3155 static const gchar *
3156 get_object_path_header (GDBusMessage            *message,
3157                         GDBusMessageHeaderField  header_field)
3158 {
3159   GVariant *value;
3160   const gchar *ret;
3161
3162   ret = NULL;
3163   value = g_hash_table_lookup (message->headers, GUINT_TO_POINTER (header_field));
3164   if (value != NULL && g_variant_is_of_type (value, G_VARIANT_TYPE_OBJECT_PATH))
3165     ret = g_variant_get_string (value, NULL);
3166
3167   return ret;
3168 }
3169
3170 static const gchar *
3171 get_signature_header (GDBusMessage            *message,
3172                       GDBusMessageHeaderField  header_field)
3173 {
3174   GVariant *value;
3175   const gchar *ret;
3176
3177   ret = NULL;
3178   value = g_hash_table_lookup (message->headers, GUINT_TO_POINTER (header_field));
3179   if (value != NULL && g_variant_is_of_type (value, G_VARIANT_TYPE_SIGNATURE))
3180     ret = g_variant_get_string (value, NULL);
3181
3182   return ret;
3183 }
3184
3185 /* ---------------------------------------------------------------------------------------------------- */
3186
3187 static void
3188 set_uint32_header (GDBusMessage             *message,
3189                    GDBusMessageHeaderField   header_field,
3190                    guint32                   value)
3191 {
3192   g_dbus_message_set_header (message,
3193                              header_field,
3194                              g_variant_new_uint32 (value));
3195 }
3196
3197 static void
3198 set_string_header (GDBusMessage             *message,
3199                    GDBusMessageHeaderField   header_field,
3200                    const gchar              *value)
3201 {
3202   g_dbus_message_set_header (message,
3203                              header_field,
3204                              value == NULL ? NULL : g_variant_new_string (value));
3205 }
3206
3207 static void
3208 set_object_path_header (GDBusMessage             *message,
3209                         GDBusMessageHeaderField   header_field,
3210                         const gchar              *value)
3211 {
3212   g_dbus_message_set_header (message,
3213                              header_field,
3214                              value == NULL ? NULL : g_variant_new_object_path (value));
3215 }
3216
3217 static void
3218 set_signature_header (GDBusMessage             *message,
3219                       GDBusMessageHeaderField   header_field,
3220                       const gchar              *value)
3221 {
3222   g_dbus_message_set_header (message,
3223                              header_field,
3224                              value == NULL ? NULL : g_variant_new_signature (value));
3225 }
3226
3227 /* ---------------------------------------------------------------------------------------------------- */
3228
3229 /**
3230  * g_dbus_message_get_reply_serial:
3231  * @message: A #GDBusMessage.
3232  *
3233  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL header field.
3234  *
3235  * Returns: The value.
3236  *
3237  * Since: 2.26
3238  */
3239 guint32
3240 g_dbus_message_get_reply_serial (GDBusMessage  *message)
3241 {
3242   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), 0);
3243   return get_uint32_header (message, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL);
3244 }
3245
3246 /**
3247  * g_dbus_message_set_reply_serial:
3248  * @message: A #GDBusMessage.
3249  * @value: The value to set.
3250  *
3251  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL header field.
3252  *
3253  * Since: 2.26
3254  */
3255 void
3256 g_dbus_message_set_reply_serial (GDBusMessage  *message,
3257                                  guint32        value)
3258 {
3259   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3260   set_uint32_header (message, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL, value);
3261 }
3262
3263 /* ---------------------------------------------------------------------------------------------------- */
3264
3265 /**
3266  * g_dbus_message_get_interface:
3267  * @message: A #GDBusMessage.
3268  *
3269  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE header field.
3270  *
3271  * Returns: (nullable): The value.
3272  *
3273  * Since: 2.26
3274  */
3275 const gchar *
3276 g_dbus_message_get_interface (GDBusMessage  *message)
3277 {
3278   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3279   return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE);
3280 }
3281
3282 /**
3283  * g_dbus_message_set_interface:
3284  * @message: A #GDBusMessage.
3285  * @value: (nullable): The value to set.
3286  *
3287  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE header field.
3288  *
3289  * Since: 2.26
3290  */
3291 void
3292 g_dbus_message_set_interface (GDBusMessage  *message,
3293                               const gchar   *value)
3294 {
3295   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3296   g_return_if_fail (value == NULL || g_dbus_is_interface_name (value));
3297   set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE, value);
3298 }
3299
3300 /* ---------------------------------------------------------------------------------------------------- */
3301
3302 /**
3303  * g_dbus_message_get_member:
3304  * @message: A #GDBusMessage.
3305  *
3306  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_MEMBER header field.
3307  *
3308  * Returns: (nullable): The value.
3309  *
3310  * Since: 2.26
3311  */
3312 const gchar *
3313 g_dbus_message_get_member (GDBusMessage  *message)
3314 {
3315   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3316   return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER);
3317 }
3318
3319 /**
3320  * g_dbus_message_set_member:
3321  * @message: A #GDBusMessage.
3322  * @value: (nullable): The value to set.
3323  *
3324  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_MEMBER header field.
3325  *
3326  * Since: 2.26
3327  */
3328 void
3329 g_dbus_message_set_member (GDBusMessage  *message,
3330                            const gchar   *value)
3331 {
3332   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3333   g_return_if_fail (value == NULL || g_dbus_is_member_name (value));
3334   set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER, value);
3335 }
3336
3337 /* ---------------------------------------------------------------------------------------------------- */
3338
3339 /**
3340  * g_dbus_message_get_path:
3341  * @message: A #GDBusMessage.
3342  *
3343  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_PATH header field.
3344  *
3345  * Returns: (nullable): The value.
3346  *
3347  * Since: 2.26
3348  */
3349 const gchar *
3350 g_dbus_message_get_path (GDBusMessage  *message)
3351 {
3352   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3353   return get_object_path_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH);
3354 }
3355
3356 /**
3357  * g_dbus_message_set_path:
3358  * @message: A #GDBusMessage.
3359  * @value: (nullable): The value to set.
3360  *
3361  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_PATH header field.
3362  *
3363  * Since: 2.26
3364  */
3365 void
3366 g_dbus_message_set_path (GDBusMessage  *message,
3367                          const gchar   *value)
3368 {
3369   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3370   g_return_if_fail (value == NULL || g_variant_is_object_path (value));
3371   set_object_path_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH, value);
3372 }
3373
3374 /* ---------------------------------------------------------------------------------------------------- */
3375
3376 /**
3377  * g_dbus_message_get_sender:
3378  * @message: A #GDBusMessage.
3379  *
3380  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_SENDER header field.
3381  *
3382  * Returns: (nullable): The value.
3383  *
3384  * Since: 2.26
3385  */
3386 const gchar *
3387 g_dbus_message_get_sender (GDBusMessage *message)
3388 {
3389   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3390   return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SENDER);
3391 }
3392
3393 /**
3394  * g_dbus_message_set_sender:
3395  * @message: A #GDBusMessage.
3396  * @value: (nullable): The value to set.
3397  *
3398  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_SENDER header field.
3399  *
3400  * Since: 2.26
3401  */
3402 void
3403 g_dbus_message_set_sender (GDBusMessage  *message,
3404                            const gchar   *value)
3405 {
3406   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3407   g_return_if_fail (value == NULL || g_dbus_is_name (value));
3408   set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SENDER, value);
3409 }
3410
3411 /* ---------------------------------------------------------------------------------------------------- */
3412
3413 /**
3414  * g_dbus_message_get_destination:
3415  * @message: A #GDBusMessage.
3416  *
3417  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION header field.
3418  *
3419  * Returns: (nullable): The value.
3420  *
3421  * Since: 2.26
3422  */
3423 const gchar *
3424 g_dbus_message_get_destination (GDBusMessage  *message)
3425 {
3426   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3427   return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION);
3428 }
3429
3430 /**
3431  * g_dbus_message_set_destination:
3432  * @message: A #GDBusMessage.
3433  * @value: (nullable): The value to set.
3434  *
3435  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION header field.
3436  *
3437  * Since: 2.26
3438  */
3439 void
3440 g_dbus_message_set_destination (GDBusMessage  *message,
3441                                 const gchar   *value)
3442 {
3443   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3444   g_return_if_fail (value == NULL || g_dbus_is_name (value));
3445   set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION, value);
3446 }
3447
3448 /* ---------------------------------------------------------------------------------------------------- */
3449
3450 /**
3451  * g_dbus_message_get_error_name:
3452  * @message: A #GDBusMessage.
3453  *
3454  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME header field.
3455  *
3456  * Returns: (nullable): The value.
3457  *
3458  * Since: 2.26
3459  */
3460 const gchar *
3461 g_dbus_message_get_error_name (GDBusMessage  *message)
3462 {
3463   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3464   return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME);
3465 }
3466
3467 /**
3468  * g_dbus_message_set_error_name:
3469  * @message: (nullable): A #GDBusMessage.
3470  * @value: The value to set.
3471  *
3472  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME header field.
3473  *
3474  * Since: 2.26
3475  */
3476 void
3477 g_dbus_message_set_error_name (GDBusMessage  *message,
3478                                const gchar   *value)
3479 {
3480   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3481   g_return_if_fail (value == NULL || g_dbus_is_error_name (value));
3482   set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME, value);
3483 }
3484
3485 /* ---------------------------------------------------------------------------------------------------- */
3486
3487 /**
3488  * g_dbus_message_get_signature:
3489  * @message: A #GDBusMessage.
3490  *
3491  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE header field.
3492  *
3493  * This will always be non-%NULL, but may be an empty string.
3494  *
3495  * Returns: (not nullable): The value.
3496  *
3497  * Since: 2.26
3498  */
3499 const gchar *
3500 g_dbus_message_get_signature (GDBusMessage  *message)
3501 {
3502   const gchar *ret;
3503   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3504   ret = get_signature_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE);
3505   if (ret == NULL)
3506     ret = "";
3507   return ret;
3508 }
3509
3510 /**
3511  * g_dbus_message_set_signature:
3512  * @message: A #GDBusMessage.
3513  * @value: (nullable): The value to set.
3514  *
3515  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE header field.
3516  *
3517  * Since: 2.26
3518  */
3519 void
3520 g_dbus_message_set_signature (GDBusMessage  *message,
3521                               const gchar   *value)
3522 {
3523   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3524   g_return_if_fail (value == NULL || g_variant_is_signature (value));
3525   set_signature_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE, value);
3526 }
3527
3528 /* ---------------------------------------------------------------------------------------------------- */
3529
3530 /**
3531  * g_dbus_message_get_arg0:
3532  * @message: A #GDBusMessage.
3533  *
3534  * Convenience to get the first item in the body of @message.
3535  *
3536  * See [method@Gio.DBusMessage.get_arg0_path] for returning object-path-typed
3537  * arg0 values.
3538  *
3539  * Returns: (nullable): The string item or %NULL if the first item in the body of
3540  * @message is not a string.
3541  *
3542  * Since: 2.26
3543  */
3544 const gchar *
3545 g_dbus_message_get_arg0 (GDBusMessage  *message)
3546 {
3547   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3548
3549   if (message->arg0_cache != NULL &&
3550       g_variant_is_of_type (message->arg0_cache, G_VARIANT_TYPE_STRING))
3551     return g_variant_get_string (message->arg0_cache, NULL);
3552
3553   return NULL;
3554 }
3555
3556 /**
3557  * g_dbus_message_get_arg0_path:
3558  * @message: A `GDBusMessage`.
3559  *
3560  * Convenience to get the first item in the body of @message.
3561  *
3562  * See [method@Gio.DBusMessage.get_arg0] for returning string-typed arg0 values.
3563  *
3564  * Returns: (nullable): The object path item or `NULL` if the first item in the
3565  *   body of @message is not an object path.
3566  *
3567  * Since: 2.80
3568  */
3569 const gchar *
3570 g_dbus_message_get_arg0_path (GDBusMessage  *message)
3571 {
3572   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3573
3574   if (message->arg0_cache != NULL &&
3575       g_variant_is_of_type (message->arg0_cache, G_VARIANT_TYPE_OBJECT_PATH))
3576     return g_variant_get_string (message->arg0_cache, NULL);
3577
3578   return NULL;
3579 }
3580
3581 /* ---------------------------------------------------------------------------------------------------- */
3582
3583 /**
3584  * g_dbus_message_get_num_unix_fds:
3585  * @message: A #GDBusMessage.
3586  *
3587  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS header field.
3588  *
3589  * Returns: The value.
3590  *
3591  * Since: 2.26
3592  */
3593 guint32
3594 g_dbus_message_get_num_unix_fds (GDBusMessage *message)
3595 {
3596   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), 0);
3597   return get_uint32_header (message, G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS);
3598 }
3599
3600 /**
3601  * g_dbus_message_set_num_unix_fds:
3602  * @message: A #GDBusMessage.
3603  * @value: The value to set.
3604  *
3605  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS header field.
3606  *
3607  * Since: 2.26
3608  */
3609 void
3610 g_dbus_message_set_num_unix_fds (GDBusMessage  *message,
3611                                  guint32        value)
3612 {
3613   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3614   set_uint32_header (message, G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS, value);
3615 }
3616
3617 /* ---------------------------------------------------------------------------------------------------- */
3618
3619 /**
3620  * g_dbus_message_to_gerror:
3621  * @message: A #GDBusMessage.
3622  * @error: The #GError to set.
3623  *
3624  * If @message is not of type %G_DBUS_MESSAGE_TYPE_ERROR does
3625  * nothing and returns %FALSE.
3626  *
3627  * Otherwise this method encodes the error in @message as a #GError
3628  * using g_dbus_error_set_dbus_error() using the information in the
3629  * %G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME header field of @message as
3630  * well as the first string item in @message's body.
3631  *
3632  * Returns: %TRUE if @error was set, %FALSE otherwise.
3633  *
3634  * Since: 2.26
3635  */
3636 gboolean
3637 g_dbus_message_to_gerror (GDBusMessage   *message,
3638                           GError        **error)
3639 {
3640   gboolean ret;
3641   const gchar *error_name;
3642
3643   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), FALSE);
3644
3645   ret = FALSE;
3646   if (message->type != G_DBUS_MESSAGE_TYPE_ERROR)
3647     goto out;
3648
3649   error_name = g_dbus_message_get_error_name (message);
3650   if (error_name != NULL)
3651     {
3652       GVariant *body;
3653
3654       body = g_dbus_message_get_body (message);
3655
3656       if (body != NULL && g_variant_is_of_type (body, G_VARIANT_TYPE ("(s)")))
3657         {
3658           const gchar *error_message;
3659           g_variant_get (body, "(&s)", &error_message);
3660           g_dbus_error_set_dbus_error (error,
3661                                        error_name,
3662                                        error_message,
3663                                        NULL);
3664         }
3665       else
3666         {
3667           /* these two situations are valid, yet pretty rare */
3668           if (body != NULL)
3669             {
3670               g_dbus_error_set_dbus_error (error,
3671                                            error_name,
3672                                            "",
3673                                            _("Error return with body of type “%s”"),
3674                                            g_variant_get_type_string (body));
3675             }
3676           else
3677             {
3678               g_dbus_error_set_dbus_error (error,
3679                                            error_name,
3680                                            "",
3681                                            _("Error return with empty body"));
3682             }
3683         }
3684     }
3685   else
3686     {
3687       /* TODO: this shouldn't happen - should check this at message serialization
3688        * time and disconnect the peer.
3689        */
3690       g_set_error (error,
3691                    G_IO_ERROR,
3692                    G_IO_ERROR_FAILED,
3693                    "Error return without error-name header!");
3694     }
3695
3696   ret = TRUE;
3697
3698  out:
3699   return ret;
3700 }
3701
3702 /* ---------------------------------------------------------------------------------------------------- */
3703
3704 static gchar *
3705 flags_to_string (GType flags_type, guint value)
3706 {
3707   GString *s;
3708   GFlagsClass *klass;
3709   guint n;
3710
3711   klass = g_type_class_ref (flags_type);
3712   s = g_string_new (NULL);
3713   for (n = 0; n < 32; n++)
3714     {
3715       if ((value & (1<<n)) != 0)
3716         {
3717           GFlagsValue *flags_value;
3718           flags_value = g_flags_get_first_value (klass, (1<<n));
3719           if (s->len > 0)
3720             g_string_append_c (s, ',');
3721           if (flags_value != NULL)
3722             g_string_append (s, flags_value->value_nick);
3723           else
3724             g_string_append_printf (s, "unknown (bit %d)", n);
3725         }
3726     }
3727   if (s->len == 0)
3728     g_string_append (s, "none");
3729   g_type_class_unref (klass);
3730   return g_string_free (s, FALSE);
3731 }
3732
3733 static gint
3734 _sort_keys_func (gconstpointer a,
3735                  gconstpointer b)
3736 {
3737   gint ia;
3738   gint ib;
3739
3740   ia = GPOINTER_TO_INT (a);
3741   ib = GPOINTER_TO_INT (b);
3742
3743   return ia - ib;
3744 }
3745
3746 /**
3747  * g_dbus_message_print:
3748  * @message: A #GDBusMessage.
3749  * @indent: Indentation level.
3750  *
3751  * Produces a human-readable multi-line description of @message.
3752  *
3753  * The contents of the description has no ABI guarantees, the contents
3754  * and formatting is subject to change at any time. Typical output
3755  * looks something like this:
3756  * ```
3757  * Type:    method-call
3758  * Flags:   none
3759  * Version: 0
3760  * Serial:  4
3761  * Headers:
3762  *   path -> objectpath '/org/gtk/GDBus/TestObject'
3763  *   interface -> 'org.gtk.GDBus.TestInterface'
3764  *   member -> 'GimmeStdout'
3765  *   destination -> ':1.146'
3766  * Body: ()
3767  * UNIX File Descriptors:
3768  *   (none)
3769  * ```
3770  * or
3771  * ```
3772  * Type:    method-return
3773  * Flags:   no-reply-expected
3774  * Version: 0
3775  * Serial:  477
3776  * Headers:
3777  *   reply-serial -> uint32 4
3778  *   destination -> ':1.159'
3779  *   sender -> ':1.146'
3780  *   num-unix-fds -> uint32 1
3781  * Body: ()
3782  * UNIX File Descriptors:
3783  *   fd 12: dev=0:10,mode=020620,ino=5,uid=500,gid=5,rdev=136:2,size=0,atime=1273085037,mtime=1273085851,ctime=1272982635
3784  * ```
3785  *
3786  * Returns: (not nullable): A string that should be freed with [func@GLib.free].
3787  *
3788  * Since: 2.26
3789  */
3790 gchar *
3791 g_dbus_message_print (GDBusMessage *message,
3792                       guint         indent)
3793 {
3794   GString *str;
3795   gchar *s;
3796   GList *keys;
3797   GList *l;
3798
3799   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3800
3801   str = g_string_new (NULL);
3802
3803   s = _g_dbus_enum_to_string (G_TYPE_DBUS_MESSAGE_TYPE, message->type);
3804   g_string_append_printf (str, "%*sType:    %s\n", indent, "", s);
3805   g_free (s);
3806   s = flags_to_string (G_TYPE_DBUS_MESSAGE_FLAGS, message->flags);
3807   g_string_append_printf (str, "%*sFlags:   %s\n", indent, "", s);
3808   g_free (s);
3809   g_string_append_printf (str, "%*sVersion: %d\n", indent, "", message->major_protocol_version);
3810   g_string_append_printf (str, "%*sSerial:  %d\n", indent, "", message->serial);
3811
3812   g_string_append_printf (str, "%*sHeaders:\n", indent, "");
3813   keys = g_hash_table_get_keys (message->headers);
3814   keys = g_list_sort (keys, _sort_keys_func);
3815   if (keys != NULL)
3816     {
3817       for (l = keys; l != NULL; l = l->next)
3818         {
3819           gint key = GPOINTER_TO_INT (l->data);
3820           GVariant *value;
3821           gchar *value_str;
3822
3823           value = g_hash_table_lookup (message->headers, l->data);
3824           g_assert (value != NULL);
3825
3826           s = _g_dbus_enum_to_string (G_TYPE_DBUS_MESSAGE_HEADER_FIELD, key);
3827           value_str = g_variant_print (value, TRUE);
3828           g_string_append_printf (str, "%*s  %s -> %s\n", indent, "", s, value_str);
3829           g_free (s);
3830           g_free (value_str);
3831         }
3832     }
3833   else
3834     {
3835       g_string_append_printf (str, "%*s  (none)\n", indent, "");
3836     }
3837   g_list_free (keys);
3838   g_string_append_printf (str, "%*sBody: ", indent, "");
3839   if (message->body != NULL)
3840     {
3841       g_variant_print_string (message->body,
3842                               str,
3843                               TRUE);
3844     }
3845   else
3846     {
3847       g_string_append (str, "()");
3848     }
3849   g_string_append (str, "\n");
3850 #ifdef G_OS_UNIX
3851   g_string_append_printf (str, "%*sUNIX File Descriptors:\n", indent, "");
3852   if (message->fd_list != NULL)
3853     {
3854       gint num_fds;
3855       const gint *fds;
3856       gint n;
3857
3858       fds = g_unix_fd_list_peek_fds (message->fd_list, &num_fds);
3859       if (num_fds > 0)
3860         {
3861           for (n = 0; n < num_fds; n++)
3862             {
3863               GString *fs;
3864               struct stat statbuf;
3865               fs = g_string_new (NULL);
3866               if (fstat (fds[n], &statbuf) == 0)
3867                 {
3868 #ifndef MAJOR_MINOR_NOT_FOUND                       
3869                   g_string_append_printf (fs, "%s" "dev=%d:%d", fs->len > 0 ? "," : "",
3870                                           (gint) major (statbuf.st_dev), (gint) minor (statbuf.st_dev));
3871 #endif                  
3872                   g_string_append_printf (fs, "%s" "mode=0%o", fs->len > 0 ? "," : "",
3873                                           (guint) statbuf.st_mode);
3874                   g_string_append_printf (fs, "%s" "ino=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
3875                                           (guint64) statbuf.st_ino);
3876                   g_string_append_printf (fs, "%s" "uid=%u", fs->len > 0 ? "," : "",
3877                                           (guint) statbuf.st_uid);
3878                   g_string_append_printf (fs, "%s" "gid=%u", fs->len > 0 ? "," : "",
3879                                           (guint) statbuf.st_gid);
3880 #ifndef MAJOR_MINOR_NOT_FOUND                     
3881                   g_string_append_printf (fs, "%s" "rdev=%d:%d", fs->len > 0 ? "," : "",
3882                                           (gint) major (statbuf.st_rdev), (gint) minor (statbuf.st_rdev));
3883 #endif                  
3884                   g_string_append_printf (fs, "%s" "size=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
3885                                           (guint64) statbuf.st_size);
3886                   g_string_append_printf (fs, "%s" "atime=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
3887                                           (guint64) statbuf.st_atime);
3888                   g_string_append_printf (fs, "%s" "mtime=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
3889                                           (guint64) statbuf.st_mtime);
3890                   g_string_append_printf (fs, "%s" "ctime=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
3891                                           (guint64) statbuf.st_ctime);
3892                 }
3893               else
3894                 {
3895                   int errsv = errno;
3896                   g_string_append_printf (fs, "(fstat failed: %s)", g_strerror (errsv));
3897                 }
3898               g_string_append_printf (str, "%*s  fd %d: %s\n", indent, "", fds[n], fs->str);
3899               g_string_free (fs, TRUE);
3900             }
3901         }
3902       else
3903         {
3904           g_string_append_printf (str, "%*s  (empty)\n", indent, "");
3905         }
3906     }
3907   else
3908     {
3909       g_string_append_printf (str, "%*s  (none)\n", indent, "");
3910     }
3911 #endif
3912
3913   return g_string_free (str, FALSE);
3914 }
3915
3916 /**
3917  * g_dbus_message_get_locked:
3918  * @message: A #GDBusMessage.
3919  *
3920  * Checks whether @message is locked. To monitor changes to this
3921  * value, conncet to the #GObject::notify signal to listen for changes
3922  * on the #GDBusMessage:locked property.
3923  *
3924  * Returns: %TRUE if @message is locked, %FALSE otherwise.
3925  *
3926  * Since: 2.26
3927  */
3928 gboolean
3929 g_dbus_message_get_locked (GDBusMessage *message)
3930 {
3931   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), FALSE);
3932   return message->locked;
3933 }
3934
3935 /**
3936  * g_dbus_message_lock:
3937  * @message: A #GDBusMessage.
3938  *
3939  * If @message is locked, does nothing. Otherwise locks the message.
3940  *
3941  * Since: 2.26
3942  */
3943 void
3944 g_dbus_message_lock (GDBusMessage *message)
3945 {
3946   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3947
3948   if (message->locked)
3949     goto out;
3950
3951   message->locked = TRUE;
3952   g_object_notify (G_OBJECT (message), "locked");
3953
3954  out:
3955   ;
3956 }
3957
3958 /**
3959  * g_dbus_message_copy:
3960  * @message: A #GDBusMessage.
3961  * @error: Return location for error or %NULL.
3962  *
3963  * Copies @message. The copy is a deep copy and the returned
3964  * #GDBusMessage is completely identical except that it is guaranteed
3965  * to not be locked.
3966  *
3967  * This operation can fail if e.g. @message contains file descriptors
3968  * and the per-process or system-wide open files limit is reached.
3969  *
3970  * Returns: (transfer full): A new #GDBusMessage or %NULL if @error is set.
3971  *     Free with g_object_unref().
3972  *
3973  * Since: 2.26
3974  */
3975 GDBusMessage *
3976 g_dbus_message_copy (GDBusMessage  *message,
3977                      GError       **error)
3978 {
3979   GDBusMessage *ret;
3980   GHashTableIter iter;
3981   gpointer header_key;
3982   GVariant *header_value;
3983
3984   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3985   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
3986
3987   ret = g_dbus_message_new ();
3988   ret->type                   = message->type;
3989   ret->flags                  = message->flags;
3990   ret->byte_order             = message->byte_order;
3991   ret->major_protocol_version = message->major_protocol_version;
3992   ret->serial                 = message->serial;
3993
3994 #ifdef G_OS_UNIX
3995   if (message->fd_list != NULL)
3996     {
3997       gint n;
3998       gint num_fds;
3999       const gint *fds;
4000
4001       ret->fd_list = g_unix_fd_list_new ();
4002       fds = g_unix_fd_list_peek_fds (message->fd_list, &num_fds);
4003       for (n = 0; n < num_fds; n++)
4004         {
4005           if (g_unix_fd_list_append (ret->fd_list,
4006                                      fds[n],
4007                                      error) == -1)
4008             {
4009               g_object_unref (ret);
4010               ret = NULL;
4011               goto out;
4012             }
4013         }
4014     }
4015 #endif
4016
4017   /* see https://bugzilla.gnome.org/show_bug.cgi?id=624546#c8 for why it's fine
4018    * to just ref (as opposed to deep-copying) the GVariant instances
4019    */
4020   ret->body = message->body != NULL ? g_variant_ref (message->body) : NULL;
4021   ret->arg0_cache = message->arg0_cache != NULL ? g_variant_ref (message->arg0_cache) : NULL;
4022   g_hash_table_iter_init (&iter, message->headers);
4023   while (g_hash_table_iter_next (&iter, &header_key, (gpointer) &header_value))
4024     g_hash_table_insert (ret->headers, header_key, g_variant_ref (header_value));
4025
4026 #ifdef G_OS_UNIX
4027  out:
4028 #endif
4029   return ret;
4030 }
4031
4032 void
4033 g_dbus_message_init_header_iter (GDBusMessage   *message,
4034                                  GHashTableIter *iter)
4035 {
4036   g_hash_table_iter_init (iter, message->headers);
4037 }