GDBusMessage: Validate UTF-8 strings when serializing from blob
[platform/upstream/glib.git] / gio / gdbusmessage.c
1 /* GDBus - GLib D-Bus Library
2  *
3  * Copyright (C) 2008-2010 Red Hat, Inc.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General
16  * Public License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18  * Boston, MA 02111-1307, USA.
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 #ifdef HAVE_UNISTD_H
33 #include <unistd.h>
34 #endif
35
36 #include "gdbusutils.h"
37 #include "gdbusmessage.h"
38 #include "gdbuserror.h"
39 #include "gioenumtypes.h"
40 #include "ginputstream.h"
41 #include "gdatainputstream.h"
42 #include "gmemoryinputstream.h"
43 #include "goutputstream.h"
44 #include "gdataoutputstream.h"
45 #include "gmemoryoutputstream.h"
46 #include "gseekable.h"
47 #include "gioerror.h"
48 #include "gdbusprivate.h"
49
50 #ifdef G_OS_UNIX
51 #include "gunixfdlist.h"
52 #endif
53
54 #include "glibintl.h"
55
56 /**
57  * SECTION:gdbusmessage
58  * @short_description: D-Bus Message
59  * @include: gio/gio.h
60  *
61  * A type for representing D-Bus messages that can be sent or received
62  * on a #GDBusConnection.
63  */
64
65 typedef struct _GDBusMessageClass GDBusMessageClass;
66
67 /**
68  * GDBusMessageClass:
69  *
70  * Class structure for #GDBusMessage.
71  *
72  * Since: 2.26
73  */
74 struct _GDBusMessageClass
75 {
76   /*< private >*/
77   GObjectClass parent_class;
78 };
79
80 /**
81  * GDBusMessage:
82  *
83  * The #GDBusMessage structure contains only private data and should
84  * only be accessed using the provided API.
85  *
86  * Since: 2.26
87  */
88 struct _GDBusMessage
89 {
90   /*< private >*/
91   GObject parent_instance;
92
93   GDBusMessageType type;
94   GDBusMessageFlags flags;
95   guchar major_protocol_version;
96   guint32 serial;
97   GHashTable *headers;
98   GVariant *body;
99 #ifdef G_OS_UNIX
100   GUnixFDList *fd_list;
101 #endif
102 };
103
104 G_DEFINE_TYPE (GDBusMessage, g_dbus_message, G_TYPE_OBJECT);
105
106 static void
107 g_dbus_message_finalize (GObject *object)
108 {
109   GDBusMessage *message = G_DBUS_MESSAGE (object);
110
111   if (message->headers != NULL)
112     g_hash_table_unref (message->headers);
113   if (message->body != NULL)
114     g_variant_unref (message->body);
115 #ifdef G_OS_UNIX
116   if (message->fd_list != NULL)
117     g_object_unref (message->fd_list);
118 #endif
119
120   if (G_OBJECT_CLASS (g_dbus_message_parent_class)->finalize != NULL)
121     G_OBJECT_CLASS (g_dbus_message_parent_class)->finalize (object);
122 }
123
124 static void
125 g_dbus_message_class_init (GDBusMessageClass *klass)
126 {
127   GObjectClass *gobject_class;
128
129   gobject_class = G_OBJECT_CLASS (klass);
130
131   gobject_class->finalize     = g_dbus_message_finalize;
132 }
133
134 static void
135 g_dbus_message_init (GDBusMessage *message)
136 {
137   message->headers = g_hash_table_new_full (g_direct_hash,
138                                             g_direct_equal,
139                                             NULL,
140                                             (GDestroyNotify) g_variant_unref);
141 }
142
143 /**
144  * g_dbus_message_new:
145  *
146  * Creates a new empty #GDBusMessage.
147  *
148  * Returns: A #GDBusMessage. Free with g_object_unref().
149  *
150  * Since: 2.26
151  */
152 GDBusMessage *
153 g_dbus_message_new (void)
154 {
155   return g_object_new (G_TYPE_DBUS_MESSAGE, NULL);
156 }
157
158 /**
159  * g_dbus_message_new_method_call:
160  * @name: A valid D-Bus name or %NULL.
161  * @path: A valid object path.
162  * @interface_: A valid D-Bus interface name or %NULL.
163  * @method: A valid method name.
164  *
165  * Creates a new #GDBusMessage for a method call.
166  *
167  * Returns: A #GDBusMessage. Free with g_object_unref().
168  *
169  * Since: 2.26
170  */
171 GDBusMessage *
172 g_dbus_message_new_method_call (const gchar *name,
173                                 const gchar *path,
174                                 const gchar *interface_,
175                                 const gchar *method)
176 {
177   GDBusMessage *message;
178
179   g_return_val_if_fail (name == NULL || g_dbus_is_name (name), NULL);
180   g_return_val_if_fail (g_variant_is_object_path (path), NULL);
181   g_return_val_if_fail (g_dbus_is_member_name (method), NULL);
182   g_return_val_if_fail (interface_ == NULL || g_dbus_is_interface_name (interface_), NULL);
183
184   message = g_dbus_message_new ();
185   message->type = G_DBUS_MESSAGE_TYPE_METHOD_CALL;
186
187   if (name != NULL)
188     g_dbus_message_set_destination (message, name);
189   g_dbus_message_set_path (message, path);
190   g_dbus_message_set_member (message, method);
191   if (interface_ != NULL)
192     g_dbus_message_set_interface (message, interface_);
193
194   return message;
195 }
196
197 /**
198  * g_dbus_message_new_signal:
199  * @path: A valid object path.
200  * @interface_: A valid D-Bus interface name or %NULL.
201  * @signal: A valid signal name.
202  *
203  * Creates a new #GDBusMessage for a signal emission.
204  *
205  * Returns: A #GDBusMessage. Free with g_object_unref().
206  *
207  * Since: 2.26
208  */
209 GDBusMessage *
210 g_dbus_message_new_signal (const gchar  *path,
211                            const gchar  *interface_,
212                            const gchar  *signal)
213 {
214   GDBusMessage *message;
215
216   g_return_val_if_fail (g_variant_is_object_path (path), NULL);
217   g_return_val_if_fail (g_dbus_is_member_name (signal), NULL);
218   g_return_val_if_fail (interface_ == NULL || g_dbus_is_interface_name (interface_), NULL);
219
220   message = g_dbus_message_new ();
221   message->type = G_DBUS_MESSAGE_TYPE_SIGNAL;
222   message->flags = G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED;
223
224   g_dbus_message_set_path (message, path);
225   g_dbus_message_set_member (message, signal);
226
227   if (interface_ != NULL)
228     g_dbus_message_set_interface (message, interface_);
229
230   return message;
231 }
232
233
234 /**
235  * g_dbus_message_new_method_reply:
236  * @method_call_message: A message of type %G_DBUS_MESSAGE_TYPE_METHOD_CALL to
237  * create a reply message to.
238  *
239  * Creates a new #GDBusMessage that is a reply to @method_call_message.
240  *
241  * Returns: A #GDBusMessage. Free with g_object_unref().
242  *
243  * Since: 2.26
244  */
245 GDBusMessage *
246 g_dbus_message_new_method_reply (GDBusMessage *method_call_message)
247 {
248   GDBusMessage *message;
249   const gchar *sender;
250
251   g_return_val_if_fail (G_IS_DBUS_MESSAGE (method_call_message), NULL);
252   g_return_val_if_fail (g_dbus_message_get_message_type (method_call_message) == G_DBUS_MESSAGE_TYPE_METHOD_CALL, NULL);
253   g_return_val_if_fail (g_dbus_message_get_serial (method_call_message) != 0, NULL);
254
255   message = g_dbus_message_new ();
256   message->type = G_DBUS_MESSAGE_TYPE_METHOD_RETURN;
257   message->flags = G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED;
258
259   g_dbus_message_set_reply_serial (message, g_dbus_message_get_serial (method_call_message));
260   sender = g_dbus_message_get_sender (method_call_message);
261   if (sender != NULL)
262     g_dbus_message_set_destination (message, sender);
263
264   return message;
265 }
266
267 /**
268  * g_dbus_message_new_method_error:
269  * @method_call_message: A message of type %G_DBUS_MESSAGE_TYPE_METHOD_CALL to
270  * create a reply message to.
271  * @error_name: A valid D-Bus error name.
272  * @error_message_format: The D-Bus error message in a printf() format.
273  * @...: Arguments for @error_message_format.
274  *
275  * Creates a new #GDBusMessage that is an error reply to @method_call_message.
276  *
277  * Returns: A #GDBusMessage. Free with g_object_unref().
278  *
279  * Since: 2.26
280  */
281 GDBusMessage *
282 g_dbus_message_new_method_error (GDBusMessage             *method_call_message,
283                                  const gchar              *error_name,
284                                  const gchar              *error_message_format,
285                                  ...)
286 {
287   GDBusMessage *ret;
288   va_list var_args;
289
290   va_start (var_args, error_message_format);
291   ret = g_dbus_message_new_method_error_valist (method_call_message,
292                                                 error_name,
293                                                 error_message_format,
294                                                 var_args);
295   va_end (var_args);
296
297   return ret;
298 }
299
300 /**
301  * g_dbus_message_new_method_error_literal:
302  * @method_call_message: A message of type %G_DBUS_MESSAGE_TYPE_METHOD_CALL to
303  * create a reply message to.
304  * @error_name: A valid D-Bus error name.
305  * @error_message: The D-Bus error message.
306  *
307  * Creates a new #GDBusMessage that is an error reply to @method_call_message.
308  *
309  * Returns: A #GDBusMessage. Free with g_object_unref().
310  *
311  * Since: 2.26
312  */
313 GDBusMessage *
314 g_dbus_message_new_method_error_literal (GDBusMessage  *method_call_message,
315                                          const gchar   *error_name,
316                                          const gchar   *error_message)
317 {
318   GDBusMessage *message;
319   const gchar *sender;
320
321   g_return_val_if_fail (G_IS_DBUS_MESSAGE (method_call_message), NULL);
322   g_return_val_if_fail (g_dbus_message_get_message_type (method_call_message) == G_DBUS_MESSAGE_TYPE_METHOD_CALL, NULL);
323   g_return_val_if_fail (g_dbus_message_get_serial (method_call_message) != 0, NULL);
324   g_return_val_if_fail (g_dbus_is_name (error_name), NULL);
325   g_return_val_if_fail (error_message != NULL, NULL);
326
327   message = g_dbus_message_new ();
328   message->type = G_DBUS_MESSAGE_TYPE_ERROR;
329   message->flags = G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED;
330
331   g_dbus_message_set_reply_serial (message, g_dbus_message_get_serial (method_call_message));
332   g_dbus_message_set_error_name (message, error_name);
333   g_dbus_message_set_body (message, g_variant_new ("(s)", error_message));
334
335   sender = g_dbus_message_get_sender (method_call_message);
336   if (sender != NULL)
337     g_dbus_message_set_destination (message, sender);
338
339   return message;
340 }
341
342 /**
343  * g_dbus_message_new_method_error_valist:
344  * @method_call_message: A message of type %G_DBUS_MESSAGE_TYPE_METHOD_CALL to
345  * create a reply message to.
346  * @error_name: A valid D-Bus error name.
347  * @error_message_format: The D-Bus error message in a printf() format.
348  * @var_args: Arguments for @error_message_format.
349  *
350  * Like g_dbus_message_new_method_error() but intended for language bindings.
351  *
352  * Returns: A #GDBusMessage. Free with g_object_unref().
353  *
354  * Since: 2.26
355  */
356 GDBusMessage *
357 g_dbus_message_new_method_error_valist (GDBusMessage             *method_call_message,
358                                         const gchar              *error_name,
359                                         const gchar              *error_message_format,
360                                         va_list                   var_args)
361 {
362   GDBusMessage *ret;
363   gchar *error_message;
364   error_message = g_strdup_vprintf (error_message_format, var_args);
365   ret = g_dbus_message_new_method_error_literal (method_call_message,
366                                                  error_name,
367                                                  error_message);
368   g_free (error_message);
369   return ret;
370 }
371
372 /* ---------------------------------------------------------------------------------------------------- */
373
374 /* TODO: need GI annotations to specify that any guchar value goes for the type */
375
376 /**
377  * g_dbus_message_get_message_type:
378  * @message: A #GDBusMessage.
379  *
380  * Gets the type of @message.
381  *
382  * Returns: A 8-bit unsigned integer (typically a value from the #GDBusMessageType enumeration).
383  *
384  * Since: 2.26
385  */
386 GDBusMessageType
387 g_dbus_message_get_message_type (GDBusMessage  *message)
388 {
389   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), G_DBUS_MESSAGE_TYPE_INVALID);
390   return message->type;
391 }
392
393 /**
394  * g_dbus_message_set_message_type:
395  * @message: A #GDBusMessage.
396  * @type: A 8-bit unsigned integer (typically a value from the #GDBusMessageType enumeration).
397  *
398  * Sets @message to be of @type.
399  *
400  * Since: 2.26
401  */
402 void
403 g_dbus_message_set_message_type (GDBusMessage      *message,
404                                  GDBusMessageType   type)
405 {
406   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
407   g_return_if_fail (type >=0 && type < 256);
408   message->type = type;
409 }
410
411 /* ---------------------------------------------------------------------------------------------------- */
412
413 /* TODO: need GI annotations to specify that any guchar value goes for flags */
414
415 /**
416  * g_dbus_message_get_flags:
417  * @message: A #GDBusMessage.
418  *
419  * Gets the flags for @message.
420  *
421  * Returns: Flags that are set (typically values from the #GDBusMessageFlags enumeration bitwise ORed together).
422  *
423  * Since: 2.26
424  */
425 GDBusMessageFlags
426 g_dbus_message_get_flags (GDBusMessage  *message)
427 {
428   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), G_DBUS_MESSAGE_FLAGS_NONE);
429   return message->flags;
430 }
431
432 /**
433  * g_dbus_message_set_flags:
434  * @message: A #GDBusMessage.
435  * @flags: Flags for @message that are set (typically values from the #GDBusMessageFlags
436  * enumeration bitwise ORed together).
437  *
438  * Sets the flags to set on @message.
439  *
440  * Since: 2.26
441  */
442 void
443 g_dbus_message_set_flags (GDBusMessage       *message,
444                           GDBusMessageFlags   flags)
445 {
446   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
447   g_return_if_fail (flags >=0 && flags < 256);
448   message->flags = flags;
449 }
450
451 /* ---------------------------------------------------------------------------------------------------- */
452
453 /**
454  * g_dbus_message_get_serial:
455  * @message: A #GDBusMessage.
456  *
457  * Gets the serial for @message.
458  *
459  * Returns: A #guint32.
460  *
461  * Since: 2.26
462  */
463 guint32
464 g_dbus_message_get_serial (GDBusMessage *message)
465 {
466   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), 0);
467   return message->serial;
468 }
469
470 /**
471  * g_dbus_message_set_serial:
472  * @message: A #GDBusMessage.
473  * @serial: A #guint32.
474  *
475  * Sets the serial for @message.
476  *
477  * Since: 2.26
478  */
479 void
480 g_dbus_message_set_serial (GDBusMessage  *message,
481                            guint32        serial)
482 {
483   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
484   message->serial = serial;
485 }
486
487 /* ---------------------------------------------------------------------------------------------------- */
488
489 /* TODO: need GI annotations to specify that any guchar value goes for header_field */
490
491 /**
492  * g_dbus_message_get_header:
493  * @message: A #GDBusMessage.
494  * @header_field: A 8-bit unsigned integer (typically a value from the #GDBusMessageHeaderField enumeration)
495  *
496  * Gets a header field on @message.
497  *
498  * Returns: A #GVariant with the value if the header was found, %NULL
499  * otherwise. Do not free, it is owned by @message.
500  *
501  * Since: 2.26
502  */
503 GVariant *
504 g_dbus_message_get_header (GDBusMessage             *message,
505                            GDBusMessageHeaderField   header_field)
506 {
507   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
508   g_return_val_if_fail (header_field >=0 && header_field < 256, NULL);
509   return g_hash_table_lookup (message->headers, GUINT_TO_POINTER (header_field));
510 }
511
512 /**
513  * g_dbus_message_set_header:
514  * @message: A #GDBusMessage.
515  * @header_field: A 8-bit unsigned integer (typically a value from the #GDBusMessageHeaderField enumeration)
516  * @value: A #GVariant to set the header field or %NULL to clear the header field.
517  *
518  * Sets a header field on @message.
519  *
520  * If @value is floating, @message assumes ownership of @value.
521  *
522  * Since: 2.26
523  */
524 void
525 g_dbus_message_set_header (GDBusMessage             *message,
526                            GDBusMessageHeaderField   header_field,
527                            GVariant                 *value)
528 {
529   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
530   g_return_if_fail (header_field >=0 && header_field < 256);
531   if (value == NULL)
532     {
533       g_hash_table_remove (message->headers, GUINT_TO_POINTER (header_field));
534     }
535   else
536     {
537       g_hash_table_insert (message->headers, GUINT_TO_POINTER (header_field), g_variant_ref_sink (value));
538     }
539 }
540
541 /**
542  * g_dbus_message_get_header_fields:
543  * @message: A #GDBusMessage.
544  *
545  * Gets an array of all header fields on @message that are set.
546  *
547  * Returns: An array of header fields terminated by
548  * %G_DBUS_MESSAGE_HEADER_FIELD_INVALID.  Each element is a
549  * #guchar. Free with g_free().
550  *
551  * Since: 2.26
552  */
553 guchar *
554 g_dbus_message_get_header_fields (GDBusMessage  *message)
555 {
556   GList *keys;
557   guchar *ret;
558   guint num_keys;
559   GList *l;
560   guint n;
561
562   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
563
564   keys = g_hash_table_get_keys (message->headers);
565   num_keys = g_list_length (keys);
566   ret = g_new (guchar, num_keys + 1);
567   for (l = keys, n = 0; l != NULL; l = l->next, n++)
568     ret[n] = GPOINTER_TO_UINT (l->data);
569   g_assert (n == num_keys);
570   ret[n] = G_DBUS_MESSAGE_HEADER_FIELD_INVALID;
571   g_list_free (keys);
572
573   return ret;
574 }
575
576 /* ---------------------------------------------------------------------------------------------------- */
577
578 /**
579  * g_dbus_message_get_body:
580  * @message: A #GDBusMessage.
581  *
582  * Gets the body of a message.
583  *
584  * Returns: A #GVariant or %NULL if the body is empty. Do not free, it is owned by @message.
585  *
586  * Since: 2.26
587  */
588 GVariant *
589 g_dbus_message_get_body (GDBusMessage  *message)
590 {
591   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
592   return message->body;
593 }
594
595 /**
596  * g_dbus_message_set_body:
597  * @message: A #GDBusMessage.
598  * @body: Either %NULL or a #GVariant that is a tuple.
599  *
600  * Sets the body @message. As a side-effect the
601  * %G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE header field is set to the
602  * type string of @body (or cleared if @body is %NULL).
603  *
604  * If @body is floating, @message assumes ownership of @body.
605  *
606  * Since: 2.26
607  */
608 void
609 g_dbus_message_set_body (GDBusMessage  *message,
610                          GVariant      *body)
611 {
612   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
613   g_return_if_fail ((body == NULL) || g_variant_is_of_type (body, G_VARIANT_TYPE_TUPLE));
614
615   if (message->body != NULL)
616     g_variant_unref (message->body);
617   if (body == NULL)
618     {
619       message->body = NULL;
620       g_dbus_message_set_signature (message, NULL);
621     }
622   else
623     {
624       const gchar *type_string;
625       gsize type_string_len;
626       gchar *signature;
627
628       message->body = g_variant_ref_sink (body);
629
630       type_string = g_variant_get_type_string (body);
631       type_string_len = strlen (type_string);
632       g_assert (type_string_len >= 2);
633       signature = g_strndup (type_string + 1, type_string_len - 2);
634       g_dbus_message_set_signature (message, signature);
635       g_free (signature);
636     }
637 }
638
639 /* ---------------------------------------------------------------------------------------------------- */
640
641 #ifdef G_OS_UNIX
642 /**
643  * g_dbus_message_get_unix_fd_list:
644  * @message: A #GDBusMessage.
645  *
646  * Gets the UNIX file descriptors associated with @message, if any.
647  *
648  * This method is only available on UNIX.
649  *
650  * Returns: A #GUnixFDList or %NULL if no file descriptors are
651  * associated. Do not free, this object is owned by @message.
652  *
653  * Since: 2.26
654  */
655 GUnixFDList *
656 g_dbus_message_get_unix_fd_list (GDBusMessage  *message)
657 {
658   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
659   return message->fd_list;
660 }
661
662 /**
663  * g_dbus_message_set_unix_fd_list:
664  * @message: A #GDBusMessage.
665  * @fd_list: A #GUnixFDList or %NULL.
666  *
667  * Sets the UNIX file descriptors associated with @message. As a
668  * side-effect the %G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS header
669  * field is set to the number of fds in @fd_list (or cleared if
670  * @fd_list is %NULL).
671  *
672  * This method is only available on UNIX.
673  *
674  * Since: 2.26
675  */
676 void
677 g_dbus_message_set_unix_fd_list (GDBusMessage  *message,
678                                  GUnixFDList   *fd_list)
679 {
680   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
681   g_return_if_fail (fd_list == NULL || G_IS_UNIX_FD_LIST (fd_list));
682   if (message->fd_list != NULL)
683     g_object_unref (message->fd_list);
684   if (fd_list != NULL)
685     {
686       message->fd_list = g_object_ref (fd_list);
687       g_dbus_message_set_num_unix_fds (message, g_unix_fd_list_get_length (fd_list));
688     }
689   else
690     {
691       message->fd_list = NULL;
692       g_dbus_message_set_num_unix_fds (message, 0);
693     }
694 }
695 #endif
696
697 /* ---------------------------------------------------------------------------------------------------- */
698
699 static gboolean
700 ensure_input_padding (GMemoryInputStream   *mis,
701                       gsize                 padding_size,
702                       GError              **error)
703 {
704   gsize offset;
705   gsize wanted_offset;
706
707   offset = g_seekable_tell (G_SEEKABLE (mis));
708   wanted_offset = ((offset + padding_size - 1) / padding_size) * padding_size;
709
710   if (offset != wanted_offset)
711     {
712       return g_seekable_seek (G_SEEKABLE (mis), wanted_offset, G_SEEK_SET, NULL, error);
713     }
714   else
715     {
716       return TRUE;
717     }
718 }
719
720 static gchar *
721 read_string (GMemoryInputStream    *mis,
722              GDataInputStream      *dis,
723              gsize                  len,
724              GError               **error)
725 {
726   GString *s;
727   gchar buf[256];
728   gsize remaining;
729   guchar nul;
730   GError *local_error;
731   const gchar *end_valid;
732
733   s = g_string_new (NULL);
734
735   remaining = len;
736   while (remaining > 0)
737     {
738       gsize to_read;
739       gssize num_read;
740
741       to_read = MIN (remaining, sizeof (buf));
742       num_read = g_input_stream_read (G_INPUT_STREAM (mis),
743                                       buf,
744                                       to_read,
745                                       NULL,
746                                       error);
747       if (num_read < 0)
748         goto fail;
749       if (num_read == 0)
750         {
751           /* G_GSIZE_FORMAT doesn't work with gettext, so we use %lu */
752           g_set_error (error,
753                        G_IO_ERROR,
754                        G_IO_ERROR_INVALID_ARGUMENT,
755                        _("Wanted to read %lu bytes but got EOF"),
756                        to_read);
757           goto fail;
758         }
759
760       remaining -= num_read;
761       g_string_append_len (s, buf, num_read);
762     }
763
764   local_error = NULL;
765   nul = g_data_input_stream_read_byte (dis, NULL, &local_error);
766   if (local_error != NULL)
767     {
768       g_propagate_error (error, local_error);
769       goto fail;
770     }
771   if (!g_utf8_validate (s->str, -1, &end_valid))
772     {
773       gint offset;
774       gchar *valid_str;
775       offset = (gint) (end_valid - s->str);
776       valid_str = g_strndup (s->str, offset);
777       g_set_error (error,
778                    G_IO_ERROR,
779                    G_IO_ERROR_INVALID_ARGUMENT,
780                    _("Expected valid UTF-8 string but found invalid bytes at byte offset %d (length of string is %d). "
781                      "The valid UTF-8 string up until that that point was `%s'"),
782                    offset,
783                    (gint) s->len,
784                    valid_str);
785       g_free (valid_str);
786       goto fail;
787     }
788   if (nul != '\0')
789     {
790       g_set_error (error,
791                    G_IO_ERROR,
792                    G_IO_ERROR_INVALID_ARGUMENT,
793                    _("Expected NUL byte after the string `%s' but found byte %d"),
794                    s->str, nul);
795       goto fail;
796     }
797
798   return g_string_free (s, FALSE);
799
800  fail:
801   g_string_free (s, TRUE);
802   return NULL;
803 }
804
805 /* if just_align==TRUE, don't read a value, just align the input stream wrt padding */
806
807 /* returns a non-floating GVariant! */
808 static GVariant *
809 parse_value_from_blob (GMemoryInputStream    *mis,
810                        GDataInputStream      *dis,
811                        const GVariantType    *type,
812                        gboolean               just_align,
813                        guint                  indent,
814                        GError               **error)
815 {
816   GVariant *ret;
817   GError *local_error;
818   gboolean is_leaf;
819
820 #ifdef DEBUG_SERIALIZER
821   if (!just_align)
822     {
823       gchar *s;
824       s = g_variant_type_dup_string (type);
825       g_print ("%*sReading type %s from offset 0x%04x",
826                indent, "",
827                s,
828                (gint) g_seekable_tell (G_SEEKABLE (mis)));
829       g_free (s);
830     }
831 #endif /* DEBUG_SERIALIZER */
832
833   ret = NULL;
834
835   is_leaf = TRUE;
836   local_error = NULL;
837   if (g_variant_type_equal (type, G_VARIANT_TYPE_BOOLEAN))
838     {
839       if (!ensure_input_padding (mis, 4, &local_error))
840         goto fail;
841       if (!just_align)
842         {
843           gboolean v;
844           v = g_data_input_stream_read_uint32 (dis, NULL, &local_error);
845           if (local_error != NULL)
846             goto fail;
847           ret = g_variant_new_boolean (v);
848         }
849     }
850   else if (g_variant_type_equal (type, G_VARIANT_TYPE_BYTE))
851     {
852       if (!just_align)
853         {
854           guchar v;
855           v = g_data_input_stream_read_byte (dis, NULL, &local_error);
856           if (local_error != NULL)
857             goto fail;
858           ret = g_variant_new_byte (v);
859         }
860     }
861   else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT16))
862     {
863       if (!ensure_input_padding (mis, 2, &local_error))
864         goto fail;
865       if (!just_align)
866         {
867           gint16 v;
868           v = g_data_input_stream_read_int16 (dis, NULL, &local_error);
869           if (local_error != NULL)
870             goto fail;
871           ret = g_variant_new_int16 (v);
872         }
873     }
874   else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT16))
875     {
876       if (!ensure_input_padding (mis, 2, &local_error))
877         goto fail;
878       if (!just_align)
879         {
880           guint16 v;
881           v = g_data_input_stream_read_uint16 (dis, NULL, &local_error);
882           if (local_error != NULL)
883             goto fail;
884           ret = g_variant_new_uint16 (v);
885         }
886     }
887   else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT32))
888     {
889       if (!ensure_input_padding (mis, 4, &local_error))
890         goto fail;
891       if (!just_align)
892         {
893           gint32 v;
894           v = g_data_input_stream_read_int32 (dis, NULL, &local_error);
895           if (local_error != NULL)
896             goto fail;
897           ret = g_variant_new_int32 (v);
898         }
899     }
900   else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT32))
901     {
902       if (!ensure_input_padding (mis, 4, &local_error))
903         goto fail;
904       if (!just_align)
905         {
906           guint32 v;
907           v = g_data_input_stream_read_uint32 (dis, NULL, &local_error);
908           if (local_error != NULL)
909             goto fail;
910           ret = g_variant_new_uint32 (v);
911         }
912     }
913   else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT64))
914     {
915       if (!ensure_input_padding (mis, 8, &local_error))
916         goto fail;
917       if (!just_align)
918         {
919           gint64 v;
920           v = g_data_input_stream_read_int64 (dis, NULL, &local_error);
921           if (local_error != NULL)
922             goto fail;
923           ret = g_variant_new_int64 (v);
924         }
925     }
926   else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT64))
927     {
928       if (!ensure_input_padding (mis, 8, &local_error))
929         goto fail;
930       if (!just_align)
931         {
932           guint64 v;
933           v = g_data_input_stream_read_uint64 (dis, NULL, &local_error);
934           if (local_error != NULL)
935             goto fail;
936           ret = g_variant_new_uint64 (v);
937         }
938     }
939   else if (g_variant_type_equal (type, G_VARIANT_TYPE_DOUBLE))
940     {
941       if (!ensure_input_padding (mis, 8, &local_error))
942         goto fail;
943       if (!just_align)
944         {
945           guint64 v;
946           gdouble *encoded;
947           v = g_data_input_stream_read_uint64 (dis, NULL, &local_error);
948           if (local_error != NULL)
949             goto fail;
950           /* TODO: hmm */
951           encoded = (gdouble *) &v;
952           ret = g_variant_new_double (*encoded);
953         }
954     }
955   else if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING))
956     {
957       if (!ensure_input_padding (mis, 4, &local_error))
958         goto fail;
959       if (!just_align)
960         {
961           guint32 len;
962           gchar *v;
963           len = g_data_input_stream_read_uint32 (dis, NULL, &local_error);
964           if (local_error != NULL)
965             goto fail;
966           v = read_string (mis, dis, (gsize) len, &local_error);
967           if (v == NULL)
968             goto fail;
969           ret = g_variant_new_string (v);
970           g_free (v);
971         }
972     }
973   else if (g_variant_type_equal (type, G_VARIANT_TYPE_OBJECT_PATH))
974     {
975       if (!ensure_input_padding (mis, 4, &local_error))
976         goto fail;
977       if (!just_align)
978         {
979           guint32 len;
980           gchar *v;
981           len = g_data_input_stream_read_uint32 (dis, NULL, &local_error);
982           if (local_error != NULL)
983             goto fail;
984           v = read_string (mis, dis, (gsize) len, &local_error);
985           if (v == NULL)
986             goto fail;
987           if (!g_variant_is_object_path (v))
988             {
989               g_set_error (&local_error,
990                            G_IO_ERROR,
991                            G_IO_ERROR_INVALID_ARGUMENT,
992                            _("Parsed value `%s' is not a valid D-Bus object path"),
993                            v);
994               g_free (v);
995               goto fail;
996             }
997           ret = g_variant_new_object_path (v);
998           g_free (v);
999         }
1000     }
1001   else if (g_variant_type_equal (type, G_VARIANT_TYPE_SIGNATURE))
1002     {
1003       if (!just_align)
1004         {
1005           guchar len;
1006           gchar *v;
1007           len = g_data_input_stream_read_byte (dis, NULL, &local_error);
1008           if (local_error != NULL)
1009             goto fail;
1010           v = read_string (mis, dis, (gsize) len, &local_error);
1011           if (v == NULL)
1012             goto fail;
1013           if (!g_variant_is_signature (v))
1014             {
1015               g_set_error (&local_error,
1016                            G_IO_ERROR,
1017                            G_IO_ERROR_INVALID_ARGUMENT,
1018                            _("Parsed value `%s' is not a valid D-Bus signature"),
1019                        v);
1020               g_free (v);
1021               goto fail;
1022             }
1023           ret = g_variant_new_signature (v);
1024           g_free (v);
1025         }
1026     }
1027   else if (g_variant_type_equal (type, G_VARIANT_TYPE_HANDLE))
1028     {
1029       if (!ensure_input_padding (mis, 4, &local_error))
1030         goto fail;
1031       if (!just_align)
1032         {
1033           gint32 v;
1034           v = g_data_input_stream_read_int32 (dis, NULL, &local_error);
1035           if (local_error != NULL)
1036             goto fail;
1037           ret = g_variant_new_handle (v);
1038         }
1039     }
1040   else if (g_variant_type_is_array (type))
1041     {
1042       guint32 array_len;
1043       goffset offset;
1044       goffset target;
1045       const GVariantType *element_type;
1046       GVariantBuilder builder;
1047
1048       if (!ensure_input_padding (mis, 4, &local_error))
1049         goto fail;
1050
1051       if (just_align)
1052         {
1053           array_len = 0;
1054         }
1055       else
1056         {
1057           array_len = g_data_input_stream_read_uint32 (dis, NULL, &local_error);
1058           if (local_error != NULL)
1059             goto fail;
1060
1061           is_leaf = FALSE;
1062 #ifdef DEBUG_SERIALIZER
1063           g_print (": array spans 0x%04x bytes\n", array_len);
1064 #endif /* DEBUG_SERIALIZER */
1065
1066           if (array_len > (2<<26))
1067             {
1068               /* G_GUINT32_FORMAT doesn't work with gettext, so use u */
1069               g_set_error (&local_error,
1070                            G_IO_ERROR,
1071                            G_IO_ERROR_INVALID_ARGUMENT,
1072                            _("Encountered array of length %u bytes. Maximum length is 2<<26 bytes (64 MiB)."),
1073                            array_len);
1074               goto fail;
1075             }
1076         }
1077
1078       g_variant_builder_init (&builder, type);
1079       element_type = g_variant_type_element (type);
1080
1081       if (array_len == 0)
1082         {
1083           GVariant *item;
1084           item = parse_value_from_blob (mis,
1085                                         dis,
1086                                         element_type,
1087                                         TRUE,
1088                                         indent + 2,
1089                                         &local_error);
1090           g_assert (item == NULL);
1091         }
1092       else
1093         {
1094           /* TODO: optimize array of primitive types */
1095           offset = g_seekable_tell (G_SEEKABLE (mis));
1096           target = offset + array_len;
1097           while (offset < target)
1098             {
1099               GVariant *item;
1100               item = parse_value_from_blob (mis,
1101                                             dis,
1102                                             element_type,
1103                                             FALSE,
1104                                             indent + 2,
1105                                             &local_error);
1106               if (item == NULL)
1107                 {
1108                   g_variant_builder_clear (&builder);
1109                   goto fail;
1110                 }
1111               g_variant_builder_add_value (&builder, item);
1112               g_variant_unref (item);
1113               offset = g_seekable_tell (G_SEEKABLE (mis));
1114             }
1115         }
1116
1117       if (!just_align)
1118         {
1119           ret = g_variant_builder_end (&builder);
1120         }
1121       else
1122         {
1123           g_variant_builder_clear (&builder);
1124         }
1125     }
1126   else if (g_variant_type_is_dict_entry (type))
1127     {
1128       const GVariantType *key_type;
1129       const GVariantType *value_type;
1130       GVariant *key;
1131       GVariant *value;
1132
1133       if (!ensure_input_padding (mis, 8, &local_error))
1134         goto fail;
1135
1136       is_leaf = FALSE;
1137 #ifdef DEBUG_SERIALIZER
1138       g_print ("\n");
1139 #endif /* DEBUG_SERIALIZER */
1140
1141       if (!just_align)
1142         {
1143           key_type = g_variant_type_key (type);
1144           key = parse_value_from_blob (mis,
1145                                        dis,
1146                                        key_type,
1147                                        FALSE,
1148                                        indent + 2,
1149                                        &local_error);
1150           if (key == NULL)
1151             goto fail;
1152           value_type = g_variant_type_value (type);
1153           value = parse_value_from_blob (mis,
1154                                          dis,
1155                                          value_type,
1156                                          FALSE,
1157                                          indent + 2,
1158                                          &local_error);
1159           if (value == NULL)
1160             {
1161               g_variant_unref (key);
1162               goto fail;
1163             }
1164           ret = g_variant_new_dict_entry (key, value);
1165           g_variant_unref (key);
1166           g_variant_unref (value);
1167         }
1168     }
1169   else if (g_variant_type_is_tuple (type))
1170     {
1171       if (!ensure_input_padding (mis, 8, &local_error))
1172         goto fail;
1173
1174       is_leaf = FALSE;
1175 #ifdef DEBUG_SERIALIZER
1176       g_print ("\n");
1177 #endif /* DEBUG_SERIALIZER */
1178
1179       if (!just_align)
1180         {
1181           const GVariantType *element_type;
1182           GVariantBuilder builder;
1183
1184           g_variant_builder_init (&builder, type);
1185           element_type = g_variant_type_first (type);
1186           while (element_type != NULL)
1187             {
1188               GVariant *item;
1189               item = parse_value_from_blob (mis,
1190                                             dis,
1191                                             element_type,
1192                                             FALSE,
1193                                             indent + 2,
1194                                             &local_error);
1195               if (item == NULL)
1196                 {
1197                   g_variant_builder_clear (&builder);
1198                   goto fail;
1199                 }
1200               g_variant_builder_add_value (&builder, item);
1201               g_variant_unref (item);
1202
1203               element_type = g_variant_type_next (element_type);
1204             }
1205           ret = g_variant_builder_end (&builder);
1206         }
1207     }
1208   else if (g_variant_type_is_variant (type))
1209     {
1210       is_leaf = FALSE;
1211 #ifdef DEBUG_SERIALIZER
1212       g_print ("\n");
1213 #endif /* DEBUG_SERIALIZER */
1214
1215       if (!just_align)
1216         {
1217           guchar siglen;
1218           gchar *sig;
1219           GVariantType *variant_type;
1220           GVariant *value;
1221
1222           siglen = g_data_input_stream_read_byte (dis, NULL, &local_error);
1223           if (local_error != NULL)
1224             goto fail;
1225           sig = read_string (mis, dis, (gsize) siglen, &local_error);
1226           if (sig == NULL)
1227             goto fail;
1228           if (!g_variant_is_signature (sig))
1229             {
1230               g_set_error (&local_error,
1231                            G_IO_ERROR,
1232                            G_IO_ERROR_INVALID_ARGUMENT,
1233                            _("Parsed value `%s' for variant is not a valid D-Bus signature"),
1234                            sig);
1235               g_free (sig);
1236               goto fail;
1237             }
1238           variant_type = g_variant_type_new (sig);
1239           g_free (sig);
1240           value = parse_value_from_blob (mis,
1241                                          dis,
1242                                          variant_type,
1243                                          FALSE,
1244                                          indent + 2,
1245                                          &local_error);
1246           g_variant_type_free (variant_type);
1247           if (value == NULL)
1248             goto fail;
1249           ret = g_variant_new_variant (value);
1250           g_variant_unref (value);
1251         }
1252     }
1253   else
1254     {
1255       gchar *s;
1256       s = g_variant_type_dup_string (type);
1257       g_set_error (&local_error,
1258                    G_IO_ERROR,
1259                    G_IO_ERROR_INVALID_ARGUMENT,
1260                    _("Error deserializing GVariant with type-string `%s' from the D-Bus wire format"),
1261                    s);
1262       g_free (s);
1263       goto fail;
1264     }
1265
1266   g_assert ((just_align && ret == NULL) || (!just_align && ret != NULL));
1267
1268 #ifdef DEBUG_SERIALIZER
1269   if (ret != NULL)
1270     {
1271       if (is_leaf)
1272         {
1273           gchar *s;
1274           if (g_variant_type_equal (type, G_VARIANT_TYPE_BYTE))
1275             {
1276               s = g_strdup_printf ("0x%02x '%c'", g_variant_get_byte (ret), g_variant_get_byte (ret));
1277             }
1278           else
1279             {
1280               s = g_variant_print (ret, FALSE);
1281             }
1282           g_print (": %s\n", s);
1283           g_free (s);
1284         }
1285     }
1286 #endif /* DEBUG_SERIALIZER */
1287
1288   /* sink the reference */
1289   if (ret != NULL)
1290     {
1291       g_assert (g_variant_is_floating (ret));
1292       g_variant_ref_sink (ret);
1293     }
1294   return ret;
1295
1296  fail:
1297 #ifdef DEBUG_SERIALIZER
1298   g_print ("\n"
1299            "%*sFAILURE: %s (%s, %d)\n",
1300            indent, "",
1301            local_error->message,
1302            g_quark_to_string (local_error->domain),
1303            local_error->code);
1304 #endif /* DEBUG_SERIALIZER */
1305   g_propagate_error (error, local_error);
1306   return NULL;
1307 }
1308
1309 /* ---------------------------------------------------------------------------------------------------- */
1310
1311 /* message_header must be at least 16 bytes */
1312
1313 /**
1314  * g_dbus_message_bytes_needed:
1315  * @blob: A blob represent a binary D-Bus message.
1316  * @blob_len: The length of @blob (must be at least 16).
1317  * @error: Return location for error or %NULL.
1318  *
1319  * Utility function to calculate how many bytes are needed to
1320  * completely deserialize the D-Bus message stored at @blob.
1321  *
1322  * Returns: Number of bytes needed or -1 if @error is set (e.g. if
1323  * @blob contains invalid data or not enough data is available to
1324  * determine the size).
1325  *
1326  * Since: 2.26
1327  */
1328 gssize
1329 g_dbus_message_bytes_needed (guchar                *blob,
1330                              gsize                  blob_len,
1331                              GError               **error)
1332 {
1333   gssize ret;
1334
1335   ret = -1;
1336
1337   g_return_val_if_fail (blob != NULL, -1);
1338   g_return_val_if_fail (error == NULL || *error == NULL, -1);
1339   g_return_val_if_fail (blob_len >= 16, -1);
1340
1341   if (blob[0] == 'l')
1342     {
1343       /* core header (12 bytes) + ARRAY of STRUCT of (BYTE,VARIANT) */
1344       ret = 12 + 4 + GUINT32_FROM_LE (((guint32 *) blob)[3]);
1345       /* round up so it's a multiple of 8 */
1346       ret = 8 * ((ret + 7)/8);
1347       /* finally add the body size */
1348       ret += GUINT32_FROM_LE (((guint32 *) blob)[1]);
1349     }
1350   else if (blob[0] == 'B')
1351     {
1352       /* core header (12 bytes) + ARRAY of STRUCT of (BYTE,VARIANT) */
1353       ret = 12 + 4 + GUINT32_FROM_BE (((guint32 *) blob)[3]);
1354       /* round up so it's a multiple of 8 */
1355       ret = 8 * ((ret + 7)/8);
1356       /* finally add the body size */
1357       ret += GUINT32_FROM_BE (((guint32 *) blob)[1]);
1358     }
1359   else
1360     {
1361       g_set_error (error,
1362                    G_IO_ERROR,
1363                    G_IO_ERROR_INVALID_ARGUMENT,
1364                    "Unable to determine message blob length - given blob is malformed");
1365     }
1366
1367   if (ret > (2<<27))
1368     {
1369       g_set_error (error,
1370                    G_IO_ERROR,
1371                    G_IO_ERROR_INVALID_ARGUMENT,
1372                    "Blob indicates that message exceeds maximum message length (128MiB)");
1373       ret = -1;
1374     }
1375
1376   return ret;
1377 }
1378
1379 /* ---------------------------------------------------------------------------------------------------- */
1380
1381 /**
1382  * g_dbus_message_new_from_blob:
1383  * @blob: A blob represent a binary D-Bus message.
1384  * @blob_len: The length of @blob.
1385  * @capabilities: A #GDBusCapabilityFlags describing what protocol features are supported.
1386  * @error: Return location for error or %NULL.
1387  *
1388  * Creates a new #GDBusMessage from the data stored at @blob.
1389  *
1390  * Returns: A new #GDBusMessage or %NULL if @error is set. Free with
1391  * g_object_unref().
1392  *
1393  * Since: 2.26
1394  */
1395 GDBusMessage *
1396 g_dbus_message_new_from_blob (guchar                *blob,
1397                               gsize                  blob_len,
1398                               GDBusCapabilityFlags   capabilities,
1399                               GError               **error)
1400 {
1401   gboolean ret;
1402   GMemoryInputStream *mis;
1403   GDataInputStream *dis;
1404   GDBusMessage *message;
1405   guchar endianness;
1406   guchar major_protocol_version;
1407   GDataStreamByteOrder byte_order;
1408   guint32 message_body_len;
1409   GVariant *headers;
1410   GVariant *item;
1411   GVariantIter iter;
1412   GVariant *signature;
1413
1414   /* TODO: check against @capabilities */
1415
1416   ret = FALSE;
1417
1418   g_return_val_if_fail (blob != NULL, NULL);
1419   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1420   g_return_val_if_fail (blob_len >= 12, NULL);
1421
1422   message = g_dbus_message_new ();
1423
1424   mis = G_MEMORY_INPUT_STREAM (g_memory_input_stream_new_from_data (blob, blob_len, NULL));
1425   dis = g_data_input_stream_new (G_INPUT_STREAM (mis));
1426
1427   endianness = g_data_input_stream_read_byte (dis, NULL, NULL);
1428   switch (endianness)
1429     {
1430     case 'l':
1431       byte_order = G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN;
1432       break;
1433     case 'B':
1434       byte_order = G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN;
1435       break;
1436     default:
1437       g_set_error (error,
1438                    G_IO_ERROR,
1439                    G_IO_ERROR_INVALID_ARGUMENT,
1440                    _("Invalid endianness value. Expected 'l' or 'B' but found '%c' (%d)"),
1441                    endianness, endianness);
1442       goto out;
1443     }
1444   g_data_input_stream_set_byte_order (dis, byte_order);
1445
1446   message->type = g_data_input_stream_read_byte (dis, NULL, NULL);
1447   message->flags = g_data_input_stream_read_byte (dis, NULL, NULL);
1448   major_protocol_version = g_data_input_stream_read_byte (dis, NULL, NULL);
1449   if (major_protocol_version != 1)
1450     {
1451       g_set_error (error,
1452                    G_IO_ERROR,
1453                    G_IO_ERROR_INVALID_ARGUMENT,
1454                    _("Invalid major protocol version. Expected 1 but found %d"),
1455                    major_protocol_version);
1456       goto out;
1457     }
1458   message_body_len = g_data_input_stream_read_uint32 (dis, NULL, NULL);
1459   message->serial = g_data_input_stream_read_uint32 (dis, NULL, NULL);
1460
1461 #ifdef DEBUG_SERIALIZER
1462   g_print ("Parsing blob (blob_len = 0x%04x bytes)\n", (gint) blob_len);
1463   {
1464     gchar *s;
1465     s = _g_dbus_hexdump ((const gchar *) blob, blob_len, 2);
1466     g_print ("%s\n", s);
1467     g_free (s);
1468   }
1469 #endif /* DEBUG_SERIALIZER */
1470
1471 #ifdef DEBUG_SERIALIZER
1472   g_print ("Parsing headers (blob_len = 0x%04x bytes)\n", (gint) blob_len);
1473 #endif /* DEBUG_SERIALIZER */
1474   headers = parse_value_from_blob (mis,
1475                                    dis,
1476                                    G_VARIANT_TYPE ("a{yv}"),
1477                                    FALSE,
1478                                    2,
1479                                    error);
1480   if (headers == NULL)
1481     goto out;
1482   g_variant_iter_init (&iter, headers);
1483   while ((item = g_variant_iter_next_value (&iter)) != NULL)
1484     {
1485       guchar header_field;
1486       GVariant *value;
1487       g_variant_get (item,
1488                      "{yv}",
1489                      &header_field,
1490                      &value);
1491       g_dbus_message_set_header (message, header_field, value);
1492       g_variant_unref (value);
1493       g_variant_unref (item);
1494     }
1495   g_variant_unref (headers);
1496
1497   signature = g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE);
1498   if (signature != NULL)
1499     {
1500       const gchar *signature_str;
1501       gsize signature_str_len;
1502
1503       signature_str = g_variant_get_string (signature, &signature_str_len);
1504
1505       /* signature but no body */
1506       if (message_body_len == 0 && signature_str_len > 0)
1507         {
1508           g_set_error (error,
1509                        G_IO_ERROR,
1510                        G_IO_ERROR_INVALID_ARGUMENT,
1511                        _("Signature header with signature `%s' found but message body is empty"),
1512                        signature_str);
1513           goto out;
1514         }
1515       else if (signature_str_len > 0)
1516         {
1517           GVariantType *variant_type;
1518           gchar *tupled_signature_str;
1519
1520           if (!g_variant_is_signature (signature_str))
1521             {
1522               g_set_error (error,
1523                            G_IO_ERROR,
1524                            G_IO_ERROR_INVALID_ARGUMENT,
1525                            _("Parsed value `%s' is not a valid D-Bus signature (for body)"),
1526                            signature_str);
1527               goto out;
1528             }
1529           tupled_signature_str = g_strdup_printf ("(%s)", signature_str);
1530           variant_type = g_variant_type_new (tupled_signature_str);
1531           g_free (tupled_signature_str);
1532 #ifdef DEBUG_SERIALIZER
1533           g_print ("Parsing body (blob_len = 0x%04x bytes)\n", (gint) blob_len);
1534 #endif /* DEBUG_SERIALIZER */
1535           message->body = parse_value_from_blob (mis,
1536                                                  dis,
1537                                                  variant_type,
1538                                                  FALSE,
1539                                                  2,
1540                                                  error);
1541           g_variant_type_free (variant_type);
1542           if (message->body == NULL)
1543             goto out;
1544         }
1545     }
1546   else
1547     {
1548       /* no signature, this is only OK if the body is empty */
1549       if (message_body_len != 0)
1550         {
1551           /* G_GUINT32_FORMAT doesn't work with gettext, just use %u */
1552           g_set_error (error,
1553                        G_IO_ERROR,
1554                        G_IO_ERROR_INVALID_ARGUMENT,
1555                        _("No signature header in message but the message body is %u bytes"),
1556                        message_body_len);
1557           goto out;
1558         }
1559     }
1560
1561
1562   ret = TRUE;
1563
1564  out:
1565   g_object_unref (dis);
1566   g_object_unref (mis);
1567
1568   if (ret)
1569     {
1570       return message;
1571     }
1572   else
1573     {
1574       if (message != NULL)
1575         g_object_unref (message);
1576       return NULL;
1577     }
1578 }
1579
1580 /* ---------------------------------------------------------------------------------------------------- */
1581
1582 static gsize
1583 ensure_output_padding (GMemoryOutputStream  *mos,
1584                        GDataOutputStream    *dos,
1585                        gsize                 padding_size)
1586 {
1587   gsize offset;
1588   gsize wanted_offset;
1589   gsize padding_needed;
1590   guint n;
1591
1592   offset = g_memory_output_stream_get_data_size (mos);
1593   wanted_offset = ((offset + padding_size - 1) / padding_size) * padding_size;
1594   padding_needed = wanted_offset - offset;
1595
1596   for (n = 0; n < padding_needed; n++)
1597     g_data_output_stream_put_byte (dos, '\0', NULL, NULL);
1598
1599   return padding_needed;
1600 }
1601
1602 /* note that value can be NULL for e.g. empty arrays - type is never NULL */
1603 static gboolean
1604 append_value_to_blob (GVariant             *value,
1605                       const GVariantType   *type,
1606                       GMemoryOutputStream  *mos,
1607                       GDataOutputStream    *dos,
1608                       gsize                *out_padding_added,
1609                       GError              **error)
1610 {
1611   gsize padding_added;
1612
1613   padding_added = 0;
1614
1615   if (g_variant_type_equal (type, G_VARIANT_TYPE_BOOLEAN))
1616     {
1617       padding_added = ensure_output_padding (mos, dos, 4);
1618       if (value != NULL)
1619         {
1620           gboolean v = g_variant_get_boolean (value);
1621           g_data_output_stream_put_uint32 (dos, v, NULL, NULL);
1622         }
1623     }
1624   else if (g_variant_type_equal (type, G_VARIANT_TYPE_BYTE))
1625     {
1626       if (value != NULL)
1627         {
1628           guint8 v = g_variant_get_byte (value);
1629           g_data_output_stream_put_byte (dos, v, NULL, NULL);
1630         }
1631     }
1632   else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT16))
1633     {
1634       padding_added = ensure_output_padding (mos, dos, 2);
1635       if (value != NULL)
1636         {
1637           gint16 v = g_variant_get_int16 (value);
1638           g_data_output_stream_put_int16 (dos, v, NULL, NULL);
1639         }
1640     }
1641   else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT16))
1642     {
1643       padding_added = ensure_output_padding (mos, dos, 2);
1644       if (value != NULL)
1645         {
1646           guint16 v = g_variant_get_uint16 (value);
1647           g_data_output_stream_put_uint16 (dos, v, NULL, NULL);
1648         }
1649     }
1650   else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT32))
1651     {
1652       padding_added = ensure_output_padding (mos, dos, 4);
1653       if (value != NULL)
1654         {
1655           gint32 v = g_variant_get_int32 (value);
1656           g_data_output_stream_put_int32 (dos, v, NULL, NULL);
1657         }
1658     }
1659   else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT32))
1660     {
1661       padding_added = ensure_output_padding (mos, dos, 4);
1662       if (value != NULL)
1663         {
1664           guint32 v = g_variant_get_uint32 (value);
1665           g_data_output_stream_put_uint32 (dos, v, NULL, NULL);
1666         }
1667     }
1668   else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT64))
1669     {
1670       padding_added = ensure_output_padding (mos, dos, 8);
1671       if (value != NULL)
1672         {
1673           gint64 v = g_variant_get_int64 (value);
1674           g_data_output_stream_put_int64 (dos, v, NULL, NULL);
1675         }
1676     }
1677   else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT64))
1678     {
1679       padding_added = ensure_output_padding (mos, dos, 8);
1680       if (value != NULL)
1681         {
1682           guint64 v = g_variant_get_uint64 (value);
1683           g_data_output_stream_put_uint64 (dos, v, NULL, NULL);
1684         }
1685     }
1686   else if (g_variant_type_equal (type, G_VARIANT_TYPE_DOUBLE))
1687     {
1688       padding_added = ensure_output_padding (mos, dos, 8);
1689       if (value != NULL)
1690         {
1691           guint64 *encoded;
1692           gdouble v = g_variant_get_double (value);
1693           /* TODO: hmm */
1694           encoded = (guint64 *) &v;
1695           g_data_output_stream_put_uint64 (dos, *encoded, NULL, NULL);
1696         }
1697     }
1698   else if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING))
1699     {
1700       padding_added = ensure_output_padding (mos, dos, 4);
1701       if (value != NULL)
1702         {
1703           gsize len;
1704           const gchar *v = g_variant_get_string (value, &len);
1705           g_data_output_stream_put_uint32 (dos, len, NULL, NULL);
1706           g_data_output_stream_put_string (dos, v, NULL, NULL);
1707           g_data_output_stream_put_byte (dos, '\0', NULL, NULL);
1708         }
1709     }
1710   else if (g_variant_type_equal (type, G_VARIANT_TYPE_OBJECT_PATH))
1711     {
1712       padding_added = ensure_output_padding (mos, dos, 4);
1713       if (value != NULL)
1714         {
1715           /* TODO: validate object path */
1716           gsize len;
1717           const gchar *v = g_variant_get_string (value, &len);
1718           g_data_output_stream_put_uint32 (dos, len, NULL, NULL);
1719           g_data_output_stream_put_string (dos, v, NULL, NULL);
1720           g_data_output_stream_put_byte (dos, '\0', NULL, NULL);
1721         }
1722     }
1723   else if (g_variant_type_equal (type, G_VARIANT_TYPE_SIGNATURE))
1724     {
1725       if (value != NULL)
1726         {
1727           /* TODO: validate signature (including max len being 255) */
1728           gsize len;
1729           const gchar *v = g_variant_get_string (value, &len);
1730           g_data_output_stream_put_byte (dos, len, NULL, NULL);
1731           g_data_output_stream_put_string (dos, v, NULL, NULL);
1732           g_data_output_stream_put_byte (dos, '\0', NULL, NULL);
1733         }
1734     }
1735   else if (g_variant_type_equal (type, G_VARIANT_TYPE_HANDLE))
1736     {
1737       padding_added = ensure_output_padding (mos, dos, 4);
1738       if (value != NULL)
1739         {
1740           gint32 v = g_variant_get_handle (value);
1741           g_data_output_stream_put_int32 (dos, v, NULL, NULL);
1742         }
1743     }
1744   else if (g_variant_type_is_array (type))
1745     {
1746       GVariant *item;
1747       GVariantIter iter;
1748       goffset array_len_offset;
1749       goffset array_payload_begin_offset;
1750       goffset cur_offset;
1751       gsize array_len;
1752
1753       padding_added = ensure_output_padding (mos, dos, 4);
1754       if (value != NULL)
1755         {
1756           /* array length - will be filled in later */
1757           array_len_offset = g_memory_output_stream_get_data_size (mos);
1758           g_data_output_stream_put_uint32 (dos, 0xF00DFACE, NULL, NULL);
1759
1760           /* From the D-Bus spec:
1761            *
1762            *   "A UINT32 giving the length of the array data in bytes,
1763            *    followed by alignment padding to the alignment boundary of
1764            *    the array element type, followed by each array element. The
1765            *    array length is from the end of the alignment padding to
1766            *    the end of the last element, i.e. it does not include the
1767            *    padding after the length, or any padding after the last
1768            *    element."
1769            *
1770            * Thus, we need to count how much padding the first element
1771            * contributes and subtract that from the array length.
1772            */
1773           array_payload_begin_offset = g_memory_output_stream_get_data_size (mos);
1774
1775           if (g_variant_n_children (value) == 0)
1776             {
1777               gsize padding_added_for_item;
1778               if (!append_value_to_blob (NULL,
1779                                          g_variant_type_element (type),
1780                                          mos,
1781                                          dos,
1782                                          &padding_added_for_item,
1783                                          error))
1784                 goto fail;
1785               array_payload_begin_offset += padding_added_for_item;
1786             }
1787           else
1788             {
1789               guint n;
1790               n = 0;
1791               g_variant_iter_init (&iter, value);
1792               while ((item = g_variant_iter_next_value (&iter)) != NULL)
1793                 {
1794                   gsize padding_added_for_item;
1795                   if (!append_value_to_blob (item,
1796                                              g_variant_get_type (item),
1797                                              mos,
1798                                              dos,
1799                                              &padding_added_for_item,
1800                                              error))
1801                     {
1802                       g_variant_unref (item);
1803                       goto fail;
1804                     }
1805                   g_variant_unref (item);
1806                   if (n == 0)
1807                     {
1808                       array_payload_begin_offset += padding_added_for_item;
1809                     }
1810                   n++;
1811                 }
1812             }
1813
1814           cur_offset = g_memory_output_stream_get_data_size (mos);
1815
1816           array_len = cur_offset - array_payload_begin_offset;
1817
1818           if (!g_seekable_seek (G_SEEKABLE (mos), array_len_offset, G_SEEK_SET, NULL, error))
1819             goto fail;
1820
1821           g_data_output_stream_put_uint32 (dos, array_len, NULL, NULL);
1822
1823           if (!g_seekable_seek (G_SEEKABLE (mos), cur_offset, G_SEEK_SET, NULL, error))
1824             goto fail;
1825         }
1826     }
1827   else if (g_variant_type_is_dict_entry (type) || g_variant_type_is_tuple (type))
1828     {
1829       padding_added = ensure_output_padding (mos, dos, 8);
1830       if (value != NULL)
1831         {
1832           GVariant *item;
1833           GVariantIter iter;
1834           g_variant_iter_init (&iter, value);
1835           while ((item = g_variant_iter_next_value (&iter)) != NULL)
1836             {
1837               if (!append_value_to_blob (item,
1838                                          g_variant_get_type (item),
1839                                          mos,
1840                                          dos,
1841                                          NULL,
1842                                          error))
1843                 {
1844                   g_variant_unref (item);
1845                   goto fail;
1846                 }
1847               g_variant_unref (item);
1848             }
1849         }
1850     }
1851   else if (g_variant_type_is_variant (type))
1852     {
1853       if (value != NULL)
1854         {
1855           GVariant *child;
1856           const gchar *signature;
1857           child = g_variant_get_child_value (value, 0);
1858           signature = g_variant_get_type_string (child);
1859           /* TODO: validate signature (including max len being 255) */
1860           g_data_output_stream_put_byte (dos, strlen (signature), NULL, NULL);
1861           g_data_output_stream_put_string (dos, signature, NULL, NULL);
1862           g_data_output_stream_put_byte (dos, '\0', NULL, NULL);
1863           if (!append_value_to_blob (child,
1864                                      g_variant_get_type (child),
1865                                      mos,
1866                                      dos,
1867                                      NULL,
1868                                      error))
1869             {
1870               g_variant_unref (child);
1871               goto fail;
1872             }
1873           g_variant_unref (child);
1874         }
1875     }
1876   else
1877     {
1878       g_set_error (error,
1879                    G_IO_ERROR,
1880                    G_IO_ERROR_INVALID_ARGUMENT,
1881                    _("Error serializing GVariant with type-string `%s' to the D-Bus wire format"),
1882                    g_variant_get_type_string (value));
1883       goto fail;
1884     }
1885
1886   if (out_padding_added != NULL)
1887     *out_padding_added = padding_added;
1888
1889   return TRUE;
1890
1891  fail:
1892   return FALSE;
1893 }
1894
1895 static gboolean
1896 append_body_to_blob (GVariant             *value,
1897                      GMemoryOutputStream  *mos,
1898                      GDataOutputStream    *dos,
1899                      GError              **error)
1900 {
1901   gboolean ret;
1902   GVariant *item;
1903   GVariantIter iter;
1904
1905   ret = FALSE;
1906
1907   if (!g_variant_is_of_type (value, G_VARIANT_TYPE_TUPLE))
1908     {
1909       g_set_error (error,
1910                    G_IO_ERROR,
1911                    G_IO_ERROR_INVALID_ARGUMENT,
1912                    "Expected a tuple for the body of the GDBusMessage.");
1913       goto fail;
1914     }
1915
1916   g_variant_iter_init (&iter, value);
1917   while ((item = g_variant_iter_next_value (&iter)) != NULL)
1918     {
1919       if (!append_value_to_blob (item,
1920                                  g_variant_get_type (item),
1921                                  mos,
1922                                  dos,
1923                                  NULL,
1924                                  error))
1925         {
1926           g_variant_unref (item);
1927           goto fail;
1928         }
1929       g_variant_unref (item);
1930     }
1931   return TRUE;
1932
1933  fail:
1934   return FALSE;
1935 }
1936
1937 /* ---------------------------------------------------------------------------------------------------- */
1938
1939 /**
1940  * g_dbus_message_to_blob:
1941  * @message: A #GDBusMessage.
1942  * @out_size: Return location for size of generated blob.
1943  * @capabilities: A #GDBusCapabilityFlags describing what protocol features are supported.
1944  * @error: Return location for error.
1945  *
1946  * Serializes @message to a blob.
1947  *
1948  * Returns: A pointer to a valid binary D-Bus message of @out_size bytes
1949  * generated by @message or %NULL if @error is set. Free with g_free().
1950  *
1951  * Since: 2.26
1952  */
1953 guchar *
1954 g_dbus_message_to_blob (GDBusMessage          *message,
1955                         gsize                 *out_size,
1956                         GDBusCapabilityFlags   capabilities,
1957                         GError               **error)
1958 {
1959   GMemoryOutputStream *mos;
1960   GDataOutputStream *dos;
1961   guchar *ret;
1962   gsize size;
1963   GDataStreamByteOrder byte_order;
1964   goffset body_len_offset;
1965   goffset body_start_offset;
1966   gsize body_size;
1967   GVariant *header_fields;
1968   GVariantBuilder builder;
1969   GHashTableIter hash_iter;
1970   gpointer key;
1971   GVariant *header_value;
1972   GVariant *signature;
1973   const gchar *signature_str;
1974   gint num_fds_in_message;
1975   gint num_fds_according_to_header;
1976
1977   /* TODO: check against @capabilities */
1978
1979   ret = NULL;
1980
1981   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
1982   g_return_val_if_fail (out_size != NULL, NULL);
1983   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1984
1985   mos = G_MEMORY_OUTPUT_STREAM (g_memory_output_stream_new (NULL, 0, g_realloc, g_free));
1986   dos = g_data_output_stream_new (G_OUTPUT_STREAM (mos));
1987
1988   /* Any D-Bus implementation is supposed to handle both Big and
1989    * Little Endian encodings and the Endianness is part of the D-Bus
1990    * message - we prefer to use Big Endian (since it's Network Byte
1991    * Order and just easier to read for humans) but if the machine is
1992    * Little Endian we use that for performance reasons.
1993    */
1994 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1995   byte_order = G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN;
1996 #else
1997   /* this could also be G_PDP_ENDIAN */
1998   byte_order = G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN;
1999 #endif
2000   g_data_output_stream_set_byte_order (dos, byte_order);
2001
2002   /* Core header */
2003   g_data_output_stream_put_byte (dos, byte_order == G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN ? 'l' : 'B', NULL, NULL);
2004   g_data_output_stream_put_byte (dos, message->type, NULL, NULL);
2005   g_data_output_stream_put_byte (dos, message->flags, NULL, NULL);
2006   g_data_output_stream_put_byte (dos, 1, NULL, NULL); /* major protocol version */
2007   body_len_offset = g_memory_output_stream_get_data_size (mos);
2008   /* body length - will be filled in later */
2009   g_data_output_stream_put_uint32 (dos, 0xF00DFACE, NULL, NULL);
2010   g_data_output_stream_put_uint32 (dos, message->serial, NULL, NULL);
2011
2012   num_fds_in_message = 0;
2013 #ifdef G_OS_UNIX
2014   if (message->fd_list != NULL)
2015     num_fds_in_message = g_unix_fd_list_get_length (message->fd_list);
2016 #endif
2017   num_fds_according_to_header = g_dbus_message_get_num_unix_fds (message);
2018   /* TODO: check we have all the right header fields and that they are the correct value etc etc */
2019   if (num_fds_in_message != num_fds_according_to_header)
2020     {
2021       g_set_error (error,
2022                    G_IO_ERROR,
2023                    G_IO_ERROR_INVALID_ARGUMENT,
2024                    _("Message has %d fds but the header field indicates %d fds"),
2025                    num_fds_in_message,
2026                    num_fds_according_to_header);
2027       goto out;
2028     }
2029
2030   g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{yv}"));
2031   g_hash_table_iter_init (&hash_iter, message->headers);
2032   while (g_hash_table_iter_next (&hash_iter, &key, (gpointer) &header_value))
2033     {
2034       g_variant_builder_add (&builder,
2035                              "{yv}",
2036                              (guchar) GPOINTER_TO_UINT (key),
2037                              header_value);
2038     }
2039   header_fields = g_variant_builder_end (&builder);
2040
2041   if (!append_value_to_blob (header_fields,
2042                              g_variant_get_type (header_fields),
2043                              mos, dos,
2044                              NULL,
2045                              error))
2046     {
2047       g_variant_unref (header_fields);
2048       goto out;
2049     }
2050   g_variant_unref (header_fields);
2051
2052   /* header size must be a multiple of 8 */
2053   ensure_output_padding (mos, dos, 8);
2054
2055   body_start_offset = g_memory_output_stream_get_data_size (mos);
2056
2057   signature = g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE);
2058   signature_str = NULL;
2059   if (signature != NULL)
2060       signature_str = g_variant_get_string (signature, NULL);
2061   if (message->body != NULL)
2062     {
2063       gchar *tupled_signature_str;
2064       tupled_signature_str = g_strdup_printf ("(%s)", signature_str);
2065       if (signature == NULL)
2066         {
2067           g_set_error (error,
2068                        G_IO_ERROR,
2069                        G_IO_ERROR_INVALID_ARGUMENT,
2070                        _("Message body has signature `%s' but there is no signature header"),
2071                        signature_str);
2072           g_free (tupled_signature_str);
2073           goto out;
2074         }
2075       else if (g_strcmp0 (tupled_signature_str, g_variant_get_type_string (message->body)) != 0)
2076         {
2077           g_set_error (error,
2078                        G_IO_ERROR,
2079                        G_IO_ERROR_INVALID_ARGUMENT,
2080                        _("Message body has type signature `%s' but signature in the header field is `%s'"),
2081                        tupled_signature_str, g_variant_get_type_string (message->body));
2082           g_free (tupled_signature_str);
2083           goto out;
2084         }
2085       g_free (tupled_signature_str);
2086       if (!append_body_to_blob (message->body, mos, dos, error))
2087         goto out;
2088     }
2089   else
2090     {
2091       if (signature != NULL && strlen (signature_str) > 0)
2092         {
2093           g_set_error (error,
2094                        G_IO_ERROR,
2095                        G_IO_ERROR_INVALID_ARGUMENT,
2096                        _("Message body is empty but signature in the header field is `(%s)'"),
2097                        signature_str);
2098           goto out;
2099         }
2100     }
2101
2102   /* OK, we're done writing the message - set the body length */
2103   size = g_memory_output_stream_get_data_size (mos);
2104   body_size = size - body_start_offset;
2105
2106   if (!g_seekable_seek (G_SEEKABLE (mos), body_len_offset, G_SEEK_SET, NULL, error))
2107     goto out;
2108
2109   g_data_output_stream_put_uint32 (dos, body_size, NULL, NULL);
2110
2111   *out_size = size;
2112   ret = g_memdup (g_memory_output_stream_get_data (mos), size);
2113
2114  out:
2115   g_object_unref (dos);
2116   g_object_unref (mos);
2117
2118   return ret;
2119 }
2120
2121 /* ---------------------------------------------------------------------------------------------------- */
2122
2123 static guint32
2124 get_uint32_header (GDBusMessage            *message,
2125                    GDBusMessageHeaderField  header_field)
2126 {
2127   GVariant *value;
2128   guint32 ret;
2129
2130   ret = 0;
2131   value = g_hash_table_lookup (message->headers, GUINT_TO_POINTER (header_field));
2132   if (value != NULL && g_variant_is_of_type (value, G_VARIANT_TYPE_UINT32))
2133     ret = g_variant_get_uint32 (value);
2134
2135   return ret;
2136 }
2137
2138 static const gchar *
2139 get_string_header (GDBusMessage            *message,
2140                    GDBusMessageHeaderField  header_field)
2141 {
2142   GVariant *value;
2143   const gchar *ret;
2144
2145   ret = NULL;
2146   value = g_hash_table_lookup (message->headers, GUINT_TO_POINTER (header_field));
2147   if (value != NULL && g_variant_is_of_type (value, G_VARIANT_TYPE_STRING))
2148     ret = g_variant_get_string (value, NULL);
2149
2150   return ret;
2151 }
2152
2153 static const gchar *
2154 get_object_path_header (GDBusMessage            *message,
2155                         GDBusMessageHeaderField  header_field)
2156 {
2157   GVariant *value;
2158   const gchar *ret;
2159
2160   ret = NULL;
2161   value = g_hash_table_lookup (message->headers, GUINT_TO_POINTER (header_field));
2162   if (value != NULL && g_variant_is_of_type (value, G_VARIANT_TYPE_OBJECT_PATH))
2163     ret = g_variant_get_string (value, NULL);
2164
2165   return ret;
2166 }
2167
2168 static const gchar *
2169 get_signature_header (GDBusMessage            *message,
2170                       GDBusMessageHeaderField  header_field)
2171 {
2172   GVariant *value;
2173   const gchar *ret;
2174
2175   ret = NULL;
2176   value = g_hash_table_lookup (message->headers, GUINT_TO_POINTER (header_field));
2177   if (value != NULL && g_variant_is_of_type (value, G_VARIANT_TYPE_SIGNATURE))
2178     ret = g_variant_get_string (value, NULL);
2179
2180   return ret;
2181 }
2182
2183 /* ---------------------------------------------------------------------------------------------------- */
2184
2185 static void
2186 set_uint32_header (GDBusMessage             *message,
2187                    GDBusMessageHeaderField   header_field,
2188                    guint32                   value)
2189 {
2190   g_dbus_message_set_header (message,
2191                              header_field,
2192                              g_variant_new_uint32 (value));
2193 }
2194
2195 static void
2196 set_string_header (GDBusMessage             *message,
2197                    GDBusMessageHeaderField   header_field,
2198                    const gchar              *value)
2199 {
2200   g_dbus_message_set_header (message,
2201                              header_field,
2202                              value == NULL ? NULL : g_variant_new_string (value));
2203 }
2204
2205 static void
2206 set_object_path_header (GDBusMessage             *message,
2207                         GDBusMessageHeaderField   header_field,
2208                         const gchar              *value)
2209 {
2210   g_dbus_message_set_header (message,
2211                              header_field,
2212                              value == NULL ? NULL : g_variant_new_object_path (value));
2213 }
2214
2215 static void
2216 set_signature_header (GDBusMessage             *message,
2217                       GDBusMessageHeaderField   header_field,
2218                       const gchar              *value)
2219 {
2220   g_dbus_message_set_header (message,
2221                              header_field,
2222                              value == NULL ? NULL : g_variant_new_signature (value));
2223 }
2224
2225 /* ---------------------------------------------------------------------------------------------------- */
2226
2227 /**
2228  * g_dbus_message_get_reply_serial:
2229  * @message: A #GDBusMessage.
2230  *
2231  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL header field.
2232  *
2233  * Returns: The value.
2234  *
2235  * Since: 2.26
2236  */
2237 guint32
2238 g_dbus_message_get_reply_serial (GDBusMessage  *message)
2239 {
2240   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), 0);
2241   return get_uint32_header (message, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL);
2242 }
2243
2244 /**
2245  * g_dbus_message_set_reply_serial:
2246  * @message: A #GDBusMessage.
2247  * @value: The value to set.
2248  *
2249  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL header field.
2250  *
2251  * Since: 2.26
2252  */
2253 void
2254 g_dbus_message_set_reply_serial (GDBusMessage  *message,
2255                                  guint32        value)
2256 {
2257   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2258   set_uint32_header (message, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL, value);
2259 }
2260
2261 /* ---------------------------------------------------------------------------------------------------- */
2262
2263 /**
2264  * g_dbus_message_get_interface:
2265  * @message: A #GDBusMessage.
2266  *
2267  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE header field.
2268  *
2269  * Returns: The value.
2270  *
2271  * Since: 2.26
2272  */
2273 const gchar *
2274 g_dbus_message_get_interface (GDBusMessage  *message)
2275 {
2276   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2277   return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE);
2278 }
2279
2280 /**
2281  * g_dbus_message_set_interface:
2282  * @message: A #GDBusMessage.
2283  * @value: The value to set.
2284  *
2285  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE header field.
2286  *
2287  * Since: 2.26
2288  */
2289 void
2290 g_dbus_message_set_interface (GDBusMessage  *message,
2291                               const gchar   *value)
2292 {
2293   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2294   g_return_if_fail (value == NULL || g_dbus_is_interface_name (value));
2295   set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE, value);
2296 }
2297
2298 /* ---------------------------------------------------------------------------------------------------- */
2299
2300 /**
2301  * g_dbus_message_get_member:
2302  * @message: A #GDBusMessage.
2303  *
2304  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_MEMBER header field.
2305  *
2306  * Returns: The value.
2307  *
2308  * Since: 2.26
2309  */
2310 const gchar *
2311 g_dbus_message_get_member (GDBusMessage  *message)
2312 {
2313   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2314   return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER);
2315 }
2316
2317 /**
2318  * g_dbus_message_set_member:
2319  * @message: A #GDBusMessage.
2320  * @value: The value to set.
2321  *
2322  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_MEMBER header field.
2323  *
2324  * Since: 2.26
2325  */
2326 void
2327 g_dbus_message_set_member (GDBusMessage  *message,
2328                            const gchar   *value)
2329 {
2330   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2331   g_return_if_fail (value == NULL || g_dbus_is_member_name (value));
2332   set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER, value);
2333 }
2334
2335 /* ---------------------------------------------------------------------------------------------------- */
2336
2337 /**
2338  * g_dbus_message_get_path:
2339  * @message: A #GDBusMessage.
2340  *
2341  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_PATH header field.
2342  *
2343  * Returns: The value.
2344  *
2345  * Since: 2.26
2346  */
2347 const gchar *
2348 g_dbus_message_get_path (GDBusMessage  *message)
2349 {
2350   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2351   return get_object_path_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH);
2352 }
2353
2354 /**
2355  * g_dbus_message_set_path:
2356  * @message: A #GDBusMessage.
2357  * @value: The value to set.
2358  *
2359  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_PATH header field.
2360  *
2361  * Since: 2.26
2362  */
2363 void
2364 g_dbus_message_set_path (GDBusMessage  *message,
2365                          const gchar   *value)
2366 {
2367   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2368   g_return_if_fail (value == NULL || g_variant_is_object_path (value));
2369   set_object_path_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH, value);
2370 }
2371
2372 /* ---------------------------------------------------------------------------------------------------- */
2373
2374 /**
2375  * g_dbus_message_get_sender:
2376  * @message: A #GDBusMessage.
2377  *
2378  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_SENDER header field.
2379  *
2380  * Returns: The value.
2381  *
2382  * Since: 2.26
2383  */
2384 const gchar *
2385 g_dbus_message_get_sender (GDBusMessage *message)
2386 {
2387   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2388   return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SENDER);
2389 }
2390
2391 /**
2392  * g_dbus_message_set_sender:
2393  * @message: A #GDBusMessage.
2394  * @value: The value to set.
2395  *
2396  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_SENDER header field.
2397  *
2398  * Since: 2.26
2399  */
2400 void
2401 g_dbus_message_set_sender (GDBusMessage  *message,
2402                            const gchar   *value)
2403 {
2404   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2405   g_return_if_fail (value == NULL || g_dbus_is_name (value));
2406   set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SENDER, value);
2407 }
2408
2409 /* ---------------------------------------------------------------------------------------------------- */
2410
2411 /**
2412  * g_dbus_message_get_destination:
2413  * @message: A #GDBusMessage.
2414  *
2415  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION header field.
2416  *
2417  * Returns: The value.
2418  *
2419  * Since: 2.26
2420  */
2421 const gchar *
2422 g_dbus_message_get_destination (GDBusMessage  *message)
2423 {
2424   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2425   return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION);
2426 }
2427
2428 /**
2429  * g_dbus_message_set_destination:
2430  * @message: A #GDBusMessage.
2431  * @value: The value to set.
2432  *
2433  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION header field.
2434  *
2435  * Since: 2.26
2436  */
2437 void
2438 g_dbus_message_set_destination (GDBusMessage  *message,
2439                                 const gchar   *value)
2440 {
2441   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2442   g_return_if_fail (value == NULL || g_dbus_is_name (value));
2443   set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION, value);
2444 }
2445
2446 /* ---------------------------------------------------------------------------------------------------- */
2447
2448 /**
2449  * g_dbus_message_get_error_name:
2450  * @message: A #GDBusMessage.
2451  *
2452  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME header field.
2453  *
2454  * Returns: The value.
2455  *
2456  * Since: 2.26
2457  */
2458 const gchar *
2459 g_dbus_message_get_error_name (GDBusMessage  *message)
2460 {
2461   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2462   return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME);
2463 }
2464
2465 /**
2466  * g_dbus_message_set_error_name:
2467  * @message: A #GDBusMessage.
2468  * @value: The value to set.
2469  *
2470  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME header field.
2471  *
2472  * Since: 2.26
2473  */
2474 void
2475 g_dbus_message_set_error_name (GDBusMessage  *message,
2476                                const gchar   *value)
2477 {
2478   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2479   g_return_if_fail (value == NULL || g_dbus_is_interface_name (value));
2480   set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME, value);
2481 }
2482
2483 /* ---------------------------------------------------------------------------------------------------- */
2484
2485 /**
2486  * g_dbus_message_get_signature:
2487  * @message: A #GDBusMessage.
2488  *
2489  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE header field.
2490  *
2491  * Returns: The value.
2492  *
2493  * Since: 2.26
2494  */
2495 const gchar *
2496 g_dbus_message_get_signature (GDBusMessage  *message)
2497 {
2498   const gchar *ret;
2499   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2500   ret = get_signature_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE);
2501   if (ret == NULL)
2502     ret = "";
2503   return ret;
2504 }
2505
2506 /**
2507  * g_dbus_message_set_signature:
2508  * @message: A #GDBusMessage.
2509  * @value: The value to set.
2510  *
2511  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE header field.
2512  *
2513  * Since: 2.26
2514  */
2515 void
2516 g_dbus_message_set_signature (GDBusMessage  *message,
2517                               const gchar   *value)
2518 {
2519   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2520   g_return_if_fail (value == NULL || g_variant_is_signature (value));
2521   set_signature_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE, value);
2522 }
2523
2524 /* ---------------------------------------------------------------------------------------------------- */
2525
2526 /**
2527  * g_dbus_message_get_arg0:
2528  * @message: A #GDBusMessage.
2529  *
2530  * Convenience to get the first item in the body of @message.
2531  *
2532  * Returns: The string item or %NULL if the first item in the body of
2533  * @message is not a string.
2534  *
2535  * Since: 2.26
2536  */
2537 const gchar *
2538 g_dbus_message_get_arg0 (GDBusMessage  *message)
2539 {
2540   const gchar *ret;
2541
2542   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2543
2544   ret = NULL;
2545
2546   if (message->body != NULL && g_variant_is_of_type (message->body, G_VARIANT_TYPE_TUPLE))
2547     {
2548       GVariant *item;
2549       item = g_variant_get_child_value (message->body, 0);
2550       if (g_variant_is_of_type (item, G_VARIANT_TYPE_STRING))
2551         ret = g_variant_get_string (item, NULL);
2552       g_variant_unref (item);
2553     }
2554
2555   return ret;
2556 }
2557
2558 /* ---------------------------------------------------------------------------------------------------- */
2559
2560 /**
2561  * g_dbus_message_get_num_unix_fds:
2562  * @message: A #GDBusMessage.
2563  *
2564  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS header field.
2565  *
2566  * Returns: The value.
2567  *
2568  * Since: 2.26
2569  */
2570 guint32
2571 g_dbus_message_get_num_unix_fds (GDBusMessage *message)
2572 {
2573   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), 0);
2574   return get_uint32_header (message, G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS);
2575 }
2576
2577 /**
2578  * g_dbus_message_set_num_unix_fds:
2579  * @message: A #GDBusMessage.
2580  * @value: The value to set.
2581  *
2582  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS header field.
2583  *
2584  * Since: 2.26
2585  */
2586 void
2587 g_dbus_message_set_num_unix_fds (GDBusMessage  *message,
2588                                  guint32        value)
2589 {
2590   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2591   set_uint32_header (message, G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS, value);
2592 }
2593
2594 /* ---------------------------------------------------------------------------------------------------- */
2595
2596 /**
2597  * g_dbus_message_to_gerror:
2598  * @message: A #GDBusMessage.
2599  * @error: The #GError to set.
2600  *
2601  * If @message is not of type %G_DBUS_MESSAGE_TYPE_ERROR does
2602  * nothing and returns %FALSE.
2603  *
2604  * Otherwise this method encodes the error in @message as a #GError
2605  * using g_dbus_error_set_dbus_error() using the information in the
2606  * %G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME header field of @message as
2607  * well as the first string item in @message's body.
2608  *
2609  * Returns: %TRUE if @error was set, %FALSE otherwise.
2610  *
2611  * Since: 2.26
2612  */
2613 gboolean
2614 g_dbus_message_to_gerror (GDBusMessage   *message,
2615                           GError        **error)
2616 {
2617   gboolean ret;
2618   const gchar *error_name;
2619
2620   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), FALSE);
2621
2622   ret = FALSE;
2623   if (message->type != G_DBUS_MESSAGE_TYPE_ERROR)
2624     goto out;
2625
2626   error_name = g_dbus_message_get_error_name (message);
2627   if (error_name != NULL)
2628     {
2629       GVariant *body;
2630
2631       body = g_dbus_message_get_body (message);
2632
2633       if (body != NULL && g_variant_is_of_type (body, G_VARIANT_TYPE ("(s)")))
2634         {
2635           const gchar *error_message;
2636           g_variant_get (body, "(&s)", &error_message);
2637           g_dbus_error_set_dbus_error (error,
2638                                        error_name,
2639                                        error_message,
2640                                        NULL);
2641         }
2642       else
2643         {
2644           /* these two situations are valid, yet pretty rare */
2645           if (body != NULL)
2646             {
2647               g_dbus_error_set_dbus_error (error,
2648                                            error_name,
2649                                            "",
2650                                            _("Error return with body of type `%s'"),
2651                                            g_variant_get_type_string (body));
2652             }
2653           else
2654             {
2655               g_dbus_error_set_dbus_error (error,
2656                                            error_name,
2657                                            "",
2658                                            _("Error return with empty body"));
2659             }
2660         }
2661     }
2662   else
2663     {
2664       /* TOOD: this shouldn't happen - should check this at message serialization
2665        * time and disconnect the peer.
2666        */
2667       g_set_error (error,
2668                    G_IO_ERROR,
2669                    G_IO_ERROR_FAILED,
2670                    "Error return without error-name header!");
2671     }
2672
2673   ret = TRUE;
2674
2675  out:
2676   return ret;
2677 }
2678
2679 /* ---------------------------------------------------------------------------------------------------- */
2680
2681 static gchar *
2682 flags_to_string (GType flags_type, guint value)
2683 {
2684   GString *s;
2685   GFlagsClass *klass;
2686   guint n;
2687
2688   klass = g_type_class_ref (flags_type);
2689   s = g_string_new (NULL);
2690   for (n = 0; n < 32; n++)
2691     {
2692       if ((value & (1<<n)) != 0)
2693         {
2694           GFlagsValue *flags_value;
2695           flags_value = g_flags_get_first_value (klass, (1<<n));
2696           if (s->len > 0)
2697             g_string_append_c (s, ',');
2698           if (flags_value != NULL)
2699             g_string_append (s, flags_value->value_nick);
2700           else
2701             g_string_append_printf (s, "unknown (bit %d)", n);
2702         }
2703     }
2704   if (s->len == 0)
2705     g_string_append (s, "none");
2706   g_type_class_unref (klass);
2707   return g_string_free (s, FALSE);
2708 }
2709
2710 static gint
2711 _sort_keys_func (gconstpointer a,
2712                  gconstpointer b)
2713 {
2714   gint ia;
2715   gint ib;
2716
2717   ia = GPOINTER_TO_INT (a);
2718   ib = GPOINTER_TO_INT (b);
2719
2720   return ia - ib;
2721 }
2722
2723 /**
2724  * g_dbus_message_print:
2725  * @message: A #GDBusMessage.
2726  * @indent: Indentation level.
2727  *
2728  * Produces a human-readable multi-line description of @message.
2729  *
2730  * The contents of the description has no ABI guarantees, the contents
2731  * and formatting is subject to change at any time. Typical output
2732  * looks something like this:
2733  * <programlisting>
2734  * Type:    method-call
2735  * Flags:   none
2736  * Version: 0
2737  * Serial:  4
2738  * Headers:
2739  *   path -> objectpath '/org/gtk/GDBus/TestObject'
2740  *   interface -> 'org.gtk.GDBus.TestInterface'
2741  *   member -> 'GimmeStdout'
2742  *   destination -> ':1.146'
2743  * Body: ()
2744  * UNIX File Descriptors:
2745  *   (none)
2746  * </programlisting>
2747  * or
2748  * <programlisting>
2749  * Type:    method-return
2750  * Flags:   no-reply-expected
2751  * Version: 0
2752  * Serial:  477
2753  * Headers:
2754  *   reply-serial -> uint32 4
2755  *   destination -> ':1.159'
2756  *   sender -> ':1.146'
2757  *   num-unix-fds -> uint32 1
2758  * Body: ()
2759  * UNIX File Descriptors:
2760  *   fd 12: dev=0:10,mode=020620,ino=5,uid=500,gid=5,rdev=136:2,size=0,atime=1273085037,mtime=1273085851,ctime=1272982635
2761  * </programlisting>
2762  *
2763  * Returns: A string that should be freed with g_free().
2764  *
2765  * Since: 2.26
2766  */
2767 gchar *
2768 g_dbus_message_print (GDBusMessage *message,
2769                       guint         indent)
2770 {
2771   GString *str;
2772   gchar *s;
2773   GList *keys;
2774   GList *l;
2775
2776   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2777
2778   str = g_string_new (NULL);
2779
2780   s = _g_dbus_enum_to_string (G_TYPE_DBUS_MESSAGE_TYPE, message->type);
2781   g_string_append_printf (str, "%*sType:    %s\n", indent, "", s);
2782   g_free (s);
2783   s = flags_to_string (G_TYPE_DBUS_MESSAGE_FLAGS, message->flags);
2784   g_string_append_printf (str, "%*sFlags:   %s\n", indent, "", s);
2785   g_free (s);
2786   g_string_append_printf (str, "%*sVersion: %d\n", indent, "", message->major_protocol_version);
2787   g_string_append_printf (str, "%*sSerial:  %d\n", indent, "", message->serial);
2788
2789   g_string_append_printf (str, "%*sHeaders:\n", indent, "");
2790   keys = g_hash_table_get_keys (message->headers);
2791   keys = g_list_sort (keys, _sort_keys_func);
2792   if (keys != NULL)
2793     {
2794       for (l = keys; l != NULL; l = l->next)
2795         {
2796           gint key = GPOINTER_TO_INT (l->data);
2797           GVariant *value;
2798           gchar *value_str;
2799
2800           value = g_hash_table_lookup (message->headers, l->data);
2801           g_assert (value != NULL);
2802
2803           s = _g_dbus_enum_to_string (G_TYPE_DBUS_MESSAGE_HEADER_FIELD, key);
2804           value_str = g_variant_print (value, TRUE);
2805           g_string_append_printf (str, "%*s  %s -> %s\n", indent, "", s, value_str);
2806           g_free (s);
2807           g_free (value_str);
2808         }
2809     }
2810   else
2811     {
2812       g_string_append_printf (str, "%*s  (none)\n", indent, "");
2813     }
2814   g_string_append_printf (str, "%*sBody: ", indent, "");
2815   if (message->body != NULL)
2816     {
2817       g_variant_print_string (message->body,
2818                               str,
2819                               TRUE);
2820     }
2821   else
2822     {
2823       g_string_append (str, "()");
2824     }
2825   g_string_append (str, "\n");
2826 #ifdef G_OS_UNIX
2827   g_string_append_printf (str, "%*sUNIX File Descriptors:\n", indent, "");
2828   if (message->fd_list != NULL)
2829     {
2830       gint num_fds;
2831       const gint *fds;
2832       gint n;
2833
2834       fds = g_unix_fd_list_peek_fds (message->fd_list, &num_fds);
2835       if (num_fds > 0)
2836         {
2837           for (n = 0; n < num_fds; n++)
2838             {
2839               GString *fs;
2840               struct stat statbuf;
2841               fs = g_string_new (NULL);
2842               if (fstat (fds[n], &statbuf) == 0)
2843                 {
2844                   g_string_append_printf (fs, "%s" "dev=%d:%d", fs->len > 0 ? "," : "",
2845                                           major (statbuf.st_dev), minor (statbuf.st_dev));
2846                   g_string_append_printf (fs, "%s" "mode=0%o", fs->len > 0 ? "," : "",
2847                                           statbuf.st_mode);
2848                   g_string_append_printf (fs, "%s" "ino=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
2849                                           (guint64) statbuf.st_ino);
2850                   g_string_append_printf (fs, "%s" "uid=%d", fs->len > 0 ? "," : "",
2851                                           statbuf.st_uid);
2852                   g_string_append_printf (fs, "%s" "gid=%d", fs->len > 0 ? "," : "",
2853                                           statbuf.st_gid);
2854                   g_string_append_printf (fs, "%s" "rdev=%d:%d", fs->len > 0 ? "," : "",
2855                                           major (statbuf.st_rdev), minor (statbuf.st_rdev));
2856                   g_string_append_printf (fs, "%s" "size=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
2857                                           (guint64) statbuf.st_size);
2858                   g_string_append_printf (fs, "%s" "atime=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
2859                                           (guint64) statbuf.st_atime);
2860                   g_string_append_printf (fs, "%s" "mtime=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
2861                                           (guint64) statbuf.st_mtime);
2862                   g_string_append_printf (fs, "%s" "ctime=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
2863                                           (guint64) statbuf.st_ctime);
2864                 }
2865               else
2866                 {
2867                   g_string_append_printf (fs, "(fstat failed: %s)", strerror (errno));
2868                 }
2869               g_string_append_printf (str, "%*s  fd %d: %s\n", indent, "", fds[n], fs->str);
2870               g_string_free (fs, TRUE);
2871             }
2872         }
2873       else
2874         {
2875           g_string_append_printf (str, "%*s  (empty)\n", indent, "");
2876         }
2877     }
2878   else
2879     {
2880       g_string_append_printf (str, "%*s  (none)\n", indent, "");
2881     }
2882 #endif
2883
2884   return g_string_free (str, FALSE);
2885 }