1 /*
2 * Hangouts Plugin for libpurple/Pidgin
3 * Copyright (c) 2015-2016 Eion Robb, Mike Ruprecht
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include "hangouts_json.h"
20
21 #include <debug.h>
22
23 gchar *
json_encode(JsonNode * node,gsize * len)24 json_encode(JsonNode *node, gsize *len)
25 {
26 gchar *data;
27 JsonGenerator *generator = json_generator_new();
28
29 json_generator_set_root(generator, node);
30
31 data = json_generator_to_data(generator, len);
32
33 g_object_unref(generator);
34
35 return data;
36 }
37
38 gchar *
json_pretty_encode(JsonNode * node,gsize * len)39 json_pretty_encode(JsonNode *node, gsize *len)
40 {
41 gchar *data;
42 JsonGenerator *generator = json_generator_new();
43
44 g_object_set(generator, "pretty", TRUE, NULL);
45 g_object_set(generator, "indent-char", '\t', NULL);
46 g_object_set(generator, "indent", 1, NULL);
47
48 json_generator_set_root(generator, node);
49
50 data = json_generator_to_data(generator, len);
51
52 g_object_unref(generator);
53
54 return data;
55 }
56
57 gchar *
json_encode_array(JsonArray * array,gsize * len)58 json_encode_array(JsonArray *array, gsize *len)
59 {
60 JsonNode *node = json_node_new(JSON_NODE_ARRAY);
61 gchar *json;
62
63 json_node_set_array(node, array);
64 json = json_encode(node, len);
65
66 json_node_free(node);
67 return json;
68 }
69
70 gchar *
json_encode_object(JsonObject * object,gsize * len)71 json_encode_object(JsonObject *object, gsize *len)
72 {
73 JsonNode *node = json_node_new(JSON_NODE_OBJECT);
74 gchar *json;
75
76 json_node_set_object(node, object);
77 json = json_encode(node, len);
78
79 json_node_free(node);
80 return json;
81 }
82
83 JsonNode *
json_decode(const gchar * data,gssize len)84 json_decode(const gchar *data, gssize len)
85 {
86 JsonParser *parser = json_parser_new();
87 JsonNode *root = NULL;
88
89 if (!data || !json_parser_load_from_data(parser, data, len, NULL))
90 {
91 purple_debug_error("hangouts", "Error parsing JSON: %s\n", data);
92 } else {
93 root = json_parser_get_root(parser);
94 if (root != NULL) {
95 root = json_node_copy(root);
96 }
97 }
98 g_object_unref(parser);
99
100 return root;
101 }
102
103 JsonArray *
json_decode_array(const gchar * data,gssize len)104 json_decode_array(const gchar *data, gssize len)
105 {
106 JsonNode *root = json_decode(data, len);
107 JsonArray *ret;
108
109 g_return_val_if_fail(root, NULL);
110
111 if (!JSON_NODE_HOLDS_ARRAY(root)) {
112 // That ain't my belly button!
113 json_node_free(root);
114 return NULL;
115 }
116
117 ret = json_node_dup_array(root);
118
119 json_node_free(root);
120
121 return ret;
122 }
123
124 JsonObject *
json_decode_object(const gchar * data,gssize len)125 json_decode_object(const gchar *data, gssize len)
126 {
127 JsonNode *root = json_decode(data, len);
128 JsonObject *ret;
129
130 g_return_val_if_fail(root, NULL);
131
132 if (!JSON_NODE_HOLDS_OBJECT(root)) {
133 // That ain't my thumb, neither!
134 json_node_free(root);
135 return NULL;
136 }
137
138 ret = json_node_dup_object(root);
139
140 json_node_free(root);
141
142 return ret;
143 }
144
145
146 JsonNode *
hangouts_json_path_query(JsonNode * root,const gchar * expr,GError ** error)147 hangouts_json_path_query(JsonNode *root, const gchar *expr, GError **error)
148 {
149 JsonNode *ret;
150 JsonNode *node;
151 JsonArray *result;
152
153 if (g_str_equal(expr, "$")) {
154 return root;
155 }
156
157 node = json_path_query(expr, root, error);
158
159 if (error != NULL)
160 {
161 json_node_free(node);
162 return NULL;
163 }
164
165 result = json_node_get_array(node);
166 if (json_array_get_length(result) == 0)
167 {
168 json_node_free(node);
169 return NULL;
170 }
171 ret = json_array_dup_element(result, 0);
172 json_node_free(node);
173 return ret;
174
175 }
176
177 gchar *
hangouts_json_path_query_string(JsonNode * root,const gchar * expr,GError ** error)178 hangouts_json_path_query_string(JsonNode *root, const gchar *expr, GError **error)
179 {
180 gchar *ret;
181 JsonNode *rslt;
182
183 rslt = hangouts_json_path_query(root, expr, error);
184
185 if (rslt == NULL)
186 {
187 return NULL;
188 }
189
190 ret = g_strdup(json_node_get_string(rslt));
191 json_node_free(rslt);
192 return ret;
193 }
194
195 gint64
hangouts_json_path_query_int(JsonNode * root,const gchar * expr,GError ** error)196 hangouts_json_path_query_int(JsonNode *root, const gchar *expr, GError **error)
197 {
198 gint64 ret;
199 JsonNode *rslt;
200
201 rslt = hangouts_json_path_query(root, expr, error);
202
203 if (rslt == NULL)
204 {
205 return 0;
206 }
207
208 ret = json_node_get_int(rslt);
209 json_node_free(rslt);
210 return ret;
211 }
212
213 gchar *
hangouts_json_tidy_blank_arrays(const gchar * json)214 hangouts_json_tidy_blank_arrays(const gchar *json)
215 {
216 static GRegex *tidy_regex = NULL;
217
218 if (tidy_regex == NULL) {
219 tidy_regex = g_regex_new("\"(\\\\\"|.)*?\"(*SKIP)(*FAIL)|\\[\\](*SKIP)(*FAIL)|(?<=,|\\[)\\s*(?=,|\\])", G_REGEX_OPTIMIZE, 0, NULL);
220 }
221
222 return g_regex_replace_literal(tidy_regex, json, -1, 0, "null", 0, NULL);
223 }
224
225