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