diff options
Diffstat (limited to 'src/util/json.c')
-rw-r--r-- | src/util/json.c | 294 |
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 */ | ||
217 | struct 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 */ | ||
224 | static 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 | |||
371 | static int | ||
372 | cmp_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 | */ | ||
387 | static int | ||
388 | validate_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", ÷nd, &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 | */ | ||
458 | int | ||
459 | TALER_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 */ |