json_helper.c 22 KB

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