aboutsummaryrefslogtreecommitdiff
path: root/src/jsonapi
diff options
context:
space:
mode:
authorMartin Schanzenbach <mschanzenbach@posteo.de>2016-05-02 16:32:36 +0000
committerMartin Schanzenbach <mschanzenbach@posteo.de>2016-05-02 16:32:36 +0000
commitbee208bcd6803829aa26c55a4c8e176a5f2c815f (patch)
tree6974bc9e94a1ec938b5376d2631233d2e75baf7d /src/jsonapi
parentfc9b25be2dbe5392501dbc0b6659c1aa50809bc2 (diff)
downloadgnunet-bee208bcd6803829aa26c55a4c8e176a5f2c815f.tar.gz
gnunet-bee208bcd6803829aa26c55a4c8e176a5f2c815f.zip
- Refactor jsonapi into separate module
Diffstat (limited to 'src/jsonapi')
-rw-r--r--src/jsonapi/Makefile.am34
-rw-r--r--src/jsonapi/jsonapi.c478
2 files changed, 512 insertions, 0 deletions
diff --git a/src/jsonapi/Makefile.am b/src/jsonapi/Makefile.am
new file mode 100644
index 000000000..1d3fcc760
--- /dev/null
+++ b/src/jsonapi/Makefile.am
@@ -0,0 +1,34 @@
1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3
4if USE_COVERAGE
5 AM_CFLAGS = --coverage -O0
6 XLIB = -lgcov
7endif
8
9lib_LTLIBRARIES = \
10 libgnunetjsonapi.la
11
12libgnunetjsonapi_la_LDFLAGS = \
13 -version-info 0:0:0 \
14 -no-undefined
15libgnunetjsonapi_la_SOURCES = \
16 jsonapi.c
17libgnunetjsonapi_la_LIBADD = \
18 $(top_builddir)/src/util/libgnunetutil.la \
19 $(top_builddir)/src/json/libgnunetjson.la \
20 -ljansson \
21 $(XLIB)
22
23#check_PROGRAMS = \
24# test_json
25
26#TESTS = \
27# $(check_PROGRAMS)
28
29#test_json_SOURCES = \
30# test_json.c
31#test_json_LDADD = \
32# libgnunetjson.la \
33# $(top_builddir)/src/util/libgnunetutil.la \
34# -ljansson
diff --git a/src/jsonapi/jsonapi.c b/src/jsonapi/jsonapi.c
new file mode 100644
index 000000000..7bc4c05e5
--- /dev/null
+++ b/src/jsonapi/jsonapi.c
@@ -0,0 +1,478 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2014, 2015, 2016 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License along with
14 GNUnet; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
15*/
16/**
17 * @file json/jsonapi.c
18 * @brief functions to generate specifciations for JSONAPI parsing
19 * @author Martin Schanzenbach
20 */
21#include "platform.h"
22#include "gnunet_json_lib.h"
23
24#define GNUNET_JSONAPI_JSONAPI_KEY_DATA "data"
25
26#define GNUNET_JSONAPI_JSONAPI_KEY_ID "id"
27
28#define GNUNET_JSONAPI_JSONAPI_KEY_TYPE "type"
29
30struct GNUNET_JSONAPI_Resource
31{
32 /**
33 * DLL
34 */
35 struct GNUNET_JSONAPI_Resource *next;
36
37 /**
38 * DLL
39 */
40 struct GNUNET_JSONAPI_Resource *prev;
41
42 /**
43 * Resource content
44 */
45 json_t *res_obj;
46};
47
48
49struct GNUNET_JSONAPI_Object
50{
51 /**
52 * DLL Resource
53 */
54 struct GNUNET_JSONAPI_Resource *res_list_head;
55
56 /**
57 * DLL Resource
58 */
59 struct GNUNET_JSONAPI_Resource *res_list_tail;
60
61 /**
62 * num resources
63 */
64 int res_count;
65};
66
67
68/**
69 * JSON API
70 */
71
72
73/**
74 * Create a JSON API resource
75 *
76 * @param type the JSON API resource type
77 * @param id the JSON API resource id
78 * @return a new JSON API resource or NULL on error.
79 */
80struct GNUNET_JSONAPI_Resource*
81GNUNET_JSONAPI_resource_new (const char *type, const char *id)
82{
83 struct GNUNET_JSONAPI_Resource *res;
84
85 if ( (NULL == type) || (0 == strlen (type)) )
86 return NULL;
87 if ( (NULL == id) || (0 == strlen (id)) )
88 return NULL;
89
90 res = GNUNET_new (struct GNUNET_JSONAPI_Resource);
91 res->prev = NULL;
92 res->next = NULL;
93
94 res->res_obj = json_object ();
95
96 json_object_set_new (res->res_obj, GNUNET_JSONAPI_JSONAPI_KEY_ID, json_string (id));
97 json_object_set_new (res->res_obj, GNUNET_JSONAPI_JSONAPI_KEY_TYPE, json_string (type));
98
99 return res;
100}
101
102
103
104/**
105 * Add a JSON API attribute
106 *
107 * @param res the JSON resource
108 * @param key the key for the attribute
109 * @param json the json_t attribute to add
110 * @return #GNUNET_OK if added successfully
111 * #GNUNET_SYSERR if not
112 */
113int
114GNUNET_JSONAPI_resource_add_attr (const struct GNUNET_JSONAPI_Resource *resource,
115 const char* key,
116 json_t *json)
117{
118 if ( (NULL == resource) ||
119 (NULL == key) ||
120 (NULL == json) )
121 return GNUNET_SYSERR;
122 json_object_set (resource->res_obj, key, json);
123 return GNUNET_OK;
124}
125
126/**
127 * Read a JSON API attribute
128 *
129 * @param res the JSON resource
130 * @param key the key for the attribute
131 * @return the json_t object
132 */
133json_t*
134GNUNET_JSONAPI_resource_read_attr (const struct GNUNET_JSONAPI_Resource *resource,
135 const char* key)
136{
137 if ( (NULL == resource) ||
138 (NULL == key))
139 return NULL;
140 return json_object_get (resource->res_obj, key);
141}
142
143int
144check_resource_attr_str (const struct GNUNET_JSONAPI_Resource *resource,
145 const char* key,
146 const char* attr)
147{
148 json_t *value;
149 if ( (NULL == resource) ||
150 (NULL == key) ||
151 (NULL == attr))
152 return GNUNET_NO;
153 value = json_object_get (resource->res_obj, key);
154 if (NULL == value)
155 return GNUNET_NO;
156 if (!json_is_string (value) ||
157 (0 != strcmp (attr, json_string_value(value))))
158 {
159 return GNUNET_NO;
160 }
161 return GNUNET_YES;
162}
163
164/**
165 * Check a JSON API resource id
166 *
167 * @param res the JSON resource
168 * @param id the expected id
169 * @return GNUNET_YES if id matches
170 */
171int
172GNUNET_JSONAPI_resource_check_id (const struct GNUNET_JSONAPI_Resource *resource,
173 const char* id)
174{
175 return check_resource_attr_str (resource, GNUNET_JSONAPI_JSONAPI_KEY_ID, id);
176}
177
178/**
179 * Check a JSON API resource id
180 *
181 * @param res the JSON resource
182 * @return the resource id
183 */
184json_t*
185GNUNET_JSONAPI_resource_get_id (const struct GNUNET_JSONAPI_Resource *resource)
186{
187 return GNUNET_JSONAPI_resource_read_attr (resource, GNUNET_JSONAPI_JSONAPI_KEY_ID);
188}
189
190/**
191 * Check a JSON API resource type
192 *
193 * @param res the JSON resource
194 * @param type the expected type
195 * @return GNUNET_YES if id matches
196 */
197int
198GNUNET_JSONAPI_resource_check_type (const struct GNUNET_JSONAPI_Resource *resource,
199 const char* type)
200{
201 return check_resource_attr_str (resource, GNUNET_JSONAPI_JSONAPI_KEY_TYPE, type);
202}
203
204/**
205 * Get a JSON API object resource count
206 *
207 * @param resp the JSON API object
208 * @return the number of resources
209 */
210int
211GNUNET_JSONAPI_object_resource_count (struct GNUNET_JSONAPI_Object *resp)
212{
213 return resp->res_count;
214}
215
216/**
217 * Get a JSON API object resource by index
218 *
219 * @param resp the JSON API object
220 * @param num the number of the resource
221 * @return the resource
222 */
223struct GNUNET_JSONAPI_Resource*
224GNUNET_JSONAPI_object_get_resource (struct GNUNET_JSONAPI_Object *resp,
225 int num)
226{
227 struct GNUNET_JSONAPI_Resource *res;
228 int i;
229
230 if ((0 == resp->res_count) ||
231 (num >= resp->res_count))
232 return NULL;
233 res = resp->res_list_head;
234 for (i = 0; i < num; i++)
235 {
236 res = res->next;
237 }
238 return res;
239}
240
241/**
242 * Delete a JSON API resource
243 *
244 * @param res the JSON resource
245 * @param result Pointer where the resource should be stored
246 */
247void
248GNUNET_JSONAPI_resource_delete (struct GNUNET_JSONAPI_Resource *resource)
249{
250 json_decref (resource->res_obj);
251 GNUNET_free (resource);
252 resource = NULL;
253}
254
255/**
256 * Delete a JSON API primary data
257 *
258 * @param type the JSON API resource type
259 * @param id the JSON API resource id
260 * @return a new JSON API resource or NULL on error.
261 */
262void
263GNUNET_JSONAPI_object_delete (struct GNUNET_JSONAPI_Object *resp)
264{
265 struct GNUNET_JSONAPI_Resource *res;
266 struct GNUNET_JSONAPI_Resource *res_next;
267
268 for (res = resp->res_list_head;
269 res != NULL;)
270 {
271 res_next = res->next;
272 GNUNET_CONTAINER_DLL_remove (resp->res_list_head,
273 resp->res_list_tail,
274 res);
275 GNUNET_JSONAPI_resource_delete (res);
276 res = res_next;
277 }
278 GNUNET_free (resp);
279 resp = NULL;
280}
281
282/**
283 * Create a JSON API primary data
284 *
285 * @return a new JSON API resource or NULL on error.
286 */
287struct GNUNET_JSONAPI_Object*
288GNUNET_JSONAPI_jsonapi_object_new ()
289{
290 struct GNUNET_JSONAPI_Object *result;
291
292 result = GNUNET_new (struct GNUNET_JSONAPI_Object);
293 result->res_count = 0;
294 return result;
295}
296
297/**
298 * Add a JSON API object to primary data
299 *
300 * @param data The JSON API data to add to
301 * @param res the JSON API resource to add
302 * @return the new number of resources
303 */
304void
305GNUNET_JSONAPI_object_resource_add (struct GNUNET_JSONAPI_Object *resp,
306 struct GNUNET_JSONAPI_Resource *res)
307{
308 GNUNET_CONTAINER_DLL_insert (resp->res_list_head,
309 resp->res_list_tail,
310 res);
311
312 resp->res_count++;
313}
314
315static void
316add_json_resource (struct GNUNET_JSONAPI_Object *obj,
317 const json_t *res_json)
318{
319 struct GNUNET_JSONAPI_Resource *res;
320 const char *type_json;
321
322 struct GNUNET_JSON_Specification dspec[] = {
323 GNUNET_JSON_spec_string (GNUNET_JSONAPI_JSONAPI_KEY_TYPE, &type_json),
324 GNUNET_JSON_spec_end()
325 };
326
327 GNUNET_assert (GNUNET_OK ==
328 GNUNET_JSON_parse (res_json, dspec,
329 NULL, NULL));
330 GNUNET_JSON_parse_free (dspec);
331 res = GNUNET_new (struct GNUNET_JSONAPI_Resource);
332 res->next = NULL;
333 res->prev = NULL;
334 res->res_obj = json_deep_copy (res_json);
335 GNUNET_JSONAPI_object_resource_add (obj, res);
336}
337
338/**
339 * Parse given JSON object to RSA public key.
340 *
341 * @param cls closure, NULL
342 * @param root the json object representing data
343 * @param[out] spec where to write the data
344 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
345 */
346static int
347parse_jsonapiobject (void *cls,
348 json_t *root,
349 struct GNUNET_JSON_Specification *spec)
350{
351 struct GNUNET_JSONAPI_Object *result;
352 json_t *data_json;
353 int res_count = 0;
354 int i;
355
356 struct GNUNET_JSON_Specification jsonapispec[] = {
357 GNUNET_JSON_spec_json (GNUNET_JSONAPI_JSONAPI_KEY_DATA, &data_json),
358 GNUNET_JSON_spec_end()
359 };
360 if (GNUNET_OK !=
361 GNUNET_JSON_parse (root, jsonapispec,
362 NULL, NULL) || (NULL == data_json))
363 {
364 return GNUNET_SYSERR;
365 }
366
367 result = GNUNET_new (struct GNUNET_JSONAPI_Object);
368 result->res_count = 0;
369 if (json_is_object (data_json))
370 add_json_resource (result, data_json);
371 else if (json_is_array (data_json))
372 {
373 res_count = json_array_size (data_json);
374 for (i = 0; i < res_count; i++)
375 add_json_resource (result, json_array_get (data_json, i));
376 }
377 if (0 == result->res_count)
378 {
379 GNUNET_free (result);
380 GNUNET_JSON_parse_free (jsonapispec);
381 return GNUNET_SYSERR;
382 }
383 *(struct GNUNET_JSONAPI_Object **) spec->ptr = result;
384 GNUNET_JSON_parse_free (jsonapispec);
385 return GNUNET_OK;
386}
387
388
389/**
390 * Cleanup data left from parsing RSA public key.
391 *
392 * @param cls closure, NULL
393 * @param[out] spec where to free the data
394 */
395static void
396clean_jsonapiobject (void *cls,
397 struct GNUNET_JSON_Specification *spec)
398{
399 struct GNUNET_JSONAPI_Object **jsonapi_obj;
400 jsonapi_obj = (struct GNUNET_JSONAPI_Object **) spec->ptr;
401 if (NULL != *jsonapi_obj)
402 {
403 GNUNET_JSONAPI_object_delete (*jsonapi_obj);
404 *jsonapi_obj = NULL;
405 }
406}
407
408/**
409 * Add a JSON API resource to primary data
410 *
411 * @param data The JSON API data to add to
412 * @param res the JSON API resource to add
413 * @return the new number of resources
414 */
415void
416GNUNET_JSONAPI_data_resource_remove (struct GNUNET_JSONAPI_Object *resp,
417 struct GNUNET_JSONAPI_Resource *res)
418{
419 GNUNET_CONTAINER_DLL_remove (resp->res_list_head,
420 resp->res_list_tail,
421 res);
422 resp->res_count--;
423}
424
425/**
426 * String serialze jsonapi primary data
427 *
428 * @param data the JSON API primary data
429 * @param result where to store the result
430 * @return GNUNET_SYSERR on error else GNUNET_OK
431 */
432int
433GNUNET_JSONAPI_data_serialize (const struct GNUNET_JSONAPI_Object *resp,
434 char **result)
435{
436 struct GNUNET_JSONAPI_Resource *res;
437 json_t *root_json;
438 json_t *res_arr;
439
440 if ((NULL == resp))
441 return GNUNET_SYSERR;
442
443 root_json = json_object ();
444 res_arr = json_array ();
445 for (res = resp->res_list_head;
446 res != NULL;
447 res = res->next)
448 {
449 json_array_append (res_arr, res->res_obj);
450 }
451 json_object_set (root_json, GNUNET_JSONAPI_JSONAPI_KEY_DATA, res_arr);
452 *result = json_dumps (root_json, JSON_INDENT(2));
453 json_decref (root_json);
454 json_decref (res_arr);
455 return GNUNET_OK;
456}
457
458/**
459 * JSON object.
460 *
461 * @param name name of the JSON field
462 * @param[out] jsonp where to store the JSON found under @a name
463 */
464struct GNUNET_JSON_Specification
465GNUNET_JSON_spec_jsonapi (struct GNUNET_JSONAPI_Object **jsonapi_object)
466{
467 struct GNUNET_JSON_Specification ret = {
468 .parser = &parse_jsonapiobject,
469 .cleaner = &clean_jsonapiobject,
470 .cls = NULL,
471 .field = NULL,
472 .ptr = jsonapi_object,
473 .ptr_size = 0,
474 .size_ptr = NULL
475 };
476 *jsonapi_object = NULL;
477 return ret;
478}