reduce loop counters to more practical levels
[oweals/gnunet.git] / src / json / json_helper.c
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/json_helper.c
18  * @brief functions to generate specifciations for JSON parsing
19  * @author Florian Dold
20  * @author Benedikt Mueller
21  * @author Christian Grothoff
22  */
23 #include "platform.h"
24 #include "gnunet_json_lib.h"
25
26
27 /**
28  * End of a parser specification.
29  */
30 struct GNUNET_JSON_Specification
31 GNUNET_JSON_spec_end ()
32 {
33   struct GNUNET_JSON_Specification ret = {
34     .parser = NULL,
35     .cleaner = NULL,
36     .cls = NULL
37   };
38   return ret;
39 }
40
41
42 /**
43  * Parse given JSON object to fixed size data
44  *
45  * @param cls closure, NULL
46  * @param root the json object representing data
47  * @param[out] spec where to write the data
48  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
49  */
50 static int
51 parse_fixed_data (void *cls,
52                   json_t *root,
53                   struct GNUNET_JSON_Specification *spec)
54 {
55   const char *enc;
56   unsigned int len;
57
58   if (NULL == (enc = json_string_value (root)))
59   {
60     GNUNET_break_op (0);
61     return GNUNET_SYSERR;
62   }
63   len = strlen (enc);
64   if (((len * 5) / 8) != spec->ptr_size)
65   {
66     GNUNET_break_op (0);
67     return GNUNET_SYSERR;
68   }
69   if (GNUNET_OK !=
70       GNUNET_STRINGS_string_to_data (enc,
71                                      len,
72                                      spec->ptr,
73                                      spec->ptr_size))
74   {
75     GNUNET_break_op (0);
76     return GNUNET_SYSERR;
77   }
78   return GNUNET_OK;
79 }
80
81
82 /**
83  * Variable size object (in network byte order, encoded using Crockford
84  * Base32hex encoding).
85  *
86  * @param name name of the JSON field
87  * @param[out] obj pointer where to write the data, must have @a size bytes
88  * @param size number of bytes expected in @a obj
89  */
90 struct GNUNET_JSON_Specification
91 GNUNET_JSON_spec_fixed (const char *name,
92                         void *obj,
93                         size_t size)
94 {
95   struct GNUNET_JSON_Specification ret = {
96     .parser = &parse_fixed_data,
97     .cleaner = NULL,
98     .cls = NULL,
99     .field = name,
100     .ptr = obj,
101     .ptr_size = size,
102     .size_ptr = NULL
103   };
104   return ret;
105 }
106
107
108 /**
109  * Parse given JSON object to variable size data
110  *
111  * @param cls closure, NULL
112  * @param root the json object representing data
113  * @param[out] spec where to write the data
114  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
115  */
116 static int
117 parse_variable_data (void *cls,
118                      json_t *root,
119                      struct GNUNET_JSON_Specification *spec)
120 {
121   const char *str;
122   size_t size;
123   void *data;
124   int res;
125
126   str = json_string_value (root);
127   if (NULL == str)
128   {
129     GNUNET_break_op (0);
130     return GNUNET_SYSERR;
131   }
132   size = (strlen (str) * 5) / 8;
133   if (size >= 1024)
134   {
135     GNUNET_break_op (0);
136     return GNUNET_SYSERR;
137   }
138   data = GNUNET_malloc (size);
139   res = GNUNET_STRINGS_string_to_data (str,
140                                        strlen (str),
141                                        data,
142                                        size);
143   if (GNUNET_OK != res)
144   {
145     GNUNET_break_op (0);
146     GNUNET_free (data);
147     return GNUNET_SYSERR;
148   }
149   *(void**) spec->ptr = data;
150   *spec->size_ptr = size;
151   return GNUNET_OK;
152 }
153
154
155 /**
156  * Cleanup data left from parsing variable size data
157  *
158  * @param cls closure, NULL
159  * @param[out] spec where to free the data
160  */
161 static void
162 clean_variable_data (void *cls,
163                      struct GNUNET_JSON_Specification *spec)
164 {
165   if (0 != *spec->size_ptr)
166   {
167     GNUNET_free (*(void **) spec->ptr);
168     *(void**) spec->ptr = NULL;
169     *spec->size_ptr = 0;
170   }
171 }
172
173
174 /**
175  * Variable size object (in network byte order, encoded using
176  * Crockford Base32hex encoding).
177  *
178  * @param name name of the JSON field
179  * @param[out] obj pointer where to write the data, will be allocated
180  * @param[out] size where to store the number of bytes allocated for @a obj
181  */
182 struct GNUNET_JSON_Specification
183 GNUNET_JSON_spec_varsize (const char *name,
184                           void **obj,
185                           size_t *size)
186 {
187   struct GNUNET_JSON_Specification ret = {
188     .parser = &parse_variable_data,
189     .cleaner = &clean_variable_data,
190     .cls = NULL,
191     .field = name,
192     .ptr = obj,
193     .ptr_size = 0,
194     .size_ptr = size
195   };
196   *obj = NULL;
197   *size = 0;
198   return ret;
199 }
200
201
202 /**
203  * Parse given JSON object to string.
204  *
205  * @param cls closure, NULL
206  * @param root the json object representing data
207  * @param[out] spec where to write the data
208  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
209  */
210 static int
211 parse_string (void *cls,
212               json_t *root,
213               struct GNUNET_JSON_Specification *spec)
214 {
215   const char *str;
216
217   str = json_string_value (root);
218   if (NULL == str)
219   {
220     GNUNET_break_op (0);
221     return GNUNET_SYSERR;
222   }
223   *(const char **) spec->ptr = str;
224   return GNUNET_OK;
225 }
226
227
228 /**
229  * The expected field stores a string.
230  *
231  * @param name name of the JSON field
232  * @param strptr where to store a pointer to the field
233  */
234 struct GNUNET_JSON_Specification
235 GNUNET_JSON_spec_string (const char *name,
236                          const char **strptr)
237 {
238   struct GNUNET_JSON_Specification ret = {
239     .parser = &parse_string,
240     .cleaner = NULL,
241     .cls = NULL,
242     .field = name,
243     .ptr = strptr,
244     .ptr_size = 0,
245     .size_ptr = NULL
246   };
247   *strptr = NULL;
248   return ret;
249 }
250
251
252 /**
253  * Parse given JSON object to a JSON object. (Yes, trivial.)
254  *
255  * @param cls closure, NULL
256  * @param root the json object representing data
257  * @param[out] spec where to write the data
258  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
259  */
260 static int
261 parse_object (void *cls,
262               json_t *root,
263               struct GNUNET_JSON_Specification *spec)
264 {
265   if (! (json_is_object (root) || json_is_array (root)) )
266   {
267     GNUNET_break_op (0);
268     return GNUNET_SYSERR;
269   }
270   json_incref (root);
271   *(json_t **) spec->ptr = root;
272   return GNUNET_OK;
273 }
274
275
276 /**
277  * Cleanup data left from parsing JSON object.
278  *
279  * @param cls closure, NULL
280  * @param[out] spec where to free the data
281  */
282 static void
283 clean_object (void *cls,
284               struct GNUNET_JSON_Specification *spec)
285 {
286   json_t **ptr = (json_t **) spec->ptr;
287
288   if (NULL != *ptr)
289   {
290     json_decref (*ptr);
291     *ptr = NULL;
292   }
293 }
294
295
296 /**
297  * JSON object.
298  *
299  * @param name name of the JSON field
300  * @param[out] jsonp where to store the JSON found under @a name
301  */
302 struct GNUNET_JSON_Specification
303 GNUNET_JSON_spec_json (const char *name,
304                        json_t **jsonp)
305 {
306   struct GNUNET_JSON_Specification ret = {
307     .parser = &parse_object,
308     .cleaner = &clean_object,
309     .cls = NULL,
310     .field = name,
311     .ptr = jsonp,
312     .ptr_size = 0,
313     .size_ptr = NULL
314   };
315   *jsonp = NULL;
316   return ret;
317 }
318
319
320 /**
321  * Parse given JSON object to a uint8_t.
322  *
323  * @param cls closure, NULL
324  * @param root the json object representing data
325  * @param[out] spec where to write the data
326  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
327  */
328 static int
329 parse_u8 (void *cls,
330           json_t *root,
331           struct GNUNET_JSON_Specification *spec)
332 {
333   json_int_t val;
334   uint8_t *up = spec->ptr;
335
336   if (! json_is_integer (root))
337   {
338     GNUNET_break_op (0);
339     return GNUNET_SYSERR;
340   }
341   val = json_integer_value (root);
342   if ( (0 > val) || (val > UINT8_MAX) )
343   {
344     GNUNET_break_op (0);
345     return GNUNET_SYSERR;
346   }
347   *up = (uint8_t) val;
348   return GNUNET_OK;
349 }
350
351
352 /**
353  * 8-bit integer.
354  *
355  * @param name name of the JSON field
356  * @param[out] u8 where to store the integer found under @a name
357  */
358 struct GNUNET_JSON_Specification
359 GNUNET_JSON_spec_uint8 (const char *name,
360                         uint8_t *u8)
361 {
362   struct GNUNET_JSON_Specification ret = {
363     .parser = &parse_u8,
364     .cleaner = NULL,
365     .cls = NULL,
366     .field = name,
367     .ptr = u8,
368     .ptr_size = sizeof (uint8_t),
369     .size_ptr = NULL
370   };
371   return ret;
372 }
373
374
375 /**
376  * Parse given JSON object to a uint16_t.
377  *
378  * @param cls closure, NULL
379  * @param root the json object representing data
380  * @param[out] spec where to write the data
381  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
382  */
383 static int
384 parse_u16 (void *cls,
385            json_t *root,
386            struct GNUNET_JSON_Specification *spec)
387 {
388   json_int_t val;
389   uint16_t *up = spec->ptr;
390
391   if (! json_is_integer (root))
392   {
393     GNUNET_break_op (0);
394     return GNUNET_SYSERR;
395   }
396   val = json_integer_value (root);
397   if ( (0 > val) || (val > UINT16_MAX) )
398   {
399     GNUNET_break_op (0);
400     return GNUNET_SYSERR;
401   }
402   *up = (uint16_t) val;
403   return GNUNET_OK;
404 }
405
406
407 /**
408  * 16-bit integer.
409  *
410  * @param name name of the JSON field
411  * @param[out] u16 where to store the integer found under @a name
412  */
413 struct GNUNET_JSON_Specification
414 GNUNET_JSON_spec_uint16 (const char *name,
415                          uint16_t *u16)
416 {
417   struct GNUNET_JSON_Specification ret = {
418     .parser = &parse_u16,
419     .cleaner = NULL,
420     .cls = NULL,
421     .field = name,
422     .ptr = u16,
423     .ptr_size = sizeof (uint16_t),
424     .size_ptr = NULL
425   };
426   return ret;
427 }
428
429
430 /**
431  * Parse given JSON object to a uint32_t.
432  *
433  * @param cls closure, NULL
434  * @param root the json object representing data
435  * @param[out] spec where to write the data
436  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
437  */
438 static int
439 parse_u32 (void *cls,
440            json_t *root,
441            struct GNUNET_JSON_Specification *spec)
442 {
443   json_int_t val;
444   uint32_t *up = spec->ptr;
445
446   if (! json_is_integer (root))
447   {
448     GNUNET_break_op (0);
449     return GNUNET_SYSERR;
450   }
451   val = json_integer_value (root);
452   if ( (0 > val) || (val > UINT32_MAX) )
453   {
454     GNUNET_break_op (0);
455     return GNUNET_SYSERR;
456   }
457   *up = (uint32_t) val;
458   return GNUNET_OK;
459 }
460
461
462 /**
463  * 32-bit integer.
464  *
465  * @param name name of the JSON field
466  * @param[out] u32 where to store the integer found under @a name
467  */
468 struct GNUNET_JSON_Specification
469 GNUNET_JSON_spec_uint32 (const char *name,
470                          uint32_t *u32)
471 {
472   struct GNUNET_JSON_Specification ret = {
473     .parser = &parse_u32,
474     .cleaner = NULL,
475     .cls = NULL,
476     .field = name,
477     .ptr = u32,
478     .ptr_size = sizeof (uint32_t),
479     .size_ptr = NULL
480   };
481   return ret;
482 }
483
484
485 /**
486  * Parse given JSON object to a uint8_t.
487  *
488  * @param cls closure, NULL
489  * @param root the json object representing data
490  * @param[out] spec where to write the data
491  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
492  */
493 static int
494 parse_u64 (void *cls,
495            json_t *root,
496            struct GNUNET_JSON_Specification *spec)
497 {
498   json_int_t val;
499   uint64_t *up = spec->ptr;
500
501   if (! json_is_integer (root))
502   {
503     GNUNET_break_op (0);
504     return GNUNET_SYSERR;
505   }
506   val = json_integer_value (root);
507   *up = (uint64_t) val;
508   return GNUNET_OK;
509 }
510
511
512 /**
513  * 64-bit integer.
514  *
515  * @param name name of the JSON field
516  * @param[out] u64 where to store the integer found under @a name
517  */
518 struct GNUNET_JSON_Specification
519 GNUNET_JSON_spec_uint64 (const char *name,
520                          uint64_t *u64)
521 {
522   struct GNUNET_JSON_Specification ret = {
523     .parser = &parse_u64,
524     .cleaner = NULL,
525     .cls = NULL,
526     .field = name,
527     .ptr = u64,
528     .ptr_size = sizeof (uint64_t),
529     .size_ptr = NULL
530   };
531   return ret;
532 }
533
534
535 /* ************ GNUnet-specific parser specifications ******************* */
536
537 /**
538  * Parse given JSON object to absolute time.
539  *
540  * @param cls closure, NULL
541  * @param root the json object representing data
542  * @param[out] spec where to write the data
543  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
544  */
545 static int
546 parse_abs_time (void *cls,
547                 json_t *root,
548                 struct GNUNET_JSON_Specification *spec)
549 {
550   struct GNUNET_TIME_Absolute *abs = spec->ptr;
551   const char *val;
552   unsigned long long int tval;
553
554   val = json_string_value (root);
555   if (NULL == val)
556   {
557     GNUNET_break_op (0);
558     return GNUNET_SYSERR;
559   }
560   if ( (0 == strcasecmp (val,
561                          "/forever/")) ||
562        (0 == strcasecmp (val,
563                          "/end of time/")) ||
564        (0 == strcasecmp (val,
565                          "/never/")) )
566   {
567     *abs = GNUNET_TIME_UNIT_FOREVER_ABS;
568     return GNUNET_OK;
569   }
570   if (1 != sscanf (val,
571                    "/Date(%llu)/",
572                    &tval))
573   {
574     GNUNET_break_op (0);
575     return GNUNET_SYSERR;
576   }
577   /* Time is in seconds in JSON, but in microseconds in GNUNET_TIME_Absolute */
578   abs->abs_value_us = tval * 1000LL * 1000LL;
579   if ( (abs->abs_value_us) / 1000LL / 1000LL != tval)
580   {
581     /* Integer overflow */
582     GNUNET_break_op (0);
583     return GNUNET_SYSERR;
584   }
585   return GNUNET_OK;
586 }
587
588
589 /**
590  * Absolute time.
591  *
592  * @param name name of the JSON field
593  * @param[out] at where to store the absolute time found under @a name
594  */
595 struct GNUNET_JSON_Specification
596 GNUNET_JSON_spec_absolute_time (const char *name,
597                                 struct GNUNET_TIME_Absolute *at)
598 {
599   struct GNUNET_JSON_Specification ret = {
600     .parser = &parse_abs_time,
601     .cleaner = NULL,
602     .cls = NULL,
603     .field = name,
604     .ptr = at,
605     .ptr_size = sizeof (uint64_t),
606     .size_ptr = NULL
607   };
608   return ret;
609 }
610
611
612 /**
613  * Parse given JSON object to absolute time.
614  *
615  * @param cls closure, NULL
616  * @param root the json object representing data
617  * @param[out] spec where to write the data
618  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
619  */
620 static int
621 parse_abs_time_nbo (void *cls,
622                     json_t *root,
623                     struct GNUNET_JSON_Specification *spec)
624 {
625   struct GNUNET_TIME_AbsoluteNBO *abs = spec->ptr;
626   const char *val;
627   unsigned long long int tval;
628   struct GNUNET_TIME_Absolute a;
629
630   val = json_string_value (root);
631   if (NULL == val)
632   {
633     GNUNET_break_op (0);
634     return GNUNET_SYSERR;
635   }
636   if ( (0 == strcasecmp (val,
637                          "/forever/")) ||
638        (0 == strcasecmp (val,
639                          "/end of time/")) ||
640        (0 == strcasecmp (val,
641                          "/never/")) )
642   {
643     *abs = GNUNET_TIME_absolute_hton (GNUNET_TIME_UNIT_FOREVER_ABS);
644     return GNUNET_OK;
645   }
646   if (1 != sscanf (val,
647                    "/Date(%llu)/",
648                    &tval))
649   {
650     GNUNET_break_op (0);
651     return GNUNET_SYSERR;
652   }
653   /* Time is in seconds in JSON, but in microseconds in GNUNET_TIME_Absolute */
654   a.abs_value_us = tval * 1000LL * 1000LL;
655   if ( (a.abs_value_us) / 1000LL / 1000LL != tval)
656   {
657     /* Integer overflow */
658     GNUNET_break_op (0);
659     return GNUNET_SYSERR;
660   }
661   *abs = GNUNET_TIME_absolute_hton (a);
662   return GNUNET_OK;
663 }
664
665
666 /**
667  * Absolute time in network byte order.
668  *
669  * @param name name of the JSON field
670  * @param[out] at where to store the absolute time found under @a name
671  */
672 struct GNUNET_JSON_Specification
673 GNUNET_JSON_spec_absolute_time_nbo (const char *name,
674                                     struct GNUNET_TIME_AbsoluteNBO *at)
675 {
676   struct GNUNET_JSON_Specification ret = {
677     .parser = &parse_abs_time_nbo,
678     .cleaner = NULL,
679     .cls = NULL,
680     .field = name,
681     .ptr = at,
682     .ptr_size = sizeof (uint64_t),
683     .size_ptr = NULL
684   };
685   return ret;
686 }
687
688
689 /**
690  * Parse given JSON object to relative time.
691  *
692  * @param cls closure, NULL
693  * @param root the json object representing data
694  * @param[out] spec where to write the data
695  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
696  */
697 static int
698 parse_rel_time (void *cls,
699                 json_t *root,
700                 struct GNUNET_JSON_Specification *spec)
701 {
702   struct GNUNET_TIME_Relative *rel = spec->ptr;
703   const char *val;
704   unsigned long long int tval;
705
706   val = json_string_value (root);
707   if (NULL == val)
708   {
709     GNUNET_break_op (0);
710     return GNUNET_SYSERR;
711   }
712   if ( (0 == strcasecmp (val,
713                          "/forever/")) )
714   {
715     *rel = GNUNET_TIME_UNIT_FOREVER_REL;
716     return GNUNET_OK;
717   }
718   if (1 != sscanf (val,
719                    "/Delay(%llu)/",
720                    &tval))
721   {
722     GNUNET_break_op (0);
723     return GNUNET_SYSERR;
724   }
725   /* Time is in seconds in JSON, but in microseconds in GNUNET_TIME_Relative */
726   rel->rel_value_us = tval * 1000LL * 1000LL;
727   if ( (rel->rel_value_us) / 1000LL / 1000LL != tval)
728   {
729     /* Integer overflow */
730     GNUNET_break_op (0);
731     return GNUNET_SYSERR;
732   }
733   return GNUNET_OK;
734 }
735
736
737 /**
738  * Relative time.
739  *
740  * @param name name of the JSON field
741  * @param[out] rt where to store the relative time found under @a name
742  */
743 struct GNUNET_JSON_Specification
744 GNUNET_JSON_spec_relative_time (const char *name,
745                                 struct GNUNET_TIME_Relative *rt)
746 {
747   struct GNUNET_JSON_Specification ret = {
748     .parser = &parse_rel_time,
749     .cleaner = NULL,
750     .cls = NULL,
751     .field = name,
752     .ptr = rt,
753     .ptr_size = sizeof (uint64_t),
754     .size_ptr = NULL
755   };
756   return ret;
757 }
758
759
760 /**
761  * Parse given JSON object to RSA public key.
762  *
763  * @param cls closure, NULL
764  * @param root the json object representing data
765  * @param[out] spec where to write the data
766  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
767  */
768 static int
769 parse_rsa_public_key (void *cls,
770                       json_t *root,
771                       struct GNUNET_JSON_Specification *spec)
772 {
773   struct GNUNET_CRYPTO_RsaPublicKey **pk = spec->ptr;
774   const char *enc;
775   char *buf;
776   size_t len;
777   size_t buf_len;
778
779   if (NULL == (enc = json_string_value (root)))
780   {
781     GNUNET_break_op (0);
782     return GNUNET_SYSERR;
783   }
784   len = strlen (enc);
785   buf_len =  (len * 5) / 8;
786   buf = GNUNET_malloc (buf_len);
787   if (GNUNET_OK !=
788       GNUNET_STRINGS_string_to_data (enc,
789                                      len,
790                                      buf,
791                                      buf_len))
792   {
793     GNUNET_break_op (0);
794     GNUNET_free (buf);
795     return GNUNET_SYSERR;
796   }
797   if (NULL == (*pk = GNUNET_CRYPTO_rsa_public_key_decode (buf,
798                                                           buf_len)))
799   {
800     GNUNET_break_op (0);
801     GNUNET_free (buf);
802     return GNUNET_SYSERR;
803   }
804   GNUNET_free (buf);
805   return GNUNET_OK;
806 }
807
808
809 /**
810  * Cleanup data left from parsing RSA public key.
811  *
812  * @param cls closure, NULL
813  * @param[out] spec where to free the data
814  */
815 static void
816 clean_rsa_public_key (void *cls,
817                       struct GNUNET_JSON_Specification *spec)
818 {
819   struct GNUNET_CRYPTO_RsaPublicKey **pk = spec->ptr;
820
821   if (NULL != *pk)
822   {
823     GNUNET_CRYPTO_rsa_public_key_free (*pk);
824     *pk = NULL;
825   }
826 }
827
828
829 /**
830  * Specification for parsing an RSA public key.
831  *
832  * @param name name of the JSON field
833  * @param pk where to store the RSA key found under @a name
834  */
835 struct GNUNET_JSON_Specification
836 GNUNET_JSON_spec_rsa_public_key (const char *name,
837                                  struct GNUNET_CRYPTO_RsaPublicKey **pk)
838 {
839   struct GNUNET_JSON_Specification ret = {
840     .parser = &parse_rsa_public_key,
841     .cleaner = &clean_rsa_public_key,
842     .cls = NULL,
843     .field = name,
844     .ptr = pk,
845     .ptr_size = 0,
846     .size_ptr = NULL
847   };
848   *pk = NULL;
849   return ret;
850 }
851
852
853 /**
854  * Parse given JSON object to RSA signature.
855  *
856  * @param cls closure, NULL
857  * @param root the json object representing data
858  * @param[out] spec where to write the data
859  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
860  */
861 static int
862 parse_rsa_signature (void *cls,
863                      json_t *root,
864                      struct GNUNET_JSON_Specification *spec)
865 {
866   struct GNUNET_CRYPTO_RsaSignature **sig = spec->ptr;
867   size_t size;
868   const char *str;
869   int res;
870   void *buf;
871
872   str = json_string_value (root);
873   if (NULL == str)
874   {
875     GNUNET_break_op (0);
876     return GNUNET_SYSERR;
877   }
878   size = (strlen (str) * 5) / 8;
879   buf = GNUNET_malloc (size);
880   res = GNUNET_STRINGS_string_to_data (str,
881                                        strlen (str),
882                                        buf,
883                                        size);
884   if (GNUNET_OK != res)
885   {
886     GNUNET_free (buf);
887     GNUNET_break_op (0);
888     return GNUNET_SYSERR;
889   }
890   if (NULL == (*sig = GNUNET_CRYPTO_rsa_signature_decode (buf,
891                                                           size)))
892   {
893     GNUNET_break_op (0);
894     GNUNET_free (buf);
895     return GNUNET_SYSERR;
896   }
897   GNUNET_free (buf);
898   return GNUNET_OK;
899 }
900
901
902 /**
903  * Cleanup data left from parsing RSA signature.
904  *
905  * @param cls closure, NULL
906  * @param[out] spec where to free the data
907  */
908 static void
909 clean_rsa_signature (void *cls,
910                      struct GNUNET_JSON_Specification *spec)
911 {
912   struct GNUNET_CRYPTO_RsaSignature  **sig = spec->ptr;
913
914   if (NULL != *sig)
915   {
916     GNUNET_CRYPTO_rsa_signature_free (*sig);
917     *sig = NULL;
918   }
919 }
920
921
922 /**
923  * Specification for parsing an RSA signature.
924  *
925  * @param name name of the JSON field
926  * @param sig where to store the RSA signature found under @a name
927  */
928 struct GNUNET_JSON_Specification
929 GNUNET_JSON_spec_rsa_signature (const char *name,
930                                 struct GNUNET_CRYPTO_RsaSignature **sig)
931 {
932   struct GNUNET_JSON_Specification ret = {
933     .parser = &parse_rsa_signature,
934     .cleaner = &clean_rsa_signature,
935     .cls = NULL,
936     .field = name,
937     .ptr = sig,
938     .ptr_size = 0,
939     .size_ptr = NULL
940   };
941   *sig = NULL;
942   return ret;
943 }
944
945
946 /**
947  * Parse given JSON object to an int as a boolean.
948  *
949  * @param cls closure, NULL
950  * @param root the json object representing data
951  * @param[out] spec where to write the data
952  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
953  */
954 static int
955 parse_boolean (void *cls,
956                json_t *root,
957                struct GNUNET_JSON_Specification *spec)
958 {
959   int *bp = spec->ptr;
960
961   if (! json_is_boolean (root))
962   {
963     GNUNET_break_op (0);
964     return GNUNET_SYSERR;
965   }
966   *bp = json_boolean_value (root) ? GNUNET_YES : GNUNET_NO;
967   return GNUNET_OK;
968 }
969
970
971 /**
972  * Boolean (true mapped to GNUNET_YES, false mapped to GNUNET_NO).
973  *
974  * @param name name of the JSON field
975  * @param[out] boolean where to store the boolean found under @a name
976  */
977 struct GNUNET_JSON_Specification
978 GNUNET_JSON_spec_boolean (const char *name,
979                           int *boolean)
980 {
981   struct GNUNET_JSON_Specification ret = {
982     .parser = &parse_boolean,
983     .cleaner = NULL,
984     .cls = NULL,
985     .field = name,
986     .ptr = boolean,
987     .ptr_size = sizeof (int),
988     .size_ptr = NULL
989   };
990   return ret;
991 }
992
993
994 /* end of json_helper.c */