diff options
Diffstat (limited to 'src/lib/merchant_api_get_products.c')
-rw-r--r-- | src/lib/merchant_api_get_products.c | 153 |
1 files changed, 82 insertions, 71 deletions
diff --git a/src/lib/merchant_api_get_products.c b/src/lib/merchant_api_get_products.c index c3cc30e7..c33e24c9 100644 --- a/src/lib/merchant_api_get_products.c +++ b/src/lib/merchant_api_get_products.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2018, 2020 Taler Systems SA + Copyright (C) 2014-2024 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software @@ -32,6 +32,12 @@ /** + * Maximum number of products we return. + */ +#define MAX_PRODUCTS 1024 + + +/** * Handle for a GET /products operation. */ struct TALER_MERCHANT_ProductsGetHandle @@ -67,54 +73,68 @@ struct TALER_MERCHANT_ProductsGetHandle /** * Parse product information from @a ia. * + * @param json overall JSON reply * @param ia JSON array (or NULL!) with product data * @param pgh operation handle * @return #GNUNET_OK on success */ -static int -parse_products (const json_t *ia, +static enum GNUNET_GenericReturnValue +parse_products (const json_t *json, + const json_t *ia, struct TALER_MERCHANT_ProductsGetHandle *pgh) { unsigned int ies_len = json_array_size (ia); - struct TALER_MERCHANT_InventoryEntry ies[ies_len]; - size_t index; - json_t *value; - int ret; - - ret = GNUNET_OK; - json_array_foreach (ia, index, value) { - struct TALER_MERCHANT_InventoryEntry *ie = &ies[index]; - struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_string ("product_id", - &ie->product_id), - GNUNET_JSON_spec_end () - }; - - if (GNUNET_OK != - GNUNET_JSON_parse (value, - spec, - NULL, NULL)) - { - GNUNET_break_op (0); - ret = GNUNET_SYSERR; - continue; - } - if (GNUNET_SYSERR == ret) - break; + + if ( (json_array_size (ia) != (size_t) ies_len) || + (ies_len > MAX_PRODUCTS) ) + { + GNUNET_break (0); + return GNUNET_SYSERR; } - if (GNUNET_OK == ret) { - struct TALER_MERCHANT_HttpResponse hr = { - .http_status = MHD_HTTP_OK - }; - - pgh->cb (pgh->cb_cls, - &hr, - ies_len, - ies); - pgh->cb = NULL; /* just to be sure */ + struct TALER_MERCHANT_InventoryEntry ies[GNUNET_NZL (ies_len)]; + size_t index; + json_t *value; + enum GNUNET_GenericReturnValue ret; + + ret = GNUNET_OK; + json_array_foreach (ia, index, value) { + struct TALER_MERCHANT_InventoryEntry *ie = &ies[index]; + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_string ("product_id", + &ie->product_id), + GNUNET_JSON_spec_uint64 ("product_serial", + &ie->product_serial), + GNUNET_JSON_spec_end () + }; + + if (GNUNET_OK != + GNUNET_JSON_parse (value, + spec, + NULL, NULL)) + { + GNUNET_break_op (0); + ret = GNUNET_SYSERR; + continue; + } + if (GNUNET_SYSERR == ret) + break; + } + if (GNUNET_OK == ret) + { + struct TALER_MERCHANT_GetProductsResponse gpr = { + .hr.http_status = MHD_HTTP_OK, + .hr.reply = json, + .details.ok.products_length = ies_len, + .details.ok.products = ies + }; + + pgh->cb (pgh->cb_cls, + &gpr); + pgh->cb = NULL; /* just to be sure */ + } + return ret; } - return ret; } @@ -133,9 +153,9 @@ handle_get_products_finished (void *cls, { struct TALER_MERCHANT_ProductsGetHandle *pgh = cls; const json_t *json = response; - struct TALER_MERCHANT_HttpResponse hr = { - .http_status = (unsigned int) response_code, - .reply = json + struct TALER_MERCHANT_GetProductsResponse gpr = { + .hr.http_status = (unsigned int) response_code, + .hr.reply = json }; pgh->job = NULL; @@ -146,10 +166,10 @@ handle_get_products_finished (void *cls, { case MHD_HTTP_OK: { - json_t *products; + const json_t *products; struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_json ("products", - &products), + GNUNET_JSON_spec_array_const ("products", + &products), GNUNET_JSON_spec_end () }; @@ -158,48 +178,39 @@ handle_get_products_finished (void *cls, spec, NULL, NULL)) { - hr.http_status = 0; - hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; + gpr.hr.http_status = 0; + gpr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; + break; } - else + if (GNUNET_OK == + parse_products (json, + products, + pgh)) { - if ( (! json_is_array (products)) || - (GNUNET_OK == - parse_products (products, - pgh)) ) - { - GNUNET_JSON_parse_free (spec); - TALER_MERCHANT_products_get_cancel (pgh); - return; - } - else - { - hr.http_status = 0; - hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; - } + TALER_MERCHANT_products_get_cancel (pgh); + return; } - GNUNET_JSON_parse_free (spec); + gpr.hr.http_status = 0; + gpr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; break; } case MHD_HTTP_UNAUTHORIZED: - hr.ec = TALER_JSON_get_error_code (json); - hr.hint = TALER_JSON_get_error_hint (json); + gpr.hr.ec = TALER_JSON_get_error_code (json); + gpr.hr.hint = TALER_JSON_get_error_hint (json); /* Nothing really to verify, merchant says we need to authenticate. */ break; default: /* unexpected response code */ - hr.ec = TALER_JSON_get_error_code (json); - hr.hint = TALER_JSON_get_error_hint (json); + gpr.hr.ec = TALER_JSON_get_error_code (json); + gpr.hr.hint = TALER_JSON_get_error_hint (json); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unexpected response code %u/%d\n", (unsigned int) response_code, - (int) hr.ec); + (int) gpr.hr.ec); break; } pgh->cb (pgh->cb_cls, - &hr, - 0, - NULL); + &gpr); TALER_MERCHANT_products_get_cancel (pgh); } |