1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-gvalue.c GValue to-from DBusMessageIter
3  *
4  * Copyright (C) 2004 Ximian, Inc.
5  * Copyright (C) 2005 Red Hat, Inc.
6  *
7  * SPDX-License-Identifier: AFL-2.1 OR GPL-2.0-or-later
8  *
9  * Licensed under the Academic Free License version 2.1
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
24  *
25  */
26 
27 #include "config.h"
28 #include "dbus-gtest.h"
29 #include "dbus-gvalue.h"
30 #include "dbus-gsignature.h"
31 #include "dbus-gobject.h"
32 #include "dbus-gvalue-utils.h"
33 #include "dbus/dbus-glib.h"
34 #include <string.h>
35 #include <glib.h>
36 #include "dbus/dbus-signature.h"
37 
38 /* Seems reasonable, but this should probably be part of the standard protocol */
39 #define DBUS_GLIB_MAX_VARIANT_RECURSION 32
40 
41 static gboolean demarshal_static_variant (DBusGValueMarshalCtx    *context,
42 					  DBusMessageIter         *iter,
43 					  GValue                  *value,
44 					  GError                 **error);
45 
46 
47 static gboolean marshal_basic                   (DBusMessageIter           *iter,
48 						 const GValue              *value);
49 static gboolean demarshal_basic                 (DBusGValueMarshalCtx      *context,
50 						 DBusMessageIter           *iter,
51 						 GValue                    *value,
52 						 GError                   **error);
53 static gboolean marshal_strv                    (DBusMessageIter           *iter,
54 						 const GValue              *value);
55 static gboolean demarshal_strv                  (DBusGValueMarshalCtx      *context,
56 						 DBusMessageIter           *iter,
57 						 GValue                    *value,
58 						 GError                   **error);
59 static gboolean marshal_valuearray              (DBusMessageIter           *iter,
60 						 const GValue              *value);
61 static gboolean demarshal_valuearray            (DBusGValueMarshalCtx      *context,
62 						 DBusMessageIter           *iter,
63 						 GValue                    *value,
64 						 GError                   **error);
65 static gboolean marshal_variant                 (DBusMessageIter           *iter,
66 						 const GValue              *value);
67 static gboolean demarshal_variant               (DBusGValueMarshalCtx      *context,
68 						 DBusMessageIter           *iter,
69 						 GValue                    *value,
70 						 GError                   **error);
71 static gboolean marshal_proxy                   (DBusMessageIter           *iter,
72 						 const GValue             *value);
73 static gboolean demarshal_proxy                 (DBusGValueMarshalCtx      *context,
74 						 DBusMessageIter           *iter,
75 						 GValue                    *value,
76 						 GError                   **error);
77 static gboolean marshal_object_path             (DBusMessageIter           *iter,
78 						 const GValue             *value);
79 static gboolean demarshal_object_path           (DBusGValueMarshalCtx      *context,
80 						 DBusMessageIter           *iter,
81 						 GValue                    *value,
82 						 GError                   **error);
83 static gboolean marshal_object                  (DBusMessageIter           *iter,
84 						 const GValue              *value);
85 static gboolean demarshal_object                (DBusGValueMarshalCtx      *context,
86 						 DBusMessageIter           *iter,
87 						 GValue                    *value,
88 						 GError                   **error);
89 static gboolean marshal_signature		(DBusMessageIter           *iter,
90 						 const GValue             *value);
91 static gboolean demarshal_signature		(DBusGValueMarshalCtx      *context,
92 						 DBusMessageIter           *iter,
93 						 GValue                    *value,
94 						 GError                   **error);
95 static gboolean marshal_map                     (DBusMessageIter           *iter,
96 						 const GValue              *value);
97 static gboolean demarshal_map                   (DBusGValueMarshalCtx      *context,
98 						 DBusMessageIter           *iter,
99 						 GValue                    *value,
100 						 GError                   **error);
101 
102 static gboolean marshal_collection              (DBusMessageIter           *iter,
103 						 const GValue              *value);
104 static gboolean marshal_collection_ptrarray     (DBusMessageIter           *iter,
105 						 const GValue              *value);
106 static gboolean marshal_collection_array        (DBusMessageIter           *iter,
107 						 const GValue              *value);
108 static gboolean demarshal_collection            (DBusGValueMarshalCtx      *context,
109 						 DBusMessageIter           *iter,
110 						 GValue                    *value,
111 						 GError                   **error);
112 static gboolean demarshal_collection_ptrarray   (DBusGValueMarshalCtx      *context,
113 						 DBusMessageIter           *iter,
114 						 GValue                    *value,
115 						 GError                   **error);
116 static gboolean demarshal_collection_array      (DBusGValueMarshalCtx      *context,
117 						 DBusMessageIter           *iter,
118 						 GValue                    *value,
119 						 GError                   **error);
120 static gboolean marshal_struct                  (DBusMessageIter           *iter,
121 						 const GValue              *value);
122 static gboolean demarshal_struct                (DBusGValueMarshalCtx      *context,
123 						 DBusMessageIter           *iter,
124 						 GValue                    *value,
125 						 GError                   **error);
126 
127 
128 typedef gboolean (*DBusGValueMarshalFunc)       (DBusMessageIter           *iter,
129 						 const GValue              *value);
130 typedef gboolean (*DBusGValueDemarshalFunc)     (DBusGValueMarshalCtx      *context,
131 						 DBusMessageIter           *iter,
132 						 GValue                    *value,
133 						 GError                   **error);
134 
135 typedef struct {
136   DBusGValueMarshalFunc       marshaller;
137   DBusGValueDemarshalFunc     demarshaller;
138 } DBusGTypeMarshalVtable;
139 
140 typedef struct {
141   const char                       *sig;
142   const DBusGTypeMarshalVtable     *vtable;
143 } DBusGTypeMarshalData;
144 
145 static GQuark
dbus_g_type_metadata_data_quark()146 dbus_g_type_metadata_data_quark ()
147 {
148   static GQuark quark;
149   if (!quark)
150     quark = g_quark_from_static_string ("DBusGTypeMetaData");
151 
152   return quark;
153 }
154 
155 static void
set_type_metadata(GType type,const DBusGTypeMarshalData * data)156 set_type_metadata (GType type, const DBusGTypeMarshalData *data)
157 {
158   g_type_set_qdata (type, dbus_g_type_metadata_data_quark (), (gpointer) data);
159 }
160 
161 static void
register_basic(int typecode,const DBusGTypeMarshalData * typedata)162 register_basic (int typecode, const DBusGTypeMarshalData *typedata)
163 {
164   set_type_metadata (_dbus_gtype_from_basic_typecode (typecode), typedata);
165 }
166 
167 void
_dbus_g_value_types_init(void)168 _dbus_g_value_types_init (void)
169 {
170   static gboolean types_initialized;
171 
172   static const DBusGTypeMarshalVtable basic_vtable = {
173     marshal_basic,
174     demarshal_basic
175   };
176 
177   if (types_initialized)
178     return;
179 
180   dbus_g_type_specialized_init ();
181 
182   /* Register basic types */
183   {
184     static const DBusGTypeMarshalData typedata = {
185       DBUS_TYPE_BOOLEAN_AS_STRING,
186       &basic_vtable,
187     };
188     register_basic (DBUS_TYPE_BOOLEAN, &typedata);
189   }
190   {
191     static const DBusGTypeMarshalData typedata = {
192       DBUS_TYPE_BYTE_AS_STRING,
193       &basic_vtable,
194     };
195     register_basic (DBUS_TYPE_BYTE, &typedata);
196   }
197   {
198     static const DBusGTypeMarshalData typedata = {
199       DBUS_TYPE_INT16_AS_STRING,
200       &basic_vtable,
201     };
202     register_basic (DBUS_TYPE_INT16, &typedata);
203   }
204   {
205     static const DBusGTypeMarshalData typedata = {
206       DBUS_TYPE_UINT16_AS_STRING,
207       &basic_vtable,
208     };
209     register_basic (DBUS_TYPE_UINT16, &typedata);
210   }
211   {
212     static const DBusGTypeMarshalData typedata = {
213       DBUS_TYPE_UINT32_AS_STRING,
214       &basic_vtable,
215     };
216     register_basic (DBUS_TYPE_UINT32, &typedata);
217   }
218   {
219     static const DBusGTypeMarshalData typedata = {
220       DBUS_TYPE_INT32_AS_STRING,
221       &basic_vtable,
222     };
223     register_basic (DBUS_TYPE_INT32, &typedata);
224   }
225   {
226     static const DBusGTypeMarshalData typedata = {
227       DBUS_TYPE_UINT64_AS_STRING,
228       &basic_vtable,
229     };
230     register_basic (DBUS_TYPE_UINT64, &typedata);
231   }
232   {
233     static const DBusGTypeMarshalData typedata = {
234       DBUS_TYPE_INT64_AS_STRING,
235       &basic_vtable,
236     };
237     register_basic (DBUS_TYPE_INT64, &typedata);
238   }
239   {
240     static const DBusGTypeMarshalData typedata = {
241       DBUS_TYPE_DOUBLE_AS_STRING,
242       &basic_vtable,
243     };
244     register_basic (DBUS_TYPE_DOUBLE, &typedata);
245   }
246   {
247     static const DBusGTypeMarshalData typedata = {
248       DBUS_TYPE_STRING_AS_STRING,
249       &basic_vtable,
250     };
251     register_basic (DBUS_TYPE_STRING, &typedata);
252   }
253   /* fundamental GTypes that don't map 1:1 with D-BUS types */
254   {
255     static const DBusGTypeMarshalData typedata = {
256       DBUS_TYPE_BYTE_AS_STRING,
257       &basic_vtable,
258     };
259     set_type_metadata (G_TYPE_CHAR, &typedata);
260   }
261   {
262     static const DBusGTypeMarshalData typedata = {
263       DBUS_TYPE_INT32_AS_STRING,
264       &basic_vtable,
265     };
266     set_type_metadata (G_TYPE_LONG, &typedata);
267   }
268   {
269     static const DBusGTypeMarshalData typedata = {
270       DBUS_TYPE_UINT32_AS_STRING,
271       &basic_vtable,
272     };
273     set_type_metadata (G_TYPE_ULONG, &typedata);
274   }
275   {
276     static const DBusGTypeMarshalData typedata = {
277       DBUS_TYPE_DOUBLE_AS_STRING,
278       &basic_vtable,
279     };
280     set_type_metadata (G_TYPE_FLOAT, &typedata);
281   }
282 
283   /* Register complex types with builtin GType mappings */
284   {
285     static const DBusGTypeMarshalVtable vtable = {
286       marshal_variant,
287       demarshal_variant
288     };
289     static const DBusGTypeMarshalData typedata = {
290       DBUS_TYPE_VARIANT_AS_STRING,
291       &vtable
292     };
293     set_type_metadata (G_TYPE_VALUE, &typedata);
294   };
295   {
296     static const DBusGTypeMarshalVtable vtable = {
297       marshal_strv,
298       demarshal_strv
299     };
300     static const DBusGTypeMarshalData typedata = {
301       DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,
302       &vtable
303     };
304     set_type_metadata (G_TYPE_STRV, &typedata);
305   };
306 
307 
308   /* Register some types specific to the D-BUS GLib bindings */
309   {
310     static const DBusGTypeMarshalVtable vtable = {
311       marshal_proxy,
312       demarshal_proxy
313     };
314     static const DBusGTypeMarshalData typedata = {
315       DBUS_TYPE_OBJECT_PATH_AS_STRING,
316       &vtable
317     };
318     set_type_metadata (DBUS_TYPE_G_PROXY, &typedata);
319   }
320 
321   {
322     static const DBusGTypeMarshalVtable vtable = {
323       marshal_object_path,
324       demarshal_object_path
325     };
326     static const DBusGTypeMarshalData typedata = {
327       DBUS_TYPE_OBJECT_PATH_AS_STRING,
328       &vtable
329     };
330     set_type_metadata (DBUS_TYPE_G_OBJECT_PATH, &typedata);
331   }
332 
333   {
334     static const DBusGTypeMarshalVtable vtable = {
335       marshal_object,
336       demarshal_object
337     };
338     static const DBusGTypeMarshalData typedata = {
339       DBUS_TYPE_OBJECT_PATH_AS_STRING,
340       &vtable
341     };
342     set_type_metadata (G_TYPE_OBJECT, &typedata);
343   }
344 
345   {
346     static const DBusGTypeMarshalVtable vtable = {
347       marshal_signature,
348       demarshal_signature
349     };
350     static const DBusGTypeMarshalData typedata = {
351       DBUS_TYPE_SIGNATURE_AS_STRING,
352       &vtable
353     };
354     set_type_metadata (DBUS_TYPE_G_SIGNATURE, &typedata);
355   }
356 
357   types_initialized = TRUE;
358 }
359 
360 /**
361  * DBusGObjectPath:
362  *
363  * A typedef for a string used to represent D-Bus object paths.
364  * Its GType is %DBUS_TYPE_G_OBJECT_PATH, derived from %G_TYPE_BOXED.
365  *
366  * Prior to version 0.FIXME this was used as the type name of
367  * %DBUS_TYPE_G_OBJECT_PATH, but did not actually exist as a typedef.
368  *
369  * Since: 0.FIXME
370  *
371  * Deprecated: New code should use GDBus instead. The closest equivalent
372  *  is a #GVariant (%G_TYPE_VARIANT) of type %G_VARIANT_TYPE_OBJECT_PATH.
373  */
374 
375 /**
376  * DBUS_TYPE_G_OBJECT_PATH:
377  *
378  * The #GType of a #DBusGObjectPath, which is a boxed type containing a
379  * D-Bus object path as a zero-terminated string. Object paths can be
380  * copied with g_strdup() and freed with g_free(), just like %G_TYPE_STRING,
381  * but have a distinct boxed type to allow them to be distinguished when
382  * stored in a #GValue.
383  *
384  * Returns: a type derived from %G_TYPE_BOXED
385  *
386  * Deprecated: New code should use GDBus instead. The closest equivalent
387  *  is a #GVariant (%G_TYPE_VARIANT) of type %G_VARIANT_TYPE_OBJECT_PATH.
388  */
389 GType
dbus_g_object_path_get_g_type(void)390 dbus_g_object_path_get_g_type (void)
391 {
392   static GType type_id = 0;
393 
394   if (!type_id)
395     type_id = g_boxed_type_register_static ("DBusGObjectPath",
396 					    (GBoxedCopyFunc) g_strdup,
397 					    (GBoxedFreeFunc) g_free);
398   return type_id;
399 }
400 
401 /**
402  * DBusGSignature:
403  *
404  * A typedef for a string used to represent D-Bus signatures.
405  * Its GType is %DBUS_TYPE_G_SIGNATURE, derived from %G_TYPE_BOXED.
406  *
407  * Prior to version 0.FIXME this was used as the type name of
408  * %DBUS_TYPE_G_SIGNATURE, but did not actually exist as a typedef.
409  *
410  * Since: 0.FIXME
411  *
412  * Deprecated: New code should use GDBus instead. The closest equivalent
413  *  is a #GVariant (%G_TYPE_VARIANT) of type %G_VARIANT_TYPE_SIGNATURE.
414  */
415 
416 /**
417  * DBUS_TYPE_G_SIGNATURE:
418  *
419  * The #GType of a #DBusGSignature, which is a boxed type containing a
420  * D-Bus signature as a zero-terminated string. Signatures can be
421  * copied with g_strdup() and freed with g_free(), just like %G_TYPE_STRING,
422  * but have a distinct boxed type to allow them to be distinguished when
423  * stored in a #GValue.
424  *
425  * Returns: a type derived from %G_TYPE_BOXED
426  *
427  * Deprecated: New code should use GDBus instead. The closest equivalent
428  *  is a #GVariant (%G_TYPE_VARIANT) of type %G_VARIANT_TYPE_SIGNATURE.
429  */
430 GType
dbus_g_signature_get_g_type(void)431 dbus_g_signature_get_g_type (void)
432 {
433   static GType type_id = 0;
434 
435   if (G_UNLIKELY (type_id == 0))
436     type_id = g_boxed_type_register_static ("DBusGSignature",
437 					    (GBoxedCopyFunc) g_strdup,
438 					    (GBoxedFreeFunc) g_free);
439 
440   return type_id;
441 }
442 
443 
444 char *
_dbus_gtype_to_signature(GType gtype)445 _dbus_gtype_to_signature (GType gtype)
446 {
447   char *ret;
448   DBusGTypeMarshalData *typedata;
449 
450   if (dbus_g_type_is_collection (gtype))
451     {
452       GType elt_gtype;
453       char *subsig;
454 
455       elt_gtype = dbus_g_type_get_collection_specialization (gtype);
456       subsig = _dbus_gtype_to_signature (elt_gtype);
457       ret = g_strconcat (DBUS_TYPE_ARRAY_AS_STRING, subsig, NULL);
458       g_free (subsig);
459     }
460   else if (dbus_g_type_is_map (gtype))
461     {
462       GType key_gtype;
463       GType val_gtype;
464       char *key_subsig;
465       char *val_subsig;
466 
467       key_gtype = dbus_g_type_get_map_key_specialization (gtype);
468       val_gtype = dbus_g_type_get_map_value_specialization (gtype);
469       key_subsig = _dbus_gtype_to_signature (key_gtype);
470       val_subsig = _dbus_gtype_to_signature (val_gtype);
471       ret = g_strconcat (DBUS_TYPE_ARRAY_AS_STRING DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING, key_subsig, val_subsig, DBUS_DICT_ENTRY_END_CHAR_AS_STRING, NULL);
472       g_free (key_subsig);
473       g_free (val_subsig);
474     }
475   else if (dbus_g_type_is_struct (gtype))
476     {
477       guint i, size;
478       GString *sig;
479       size = dbus_g_type_get_struct_size (gtype);
480       sig = g_string_sized_new (size+2); /*some sensible starting size*/
481       g_string_assign (sig, DBUS_STRUCT_BEGIN_CHAR_AS_STRING);
482       for (i = 0; i < size; i++)
483         {
484           gchar *subsig;
485           subsig = _dbus_gtype_to_signature (
486               dbus_g_type_get_struct_member_type (gtype, i));
487           g_string_append (sig, subsig);
488           g_free (subsig);
489         }
490       g_string_append (sig, DBUS_STRUCT_END_CHAR_AS_STRING);
491       ret = g_string_free (sig, FALSE);
492     }
493   else
494     {
495       typedata = g_type_get_qdata (gtype, dbus_g_type_metadata_data_quark ());
496       if (typedata == NULL)
497 	return NULL;
498       ret = g_strdup (typedata->sig);
499     }
500   return ret;
501 }
502 
503 char *
_dbus_gvalue_to_signature(const GValue * val)504 _dbus_gvalue_to_signature (const GValue *val)
505 {
506   GType gtype;
507 
508   gtype = G_VALUE_TYPE (val);
509   if (g_type_is_a (gtype, G_TYPE_VALUE_ARRAY))
510     {
511       GString *str;
512       guint i;
513       GValueArray *array;
514 
515       array = g_value_get_boxed (val);
516 
517       str = g_string_new (DBUS_STRUCT_BEGIN_CHAR_AS_STRING);
518       for (i = 0; i < array->n_values; i++)
519 	{
520 	  char *sig;
521 	  sig = _dbus_gvalue_to_signature (g_value_array_get_nth (array, i));
522 	  g_string_append (str, sig);
523 	  g_free (sig);
524 	}
525       g_string_append (str, DBUS_STRUCT_END_CHAR_AS_STRING);
526 
527       return g_string_free (str, FALSE);
528     }
529   else
530     return _dbus_gtype_to_signature (gtype);
531 }
532 
533 static gboolean
demarshal_basic(DBusGValueMarshalCtx * context,DBusMessageIter * iter,GValue * value,GError ** error)534 demarshal_basic (DBusGValueMarshalCtx      *context,
535 		 DBusMessageIter           *iter,
536 		 GValue                    *value,
537 		 GError                   **error)
538 {
539   int current_type;
540 
541   current_type = dbus_message_iter_get_arg_type (iter);
542   g_assert (dbus_type_is_basic (current_type));
543 
544   switch (current_type)
545     {
546     case DBUS_TYPE_BOOLEAN:
547       {
548 	dbus_bool_t bool;
549         if (!G_VALUE_HOLDS (value, G_TYPE_BOOLEAN))
550           goto invalid_type;
551 	dbus_message_iter_get_basic (iter, &bool);
552 	g_value_set_boolean (value, bool);
553 	return TRUE;
554       }
555     case DBUS_TYPE_BYTE:
556       {
557 	unsigned char byte;
558         if (!G_VALUE_HOLDS (value, G_TYPE_UCHAR))
559           goto invalid_type;
560 	dbus_message_iter_get_basic (iter, &byte);
561 	g_value_set_uchar (value, byte);
562 	return TRUE;
563       }
564     case DBUS_TYPE_INT32:
565       {
566 	dbus_int32_t intval;
567         if (!G_VALUE_HOLDS (value, G_TYPE_INT))
568           goto invalid_type;
569 	dbus_message_iter_get_basic (iter, &intval);
570 	g_value_set_int (value, intval);
571 	return TRUE;
572       }
573     case DBUS_TYPE_UINT32:
574       {
575 	dbus_uint32_t intval;
576         if (!G_VALUE_HOLDS (value, G_TYPE_UINT))
577           goto invalid_type;
578 	dbus_message_iter_get_basic (iter, &intval);
579 	g_value_set_uint (value, intval);
580 	return TRUE;
581       }
582     case DBUS_TYPE_INT64:
583       {
584 	dbus_int64_t intval;
585         if (!G_VALUE_HOLDS (value, G_TYPE_INT64))
586           goto invalid_type;
587 	dbus_message_iter_get_basic (iter, &intval);
588 	g_value_set_int64 (value, intval);
589 	return TRUE;
590       }
591     case DBUS_TYPE_UINT64:
592       {
593 	dbus_uint64_t intval;
594         if (!G_VALUE_HOLDS (value, G_TYPE_UINT64))
595           goto invalid_type;
596 	dbus_message_iter_get_basic (iter, &intval);
597 	g_value_set_uint64 (value, intval);
598 	return TRUE;
599       }
600     case DBUS_TYPE_DOUBLE:
601       {
602 	double dval;
603         if (!G_VALUE_HOLDS (value, G_TYPE_DOUBLE))
604           goto invalid_type;
605 	dbus_message_iter_get_basic (iter, &dval);
606 	g_value_set_double (value, dval);
607 	return TRUE;
608       }
609     case DBUS_TYPE_INT16:
610       {
611         dbus_int16_t v;
612         if (!G_VALUE_HOLDS (value, G_TYPE_INT))
613           goto invalid_type;
614         dbus_message_iter_get_basic (iter, &v);
615         g_value_set_int (value, v);
616 	return TRUE;
617       }
618     case DBUS_TYPE_UINT16:
619       {
620         dbus_uint16_t v;
621         if (!G_VALUE_HOLDS (value, G_TYPE_UINT))
622           goto invalid_type;
623         dbus_message_iter_get_basic (iter, &v);
624         g_value_set_uint (value, v);
625 	return TRUE;
626       }
627     case DBUS_TYPE_STRING:
628       {
629         const char *s;
630         if (!G_VALUE_HOLDS (value, G_TYPE_STRING))
631           goto invalid_type;
632         dbus_message_iter_get_basic (iter, &s);
633 	g_value_set_string (value, s);
634 	return TRUE;
635       }
636     default:
637       /* fall through to invalid_type */
638       break;
639     }
640   invalid_type:
641     g_set_error (error,
642                  DBUS_GERROR,
643                  DBUS_GERROR_INVALID_ARGS,
644                  "Expected type %s, got type code \'%c\'",
645                  g_type_name (G_VALUE_TYPE (value)),
646                  (guchar) current_type);
647     return FALSE;
648 }
649 
650 static gboolean
demarshal_static_variant(DBusGValueMarshalCtx * context,DBusMessageIter * iter,GValue * value,GError ** error)651 demarshal_static_variant (DBusGValueMarshalCtx    *context,
652 			  DBusMessageIter         *iter,
653 			  GValue                  *value,
654 			  GError                 **error)
655 {
656   char *sig;
657   DBusMessageIter subiter;
658   GType variant_type;
659 
660   dbus_message_iter_recurse (iter, &subiter);
661   sig = dbus_message_iter_get_signature (&subiter);
662 
663   variant_type = _dbus_gtype_from_signature (sig, context->proxy != NULL);
664   if (variant_type == G_TYPE_INVALID)
665     {
666       /* It can happen if we received an unknown type such as
667        * DBUS_TYPE_UNIX_FD or DBUS_TYPE_MAYBE. */
668       g_set_error (error, DBUS_GERROR,
669                    DBUS_GERROR_INVALID_SIGNATURE,
670                    "Variant contains unknown signature \'%s\'", sig);
671       dbus_free (sig);
672       return FALSE;
673     }
674 
675   dbus_free (sig);
676 
677   g_value_init (value, variant_type);
678 
679   if (!_dbus_gvalue_demarshal (context, &subiter, value, error))
680     return FALSE;
681 
682   return TRUE;
683 }
684 
685 static gboolean
demarshal_variant(DBusGValueMarshalCtx * context,DBusMessageIter * iter,GValue * value,GError ** error)686 demarshal_variant (DBusGValueMarshalCtx    *context,
687 		   DBusMessageIter         *iter,
688 		   GValue                  *value,
689 		   GError                 **error)
690 
691 {
692   GValue *variant_val;
693   variant_val = g_new0 (GValue, 1);
694 
695   if (!demarshal_static_variant (context, iter, variant_val, error))
696     return FALSE;
697 
698   g_value_take_boxed (value, variant_val);
699   return TRUE;
700 }
701 
702 static gboolean
demarshal_proxy(DBusGValueMarshalCtx * context,DBusMessageIter * iter,GValue * value,GError ** error)703 demarshal_proxy (DBusGValueMarshalCtx    *context,
704 		 DBusMessageIter         *iter,
705 		 GValue                  *value,
706 		 GError                 **error)
707 {
708   DBusGProxy *new_proxy;
709   const char *objpath;
710   int current_type;
711 
712   current_type = dbus_message_iter_get_arg_type (iter);
713   if (current_type != DBUS_TYPE_OBJECT_PATH)
714     {
715       g_set_error (error,
716 		   DBUS_GERROR,
717 		   DBUS_GERROR_INVALID_ARGS,
718 		   "Expected D-BUS object path, got type code \'%c\'", (guchar) current_type);
719       return FALSE;
720     }
721 
722   g_assert (context->proxy != NULL);
723 
724   dbus_message_iter_get_basic (iter, &objpath);
725 
726   new_proxy = dbus_g_proxy_new_from_proxy (context->proxy, NULL, objpath);
727   g_value_take_object (value, new_proxy);
728 
729   return TRUE;
730 }
731 
732 static gboolean
demarshal_object_path(DBusGValueMarshalCtx * context,DBusMessageIter * iter,GValue * value,GError ** error)733 demarshal_object_path (DBusGValueMarshalCtx    *context,
734 		       DBusMessageIter         *iter,
735 		       GValue                  *value,
736 		       GError                 **error)
737 {
738   const char *objpath;
739   int current_type;
740 
741   current_type = dbus_message_iter_get_arg_type (iter);
742   if (current_type != DBUS_TYPE_OBJECT_PATH)
743     {
744       g_set_error (error,
745 		   DBUS_GERROR,
746 		   DBUS_GERROR_INVALID_ARGS,
747 		   "Expected D-BUS object path, got type code \'%c\'", (guchar) current_type);
748       return FALSE;
749     }
750 
751   dbus_message_iter_get_basic (iter, &objpath);
752 
753   g_value_set_boxed (value, objpath);
754 
755   return TRUE;
756 }
757 
758 static gboolean
demarshal_object(DBusGValueMarshalCtx * context,DBusMessageIter * iter,GValue * value,GError ** error)759 demarshal_object (DBusGValueMarshalCtx    *context,
760 		  DBusMessageIter         *iter,
761 		  GValue                  *value,
762 		  GError                 **error)
763 {
764   const char *objpath;
765   int current_type;
766   GObject *obj;
767 
768   current_type = dbus_message_iter_get_arg_type (iter);
769   if (current_type != DBUS_TYPE_OBJECT_PATH)
770     {
771       g_set_error (error,
772 		   DBUS_GERROR,
773 		   DBUS_GERROR_INVALID_ARGS,
774 		   "Expected D-BUS object path, got type code \'%c\'", (guchar) current_type);
775       return FALSE;
776     }
777   g_assert (context->proxy == NULL);
778 
779   dbus_message_iter_get_basic (iter, &objpath);
780 
781   obj = dbus_g_connection_lookup_g_object (context->gconnection, objpath);
782   if (obj == NULL)
783     {
784       g_set_error (error,
785 		   DBUS_GERROR,
786 		   DBUS_GERROR_INVALID_ARGS,
787 		   "Unregistered object at path '%s'",
788 		   objpath);
789       return FALSE;
790     }
791   g_value_set_object (value, obj);
792 
793   return TRUE;
794 }
795 
796 static gboolean
demarshal_signature(DBusGValueMarshalCtx * context,DBusMessageIter * iter,GValue * value,GError ** error)797 demarshal_signature (DBusGValueMarshalCtx    *context,
798 		     DBusMessageIter         *iter,
799 		     GValue                  *value,
800 		     GError                 **error)
801 {
802   const char *sig;
803   int current_type;
804 
805   current_type = dbus_message_iter_get_arg_type (iter);
806   if (current_type != DBUS_TYPE_SIGNATURE)
807     {
808       g_set_error (error,
809 		   DBUS_GERROR,
810 		   DBUS_GERROR_INVALID_ARGS,
811 		   "Expected D-BUS signature, got type code \'%c\'", (guchar) current_type);
812       return FALSE;
813     }
814 
815   dbus_message_iter_get_basic (iter, &sig);
816 
817   g_value_set_boxed (value, sig);
818 
819   return TRUE;
820 }
821 
822 static gboolean
demarshal_strv(DBusGValueMarshalCtx * context,DBusMessageIter * iter,GValue * value,GError ** error)823 demarshal_strv (DBusGValueMarshalCtx    *context,
824 		DBusMessageIter         *iter,
825 		GValue                  *value,
826 		GError                 **error)
827 {
828   DBusMessageIter subiter;
829   int current_type;
830   GArray *arr;
831 
832   current_type = dbus_message_iter_get_arg_type (iter);
833   if (current_type != DBUS_TYPE_ARRAY)
834     {
835       g_set_error (error,
836 		   DBUS_GERROR,
837 		   DBUS_GERROR_INVALID_ARGS,
838 		   "Expected D-BUS array, got type code \'%c\'", (guchar) current_type);
839       return FALSE;
840     }
841 
842   dbus_message_iter_recurse (iter, &subiter);
843 
844   current_type = dbus_message_iter_get_arg_type (&subiter);
845   if (current_type != DBUS_TYPE_INVALID
846       && current_type != DBUS_TYPE_STRING)
847     {
848       g_set_error (error,
849 		   DBUS_GERROR,
850 		   DBUS_GERROR_INVALID_ARGS,
851 		   "Expected D-BUS string, got type code \'%c\'", (guchar) current_type);
852       return FALSE;
853     }
854 
855   arr = g_array_new (TRUE, FALSE, sizeof (char *));
856 
857   while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
858     {
859       g_assert (current_type == DBUS_TYPE_STRING);
860       const char *str;
861       char *copy;
862 
863       dbus_message_iter_get_basic (&subiter, &str);
864       copy = g_strdup (str);
865       g_array_append_val (arr, copy);
866 
867       dbus_message_iter_next (&subiter);
868     }
869 
870   g_value_take_boxed (value, arr->data);
871   g_array_free (arr, FALSE);
872 
873   return TRUE;
874 }
875 
876 static gboolean
demarshal_valuearray(DBusGValueMarshalCtx * context,DBusMessageIter * iter,GValue * value,GError ** error)877 demarshal_valuearray (DBusGValueMarshalCtx    *context,
878 		      DBusMessageIter         *iter,
879 		      GValue                  *value,
880 		      GError                 **error)
881 {
882   int current_type;
883   GValueArray *ret;
884   DBusMessageIter subiter;
885 
886   current_type = dbus_message_iter_get_arg_type (iter);
887   if (current_type != DBUS_TYPE_STRUCT)
888     {
889       g_set_error (error,
890 		   DBUS_GERROR,
891 		   DBUS_GERROR_INVALID_ARGS,
892 		   "Expected D-BUS struct, got type code \'%c\'", (guchar) current_type);
893       return FALSE;
894     }
895 
896   dbus_message_iter_recurse (iter, &subiter);
897 
898   ret = g_value_array_new (12);
899 
900   while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
901     {
902       GValue *val;
903       GType elt_type;
904       char *current_sig;
905 
906       g_value_array_append (ret, NULL);
907       val = g_value_array_get_nth (ret, ret->n_values - 1);
908 
909       current_sig = dbus_message_iter_get_signature (&subiter);
910       elt_type = _dbus_gtype_from_signature (current_sig, TRUE);
911 
912       if (elt_type == G_TYPE_INVALID)
913 	{
914 	  g_value_array_free (ret);
915 	  g_set_error (error,
916 		       DBUS_GERROR,
917 		       DBUS_GERROR_INVALID_ARGS,
918 		       "Couldn't demarshal argument with signature \"%s\"", current_sig);
919 	  dbus_free (current_sig);
920 	  return FALSE;
921 	}
922       dbus_free (current_sig);
923 
924       g_value_init (val, elt_type);
925 
926       if (!_dbus_gvalue_demarshal (context, &subiter, val, error))
927 	{
928 	  g_value_array_free (ret);
929 	  return FALSE;
930 	}
931 
932       dbus_message_iter_next (&subiter);
933     }
934 
935   g_value_take_boxed (value, ret);
936 
937   return TRUE;
938 }
939 
940 static gboolean
demarshal_map(DBusGValueMarshalCtx * context,DBusMessageIter * iter,GValue * value,GError ** error)941 demarshal_map (DBusGValueMarshalCtx    *context,
942 	       DBusMessageIter         *iter,
943 	       GValue                  *value,
944 	       GError                 **error)
945 {
946   GType gtype;
947   DBusMessageIter subiter;
948   int current_type;
949   gpointer ret;
950   GType key_gtype;
951   GType value_gtype;
952   DBusGTypeSpecializedAppendContext appendctx;
953 
954   current_type = dbus_message_iter_get_arg_type (iter);
955   if (current_type != DBUS_TYPE_ARRAY)
956     {
957       g_set_error (error,
958 		   DBUS_GERROR,
959 		   DBUS_GERROR_INVALID_ARGS,
960 		   "Expected D-BUS array, got type code \'%c\'", (guchar) current_type);
961       return FALSE;
962     }
963 
964   gtype = G_VALUE_TYPE (value);
965 
966   dbus_message_iter_recurse (iter, &subiter);
967 
968   current_type = dbus_message_iter_get_arg_type (&subiter);
969   if (current_type != DBUS_TYPE_INVALID
970       && current_type != DBUS_TYPE_DICT_ENTRY)
971     {
972       g_set_error (error,
973 		   DBUS_GERROR,
974 		   DBUS_GERROR_INVALID_ARGS,
975 		   "Expected D-BUS dict entry, got type code \'%c\'", (guchar) current_type);
976       return FALSE;
977     }
978 
979   key_gtype = dbus_g_type_get_map_key_specialization (gtype);
980   value_gtype = dbus_g_type_get_map_value_specialization (gtype);
981 
982   ret = dbus_g_type_specialized_construct (gtype);
983   g_value_take_boxed (value, ret);
984 
985   dbus_g_type_specialized_init_append (value, &appendctx);
986 
987   while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
988     {
989       DBusMessageIter entry_iter;
990       GValue key_value = {0,};
991       GValue value_value = {0,};
992 
993       current_type = dbus_message_iter_get_arg_type (&subiter);
994       g_assert (current_type == DBUS_TYPE_DICT_ENTRY);
995 
996       dbus_message_iter_recurse (&subiter, &entry_iter);
997 
998       g_value_init (&key_value, key_gtype);
999       if (!_dbus_gvalue_demarshal (context,
1000 				  &entry_iter,
1001 				  &key_value,
1002 				  error))
1003 	return FALSE;
1004 
1005       dbus_message_iter_next (&entry_iter);
1006 
1007       g_value_init (&value_value, value_gtype);
1008       if (!_dbus_gvalue_demarshal (context,
1009 				  &entry_iter,
1010 				  &value_value,
1011 				  error))
1012 	return FALSE;
1013 
1014       dbus_g_type_specialized_map_append (&appendctx, &key_value, &value_value);
1015       /* Ownership of values passes to map, don't unset */
1016 
1017       dbus_message_iter_next (&subiter);
1018     }
1019 
1020   return TRUE;
1021 }
1022 
1023 static gboolean
demarshal_struct(DBusGValueMarshalCtx * context,DBusMessageIter * iter,GValue * value,GError ** error)1024 demarshal_struct (DBusGValueMarshalCtx    *context,
1025                   DBusMessageIter         *iter,
1026                   GValue                  *value,
1027                   GError                 **error)
1028 {
1029   int current_type;
1030   DBusMessageIter subiter;
1031   guint i, size;
1032   GValue val = {0,};
1033   GType elt_type;
1034 
1035   current_type = dbus_message_iter_get_arg_type (iter);
1036   if (current_type != DBUS_TYPE_STRUCT)
1037     {
1038       g_set_error (error,
1039                    DBUS_GERROR,
1040                    DBUS_GERROR_INVALID_ARGS,
1041                    "Expected D-BUS struct, got type code \'%c\'", (guchar) current_type);
1042       return FALSE;
1043     }
1044 
1045   dbus_message_iter_recurse (iter, &subiter);
1046 
1047   g_value_take_boxed (value,
1048     dbus_g_type_specialized_construct (G_VALUE_TYPE (value)));
1049 
1050   size = dbus_g_type_get_struct_size (G_VALUE_TYPE (value));
1051 
1052   for (i=0; i < size; i++)
1053     {
1054 
1055       elt_type = dbus_g_type_get_struct_member_type (G_VALUE_TYPE(value), i);
1056       if (elt_type == G_TYPE_INVALID)
1057         {
1058           g_value_unset (value);
1059           g_set_error (error,
1060                        DBUS_GERROR,
1061                        DBUS_GERROR_INVALID_ARGS,
1062                        "Couldn't demarshal argument, "
1063                          "struct type %s has no member %d",
1064                        g_type_name (G_VALUE_TYPE(value)), i);
1065           return FALSE;
1066         }
1067 
1068       g_value_init (&val, elt_type);
1069 
1070       if (!_dbus_gvalue_demarshal (context, &subiter, &val, error))
1071         {
1072           g_value_unset (&val);
1073           g_value_unset (value);
1074           return FALSE;
1075         }
1076       if (!dbus_g_type_struct_set_member (value, i, &val))
1077         {
1078           g_value_unset (&val);
1079           g_value_unset (value);
1080           return FALSE;
1081         }
1082 
1083       dbus_message_iter_next (&subiter);
1084       g_value_unset (&val);
1085     }
1086 
1087   g_assert (dbus_message_iter_get_arg_type (&subiter) == DBUS_TYPE_INVALID);
1088 
1089   return TRUE;
1090 }
1091 
1092 
1093 static DBusGValueDemarshalFunc
get_type_demarshaller(GType type)1094 get_type_demarshaller (GType type)
1095 {
1096   DBusGTypeMarshalData *typedata;
1097 
1098   typedata = g_type_get_qdata (type, dbus_g_type_metadata_data_quark ());
1099   if (typedata == NULL)
1100     {
1101       if (g_type_is_a (type, G_TYPE_VALUE_ARRAY))
1102 	return demarshal_valuearray;
1103       if (dbus_g_type_is_collection (type))
1104 	return demarshal_collection;
1105       if (dbus_g_type_is_map (type))
1106 	return demarshal_map;
1107       if (dbus_g_type_is_struct (type))
1108         return demarshal_struct;
1109 
1110       g_warning ("No demarshaller registered for type \"%s\"", g_type_name (type));
1111       return NULL;
1112     }
1113   g_assert (typedata->vtable);
1114   return typedata->vtable->demarshaller;
1115 }
1116 
1117 static gboolean
demarshal_collection(DBusGValueMarshalCtx * context,DBusMessageIter * iter,GValue * value,GError ** error)1118 demarshal_collection (DBusGValueMarshalCtx    *context,
1119 		      DBusMessageIter         *iter,
1120 		      GValue                  *value,
1121 		      GError                 **error)
1122 {
1123   GType coltype;
1124   GType subtype;
1125 
1126   coltype = G_VALUE_TYPE (value);
1127   subtype = dbus_g_type_get_collection_specialization (coltype);
1128 
1129   if (_dbus_g_type_is_fixed (subtype))
1130     return demarshal_collection_array (context, iter, value, error);
1131   else
1132     return demarshal_collection_ptrarray (context, iter, value, error);
1133 }
1134 
1135 static gboolean
demarshal_collection_ptrarray(DBusGValueMarshalCtx * context,DBusMessageIter * iter,GValue * value,GError ** error)1136 demarshal_collection_ptrarray (DBusGValueMarshalCtx    *context,
1137 			       DBusMessageIter         *iter,
1138 			       GValue                  *value,
1139 			       GError                 **error)
1140 {
1141   GType coltype;
1142   GType subtype;
1143   gpointer instance;
1144   DBusGTypeSpecializedAppendContext ctx;
1145   DBusGValueDemarshalFunc demarshaller;
1146   DBusMessageIter subiter;
1147   int current_type;
1148 
1149   current_type = dbus_message_iter_get_arg_type (iter);
1150 
1151   if (current_type != DBUS_TYPE_ARRAY)
1152     {
1153       g_set_error (error,
1154 		   DBUS_GERROR,
1155 		   DBUS_GERROR_INVALID_ARGS,
1156 		   "Expected D-BUS array, got type code \'%c\'", (guchar) current_type);
1157       return FALSE;
1158     }
1159 
1160   dbus_message_iter_recurse (iter, &subiter);
1161 
1162   coltype = G_VALUE_TYPE (value);
1163   subtype = dbus_g_type_get_collection_specialization (coltype);
1164 
1165   demarshaller = get_type_demarshaller (subtype);
1166 
1167   if (!demarshaller)
1168     {
1169       g_set_error (error,
1170 		   DBUS_GERROR,
1171 		   DBUS_GERROR_INVALID_ARGS,
1172 		   "No demarshaller registered for type \"%s\" of collection \"%s\"",
1173 		   g_type_name (coltype),
1174 		   g_type_name (subtype));
1175       return FALSE;
1176     }
1177 
1178   instance = dbus_g_type_specialized_construct (coltype);
1179   g_value_take_boxed (value, instance);
1180 
1181   dbus_g_type_specialized_init_append (value, &ctx);
1182 
1183   while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
1184     {
1185       GValue eltval = {0, };
1186 
1187       g_value_init (&eltval, subtype);
1188 
1189       if (!demarshaller (context, &subiter, &eltval, error))
1190 	{
1191 	  dbus_g_type_specialized_collection_end_append (&ctx);
1192 	  g_value_unset (value);
1193 	  return FALSE;
1194 	}
1195       dbus_g_type_specialized_collection_append (&ctx, &eltval);
1196 
1197       dbus_message_iter_next (&subiter);
1198     }
1199   dbus_g_type_specialized_collection_end_append (&ctx);
1200 
1201   return TRUE;
1202 }
1203 
1204 static gboolean
demarshal_collection_array(DBusGValueMarshalCtx * context,DBusMessageIter * iter,GValue * value,GError ** error)1205 demarshal_collection_array (DBusGValueMarshalCtx    *context,
1206 			    DBusMessageIter         *iter,
1207 			    GValue                  *value,
1208 			    GError                 **error)
1209 {
1210   DBusMessageIter subiter;
1211   GArray *ret;
1212   GType elt_gtype;
1213   int elt_size;
1214   void *msgarray;
1215   int msgarray_len;
1216 
1217   dbus_message_iter_recurse (iter, &subiter);
1218 
1219   elt_gtype = dbus_g_type_get_collection_specialization (G_VALUE_TYPE (value));
1220   g_assert (elt_gtype != G_TYPE_INVALID);
1221   g_assert (_dbus_g_type_is_fixed (elt_gtype));
1222 
1223   elt_size = _dbus_g_type_fixed_get_size (elt_gtype);
1224 
1225   ret = g_array_new (FALSE, TRUE, elt_size);
1226 
1227   msgarray = NULL;
1228   dbus_message_iter_get_fixed_array (&subiter,
1229 				     &msgarray,
1230 				     &msgarray_len);
1231   g_assert (msgarray != NULL || msgarray_len == 0);
1232 
1233   if (msgarray_len)
1234     g_array_append_vals (ret, msgarray, (guint) msgarray_len);
1235 
1236   g_value_take_boxed (value, ret);
1237 
1238   return TRUE;
1239 }
1240 
1241 gboolean
_dbus_gvalue_demarshal(DBusGValueMarshalCtx * context,DBusMessageIter * iter,GValue * value,GError ** error)1242 _dbus_gvalue_demarshal (DBusGValueMarshalCtx    *context,
1243 		       DBusMessageIter         *iter,
1244 		       GValue                  *value,
1245 		       GError                 **error)
1246 {
1247   GType gtype;
1248   DBusGValueDemarshalFunc demarshaller;
1249   gboolean retcode = FALSE;
1250 
1251   if (context->recursion_depth > DBUS_GLIB_MAX_VARIANT_RECURSION)
1252     {
1253       g_set_error (error, DBUS_GERROR,
1254                    DBUS_GERROR_NO_MEMORY,
1255                    "Variant recursion limit exceeded");
1256       return FALSE;
1257     }
1258   context->recursion_depth++;
1259 
1260   gtype = G_VALUE_TYPE (value);
1261 
1262   demarshaller = get_type_demarshaller (gtype);
1263 
1264   if (demarshaller == NULL)
1265     {
1266       g_set_error (error,
1267 		   DBUS_GERROR,
1268 		   DBUS_GERROR_INVALID_ARGS,
1269 		   "No demarshaller registered for type \"%s\"",
1270 		   g_type_name (gtype));
1271 
1272       goto out;
1273     }
1274 
1275   retcode = demarshaller (context, iter, value, error);
1276  out:
1277   context->recursion_depth--;
1278   return retcode;
1279 }
1280 
1281 gboolean
_dbus_gvalue_demarshal_variant(DBusGValueMarshalCtx * context,DBusMessageIter * iter,GValue * value,GError ** error)1282 _dbus_gvalue_demarshal_variant (DBusGValueMarshalCtx    *context,
1283 			       DBusMessageIter         *iter,
1284 			       GValue                  *value,
1285 			       GError                 **error)
1286 {
1287   return demarshal_static_variant (context, iter, value, error);
1288 }
1289 
1290 GValueArray *
_dbus_gvalue_demarshal_message(DBusGValueMarshalCtx * context,DBusMessage * message,guint n_types,const GType * types,GError ** error)1291 _dbus_gvalue_demarshal_message  (DBusGValueMarshalCtx    *context,
1292 				DBusMessage             *message,
1293 				guint                    n_types,
1294 				const GType             *types,
1295 				GError                 **error)
1296 {
1297   GValueArray *ret;
1298   DBusMessageIter iter;
1299   int current_type;
1300   guint index_;
1301 
1302   ret = g_value_array_new (6);  /* 6 is a typical maximum for arguments */
1303 
1304   dbus_message_iter_init (message, &iter);
1305   index_ = 0;
1306   while ((current_type = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID)
1307     {
1308       GValue *value;
1309       GType gtype;
1310 
1311       if (index_ >= n_types)
1312 	{
1313 	  g_set_error (error, DBUS_GERROR,
1314 		       DBUS_GERROR_INVALID_ARGS,
1315 		       "Too many arguments in message");
1316 	  goto lose;
1317 	}
1318 
1319       g_value_array_append (ret, NULL);
1320       value = g_value_array_get_nth (ret, index_);
1321 
1322       gtype = types[index_];
1323       g_value_init (value, gtype);
1324 
1325       if (!_dbus_gvalue_demarshal (context, &iter, value, error))
1326 	goto lose;
1327       dbus_message_iter_next (&iter);
1328       index_++;
1329     }
1330   if (index_ < n_types)
1331     {
1332       g_set_error (error, DBUS_GERROR,
1333 		   DBUS_GERROR_INVALID_ARGS,
1334 		   "Too few arguments in message");
1335       goto lose;
1336     }
1337 
1338   return ret;
1339  lose:
1340   g_value_array_free (ret);
1341   return NULL;
1342 }
1343 
1344 static void oom (void) G_GNUC_NORETURN;
1345 static void
oom(void)1346 oom (void)
1347 {
1348   g_error ("no memory");
1349 }
1350 
1351 static gboolean
marshal_basic(DBusMessageIter * iter,const GValue * value)1352 marshal_basic (DBusMessageIter *iter, const GValue *value)
1353 {
1354   GType value_type;
1355 
1356   value_type = G_VALUE_TYPE (value);
1357 
1358   switch (value_type)
1359     {
1360     case G_TYPE_CHAR:
1361       {
1362         char b = g_value_get_char (value);
1363         if (!dbus_message_iter_append_basic (iter,
1364                                              DBUS_TYPE_BYTE,
1365                                              &b))
1366           oom ();
1367       }
1368       return TRUE;
1369     case G_TYPE_UCHAR:
1370       {
1371         unsigned char b = g_value_get_uchar (value);
1372         if (!dbus_message_iter_append_basic (iter,
1373                                              DBUS_TYPE_BYTE,
1374                                              &b))
1375           oom ();
1376       }
1377       return TRUE;
1378     case G_TYPE_BOOLEAN:
1379       {
1380         dbus_bool_t b = g_value_get_boolean (value);
1381 
1382         g_return_val_if_fail (b == TRUE || b == FALSE, FALSE);
1383 
1384         if (!dbus_message_iter_append_basic (iter,
1385                                              DBUS_TYPE_BOOLEAN,
1386                                              &b))
1387           oom ();
1388       }
1389       return TRUE;
1390     case G_TYPE_INT:
1391       {
1392         dbus_int32_t v = g_value_get_int (value);
1393         if (!dbus_message_iter_append_basic (iter,
1394                                              DBUS_TYPE_INT32,
1395                                              &v))
1396           oom ();
1397       }
1398       return TRUE;
1399     case G_TYPE_UINT:
1400       {
1401         dbus_uint32_t v = g_value_get_uint (value);
1402         if (!dbus_message_iter_append_basic (iter,
1403                                              DBUS_TYPE_UINT32,
1404                                              &v))
1405           oom ();
1406       }
1407       return TRUE;
1408     case G_TYPE_LONG:
1409       {
1410         dbus_int32_t v = g_value_get_long (value);
1411         if (!dbus_message_iter_append_basic (iter,
1412                                              DBUS_TYPE_INT32,
1413                                              &v))
1414           oom ();
1415       }
1416       return TRUE;
1417     case G_TYPE_ULONG:
1418       {
1419         dbus_uint32_t v = g_value_get_ulong (value);
1420         if (!dbus_message_iter_append_basic (iter,
1421                                              DBUS_TYPE_UINT32,
1422                                              &v))
1423           oom ();
1424       }
1425       return TRUE;
1426     case G_TYPE_INT64:
1427       {
1428         gint64 v = g_value_get_int64 (value);
1429         if (!dbus_message_iter_append_basic (iter,
1430                                              DBUS_TYPE_INT64,
1431                                              &v))
1432           oom ();
1433       }
1434       return TRUE;
1435     case G_TYPE_UINT64:
1436       {
1437         guint64 v = g_value_get_uint64 (value);
1438         if (!dbus_message_iter_append_basic (iter,
1439                                              DBUS_TYPE_UINT64,
1440                                              &v))
1441           oom ();
1442       }
1443       return TRUE;
1444     case G_TYPE_FLOAT:
1445       {
1446         double v = g_value_get_float (value);
1447 
1448         if (!dbus_message_iter_append_basic (iter,
1449                                              DBUS_TYPE_DOUBLE,
1450                                              &v))
1451           oom ();
1452       }
1453       return TRUE;
1454     case G_TYPE_DOUBLE:
1455       {
1456         double v = g_value_get_double (value);
1457 
1458         if (!dbus_message_iter_append_basic (iter,
1459                                              DBUS_TYPE_DOUBLE,
1460                                              &v))
1461           oom ();
1462       }
1463       return TRUE;
1464     case G_TYPE_STRING:
1465       {
1466         const char *v = g_value_get_string (value);
1467 	if (!v)
1468 	  v = "";
1469 
1470         /* FIXME: fd.o #16320: consider using g_return_if_fail to check UTF-8
1471          * validity */
1472 
1473         if (!dbus_message_iter_append_basic (iter,
1474                                              DBUS_TYPE_STRING,
1475                                              &v))
1476           {
1477             gchar *s = g_strdup_value_contents (value);
1478 
1479             g_critical ("Unable to marshal string (not UTF-8 or OOM?): %s",
1480                 s);
1481             g_free (s);
1482             return FALSE;
1483           }
1484       }
1485       return TRUE;
1486 
1487     default:
1488       {
1489 	g_assert_not_reached ();
1490 	return FALSE;
1491       }
1492     }
1493 }
1494 
1495 static gboolean
marshal_strv(DBusMessageIter * iter,const GValue * value)1496 marshal_strv (DBusMessageIter   *iter,
1497 	      const GValue       *value)
1498 {
1499   DBusMessageIter subiter;
1500   char **array;
1501   char **elt;
1502   gboolean ret = FALSE;
1503 
1504   g_assert (G_VALUE_TYPE (value) == g_strv_get_type ());
1505 
1506   array = g_value_get_boxed (value);
1507 
1508   if (!dbus_message_iter_open_container (iter,
1509 					 DBUS_TYPE_ARRAY,
1510 					 "s",
1511 					 &subiter))
1512     goto out;
1513 
1514   if (array)
1515     {
1516       for (elt = array; *elt; elt++)
1517         {
1518           if (!dbus_message_iter_append_basic (&subiter,
1519 					   DBUS_TYPE_STRING,
1520 					   elt))
1521 	        goto out;
1522         }
1523     }
1524 
1525   if (!dbus_message_iter_close_container (iter, &subiter))
1526     goto out;
1527   ret = TRUE;
1528  out:
1529   return ret;
1530 }
1531 
1532 static gboolean
marshal_valuearray(DBusMessageIter * iter,const GValue * value)1533 marshal_valuearray (DBusMessageIter   *iter,
1534 		    const GValue       *value)
1535 {
1536   GValueArray *array;
1537   guint i;
1538   DBusMessageIter subiter;
1539 
1540   g_assert (G_VALUE_TYPE (value) == G_TYPE_VALUE_ARRAY);
1541 
1542   array = g_value_get_boxed (value);
1543 
1544   if (!dbus_message_iter_open_container (iter,
1545 					 DBUS_TYPE_STRUCT,
1546 					 NULL,
1547 					 &subiter))
1548     oom ();
1549 
1550   if (array)
1551     {
1552       for (i = 0; i < array->n_values; i++)
1553         {
1554           if (!_dbus_gvalue_marshal (&subiter, g_value_array_get_nth (array, i)))
1555             {
1556               dbus_message_iter_abandon_container (iter, &subiter);
1557               return FALSE;
1558             }
1559         }
1560     }
1561 
1562   return dbus_message_iter_close_container (iter, &subiter);
1563 }
1564 
1565 static gboolean
marshal_proxy(DBusMessageIter * iter,const GValue * value)1566 marshal_proxy (DBusMessageIter         *iter,
1567 	       const GValue            *value)
1568 {
1569   const char *path;
1570   DBusGProxy *proxy;
1571 
1572   g_assert (G_VALUE_TYPE (value) == dbus_g_proxy_get_type ());
1573 
1574   proxy = g_value_get_object (value);
1575   g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), FALSE);
1576   path = dbus_g_proxy_get_path (proxy);
1577   g_return_val_if_fail (g_variant_is_object_path (path), FALSE);
1578 
1579   if (!dbus_message_iter_append_basic (iter,
1580 				       DBUS_TYPE_OBJECT_PATH,
1581 				       &path))
1582     oom ();
1583 
1584   return TRUE;
1585 }
1586 
1587 static gboolean
marshal_object_path(DBusMessageIter * iter,const GValue * value)1588 marshal_object_path (DBusMessageIter         *iter,
1589 		     const GValue            *value)
1590 {
1591   const char *path;
1592 
1593   g_assert (G_VALUE_TYPE (value) == DBUS_TYPE_G_OBJECT_PATH);
1594 
1595   path = g_value_get_boxed (value);
1596   g_return_val_if_fail (g_variant_is_object_path (path), FALSE);
1597 
1598   if (!dbus_message_iter_append_basic (iter,
1599 				       DBUS_TYPE_OBJECT_PATH,
1600 				       &path))
1601     oom ();
1602 
1603   return TRUE;
1604 }
1605 
1606 static gboolean
marshal_object(DBusMessageIter * iter,const GValue * value)1607 marshal_object (DBusMessageIter         *iter,
1608 		const GValue            *value)
1609 {
1610   const char *path;
1611   GObject *obj;
1612 
1613   obj = g_value_get_object (value);
1614   g_return_val_if_fail (G_IS_OBJECT (obj), FALSE);
1615 
1616   path = _dbus_gobject_get_path (obj);
1617   g_return_val_if_fail (g_variant_is_object_path (path), FALSE);
1618 
1619   if (!dbus_message_iter_append_basic (iter,
1620 				       DBUS_TYPE_OBJECT_PATH,
1621 				       &path))
1622     oom ();
1623 
1624   return TRUE;
1625 }
1626 
1627 static gboolean
marshal_signature(DBusMessageIter * iter,const GValue * value)1628 marshal_signature (DBusMessageIter         *iter,
1629 		   const GValue            *value)
1630 {
1631   const char *sig;
1632 
1633   g_assert (G_VALUE_TYPE (value) == DBUS_TYPE_G_SIGNATURE);
1634 
1635   sig = g_value_get_boxed (value);
1636   g_return_val_if_fail (g_variant_is_signature (sig), FALSE);
1637 
1638   /* failure here isn't strictly *guaranteed* to be OOM, since GDBus might
1639    * understand more type-codes than our libdbus */
1640   if (!dbus_message_iter_append_basic (iter,
1641 				       DBUS_TYPE_SIGNATURE,
1642 				       &sig))
1643     return FALSE;
1644 
1645   return TRUE;
1646 }
1647 
1648 struct DBusGLibHashMarshalData
1649 {
1650   const char *entry_sig;
1651   DBusMessageIter *iter;
1652   gboolean err;
1653 };
1654 
1655 static void
marshal_map_entry(const GValue * key,const GValue * value,gpointer data)1656 marshal_map_entry (const GValue *key,
1657 		   const GValue *value,
1658 		   gpointer data)
1659 {
1660   struct DBusGLibHashMarshalData *hashdata = data;
1661   DBusMessageIter subiter;
1662 
1663   if (hashdata->err)
1664     return;
1665 
1666   if (!dbus_message_iter_open_container (hashdata->iter,
1667 					 DBUS_TYPE_DICT_ENTRY,
1668 					 NULL,
1669 					 &subiter))
1670     goto lose;
1671 
1672   if (!_dbus_gvalue_marshal (&subiter, key))
1673     goto lose;
1674 
1675   if (!_dbus_gvalue_marshal (&subiter, value))
1676     goto lose;
1677 
1678   if (!dbus_message_iter_close_container (hashdata->iter, &subiter))
1679     goto lose;
1680 
1681   return;
1682  lose:
1683   hashdata->err = TRUE;
1684 }
1685 
1686 static gboolean
marshal_map(DBusMessageIter * iter,const GValue * value)1687 marshal_map (DBusMessageIter   *iter,
1688 	     const GValue      *value)
1689 {
1690   GType gtype;
1691   DBusMessageIter arr_iter;
1692   struct DBusGLibHashMarshalData hashdata;
1693   char *key_sig;
1694   char *value_sig;
1695   GType key_type;
1696   GType value_type;
1697   char *entry_sig;
1698   char *array_sig;
1699 
1700   gtype = G_VALUE_TYPE (value);
1701 
1702   key_type = dbus_g_type_get_map_key_specialization (gtype);
1703   g_assert (_dbus_gtype_is_valid_hash_key (key_type));
1704   value_type = dbus_g_type_get_map_value_specialization (gtype);
1705   g_assert (_dbus_gtype_is_valid_hash_value (value_type));
1706 
1707   key_sig = _dbus_gtype_to_signature (key_type);
1708   if (!key_sig)
1709     {
1710       g_warning ("Cannot marshal type \"%s\" in map\n", g_type_name (key_type));
1711       return FALSE;
1712     }
1713   value_sig = _dbus_gtype_to_signature (value_type);
1714   if (!value_sig)
1715     {
1716       g_free (key_sig);
1717       g_warning ("Cannot marshal type \"%s\" in map\n", g_type_name (value_type));
1718       return FALSE;
1719     }
1720   entry_sig = g_strdup_printf ("%s%s", key_sig, value_sig);
1721   g_free (key_sig);
1722   g_free (value_sig);
1723   array_sig = g_strdup_printf ("%c%s%c",
1724 			       DBUS_DICT_ENTRY_BEGIN_CHAR,
1725 			       entry_sig,
1726 			       DBUS_DICT_ENTRY_END_CHAR);
1727   if (!dbus_message_iter_open_container (iter,
1728 					 DBUS_TYPE_ARRAY,
1729 					 array_sig,
1730 					 &arr_iter))
1731     goto lose;
1732 
1733   hashdata.iter = &arr_iter;
1734   hashdata.err = FALSE;
1735   hashdata.entry_sig = entry_sig;
1736 
1737   dbus_g_type_map_value_iterate (value,
1738 				 marshal_map_entry,
1739 				 &hashdata);
1740 
1741   if (hashdata.err)
1742     {
1743       dbus_message_iter_abandon_container (iter, &arr_iter);
1744       goto lose;
1745     }
1746   else if (!dbus_message_iter_close_container (iter, &arr_iter))
1747     {
1748       goto lose;
1749     }
1750 
1751  out:
1752   g_free (entry_sig);
1753   g_free (array_sig);
1754   return !hashdata.err;
1755  lose:
1756   hashdata.err = TRUE;
1757   goto out;
1758 }
1759 
1760 static gboolean
marshal_struct(DBusMessageIter * iter,const GValue * value)1761 marshal_struct (DBusMessageIter   *iter,
1762                 const GValue      *value)
1763 {
1764   GType gtype;
1765   DBusMessageIter subiter;
1766   guint size, i;
1767   GValue val = {0,};
1768 
1769   gtype = G_VALUE_TYPE (value);
1770 
1771   size = dbus_g_type_get_struct_size (gtype);
1772 
1773   if (!dbus_message_iter_open_container (iter,
1774                                          DBUS_TYPE_STRUCT,
1775                                          NULL,
1776                                          &subiter))
1777     oom ();
1778 
1779   for (i = 0; i < size; i++)
1780     {
1781       g_value_init (&val, dbus_g_type_get_struct_member_type
1782           (G_VALUE_TYPE(value), i));
1783 
1784       if (!dbus_g_type_struct_get_member (value, i, &val))
1785         goto abandon;
1786 
1787       if (!_dbus_gvalue_marshal (&subiter, &val))
1788         goto abandon;
1789 
1790       g_value_unset(&val);
1791     }
1792 
1793   return dbus_message_iter_close_container (iter, &subiter);
1794 
1795 abandon:
1796   dbus_message_iter_abandon_container (iter, &subiter);
1797   return FALSE;
1798 }
1799 
1800 static gboolean
marshal_variant(DBusMessageIter * iter,const GValue * value)1801 marshal_variant (DBusMessageIter          *iter,
1802 		 const GValue             *value)
1803 {
1804   GType value_gtype;
1805   DBusMessageIter subiter;
1806   char *variant_sig;
1807   GValue *real_value;
1808   gboolean ret = FALSE;
1809 
1810   real_value = g_value_get_boxed (value);
1811   value_gtype = G_VALUE_TYPE (real_value);
1812 
1813   variant_sig = _dbus_gvalue_to_signature (real_value);
1814   if (variant_sig == NULL)
1815     {
1816       g_warning ("Cannot marshal type \"%s\" in variant", g_type_name (value_gtype));
1817       return FALSE;
1818     }
1819 
1820   if (!dbus_message_iter_open_container (iter,
1821 					 DBUS_TYPE_VARIANT,
1822 					 variant_sig,
1823 					 &subiter))
1824     goto out;
1825 
1826   if (!_dbus_gvalue_marshal (&subiter, real_value))
1827     {
1828       dbus_message_iter_abandon_container (iter, &subiter);
1829       goto out;
1830     }
1831 
1832   if (!dbus_message_iter_close_container (iter, &subiter))
1833     goto out;
1834 
1835   ret = TRUE;
1836  out:
1837   g_free (variant_sig);
1838   return ret;
1839 }
1840 
1841 static DBusGValueMarshalFunc
get_type_marshaller(GType type)1842 get_type_marshaller (GType type)
1843 {
1844   DBusGTypeMarshalData *typedata;
1845 
1846   typedata = g_type_get_qdata (type, dbus_g_type_metadata_data_quark ());
1847   if (typedata == NULL)
1848     {
1849       if (g_type_is_a (type, G_TYPE_VALUE_ARRAY))
1850 	return marshal_valuearray;
1851       if (dbus_g_type_is_collection (type))
1852 	return marshal_collection;
1853       if (dbus_g_type_is_map (type))
1854 	return marshal_map;
1855       if (dbus_g_type_is_struct (type))
1856 	return marshal_struct;
1857 
1858       g_warning ("No marshaller registered for type \"%s\"", g_type_name (type));
1859       return NULL;
1860     }
1861   g_assert (typedata->vtable);
1862   return typedata->vtable->marshaller;
1863 }
1864 
1865 typedef struct
1866 {
1867   DBusMessageIter *iter;
1868   DBusGValueMarshalFunc marshaller;
1869   gboolean err;
1870 } DBusGValueCollectionMarshalData;
1871 
1872 static void
collection_marshal_iterator(const GValue * eltval,gpointer user_data)1873 collection_marshal_iterator (const GValue *eltval,
1874 			     gpointer      user_data)
1875 {
1876   DBusGValueCollectionMarshalData *data = user_data;
1877 
1878   if (data->err)
1879     return;
1880 
1881   if (!data->marshaller (data->iter, eltval))
1882     data->err = TRUE;
1883 }
1884 
1885 static gboolean
marshal_collection(DBusMessageIter * iter,const GValue * value)1886 marshal_collection (DBusMessageIter         *iter,
1887 		    const GValue            *value)
1888 {
1889   GType coltype;
1890   GType subtype;
1891 
1892   coltype = G_VALUE_TYPE (value);
1893   subtype = dbus_g_type_get_collection_specialization (coltype);
1894 
1895   if (_dbus_g_type_is_fixed (subtype))
1896     return marshal_collection_array (iter, value);
1897   else
1898     return marshal_collection_ptrarray (iter, value);
1899 }
1900 
1901 static gboolean
marshal_collection_ptrarray(DBusMessageIter * iter,const GValue * value)1902 marshal_collection_ptrarray (DBusMessageIter         *iter,
1903 			     const GValue            *value)
1904 {
1905   GType coltype;
1906   GType elt_gtype;
1907   DBusGValueCollectionMarshalData data;
1908   DBusMessageIter subiter;
1909   char *elt_sig;
1910 
1911   coltype = G_VALUE_TYPE (value);
1912   elt_gtype = dbus_g_type_get_collection_specialization (coltype);
1913   data.marshaller = get_type_marshaller (elt_gtype);
1914   if (!data.marshaller)
1915     return FALSE;
1916 
1917   elt_sig = _dbus_gtype_to_signature (elt_gtype);
1918   if (!elt_sig)
1919     {
1920       g_warning ("Cannot marshal type \"%s\" in collection\n", g_type_name (elt_gtype));
1921       return FALSE;
1922     }
1923   g_assert (g_variant_is_signature (elt_sig));
1924 
1925   if (!dbus_message_iter_open_container (iter,
1926 					 DBUS_TYPE_ARRAY,
1927 					 elt_sig,
1928 					 &subiter))
1929     oom ();
1930 
1931   g_free (elt_sig);
1932 
1933   data.iter = &subiter;
1934   data.err = FALSE;
1935 
1936   dbus_g_type_collection_value_iterate (value,
1937 					collection_marshal_iterator,
1938 					&data);
1939 
1940   if (data.err)
1941     {
1942       dbus_message_iter_abandon_container (iter, &subiter);
1943       return FALSE;
1944     }
1945 
1946   return dbus_message_iter_close_container (iter, &subiter);
1947 }
1948 
1949 /* If any of these assertions are violated, then marshal_collection_array
1950  * is buggy for that type. dbus_g_value_basic_array_parse_variant() has
1951  * general size-conversion code, if needed. */
1952 G_STATIC_ASSERT (sizeof (dbus_bool_t) == sizeof (gboolean));
1953 G_STATIC_ASSERT (sizeof (dbus_int32_t) == sizeof (gint));
1954 G_STATIC_ASSERT (sizeof (dbus_uint32_t) == sizeof (guint));
1955 /* These should be true regardless, but just for completeness... */
1956 G_STATIC_ASSERT (sizeof (dbus_int64_t) == sizeof (gint64));
1957 G_STATIC_ASSERT (sizeof (dbus_uint64_t) == sizeof (guint64));
1958 G_STATIC_ASSERT (sizeof (double) == sizeof (gdouble));
1959 
1960 static gboolean
marshal_collection_array(DBusMessageIter * iter,const GValue * value)1961 marshal_collection_array (DBusMessageIter   *iter,
1962 			  const GValue      *value)
1963 {
1964   GType elt_gtype;
1965   DBusMessageIter subiter;
1966   GArray *array;
1967   char *subsignature_str;
1968 
1969   array = g_value_get_boxed (value);
1970   g_return_val_if_fail (array != NULL, FALSE);
1971 
1972   elt_gtype = dbus_g_type_get_collection_specialization (G_VALUE_TYPE (value));
1973   g_assert (_dbus_g_type_is_fixed (elt_gtype));
1974   subsignature_str = _dbus_gtype_to_signature (elt_gtype);
1975   if (!subsignature_str)
1976     {
1977       g_warning ("Cannot marshal type \"%s\" in collection\n", g_type_name (elt_gtype));
1978       return FALSE;
1979     }
1980   g_assert (g_variant_is_signature (subsignature_str));
1981 
1982   if (!dbus_message_iter_open_container (iter,
1983 					 DBUS_TYPE_ARRAY,
1984 					 subsignature_str,
1985 					 &subiter))
1986     oom ();
1987 
1988   /* TODO - This assumes that basic values are the same size
1989    * is this always true?  If it is we can probably avoid
1990    * a lot of the overhead in _marshal_basic_instance...
1991    */
1992   if (!dbus_message_iter_append_fixed_array (&subiter,
1993 					     subsignature_str[0],
1994 					     &(array->data),
1995 					     array->len))
1996     {
1997       g_critical ("Unable to serialize %u GArray members as signature %s "
1998           "(OOM or invalid boolean value?)", array->len, subsignature_str);
1999 
2000       g_free (subsignature_str);
2001       dbus_message_iter_abandon_container (iter, &subiter);
2002       return FALSE;
2003     }
2004 
2005   g_free (subsignature_str);
2006   return dbus_message_iter_close_container (iter, &subiter);
2007 }
2008 
2009 gboolean
_dbus_gvalue_marshal(DBusMessageIter * iter,const GValue * value)2010 _dbus_gvalue_marshal (DBusMessageIter         *iter,
2011 		     const GValue       *value)
2012 {
2013   GType gtype;
2014   DBusGValueMarshalFunc marshaller;
2015 
2016   gtype = G_VALUE_TYPE (value);
2017 
2018   marshaller = get_type_marshaller (gtype);
2019   if (marshaller == NULL)
2020     return FALSE;
2021   return marshaller (iter, value);
2022 }
2023 
2024 #ifdef DBUS_BUILD_TESTS
2025 
2026 static void
assert_type_maps_to(GType gtype,const char * expected_sig)2027 assert_type_maps_to (GType gtype, const char *expected_sig)
2028 {
2029   char *sig;
2030   sig = _dbus_gtype_to_signature (gtype);
2031   g_assert_nonnull (sig);
2032   g_assert_cmpstr (expected_sig, ==, sig);
2033   g_free (sig);
2034 }
2035 
2036 static void
assert_signature_maps_to(const char * sig,GType expected_gtype)2037 assert_signature_maps_to (const char *sig, GType expected_gtype)
2038 {
2039   g_assert_cmpuint (_dbus_gtype_from_signature (sig, TRUE), ==, expected_gtype);
2040 }
2041 
2042 static void
assert_bidirectional_mapping(GType gtype,const char * expected_sig)2043 assert_bidirectional_mapping (GType gtype, const char *expected_sig)
2044 {
2045   assert_type_maps_to (gtype, expected_sig);
2046   assert_signature_maps_to (expected_sig, gtype);
2047 }
2048 
2049 /*
2050  * Unit test for general glib stuff
2051  * Returns: %TRUE on success.
2052  */
2053 gboolean
_dbus_gvalue_test(const char * test_data_dir)2054 _dbus_gvalue_test (const char *test_data_dir)
2055 {
2056   GType type;
2057   GType rectype;
2058 
2059   g_type_init ();
2060   _dbus_g_value_types_init ();
2061 
2062   assert_bidirectional_mapping (G_TYPE_STRING, DBUS_TYPE_STRING_AS_STRING);
2063   assert_bidirectional_mapping (G_TYPE_UCHAR, DBUS_TYPE_BYTE_AS_STRING);
2064   assert_bidirectional_mapping (G_TYPE_UINT, DBUS_TYPE_UINT32_AS_STRING);
2065 
2066   assert_bidirectional_mapping (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
2067 			      DBUS_TYPE_ARRAY_AS_STRING DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING DBUS_DICT_ENTRY_END_CHAR_AS_STRING);
2068   assert_bidirectional_mapping (dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH),
2069 				DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING);
2070   assert_bidirectional_mapping (dbus_g_type_get_collection ("GArray", G_TYPE_INT),
2071 				DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING);
2072 
2073   assert_bidirectional_mapping (dbus_g_type_get_struct ("GValueArray", G_TYPE_INT, G_TYPE_STRING, DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID),
2074   				DBUS_STRUCT_BEGIN_CHAR_AS_STRING DBUS_TYPE_INT32_AS_STRING DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING DBUS_STRUCT_END_CHAR_AS_STRING );
2075 
2076   rectype = dbus_g_type_get_collection ("GArray", G_TYPE_UINT);
2077   g_assert_cmpuint (rectype, !=, G_TYPE_INVALID);
2078   g_assert_cmpstr (g_type_name (rectype), ==, "GArray_guint_");
2079 
2080   type = _dbus_gtype_from_signature ("au", TRUE);
2081   g_assert_cmpuint (type, ==, rectype);
2082 
2083   rectype = dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING);
2084   g_assert_cmpuint (rectype, !=, G_TYPE_INVALID);
2085   g_assert_cmpstr (g_type_name (rectype), ==, "GHashTable_gchararray+gchararray_");
2086 
2087   type = _dbus_gtype_from_signature ("a{ss}", TRUE);
2088   g_assert_cmpuint (type, ==, rectype);
2089 
2090   type = _dbus_gtype_from_signature ("o", FALSE);
2091   g_assert_cmpuint (type, ==, DBUS_TYPE_G_OBJECT_PATH);
2092   type = _dbus_gtype_from_signature ("o", TRUE);
2093   g_assert_cmpuint (type, ==, DBUS_TYPE_G_OBJECT_PATH);
2094 
2095   type = _dbus_gtype_from_signature ("g", TRUE);
2096   g_assert_cmpuint (type, ==, DBUS_TYPE_G_SIGNATURE);
2097 
2098   return TRUE;
2099 }
2100 
2101 #endif /* DBUS_BUILD_TESTS */
2102