1 /* json-gvariant.c - JSON GVariant integration
2  *
3  * This file is part of JSON-GLib
4  * Copyright (C) 2007  OpenedHand Ltd.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * Author:
17  *   Eduardo Lima Mitev  <elima@igalia.com>
18  */
19 
20 #include "config.h"
21 
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <errno.h>
25 
26 #include <glib/gi18n-lib.h>
27 
28 #include <gio/gio.h>
29 
30 #include "json-gvariant.h"
31 
32 #include "json-generator.h"
33 #include "json-parser.h"
34 #include "json-types-private.h"
35 
36 /**
37  * SECTION:json-gvariant
38  * @short_description: Serialize and deserialize GVariant types
39  * @Title: JSON GVariant Integration
40  *
41  * Use json_gvariant_serialize() and json_gvariant_serialize_data() to
42  * convert from any #GVariant value to a #JsonNode tree or its string
43  * representation.
44  *
45  * Use json_gvariant_deserialize() and json_gvariant_deserialize_data() to
46  * obtain the #GVariant value from a #JsonNode tree or directly from a JSON
47  * string.
48  *
49  * Since many #GVariant data types cannot be directly represented as
50  * JSON, a #GVariant type string (signature) should be provided to these
51  * methods in order to obtain a correct, type-contrained result.
52  * If no signature is provided, conversion can still be done, but the
53  * resulting #GVariant value will be "guessed" from the JSON data types
54  * using the following rules:
55  *
56  * ## Strings
57  * JSON strings map to GVariant `(s)`.
58  *
59  * ## Integers
60  * JSON integers map to GVariant int64 `(x)`.
61  *
62  * ## Booleans
63  * JSON booleans map to GVariant boolean `(b)`.
64  *
65  * ## Numbers
66  * JSON numbers map to GVariant double `(d)`.
67  *
68  * ## Arrays
69  * JSON arrays map to GVariant arrays of variants `(av)`.
70  *
71  * ## Objects
72  * JSON objects map to GVariant dictionaries of string to variants `(a{sv})`.
73  *
74  * ## Null values
75  * JSON null values map to GVariant maybe variants `(mv)`.
76  */
77 
78 /* custom extension to the GVariantClass enumeration to differentiate
79  * a single dictionary entry from an array of dictionary entries
80  */
81 #define JSON_G_VARIANT_CLASS_DICTIONARY 'c'
82 
83 typedef void (* GVariantForeachFunc) (GVariant *variant_child,
84                                       gpointer  user_data);
85 
86 static GVariant * json_to_gvariant_recurse (JsonNode      *json_node,
87                                             const gchar  **signature,
88                                             GError       **error);
89 
90 /* ========================================================================== */
91 /* GVariant to JSON */
92 /* ========================================================================== */
93 
94 static void
gvariant_foreach(GVariant * variant,GVariantForeachFunc func,gpointer user_data)95 gvariant_foreach (GVariant            *variant,
96                   GVariantForeachFunc  func,
97                   gpointer             user_data)
98 {
99   GVariantIter iter;
100   GVariant *variant_child;
101 
102   g_variant_iter_init (&iter, variant);
103   while ((variant_child = g_variant_iter_next_value (&iter)) != NULL)
104     {
105       func (variant_child, user_data);
106       g_variant_unref (variant_child);
107     }
108 }
109 
110 static void
gvariant_to_json_array_foreach(GVariant * variant_child,gpointer user_data)111 gvariant_to_json_array_foreach (GVariant *variant_child,
112                                 gpointer  user_data)
113 {
114   JsonArray *array = user_data;
115   JsonNode *json_child;
116 
117   json_child = json_gvariant_serialize (variant_child);
118   json_array_add_element (array, json_child);
119 }
120 
121 static JsonNode *
gvariant_to_json_array(GVariant * variant)122 gvariant_to_json_array (GVariant *variant)
123 {
124   JsonArray *array;
125   JsonNode *json_node;
126 
127   array = json_array_new ();
128   json_node = json_node_new (JSON_NODE_ARRAY);
129   json_node_set_array (json_node, array);
130   json_array_unref (array);
131 
132   gvariant_foreach (variant,
133                     gvariant_to_json_array_foreach,
134                     array);
135 
136   return json_node;
137 }
138 
139 static gchar *
gvariant_simple_to_string(GVariant * variant)140 gvariant_simple_to_string (GVariant *variant)
141 {
142   GVariantClass class;
143   gchar *str;
144 
145   class = g_variant_classify (variant);
146   switch (class)
147     {
148     case G_VARIANT_CLASS_BOOLEAN:
149       if (g_variant_get_boolean (variant))
150         str = g_strdup ("true");
151       else
152         str = g_strdup ("false");
153       break;
154 
155     case G_VARIANT_CLASS_BYTE:
156       str = g_strdup_printf ("%u", g_variant_get_byte (variant));
157       break;
158     case G_VARIANT_CLASS_INT16:
159       str = g_strdup_printf ("%d", g_variant_get_int16 (variant));
160       break;
161     case G_VARIANT_CLASS_UINT16:
162       str = g_strdup_printf ("%u", g_variant_get_uint16 (variant));
163       break;
164     case G_VARIANT_CLASS_INT32:
165       str = g_strdup_printf ("%d", g_variant_get_int32 (variant));
166       break;
167     case G_VARIANT_CLASS_UINT32:
168       str = g_strdup_printf ("%u", g_variant_get_uint32 (variant));
169       break;
170     case G_VARIANT_CLASS_INT64:
171       str = g_strdup_printf ("%" G_GINT64_FORMAT,
172                              g_variant_get_int64 (variant));
173       break;
174     case G_VARIANT_CLASS_UINT64:
175       str = g_strdup_printf ("%" G_GUINT64_FORMAT,
176                              g_variant_get_uint64 (variant));
177       break;
178     case G_VARIANT_CLASS_HANDLE:
179       str = g_strdup_printf ("%d", g_variant_get_handle (variant));
180       break;
181 
182     case G_VARIANT_CLASS_DOUBLE:
183       {
184         gchar buf[G_ASCII_DTOSTR_BUF_SIZE];
185 
186         g_ascii_formatd (buf,
187                          G_ASCII_DTOSTR_BUF_SIZE,
188                          "%f",
189                          g_variant_get_double (variant));
190 
191         str = g_strdup (buf);
192         break;
193       }
194 
195     case G_VARIANT_CLASS_STRING:
196     case G_VARIANT_CLASS_OBJECT_PATH:
197     case G_VARIANT_CLASS_SIGNATURE:
198       str = g_strdup (g_variant_get_string (variant, NULL));
199       break;
200 
201     default:
202       g_assert_not_reached ();
203       break;
204     }
205 
206   return str;
207 }
208 
209 static JsonNode *
gvariant_dict_entry_to_json(GVariant * variant,gchar ** member_name)210 gvariant_dict_entry_to_json (GVariant  *variant, gchar **member_name)
211 {
212   GVariant *member;
213   GVariant *value;
214   JsonNode *json_node;
215 
216   member = g_variant_get_child_value (variant, 0);
217   *member_name = gvariant_simple_to_string (member);
218 
219   value = g_variant_get_child_value (variant, 1);
220   json_node = json_gvariant_serialize (value);
221 
222   g_variant_unref (member);
223   g_variant_unref (value);
224 
225   return json_node;
226 }
227 
228 static void
gvariant_to_json_object_foreach(GVariant * variant_child,gpointer user_data)229 gvariant_to_json_object_foreach (GVariant *variant_child, gpointer  user_data)
230 {
231   gchar *member_name;
232   JsonNode *json_child;
233   JsonObject *object = (JsonObject *) user_data;
234 
235   json_child = gvariant_dict_entry_to_json (variant_child, &member_name);
236   json_object_set_member (object, member_name, json_child);
237   g_free (member_name);
238 }
239 
240 static JsonNode *
gvariant_to_json_object(GVariant * variant)241 gvariant_to_json_object (GVariant *variant)
242 {
243   JsonNode *json_node;
244   JsonObject *object;
245 
246   json_node = json_node_new (JSON_NODE_OBJECT);
247   object = json_object_new ();
248   json_node_set_object (json_node, object);
249   json_object_unref (object);
250 
251   gvariant_foreach (variant,
252                     gvariant_to_json_object_foreach,
253                     object);
254 
255   return json_node;
256 }
257 
258 /**
259  * json_gvariant_serialize:
260  * @variant: A #GVariant to convert
261  *
262  * Converts @variant to a JSON tree.
263  *
264  * Return value: (transfer full): A #JsonNode representing the root of the
265  *   JSON data structure obtained from @variant
266  *
267  * Since: 0.14
268  */
269 JsonNode *
json_gvariant_serialize(GVariant * variant)270 json_gvariant_serialize (GVariant *variant)
271 {
272   JsonNode *json_node = NULL;
273   GVariantClass class;
274 
275   g_return_val_if_fail (variant != NULL, NULL);
276 
277   class = g_variant_classify (variant);
278 
279   if (! g_variant_is_container (variant))
280     {
281       json_node = json_node_new (JSON_NODE_VALUE);
282 
283       switch (class)
284         {
285         case G_VARIANT_CLASS_BOOLEAN:
286           json_node_set_boolean (json_node, g_variant_get_boolean (variant));
287           break;
288 
289         case G_VARIANT_CLASS_BYTE:
290           json_node_set_int (json_node, g_variant_get_byte (variant));
291           break;
292         case G_VARIANT_CLASS_INT16:
293           json_node_set_int (json_node, g_variant_get_int16 (variant));
294           break;
295         case G_VARIANT_CLASS_UINT16:
296           json_node_set_int (json_node, g_variant_get_uint16 (variant));
297           break;
298         case G_VARIANT_CLASS_INT32:
299           json_node_set_int (json_node, g_variant_get_int32 (variant));
300           break;
301         case G_VARIANT_CLASS_UINT32:
302           json_node_set_int (json_node, g_variant_get_uint32 (variant));
303           break;
304         case G_VARIANT_CLASS_INT64:
305           json_node_set_int (json_node, g_variant_get_int64 (variant));
306           break;
307         case G_VARIANT_CLASS_UINT64:
308           json_node_set_int (json_node, g_variant_get_uint64 (variant));
309           break;
310         case G_VARIANT_CLASS_HANDLE:
311           json_node_set_int (json_node, g_variant_get_handle (variant));
312           break;
313 
314         case G_VARIANT_CLASS_DOUBLE:
315           json_node_set_double (json_node, g_variant_get_double (variant));
316           break;
317 
318         case G_VARIANT_CLASS_STRING:
319         case G_VARIANT_CLASS_OBJECT_PATH:
320         case G_VARIANT_CLASS_SIGNATURE:
321           json_node_set_string (json_node, g_variant_get_string (variant, NULL));
322           break;
323 
324         default:
325           break;
326         }
327     }
328   else
329     {
330       switch (class)
331         {
332         case G_VARIANT_CLASS_MAYBE:
333           {
334             GVariant *value;
335 
336             value = g_variant_get_maybe (variant);
337             if (value == NULL)
338               {
339                 json_node = json_node_new (JSON_NODE_NULL);
340               }
341             else
342               {
343                 json_node = json_gvariant_serialize (value);
344                 g_variant_unref (value);
345               }
346 
347             break;
348           }
349 
350         case G_VARIANT_CLASS_VARIANT:
351           {
352             GVariant *value;
353 
354             value = g_variant_get_variant (variant);
355             json_node = json_gvariant_serialize (value);
356             g_variant_unref (value);
357 
358             break;
359           }
360 
361         case G_VARIANT_CLASS_ARRAY:
362           {
363             const gchar *type;
364 
365             type = g_variant_get_type_string (variant);
366 
367             if (type[1] == G_VARIANT_CLASS_DICT_ENTRY)
368               {
369                 /* array of dictionary entries => JsonObject */
370                 json_node = gvariant_to_json_object (variant);
371               }
372             else
373               {
374                 /* array of anything else => JsonArray */
375                 json_node = gvariant_to_json_array (variant);
376               }
377 
378             break;
379           }
380 
381         case G_VARIANT_CLASS_DICT_ENTRY:
382           {
383             gchar *member_name;
384             JsonObject *object;
385             JsonNode *child;
386 
387             /* a single dictionary entry => JsonObject */
388             json_node = json_node_new (JSON_NODE_OBJECT);
389             object = json_object_new ();
390             json_node_set_object (json_node, object);
391             json_object_unref (object);
392 
393             child = gvariant_dict_entry_to_json (variant, &member_name);
394 
395             json_object_set_member (object, member_name, child);
396             g_free (member_name);
397 
398             break;
399           }
400 
401         case G_VARIANT_CLASS_TUPLE:
402           json_node = gvariant_to_json_array (variant);
403           break;
404 
405         default:
406           break;
407         }
408     }
409 
410   return json_node;
411 }
412 
413 /**
414  * json_gvariant_serialize_data:
415  * @variant: A #GVariant to convert
416  * @length: (out) (allow-none): Return location for the length of the returned
417  *   string, or %NULL
418  *
419  * Converts @variant to its JSON encoded string representation. This method
420  * is actually a helper function. It uses json_gvariant_serialize() to obtain the
421  * JSON tree, and then #JsonGenerator to stringify it.
422  *
423  * Return value: (transfer full): The JSON encoded string corresponding to
424  *   @variant
425  *
426  * Since: 0.14
427  */
428 gchar *
json_gvariant_serialize_data(GVariant * variant,gsize * length)429 json_gvariant_serialize_data (GVariant *variant, gsize *length)
430 {
431   JsonNode *json_node;
432   JsonGenerator *generator;
433   gchar *json;
434 
435   json_node = json_gvariant_serialize (variant);
436 
437   generator = json_generator_new ();
438 
439   json_generator_set_root (generator, json_node);
440   json = json_generator_to_data (generator, length);
441 
442   g_object_unref (generator);
443 
444   json_node_unref (json_node);
445 
446   return json;
447 }
448 
449 /* ========================================================================== */
450 /* JSON to GVariant */
451 /* ========================================================================== */
452 
453 static GVariantClass
json_to_gvariant_get_next_class(JsonNode * json_node,const gchar ** signature)454 json_to_gvariant_get_next_class (JsonNode     *json_node,
455                                  const gchar **signature)
456 {
457   if (signature == NULL)
458     {
459       GVariantClass class = 0;
460 
461       switch (json_node_get_node_type (json_node))
462         {
463         case JSON_NODE_VALUE:
464           switch (json_node_get_value_type (json_node))
465             {
466             case G_TYPE_BOOLEAN:
467               class = G_VARIANT_CLASS_BOOLEAN;
468               break;
469 
470             case G_TYPE_INT64:
471               class = G_VARIANT_CLASS_INT64;
472               break;
473 
474             case G_TYPE_DOUBLE:
475               class = G_VARIANT_CLASS_DOUBLE;
476               break;
477 
478             case G_TYPE_STRING:
479               class = G_VARIANT_CLASS_STRING;
480               break;
481             }
482 
483           break;
484 
485         case JSON_NODE_ARRAY:
486           class = G_VARIANT_CLASS_ARRAY;
487           break;
488 
489         case JSON_NODE_OBJECT:
490           class = JSON_G_VARIANT_CLASS_DICTIONARY;
491           break;
492 
493         case JSON_NODE_NULL:
494           class = G_VARIANT_CLASS_MAYBE;
495           break;
496         }
497 
498       return class;
499     }
500   else
501     {
502       if ((*signature)[0] == G_VARIANT_CLASS_ARRAY &&
503           (*signature)[1] == G_VARIANT_CLASS_DICT_ENTRY)
504         return JSON_G_VARIANT_CLASS_DICTIONARY;
505       else
506         return (*signature)[0];
507     }
508 }
509 
510 static gboolean
json_node_assert_type(JsonNode * json_node,JsonNodeType type,GType sub_type,GError ** error)511 json_node_assert_type (JsonNode       *json_node,
512                        JsonNodeType    type,
513                        GType           sub_type,
514                        GError        **error)
515 {
516   if (JSON_NODE_TYPE (json_node) != type ||
517       (type == JSON_NODE_VALUE &&
518        (json_node_get_value_type (json_node) != sub_type)))
519     {
520       g_set_error (error,
521                    G_IO_ERROR,
522                    G_IO_ERROR_INVALID_DATA,
523                    /* translators: the '%s' is the type name */
524                    _("Unexpected type “%s” in JSON node"),
525                    g_type_name (json_node_get_value_type (json_node)));
526       return FALSE;
527     }
528   else
529     {
530       return TRUE;
531     }
532 }
533 
534 static void
json_to_gvariant_foreach_add(gpointer data,gpointer user_data)535 json_to_gvariant_foreach_add (gpointer data, gpointer user_data)
536 {
537   GVariantBuilder *builder = (GVariantBuilder *) user_data;
538   GVariant *child = (GVariant *) data;
539 
540   g_variant_builder_add_value (builder, child);
541 }
542 
543 static void
json_to_gvariant_foreach_free(gpointer data,gpointer user_data)544 json_to_gvariant_foreach_free (gpointer data, gpointer user_data)
545 {
546   GVariant *child = (GVariant *) data;
547 
548   g_variant_unref (child);
549 }
550 
551 static GVariant *
json_to_gvariant_build_from_glist(GList * list,const gchar * signature)552 json_to_gvariant_build_from_glist (GList *list, const gchar *signature)
553 {
554   GVariantBuilder *builder;
555   GVariant *result;
556 
557   builder = g_variant_builder_new (G_VARIANT_TYPE (signature));
558 
559   g_list_foreach (list, json_to_gvariant_foreach_add, builder);
560   result = g_variant_builder_end (builder);
561 
562   g_variant_builder_unref (builder);
563 
564   return result;
565 }
566 
567 static GVariant *
json_to_gvariant_tuple(JsonNode * json_node,const gchar ** signature,GError ** error)568 json_to_gvariant_tuple (JsonNode     *json_node,
569                         const gchar **signature,
570                         GError      **error)
571 {
572   GVariant *variant = NULL;
573   JsonArray *array;
574   gint i;
575   GList *children = NULL;
576   gboolean roll_back = FALSE;
577   const gchar *initial_signature;
578 
579   array = json_node_get_array (json_node);
580 
581   initial_signature = *signature;
582   (*signature)++;
583   i = 1;
584   while ((*signature)[0] != ')' && (*signature)[0] != '\0')
585     {
586       JsonNode *json_child;
587       GVariant *variant_child;
588 
589       if (i - 1 >= json_array_get_length (array))
590         {
591           g_set_error_literal (error,
592                                G_IO_ERROR,
593                                G_IO_ERROR_INVALID_DATA,
594                                _("Missing elements in JSON array to conform to a tuple"));
595           roll_back = TRUE;
596           break;
597         }
598 
599       json_child = json_array_get_element (array, i - 1);
600 
601       variant_child = json_to_gvariant_recurse (json_child, signature, error);
602       if (variant_child != NULL)
603         {
604           children = g_list_append (children, variant_child);
605         }
606       else
607         {
608           roll_back = TRUE;
609           break;
610         }
611 
612       i++;
613     }
614 
615   if (! roll_back)
616     {
617       if ( (*signature)[0] != ')')
618         {
619           g_set_error_literal (error,
620                                G_IO_ERROR,
621                                G_IO_ERROR_INVALID_DATA,
622                                _("Missing closing symbol “)” in the GVariant tuple type"));
623           roll_back = TRUE;
624         }
625       else if (json_array_get_length (array) >= i)
626         {
627           g_set_error_literal (error,
628                                G_IO_ERROR,
629                                G_IO_ERROR_INVALID_DATA,
630                                _("Unexpected extra elements in JSON array"));
631           roll_back = TRUE;
632         }
633       else
634         {
635           gchar *tuple_type;
636 
637           tuple_type = g_strndup (initial_signature,
638                                   (*signature) - initial_signature + 1);
639 
640           variant = json_to_gvariant_build_from_glist (children, tuple_type);
641 
642           g_free (tuple_type);
643         }
644     }
645 
646   if (roll_back)
647     g_list_foreach (children, json_to_gvariant_foreach_free, NULL);
648 
649   g_list_free (children);
650 
651   return variant;
652 }
653 
654 static gchar *
signature_get_next_complete_type(const gchar ** signature)655 signature_get_next_complete_type (const gchar **signature)
656 {
657   GVariantClass class;
658   const gchar *initial_signature;
659   gchar *result;
660 
661   /* here it is assumed that 'signature' is a valid type string */
662 
663   initial_signature = *signature;
664   class = (*signature)[0];
665 
666   if (class == G_VARIANT_CLASS_TUPLE || class == G_VARIANT_CLASS_DICT_ENTRY)
667     {
668       gchar stack[256] = {0};
669       guint stack_len = 0;
670 
671       do
672         {
673           if ( (*signature)[0] == G_VARIANT_CLASS_TUPLE)
674             {
675               stack[stack_len] = ')';
676               stack_len++;
677             }
678           else if ( (*signature)[0] == G_VARIANT_CLASS_DICT_ENTRY)
679             {
680               stack[stack_len] = '}';
681               stack_len++;
682             }
683 
684           (*signature)++;
685 
686           if ( (*signature)[0] == stack[stack_len - 1])
687             stack_len--;
688         }
689       while (stack_len > 0);
690 
691       (*signature)++;
692     }
693   else if (class == G_VARIANT_CLASS_ARRAY || class == G_VARIANT_CLASS_MAYBE)
694     {
695       gchar *tmp_sig;
696 
697       (*signature)++;
698       tmp_sig = signature_get_next_complete_type (signature);
699       g_free (tmp_sig);
700     }
701   else
702     {
703       (*signature)++;
704     }
705 
706   result = g_strndup (initial_signature, (*signature) - initial_signature);
707 
708   return result;
709 }
710 
711 static GVariant *
json_to_gvariant_maybe(JsonNode * json_node,const gchar ** signature,GError ** error)712 json_to_gvariant_maybe (JsonNode     *json_node,
713                         const gchar **signature,
714                         GError      **error)
715 {
716   GVariant *variant = NULL;
717   GVariant *value;
718   gchar *maybe_signature;
719 
720   if (signature)
721     {
722       (*signature)++;
723       maybe_signature = signature_get_next_complete_type (signature);
724     }
725   else
726     {
727       maybe_signature = g_strdup ("v");
728     }
729 
730   if (json_node_get_node_type (json_node) == JSON_NODE_NULL)
731     {
732       variant = g_variant_new_maybe (G_VARIANT_TYPE (maybe_signature), NULL);
733     }
734   else
735     {
736       const gchar *tmp_signature;
737 
738       tmp_signature = maybe_signature;
739       value = json_to_gvariant_recurse (json_node,
740                                         &tmp_signature,
741                                         error);
742 
743       if (value != NULL)
744         variant = g_variant_new_maybe (G_VARIANT_TYPE (maybe_signature), value);
745     }
746 
747   g_free (maybe_signature);
748 
749   /* compensate the (*signature)++ call at the end of 'recurse()' */
750   if (signature)
751     (*signature)--;
752 
753   return variant;
754 }
755 
756 static GVariant *
json_to_gvariant_array(JsonNode * json_node,const gchar ** signature,GError ** error)757 json_to_gvariant_array (JsonNode     *json_node,
758                         const gchar **signature,
759                         GError      **error)
760 {
761   GVariant *variant = NULL;
762   JsonArray *array;
763   GList *children = NULL;
764   gboolean roll_back = FALSE;
765   const gchar *orig_signature = NULL;
766   gchar *child_signature;
767 
768   array = json_node_get_array (json_node);
769 
770   if (signature != NULL)
771     {
772       orig_signature = *signature;
773 
774       (*signature)++;
775       child_signature = signature_get_next_complete_type (signature);
776     }
777   else
778     child_signature = g_strdup ("v");
779 
780   if (json_array_get_length (array) > 0)
781     {
782       gint i;
783       guint len;
784 
785       len = json_array_get_length (array);
786       for (i = 0; i < len; i++)
787         {
788           JsonNode *json_child;
789           GVariant *variant_child;
790           const gchar *tmp_signature;
791 
792           json_child = json_array_get_element (array, i);
793 
794           tmp_signature = child_signature;
795           variant_child = json_to_gvariant_recurse (json_child,
796                                                     &tmp_signature,
797                                                     error);
798           if (variant_child != NULL)
799             {
800               children = g_list_append (children, variant_child);
801             }
802           else
803             {
804               roll_back = TRUE;
805               break;
806             }
807         }
808     }
809 
810   if (!roll_back)
811     {
812       gchar *array_signature;
813 
814       if (signature)
815         array_signature = g_strndup (orig_signature, (*signature) - orig_signature);
816       else
817         array_signature = g_strdup ("av");
818 
819       variant = json_to_gvariant_build_from_glist (children, array_signature);
820 
821       g_free (array_signature);
822 
823       /* compensate the (*signature)++ call at the end of 'recurse()' */
824       if (signature)
825         (*signature)--;
826     }
827   else
828     g_list_foreach (children, json_to_gvariant_foreach_free, NULL);
829 
830   g_list_free (children);
831   g_free (child_signature);
832 
833   return variant;
834 }
835 
836 static GVariant *
gvariant_simple_from_string(const gchar * st,GVariantClass class,GError ** error)837 gvariant_simple_from_string (const gchar    *st,
838                              GVariantClass   class,
839                              GError        **error)
840 {
841   GVariant *variant = NULL;
842   gchar *nptr = NULL;
843   gboolean conversion_error = FALSE;
844   gint64 signed_value;
845   guint64 unsigned_value;
846   gdouble double_value;
847 
848   errno = 0;
849 
850   switch (class)
851     {
852     case G_VARIANT_CLASS_BOOLEAN:
853       if (g_strcmp0 (st, "true") == 0)
854         variant = g_variant_new_boolean (TRUE);
855       else if (g_strcmp0 (st, "false") == 0)
856         variant = g_variant_new_boolean (FALSE);
857       else
858         conversion_error = TRUE;
859       break;
860 
861     case G_VARIANT_CLASS_BYTE:
862       signed_value = g_ascii_strtoll (st, &nptr, 10);
863       conversion_error = errno != 0 || nptr == st;
864       variant = g_variant_new_byte (signed_value);
865       break;
866 
867     case G_VARIANT_CLASS_INT16:
868       signed_value = g_ascii_strtoll (st, &nptr, 10);
869       conversion_error = errno != 0 || nptr == st;
870       variant = g_variant_new_int16 (signed_value);
871       break;
872 
873     case G_VARIANT_CLASS_UINT16:
874       signed_value = g_ascii_strtoll (st, &nptr, 10);
875       conversion_error = errno != 0 || nptr == st;
876       variant = g_variant_new_uint16 (signed_value);
877       break;
878 
879     case G_VARIANT_CLASS_INT32:
880       signed_value = g_ascii_strtoll (st, &nptr, 10);
881       conversion_error = errno != 0 || nptr == st;
882       variant = g_variant_new_int32 (signed_value);
883       break;
884 
885     case G_VARIANT_CLASS_UINT32:
886       unsigned_value = g_ascii_strtoull (st, &nptr, 10);
887       conversion_error = errno != 0 || nptr == st;
888       variant = g_variant_new_uint32 (unsigned_value);
889       break;
890 
891     case G_VARIANT_CLASS_INT64:
892       signed_value = g_ascii_strtoll (st, &nptr, 10);
893       conversion_error = errno != 0 || nptr == st;
894       variant = g_variant_new_int64 (signed_value);
895       break;
896 
897     case G_VARIANT_CLASS_UINT64:
898       unsigned_value = g_ascii_strtoull (st, &nptr, 10);
899       conversion_error = errno != 0 || nptr == st;
900       variant = g_variant_new_uint64 (unsigned_value);
901       break;
902 
903     case G_VARIANT_CLASS_HANDLE:
904       signed_value = strtol (st, &nptr, 10);
905       conversion_error = errno != 0 || nptr == st;
906       variant = g_variant_new_handle (signed_value);
907       break;
908 
909     case G_VARIANT_CLASS_DOUBLE:
910       double_value = g_ascii_strtod (st, &nptr);
911       conversion_error = errno != 0 || nptr == st;
912       variant = g_variant_new_double (double_value);
913       break;
914 
915     case G_VARIANT_CLASS_STRING:
916     case G_VARIANT_CLASS_OBJECT_PATH:
917     case G_VARIANT_CLASS_SIGNATURE:
918       variant = g_variant_new_string (st);
919       break;
920 
921     default:
922       g_assert_not_reached ();
923       break;
924     }
925 
926   if (conversion_error)
927     {
928       g_set_error_literal (error,
929                            G_IO_ERROR,
930                            G_IO_ERROR_INVALID_DATA,
931                            _("Invalid string value converting to GVariant"));
932       if (variant != NULL)
933         {
934           g_variant_unref (variant);
935           variant = NULL;
936         }
937     }
938 
939   return variant;
940 }
941 
942 static void
parse_dict_entry_signature(const gchar ** signature,gchar ** entry_signature,gchar ** key_signature,gchar ** value_signature)943 parse_dict_entry_signature (const gchar **signature,
944                             gchar       **entry_signature,
945                             gchar       **key_signature,
946                             gchar       **value_signature)
947 {
948   const gchar *tmp_sig;
949 
950   if (signature != NULL)
951     *entry_signature = signature_get_next_complete_type (signature);
952   else
953     *entry_signature = g_strdup ("{sv}");
954 
955   tmp_sig = (*entry_signature) + 1;
956   *key_signature = signature_get_next_complete_type (&tmp_sig);
957   *value_signature = signature_get_next_complete_type (&tmp_sig);
958 }
959 
960 static GVariant *
json_to_gvariant_dict_entry(JsonNode * json_node,const gchar ** signature,GError ** error)961 json_to_gvariant_dict_entry (JsonNode     *json_node,
962                              const gchar **signature,
963                              GError      **error)
964 {
965   GVariant *variant = NULL;
966   JsonObject *obj;
967 
968   gchar *entry_signature;
969   gchar *key_signature;
970   gchar *value_signature;
971   const gchar *tmp_signature;
972 
973   GQueue *members;
974   const gchar *json_member;
975   JsonNode *json_value;
976   GVariant *variant_member;
977   GVariant *variant_value;
978 
979   obj = json_node_get_object (json_node);
980 
981   if (json_object_get_size (obj) != 1)
982     {
983       g_set_error_literal (error,
984                            G_IO_ERROR,
985                            G_IO_ERROR_INVALID_DATA,
986                            _("A GVariant dictionary entry expects a JSON object with exactly one member"));
987       return NULL;
988     }
989 
990   parse_dict_entry_signature (signature,
991                               &entry_signature,
992                               &key_signature,
993                               &value_signature);
994 
995   members = json_object_get_members_internal (obj);
996   json_member = (const gchar *) members->head->data;
997   variant_member = gvariant_simple_from_string (json_member,
998                                                 key_signature[0],
999                                                 error);
1000   if (variant_member != NULL)
1001     {
1002       json_value = json_object_get_member (obj, json_member);
1003 
1004       tmp_signature = value_signature;
1005       variant_value = json_to_gvariant_recurse (json_value,
1006                                                 &tmp_signature,
1007                                                 error);
1008 
1009       if (variant_value != NULL)
1010         {
1011           GVariantBuilder *builder;
1012 
1013           builder = g_variant_builder_new (G_VARIANT_TYPE (entry_signature));
1014           g_variant_builder_add_value (builder, variant_member);
1015           g_variant_builder_add_value (builder, variant_value);
1016           variant = g_variant_builder_end (builder);
1017 
1018           g_variant_builder_unref (builder);
1019         }
1020     }
1021 
1022   g_free (value_signature);
1023   g_free (key_signature);
1024   g_free (entry_signature);
1025 
1026   /* compensate the (*signature)++ call at the end of 'recurse()' */
1027   if (signature)
1028     (*signature)--;
1029 
1030   return variant;
1031 }
1032 
1033 static GVariant *
json_to_gvariant_dictionary(JsonNode * json_node,const gchar ** signature,GError ** error)1034 json_to_gvariant_dictionary (JsonNode     *json_node,
1035                              const gchar **signature,
1036                              GError      **error)
1037 {
1038   GVariant *variant = NULL;
1039   JsonObject *obj;
1040   gboolean roll_back = FALSE;
1041 
1042   gchar *dict_signature;
1043   gchar *entry_signature;
1044   gchar *key_signature;
1045   gchar *value_signature;
1046   const gchar *tmp_signature;
1047 
1048   GVariantBuilder *builder;
1049   GQueue *members;
1050   GList *member;
1051 
1052   obj = json_node_get_object (json_node);
1053 
1054   if (signature != NULL)
1055     (*signature)++;
1056 
1057   parse_dict_entry_signature (signature,
1058                               &entry_signature,
1059                               &key_signature,
1060                               &value_signature);
1061 
1062   dict_signature = g_strdup_printf ("a%s", entry_signature);
1063 
1064   builder = g_variant_builder_new (G_VARIANT_TYPE (dict_signature));
1065 
1066   members = json_object_get_members_internal (obj);
1067 
1068   for (member = members->head; member != NULL; member = member->next)
1069     {
1070       const gchar *json_member;
1071       JsonNode *json_value;
1072       GVariant *variant_member;
1073       GVariant *variant_value;
1074 
1075       json_member = (const gchar *) member->data;
1076       variant_member = gvariant_simple_from_string (json_member,
1077                                                     key_signature[0],
1078                                                     error);
1079       if (variant_member == NULL)
1080         {
1081           roll_back = TRUE;
1082           break;
1083         }
1084 
1085       json_value = json_object_get_member (obj, json_member);
1086 
1087       tmp_signature = value_signature;
1088       variant_value = json_to_gvariant_recurse (json_value,
1089                                                 &tmp_signature,
1090                                                 error);
1091 
1092       if (variant_value != NULL)
1093         {
1094           g_variant_builder_open (builder, G_VARIANT_TYPE (entry_signature));
1095           g_variant_builder_add_value (builder, variant_member);
1096           g_variant_builder_add_value (builder, variant_value);
1097           g_variant_builder_close (builder);
1098         }
1099       else
1100         {
1101           roll_back = TRUE;
1102           break;
1103         }
1104     }
1105 
1106   if (! roll_back)
1107     variant = g_variant_builder_end (builder);
1108 
1109   g_variant_builder_unref (builder);
1110   g_free (value_signature);
1111   g_free (key_signature);
1112   g_free (entry_signature);
1113   g_free (dict_signature);
1114 
1115   /* compensate the (*signature)++ call at the end of 'recurse()' */
1116   if (signature != NULL)
1117     (*signature)--;
1118 
1119   return variant;
1120 }
1121 
1122 static GVariant *
json_to_gvariant_recurse(JsonNode * json_node,const gchar ** signature,GError ** error)1123 json_to_gvariant_recurse (JsonNode      *json_node,
1124                           const gchar  **signature,
1125                           GError       **error)
1126 {
1127   GVariant *variant = NULL;
1128   GVariantClass class;
1129 
1130   class = json_to_gvariant_get_next_class (json_node, signature);
1131 
1132   if (class == JSON_G_VARIANT_CLASS_DICTIONARY)
1133     {
1134       if (json_node_assert_type (json_node, JSON_NODE_OBJECT, 0, error))
1135         variant = json_to_gvariant_dictionary (json_node, signature, error);
1136 
1137       goto out;
1138     }
1139 
1140   if (JSON_NODE_TYPE (json_node) == JSON_NODE_VALUE &&
1141       json_node_get_value_type (json_node) == G_TYPE_STRING)
1142     {
1143       const gchar* str = json_node_get_string (json_node);
1144       switch (class)
1145         {
1146         case G_VARIANT_CLASS_BOOLEAN:
1147         case G_VARIANT_CLASS_BYTE:
1148         case G_VARIANT_CLASS_INT16:
1149         case G_VARIANT_CLASS_UINT16:
1150         case G_VARIANT_CLASS_INT32:
1151         case G_VARIANT_CLASS_UINT32:
1152         case G_VARIANT_CLASS_INT64:
1153         case G_VARIANT_CLASS_UINT64:
1154         case G_VARIANT_CLASS_HANDLE:
1155         case G_VARIANT_CLASS_DOUBLE:
1156         case G_VARIANT_CLASS_STRING:
1157           variant = gvariant_simple_from_string (str, class, error);
1158           goto out;
1159         default:
1160           break;
1161         }
1162     }
1163 
1164   switch (class)
1165     {
1166     case G_VARIANT_CLASS_BOOLEAN:
1167       if (json_node_assert_type (json_node, JSON_NODE_VALUE, G_TYPE_BOOLEAN, error))
1168         variant = g_variant_new_boolean (json_node_get_boolean (json_node));
1169       break;
1170 
1171     case G_VARIANT_CLASS_BYTE:
1172       if (json_node_assert_type (json_node, JSON_NODE_VALUE, G_TYPE_INT64, error))
1173         variant = g_variant_new_byte (json_node_get_int (json_node));
1174       break;
1175 
1176     case G_VARIANT_CLASS_INT16:
1177       if (json_node_assert_type (json_node, JSON_NODE_VALUE, G_TYPE_INT64, error))
1178         variant = g_variant_new_int16 (json_node_get_int (json_node));
1179       break;
1180 
1181     case G_VARIANT_CLASS_UINT16:
1182       if (json_node_assert_type (json_node, JSON_NODE_VALUE, G_TYPE_INT64, error))
1183         variant = g_variant_new_uint16 (json_node_get_int (json_node));
1184       break;
1185 
1186     case G_VARIANT_CLASS_INT32:
1187       if (json_node_assert_type (json_node, JSON_NODE_VALUE, G_TYPE_INT64, error))
1188         variant = g_variant_new_int32 (json_node_get_int (json_node));
1189       break;
1190 
1191     case G_VARIANT_CLASS_UINT32:
1192       if (json_node_assert_type (json_node, JSON_NODE_VALUE, G_TYPE_INT64, error))
1193         variant = g_variant_new_uint32 (json_node_get_int (json_node));
1194       break;
1195 
1196     case G_VARIANT_CLASS_INT64:
1197       if (json_node_assert_type (json_node, JSON_NODE_VALUE, G_TYPE_INT64, error))
1198         variant = g_variant_new_int64 (json_node_get_int (json_node));
1199       break;
1200 
1201     case G_VARIANT_CLASS_UINT64:
1202       if (json_node_assert_type (json_node, JSON_NODE_VALUE, G_TYPE_INT64, error))
1203         variant = g_variant_new_uint64 (json_node_get_int (json_node));
1204       break;
1205 
1206     case G_VARIANT_CLASS_HANDLE:
1207       if (json_node_assert_type (json_node, JSON_NODE_VALUE, G_TYPE_INT64, error))
1208         variant = g_variant_new_handle (json_node_get_int (json_node));
1209       break;
1210 
1211     case G_VARIANT_CLASS_DOUBLE:
1212       /* Doubles can look like ints to the json parser: when they don't have a dot */
1213       if (JSON_NODE_TYPE (json_node) == JSON_NODE_VALUE &&
1214           json_node_get_value_type (json_node) == G_TYPE_INT64)
1215         variant = g_variant_new_double (json_node_get_int (json_node));
1216       else if (json_node_assert_type (json_node, JSON_NODE_VALUE, G_TYPE_DOUBLE, error))
1217         variant = g_variant_new_double (json_node_get_double (json_node));
1218       break;
1219 
1220     case G_VARIANT_CLASS_STRING:
1221       if (json_node_assert_type (json_node, JSON_NODE_VALUE, G_TYPE_STRING, error))
1222         variant = g_variant_new_string (json_node_get_string (json_node));
1223       break;
1224 
1225     case G_VARIANT_CLASS_OBJECT_PATH:
1226       if (json_node_assert_type (json_node, JSON_NODE_VALUE, G_TYPE_STRING, error))
1227         variant = g_variant_new_object_path (json_node_get_string (json_node));
1228       break;
1229 
1230     case G_VARIANT_CLASS_SIGNATURE:
1231       if (json_node_assert_type (json_node, JSON_NODE_VALUE, G_TYPE_STRING, error))
1232         variant = g_variant_new_signature (json_node_get_string (json_node));
1233       break;
1234 
1235     case G_VARIANT_CLASS_VARIANT:
1236       variant = g_variant_new_variant (json_to_gvariant_recurse (json_node,
1237                                                                  NULL,
1238                                                                  error));
1239       break;
1240 
1241     case G_VARIANT_CLASS_MAYBE:
1242       variant = json_to_gvariant_maybe (json_node, signature, error);
1243       break;
1244 
1245     case G_VARIANT_CLASS_ARRAY:
1246       if (json_node_assert_type (json_node, JSON_NODE_ARRAY, 0, error))
1247         variant = json_to_gvariant_array (json_node, signature, error);
1248       break;
1249 
1250     case G_VARIANT_CLASS_TUPLE:
1251       if (json_node_assert_type (json_node, JSON_NODE_ARRAY, 0, error))
1252         variant = json_to_gvariant_tuple (json_node, signature, error);
1253       break;
1254 
1255     case G_VARIANT_CLASS_DICT_ENTRY:
1256       if (json_node_assert_type (json_node, JSON_NODE_OBJECT, 0, error))
1257         variant = json_to_gvariant_dict_entry (json_node, signature, error);
1258       break;
1259 
1260     default:
1261       g_set_error (error,
1262                    G_IO_ERROR,
1263                    G_IO_ERROR_INVALID_DATA,
1264                    _("GVariant class “%c” not supported"), class);
1265       break;
1266     }
1267 
1268 out:
1269   if (signature)
1270     (*signature)++;
1271 
1272   return variant;
1273 }
1274 
1275 /**
1276  * json_gvariant_deserialize:
1277  * @json_node: A #JsonNode to convert
1278  * @signature: (allow-none): A valid #GVariant type string, or %NULL
1279  * @error: A pointer to a #GError
1280  *
1281  * Converts a JSON data structure to a GVariant value using @signature to
1282  * resolve ambiguous data types. If no error occurs, the resulting #GVariant
1283  * is guaranteed to conform to @signature.
1284  *
1285  * If @signature is not %NULL but does not represent a valid GVariant type
1286  * string, %NULL is returned and error is set to %G_IO_ERROR_INVALID_ARGUMENT.
1287  * If a @signature is provided but the JSON structure cannot be mapped to it,
1288  * %NULL is returned and error is set to %G_IO_ERROR_INVALID_DATA.
1289  * If @signature is %NULL, the conversion is done based strictly on the types
1290  * in the JSON nodes.
1291  *
1292  * The returned variant has a floating reference that will need to be sunk
1293  * by the caller code.
1294  *
1295  * Return value: (transfer none): A newly created, floating #GVariant
1296  *   compliant with @signature, or %NULL on error
1297  *
1298  * Since: 0.14
1299  */
1300 GVariant *
json_gvariant_deserialize(JsonNode * json_node,const gchar * signature,GError ** error)1301 json_gvariant_deserialize (JsonNode     *json_node,
1302                            const gchar  *signature,
1303                            GError      **error)
1304 {
1305   g_return_val_if_fail (json_node != NULL, NULL);
1306 
1307   if (signature != NULL && ! g_variant_type_string_is_valid (signature))
1308     {
1309       g_set_error_literal (error,
1310                            G_IO_ERROR,
1311                            G_IO_ERROR_INVALID_ARGUMENT,
1312                            _("Invalid GVariant signature"));
1313       return NULL;
1314     }
1315 
1316   return json_to_gvariant_recurse (json_node, signature ? &signature : NULL, error);
1317 }
1318 
1319 /**
1320  * json_gvariant_deserialize_data:
1321  * @json: A JSON data string
1322  * @length: The length of @json, or -1 if %NULL-terminated
1323  * @signature: (allow-none): A valid #GVariant type string, or %NULL
1324  * @error: A pointer to a #GError
1325  *
1326  * Converts a JSON string to a #GVariant value. This method works exactly
1327  * like json_gvariant_deserialize(), but takes a JSON encoded string instead.
1328  * The string is first converted to a #JsonNode using #JsonParser, and then
1329  * json_gvariant_deserialize() is called.
1330  *
1331  * The returned variant has a floating reference that will need to be sunk
1332  * by the caller code.
1333  *
1334  * Returns: (transfer none): A newly created, floating #GVariant compliant
1335  *   with @signature, or %NULL on error
1336  *
1337  * Since: 0.14
1338  */
1339 GVariant *
json_gvariant_deserialize_data(const gchar * json,gssize length,const gchar * signature,GError ** error)1340 json_gvariant_deserialize_data (const gchar  *json,
1341                                 gssize        length,
1342                                 const gchar  *signature,
1343                                 GError      **error)
1344 {
1345   JsonParser *parser;
1346   GVariant *variant = NULL;
1347   JsonNode *root;
1348 
1349   parser = json_parser_new ();
1350 
1351   if (! json_parser_load_from_data (parser, json, length, error))
1352     return NULL;
1353 
1354   root = json_parser_get_root (parser);
1355   if (root == NULL)
1356     {
1357       g_set_error_literal (error,
1358                            G_IO_ERROR,
1359                            G_IO_ERROR_INVALID_DATA,
1360                            _("JSON data is empty"));
1361     }
1362   else
1363     {
1364       variant =
1365         json_gvariant_deserialize (json_parser_get_root (parser), signature, error);
1366     }
1367 
1368   g_object_unref (parser);
1369 
1370   return variant;
1371 }
1372