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