aboutsummaryrefslogtreecommitdiff
path: root/src/util/json.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/json.c')
-rw-r--r--src/util/json.c294
1 files changed, 284 insertions, 10 deletions
diff --git a/src/util/json.c b/src/util/json.c
index 55717c5e0..02591d7bf 100644
--- a/src/util/json.c
+++ b/src/util/json.c
@@ -32,19 +32,11 @@
32 } while (0) 32 } while (0)
33 33
34/** 34/**
35 * Print JSON parsing related error information
36 */
37#define WARN_JSON(error) \
38 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, \
39 "JSON parsing failed at %s:%u: %s (%s)", \
40 __FILE__, __LINE__, error.text, error.source)
41
42/**
43 * Shorthand for JSON parsing related exit jumps. 35 * Shorthand for JSON parsing related exit jumps.
44 */ 36 */
45#define UNPACK_EXITIF(cond) \ 37#define UNPACK_EXITIF(cond) \
46 do { \ 38 do { \
47 if (cond) { WARN_JSON(error); goto EXITIF_exit; } \ 39 if (cond) { TALER_JSON_warn (error); goto EXITIF_exit; } \
48 } while (0) 40 } while (0)
49 41
50 42
@@ -221,4 +213,286 @@ TALER_JSON_to_data (json_t *json,
221 return GNUNET_SYSERR; 213 return GNUNET_SYSERR;
222} 214}
223 215
216/* Taken from GNU gettext */
217struct table_entry
218{
219 const char *code;
220 const char *english;
221};
222/* Keep the following table in sync with gettext.
223 WARNING: the entries should stay sorted according to the code */
224static const struct table_entry country_table[] =
225 {
226 { "AE", "U.A.E." },
227 { "AF", "Afghanistan" },
228 { "AL", "Albania" },
229 { "AM", "Armenia" },
230 { "AN", "Netherlands Antilles" },
231 { "AR", "Argentina" },
232 { "AT", "Austria" },
233 { "AU", "Australia" },
234 { "AZ", "Azerbaijan" },
235 { "BA", "Bosnia and Herzegovina" },
236 { "BD", "Bangladesh" },
237 { "BE", "Belgium" },
238 { "BG", "Bulgaria" },
239 { "BH", "Bahrain" },
240 { "BN", "Brunei Darussalam" },
241 { "BO", "Bolivia" },
242 { "BR", "Brazil" },
243 { "BT", "Bhutan" },
244 { "BY", "Belarus" },
245 { "BZ", "Belize" },
246 { "CA", "Canada" },
247 { "CG", "Congo" },
248 { "CH", "Switzerland" },
249 { "CI", "Cote d'Ivoire" },
250 { "CL", "Chile" },
251 { "CM", "Cameroon" },
252 { "CN", "People's Republic of China" },
253 { "CO", "Colombia" },
254 { "CR", "Costa Rica" },
255 { "CS", "Serbia and Montenegro" },
256 { "CZ", "Czech Republic" },
257 { "DE", "Germany" },
258 { "DK", "Denmark" },
259 { "DO", "Dominican Republic" },
260 { "DZ", "Algeria" },
261 { "EC", "Ecuador" },
262 { "EE", "Estonia" },
263 { "EG", "Egypt" },
264 { "ER", "Eritrea" },
265 { "ES", "Spain" },
266 { "ET", "Ethiopia" },
267 { "FI", "Finland" },
268 { "FO", "Faroe Islands" },
269 { "FR", "France" },
270 { "GB", "United Kingdom" },
271 { "GD", "Caribbean" },
272 { "GE", "Georgia" },
273 { "GL", "Greenland" },
274 { "GR", "Greece" },
275 { "GT", "Guatemala" },
276 { "HK", "Hong Kong" },
277 { "HK", "Hong Kong S.A.R." },
278 { "HN", "Honduras" },
279 { "HR", "Croatia" },
280 { "HT", "Haiti" },
281 { "HU", "Hungary" },
282 { "ID", "Indonesia" },
283 { "IE", "Ireland" },
284 { "IL", "Israel" },
285 { "IN", "India" },
286 { "IQ", "Iraq" },
287 { "IR", "Iran" },
288 { "IS", "Iceland" },
289 { "IT", "Italy" },
290 { "JM", "Jamaica" },
291 { "JO", "Jordan" },
292 { "JP", "Japan" },
293 { "KE", "Kenya" },
294 { "KG", "Kyrgyzstan" },
295 { "KH", "Cambodia" },
296 { "KR", "South Korea" },
297 { "KW", "Kuwait" },
298 { "KZ", "Kazakhstan" },
299 { "LA", "Laos" },
300 { "LB", "Lebanon" },
301 { "LI", "Liechtenstein" },
302 { "LK", "Sri Lanka" },
303 { "LT", "Lithuania" },
304 { "LU", "Luxembourg" },
305 { "LV", "Latvia" },
306 { "LY", "Libya" },
307 { "MA", "Morocco" },
308 { "MC", "Principality of Monaco" },
309 { "MD", "Moldava" },
310 { "MD", "Moldova" },
311 { "ME", "Montenegro" },
312 { "MK", "Former Yugoslav Republic of Macedonia" },
313 { "ML", "Mali" },
314 { "MM", "Myanmar" },
315 { "MN", "Mongolia" },
316 { "MO", "Macau S.A.R." },
317 { "MT", "Malta" },
318 { "MV", "Maldives" },
319 { "MX", "Mexico" },
320 { "MY", "Malaysia" },
321 { "NG", "Nigeria" },
322 { "NI", "Nicaragua" },
323 { "NL", "Netherlands" },
324 { "NO", "Norway" },
325 { "NP", "Nepal" },
326 { "NZ", "New Zealand" },
327 { "OM", "Oman" },
328 { "PA", "Panama" },
329 { "PE", "Peru" },
330 { "PH", "Philippines" },
331 { "PK", "Islamic Republic of Pakistan" },
332 { "PL", "Poland" },
333 { "PR", "Puerto Rico" },
334 { "PT", "Portugal" },
335 { "PY", "Paraguay" },
336 { "QA", "Qatar" },
337 { "RE", "Reunion" },
338 { "RO", "Romania" },
339 { "RS", "Serbia" },
340 { "RU", "Russia" },
341 { "RW", "Rwanda" },
342 { "SA", "Saudi Arabia" },
343 { "SE", "Sweden" },
344 { "SG", "Singapore" },
345 { "SI", "Slovenia" },
346 { "SK", "Slovak" },
347 { "SN", "Senegal" },
348 { "SO", "Somalia" },
349 { "SR", "Suriname" },
350 { "SV", "El Salvador" },
351 { "SY", "Syria" },
352 { "TH", "Thailand" },
353 { "TJ", "Tajikistan" },
354 { "TM", "Turkmenistan" },
355 { "TN", "Tunisia" },
356 { "TR", "Turkey" },
357 { "TT", "Trinidad and Tobago" },
358 { "TW", "Taiwan" },
359 { "TZ", "Tanzania" },
360 { "UA", "Ukraine" },
361 { "US", "United States" },
362 { "UY", "Uruguay" },
363 { "VA", "Vatican" },
364 { "VE", "Venezuela" },
365 { "VN", "Viet Nam" },
366 { "YE", "Yemen" },
367 { "ZA", "South Africa" },
368 { "ZW", "Zimbabwe" }
369 };
370
371static int
372cmp_country_code (const void *ptr1, const void *ptr2)
373{
374 const struct table_entry *cc1 = ptr1;
375 const struct table_entry *cc2 = ptr2;
376
377 return strncmp (cc1->code, cc2->code, 2);
378}
379
380/**
381 * Validates given IBAN according to the European Banking Standards. See:
382 * http://www.europeanpaymentscouncil.eu/documents/ECBS%20IBAN%20standard%20EBS204_V3.2.pdf
383 *
384 * @param iban the IBAN number to validate
385 * @return 1 is validated successfully; 0 if not.
386 */
387static int
388validate_iban (const char *iban)
389{
390 char cc[2];
391 char ibancpy[35];
392 struct table_entry cc_entry;
393 unsigned int len;
394 char *nbuf;
395 int i,j;
396
397 len = strlen(iban);
398 if (len > 34)
399 return 0;
400 (void) strncpy (cc, iban, 2);
401 (void) strncpy (ibancpy, iban+4, len - 4);
402 (void) strncpy (ibancpy + len - 4, iban, 4);
403 ibancpy[len] = '\0';
404 cc_entry.code = cc;
405 cc_entry.english = NULL;
406 if (NULL ==
407 bsearch (&cc_entry, country_table,
408 sizeof(country_table)/sizeof(struct table_entry),
409 sizeof (struct table_entry),
410 &cmp_country_code))
411 return 0;
412 nbuf = GNUNET_malloc((len * 2) + 1);
413 for (i=0, j=0; i < len; i++)
414 {
415 if(isalpha(ibancpy[i]))
416 {
417 EXITIF(2 != snprintf(&nbuf[j], 3, "%2u", (ibancpy[i] - 'A' + 10)));
418 j+=2;
419 continue;
420 }
421 nbuf[j] = ibancpy[i];
422 j++;
423 }
424 for (j=0; ;j++)
425 {
426 if ('\0' == nbuf[j])
427 break;
428 GNUNET_assert (isdigit(nbuf[j]));
429 }
430 unsigned long long dividend;
431 unsigned long long remainder = 0;
432 int nread;
433 int ret;
434 GNUNET_assert (sizeof(dividend) >= 8);
435 for (i=0; i<j; i+=16)
436 {
437 EXITIF (1 != (ret = sscanf(&nbuf[i], "%16llu %n", &dividend, &nread)));
438 if (0 != remainder)
439 dividend += remainder * (pow (10, nread));
440 remainder = dividend % 97;
441 }
442 EXITIF (1 != remainder);
443 GNUNET_free (nbuf);
444 return 1;
445
446 EXITIF_exit:
447 GNUNET_free (nbuf);
448 return 0;
449}
450
451/**
452 * Check if the given wire format JSON object is correctly formatted
453 *
454 * @param type the type of the wire format
455 * @param wire the JSON wire format object
456 * @return 1 if correctly formatted; 0 if not
457 */
458int
459TALER_JSON_validate_wireformat (const char *type, json_t *wire)
460{
461 json_error_t error;
462 if (0 == strcmp ("SEPA", type))
463 {
464 const char *type;
465 const char *iban;
466 const char *name;
467 const char *bic;
468 const char *edate;
469 uint64_t r;
470 const char *address;
471 UNPACK_EXITIF (0 != json_unpack_ex
472 (wire, &error, JSON_STRICT,
473 "{"
474 "s:s " /* type: "SEPA" */
475 "s:s " /* IBAN: iban */
476 "s:s " /* name: beneficiary name */
477 "s:s " /* BIC: beneficiary bank's BIC */
478 "s:s " /* edate: transfer execution date */
479 "s:i " /* r: random 64-bit integer nounce */
480 "s?s " /* address: address of the beneficiary */
481 "}",
482 "type", &type,
483 "IBAN", &iban,
484 "name", &name,
485 "bic", &bic,
486 "edate", &edate,
487 "r", &r,
488 "address", &address));
489 EXITIF (0 != strcmp (type, "SEPA"));
490 EXITIF (1 != validate_iban (iban));
491 return 1;
492 }
493
494 EXITIF_exit:
495 return 0;
496}
497
224/* End of util/json.c */ 498/* End of util/json.c */