From 737e3f4bf67a2048381785328206c595bffe632a Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 19 Mar 2016 19:16:35 +0100 Subject: refactor to eliminate duplicated JSON parsing logic (#4150) --- src/exchange/taler-exchange-httpd_admin.c | 16 +- src/exchange/taler-exchange-httpd_deposit.c | 48 +- src/exchange/taler-exchange-httpd_parsing.c | 891 +++------------------------ src/exchange/taler-exchange-httpd_parsing.h | 309 +--------- src/exchange/taler-exchange-httpd_refresh.c | 194 +++--- src/exchange/taler-exchange-httpd_reserve.c | 18 +- src/exchange/taler-exchange-httpd_test.c | 74 +-- src/exchange/taler-exchange-httpd_tracking.c | 18 +- src/include/taler_json_lib.h | 24 + src/json/json_helper.c | 32 + 10 files changed, 344 insertions(+), 1280 deletions(-) diff --git a/src/exchange/taler-exchange-httpd_admin.c b/src/exchange/taler-exchange-httpd_admin.c index 575df7bb0..cc0245cd6 100644 --- a/src/exchange/taler-exchange-httpd_admin.c +++ b/src/exchange/taler-exchange-httpd_admin.c @@ -113,12 +113,12 @@ TMH_ADMIN_handler_admin_add_incoming (struct TMH_RequestHandler *rh, struct GNUNET_TIME_Absolute at; json_t *wire; json_t *root; - struct TMH_PARSE_FieldSpecification spec[] = { - TMH_PARSE_member_fixed ("reserve_pub", &reserve_pub), - TMH_PARSE_member_amount ("amount", &amount), - TMH_PARSE_member_time_abs ("execution_date", &at), - TMH_PARSE_member_object ("wire", &wire), - TMH_PARSE_MEMBER_END + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_fixed_auto ("reserve_pub", &reserve_pub), + TALER_JSON_spec_amount ("amount", &amount), + GNUNET_JSON_spec_absolute_time ("execution_date", &at), + GNUNET_JSON_spec_json ("wire", &wire), + GNUNET_JSON_spec_end () }; int res; @@ -148,7 +148,7 @@ TMH_ADMIN_handler_admin_add_incoming (struct TMH_RequestHandler *rh, TMH_json_validate_wireformat (wire)) { GNUNET_break_op (0); - TMH_PARSE_release_data (spec); + GNUNET_JSON_parse_free (spec); return TMH_RESPONSE_reply_arg_unknown (connection, "wire"); } @@ -157,7 +157,7 @@ TMH_ADMIN_handler_admin_add_incoming (struct TMH_RequestHandler *rh, &amount, at, wire); - TMH_PARSE_release_data (spec); + GNUNET_JSON_parse_free (spec); return res; } diff --git a/src/exchange/taler-exchange-httpd_deposit.c b/src/exchange/taler-exchange-httpd_deposit.c index 82dcf1a55..73e6463df 100644 --- a/src/exchange/taler-exchange-httpd_deposit.c +++ b/src/exchange/taler-exchange-httpd_deposit.c @@ -140,19 +140,19 @@ parse_and_handle_deposit_request (struct MHD_Connection *connection, struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki; struct TMH_KS_StateHandle *ks; struct GNUNET_HashCode my_h_wire; - struct TMH_PARSE_FieldSpecification spec[] = { - TMH_PARSE_member_denomination_public_key ("denom_pub", &deposit.coin.denom_pub), - TMH_PARSE_member_denomination_signature ("ub_sig", &deposit.coin.denom_sig), - TMH_PARSE_member_fixed ("coin_pub", &deposit.coin.coin_pub), - TMH_PARSE_member_fixed ("merchant_pub", &deposit.merchant_pub), - TMH_PARSE_member_fixed ("H_contract", &deposit.h_contract), - TMH_PARSE_member_fixed ("H_wire", &deposit.h_wire), - TMH_PARSE_member_fixed ("coin_sig", &deposit.csig), - TMH_PARSE_member_uint64 ("transaction_id", &deposit.transaction_id), - TMH_PARSE_member_time_abs ("timestamp", &deposit.timestamp), - TMH_PARSE_member_time_abs ("refund_deadline", &deposit.refund_deadline), - TMH_PARSE_member_time_abs ("edate", &deposit.wire_deadline), - TMH_PARSE_MEMBER_END + struct GNUNET_JSON_Specification spec[] = { + TALER_JSON_spec_denomination_public_key ("denom_pub", &deposit.coin.denom_pub), + TALER_JSON_spec_denomination_signature ("ub_sig", &deposit.coin.denom_sig), + GNUNET_JSON_spec_fixed_auto ("coin_pub", &deposit.coin.coin_pub), + GNUNET_JSON_spec_fixed_auto ("merchant_pub", &deposit.merchant_pub), + GNUNET_JSON_spec_fixed_auto ("H_contract", &deposit.h_contract), + GNUNET_JSON_spec_fixed_auto ("H_wire", &deposit.h_wire), + GNUNET_JSON_spec_fixed_auto ("coin_sig", &deposit.csig), + GNUNET_JSON_spec_uint64 ("transaction_id", &deposit.transaction_id), + GNUNET_JSON_spec_absolute_time ("timestamp", &deposit.timestamp), + GNUNET_JSON_spec_absolute_time ("refund_deadline", &deposit.refund_deadline), + GNUNET_JSON_spec_absolute_time ("edate", &deposit.wire_deadline), + GNUNET_JSON_spec_end () }; memset (&deposit, 0, sizeof (deposit)); @@ -167,7 +167,7 @@ parse_and_handle_deposit_request (struct MHD_Connection *connection, if (GNUNET_YES != TMH_json_validate_wireformat (wire)) { - TMH_PARSE_release_data (spec); + GNUNET_JSON_parse_free (spec); return TMH_RESPONSE_reply_arg_unknown (connection, "wire"); } @@ -176,7 +176,7 @@ parse_and_handle_deposit_request (struct MHD_Connection *connection, &my_h_wire)) { TALER_LOG_WARNING ("Failed to parse JSON wire format specification for /deposit request\n"); - TMH_PARSE_release_data (spec); + GNUNET_JSON_parse_free (spec); return TMH_RESPONSE_reply_arg_invalid (connection, "wire"); } @@ -185,7 +185,7 @@ parse_and_handle_deposit_request (struct MHD_Connection *connection, sizeof (struct GNUNET_HashCode))) { /* Client hashed contract differently than we did, reject */ - TMH_PARSE_release_data (spec); + GNUNET_JSON_parse_free (spec); return TMH_RESPONSE_reply_arg_invalid (connection, "H_wire"); } @@ -196,7 +196,7 @@ parse_and_handle_deposit_request (struct MHD_Connection *connection, if (NULL == dki) { TMH_KS_release (ks); - TMH_PARSE_release_data (spec); + GNUNET_JSON_parse_free (spec); return TMH_RESPONSE_reply_arg_unknown (connection, "denom_pub"); } @@ -209,13 +209,13 @@ parse_and_handle_deposit_request (struct MHD_Connection *connection, &deposit.deposit_fee)) { /* Total amount smaller than fee, invalid */ - TMH_PARSE_release_data (spec); + GNUNET_JSON_parse_free (spec); return TMH_RESPONSE_reply_arg_invalid (connection, "f"); } res = verify_and_execute_deposit (connection, &deposit); - TMH_PARSE_release_data (spec); + GNUNET_JSON_parse_free (spec); return res; } @@ -247,10 +247,10 @@ TMH_DEPOSIT_handler_deposit (struct TMH_RequestHandler *rh, json_t *wire; int res; struct TALER_Amount amount; - struct TMH_PARSE_FieldSpecification spec[] = { - TMH_PARSE_member_object ("wire", &wire), - TMH_PARSE_member_amount ("f", &amount), - TMH_PARSE_MEMBER_END + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_json ("wire", &wire), + TALER_JSON_spec_amount ("f", &amount), + GNUNET_JSON_spec_end () }; res = TMH_PARSE_post_json (connection, @@ -274,7 +274,7 @@ TMH_DEPOSIT_handler_deposit (struct TMH_RequestHandler *rh, json, &amount, wire); - TMH_PARSE_release_data (spec); + GNUNET_JSON_parse_free (spec); json_decref (json); return res; } diff --git a/src/exchange/taler-exchange-httpd_parsing.c b/src/exchange/taler-exchange-httpd_parsing.c index 3fd69ae50..f6e367813 100644 --- a/src/exchange/taler-exchange-httpd_parsing.c +++ b/src/exchange/taler-exchange-httpd_parsing.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015 GNUnet e.V. + Copyright (C) 2014, 2015, 2016 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software @@ -141,89 +141,6 @@ buffer_append (struct Buffer *buf, } -/** - * Release all memory allocated for the variable-size fields in - * the parser specification. - * - * @param spec specification to free - * @param spec_len number of items in @a spec to look at - */ -static void -release_data (struct TMH_PARSE_FieldSpecification *spec, - unsigned int spec_len) -{ - unsigned int i; - - for (i=0; i < spec_len; i++) - { - switch (spec[i].command) - { - case TMH_PARSE_JNC_FIELD: - GNUNET_break (0); - return; - case TMH_PARSE_JNC_INDEX: - GNUNET_break (0); - return; - case TMH_PARSE_JNC_RET_DATA: - break; - case TMH_PARSE_JNC_RET_DATA_VAR: - if (NULL != spec[i].destination) - { - GNUNET_free (* (void**) spec[i].destination); - *(void**) spec[i].destination = NULL; - *spec[i].destination_size_out = 0; - } - break; - case TMH_PARSE_JNC_RET_TYPED_JSON: - { - json_t *json; - - json = *(json_t **) spec[i].destination; - if (NULL != json) - { - json_decref (json); - *(json_t**) spec[i].destination = NULL; - } - } - break; - case TMH_PARSE_JNC_RET_RSA_PUBLIC_KEY: - { - struct TALER_DenominationPublicKey *pk; - - pk = spec[i].destination; - if (NULL != pk->rsa_public_key) - { - GNUNET_CRYPTO_rsa_public_key_free (pk->rsa_public_key); - pk->rsa_public_key = NULL; - } - } - break; - case TMH_PARSE_JNC_RET_RSA_SIGNATURE: - { - struct TALER_DenominationSignature *sig; - - sig = spec[i].destination; - if (NULL != sig->rsa_signature) - { - GNUNET_CRYPTO_rsa_signature_free (sig->rsa_signature); - sig->rsa_signature = NULL; - } - } - break; - case TMH_PARSE_JNC_RET_AMOUNT: - memset (spec[i].destination, - 0, - sizeof (struct TALER_Amount)); - break; - case TMH_PARSE_JNC_RET_TIME_ABSOLUTE: - break; - case TMH_PARSE_JNC_RET_UINT64: - break; - } - } -} - - /** * Process a POST request containing a JSON object. This function * realizes an MHD POST processor that will (incrementally) process @@ -349,8 +266,8 @@ TMH_PARSE_post_cleanup_callback (void *con_cls) /** * Extract base32crockford encoded data from request. * - * Queues an error response to the connection if the parameter is missing or - * invalid. + * Queues an error response to the connection if the parameter is + * missing or invalid. * * @param connection the MHD connection * @param param_name the name of the parameter with the key @@ -391,758 +308,116 @@ TMH_PARSE_mhd_request_arg_data (struct MHD_Connection *connection, /** - * Extraxt variable-size base32crockford encoded data from request. - * - * Queues an error response to the connection if the parameter is missing - * or the encoding is invalid. - * - * @param connection the MHD connection - * @param param_name the name of the parameter with the key - * @param[out] out_data pointer to allocate buffer and store the result - * @param[out] out_size set to the size of the buffer allocated in @a out_data - * @return - * #GNUNET_YES if the the argument is present - * #GNUNET_NO if the argument is absent or malformed - * #GNUNET_SYSERR on internal error (error response could not be sent) - */ -int -TMH_PARSE_mhd_request_var_arg_data (struct MHD_Connection *connection, - const char *param_name, - void **out_data, - size_t *out_size) -{ - const char *str; - size_t slen; - size_t olen; - void *out; - - str = MHD_lookup_connection_value (connection, - MHD_GET_ARGUMENT_KIND, - param_name); - if (NULL == str) - { - return (MHD_NO == - TMH_RESPONSE_reply_arg_missing (connection, param_name)) - ? GNUNET_SYSERR : GNUNET_NO; - } - slen = strlen (str); - olen = (slen * 5) / 8; - out = GNUNET_malloc (olen); - if (GNUNET_OK != - GNUNET_STRINGS_string_to_data (str, - strlen (str), - out, - olen)) - { - GNUNET_free (out); - *out_size = 0; - return (MHD_NO == - TMH_RESPONSE_reply_arg_invalid (connection, param_name)) - ? GNUNET_SYSERR : GNUNET_NO; - } - *out_data = out; - *out_size = olen; - return GNUNET_OK; -} - - -/** - * Navigate through a JSON tree. - * - * Sends an error response if navigation is impossible (i.e. - * the JSON object is invalid) + * Parse JSON object into components based on the given field + * specification. Generates error response on parse errors. * * @param connection the connection to send an error response to * @param root the JSON node to start the navigation at. - * @param ... navigation specification (see `enum TMH_PARSE_JsonNavigationCommand`) + * @param[in,out] spec field specification for the parser * @return - * #GNUNET_YES if navigation was successful + * #GNUNET_YES if navigation was successful (caller is responsible + * for freeing allocated variable-size data using + * #GNUNET_JSON_parse_free() when done) * #GNUNET_NO if json is malformed, error response was generated - * #GNUNET_SYSERR on internal error (no response was generated, - * connection must be closed) + * #GNUNET_SYSERR on internal error */ int -TMH_PARSE_navigate_json (struct MHD_Connection *connection, - const json_t *root, - ...) +TMH_PARSE_json_data (struct MHD_Connection *connection, + const json_t *root, + struct GNUNET_JSON_Specification *spec) { - va_list argp; int ret; - json_t *path; /* what's our current path from 'root'? */ - - path = json_array (); - va_start (argp, root); - ret = 2; /* just not any of the valid return values */ - while (2 == ret) + const char *error_json_name; + unsigned int error_line; + + ret = GNUNET_JSON_parse (root, + spec, + &error_json_name, + &error_line); + if (GNUNET_SYSERR == ret) { - enum TMH_PARSE_JsonNavigationCommand command - = va_arg (argp, - enum TMH_PARSE_JsonNavigationCommand); - - switch (command) - { - case TMH_PARSE_JNC_FIELD: - { - const char *fname = va_arg(argp, const char *); - - json_array_append_new (path, - json_string (fname)); - root = json_object_get (root, - fname); - if (NULL == root) - { - GNUNET_break_op (0); - ret = (MHD_YES == - TMH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_BAD_REQUEST, - "{s:s, s:s, s:O}", - "error", "missing field in JSON", - "field", fname, - "path", path)) - ? GNUNET_NO : GNUNET_SYSERR; - break; - } - } - break; - - case TMH_PARSE_JNC_INDEX: - { - int fnum = va_arg(argp, int); - - json_array_append_new (path, - json_integer (fnum)); - root = json_array_get (root, - fnum); - if (NULL == root) - { - GNUNET_break_op (0); - ret = (MHD_YES == - TMH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_BAD_REQUEST, - "{s:s, s:O}", - "error", "missing index in JSON", - "path", path)) - ? GNUNET_NO : GNUNET_SYSERR; - break; - } - } - break; - - case TMH_PARSE_JNC_RET_DATA: - { - void *where = va_arg (argp, void *); - size_t len = va_arg (argp, size_t); - const char *str; - int res; - - str = json_string_value (root); - if (NULL == str) - { - GNUNET_break_op (0); - ret = (MHD_YES == - TMH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_BAD_REQUEST, - "{s:s, s:O}", - "error", "string expected", - "path", path)) - ? GNUNET_NO : GNUNET_SYSERR; - break; - } - res = GNUNET_STRINGS_string_to_data (str, strlen (str), - where, len); - if (GNUNET_OK != res) - { - GNUNET_break_op (0); - ret = (MHD_YES == - TMH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_BAD_REQUEST, - "{s:s, s:O}", - "error", "malformed binary data in JSON", - "path", path)) - ? GNUNET_NO : GNUNET_SYSERR; - break; - } - ret = GNUNET_OK; - } - break; - - case TMH_PARSE_JNC_RET_DATA_VAR: - { - void **where = va_arg (argp, void **); - size_t *len = va_arg (argp, size_t *); - const char *str; - int res; - - str = json_string_value (root); - if (NULL == str) - { - GNUNET_break_op (0); - ret = (MHD_YES == - TMH_RESPONSE_reply_internal_error (connection, - "json_string_value() failed")) - ? GNUNET_NO : GNUNET_SYSERR; - break; - } - *len = (strlen (str) * 5) / 8; - if (NULL != where) - { - *where = GNUNET_malloc (*len); - res = GNUNET_STRINGS_string_to_data (str, - strlen (str), - *where, - *len); - if (GNUNET_OK != res) - { - GNUNET_break_op (0); - GNUNET_free (*where); - *where = NULL; - *len = 0; - ret = (MHD_YES == - TMH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_BAD_REQUEST, - "{s:s, s:O}", - "error", "malformed binary data in JSON", - "path", path)) - ? GNUNET_NO : GNUNET_SYSERR; - break; - } - } - ret = GNUNET_OK; - } - break; - - case TMH_PARSE_JNC_RET_TYPED_JSON: - { - int typ = va_arg (argp, int); - const json_t **r_json = va_arg (argp, const json_t **); - - if ( (NULL == root) || - ( (-1 != typ) && - (json_typeof (root) != typ)) ) - { - GNUNET_break_op (0); - *r_json = NULL; - ret = (MHD_YES == - TMH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_BAD_REQUEST, - "{s:s, s:i, s:i, s:O}", - "error", "wrong JSON field type", - "type_expected", typ, - "type_actual", json_typeof (root), - "path", path)) - ? GNUNET_NO : GNUNET_SYSERR; - break; - } - *r_json = root; - json_incref ((json_t *) root); - ret = GNUNET_OK; - } - break; - - case TMH_PARSE_JNC_RET_UINT64: - { - uint64_t *r_u64 = va_arg (argp, uint64_t *); - - if (json_typeof (root) != JSON_INTEGER) - { - GNUNET_break_op (0); - ret = (MHD_YES == - TMH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_BAD_REQUEST, - "{s:s, s:s, s:i, s:O}", - "error", "wrong JSON field type", - "type_expected", "integer", - "type_actual", json_typeof (root), - "path", path)) - ? GNUNET_NO : GNUNET_SYSERR; - break; - } - *r_u64 = (uint64_t) json_integer_value (root); - ret = GNUNET_OK; - } - break; - - case TMH_PARSE_JNC_RET_RSA_PUBLIC_KEY: - { - struct TALER_DenominationPublicKey *where; - size_t len; - const char *str; - int res; - void *buf; - - where = va_arg (argp, - struct TALER_DenominationPublicKey *); - str = json_string_value (root); - if (NULL == str) - { - GNUNET_break_op (0); - ret = (MHD_YES == - TMH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_BAD_REQUEST, - "{s:s, s:O}", - "error", "string expected", - "path", path)) - ? GNUNET_NO : GNUNET_SYSERR; - break; - } - len = (strlen (str) * 5) / 8; - buf = GNUNET_malloc (len); - res = GNUNET_STRINGS_string_to_data (str, - strlen (str), - buf, - len); - if (GNUNET_OK != res) - { - GNUNET_break_op (0); - GNUNET_free (buf); - ret = (MHD_YES == - TMH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_BAD_REQUEST, - "{s:s, s:O}", - "error", "malformed binary data in JSON", - "path", path)) - ? GNUNET_NO : GNUNET_SYSERR; - break; - } - where->rsa_public_key = GNUNET_CRYPTO_rsa_public_key_decode (buf, - len); - GNUNET_free (buf); - if (NULL == where->rsa_public_key) - { - GNUNET_break_op (0); - ret = (MHD_YES == - TMH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_BAD_REQUEST, - "{s:s, s:O}", - "error", "malformed RSA public key in JSON", - "path", path)) - ? GNUNET_NO : GNUNET_SYSERR; - break; - } - ret = GNUNET_OK; - break; - } - - case TMH_PARSE_JNC_RET_RSA_SIGNATURE: - { - struct TALER_DenominationSignature *where; - size_t len; - const char *str; - int res; - void *buf; - - where = va_arg (argp, - struct TALER_DenominationSignature *); - str = json_string_value (root); - if (NULL == str) - { - GNUNET_break_op (0); - ret = (MHD_YES == - TMH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_BAD_REQUEST, - "{s:s, s:O}", - "error", "string expected", - "path", path)) - ? GNUNET_NO : GNUNET_SYSERR; - break; - } - len = (strlen (str) * 5) / 8; - buf = GNUNET_malloc (len); - res = GNUNET_STRINGS_string_to_data (str, - strlen (str), - buf, - len); - if (GNUNET_OK != res) - { - GNUNET_break_op (0); - GNUNET_free (buf); - ret = (MHD_YES == - TMH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_BAD_REQUEST, - "{s:s, s:O}", - "error", "malformed binary data in JSON", - "path", path)) - ? GNUNET_NO : GNUNET_SYSERR; - break; - } - where->rsa_signature = GNUNET_CRYPTO_rsa_signature_decode (buf, - len); - GNUNET_free (buf); - if (NULL == where->rsa_signature) - { - GNUNET_break_op (0); - ret = (MHD_YES == - TMH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_BAD_REQUEST, - "{s:s, s:O}", - "error", "malformed RSA signature in JSON", - "path", path)) - ? GNUNET_NO : GNUNET_SYSERR; - break; - } - ret = GNUNET_OK; - break; - } - - case TMH_PARSE_JNC_RET_AMOUNT: - { - struct TALER_Amount *where = va_arg (argp, void *); - struct GNUNET_JSON_Specification spec[] = { - TALER_JSON_spec_amount (NULL, where), - GNUNET_JSON_spec_end () - }; - - if (GNUNET_OK != - GNUNET_JSON_parse ((json_t *) root, - spec, - NULL, NULL)) - { - GNUNET_break_op (0); - ret = (MHD_YES != - TMH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_BAD_REQUEST, - "{s:s, s:O}", - "error", "Bad format", - "path", path)) - ? GNUNET_SYSERR : GNUNET_NO; - break; - } - if (0 != strcmp (where->currency, - TMH_exchange_currency_string)) - { - GNUNET_break_op (0); - ret = (MHD_YES != - TMH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_BAD_REQUEST, - "{s:s, s:O, s:s}", - "error", "Currency not supported", - "path", path, - "currency", where->currency)) - ? GNUNET_SYSERR : GNUNET_NO; - memset (where, 0, sizeof (struct TALER_Amount)); - break; - } - ret = GNUNET_OK; - break; - } - - case TMH_PARSE_JNC_RET_TIME_ABSOLUTE: - { - struct GNUNET_TIME_Absolute *where = va_arg (argp, void *); - struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_absolute_time (NULL, where), - GNUNET_JSON_spec_end () - }; - - if (GNUNET_OK != - GNUNET_JSON_parse ((json_t *) root, - spec, - NULL, NULL)) - { - GNUNET_break_op (0); - ret = (MHD_YES != - TMH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_BAD_REQUEST, - "{s:s, s:s, s:O}", - "error", "Bad format", - "hint", "expected absolute time", - "path", path)) - ? GNUNET_SYSERR : GNUNET_NO; - break; - } - ret = GNUNET_OK; - break; - } - - default: - GNUNET_break (0); - ret = (MHD_YES == - TMH_RESPONSE_reply_internal_error (connection, - "unhandled value in switch")) - ? GNUNET_NO : GNUNET_SYSERR; - break; - } + if (NULL == error_json_name) + error_json_name = ""; + ret = (MHD_YES == + TMH_RESPONSE_reply_json_pack (connection, + MHD_HTTP_BAD_REQUEST, + "{s:s, s:s, s:I}", + "error", "parse error", + "field", error_json_name, + "line", (json_int_t) error_line)) + ? GNUNET_NO : GNUNET_SYSERR; + return ret; } - va_end (argp); - json_decref (path); - return ret; + return GNUNET_YES; } /** - * Parse JSON object into components based on the given field - * specification. + * Parse JSON array into components based on the given field + * specification. Generates error response on parse errors. * * @param connection the connection to send an error response to * @param root the JSON node to start the navigation at. - * @param spec field specification for the parser + * @param[in,out] spec field specification for the parser + * @param ... -1-terminated list of array offsets of type 'int' * @return * #GNUNET_YES if navigation was successful (caller is responsible * for freeing allocated variable-size data using - * #TMH_PARSE_release_data() when done) + * #GNUNET_JSON_parse_free() when done) * #GNUNET_NO if json is malformed, error response was generated * #GNUNET_SYSERR on internal error */ int -TMH_PARSE_json_data (struct MHD_Connection *connection, - const json_t *root, - struct TMH_PARSE_FieldSpecification *spec) +TMH_PARSE_json_array (struct MHD_Connection *connection, + const json_t *root, + struct GNUNET_JSON_Specification *spec, + ...) { - unsigned int i; int ret; - - ret = GNUNET_YES; - for (i=0; NULL != spec[i].field_name; i++) + const char *error_json_name; + unsigned int error_line; + va_list ap; + json_int_t dim; + + va_start (ap, spec); + dim = 0; + while ( (-1 != (ret = va_arg (ap, int))) && + (NULL != root) ) { - if (GNUNET_YES != ret) - break; - switch (spec[i].command) - { - case TMH_PARSE_JNC_FIELD: - GNUNET_break (0); - return GNUNET_SYSERR; - case TMH_PARSE_JNC_INDEX: - GNUNET_break (0); - return GNUNET_SYSERR; - case TMH_PARSE_JNC_RET_DATA: - ret = TMH_PARSE_navigate_json (connection, - root, - TMH_PARSE_JNC_FIELD, - spec[i].field_name, - TMH_PARSE_JNC_RET_DATA, - spec[i].destination, - spec[i].destination_size_in); - break; - case TMH_PARSE_JNC_RET_DATA_VAR: - ret = TMH_PARSE_navigate_json (connection, - root, - TMH_PARSE_JNC_FIELD, - spec[i].field_name, - TMH_PARSE_JNC_RET_DATA_VAR, - (void **) spec[i].destination, - spec[i].destination_size_out); - break; - case TMH_PARSE_JNC_RET_TYPED_JSON: - ret = TMH_PARSE_navigate_json (connection, - root, - TMH_PARSE_JNC_FIELD, - spec[i].field_name, - TMH_PARSE_JNC_RET_TYPED_JSON, - spec[i].type, - spec[i].destination); - break; - case TMH_PARSE_JNC_RET_RSA_PUBLIC_KEY: - ret = TMH_PARSE_navigate_json (connection, - root, - TMH_PARSE_JNC_FIELD, - spec[i].field_name, - TMH_PARSE_JNC_RET_RSA_PUBLIC_KEY, - spec[i].destination); - break; - case TMH_PARSE_JNC_RET_RSA_SIGNATURE: - ret = TMH_PARSE_navigate_json (connection, - root, - TMH_PARSE_JNC_FIELD, - spec[i].field_name, - TMH_PARSE_JNC_RET_RSA_SIGNATURE, - spec[i].destination); - break; - case TMH_PARSE_JNC_RET_AMOUNT: - GNUNET_assert (sizeof (struct TALER_Amount) == - spec[i].destination_size_in); - ret = TMH_PARSE_navigate_json (connection, - root, - TMH_PARSE_JNC_FIELD, - spec[i].field_name, - TMH_PARSE_JNC_RET_AMOUNT, - spec[i].destination); - break; - case TMH_PARSE_JNC_RET_TIME_ABSOLUTE: - GNUNET_assert (sizeof (struct GNUNET_TIME_Absolute) == - spec[i].destination_size_in); - ret = TMH_PARSE_navigate_json (connection, - root, - TMH_PARSE_JNC_FIELD, - spec[i].field_name, - TMH_PARSE_JNC_RET_TIME_ABSOLUTE, - spec[i].destination); - break; - case TMH_PARSE_JNC_RET_UINT64: - GNUNET_assert (sizeof (uint64_t) == - spec[i].destination_size_in); - ret = TMH_PARSE_navigate_json (connection, - root, - TMH_PARSE_JNC_FIELD, - spec[i].field_name, - TMH_PARSE_JNC_RET_UINT64, - spec[i].destination); - break; - } + dim++; + root = json_array_get (root, ret); } - if (GNUNET_YES != ret) - release_data (spec, - i - 1); - return ret; -} - - -/** - * Release all memory allocated for the variable-size fields in - * the parser specification. - * - * @param spec specification to free - */ -void -TMH_PARSE_release_data (struct TMH_PARSE_FieldSpecification *spec) -{ - unsigned int i; - - for (i=0; NULL != spec[i].field_name; i++) ; - release_data (spec, i); -} - - -/** - * Generate line in parser specification for 64-bit integer - * given as an integer in JSON. - * - * @param field name of the field - * @param[out] u64 integer to initialize - * @return corresponding field spec - */ -struct TMH_PARSE_FieldSpecification -TMH_PARSE_member_uint64 (const char *field, - uint64_t *u64) -{ - struct TMH_PARSE_FieldSpecification ret = - { field, (void *) u64, sizeof (uint64_t), NULL, TMH_PARSE_JNC_RET_UINT64, 0 }; - return ret; -} - - -/** - * Generate line in parser specification for JSON object value. - * - * @param field name of the field - * @param[out] jsonp address of pointer to JSON to initialize - * @return corresponding field spec - */ -struct TMH_PARSE_FieldSpecification -TMH_PARSE_member_object (const char *field, - json_t **jsonp) -{ - struct TMH_PARSE_FieldSpecification ret = - { field, jsonp, 0, NULL, TMH_PARSE_JNC_RET_TYPED_JSON, JSON_OBJECT }; - *jsonp = NULL; - return ret; -} - - -/** - * Generate line in parser specification for JSON array value. - * - * @param field name of the field - * @param[out] jsonp address of JSON pointer to initialize - * @return corresponding field spec - */ -struct TMH_PARSE_FieldSpecification -TMH_PARSE_member_array (const char *field, - json_t **jsonp) -{ - struct TMH_PARSE_FieldSpecification ret = - { field, jsonp, 0, NULL, TMH_PARSE_JNC_RET_TYPED_JSON, JSON_ARRAY }; - *jsonp = NULL; - return ret; -} - - -/** - * Generate line in parser specification for an absolute time. - * - * @param field name of the field - * @param[out] atime time to initialize - */ -struct TMH_PARSE_FieldSpecification -TMH_PARSE_member_time_abs (const char *field, - struct GNUNET_TIME_Absolute *atime) -{ - struct TMH_PARSE_FieldSpecification ret = - { field, atime, sizeof(struct GNUNET_TIME_Absolute), NULL, TMH_PARSE_JNC_RET_TIME_ABSOLUTE, 0 }; - return ret; -} - - -/** - * Generate line in parser specification for RSA public key. - * - * @param field name of the field - * @param[out] pk key to initialize - * @return corresponding field spec - */ -struct TMH_PARSE_FieldSpecification -TMH_PARSE_member_denomination_public_key (const char *field, - struct TALER_DenominationPublicKey *pk) -{ - struct TMH_PARSE_FieldSpecification ret = - { field, pk, 0, NULL, TMH_PARSE_JNC_RET_RSA_PUBLIC_KEY, 0 }; - pk->rsa_public_key = NULL; - return ret; -} - - -/** - * Generate line in parser specification for RSA public key. - * - * @param field name of the field - * @param sig the signature to initialize - * @return corresponding field spec - */ -struct TMH_PARSE_FieldSpecification -TMH_PARSE_member_denomination_signature (const char *field, - struct TALER_DenominationSignature *sig) -{ - struct TMH_PARSE_FieldSpecification ret = - { field, sig, 0, NULL, TMH_PARSE_JNC_RET_RSA_SIGNATURE, 0 }; - sig->rsa_signature = NULL; - return ret; -} - - -/** - * Generate line in parser specification for an amount. - * - * @param field name of the field - * @param amount a `struct TALER_Amount *` to initialize - * @return corresponding field spec - */ -struct TMH_PARSE_FieldSpecification -TMH_PARSE_member_amount (const char *field, - struct TALER_Amount *amount) -{ - struct TMH_PARSE_FieldSpecification ret = - { field, amount, sizeof(struct TALER_Amount), NULL, TMH_PARSE_JNC_RET_AMOUNT, 0 }; - memset (amount, 0, sizeof (struct TALER_Amount)); - return ret; + if (NULL == root) + { + ret = (MHD_YES == + TMH_RESPONSE_reply_json_pack (connection, + MHD_HTTP_BAD_REQUEST, + "{s:s, s:I}", + "error", "parse error", + "dimension", dim)) + ? GNUNET_NO : GNUNET_SYSERR; + return ret; + } + ret = GNUNET_JSON_parse (root, + spec, + &error_json_name, + &error_line); + if (GNUNET_SYSERR == ret) + { + if (NULL == error_json_name) + error_json_name = ""; + ret = (MHD_YES == + TMH_RESPONSE_reply_json_pack (connection, + MHD_HTTP_BAD_REQUEST, + "{s:s, s:s, s:I}", + "error", "parse error", + "field", error_json_name, + "line", (json_int_t) error_line)) + ? GNUNET_NO : GNUNET_SYSERR; + return ret; + } + return GNUNET_YES; } -/** - * Generate line in parser specification for variable-size value. - * - * @param field name of the field - * @param[out] ptr pointer to initialize - * @param[out] ptr_size size to initialize - * @return corresponding field spec - */ -struct TMH_PARSE_FieldSpecification -TMH_PARSE_member_variable (const char *field, - void **ptr, - size_t *ptr_size) -{ - struct TMH_PARSE_FieldSpecification ret = - { field, ptr, 0, ptr_size, TMH_PARSE_JNC_RET_DATA_VAR, 0 }; - *ptr = NULL; - return ret; -} - /* end of taler-exchange-httpd_parsing.c */ diff --git a/src/exchange/taler-exchange-httpd_parsing.h b/src/exchange/taler-exchange-httpd_parsing.h index a39235685..d09f58767 100644 --- a/src/exchange/taler-exchange-httpd_parsing.h +++ b/src/exchange/taler-exchange-httpd_parsing.h @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015 GNUnet e.V. + Copyright (C) 2014, 2015, 2016 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software @@ -26,6 +26,7 @@ #include #include #include "taler_util.h" +#include "taler_json_lib.h" /** @@ -72,291 +73,45 @@ TMH_PARSE_post_cleanup_callback (void *con_cls); /** - * Constants for JSON navigation description. - */ -enum TMH_PARSE_JsonNavigationCommand -{ - /** - * Access a field. - * Param: const char * - */ - TMH_PARSE_JNC_FIELD, - - /** - * Access an array index. - * Param: int - */ - TMH_PARSE_JNC_INDEX, - - /** - * Return base32crockford encoded data of - * constant size. - * Params: (void *, size_t) - */ - TMH_PARSE_JNC_RET_DATA, - - /** - * Return base32crockford encoded data of - * variable size. - * Params: (void **, size_t *) - */ - TMH_PARSE_JNC_RET_DATA_VAR, - - /** - * Return a json object, which must be - * of the given type (JSON_* type constants, - * or -1 for any type). - * Params: (int, json_t **) - */ - TMH_PARSE_JNC_RET_TYPED_JSON, - - /** - * Return a `struct GNUNET_CRYPTO_rsa_PublicKey` which was - * encoded as variable-size base32crockford encoded data. - */ - TMH_PARSE_JNC_RET_RSA_PUBLIC_KEY, - - /** - * Return a `struct GNUNET_CRYPTO_rsa_Signature` which was - * encoded as variable-size base32crockford encoded data. - */ - TMH_PARSE_JNC_RET_RSA_SIGNATURE, - - /** - * Return a `struct TALER_Amount` which was - * encoded within its own json object. - */ - TMH_PARSE_JNC_RET_AMOUNT, - - /** - * Return a `struct GNUNET_TIME_Absolute` which was - * encoded within its own json object. - * Param: struct GNUNET_TIME_Absolute * - */ - TMH_PARSE_JNC_RET_TIME_ABSOLUTE, - - /** - * Return a `uint64_t` which was - * encoded as a JSON integer. - * Param: uint64_t * - */ - TMH_PARSE_JNC_RET_UINT64 - -}; - - -/** - * Navigate through a JSON tree. - * - * Sends an error response if navigation is impossible (i.e. - * the JSON object is invalid) + * Parse JSON object into components based on the given field + * specification. * * @param connection the connection to send an error response to * @param root the JSON node to start the navigation at. - * @param ... navigation specification (see `enum TMH_PARSE_JsonNavigationCommand`) + * @param spec field specification for the parser * @return - * #GNUNET_YES if navigation was successful + * #GNUNET_YES if navigation was successful (caller is responsible + * for freeing allocated variable-size data using + * #GNUNET_JSON_parse_free() when done) * #GNUNET_NO if json is malformed, error response was generated * #GNUNET_SYSERR on internal error */ int -TMH_PARSE_navigate_json (struct MHD_Connection *connection, - const json_t *root, - ...); - - -/** - * @brief Specification for how to parse a JSON field. - */ -struct TMH_PARSE_FieldSpecification -{ - /** - * Name of the field. NULL only to terminate array. - */ - const char *field_name; - - /** - * Where to store the result. Must have exactly - * @e destination_size bytes, except if @e destination_size is zero. - * NULL to skip assignment (but check presence of the value). - */ - void *destination; - - /** - * How big should the result be, 0 for variable size. In - * this case, @e destination must be a "void **", pointing - * to a location that is currently NULL and is to be allocated. - */ - size_t destination_size_in; - - /** - * @e destination_size_out will then be set to the size of the - * value that was stored in @e destination (useful for - * variable-size allocations). - */ - size_t *destination_size_out; - - /** - * Navigation command to use to extract the value. Note that - * #TMH_PARSE_JNC_RET_DATA or #TMH_PARSE_JNC_RET_DATA_VAR must be used for @e - * destination_size_in and @e destination_size_out to have a - * meaning. #TMH_PARSE_JNC_FIELD and #TMH_PARSE_JNC_INDEX must not be used here! - */ - enum TMH_PARSE_JsonNavigationCommand command; - - /** - * JSON type to use, only meaningful in connection with a @e command - * value of #TMH_PARSE_JNC_RET_TYPED_JSON. Typical values are - * #JSON_ARRAY and #JSON_OBJECT. - */ - int type; - -}; +TMH_PARSE_json_data (struct MHD_Connection *connection, + const json_t *root, + struct GNUNET_JSON_Specification *spec); /** - * Parse JSON object into components based on the given field - * specification. + * Parse JSON array into components based on the given field + * specification. Generates error response on parse errors. * * @param connection the connection to send an error response to * @param root the JSON node to start the navigation at. - * @param spec field specification for the parser + * @param[in,out] spec field specification for the parser + * @param ... -1-terminated list of array offsets of type 'int' * @return * #GNUNET_YES if navigation was successful (caller is responsible * for freeing allocated variable-size data using - * #TMH_PARSE_release_data() when done) + * #GNUNET_JSON_parse_free() when done) * #GNUNET_NO if json is malformed, error response was generated * #GNUNET_SYSERR on internal error */ int -TMH_PARSE_json_data (struct MHD_Connection *connection, - const json_t *root, - struct TMH_PARSE_FieldSpecification *spec); - - -/** - * Release all memory allocated for the variable-size fields in - * the parser specification. - * - * @param spec specification to free - */ -void -TMH_PARSE_release_data (struct TMH_PARSE_FieldSpecification *spec); - - -/** - * Generate line in parser specification for fixed-size value. - * - * @param field name of the field - * @param value where to store the value - */ -#define TMH_PARSE_member_fixed(field,value) { field, value, sizeof (*value), NULL, TMH_PARSE_JNC_RET_DATA, 0 } - - -/** - * Generate line in parser specification for variable-size value. - * - * @param field name of the field - * @param[out] ptr pointer to initialize - * @param[out] ptr_size size to initialize - * @return corresponding field spec - */ -struct TMH_PARSE_FieldSpecification -TMH_PARSE_member_variable (const char *field, - void **ptr, - size_t *ptr_size); - - -/** - * Generate line in parser specification for 64-bit integer - * given as an integer in JSON. - * - * @param field name of the field - * @param[out] u64 integer to initialize - * @return corresponding field spec - */ -struct TMH_PARSE_FieldSpecification -TMH_PARSE_member_uint64 (const char *field, - uint64_t *u64); - - -/** - * Generate line in parser specification for JSON array value. - * - * @param field name of the field - * @param[out] jsonp address of JSON pointer to initialize - * @return corresponding field spec - */ -struct TMH_PARSE_FieldSpecification -TMH_PARSE_member_array (const char *field, - json_t **jsonp); - - -/** - * Generate line in parser specification for JSON object value. - * - * @param field name of the field - * @param[out] jsonp address of pointer to JSON to initialize - * @return corresponding field spec - */ -struct TMH_PARSE_FieldSpecification -TMH_PARSE_member_object (const char *field, - json_t **jsonp); - - -/** - * Generate line in parser specification for RSA public key. - * - * @param field name of the field - * @param[out] pk key to initialize - * @return corresponding field spec - */ -struct TMH_PARSE_FieldSpecification -TMH_PARSE_member_denomination_public_key (const char *field, - struct TALER_DenominationPublicKey *pk); - - -/** - * Generate line in parser specification for RSA public key. - * - * @param field name of the field - * @param sig the signature to initialize - * @return corresponding field spec - */ -struct TMH_PARSE_FieldSpecification -TMH_PARSE_member_denomination_signature (const char *field, - struct TALER_DenominationSignature *sig); - - -/** - * Generate line in parser specification for an amount. - * - * @param field name of the field - * @param[out] amount a `struct TALER_Amount *` to initialize - * @return corresponding field spec - */ -struct TMH_PARSE_FieldSpecification -TMH_PARSE_member_amount (const char *field, - struct TALER_Amount *amount); - - -/** - * Generate line in parser specification for an absolute time. - * - * @param field name of the field - * @param[out] atime time to initialize - * @return corresponding field spec - */ -struct TMH_PARSE_FieldSpecification -TMH_PARSE_member_time_abs (const char *field, - struct GNUNET_TIME_Absolute *atime); - - - -/** - * Generate line in parser specification indicating the end of the spec. - */ -#define TMH_PARSE_MEMBER_END { NULL, NULL, 0, NULL, TMH_PARSE_JNC_FIELD, 0 } +TMH_PARSE_json_array (struct MHD_Connection *connection, + const json_t *root, + struct GNUNET_JSON_Specification *spec, + ...); /** @@ -381,28 +136,4 @@ TMH_PARSE_mhd_request_arg_data (struct MHD_Connection *connection, size_t out_size); -/** - * Extraxt variable-size base32crockford encoded data from request. - * - * Queues an error response to the connection if the parameter is missing - * or the encoding is invalid. - * - * @param connection the MHD connection - * @param param_name the name of the parameter with the key - * @param[out] out_data pointer to allocate buffer and store the result - * @param[out] out_size set to the size of the buffer allocated in @a out_data - * @return - * #GNUNET_YES if the the argument is present - * #GNUNET_NO if the argument is absent or malformed - * #GNUNET_SYSERR on internal error (error response could not be sent) - */ -int -TMH_PARSE_mhd_request_var_arg_data (struct MHD_Connection *connection, - const char *param_name, - void **out_data, - size_t *out_size); - - - - #endif /* TALER_EXCHANGE_HTTPD_PARSING_H */ diff --git a/src/exchange/taler-exchange-httpd_refresh.c b/src/exchange/taler-exchange-httpd_refresh.c index 45bbf3d4d..2349d90ac 100644 --- a/src/exchange/taler-exchange-httpd_refresh.c +++ b/src/exchange/taler-exchange-httpd_refresh.c @@ -192,13 +192,13 @@ get_coin_public_info (struct MHD_Connection *connection, struct TALER_DenominationSignature sig; struct TALER_DenominationPublicKey pk; struct TALER_Amount amount; - struct TMH_PARSE_FieldSpecification spec[] = { - TMH_PARSE_member_fixed ("coin_pub", &r_melt_detail->coin_info.coin_pub), - TMH_PARSE_member_denomination_signature ("denom_sig", &sig), - TMH_PARSE_member_denomination_public_key ("denom_pub", &pk), - TMH_PARSE_member_fixed ("confirm_sig", &melt_sig), - TMH_PARSE_member_amount ("value_with_fee", &amount), - TMH_PARSE_MEMBER_END + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_fixed_auto ("coin_pub", &r_melt_detail->coin_info.coin_pub), + TALER_JSON_spec_denomination_signature ("denom_sig", &sig), + TALER_JSON_spec_denomination_public_key ("denom_pub", &pk), + GNUNET_JSON_spec_fixed_auto ("confirm_sig", &melt_sig), + TALER_JSON_spec_amount ("value_with_fee", &amount), + GNUNET_JSON_spec_end () }; ret = TMH_PARSE_json_data (connection, @@ -216,7 +216,7 @@ get_coin_public_info (struct MHD_Connection *connection, TALER_test_coin_valid (&r_melt_detail->coin_info)) { GNUNET_break_op (0); - TMH_PARSE_release_data (spec); + GNUNET_JSON_parse_free (spec); r_melt_detail->coin_info.denom_sig.rsa_signature = NULL; r_melt_detail->coin_info.denom_pub.rsa_public_key = NULL; return (MHD_YES == @@ -409,12 +409,16 @@ handle_refresh_melt_json (struct MHD_Connection *connection, { char *buf; size_t buf_size; - - res = TMH_PARSE_navigate_json (connection, - new_denoms, - TMH_PARSE_JNC_INDEX, (int) i, - TMH_PARSE_JNC_RET_RSA_PUBLIC_KEY, - &denom_pubs[i].rsa_public_key); + struct GNUNET_JSON_Specification spec[] = { + TALER_JSON_spec_denomination_public_key (NULL, + &denom_pubs[i]), + GNUNET_JSON_spec_end () + }; + + res = TMH_PARSE_json_array (connection, + new_denoms, + spec, + i, -1); if (GNUNET_OK != res) { res = (GNUNET_NO == res) ? MHD_YES : MHD_NO; @@ -436,6 +440,7 @@ handle_refresh_melt_json (struct MHD_Connection *connection, /* decode JSON data on coin to melt */ struct TALER_AmountNBO melt_amount; + // FIXME: check json_array_get() return value for NULL! res = get_coin_public_info (connection, json_array_get (melt_coins, i), &coin_melt_details[i]); @@ -482,15 +487,23 @@ handle_refresh_melt_json (struct MHD_Connection *connection, char *link_enc; size_t link_enc_size; struct TALER_EXCHANGEDB_RefreshCommitCoin *rcc = &commit_coin[i][j]; - - res = TMH_PARSE_navigate_json (connection, - coin_evs, - TMH_PARSE_JNC_INDEX, (int) i, - TMH_PARSE_JNC_INDEX, (int) j, - TMH_PARSE_JNC_RET_DATA_VAR, - &rcc->coin_ev, - &rcc->coin_ev_size); - + struct GNUNET_JSON_Specification coin_spec[] = { + GNUNET_JSON_spec_varsize (NULL, + (void **) &rcc->coin_ev, + &rcc->coin_ev_size), + GNUNET_JSON_spec_end () + }; + struct GNUNET_JSON_Specification link_spec[] = { + GNUNET_JSON_spec_varsize (NULL, + (void **) &link_enc, + &link_enc_size), + GNUNET_JSON_spec_end () + }; + + res = TMH_PARSE_json_array (connection, + coin_evs, + coin_spec, + i, j, -1); if (GNUNET_OK != res) { GNUNET_break_op (0); @@ -501,13 +514,10 @@ handle_refresh_melt_json (struct MHD_Connection *connection, GNUNET_CRYPTO_hash_context_read (hash_context, rcc->coin_ev, rcc->coin_ev_size); - res = TMH_PARSE_navigate_json (connection, - link_encs, - TMH_PARSE_JNC_INDEX, (int) i, - TMH_PARSE_JNC_INDEX, (int) j, - TMH_PARSE_JNC_RET_DATA_VAR, - &link_enc, - &link_enc_size); + res = TMH_PARSE_json_array (connection, + link_encs, + link_spec, + i, j, -1); if (GNUNET_OK != res) { GNUNET_break_op (0); @@ -520,7 +530,7 @@ handle_refresh_melt_json (struct MHD_Connection *connection, GNUNET_CRYPTO_hash_context_read (hash_context, link_enc, link_enc_size); - GNUNET_free (link_enc); + GNUNET_JSON_parse_free (link_spec); } } @@ -531,27 +541,29 @@ handle_refresh_melt_json (struct MHD_Connection *connection, for (j = 0; j < num_oldcoins; j++) { struct TALER_RefreshCommitLinkP *rcl = &commit_link[i][j]; - - res = TMH_PARSE_navigate_json (connection, - transfer_pubs, - TMH_PARSE_JNC_INDEX, (int) i, - TMH_PARSE_JNC_INDEX, (int) j, - TMH_PARSE_JNC_RET_DATA, - &rcl->transfer_pub, - sizeof (struct TALER_TransferPublicKeyP)); + struct GNUNET_JSON_Specification trans_spec[] = { + GNUNET_JSON_spec_fixed_auto (NULL, &rcl->transfer_pub), + GNUNET_JSON_spec_end () + }; + struct GNUNET_JSON_Specification sec_spec[] = { + GNUNET_JSON_spec_fixed_auto (NULL, &rcl->shared_secret_enc), + GNUNET_JSON_spec_end () + }; + + res = TMH_PARSE_json_array (connection, + transfer_pubs, + trans_spec, + i, j, -1); if (GNUNET_OK != res) { GNUNET_break_op (0); res = (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; goto cleanup; } - res = TMH_PARSE_navigate_json (connection, - secret_encs, - TMH_PARSE_JNC_INDEX, (int) i, - TMH_PARSE_JNC_INDEX, (int) j, - TMH_PARSE_JNC_RET_DATA, - &rcl->shared_secret_enc, - sizeof (struct TALER_EncryptedLinkSecretP)); + res = TMH_PARSE_json_array (connection, + secret_encs, + sec_spec, + i, j, -1); if (GNUNET_OK != res) { GNUNET_break_op (0); @@ -646,15 +658,16 @@ TMH_REFRESH_handler_refresh_melt (struct TMH_RequestHandler *rh, unsigned int num_oldcoins; unsigned int num_newcoins; json_t *coin_detail; + json_t *trans_detail; int res; - struct TMH_PARSE_FieldSpecification spec[] = { - TMH_PARSE_member_array ("new_denoms", &new_denoms), - TMH_PARSE_member_array ("melt_coins", &melt_coins), - TMH_PARSE_member_array ("coin_evs", &coin_evs), - TMH_PARSE_member_array ("link_encs", &link_encs), - TMH_PARSE_member_array ("transfer_pubs", &transfer_pubs), - TMH_PARSE_member_array ("secret_encs", &secret_encs), - TMH_PARSE_MEMBER_END + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_json ("new_denoms", &new_denoms), + GNUNET_JSON_spec_json ("melt_coins", &melt_coins), + GNUNET_JSON_spec_json ("coin_evs", &coin_evs), + GNUNET_JSON_spec_json ("link_encs", &link_encs), + GNUNET_JSON_spec_json ("transfer_pubs", &transfer_pubs), + GNUNET_JSON_spec_json ("secret_encs", &secret_encs), + GNUNET_JSON_spec_end () }; res = TMH_PARSE_post_json (connection, @@ -678,43 +691,36 @@ TMH_REFRESH_handler_refresh_melt (struct TMH_RequestHandler *rh, if (TALER_CNC_KAPPA != json_array_size (coin_evs)) { GNUNET_break_op (0); - TMH_PARSE_release_data (spec); + GNUNET_JSON_parse_free (spec); return TMH_RESPONSE_reply_arg_invalid (connection, "coin_evs"); } if (TALER_CNC_KAPPA != json_array_size (transfer_pubs)) { GNUNET_break_op (0); - TMH_PARSE_release_data (spec); + GNUNET_JSON_parse_free (spec); return TMH_RESPONSE_reply_arg_invalid (connection, "transfer_pubs"); } - res = TMH_PARSE_navigate_json (connection, - coin_evs, - TMH_PARSE_JNC_INDEX, (int) 0, - TMH_PARSE_JNC_RET_TYPED_JSON, - JSON_ARRAY, &coin_detail); - if (GNUNET_OK != res) + coin_detail = json_array_get (coin_evs, 0); + if (NULL == coin_detail) { + // FIXME: generate proper HTTP response! GNUNET_break_op (0); - TMH_PARSE_release_data (spec); + GNUNET_JSON_parse_free (spec); return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; } num_newcoins = json_array_size (coin_detail); - json_decref (coin_detail); - res = TMH_PARSE_navigate_json (connection, - transfer_pubs, - TMH_PARSE_JNC_INDEX, (int) 0, - TMH_PARSE_JNC_RET_TYPED_JSON, - JSON_ARRAY, &coin_detail); - if (GNUNET_OK != res) + + trans_detail = json_array_get (transfer_pubs, 0); + if (NULL == trans_detail) { + // FIXME: generate proper HTTP response! GNUNET_break_op (0); - TMH_PARSE_release_data (spec); + GNUNET_JSON_parse_free (spec); return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; } - num_oldcoins = json_array_size (coin_detail); - json_decref (coin_detail); + num_oldcoins = json_array_size (trans_detail); res = handle_refresh_melt_json (connection, new_denoms, melt_coins, @@ -724,7 +730,7 @@ TMH_REFRESH_handler_refresh_melt (struct TMH_RequestHandler *rh, num_newcoins, coin_evs, link_encs); - TMH_PARSE_release_data (spec); + GNUNET_JSON_parse_free (spec); return res; } @@ -763,15 +769,16 @@ handle_refresh_reveal_json (struct MHD_Connection *connection, break; for (j = 0; j < num_oldcoins; j++) { + struct GNUNET_JSON_Specification tp_spec[] = { + GNUNET_JSON_spec_fixed_auto (NULL, &transfer_privs[i][j]), + GNUNET_JSON_spec_end () + }; if (GNUNET_OK != res) break; - res = TMH_PARSE_navigate_json (connection, - tp_json, - TMH_PARSE_JNC_INDEX, (int) i, - TMH_PARSE_JNC_INDEX, (int) j, - TMH_PARSE_JNC_RET_DATA, - &transfer_privs[i][j], - sizeof (struct TALER_TransferPrivateKeyP)); + res = TMH_PARSE_json_array (connection, + tp_json, + tp_spec, + i, j, -1); GNUNET_break_op (GNUNET_OK == res); } } @@ -817,10 +824,10 @@ TMH_REFRESH_handler_refresh_reveal (struct TMH_RequestHandler *rh, json_t *reveal_detail; json_t *root; json_t *transfer_privs; - struct TMH_PARSE_FieldSpecification spec[] = { - TMH_PARSE_member_fixed ("session_hash", &session_hash), - TMH_PARSE_member_array ("transfer_privs", &transfer_privs), - TMH_PARSE_MEMBER_END + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_fixed_auto ("session_hash", &session_hash), + GNUNET_JSON_spec_json ("transfer_privs", &transfer_privs), + GNUNET_JSON_spec_end () }; res = TMH_PARSE_post_json (connection, @@ -846,30 +853,25 @@ TMH_REFRESH_handler_refresh_reveal (struct TMH_RequestHandler *rh, /* Note we do +1 as 1 row (cut-and-choose!) is missing! */ if (TALER_CNC_KAPPA != json_array_size (transfer_privs) + 1) { - TMH_PARSE_release_data (spec); + GNUNET_JSON_parse_free (spec); GNUNET_break_op (0); return TMH_RESPONSE_reply_arg_invalid (connection, "transfer_privs"); } - res = TMH_PARSE_navigate_json (connection, - transfer_privs, - TMH_PARSE_JNC_INDEX, 0, - TMH_PARSE_JNC_RET_TYPED_JSON, - JSON_ARRAY, - &reveal_detail); - if (GNUNET_OK != res) + reveal_detail = json_array_get (transfer_privs, 0); + if (NULL == reveal_detail) { - TMH_PARSE_release_data (spec); + // FIXME: generate proper HTTP response! + GNUNET_JSON_parse_free (spec); GNUNET_break_op (0); return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; } num_oldcoins = json_array_size (reveal_detail); - json_decref (reveal_detail); res = handle_refresh_reveal_json (connection, &session_hash, num_oldcoins, transfer_privs); - TMH_PARSE_release_data (spec); + GNUNET_JSON_parse_free (spec); return res; } diff --git a/src/exchange/taler-exchange-httpd_reserve.c b/src/exchange/taler-exchange-httpd_reserve.c index 45f073107..1763280ed 100644 --- a/src/exchange/taler-exchange-httpd_reserve.c +++ b/src/exchange/taler-exchange-httpd_reserve.c @@ -101,17 +101,17 @@ TMH_RESERVE_handler_reserve_withdraw (struct TMH_RequestHandler *rh, struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki; struct TMH_KS_StateHandle *ks; - struct TMH_PARSE_FieldSpecification spec[] = { - TMH_PARSE_member_variable ("coin_ev", + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_varsize ("coin_ev", (void **) &blinded_msg, &blinded_msg_len), - TMH_PARSE_member_fixed ("reserve_pub", + GNUNET_JSON_spec_fixed_auto ("reserve_pub", &wsrd.reserve_pub), - TMH_PARSE_member_fixed ("reserve_sig", + GNUNET_JSON_spec_fixed_auto ("reserve_sig", &signature), - TMH_PARSE_member_denomination_public_key ("denom_pub", + TALER_JSON_spec_denomination_public_key ("denom_pub", &denomination_pub), - TMH_PARSE_MEMBER_END + GNUNET_JSON_spec_end () }; res = TMH_PARSE_post_json (connection, @@ -135,7 +135,7 @@ TMH_RESERVE_handler_reserve_withdraw (struct TMH_RequestHandler *rh, TMH_KS_DKU_WITHDRAW); if (NULL == dki) { - TMH_PARSE_release_data (spec); + GNUNET_JSON_parse_free (spec); TMH_KS_release (ks); return TMH_RESPONSE_reply_arg_unknown (connection, "denom_pub"); @@ -169,7 +169,7 @@ TMH_RESERVE_handler_reserve_withdraw (struct TMH_RequestHandler *rh, &wsrd.reserve_pub.eddsa_pub)) { TALER_LOG_WARNING ("Client supplied invalid signature for /reserve/withdraw request\n"); - TMH_PARSE_release_data (spec); + GNUNET_JSON_parse_free (spec); return TMH_RESPONSE_reply_signature_invalid (connection, "reserve_sig"); } @@ -179,7 +179,7 @@ TMH_RESERVE_handler_reserve_withdraw (struct TMH_RequestHandler *rh, blinded_msg, blinded_msg_len, &signature); - TMH_PARSE_release_data (spec); + GNUNET_JSON_parse_free (spec); return res; } diff --git a/src/exchange/taler-exchange-httpd_test.c b/src/exchange/taler-exchange-httpd_test.c index 7b6438cae..0a4181ed8 100644 --- a/src/exchange/taler-exchange-httpd_test.c +++ b/src/exchange/taler-exchange-httpd_test.c @@ -63,9 +63,9 @@ TMH_TEST_handler_test_base32 (struct TMH_RequestHandler *rh, void *in_ptr; size_t in_ptr_size; struct GNUNET_HashCode hc; - struct TMH_PARSE_FieldSpecification spec[] = { - TMH_PARSE_member_variable ("input", &in_ptr, &in_ptr_size), - TMH_PARSE_MEMBER_END + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_varsize ("input", &in_ptr, &in_ptr_size), + GNUNET_JSON_spec_end () }; res = TMH_PARSE_post_json (connection, @@ -85,7 +85,7 @@ TMH_TEST_handler_test_base32 (struct TMH_RequestHandler *rh, GNUNET_CRYPTO_hash (in_ptr, in_ptr_size, &hc); - TMH_PARSE_release_data (spec); + GNUNET_JSON_parse_free (spec); json_decref (json); return TMH_RESPONSE_reply_json_pack (connection, MHD_HTTP_OK, @@ -126,10 +126,10 @@ TMH_TEST_handler_test_encrypt (struct TMH_RequestHandler *rh, struct GNUNET_CRYPTO_SymmetricSessionKey skey; void *in_ptr; size_t in_ptr_size; - struct TMH_PARSE_FieldSpecification spec[] = { - TMH_PARSE_member_variable ("input", &in_ptr, &in_ptr_size), - TMH_PARSE_member_fixed ("key_hash", &key), - TMH_PARSE_MEMBER_END + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_varsize ("input", &in_ptr, &in_ptr_size), + GNUNET_JSON_spec_fixed_auto ("key_hash", &key), + GNUNET_JSON_spec_end () }; char *out; @@ -168,7 +168,7 @@ TMH_TEST_handler_test_encrypt (struct TMH_RequestHandler *rh, json = GNUNET_JSON_from_data (out, in_ptr_size); GNUNET_free (out); - TMH_PARSE_release_data (spec); + GNUNET_JSON_parse_free (spec); return TMH_RESPONSE_reply_json_pack (connection, MHD_HTTP_OK, "{s:o}", @@ -206,9 +206,9 @@ TMH_TEST_handler_test_hkdf (struct TMH_RequestHandler *rh, struct GNUNET_HashCode hc; void *in_ptr; size_t in_ptr_size; - struct TMH_PARSE_FieldSpecification spec[] = { - TMH_PARSE_member_variable ("input", &in_ptr, &in_ptr_size), - TMH_PARSE_MEMBER_END + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_varsize ("input", &in_ptr, &in_ptr_size), + GNUNET_JSON_spec_end () }; res = TMH_PARSE_post_json (connection, @@ -231,7 +231,7 @@ TMH_TEST_handler_test_hkdf (struct TMH_RequestHandler *rh, in_ptr, in_ptr_size, NULL, 0); - TMH_PARSE_release_data (spec); + GNUNET_JSON_parse_free (spec); json = GNUNET_JSON_from_data (&hc, sizeof (struct GNUNET_HashCode)); return TMH_RESPONSE_reply_json_pack (connection, @@ -268,10 +268,10 @@ TMH_TEST_handler_test_ecdhe (struct TMH_RequestHandler *rh, struct GNUNET_CRYPTO_EcdhePublicKey pub; struct GNUNET_CRYPTO_EcdhePrivateKey priv; struct GNUNET_HashCode hc; - struct TMH_PARSE_FieldSpecification spec[] = { - TMH_PARSE_member_fixed ("ecdhe_pub", &pub), - TMH_PARSE_member_fixed ("ecdhe_priv", &priv), - TMH_PARSE_MEMBER_END + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_fixed_auto ("ecdhe_pub", &pub), + GNUNET_JSON_spec_fixed_auto ("ecdhe_priv", &priv), + GNUNET_JSON_spec_end () }; res = TMH_PARSE_post_json (connection, @@ -294,11 +294,11 @@ TMH_TEST_handler_test_ecdhe (struct TMH_RequestHandler *rh, &pub, &hc)) { - TMH_PARSE_release_data (spec); + GNUNET_JSON_parse_free (spec); return TMH_RESPONSE_reply_internal_error (connection, "Failed to perform ECDH"); } - TMH_PARSE_release_data (spec); + GNUNET_JSON_parse_free (spec); return TMH_RESPONSE_reply_json_pack (connection, MHD_HTTP_OK, "{s:o}", @@ -335,10 +335,10 @@ TMH_TEST_handler_test_eddsa (struct TMH_RequestHandler *rh, struct GNUNET_CRYPTO_EddsaPublicKey pub; struct GNUNET_CRYPTO_EddsaSignature sig; struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - struct TMH_PARSE_FieldSpecification spec[] = { - TMH_PARSE_member_fixed ("eddsa_pub", &pub), - TMH_PARSE_member_fixed ("eddsa_sig", &sig), - TMH_PARSE_MEMBER_END + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_fixed_auto ("eddsa_pub", &pub), + GNUNET_JSON_spec_fixed_auto ("eddsa_sig", &sig), + GNUNET_JSON_spec_end () }; struct GNUNET_CRYPTO_EddsaPrivateKey *pk; @@ -365,11 +365,11 @@ TMH_TEST_handler_test_eddsa (struct TMH_RequestHandler *rh, &sig, &pub)) { - TMH_PARSE_release_data (spec); + GNUNET_JSON_parse_free (spec); return TMH_RESPONSE_reply_signature_invalid (connection, "eddsa_sig"); } - TMH_PARSE_release_data (spec); + GNUNET_JSON_parse_free (spec); pk = GNUNET_CRYPTO_eddsa_key_create (); purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_TEST_EDDSA); if (GNUNET_OK != @@ -466,9 +466,9 @@ TMH_TEST_handler_test_rsa_sign (struct TMH_RequestHandler *rh, struct GNUNET_CRYPTO_rsa_Signature *sig; void *in_ptr; size_t in_ptr_size; - struct TMH_PARSE_FieldSpecification spec[] = { - TMH_PARSE_member_variable ("blind_ev", &in_ptr, &in_ptr_size), - TMH_PARSE_MEMBER_END + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_varsize ("blind_ev", &in_ptr, &in_ptr_size), + GNUNET_JSON_spec_end () }; res = TMH_PARSE_post_json (connection, @@ -491,7 +491,7 @@ TMH_TEST_handler_test_rsa_sign (struct TMH_RequestHandler *rh, if (NULL == rsa_pk) { GNUNET_break (0); - TMH_PARSE_release_data (spec); + GNUNET_JSON_parse_free (spec); return TMH_RESPONSE_reply_internal_error (connection, "Failed to create RSA key"); } @@ -501,11 +501,11 @@ TMH_TEST_handler_test_rsa_sign (struct TMH_RequestHandler *rh, if (NULL == sig) { GNUNET_break (0); - TMH_PARSE_release_data (spec); + GNUNET_JSON_parse_free (spec); return TMH_RESPONSE_reply_internal_error (connection, "Failed to RSA-sign"); } - TMH_PARSE_release_data (spec); + GNUNET_JSON_parse_free (spec); res = TMH_RESPONSE_reply_json_pack (connection, MHD_HTTP_OK, "{s:o}", @@ -542,11 +542,11 @@ TMH_TEST_handler_test_transfer (struct TMH_RequestHandler *rh, struct TALER_EncryptedLinkSecretP secret_enc; struct TALER_TransferPrivateKeyP trans_priv; struct TALER_CoinSpendPublicKeyP coin_pub; - struct TMH_PARSE_FieldSpecification spec[] = { - TMH_PARSE_member_fixed ("secret_enc", &secret_enc), - TMH_PARSE_member_fixed ("trans_priv", &trans_priv), - TMH_PARSE_member_fixed ("coin_pub", &coin_pub), - TMH_PARSE_MEMBER_END + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_fixed_auto ("secret_enc", &secret_enc), + GNUNET_JSON_spec_fixed_auto ("trans_priv", &trans_priv), + GNUNET_JSON_spec_fixed_auto ("coin_pub", &coin_pub), + GNUNET_JSON_spec_end () }; struct TALER_LinkSecretP secret; @@ -571,7 +571,7 @@ TMH_TEST_handler_test_transfer (struct TMH_RequestHandler *rh, &coin_pub, &secret)) { - TMH_PARSE_release_data (spec); + GNUNET_JSON_parse_free (spec); return TMH_RESPONSE_reply_internal_error (connection, "Failed to decrypt secret"); } diff --git a/src/exchange/taler-exchange-httpd_tracking.c b/src/exchange/taler-exchange-httpd_tracking.c index afb821cb9..36782332d 100644 --- a/src/exchange/taler-exchange-httpd_tracking.c +++ b/src/exchange/taler-exchange-httpd_tracking.c @@ -121,14 +121,14 @@ TMH_TRACKING_handler_deposit_wtid (struct TMH_RequestHandler *rh, struct TALER_DepositTrackPS tps; uint64_t transaction_id; struct TALER_MerchantSignatureP merchant_sig; - struct TMH_PARSE_FieldSpecification spec[] = { - TMH_PARSE_member_fixed ("H_wire", &tps.h_wire), - TMH_PARSE_member_fixed ("H_contract", &tps.h_contract), - TMH_PARSE_member_fixed ("coin_pub", &tps.coin_pub), - TMH_PARSE_member_uint64 ("transaction_id", &transaction_id), - TMH_PARSE_member_fixed ("merchant_pub", &tps.merchant), - TMH_PARSE_member_fixed ("merchant_sig", &merchant_sig), - TMH_PARSE_MEMBER_END + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_fixed_auto ("H_wire", &tps.h_wire), + GNUNET_JSON_spec_fixed_auto ("H_contract", &tps.h_contract), + GNUNET_JSON_spec_fixed_auto ("coin_pub", &tps.coin_pub), + GNUNET_JSON_spec_uint64 ("transaction_id", &transaction_id), + GNUNET_JSON_spec_fixed_auto ("merchant_pub", &tps.merchant), + GNUNET_JSON_spec_fixed_auto ("merchant_sig", &merchant_sig), + GNUNET_JSON_spec_end () }; res = TMH_PARSE_post_json (connection, @@ -156,7 +156,7 @@ TMH_TRACKING_handler_deposit_wtid (struct TMH_RequestHandler *rh, &tps.merchant, &merchant_sig, transaction_id); - TMH_PARSE_release_data (spec); + GNUNET_JSON_parse_free (spec); json_decref (json); return res; } diff --git a/src/include/taler_json_lib.h b/src/include/taler_json_lib.h index aee151b97..3dd661a91 100644 --- a/src/include/taler_json_lib.h +++ b/src/include/taler_json_lib.h @@ -57,6 +57,30 @@ TALER_JSON_spec_amount (const char *name, struct TALER_Amount *r_amount); +/** + * Generate line in parser specification for denomination public key. + * + * @param field name of the field + * @param[out] pk key to initialize + * @return corresponding field spec + */ +struct GNUNET_JSON_Specification +TALER_JSON_spec_denomination_public_key (const char *field, + struct TALER_DenominationPublicKey *pk); + + +/** + * Generate line in parser specification for denomination signature. + * + * @param field name of the field + * @param sig the signature to initialize + * @return corresponding field spec + */ +struct GNUNET_JSON_Specification +TALER_JSON_spec_denomination_signature (const char *field, + struct TALER_DenominationSignature *sig); + + /** * Hash a JSON for binary signing. * diff --git a/src/json/json_helper.c b/src/json/json_helper.c index b61fe21a6..7eaaa441a 100644 --- a/src/json/json_helper.c +++ b/src/json/json_helper.c @@ -143,4 +143,36 @@ TALER_JSON_spec_amount (const char *name, } +/** + * Generate line in parser specification for denomination public key. + * + * @param field name of the field + * @param[out] pk key to initialize + * @return corresponding field spec + */ +struct GNUNET_JSON_Specification +TALER_JSON_spec_denomination_public_key (const char *field, + struct TALER_DenominationPublicKey *pk) +{ + return GNUNET_JSON_spec_rsa_public_key (field, + &pk->rsa_public_key); +} + + +/** + * Generate line in parser specification for denomination signature. + * + * @param field name of the field + * @param sig the signature to initialize + * @return corresponding field spec + */ +struct GNUNET_JSON_Specification +TALER_JSON_spec_denomination_signature (const char *field, + struct TALER_DenominationSignature *sig) +{ + return GNUNET_JSON_spec_rsa_signature (field, + &sig->rsa_signature); +} + + /* end of json/json_helper.c */ -- cgit v1.2.3