donau

Donation authority for GNU Taler (experimental)
Log | Files | Refs | Submodules | README | LICENSE

commit d2bebbac2b5cc38326190a552bac4f56f52c7c4d
parent 0f8fc79f2e3251f7e0395a96698122d6e3a8f669
Author: Pius Loosli <loosp2@bfh.ch>
Date:   Mon, 27 Nov 2023 13:11:03 +0100

[build] pq: temporarily comment out unused codelines in order to build someday

Diffstat:
Msrc/pq/pq_query_helper.c | 2306++++++++++++++++++++++++++++++++++++++++----------------------------------------
Msrc/pq/pq_result_helper.c | 2800++++++++++++++++++++++++++++++++++++++++----------------------------------------
2 files changed, 2553 insertions(+), 2553 deletions(-)

diff --git a/src/pq/pq_query_helper.c b/src/pq/pq_query_helper.c @@ -26,1156 +26,1156 @@ #include <taler/taler_pq_lib.h> -/** - * Function called to convert input amount into SQL parameter as tuple. - * - * @param cls closure - * @param data pointer to input argument, here a `struct TALER_Amount` - * @param data_len number of bytes in @a data (if applicable) - * @param[out] param_values SQL data to set - * @param[out] param_lengths SQL length data to set - * @param[out] param_formats SQL format data to set - * @param param_length number of entries available in the @a param_values, @a param_lengths and @a param_formats arrays - * @param[out] scratch buffer for dynamic allocations (to be done via GNUNET_malloc() - * @param scratch_length number of entries left in @a scratch - * @return -1 on error, number of offsets used in @a scratch otherwise - */ -static int -qconv_amount_currency_tuple (void *cls, - const void *data, - size_t data_len, - void *param_values[], - int param_lengths[], - int param_formats[], - unsigned int param_length, - void *scratch[], - unsigned int scratch_length) -{ - struct GNUNET_PQ_Context *db = cls; - const struct TALER_Amount *amount = data; - size_t sz; - - GNUNET_assert (NULL != db); - GNUNET_assert (NULL != amount); - GNUNET_assert (1 == param_length); - GNUNET_assert (1 <= scratch_length); - GNUNET_assert (sizeof (struct TALER_Amount) == data_len); - GNUNET_static_assert (sizeof(uint32_t) == sizeof(Oid)); - { - char *out; - Oid oid_v; - Oid oid_f; - Oid oid_c; - struct TALER_PQ_AmountCurrencyP d; - - GNUNET_assert (GNUNET_OK == - GNUNET_PQ_get_oid_by_name (db, - "int8", - &oid_v)); - GNUNET_assert (GNUNET_OK == - GNUNET_PQ_get_oid_by_name (db, - "int4", - &oid_f)); - GNUNET_assert (GNUNET_OK == - GNUNET_PQ_get_oid_by_name (db, - "varchar", - &oid_c)); - sz = TALER_PQ_make_taler_pq_amount_currency_ (amount, - oid_v, - oid_f, - oid_c, - &d); - out = GNUNET_malloc (sz); - memcpy (out, - &d, - sz); - scratch[0] = out; - } - - param_values[0] = scratch[0]; - param_lengths[0] = sz; - param_formats[0] = 1; - - return 1; -} - - -struct GNUNET_PQ_QueryParam -TALER_PQ_query_param_amount_with_currency ( - const struct GNUNET_PQ_Context *db, - const struct TALER_Amount *amount) -{ - struct GNUNET_PQ_QueryParam res = { - .conv_cls = (void *) db, - .conv = &qconv_amount_currency_tuple, - .data = amount, - .size = sizeof (*amount), - .num_params = 1, - }; - - return res; -} - - -/** - * Function called to convert input amount into SQL parameter as tuple. - * - * @param cls closure - * @param data pointer to input argument, here a `struct TALER_Amount` - * @param data_len number of bytes in @a data (if applicable) - * @param[out] param_values SQL data to set - * @param[out] param_lengths SQL length data to set - * @param[out] param_formats SQL format data to set - * @param param_length number of entries available in the @a param_values, @a param_lengths and @a param_formats arrays - * @param[out] scratch buffer for dynamic allocations (to be done via GNUNET_malloc() - * @param scratch_length number of entries left in @a scratch - * @return -1 on error, number of offsets used in @a scratch otherwise - */ -static int -qconv_amount_tuple (void *cls, - const void *data, - size_t data_len, - void *param_values[], - int param_lengths[], - int param_formats[], - unsigned int param_length, - void *scratch[], - unsigned int scratch_length) -{ - struct GNUNET_PQ_Context *db = cls; - const struct TALER_Amount *amount = data; - size_t sz; - - GNUNET_assert (NULL != db); - GNUNET_assert (NULL != amount); - GNUNET_assert (1 == param_length); - GNUNET_assert (1 <= scratch_length); - GNUNET_assert (sizeof (struct TALER_Amount) == data_len); - GNUNET_static_assert (sizeof(uint32_t) == sizeof(Oid)); - { - char *out; - Oid oid_v; - Oid oid_f; - - GNUNET_assert (GNUNET_OK == - GNUNET_PQ_get_oid_by_name (db, - "int8", - &oid_v)); - GNUNET_assert (GNUNET_OK == - GNUNET_PQ_get_oid_by_name (db, - "int4", - &oid_f)); - - { - struct TALER_PQ_AmountP d - = TALER_PQ_make_taler_pq_amount_ (amount, - oid_v, - oid_f); - - sz = sizeof(d); - out = GNUNET_malloc (sz); - scratch[0] = out; - GNUNET_memcpy (out, - &d, - sizeof(d)); - } - } - - param_values[0] = scratch[0]; - param_lengths[0] = sz; - param_formats[0] = 1; - - return 1; -} - - -struct GNUNET_PQ_QueryParam -TALER_PQ_query_param_amount ( - const struct GNUNET_PQ_Context *db, - const struct TALER_Amount *amount) -{ - struct GNUNET_PQ_QueryParam res = { - .conv_cls = (void *) db, - .conv = &qconv_amount_tuple, - .data = amount, - .size = sizeof (*amount), - .num_params = 1, - }; - - return res; -} - - -/** - * Function called to convert input argument into SQL parameters. - * - * @param cls closure - * @param data pointer to input argument - * @param data_len number of bytes in @a data (if applicable) - * @param[out] param_values SQL data to set - * @param[out] param_lengths SQL length data to set - * @param[out] param_formats SQL format data to set - * @param param_length number of entries available in the @a param_values, @a param_lengths and @a param_formats arrays - * @param[out] scratch buffer for dynamic allocations (to be done via #GNUNET_malloc() - * @param scratch_length number of entries left in @a scratch - * @return -1 on error, number of offsets used in @a scratch otherwise - */ -static int -qconv_denom_pub (void *cls, - const void *data, - size_t data_len, - void *param_values[], - int param_lengths[], - int param_formats[], - unsigned int param_length, - void *scratch[], - unsigned int scratch_length) -{ - const struct TALER_DenominationPublicKey *denom_pub = data; - size_t tlen; - size_t len; - uint32_t be[2]; - char *buf; - void *tbuf; - - (void) cls; - (void) data_len; - GNUNET_assert (1 == param_length); - GNUNET_assert (scratch_length > 0); - GNUNET_break (NULL == cls); - be[0] = htonl ((uint32_t) denom_pub->cipher); - be[1] = htonl (denom_pub->age_mask.bits); - switch (denom_pub->cipher) - { - case TALER_DENOMINATION_RSA: - tlen = GNUNET_CRYPTO_rsa_public_key_encode ( - denom_pub->details.rsa_public_key, - &tbuf); - break; - case TALER_DENOMINATION_CS: - tlen = sizeof (denom_pub->details.cs_public_key); - break; - default: - GNUNET_assert (0); - } - len = tlen + sizeof (be); - buf = GNUNET_malloc (len); - GNUNET_memcpy (buf, - be, - sizeof (be)); - switch (denom_pub->cipher) - { - case TALER_DENOMINATION_RSA: - GNUNET_memcpy (&buf[sizeof (be)], - tbuf, - tlen); - GNUNET_free (tbuf); - break; - case TALER_DENOMINATION_CS: - GNUNET_memcpy (&buf[sizeof (be)], - &denom_pub->details.cs_public_key, - tlen); - break; - default: - GNUNET_assert (0); - } - - scratch[0] = buf; - param_values[0] = (void *) buf; - param_lengths[0] = len; - param_formats[0] = 1; - return 1; -} - - -struct GNUNET_PQ_QueryParam -TALER_PQ_query_param_denom_pub ( - const struct TALER_DenominationPublicKey *denom_pub) -{ - struct GNUNET_PQ_QueryParam res = { - .conv = &qconv_denom_pub, - .data = denom_pub, - .num_params = 1 - }; - - return res; -} - - -/** - * Function called to convert input argument into SQL parameters. - * - * @param cls closure - * @param data pointer to input argument - * @param data_len number of bytes in @a data (if applicable) - * @param[out] param_values SQL data to set - * @param[out] param_lengths SQL length data to set - * @param[out] param_formats SQL format data to set - * @param param_length number of entries available in the @a param_values, @a param_lengths and @a param_formats arrays - * @param[out] scratch buffer for dynamic allocations (to be done via #GNUNET_malloc() - * @param scratch_length number of entries left in @a scratch - * @return -1 on error, number of offsets used in @a scratch otherwise - */ -static int -qconv_denom_sig (void *cls, - const void *data, - size_t data_len, - void *param_values[], - int param_lengths[], - int param_formats[], - unsigned int param_length, - void *scratch[], - unsigned int scratch_length) -{ - const struct TALER_DenominationSignature *denom_sig = data; - size_t tlen; - size_t len; - uint32_t be[2]; - char *buf; - void *tbuf; - - (void) cls; - (void) data_len; - GNUNET_assert (1 == param_length); - GNUNET_assert (scratch_length > 0); - GNUNET_break (NULL == cls); - be[0] = htonl ((uint32_t) denom_sig->cipher); - be[1] = htonl (0x00); /* magic marker: unblinded */ - switch (denom_sig->cipher) - { - case TALER_DENOMINATION_RSA: - tlen = GNUNET_CRYPTO_rsa_signature_encode ( - denom_sig->details.rsa_signature, - &tbuf); - break; - case TALER_DENOMINATION_CS: - tlen = sizeof (denom_sig->details.cs_signature); - break; - default: - GNUNET_assert (0); - } - len = tlen + sizeof (be); - buf = GNUNET_malloc (len); - GNUNET_memcpy (buf, - &be, - sizeof (be)); - switch (denom_sig->cipher) - { - case TALER_DENOMINATION_RSA: - GNUNET_memcpy (&buf[sizeof (be)], - tbuf, - tlen); - GNUNET_free (tbuf); - break; - case TALER_DENOMINATION_CS: - GNUNET_memcpy (&buf[sizeof (be)], - &denom_sig->details.cs_signature, - tlen); - break; - default: - GNUNET_assert (0); - } - - scratch[0] = buf; - param_values[0] = (void *) buf; - param_lengths[0] = len; - param_formats[0] = 1; - return 1; -} - - -struct GNUNET_PQ_QueryParam -TALER_PQ_query_param_denom_sig ( - const struct TALER_DenominationSignature *denom_sig) -{ - struct GNUNET_PQ_QueryParam res = { - .conv = &qconv_denom_sig, - .data = denom_sig, - .num_params = 1 - }; - - return res; -} - - -/** - * Function called to convert input argument into SQL parameters. - * - * @param cls closure - * @param data pointer to input argument - * @param data_len number of bytes in @a data (if applicable) - * @param[out] param_values SQL data to set - * @param[out] param_lengths SQL length data to set - * @param[out] param_formats SQL format data to set - * @param param_length number of entries available in the @a param_values, @a param_lengths and @a param_formats arrays - * @param[out] scratch buffer for dynamic allocations (to be done via #GNUNET_malloc() - * @param scratch_length number of entries left in @a scratch - * @return -1 on error, number of offsets used in @a scratch otherwise - */ -static int -qconv_blinded_denom_sig (void *cls, - const void *data, - size_t data_len, - void *param_values[], - int param_lengths[], - int param_formats[], - unsigned int param_length, - void *scratch[], - unsigned int scratch_length) -{ - const struct TALER_BlindedDenominationSignature *denom_sig = data; - size_t tlen; - size_t len; - uint32_t be[2]; - char *buf; - void *tbuf; - - (void) cls; - (void) data_len; - GNUNET_assert (1 == param_length); - GNUNET_assert (scratch_length > 0); - GNUNET_break (NULL == cls); - be[0] = htonl ((uint32_t) denom_sig->cipher); - be[1] = htonl (0x01); /* magic marker: blinded */ - switch (denom_sig->cipher) - { - case TALER_DENOMINATION_RSA: - tlen = GNUNET_CRYPTO_rsa_signature_encode ( - denom_sig->details.blinded_rsa_signature, - &tbuf); - break; - case TALER_DENOMINATION_CS: - tlen = sizeof (denom_sig->details.blinded_cs_answer); - break; - default: - GNUNET_assert (0); - } - len = tlen + sizeof (be); - buf = GNUNET_malloc (len); - GNUNET_memcpy (buf, - &be, - sizeof (be)); - switch (denom_sig->cipher) - { - case TALER_DENOMINATION_RSA: - GNUNET_memcpy (&buf[sizeof (be)], - tbuf, - tlen); - GNUNET_free (tbuf); - break; - case TALER_DENOMINATION_CS: - GNUNET_memcpy (&buf[sizeof (be)], - &denom_sig->details.blinded_cs_answer, - tlen); - break; - default: - GNUNET_assert (0); - } - - scratch[0] = buf; - param_values[0] = (void *) buf; - param_lengths[0] = len; - param_formats[0] = 1; - return 1; -} - - -struct GNUNET_PQ_QueryParam -TALER_PQ_query_param_blinded_denom_sig ( - const struct TALER_BlindedDenominationSignature *denom_sig) -{ - struct GNUNET_PQ_QueryParam res = { - .conv = &qconv_blinded_denom_sig, - .data = denom_sig, - .num_params = 1 - }; - - return res; -} - - -/** - * Function called to convert input argument into SQL parameters. - * - * @param cls closure - * @param data pointer to input argument - * @param data_len number of bytes in @a data (if applicable) - * @param[out] param_values SQL data to set - * @param[out] param_lengths SQL length data to set - * @param[out] param_formats SQL format data to set - * @param param_length number of entries available in the @a param_values, @a param_lengths and @a param_formats arrays - * @param[out] scratch buffer for dynamic allocations (to be done via #GNUNET_malloc() - * @param scratch_length number of entries left in @a scratch - * @return -1 on error, number of offsets used in @a scratch otherwise - */ -static int -qconv_blinded_planchet (void *cls, - const void *data, - size_t data_len, - void *param_values[], - int param_lengths[], - int param_formats[], - unsigned int param_length, - void *scratch[], - unsigned int scratch_length) -{ - const struct TALER_BlindedPlanchet *bp = data; - size_t tlen; - size_t len; - uint32_t be[2]; - char *buf; - - (void) cls; - (void) data_len; - GNUNET_assert (1 == param_length); - GNUNET_assert (scratch_length > 0); - GNUNET_break (NULL == cls); - be[0] = htonl ((uint32_t) bp->cipher); - be[1] = htonl (0x0100); /* magic marker: blinded */ - switch (bp->cipher) - { - case TALER_DENOMINATION_RSA: - tlen = bp->details.rsa_blinded_planchet.blinded_msg_size; - break; - case TALER_DENOMINATION_CS: - tlen = sizeof (bp->details.cs_blinded_planchet); - break; - default: - GNUNET_assert (0); - } - len = tlen + sizeof (be); - buf = GNUNET_malloc (len); - GNUNET_memcpy (buf, - &be, - sizeof (be)); - switch (bp->cipher) - { - case TALER_DENOMINATION_RSA: - GNUNET_memcpy (&buf[sizeof (be)], - bp->details.rsa_blinded_planchet.blinded_msg, - tlen); - break; - case TALER_DENOMINATION_CS: - GNUNET_memcpy (&buf[sizeof (be)], - &bp->details.cs_blinded_planchet, - tlen); - break; - default: - GNUNET_assert (0); - } - scratch[0] = buf; - param_values[0] = (void *) buf; - param_lengths[0] = len; - param_formats[0] = 1; - return 1; -} - - -struct GNUNET_PQ_QueryParam -TALER_PQ_query_param_blinded_planchet ( - const struct TALER_BlindedPlanchet *bp) -{ - struct GNUNET_PQ_QueryParam res = { - .conv = &qconv_blinded_planchet, - .data = bp, - .num_params = 1 - }; - - return res; -} - - -/** - * Function called to convert input argument into SQL parameters. - * - * @param cls closure - * @param data pointer to input argument - * @param data_len number of bytes in @a data (if applicable) - * @param[out] param_values SQL data to set - * @param[out] param_lengths SQL length data to set - * @param[out] param_formats SQL format data to set - * @param param_length number of entries available in the @a param_values, @a param_lengths and @a param_formats arrays - * @param[out] scratch buffer for dynamic allocations (to be done via #GNUNET_malloc() - * @param scratch_length number of entries left in @a scratch - * @return -1 on error, number of offsets used in @a scratch otherwise - */ -static int -qconv_exchange_withdraw_values (void *cls, - const void *data, - size_t data_len, - void *param_values[], - int param_lengths[], - int param_formats[], - unsigned int param_length, - void *scratch[], - unsigned int scratch_length) -{ - const struct TALER_ExchangeWithdrawValues *alg_values = data; - size_t tlen; - size_t len; - uint32_t be[2]; - char *buf; - - (void) cls; - (void) data_len; - GNUNET_assert (1 == param_length); - GNUNET_assert (scratch_length > 0); - GNUNET_break (NULL == cls); - be[0] = htonl ((uint32_t) alg_values->cipher); - be[1] = htonl (0x010000); /* magic marker: EWV */ - switch (alg_values->cipher) - { - case TALER_DENOMINATION_RSA: - tlen = 0; - break; - case TALER_DENOMINATION_CS: - tlen = sizeof (struct TALER_DenominationCSPublicRPairP); - break; - default: - GNUNET_assert (0); - } - len = tlen + sizeof (be); - buf = GNUNET_malloc (len); - GNUNET_memcpy (buf, - &be, - sizeof (be)); - switch (alg_values->cipher) - { - case TALER_DENOMINATION_RSA: - break; - case TALER_DENOMINATION_CS: - GNUNET_memcpy (&buf[sizeof (be)], - &alg_values->details.cs_values, - tlen); - break; - default: - GNUNET_assert (0); - } - scratch[0] = buf; - param_values[0] = (void *) buf; - param_lengths[0] = len; - param_formats[0] = 1; - return 1; -} - - -struct GNUNET_PQ_QueryParam -TALER_PQ_query_param_exchange_withdraw_values ( - const struct TALER_ExchangeWithdrawValues *alg_values) -{ - struct GNUNET_PQ_QueryParam res = { - .conv = &qconv_exchange_withdraw_values, - .data = alg_values, - .num_params = 1 - }; - - return res; -} - - -/** - * Function called to convert input argument into SQL parameters. - * - * @param cls closure - * @param data pointer to input argument, here a `json_t *` - * @param data_len number of bytes in @a data (if applicable) - * @param[out] param_values SQL data to set - * @param[out] param_lengths SQL length data to set - * @param[out] param_formats SQL format data to set - * @param param_length number of entries available in the @a param_values, @a param_lengths and @a param_formats arrays - * @param[out] scratch buffer for dynamic allocations (to be done via GNUNET_malloc() - * @param scratch_length number of entries left in @a scratch - * @return -1 on error, number of offsets used in @a scratch otherwise - */ -static int -qconv_json (void *cls, - const void *data, - size_t data_len, - void *param_values[], - int param_lengths[], - int param_formats[], - unsigned int param_length, - void *scratch[], - unsigned int scratch_length) -{ - const json_t *json = data; - char *str; - - (void) cls; - (void) data_len; - GNUNET_assert (1 == param_length); - GNUNET_assert (scratch_length > 0); - str = json_dumps (json, JSON_COMPACT); - if (NULL == str) - return -1; - scratch[0] = str; - param_values[0] = (void *) str; - param_lengths[0] = strlen (str); - param_formats[0] = 1; - return 1; -} - - -struct GNUNET_PQ_QueryParam -TALER_PQ_query_param_json (const json_t *x) -{ - struct GNUNET_PQ_QueryParam res = { - .conv = &qconv_json, - .data = x, - .num_params = 1 - }; - - return res; -} - - -/** ------------------- Array support -----------------------------------**/ - -/** - * Closure for the array type handlers. - * - * May contain sizes information for the data, given (and handled) by the - * caller. - */ -struct qconv_array_cls -{ - /** - * If not null, contains the array of sizes (the size of the array is the - * .size field in the ambient GNUNET_PQ_QueryParam struct). We do not free - * this memory. - * - * If not null, this value has precedence over @a sizes, which MUST be NULL */ - const size_t *sizes; - - /** - * If @a size and @a c_sizes are NULL, this field defines the same size - * for each element in the array. - */ - size_t same_size; - - /** - * If true, the array parameter to the data pointer to the qconv_array is a - * continuous byte array of data, either with @a same_size each or sizes - * provided bytes by @a sizes; - */ - bool continuous; - - /** - * Type of the array elements - */ - enum TALER_PQ_ArrayType typ; - - /** - * Oid of the array elements - */ - Oid oid; - - /** - * db context, needed for OID-lookup of basis-types - */ - struct GNUNET_PQ_Context *db; -}; - -/** - * Callback to cleanup a qconv_array_cls to be used during - * GNUNET_PQ_cleanup_query_params_closures - */ -static void -qconv_array_cls_cleanup (void *cls) -{ - GNUNET_free (cls); -} - - -/** - * Function called to convert input argument into SQL parameters for arrays - * - * Note: the format for the encoding of arrays for libpq is not very well - * documented. We peeked into various sources (postgresql and libpqtypes) for - * guidance. - * - * @param cls Closure of type struct qconv_array_cls* - * @param data Pointer to first element in the array - * @param data_len Number of _elements_ in array @a data (if applicable) - * @param[out] param_values SQL data to set - * @param[out] param_lengths SQL length data to set - * @param[out] param_formats SQL format data to set - * @param param_length number of entries available in the @a param_values, @a param_lengths and @a param_formats arrays - * @param[out] scratch buffer for dynamic allocations (to be done via #GNUNET_malloc() - * @param scratch_length number of entries left in @a scratch - * @return -1 on error, number of offsets used in @a scratch otherwise - */ -static int -qconv_array ( - void *cls, - const void *data, - size_t data_len, - void *param_values[], - int param_lengths[], - int param_formats[], - unsigned int param_length, - void *scratch[], - unsigned int scratch_length) -{ - struct qconv_array_cls *meta = cls; - size_t num = data_len; - size_t total_size; - const size_t *sizes; - bool same_sized; - void *elements = NULL; - bool noerror = true; - /* needed to capture the encoded rsa signatures */ - void **buffers = NULL; - size_t *buffer_lengths = NULL; - - (void) (param_length); - (void) (scratch_length); - - GNUNET_assert (NULL != meta); - GNUNET_assert (num < INT_MAX); - - sizes = meta->sizes; - same_sized = (0 != meta->same_size); - -#define RETURN_UNLESS(cond) \ - do { \ - if (! (cond)) \ - { \ - GNUNET_break ((cond)); \ - noerror = false; \ - goto DONE; \ - } \ - } while (0) - - /* Calculate sizes and check bounds */ - { - /* num * length-field */ - size_t x = sizeof(uint32_t); - size_t y = x * num; - RETURN_UNLESS ((0 == num) || (y / num == x)); - - /* size of header */ - total_size = x = sizeof(struct GNUNET_PQ_ArrayHeader_P); - total_size += y; - RETURN_UNLESS (total_size >= x); - - /* sizes of elements */ - if (same_sized) - { - x = num * meta->same_size; - RETURN_UNLESS ((0 == num) || (x / num == meta->same_size)); - - y = total_size; - total_size += x; - RETURN_UNLESS (total_size >= y); - } - else /* sizes are different per element */ - { - switch (meta->typ) - { - case TALER_PQ_array_of_blinded_denom_sig: - { - const struct TALER_BlindedDenominationSignature *denom_sigs = data; - size_t len; - - buffers = GNUNET_new_array (num, void *); - buffer_lengths = GNUNET_new_array (num, size_t); - - for (size_t i = 0; i<num; i++) - { - switch (denom_sigs[i].cipher) - { - case TALER_DENOMINATION_RSA: - len = GNUNET_CRYPTO_rsa_signature_encode ( - denom_sigs[i].details.blinded_rsa_signature, - &buffers[i]); - RETURN_UNLESS (len != 0); - break; - case TALER_DENOMINATION_CS: - len = sizeof (denom_sigs[i].details.blinded_cs_answer); - break; - default: - GNUNET_assert (0); - } - - /* for the cipher and marker */ - len += 2 * sizeof(uint32_t); - buffer_lengths[i] = len; - - y = total_size; - total_size += len; - RETURN_UNLESS (total_size >= y); - } - sizes = buffer_lengths; - break; - } - default: - GNUNET_assert (0); - } - } - - RETURN_UNLESS (INT_MAX > total_size); - RETURN_UNLESS (0 != total_size); - - elements = GNUNET_malloc (total_size); - } - - /* Write data */ - { - char *out = elements; - struct GNUNET_PQ_ArrayHeader_P h = { - .ndim = htonl (1), /* We only support one-dimensional arrays */ - .has_null = htonl (0), /* We do not support NULL entries in arrays */ - .lbound = htonl (1), /* Default start index value */ - .dim = htonl (num), - .oid = htonl (meta->oid), - }; - - /* Write header */ - GNUNET_memcpy (out, - &h, - sizeof(h)); - out += sizeof(h); - - /* Write elements */ - for (size_t i = 0; i < num; i++) - { - size_t sz = same_sized ? meta->same_size : sizes[i]; - - *(uint32_t *) out = htonl (sz); - out += sizeof(uint32_t); - switch (meta->typ) - { - case TALER_PQ_array_of_amount: - { - const struct TALER_Amount *amounts = data; - Oid oid_v; - Oid oid_f; - - GNUNET_assert (GNUNET_OK == - GNUNET_PQ_get_oid_by_name (meta->db, - "int8", - &oid_v)); - GNUNET_assert (GNUNET_OK == - GNUNET_PQ_get_oid_by_name (meta->db, - "int4", - &oid_f)); - { - struct TALER_PQ_AmountP am - = TALER_PQ_make_taler_pq_amount_ ( - &amounts[i], - oid_v, - oid_f); - - GNUNET_memcpy (out, - &am, - sizeof(am)); - } - break; - } - case TALER_PQ_array_of_blinded_denom_sig: - { - const struct TALER_BlindedDenominationSignature *denom_sigs = data; - uint32_t be[2]; - - be[0] = htonl ((uint32_t) denom_sigs[i].cipher); - be[1] = htonl (0x01); /* magic margker: blinded */ - GNUNET_memcpy (out, - &be, - sizeof(be)); - out += sizeof(be); - sz -= sizeof(be); - - switch (denom_sigs[i].cipher) - { - case TALER_DENOMINATION_RSA: - /* For RSA, 'same_sized' must have been false */ - GNUNET_assert (NULL != buffers); - GNUNET_memcpy (out, - buffers[i], - sz); - break; - case TALER_DENOMINATION_CS: - GNUNET_memcpy (out, - &denom_sigs[i].details.blinded_cs_answer, - sz); - break; - default: - GNUNET_assert (0); - } - break; - } - case TALER_PQ_array_of_blinded_coin_hash: - { - const struct TALER_BlindedCoinHashP *coin_hs = data; - - GNUNET_memcpy (out, - &coin_hs[i], - sizeof(struct TALER_BlindedCoinHashP)); - - break; - } - case TALER_PQ_array_of_denom_hash: - { - const struct TALER_DenominationHashP *denom_hs = data; - - GNUNET_memcpy (out, - &denom_hs[i], - sizeof(struct TALER_DenominationHashP)); - break; - } - default: - { - GNUNET_assert (0); - break; - } - } - out += sz; - } - } - param_values[0] = elements; - param_lengths[0] = total_size; - param_formats[0] = 1; - scratch[0] = elements; - -DONE: - if (NULL != buffers) - { - for (size_t i = 0; i<num; i++) - GNUNET_free (buffers[i]); - GNUNET_free (buffers); - } - GNUNET_free (buffer_lengths); - if (noerror) - return 1; - return -1; -} - - -/** - * Function to generate a typ specific query parameter and corresponding closure - * - * @param num Number of elements in @a elements - * @param continuous If true, @a elements is an continuous array of data - * @param elements Array of @a num elements, either continuous or pointers - * @param sizes Array of @a num sizes, one per element, may be NULL - * @param same_size If not 0, all elements in @a elements have this size - * @param typ Supported internal type of each element in @a elements - * @param oid Oid of the type to be used in Postgres - * @param[in,out] db our database handle for looking up OIDs - * @return Query parameter - */ -static struct GNUNET_PQ_QueryParam -query_param_array_generic ( - unsigned int num, - bool continuous, - const void *elements, - const size_t *sizes, - size_t same_size, - enum TALER_PQ_ArrayType typ, - Oid oid, - struct GNUNET_PQ_Context *db) -{ - struct qconv_array_cls *meta = GNUNET_new (struct qconv_array_cls); - meta->typ = typ; - meta->oid = oid; - meta->sizes = sizes; - meta->same_size = same_size; - meta->continuous = continuous; - meta->db = db; - - struct GNUNET_PQ_QueryParam res = { - .conv = qconv_array, - .conv_cls = meta, - .conv_cls_cleanup = qconv_array_cls_cleanup, - .data = elements, - .size = num, - .num_params = 1, - }; - - return res; -} - - -struct GNUNET_PQ_QueryParam -TALER_PQ_query_param_array_blinded_denom_sig ( - size_t num, - const struct TALER_BlindedDenominationSignature *denom_sigs, - struct GNUNET_PQ_Context *db) -{ - Oid oid; - GNUNET_assert (GNUNET_OK == - GNUNET_PQ_get_oid_by_name (db, "bytea", &oid)); - return query_param_array_generic (num, - true, - denom_sigs, - NULL, - 0, - TALER_PQ_array_of_blinded_denom_sig, - oid, - NULL); -} - - -struct GNUNET_PQ_QueryParam -TALER_PQ_query_param_array_blinded_coin_hash ( - size_t num, - const struct TALER_BlindedCoinHashP *coin_hs, - struct GNUNET_PQ_Context *db) -{ - Oid oid; - GNUNET_assert (GNUNET_OK == - GNUNET_PQ_get_oid_by_name (db, "bytea", &oid)); - return query_param_array_generic (num, - true, - coin_hs, - NULL, - sizeof(struct TALER_BlindedCoinHashP), - TALER_PQ_array_of_blinded_coin_hash, - oid, - NULL); -} - - -struct GNUNET_PQ_QueryParam -TALER_PQ_query_param_array_denom_hash ( - size_t num, - const struct TALER_DenominationHashP *denom_hs, - struct GNUNET_PQ_Context *db) -{ - Oid oid; - GNUNET_assert (GNUNET_OK == - GNUNET_PQ_get_oid_by_name (db, "bytea", &oid)); - return query_param_array_generic (num, - true, - denom_hs, - NULL, - sizeof(struct TALER_DenominationHashP), - TALER_PQ_array_of_denom_hash, - oid, - NULL); -} - - -struct GNUNET_PQ_QueryParam -TALER_PQ_query_param_array_amount ( - size_t num, - const struct TALER_Amount *amounts, - struct GNUNET_PQ_Context *db) -{ - Oid oid; - GNUNET_assert (GNUNET_OK == - GNUNET_PQ_get_oid_by_name (db, "taler_amount", &oid)); - return query_param_array_generic ( - num, - true, - amounts, - NULL, - sizeof(struct TALER_PQ_AmountP), - TALER_PQ_array_of_amount, - oid, - db); -} - - -/* end of pq/pq_query_helper.c */ +// /** +// * Function called to convert input amount into SQL parameter as tuple. +// * +// * @param cls closure +// * @param data pointer to input argument, here a `struct TALER_Amount` +// * @param data_len number of bytes in @a data (if applicable) +// * @param[out] param_values SQL data to set +// * @param[out] param_lengths SQL length data to set +// * @param[out] param_formats SQL format data to set +// * @param param_length number of entries available in the @a param_values, @a param_lengths and @a param_formats arrays +// * @param[out] scratch buffer for dynamic allocations (to be done via GNUNET_malloc() +// * @param scratch_length number of entries left in @a scratch +// * @return -1 on error, number of offsets used in @a scratch otherwise +// */ +// static int +// qconv_amount_currency_tuple (void *cls, +// const void *data, +// size_t data_len, +// void *param_values[], +// int param_lengths[], +// int param_formats[], +// unsigned int param_length, +// void *scratch[], +// unsigned int scratch_length) +// { +// struct GNUNET_PQ_Context *db = cls; +// const struct TALER_Amount *amount = data; +// size_t sz; + +// GNUNET_assert (NULL != db); +// GNUNET_assert (NULL != amount); +// GNUNET_assert (1 == param_length); +// GNUNET_assert (1 <= scratch_length); +// GNUNET_assert (sizeof (struct TALER_Amount) == data_len); +// GNUNET_static_assert (sizeof(uint32_t) == sizeof(Oid)); +// { +// char *out; +// Oid oid_v; +// Oid oid_f; +// Oid oid_c; +// struct TALER_PQ_AmountCurrencyP d; + +// GNUNET_assert (GNUNET_OK == +// GNUNET_PQ_get_oid_by_name (db, +// "int8", +// &oid_v)); +// GNUNET_assert (GNUNET_OK == +// GNUNET_PQ_get_oid_by_name (db, +// "int4", +// &oid_f)); +// GNUNET_assert (GNUNET_OK == +// GNUNET_PQ_get_oid_by_name (db, +// "varchar", +// &oid_c)); +// sz = TALER_PQ_make_taler_pq_amount_currency_ (amount, +// oid_v, +// oid_f, +// oid_c, +// &d); +// out = GNUNET_malloc (sz); +// memcpy (out, +// &d, +// sz); +// scratch[0] = out; +// } + +// param_values[0] = scratch[0]; +// param_lengths[0] = sz; +// param_formats[0] = 1; + +// return 1; +// } + + +// struct GNUNET_PQ_QueryParam +// TALER_PQ_query_param_amount_with_currency ( +// const struct GNUNET_PQ_Context *db, +// const struct TALER_Amount *amount) +// { +// struct GNUNET_PQ_QueryParam res = { +// .conv_cls = (void *) db, +// .conv = &qconv_amount_currency_tuple, +// .data = amount, +// .size = sizeof (*amount), +// .num_params = 1, +// }; + +// return res; +// } + + +// /** +// * Function called to convert input amount into SQL parameter as tuple. +// * +// * @param cls closure +// * @param data pointer to input argument, here a `struct TALER_Amount` +// * @param data_len number of bytes in @a data (if applicable) +// * @param[out] param_values SQL data to set +// * @param[out] param_lengths SQL length data to set +// * @param[out] param_formats SQL format data to set +// * @param param_length number of entries available in the @a param_values, @a param_lengths and @a param_formats arrays +// * @param[out] scratch buffer for dynamic allocations (to be done via GNUNET_malloc() +// * @param scratch_length number of entries left in @a scratch +// * @return -1 on error, number of offsets used in @a scratch otherwise +// */ +// static int +// qconv_amount_tuple (void *cls, +// const void *data, +// size_t data_len, +// void *param_values[], +// int param_lengths[], +// int param_formats[], +// unsigned int param_length, +// void *scratch[], +// unsigned int scratch_length) +// { +// struct GNUNET_PQ_Context *db = cls; +// const struct TALER_Amount *amount = data; +// size_t sz; + +// GNUNET_assert (NULL != db); +// GNUNET_assert (NULL != amount); +// GNUNET_assert (1 == param_length); +// GNUNET_assert (1 <= scratch_length); +// GNUNET_assert (sizeof (struct TALER_Amount) == data_len); +// GNUNET_static_assert (sizeof(uint32_t) == sizeof(Oid)); +// { +// char *out; +// Oid oid_v; +// Oid oid_f; + +// GNUNET_assert (GNUNET_OK == +// GNUNET_PQ_get_oid_by_name (db, +// "int8", +// &oid_v)); +// GNUNET_assert (GNUNET_OK == +// GNUNET_PQ_get_oid_by_name (db, +// "int4", +// &oid_f)); + +// { +// struct TALER_PQ_AmountP d +// = TALER_PQ_make_taler_pq_amount_ (amount, +// oid_v, +// oid_f); + +// sz = sizeof(d); +// out = GNUNET_malloc (sz); +// scratch[0] = out; +// GNUNET_memcpy (out, +// &d, +// sizeof(d)); +// } +// } + +// param_values[0] = scratch[0]; +// param_lengths[0] = sz; +// param_formats[0] = 1; + +// return 1; +// } + + +// struct GNUNET_PQ_QueryParam +// TALER_PQ_query_param_amount ( +// const struct GNUNET_PQ_Context *db, +// const struct TALER_Amount *amount) +// { +// struct GNUNET_PQ_QueryParam res = { +// .conv_cls = (void *) db, +// .conv = &qconv_amount_tuple, +// .data = amount, +// .size = sizeof (*amount), +// .num_params = 1, +// }; + +// return res; +// } + + +// /** +// * Function called to convert input argument into SQL parameters. +// * +// * @param cls closure +// * @param data pointer to input argument +// * @param data_len number of bytes in @a data (if applicable) +// * @param[out] param_values SQL data to set +// * @param[out] param_lengths SQL length data to set +// * @param[out] param_formats SQL format data to set +// * @param param_length number of entries available in the @a param_values, @a param_lengths and @a param_formats arrays +// * @param[out] scratch buffer for dynamic allocations (to be done via #GNUNET_malloc() +// * @param scratch_length number of entries left in @a scratch +// * @return -1 on error, number of offsets used in @a scratch otherwise +// */ +// static int +// qconv_denom_pub (void *cls, +// const void *data, +// size_t data_len, +// void *param_values[], +// int param_lengths[], +// int param_formats[], +// unsigned int param_length, +// void *scratch[], +// unsigned int scratch_length) +// { +// const struct TALER_DenominationPublicKey *denom_pub = data; +// size_t tlen; +// size_t len; +// uint32_t be[2]; +// char *buf; +// void *tbuf; + +// (void) cls; +// (void) data_len; +// GNUNET_assert (1 == param_length); +// GNUNET_assert (scratch_length > 0); +// GNUNET_break (NULL == cls); +// be[0] = htonl ((uint32_t) denom_pub->cipher); +// be[1] = htonl (denom_pub->age_mask.bits); +// switch (denom_pub->cipher) +// { +// case TALER_DENOMINATION_RSA: +// tlen = GNUNET_CRYPTO_rsa_public_key_encode ( +// denom_pub->details.rsa_public_key, +// &tbuf); +// break; +// case TALER_DENOMINATION_CS: +// tlen = sizeof (denom_pub->details.cs_public_key); +// break; +// default: +// GNUNET_assert (0); +// } +// len = tlen + sizeof (be); +// buf = GNUNET_malloc (len); +// GNUNET_memcpy (buf, +// be, +// sizeof (be)); +// switch (denom_pub->cipher) +// { +// case TALER_DENOMINATION_RSA: +// GNUNET_memcpy (&buf[sizeof (be)], +// tbuf, +// tlen); +// GNUNET_free (tbuf); +// break; +// case TALER_DENOMINATION_CS: +// GNUNET_memcpy (&buf[sizeof (be)], +// &denom_pub->details.cs_public_key, +// tlen); +// break; +// default: +// GNUNET_assert (0); +// } + +// scratch[0] = buf; +// param_values[0] = (void *) buf; +// param_lengths[0] = len; +// param_formats[0] = 1; +// return 1; +// } + + +// struct GNUNET_PQ_QueryParam +// TALER_PQ_query_param_denom_pub ( +// const struct TALER_DenominationPublicKey *denom_pub) +// { +// struct GNUNET_PQ_QueryParam res = { +// .conv = &qconv_denom_pub, +// .data = denom_pub, +// .num_params = 1 +// }; + +// return res; +// } + + +// /** +// * Function called to convert input argument into SQL parameters. +// * +// * @param cls closure +// * @param data pointer to input argument +// * @param data_len number of bytes in @a data (if applicable) +// * @param[out] param_values SQL data to set +// * @param[out] param_lengths SQL length data to set +// * @param[out] param_formats SQL format data to set +// * @param param_length number of entries available in the @a param_values, @a param_lengths and @a param_formats arrays +// * @param[out] scratch buffer for dynamic allocations (to be done via #GNUNET_malloc() +// * @param scratch_length number of entries left in @a scratch +// * @return -1 on error, number of offsets used in @a scratch otherwise +// */ +// static int +// qconv_denom_sig (void *cls, +// const void *data, +// size_t data_len, +// void *param_values[], +// int param_lengths[], +// int param_formats[], +// unsigned int param_length, +// void *scratch[], +// unsigned int scratch_length) +// { +// const struct TALER_DenominationSignature *denom_sig = data; +// size_t tlen; +// size_t len; +// uint32_t be[2]; +// char *buf; +// void *tbuf; + +// (void) cls; +// (void) data_len; +// GNUNET_assert (1 == param_length); +// GNUNET_assert (scratch_length > 0); +// GNUNET_break (NULL == cls); +// be[0] = htonl ((uint32_t) denom_sig->cipher); +// be[1] = htonl (0x00); /* magic marker: unblinded */ +// switch (denom_sig->cipher) +// { +// case TALER_DENOMINATION_RSA: +// tlen = GNUNET_CRYPTO_rsa_signature_encode ( +// denom_sig->details.rsa_signature, +// &tbuf); +// break; +// case TALER_DENOMINATION_CS: +// tlen = sizeof (denom_sig->details.cs_signature); +// break; +// default: +// GNUNET_assert (0); +// } +// len = tlen + sizeof (be); +// buf = GNUNET_malloc (len); +// GNUNET_memcpy (buf, +// &be, +// sizeof (be)); +// switch (denom_sig->cipher) +// { +// case TALER_DENOMINATION_RSA: +// GNUNET_memcpy (&buf[sizeof (be)], +// tbuf, +// tlen); +// GNUNET_free (tbuf); +// break; +// case TALER_DENOMINATION_CS: +// GNUNET_memcpy (&buf[sizeof (be)], +// &denom_sig->details.cs_signature, +// tlen); +// break; +// default: +// GNUNET_assert (0); +// } + +// scratch[0] = buf; +// param_values[0] = (void *) buf; +// param_lengths[0] = len; +// param_formats[0] = 1; +// return 1; +// } + + +// struct GNUNET_PQ_QueryParam +// TALER_PQ_query_param_denom_sig ( +// const struct TALER_DenominationSignature *denom_sig) +// { +// struct GNUNET_PQ_QueryParam res = { +// .conv = &qconv_denom_sig, +// .data = denom_sig, +// .num_params = 1 +// }; + +// return res; +// } + + +// /** +// * Function called to convert input argument into SQL parameters. +// * +// * @param cls closure +// * @param data pointer to input argument +// * @param data_len number of bytes in @a data (if applicable) +// * @param[out] param_values SQL data to set +// * @param[out] param_lengths SQL length data to set +// * @param[out] param_formats SQL format data to set +// * @param param_length number of entries available in the @a param_values, @a param_lengths and @a param_formats arrays +// * @param[out] scratch buffer for dynamic allocations (to be done via #GNUNET_malloc() +// * @param scratch_length number of entries left in @a scratch +// * @return -1 on error, number of offsets used in @a scratch otherwise +// */ +// static int +// qconv_blinded_denom_sig (void *cls, +// const void *data, +// size_t data_len, +// void *param_values[], +// int param_lengths[], +// int param_formats[], +// unsigned int param_length, +// void *scratch[], +// unsigned int scratch_length) +// { +// const struct TALER_BlindedDenominationSignature *denom_sig = data; +// size_t tlen; +// size_t len; +// uint32_t be[2]; +// char *buf; +// void *tbuf; + +// (void) cls; +// (void) data_len; +// GNUNET_assert (1 == param_length); +// GNUNET_assert (scratch_length > 0); +// GNUNET_break (NULL == cls); +// be[0] = htonl ((uint32_t) denom_sig->cipher); +// be[1] = htonl (0x01); /* magic marker: blinded */ +// switch (denom_sig->cipher) +// { +// case TALER_DENOMINATION_RSA: +// tlen = GNUNET_CRYPTO_rsa_signature_encode ( +// denom_sig->details.blinded_rsa_signature, +// &tbuf); +// break; +// case TALER_DENOMINATION_CS: +// tlen = sizeof (denom_sig->details.blinded_cs_answer); +// break; +// default: +// GNUNET_assert (0); +// } +// len = tlen + sizeof (be); +// buf = GNUNET_malloc (len); +// GNUNET_memcpy (buf, +// &be, +// sizeof (be)); +// switch (denom_sig->cipher) +// { +// case TALER_DENOMINATION_RSA: +// GNUNET_memcpy (&buf[sizeof (be)], +// tbuf, +// tlen); +// GNUNET_free (tbuf); +// break; +// case TALER_DENOMINATION_CS: +// GNUNET_memcpy (&buf[sizeof (be)], +// &denom_sig->details.blinded_cs_answer, +// tlen); +// break; +// default: +// GNUNET_assert (0); +// } + +// scratch[0] = buf; +// param_values[0] = (void *) buf; +// param_lengths[0] = len; +// param_formats[0] = 1; +// return 1; +// } + + +// struct GNUNET_PQ_QueryParam +// TALER_PQ_query_param_blinded_denom_sig ( +// const struct TALER_BlindedDenominationSignature *denom_sig) +// { +// struct GNUNET_PQ_QueryParam res = { +// .conv = &qconv_blinded_denom_sig, +// .data = denom_sig, +// .num_params = 1 +// }; + +// return res; +// } + + +// /** +// * Function called to convert input argument into SQL parameters. +// * +// * @param cls closure +// * @param data pointer to input argument +// * @param data_len number of bytes in @a data (if applicable) +// * @param[out] param_values SQL data to set +// * @param[out] param_lengths SQL length data to set +// * @param[out] param_formats SQL format data to set +// * @param param_length number of entries available in the @a param_values, @a param_lengths and @a param_formats arrays +// * @param[out] scratch buffer for dynamic allocations (to be done via #GNUNET_malloc() +// * @param scratch_length number of entries left in @a scratch +// * @return -1 on error, number of offsets used in @a scratch otherwise +// */ +// static int +// qconv_blinded_planchet (void *cls, +// const void *data, +// size_t data_len, +// void *param_values[], +// int param_lengths[], +// int param_formats[], +// unsigned int param_length, +// void *scratch[], +// unsigned int scratch_length) +// { +// const struct TALER_BlindedPlanchet *bp = data; +// size_t tlen; +// size_t len; +// uint32_t be[2]; +// char *buf; + +// (void) cls; +// (void) data_len; +// GNUNET_assert (1 == param_length); +// GNUNET_assert (scratch_length > 0); +// GNUNET_break (NULL == cls); +// be[0] = htonl ((uint32_t) bp->cipher); +// be[1] = htonl (0x0100); /* magic marker: blinded */ +// switch (bp->cipher) +// { +// case TALER_DENOMINATION_RSA: +// tlen = bp->details.rsa_blinded_planchet.blinded_msg_size; +// break; +// case TALER_DENOMINATION_CS: +// tlen = sizeof (bp->details.cs_blinded_planchet); +// break; +// default: +// GNUNET_assert (0); +// } +// len = tlen + sizeof (be); +// buf = GNUNET_malloc (len); +// GNUNET_memcpy (buf, +// &be, +// sizeof (be)); +// switch (bp->cipher) +// { +// case TALER_DENOMINATION_RSA: +// GNUNET_memcpy (&buf[sizeof (be)], +// bp->details.rsa_blinded_planchet.blinded_msg, +// tlen); +// break; +// case TALER_DENOMINATION_CS: +// GNUNET_memcpy (&buf[sizeof (be)], +// &bp->details.cs_blinded_planchet, +// tlen); +// break; +// default: +// GNUNET_assert (0); +// } +// scratch[0] = buf; +// param_values[0] = (void *) buf; +// param_lengths[0] = len; +// param_formats[0] = 1; +// return 1; +// } + + +// struct GNUNET_PQ_QueryParam +// TALER_PQ_query_param_blinded_planchet ( +// const struct TALER_BlindedPlanchet *bp) +// { +// struct GNUNET_PQ_QueryParam res = { +// .conv = &qconv_blinded_planchet, +// .data = bp, +// .num_params = 1 +// }; + +// return res; +// } + + +// /** +// * Function called to convert input argument into SQL parameters. +// * +// * @param cls closure +// * @param data pointer to input argument +// * @param data_len number of bytes in @a data (if applicable) +// * @param[out] param_values SQL data to set +// * @param[out] param_lengths SQL length data to set +// * @param[out] param_formats SQL format data to set +// * @param param_length number of entries available in the @a param_values, @a param_lengths and @a param_formats arrays +// * @param[out] scratch buffer for dynamic allocations (to be done via #GNUNET_malloc() +// * @param scratch_length number of entries left in @a scratch +// * @return -1 on error, number of offsets used in @a scratch otherwise +// */ +// static int +// qconv_exchange_withdraw_values (void *cls, +// const void *data, +// size_t data_len, +// void *param_values[], +// int param_lengths[], +// int param_formats[], +// unsigned int param_length, +// void *scratch[], +// unsigned int scratch_length) +// { +// const struct TALER_ExchangeWithdrawValues *alg_values = data; +// size_t tlen; +// size_t len; +// uint32_t be[2]; +// char *buf; + +// (void) cls; +// (void) data_len; +// GNUNET_assert (1 == param_length); +// GNUNET_assert (scratch_length > 0); +// GNUNET_break (NULL == cls); +// be[0] = htonl ((uint32_t) alg_values->cipher); +// be[1] = htonl (0x010000); /* magic marker: EWV */ +// switch (alg_values->cipher) +// { +// case TALER_DENOMINATION_RSA: +// tlen = 0; +// break; +// case TALER_DENOMINATION_CS: +// tlen = sizeof (struct TALER_DenominationCSPublicRPairP); +// break; +// default: +// GNUNET_assert (0); +// } +// len = tlen + sizeof (be); +// buf = GNUNET_malloc (len); +// GNUNET_memcpy (buf, +// &be, +// sizeof (be)); +// switch (alg_values->cipher) +// { +// case TALER_DENOMINATION_RSA: +// break; +// case TALER_DENOMINATION_CS: +// GNUNET_memcpy (&buf[sizeof (be)], +// &alg_values->details.cs_values, +// tlen); +// break; +// default: +// GNUNET_assert (0); +// } +// scratch[0] = buf; +// param_values[0] = (void *) buf; +// param_lengths[0] = len; +// param_formats[0] = 1; +// return 1; +// } + + +// struct GNUNET_PQ_QueryParam +// TALER_PQ_query_param_exchange_withdraw_values ( +// const struct TALER_ExchangeWithdrawValues *alg_values) +// { +// struct GNUNET_PQ_QueryParam res = { +// .conv = &qconv_exchange_withdraw_values, +// .data = alg_values, +// .num_params = 1 +// }; + +// return res; +// } + + +// /** +// * Function called to convert input argument into SQL parameters. +// * +// * @param cls closure +// * @param data pointer to input argument, here a `json_t *` +// * @param data_len number of bytes in @a data (if applicable) +// * @param[out] param_values SQL data to set +// * @param[out] param_lengths SQL length data to set +// * @param[out] param_formats SQL format data to set +// * @param param_length number of entries available in the @a param_values, @a param_lengths and @a param_formats arrays +// * @param[out] scratch buffer for dynamic allocations (to be done via GNUNET_malloc() +// * @param scratch_length number of entries left in @a scratch +// * @return -1 on error, number of offsets used in @a scratch otherwise +// */ +// static int +// qconv_json (void *cls, +// const void *data, +// size_t data_len, +// void *param_values[], +// int param_lengths[], +// int param_formats[], +// unsigned int param_length, +// void *scratch[], +// unsigned int scratch_length) +// { +// const json_t *json = data; +// char *str; + +// (void) cls; +// (void) data_len; +// GNUNET_assert (1 == param_length); +// GNUNET_assert (scratch_length > 0); +// str = json_dumps (json, JSON_COMPACT); +// if (NULL == str) +// return -1; +// scratch[0] = str; +// param_values[0] = (void *) str; +// param_lengths[0] = strlen (str); +// param_formats[0] = 1; +// return 1; +// } + + +// struct GNUNET_PQ_QueryParam +// TALER_PQ_query_param_json (const json_t *x) +// { +// struct GNUNET_PQ_QueryParam res = { +// .conv = &qconv_json, +// .data = x, +// .num_params = 1 +// }; + +// return res; +// } + + +// /** ------------------- Array support -----------------------------------**/ + +// /** +// * Closure for the array type handlers. +// * +// * May contain sizes information for the data, given (and handled) by the +// * caller. +// */ +// struct qconv_array_cls +// { +// /** +// * If not null, contains the array of sizes (the size of the array is the +// * .size field in the ambient GNUNET_PQ_QueryParam struct). We do not free +// * this memory. +// * +// * If not null, this value has precedence over @a sizes, which MUST be NULL */ +// const size_t *sizes; + +// /** +// * If @a size and @a c_sizes are NULL, this field defines the same size +// * for each element in the array. +// */ +// size_t same_size; + +// /** +// * If true, the array parameter to the data pointer to the qconv_array is a +// * continuous byte array of data, either with @a same_size each or sizes +// * provided bytes by @a sizes; +// */ +// bool continuous; + +// /** +// * Type of the array elements +// */ +// enum TALER_PQ_ArrayType typ; + +// /** +// * Oid of the array elements +// */ +// Oid oid; + +// /** +// * db context, needed for OID-lookup of basis-types +// */ +// struct GNUNET_PQ_Context *db; +// }; + +// /** +// * Callback to cleanup a qconv_array_cls to be used during +// * GNUNET_PQ_cleanup_query_params_closures +// */ +// static void +// qconv_array_cls_cleanup (void *cls) +// { +// GNUNET_free (cls); +// } + + +// /** +// * Function called to convert input argument into SQL parameters for arrays +// * +// * Note: the format for the encoding of arrays for libpq is not very well +// * documented. We peeked into various sources (postgresql and libpqtypes) for +// * guidance. +// * +// * @param cls Closure of type struct qconv_array_cls* +// * @param data Pointer to first element in the array +// * @param data_len Number of _elements_ in array @a data (if applicable) +// * @param[out] param_values SQL data to set +// * @param[out] param_lengths SQL length data to set +// * @param[out] param_formats SQL format data to set +// * @param param_length number of entries available in the @a param_values, @a param_lengths and @a param_formats arrays +// * @param[out] scratch buffer for dynamic allocations (to be done via #GNUNET_malloc() +// * @param scratch_length number of entries left in @a scratch +// * @return -1 on error, number of offsets used in @a scratch otherwise +// */ +// static int +// qconv_array ( +// void *cls, +// const void *data, +// size_t data_len, +// void *param_values[], +// int param_lengths[], +// int param_formats[], +// unsigned int param_length, +// void *scratch[], +// unsigned int scratch_length) +// { +// struct qconv_array_cls *meta = cls; +// size_t num = data_len; +// size_t total_size; +// const size_t *sizes; +// bool same_sized; +// void *elements = NULL; +// bool noerror = true; +// /* needed to capture the encoded rsa signatures */ +// void **buffers = NULL; +// size_t *buffer_lengths = NULL; + +// (void) (param_length); +// (void) (scratch_length); + +// GNUNET_assert (NULL != meta); +// GNUNET_assert (num < INT_MAX); + +// sizes = meta->sizes; +// same_sized = (0 != meta->same_size); + +// #define RETURN_UNLESS(cond) \ +// do { \ +// if (! (cond)) \ +// { \ +// GNUNET_break ((cond)); \ +// noerror = false; \ +// goto DONE; \ +// } \ +// } while (0) + +// /* Calculate sizes and check bounds */ +// { +// /* num * length-field */ +// size_t x = sizeof(uint32_t); +// size_t y = x * num; +// RETURN_UNLESS ((0 == num) || (y / num == x)); + +// /* size of header */ +// total_size = x = sizeof(struct GNUNET_PQ_ArrayHeader_P); +// total_size += y; +// RETURN_UNLESS (total_size >= x); + +// /* sizes of elements */ +// if (same_sized) +// { +// x = num * meta->same_size; +// RETURN_UNLESS ((0 == num) || (x / num == meta->same_size)); + +// y = total_size; +// total_size += x; +// RETURN_UNLESS (total_size >= y); +// } +// else /* sizes are different per element */ +// { +// switch (meta->typ) +// { +// case TALER_PQ_array_of_blinded_denom_sig: +// { +// const struct TALER_BlindedDenominationSignature *denom_sigs = data; +// size_t len; + +// buffers = GNUNET_new_array (num, void *); +// buffer_lengths = GNUNET_new_array (num, size_t); + +// for (size_t i = 0; i<num; i++) +// { +// switch (denom_sigs[i].cipher) +// { +// case TALER_DENOMINATION_RSA: +// len = GNUNET_CRYPTO_rsa_signature_encode ( +// denom_sigs[i].details.blinded_rsa_signature, +// &buffers[i]); +// RETURN_UNLESS (len != 0); +// break; +// case TALER_DENOMINATION_CS: +// len = sizeof (denom_sigs[i].details.blinded_cs_answer); +// break; +// default: +// GNUNET_assert (0); +// } + +// /* for the cipher and marker */ +// len += 2 * sizeof(uint32_t); +// buffer_lengths[i] = len; + +// y = total_size; +// total_size += len; +// RETURN_UNLESS (total_size >= y); +// } +// sizes = buffer_lengths; +// break; +// } +// default: +// GNUNET_assert (0); +// } +// } + +// RETURN_UNLESS (INT_MAX > total_size); +// RETURN_UNLESS (0 != total_size); + +// elements = GNUNET_malloc (total_size); +// } + +// /* Write data */ +// { +// char *out = elements; +// struct GNUNET_PQ_ArrayHeader_P h = { +// .ndim = htonl (1), /* We only support one-dimensional arrays */ +// .has_null = htonl (0), /* We do not support NULL entries in arrays */ +// .lbound = htonl (1), /* Default start index value */ +// .dim = htonl (num), +// .oid = htonl (meta->oid), +// }; + +// /* Write header */ +// GNUNET_memcpy (out, +// &h, +// sizeof(h)); +// out += sizeof(h); + +// /* Write elements */ +// for (size_t i = 0; i < num; i++) +// { +// size_t sz = same_sized ? meta->same_size : sizes[i]; + +// *(uint32_t *) out = htonl (sz); +// out += sizeof(uint32_t); +// switch (meta->typ) +// { +// case TALER_PQ_array_of_amount: +// { +// const struct TALER_Amount *amounts = data; +// Oid oid_v; +// Oid oid_f; + +// GNUNET_assert (GNUNET_OK == +// GNUNET_PQ_get_oid_by_name (meta->db, +// "int8", +// &oid_v)); +// GNUNET_assert (GNUNET_OK == +// GNUNET_PQ_get_oid_by_name (meta->db, +// "int4", +// &oid_f)); +// { +// struct TALER_PQ_AmountP am +// = TALER_PQ_make_taler_pq_amount_ ( +// &amounts[i], +// oid_v, +// oid_f); + +// GNUNET_memcpy (out, +// &am, +// sizeof(am)); +// } +// break; +// } +// case TALER_PQ_array_of_blinded_denom_sig: +// { +// const struct TALER_BlindedDenominationSignature *denom_sigs = data; +// uint32_t be[2]; + +// be[0] = htonl ((uint32_t) denom_sigs[i].cipher); +// be[1] = htonl (0x01); /* magic margker: blinded */ +// GNUNET_memcpy (out, +// &be, +// sizeof(be)); +// out += sizeof(be); +// sz -= sizeof(be); + +// switch (denom_sigs[i].cipher) +// { +// case TALER_DENOMINATION_RSA: +// /* For RSA, 'same_sized' must have been false */ +// GNUNET_assert (NULL != buffers); +// GNUNET_memcpy (out, +// buffers[i], +// sz); +// break; +// case TALER_DENOMINATION_CS: +// GNUNET_memcpy (out, +// &denom_sigs[i].details.blinded_cs_answer, +// sz); +// break; +// default: +// GNUNET_assert (0); +// } +// break; +// } +// case TALER_PQ_array_of_blinded_coin_hash: +// { +// const struct TALER_BlindedCoinHashP *coin_hs = data; + +// GNUNET_memcpy (out, +// &coin_hs[i], +// sizeof(struct TALER_BlindedCoinHashP)); + +// break; +// } +// case TALER_PQ_array_of_denom_hash: +// { +// const struct TALER_DenominationHashP *denom_hs = data; + +// GNUNET_memcpy (out, +// &denom_hs[i], +// sizeof(struct TALER_DenominationHashP)); +// break; +// } +// default: +// { +// GNUNET_assert (0); +// break; +// } +// } +// out += sz; +// } +// } +// param_values[0] = elements; +// param_lengths[0] = total_size; +// param_formats[0] = 1; +// scratch[0] = elements; + +// DONE: +// if (NULL != buffers) +// { +// for (size_t i = 0; i<num; i++) +// GNUNET_free (buffers[i]); +// GNUNET_free (buffers); +// } +// GNUNET_free (buffer_lengths); +// if (noerror) +// return 1; +// return -1; +// } + + +// /** +// * Function to generate a typ specific query parameter and corresponding closure +// * +// * @param num Number of elements in @a elements +// * @param continuous If true, @a elements is an continuous array of data +// * @param elements Array of @a num elements, either continuous or pointers +// * @param sizes Array of @a num sizes, one per element, may be NULL +// * @param same_size If not 0, all elements in @a elements have this size +// * @param typ Supported internal type of each element in @a elements +// * @param oid Oid of the type to be used in Postgres +// * @param[in,out] db our database handle for looking up OIDs +// * @return Query parameter +// */ +// static struct GNUNET_PQ_QueryParam +// query_param_array_generic ( +// unsigned int num, +// bool continuous, +// const void *elements, +// const size_t *sizes, +// size_t same_size, +// enum TALER_PQ_ArrayType typ, +// Oid oid, +// struct GNUNET_PQ_Context *db) +// { +// struct qconv_array_cls *meta = GNUNET_new (struct qconv_array_cls); +// meta->typ = typ; +// meta->oid = oid; +// meta->sizes = sizes; +// meta->same_size = same_size; +// meta->continuous = continuous; +// meta->db = db; + +// struct GNUNET_PQ_QueryParam res = { +// .conv = qconv_array, +// .conv_cls = meta, +// .conv_cls_cleanup = qconv_array_cls_cleanup, +// .data = elements, +// .size = num, +// .num_params = 1, +// }; + +// return res; +// } + + +// struct GNUNET_PQ_QueryParam +// TALER_PQ_query_param_array_blinded_denom_sig ( +// size_t num, +// const struct TALER_BlindedDenominationSignature *denom_sigs, +// struct GNUNET_PQ_Context *db) +// { +// Oid oid; +// GNUNET_assert (GNUNET_OK == +// GNUNET_PQ_get_oid_by_name (db, "bytea", &oid)); +// return query_param_array_generic (num, +// true, +// denom_sigs, +// NULL, +// 0, +// TALER_PQ_array_of_blinded_denom_sig, +// oid, +// NULL); +// } + + +// struct GNUNET_PQ_QueryParam +// TALER_PQ_query_param_array_blinded_coin_hash ( +// size_t num, +// const struct TALER_BlindedCoinHashP *coin_hs, +// struct GNUNET_PQ_Context *db) +// { +// Oid oid; +// GNUNET_assert (GNUNET_OK == +// GNUNET_PQ_get_oid_by_name (db, "bytea", &oid)); +// return query_param_array_generic (num, +// true, +// coin_hs, +// NULL, +// sizeof(struct TALER_BlindedCoinHashP), +// TALER_PQ_array_of_blinded_coin_hash, +// oid, +// NULL); +// } + + +// struct GNUNET_PQ_QueryParam +// TALER_PQ_query_param_array_denom_hash ( +// size_t num, +// const struct TALER_DenominationHashP *denom_hs, +// struct GNUNET_PQ_Context *db) +// { +// Oid oid; +// GNUNET_assert (GNUNET_OK == +// GNUNET_PQ_get_oid_by_name (db, "bytea", &oid)); +// return query_param_array_generic (num, +// true, +// denom_hs, +// NULL, +// sizeof(struct TALER_DenominationHashP), +// TALER_PQ_array_of_denom_hash, +// oid, +// NULL); +// } + + +// struct GNUNET_PQ_QueryParam +// TALER_PQ_query_param_array_amount ( +// size_t num, +// const struct TALER_Amount *amounts, +// struct GNUNET_PQ_Context *db) +// { +// Oid oid; +// GNUNET_assert (GNUNET_OK == +// GNUNET_PQ_get_oid_by_name (db, "taler_amount", &oid)); +// return query_param_array_generic ( +// num, +// true, +// amounts, +// NULL, +// sizeof(struct TALER_PQ_AmountP), +// TALER_PQ_array_of_amount, +// oid, +// db); +// } + + +// /* end of pq/pq_query_helper.c */ diff --git a/src/pq/pq_result_helper.c b/src/pq/pq_result_helper.c @@ -18,1407 +18,1407 @@ * @brief functions to initialize parameter arrays * @author Christian Grothoff */ -#include "platform.h" +// #include "platform.h" #include <gnunet/gnunet_util_lib.h> -#include "pq_common.h" -#include "taler_pq_lib.h" - - -/** - * Extract an amount from a tuple including the currency from a Postgres - * database @a result at row @a row. - * - * @param cls closure; not used - * @param result where to extract data from - * @param row row to extract data from - * @param fname name (or prefix) of the fields to extract from - * @param[in,out] dst_size where to store size of result, may be NULL - * @param[out] dst where to store the result - * @return - * #GNUNET_YES if all results could be extracted - * #GNUNET_NO if at least one result was NULL - * #GNUNET_SYSERR if a result was invalid (non-existing field) - */ -static enum GNUNET_GenericReturnValue -extract_amount_currency_tuple (void *cls, - PGresult *result, - int row, - const char *fname, - size_t *dst_size, - void *dst) -{ - struct TALER_Amount *r_amount = dst; - int col; - - (void) cls; - if (sizeof (struct TALER_Amount) != *dst_size) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - - /* Set return value to invalid in case we don't finish */ - memset (r_amount, - 0, - sizeof (struct TALER_Amount)); - col = PQfnumber (result, - fname); - if (col < 0) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Field `%s' does not exist in result\n", - fname); - return GNUNET_SYSERR; - } - if (PQgetisnull (result, - row, - col)) - { - return GNUNET_NO; - } - - /* Parse the tuple */ - { - struct TALER_PQ_AmountCurrencyP ap; - const char *in; - size_t size; - - size = PQgetlength (result, - row, - col); - if ( (size >= sizeof (ap)) || - (size <= sizeof (ap) - TALER_CURRENCY_LEN) ) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Incorrect size of binary field `%s' (got %zu, expected (%zu-%zu))\n", - fname, - size, - sizeof (ap) - TALER_CURRENCY_LEN, - sizeof (ap)); - return GNUNET_SYSERR; - } - - in = PQgetvalue (result, - row, - col); - memset (&ap.c, - 0, - TALER_CURRENCY_LEN); - memcpy (&ap, - in, - size); - if (3 != ntohl (ap.cnt)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Incorrect number of elements in tuple-field `%s'\n", - fname); - return GNUNET_SYSERR; - } - /* TODO[oec]: OID-checks? */ - - r_amount->value = GNUNET_ntohll (ap.v); - r_amount->fraction = ntohl (ap.f); - memcpy (r_amount->currency, - ap.c, - TALER_CURRENCY_LEN); - if ('\0' != r_amount->currency[TALER_CURRENCY_LEN - 1]) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Invalid currency (not 0-terminated) in tuple field `%s'\n", - fname); - /* be sure nobody uses this by accident */ - memset (r_amount, - 0, - sizeof (struct TALER_Amount)); - return GNUNET_SYSERR; - } - } - - if (r_amount->value >= TALER_AMOUNT_MAX_VALUE) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Value in field `%s' exceeds legal range\n", - fname); - return GNUNET_SYSERR; - } - if (r_amount->fraction >= TALER_AMOUNT_FRAC_BASE) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Fraction in field `%s' exceeds legal range\n", - fname); - return GNUNET_SYSERR; - } - return GNUNET_OK; -} - - -struct GNUNET_PQ_ResultSpec -TALER_PQ_result_spec_amount_with_currency (const char *name, - struct TALER_Amount *amount) -{ - struct GNUNET_PQ_ResultSpec res = { - .conv = &extract_amount_currency_tuple, - .dst = (void *) amount, - .dst_size = sizeof (*amount), - .fname = name - }; - - return res; -} - - -/** - * Extract an amount from a tuple from a Postgres database @a result at row @a row. - * - * @param cls closure, a `const char *` giving the currency - * @param result where to extract data from - * @param row row to extract data from - * @param fname name (or prefix) of the fields to extract from - * @param[in,out] dst_size where to store size of result, may be NULL - * @param[out] dst where to store the result - * @return - * #GNUNET_YES if all results could be extracted - * #GNUNET_NO if at least one result was NULL - * #GNUNET_SYSERR if a result was invalid (non-existing field) - */ -static enum GNUNET_GenericReturnValue -extract_amount_tuple (void *cls, - PGresult *result, - int row, - const char *fname, - size_t *dst_size, - void *dst) -{ - struct TALER_Amount *r_amount = dst; - const char *currency = cls; - int col; - size_t len; - - if (sizeof (struct TALER_Amount) != *dst_size) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - - /* Set return value to invalid in case we don't finish */ - memset (r_amount, - 0, - sizeof (struct TALER_Amount)); - col = PQfnumber (result, - fname); - if (col < 0) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Field `%s' does not exist in result\n", - fname); - return GNUNET_SYSERR; - } - if (PQgetisnull (result, - row, - col)) - { - return GNUNET_NO; - } - - /* Parse the tuple */ - { - struct TALER_PQ_AmountP ap; - const char *in; - size_t size; - - size = PQgetlength (result, - row, - col); - if (sizeof(ap) != size) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Incorrect size of binary field `%s' (got %zu, expected %zu)\n", - fname, - size, - sizeof(ap)); - return GNUNET_SYSERR; - } - - in = PQgetvalue (result, - row, - col); - memcpy (&ap, - in, - size); - if (2 != ntohl (ap.cnt)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Incorrect number of elements in tuple-field `%s'\n", - fname); - return GNUNET_SYSERR; - } - /* TODO[oec]: OID-checks? */ - - r_amount->value = GNUNET_ntohll (ap.v); - r_amount->fraction = ntohl (ap.f); - } - - if (r_amount->value >= TALER_AMOUNT_MAX_VALUE) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Value in field `%s' exceeds legal range\n", - fname); - return GNUNET_SYSERR; - } - if (r_amount->fraction >= TALER_AMOUNT_FRAC_BASE) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Fraction in field `%s' exceeds legal range\n", - fname); - return GNUNET_SYSERR; - } - - len = GNUNET_MIN (TALER_CURRENCY_LEN - 1, - strlen (currency)); - - GNUNET_memcpy (r_amount->currency, - currency, - len); - return GNUNET_OK; -} - - -struct GNUNET_PQ_ResultSpec -TALER_PQ_result_spec_amount (const char *name, - const char *currency, - struct TALER_Amount *amount) -{ - struct GNUNET_PQ_ResultSpec res = { - .conv = &extract_amount_tuple, - .cls = (void *) currency, - .dst = (void *) amount, - .dst_size = sizeof (*amount), - .fname = name - }; - - return res; -} - - -/** - * Extract data from a Postgres database @a result at row @a row. - * - * @param cls closure - * @param result where to extract data from - * @param row row to extract data from - * @param fname name (or prefix) of the fields to extract from - * @param[in,out] dst_size where to store size of result, may be NULL - * @param[out] dst where to store the result - * @return - * #GNUNET_YES if all results could be extracted - * #GNUNET_NO if at least one result was NULL - * #GNUNET_SYSERR if a result was invalid (non-existing field) - */ -static enum GNUNET_GenericReturnValue -extract_json (void *cls, - PGresult *result, - int row, - const char *fname, - size_t *dst_size, - void *dst) -{ - json_t **j_dst = dst; - const char *res; - int fnum; - json_error_t json_error; - size_t slen; - - (void) cls; - (void) dst_size; - fnum = PQfnumber (result, - fname); - if (fnum < 0) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Field `%s' does not exist in result\n", - fname); - return GNUNET_SYSERR; - } - if (PQgetisnull (result, - row, - fnum)) - return GNUNET_NO; - slen = PQgetlength (result, - row, - fnum); - res = (const char *) PQgetvalue (result, - row, - fnum); - *j_dst = json_loadb (res, - slen, - JSON_REJECT_DUPLICATES, - &json_error); - if (NULL == *j_dst) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Failed to parse JSON result for field `%s': %s (%s)\n", - fname, - json_error.text, - json_error.source); - return GNUNET_SYSERR; - } - return GNUNET_OK; -} - - -/** - * Function called to clean up memory allocated - * by a #GNUNET_PQ_ResultConverter. - * - * @param cls closure - * @param rd result data to clean up - */ -static void -clean_json (void *cls, - void *rd) -{ - json_t **dst = rd; - - (void) cls; - if (NULL != *dst) - { - json_decref (*dst); - *dst = NULL; - } -} - - -struct GNUNET_PQ_ResultSpec -TALER_PQ_result_spec_json (const char *name, - json_t **jp) -{ - struct GNUNET_PQ_ResultSpec res = { - .conv = &extract_json, - .cleaner = &clean_json, - .dst = (void *) jp, - .fname = name - }; - - return res; -} - - -/** - * Extract data from a Postgres database @a result at row @a row. - * - * @param cls closure - * @param result where to extract data from - * @param row the row to extract data from - * @param fname name (or prefix) of the fields to extract from - * @param[in,out] dst_size where to store size of result, may be NULL - * @param[out] dst where to store the result - * @return - * #GNUNET_YES if all results could be extracted - * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL) - */ -static enum GNUNET_GenericReturnValue -extract_denom_pub (void *cls, - PGresult *result, - int row, - const char *fname, - size_t *dst_size, - void *dst) -{ - struct TALER_DenominationPublicKey *pk = dst; - size_t len; - const char *res; - int fnum; - uint32_t be[2]; - - (void) cls; - (void) dst_size; - fnum = PQfnumber (result, - fname); - if (fnum < 0) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - if (PQgetisnull (result, - row, - fnum)) - return GNUNET_NO; - - /* if a field is null, continue but - * remember that we now return a different result */ - len = PQgetlength (result, - row, - fnum); - res = PQgetvalue (result, - row, - fnum); - if (len < sizeof (be)) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - GNUNET_memcpy (be, - res, - sizeof (be)); - res += sizeof (be); - len -= sizeof (be); - pk->cipher = ntohl (be[0]); - pk->age_mask.bits = ntohl (be[1]); - switch (pk->cipher) - { - case TALER_DENOMINATION_RSA: - pk->details.rsa_public_key - = GNUNET_CRYPTO_rsa_public_key_decode (res, - len); - if (NULL == pk->details.rsa_public_key) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - return GNUNET_OK; - case TALER_DENOMINATION_CS: - if (sizeof (pk->details.cs_public_key) != len) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - GNUNET_memcpy (&pk->details.cs_public_key, - res, - len); - return GNUNET_OK; - default: - GNUNET_break (0); - } - return GNUNET_SYSERR; -} - - -/** - * Function called to clean up memory allocated - * by a #GNUNET_PQ_ResultConverter. - * - * @param cls closure - * @param rd result data to clean up - */ -static void -clean_denom_pub (void *cls, - void *rd) -{ - struct TALER_DenominationPublicKey *denom_pub = rd; - - (void) cls; - TALER_denom_pub_free (denom_pub); -} - - -struct GNUNET_PQ_ResultSpec -TALER_PQ_result_spec_denom_pub (const char *name, - struct TALER_DenominationPublicKey *denom_pub) -{ - struct GNUNET_PQ_ResultSpec res = { - .conv = &extract_denom_pub, - .cleaner = &clean_denom_pub, - .dst = (void *) denom_pub, - .fname = name - }; - - return res; -} - - -/** - * Extract data from a Postgres database @a result at row @a row. - * - * @param cls closure - * @param result where to extract data from - * @param row the row to extract data from - * @param fname name (or prefix) of the fields to extract from - * @param[in,out] dst_size where to store size of result, may be NULL - * @param[out] dst where to store the result - * @return - * #GNUNET_YES if all results could be extracted - * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL) - */ -static enum GNUNET_GenericReturnValue -extract_denom_sig (void *cls, - PGresult *result, - int row, - const char *fname, - size_t *dst_size, - void *dst) -{ - struct TALER_DenominationSignature *sig = dst; - size_t len; - const char *res; - int fnum; - uint32_t be[2]; - - (void) cls; - (void) dst_size; - fnum = PQfnumber (result, - fname); - if (fnum < 0) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - if (PQgetisnull (result, - row, - fnum)) - return GNUNET_NO; - - /* if a field is null, continue but - * remember that we now return a different result */ - len = PQgetlength (result, - row, - fnum); - res = PQgetvalue (result, - row, - fnum); - if (len < sizeof (be)) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - GNUNET_memcpy (&be, - res, - sizeof (be)); - if (0x00 != ntohl (be[1])) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - res += sizeof (be); - len -= sizeof (be); - sig->cipher = ntohl (be[0]); - switch (sig->cipher) - { - case TALER_DENOMINATION_RSA: - sig->details.rsa_signature - = GNUNET_CRYPTO_rsa_signature_decode (res, - len); - if (NULL == sig->details.rsa_signature) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - return GNUNET_OK; - case TALER_DENOMINATION_CS: - if (sizeof (sig->details.cs_signature) != len) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - GNUNET_memcpy (&sig->details.cs_signature, - res, - len); - return GNUNET_OK; - default: - GNUNET_break (0); - } - return GNUNET_SYSERR; -} - - -/** - * Function called to clean up memory allocated - * by a #GNUNET_PQ_ResultConverter. - * - * @param cls closure - * @param rd result data to clean up - */ -static void -clean_denom_sig (void *cls, - void *rd) -{ - struct TALER_DenominationSignature *denom_sig = rd; - - (void) cls; - TALER_denom_sig_free (denom_sig); -} - - -struct GNUNET_PQ_ResultSpec -TALER_PQ_result_spec_denom_sig (const char *name, - struct TALER_DenominationSignature *denom_sig) -{ - struct GNUNET_PQ_ResultSpec res = { - .conv = &extract_denom_sig, - .cleaner = &clean_denom_sig, - .dst = (void *) denom_sig, - .fname = name - }; - - return res; -} - - -/** - * Extract data from a Postgres database @a result at row @a row. - * - * @param cls closure - * @param result where to extract data from - * @param row the row to extract data from - * @param fname name (or prefix) of the fields to extract from - * @param[in,out] dst_size where to store size of result, may be NULL - * @param[out] dst where to store the result - * @return - * #GNUNET_YES if all results could be extracted - * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL) - */ -static enum GNUNET_GenericReturnValue -extract_blinded_denom_sig (void *cls, - PGresult *result, - int row, - const char *fname, - size_t *dst_size, - void *dst) -{ - struct TALER_BlindedDenominationSignature *sig = dst; - size_t len; - const char *res; - int fnum; - uint32_t be[2]; - - (void) cls; - (void) dst_size; - fnum = PQfnumber (result, - fname); - if (fnum < 0) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - if (PQgetisnull (result, - row, - fnum)) - return GNUNET_NO; - - /* if a field is null, continue but - * remember that we now return a different result */ - len = PQgetlength (result, - row, - fnum); - res = PQgetvalue (result, - row, - fnum); - if (len < sizeof (be)) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - GNUNET_memcpy (&be, - res, - sizeof (be)); - if (0x01 != ntohl (be[1])) /* magic marker: blinded */ - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - res += sizeof (be); - len -= sizeof (be); - sig->cipher = ntohl (be[0]); - switch (sig->cipher) - { - case TALER_DENOMINATION_RSA: - sig->details.blinded_rsa_signature - = GNUNET_CRYPTO_rsa_signature_decode (res, - len); - if (NULL == sig->details.blinded_rsa_signature) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - return GNUNET_OK; - case TALER_DENOMINATION_CS: - if (sizeof (sig->details.blinded_cs_answer) != len) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - GNUNET_memcpy (&sig->details.blinded_cs_answer, - res, - len); - return GNUNET_OK; - default: - GNUNET_break (0); - } - return GNUNET_SYSERR; -} - - -/** - * Function called to clean up memory allocated - * by a #GNUNET_PQ_ResultConverter. - * - * @param cls closure - * @param rd result data to clean up - */ -static void -clean_blinded_denom_sig (void *cls, - void *rd) -{ - struct TALER_BlindedDenominationSignature *denom_sig = rd; - - (void) cls; - TALER_blinded_denom_sig_free (denom_sig); -} - - -struct GNUNET_PQ_ResultSpec -TALER_PQ_result_spec_blinded_denom_sig ( - const char *name, - struct TALER_BlindedDenominationSignature *denom_sig) -{ - struct GNUNET_PQ_ResultSpec res = { - .conv = &extract_blinded_denom_sig, - .cleaner = &clean_blinded_denom_sig, - .dst = (void *) denom_sig, - .fname = name - }; - - return res; -} - - -/** - * Extract data from a Postgres database @a result at row @a row. - * - * @param cls closure - * @param result where to extract data from - * @param row the row to extract data from - * @param fname name (or prefix) of the fields to extract from - * @param[in,out] dst_size where to store size of result, may be NULL - * @param[out] dst where to store the result - * @return - * #GNUNET_YES if all results could be extracted - * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL) - */ -static enum GNUNET_GenericReturnValue -extract_blinded_planchet (void *cls, - PGresult *result, - int row, - const char *fname, - size_t *dst_size, - void *dst) -{ - struct TALER_BlindedPlanchet *bp = dst; - size_t len; - const char *res; - int fnum; - uint32_t be[2]; - - (void) cls; - (void) dst_size; - fnum = PQfnumber (result, - fname); - if (fnum < 0) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - if (PQgetisnull (result, - row, - fnum)) - return GNUNET_NO; - - /* if a field is null, continue but - * remember that we now return a different result */ - len = PQgetlength (result, - row, - fnum); - res = PQgetvalue (result, - row, - fnum); - if (len < sizeof (be)) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - GNUNET_memcpy (&be, - res, - sizeof (be)); - if (0x0100 != ntohl (be[1])) /* magic marker: blinded */ - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - res += sizeof (be); - len -= sizeof (be); - bp->cipher = ntohl (be[0]); - switch (bp->cipher) - { - case TALER_DENOMINATION_RSA: - bp->details.rsa_blinded_planchet.blinded_msg_size - = len; - bp->details.rsa_blinded_planchet.blinded_msg - = GNUNET_memdup (res, - len); - return GNUNET_OK; - case TALER_DENOMINATION_CS: - if (sizeof (bp->details.cs_blinded_planchet) != len) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - GNUNET_memcpy (&bp->details.cs_blinded_planchet, - res, - len); - return GNUNET_OK; - default: - GNUNET_break (0); - } - return GNUNET_SYSERR; -} - - -/** - * Function called to clean up memory allocated - * by a #GNUNET_PQ_ResultConverter. - * - * @param cls closure - * @param rd result data to clean up - */ -static void -clean_blinded_planchet (void *cls, - void *rd) -{ - struct TALER_BlindedPlanchet *bp = rd; - - (void) cls; - TALER_blinded_planchet_free (bp); -} - - -struct GNUNET_PQ_ResultSpec -TALER_PQ_result_spec_blinded_planchet ( - const char *name, - struct TALER_BlindedPlanchet *bp) -{ - struct GNUNET_PQ_ResultSpec res = { - .conv = &extract_blinded_planchet, - .cleaner = &clean_blinded_planchet, - .dst = (void *) bp, - .fname = name - }; - - return res; -} - - -/** - * Extract data from a Postgres database @a result at row @a row. - * - * @param cls closure - * @param result where to extract data from - * @param row row to extract data from - * @param fname name (or prefix) of the fields to extract from - * @param[in,out] dst_size where to store size of result, may be NULL - * @param[out] dst where to store the result - * @return - * #GNUNET_YES if all results could be extracted - * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL) - */ -static enum GNUNET_GenericReturnValue -extract_exchange_withdraw_values (void *cls, - PGresult *result, - int row, - const char *fname, - size_t *dst_size, - void *dst) -{ - struct TALER_ExchangeWithdrawValues *alg_values = dst; - size_t len; - const char *res; - int fnum; - uint32_t be[2]; - - (void) cls; - (void) dst_size; - fnum = PQfnumber (result, - fname); - if (fnum < 0) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - if (PQgetisnull (result, - row, - fnum)) - return GNUNET_NO; - - /* if a field is null, continue but - * remember that we now return a different result */ - len = PQgetlength (result, - row, - fnum); - res = PQgetvalue (result, - row, - fnum); - if (len < sizeof (be)) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - GNUNET_memcpy (&be, - res, - sizeof (be)); - if (0x010000 != ntohl (be[1])) /* magic marker: EWV */ - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - res += sizeof (be); - len -= sizeof (be); - alg_values->cipher = ntohl (be[0]); - switch (alg_values->cipher) - { - case TALER_DENOMINATION_RSA: - if (0 != len) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - return GNUNET_OK; - case TALER_DENOMINATION_CS: - if (sizeof (struct TALER_DenominationCSPublicRPairP) != len) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - GNUNET_memcpy (&alg_values->details.cs_values, - res, - len); - return GNUNET_OK; - default: - GNUNET_break (0); - } - return GNUNET_SYSERR; -} - - -struct GNUNET_PQ_ResultSpec -TALER_PQ_result_spec_exchange_withdraw_values ( - const char *name, - struct TALER_ExchangeWithdrawValues *ewv) -{ - struct GNUNET_PQ_ResultSpec res = { - .conv = &extract_exchange_withdraw_values, - .dst = (void *) ewv, - .fname = name - }; - - return res; -} - - -/** - * Closure for the array result specifications. Contains type information - * for the generic parser extract_array_generic and out-pointers for the results. - */ -struct ArrayResultCls -{ - /* Oid of the expected type, must match the oid in the header of the PQResult struct */ - Oid oid; - - /* Target type */ - enum TALER_PQ_ArrayType typ; - - /* If not 0, defines the expected size of each entry */ - size_t same_size; - - /* Out-pointer to write the number of elements in the array */ - size_t *num; - - /* Out-pointer. If @a typ is TALER_PQ_array_of_byte and @a same_size is 0, - * allocate and put the array of @a num sizes here. NULL otherwise */ - size_t **sizes; - - /* DB_connection, needed for OID-lookup for composite types */ - const struct GNUNET_PQ_Context *db; - - /* Currency information for amount composites */ - char currency[TALER_CURRENCY_LEN]; -}; - -/** - * Extract data from a Postgres database @a result as array of a specific type - * from row @a row. The type information and optionally additional - * out-parameters are given in @a cls which is of type array_result_cls. - * - * @param cls closure of type array_result_cls - * @param result where to extract data from - * @param row row to extract data from - * @param fname name (or prefix) of the fields to extract from - * @param[in,out] dst_size where to store size of result, may be NULL - * @param[out] dst where to store the result - * @return - * #GNUNET_YES if all results could be extracted - * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL) - */ -static enum GNUNET_GenericReturnValue -extract_array_generic ( - void *cls, - PGresult *result, - int row, - const char *fname, - size_t *dst_size, - void *dst) -{ - const struct ArrayResultCls *info = cls; - int data_sz; - char *data; - void *out = NULL; - struct GNUNET_PQ_ArrayHeader_P header; - int col_num; - - GNUNET_assert (NULL != dst); - *((void **) dst) = NULL; - - #define FAIL_IF(cond) \ - do { \ - if ((cond)) \ - { \ - GNUNET_break (! (cond)); \ - goto FAIL; \ - } \ - } while (0) - - col_num = PQfnumber (result, fname); - FAIL_IF (0 > col_num); - - data_sz = PQgetlength (result, row, col_num); - FAIL_IF (0 > data_sz); - FAIL_IF (sizeof(header) > (size_t) data_sz); - - data = PQgetvalue (result, row, col_num); - FAIL_IF (NULL == data); - - { - struct GNUNET_PQ_ArrayHeader_P *h = - (struct GNUNET_PQ_ArrayHeader_P *) data; - - header.ndim = ntohl (h->ndim); - header.has_null = ntohl (h->has_null); - header.oid = ntohl (h->oid); - header.dim = ntohl (h->dim); - header.lbound = ntohl (h->lbound); - - FAIL_IF (1 != header.ndim); - FAIL_IF (INT_MAX <= header.dim); - FAIL_IF (0 != header.has_null); - FAIL_IF (1 != header.lbound); - FAIL_IF (info->oid != header.oid); - } - - if (NULL != info->num) - *info->num = header.dim; - - { - char *in = data + sizeof(header); - - switch (info->typ) - { - case TALER_PQ_array_of_amount: - { - struct TALER_Amount *amounts; - if (NULL != dst_size) - *dst_size = sizeof(struct TALER_Amount) * (header.dim); - - amounts = GNUNET_new_array (header.dim, struct TALER_Amount); - *((void **) dst) = amounts; - - for (uint32_t i = 0; i < header.dim; i++) - { - struct TALER_PQ_AmountP ap; - struct TALER_Amount *amount = &amounts[i]; - uint32_t val; - size_t sz; - - GNUNET_memcpy (&val, - in, - sizeof(val)); - sz = ntohl (val); - in += sizeof(val); - - /* total size for this array-entry */ - FAIL_IF (sizeof(ap) > sz); - - GNUNET_memcpy (&ap, - in, - sz); - FAIL_IF (2 != ntohl (ap.cnt)); - - amount->value = GNUNET_ntohll (ap.v); - amount->fraction = ntohl (ap.f); - GNUNET_memcpy (amount->currency, - info->currency, - TALER_CURRENCY_LEN); - - in += sizeof(struct TALER_PQ_AmountP); - } - return GNUNET_OK; - } - case TALER_PQ_array_of_denom_hash: - if (NULL != dst_size) - *dst_size = sizeof(struct TALER_DenominationHashP) * (header.dim); - out = GNUNET_new_array (header.dim, struct TALER_DenominationHashP); - *((void **) dst) = out; - for (uint32_t i = 0; i < header.dim; i++) - { - uint32_t val; - size_t sz; - - GNUNET_memcpy (&val, - in, - sizeof(val)); - sz = ntohl (val); - FAIL_IF (sz != sizeof(struct TALER_DenominationHashP)); - in += sizeof(uint32_t); - *(struct TALER_DenominationHashP *) out = - *(struct TALER_DenominationHashP *) in; - in += sz; - out += sz; - } - return GNUNET_OK; - - case TALER_PQ_array_of_blinded_coin_hash: - if (NULL != dst_size) - *dst_size = sizeof(struct TALER_BlindedCoinHashP) * (header.dim); - out = GNUNET_new_array (header.dim, struct TALER_BlindedCoinHashP); - *((void **) dst) = out; - for (uint32_t i = 0; i < header.dim; i++) - { - uint32_t val; - size_t sz; - - GNUNET_memcpy (&val, - in, - sizeof(val)); - sz = ntohl (val); - FAIL_IF (sz != sizeof(struct TALER_BlindedCoinHashP)); - in += sizeof(uint32_t); - *(struct TALER_BlindedCoinHashP *) out = - *(struct TALER_BlindedCoinHashP *) in; - in += sz; - out += sz; - } - return GNUNET_OK; - - case TALER_PQ_array_of_blinded_denom_sig: - { - struct TALER_BlindedDenominationSignature *denom_sigs; - if (0 == header.dim) - { - if (NULL != dst_size) - *dst_size = 0; - break; - } - - denom_sigs = GNUNET_new_array (header.dim, - struct TALER_BlindedDenominationSignature); - *((void **) dst) = denom_sigs; - - /* copy data */ - for (uint32_t i = 0; i < header.dim; i++) - { - struct TALER_BlindedDenominationSignature *denom_sig = &denom_sigs[i]; - uint32_t be[2]; - uint32_t val; - size_t sz; - - GNUNET_memcpy (&val, - in, - sizeof(val)); - sz = ntohl (val); - FAIL_IF (sizeof(be) > sz); - - in += sizeof(val); - GNUNET_memcpy (&be, - in, - sizeof(be)); - FAIL_IF (0x01 != ntohl (be[1])); /* magic marker: blinded */ - - in += sizeof(be); - sz -= sizeof(be); - - denom_sig->cipher = ntohl (be[0]); - switch (denom_sig->cipher) - { - case TALER_DENOMINATION_RSA: - denom_sig->details.blinded_rsa_signature = - GNUNET_CRYPTO_rsa_signature_decode (in, - sz); - FAIL_IF (NULL == denom_sig->details.blinded_rsa_signature); - break; - - case TALER_DENOMINATION_CS: - FAIL_IF (sizeof(denom_sig->details.blinded_cs_answer) != sz); - GNUNET_memcpy (&denom_sig->details.blinded_cs_answer, - in, - sz); - break; - - default: - FAIL_IF (true); - } - - in += sz; - } - return GNUNET_OK; - } - default: - FAIL_IF (true); - } - } - -FAIL: - GNUNET_free (*(void **) dst); - return GNUNET_SYSERR; - #undef FAIL_IF - -} - - -/** - * Cleanup of the data and closure of an array spec. - */ -static void -array_cleanup (void *cls, - void *rd) -{ - - struct ArrayResultCls *info = cls; - void **dst = rd; - - if ((0 == info->same_size) && - (NULL != info->sizes)) - GNUNET_free (*(info->sizes)); - - GNUNET_free (cls); - GNUNET_free (*dst); - *dst = NULL; -} - - -struct GNUNET_PQ_ResultSpec -TALER_PQ_result_spec_array_blinded_denom_sig ( - struct GNUNET_PQ_Context *db, - const char *name, - size_t *num, - struct TALER_BlindedDenominationSignature **denom_sigs) -{ - struct ArrayResultCls *info = GNUNET_new (struct ArrayResultCls); - - info->num = num; - info->typ = TALER_PQ_array_of_blinded_denom_sig; - GNUNET_assert (GNUNET_OK == - GNUNET_PQ_get_oid_by_name (db, - "bytea", - &info->oid)); - - struct GNUNET_PQ_ResultSpec res = { - .conv = extract_array_generic, - .cleaner = array_cleanup, - .dst = (void *) denom_sigs, - .fname = name, - .cls = info - }; - return res; - -}; - -struct GNUNET_PQ_ResultSpec -TALER_PQ_result_spec_array_blinded_coin_hash ( - struct GNUNET_PQ_Context *db, - const char *name, - size_t *num, - struct TALER_BlindedCoinHashP **h_coin_evs) -{ - struct ArrayResultCls *info = GNUNET_new (struct ArrayResultCls); - - info->num = num; - info->typ = TALER_PQ_array_of_blinded_coin_hash; - GNUNET_assert (GNUNET_OK == - GNUNET_PQ_get_oid_by_name (db, - "bytea", - &info->oid)); - - struct GNUNET_PQ_ResultSpec res = { - .conv = extract_array_generic, - .cleaner = array_cleanup, - .dst = (void *) h_coin_evs, - .fname = name, - .cls = info - }; - return res; - -}; - -struct GNUNET_PQ_ResultSpec -TALER_PQ_result_spec_array_denom_hash ( - struct GNUNET_PQ_Context *db, - const char *name, - size_t *num, - struct TALER_DenominationHashP **denom_hs) -{ - struct ArrayResultCls *info = GNUNET_new (struct ArrayResultCls); - - info->num = num; - info->typ = TALER_PQ_array_of_denom_hash; - GNUNET_assert (GNUNET_OK == - GNUNET_PQ_get_oid_by_name (db, - "bytea", - &info->oid)); - - struct GNUNET_PQ_ResultSpec res = { - .conv = extract_array_generic, - .cleaner = array_cleanup, - .dst = (void *) denom_hs, - .fname = name, - .cls = info - }; - return res; - -}; - -struct GNUNET_PQ_ResultSpec -TALER_PQ_result_spec_array_amount ( - struct GNUNET_PQ_Context *db, - const char *name, - const char *currency, - size_t *num, - struct TALER_Amount **amounts) -{ - struct ArrayResultCls *info = GNUNET_new (struct ArrayResultCls); - - info->num = num; - info->typ = TALER_PQ_array_of_amount; - info->db = db; - GNUNET_assert (GNUNET_OK == - GNUNET_PQ_get_oid_by_name (db, - "taler_amount", - &info->oid)); - - { - size_t clen = GNUNET_MIN (TALER_CURRENCY_LEN - 1, - strlen (currency)); - GNUNET_memcpy (&info->currency, - currency, - clen); - } - - struct GNUNET_PQ_ResultSpec res = { - .conv = extract_array_generic, - .cleaner = array_cleanup, - .dst = (void *) amounts, - .fname = name, - .cls = info, - }; - return res; - - -} +// #include "pq_common.h" +// #include "taler_pq_lib.h" + + +// /** +// * Extract an amount from a tuple including the currency from a Postgres +// * database @a result at row @a row. +// * +// * @param cls closure; not used +// * @param result where to extract data from +// * @param row row to extract data from +// * @param fname name (or prefix) of the fields to extract from +// * @param[in,out] dst_size where to store size of result, may be NULL +// * @param[out] dst where to store the result +// * @return +// * #GNUNET_YES if all results could be extracted +// * #GNUNET_NO if at least one result was NULL +// * #GNUNET_SYSERR if a result was invalid (non-existing field) +// */ +// static enum GNUNET_GenericReturnValue +// extract_amount_currency_tuple (void *cls, +// PGresult *result, +// int row, +// const char *fname, +// size_t *dst_size, +// void *dst) +// { +// struct TALER_Amount *r_amount = dst; +// int col; + +// (void) cls; +// if (sizeof (struct TALER_Amount) != *dst_size) +// { +// GNUNET_break (0); +// return GNUNET_SYSERR; +// } + +// /* Set return value to invalid in case we don't finish */ +// memset (r_amount, +// 0, +// sizeof (struct TALER_Amount)); +// col = PQfnumber (result, +// fname); +// if (col < 0) +// { +// GNUNET_log (GNUNET_ERROR_TYPE_ERROR, +// "Field `%s' does not exist in result\n", +// fname); +// return GNUNET_SYSERR; +// } +// if (PQgetisnull (result, +// row, +// col)) +// { +// return GNUNET_NO; +// } + +// /* Parse the tuple */ +// { +// struct TALER_PQ_AmountCurrencyP ap; +// const char *in; +// size_t size; + +// size = PQgetlength (result, +// row, +// col); +// if ( (size >= sizeof (ap)) || +// (size <= sizeof (ap) - TALER_CURRENCY_LEN) ) +// { +// GNUNET_log (GNUNET_ERROR_TYPE_ERROR, +// "Incorrect size of binary field `%s' (got %zu, expected (%zu-%zu))\n", +// fname, +// size, +// sizeof (ap) - TALER_CURRENCY_LEN, +// sizeof (ap)); +// return GNUNET_SYSERR; +// } + +// in = PQgetvalue (result, +// row, +// col); +// memset (&ap.c, +// 0, +// TALER_CURRENCY_LEN); +// memcpy (&ap, +// in, +// size); +// if (3 != ntohl (ap.cnt)) +// { +// GNUNET_log (GNUNET_ERROR_TYPE_ERROR, +// "Incorrect number of elements in tuple-field `%s'\n", +// fname); +// return GNUNET_SYSERR; +// } +// /* TODO[oec]: OID-checks? */ + +// r_amount->value = GNUNET_ntohll (ap.v); +// r_amount->fraction = ntohl (ap.f); +// memcpy (r_amount->currency, +// ap.c, +// TALER_CURRENCY_LEN); +// if ('\0' != r_amount->currency[TALER_CURRENCY_LEN - 1]) +// { +// GNUNET_log (GNUNET_ERROR_TYPE_ERROR, +// "Invalid currency (not 0-terminated) in tuple field `%s'\n", +// fname); +// /* be sure nobody uses this by accident */ +// memset (r_amount, +// 0, +// sizeof (struct TALER_Amount)); +// return GNUNET_SYSERR; +// } +// } + +// if (r_amount->value >= TALER_AMOUNT_MAX_VALUE) +// { +// GNUNET_log (GNUNET_ERROR_TYPE_ERROR, +// "Value in field `%s' exceeds legal range\n", +// fname); +// return GNUNET_SYSERR; +// } +// if (r_amount->fraction >= TALER_AMOUNT_FRAC_BASE) +// { +// GNUNET_log (GNUNET_ERROR_TYPE_ERROR, +// "Fraction in field `%s' exceeds legal range\n", +// fname); +// return GNUNET_SYSERR; +// } +// return GNUNET_OK; +// } + + +// struct GNUNET_PQ_ResultSpec +// TALER_PQ_result_spec_amount_with_currency (const char *name, +// struct TALER_Amount *amount) +// { +// struct GNUNET_PQ_ResultSpec res = { +// .conv = &extract_amount_currency_tuple, +// .dst = (void *) amount, +// .dst_size = sizeof (*amount), +// .fname = name +// }; + +// return res; +// } + + +// /** +// * Extract an amount from a tuple from a Postgres database @a result at row @a row. +// * +// * @param cls closure, a `const char *` giving the currency +// * @param result where to extract data from +// * @param row row to extract data from +// * @param fname name (or prefix) of the fields to extract from +// * @param[in,out] dst_size where to store size of result, may be NULL +// * @param[out] dst where to store the result +// * @return +// * #GNUNET_YES if all results could be extracted +// * #GNUNET_NO if at least one result was NULL +// * #GNUNET_SYSERR if a result was invalid (non-existing field) +// */ +// static enum GNUNET_GenericReturnValue +// extract_amount_tuple (void *cls, +// PGresult *result, +// int row, +// const char *fname, +// size_t *dst_size, +// void *dst) +// { +// struct TALER_Amount *r_amount = dst; +// const char *currency = cls; +// int col; +// size_t len; + +// if (sizeof (struct TALER_Amount) != *dst_size) +// { +// GNUNET_break (0); +// return GNUNET_SYSERR; +// } + +// /* Set return value to invalid in case we don't finish */ +// memset (r_amount, +// 0, +// sizeof (struct TALER_Amount)); +// col = PQfnumber (result, +// fname); +// if (col < 0) +// { +// GNUNET_log (GNUNET_ERROR_TYPE_ERROR, +// "Field `%s' does not exist in result\n", +// fname); +// return GNUNET_SYSERR; +// } +// if (PQgetisnull (result, +// row, +// col)) +// { +// return GNUNET_NO; +// } + +// /* Parse the tuple */ +// { +// struct TALER_PQ_AmountP ap; +// const char *in; +// size_t size; + +// size = PQgetlength (result, +// row, +// col); +// if (sizeof(ap) != size) +// { +// GNUNET_log (GNUNET_ERROR_TYPE_ERROR, +// "Incorrect size of binary field `%s' (got %zu, expected %zu)\n", +// fname, +// size, +// sizeof(ap)); +// return GNUNET_SYSERR; +// } + +// in = PQgetvalue (result, +// row, +// col); +// memcpy (&ap, +// in, +// size); +// if (2 != ntohl (ap.cnt)) +// { +// GNUNET_log (GNUNET_ERROR_TYPE_ERROR, +// "Incorrect number of elements in tuple-field `%s'\n", +// fname); +// return GNUNET_SYSERR; +// } +// /* TODO[oec]: OID-checks? */ + +// r_amount->value = GNUNET_ntohll (ap.v); +// r_amount->fraction = ntohl (ap.f); +// } + +// if (r_amount->value >= TALER_AMOUNT_MAX_VALUE) +// { +// GNUNET_log (GNUNET_ERROR_TYPE_ERROR, +// "Value in field `%s' exceeds legal range\n", +// fname); +// return GNUNET_SYSERR; +// } +// if (r_amount->fraction >= TALER_AMOUNT_FRAC_BASE) +// { +// GNUNET_log (GNUNET_ERROR_TYPE_ERROR, +// "Fraction in field `%s' exceeds legal range\n", +// fname); +// return GNUNET_SYSERR; +// } + +// len = GNUNET_MIN (TALER_CURRENCY_LEN - 1, +// strlen (currency)); + +// GNUNET_memcpy (r_amount->currency, +// currency, +// len); +// return GNUNET_OK; +// } + + +// struct GNUNET_PQ_ResultSpec +// TALER_PQ_result_spec_amount (const char *name, +// const char *currency, +// struct TALER_Amount *amount) +// { +// struct GNUNET_PQ_ResultSpec res = { +// .conv = &extract_amount_tuple, +// .cls = (void *) currency, +// .dst = (void *) amount, +// .dst_size = sizeof (*amount), +// .fname = name +// }; + +// return res; +// } + + +// /** +// * Extract data from a Postgres database @a result at row @a row. +// * +// * @param cls closure +// * @param result where to extract data from +// * @param row row to extract data from +// * @param fname name (or prefix) of the fields to extract from +// * @param[in,out] dst_size where to store size of result, may be NULL +// * @param[out] dst where to store the result +// * @return +// * #GNUNET_YES if all results could be extracted +// * #GNUNET_NO if at least one result was NULL +// * #GNUNET_SYSERR if a result was invalid (non-existing field) +// */ +// static enum GNUNET_GenericReturnValue +// extract_json (void *cls, +// PGresult *result, +// int row, +// const char *fname, +// size_t *dst_size, +// void *dst) +// { +// json_t **j_dst = dst; +// const char *res; +// int fnum; +// json_error_t json_error; +// size_t slen; + +// (void) cls; +// (void) dst_size; +// fnum = PQfnumber (result, +// fname); +// if (fnum < 0) +// { +// GNUNET_log (GNUNET_ERROR_TYPE_ERROR, +// "Field `%s' does not exist in result\n", +// fname); +// return GNUNET_SYSERR; +// } +// if (PQgetisnull (result, +// row, +// fnum)) +// return GNUNET_NO; +// slen = PQgetlength (result, +// row, +// fnum); +// res = (const char *) PQgetvalue (result, +// row, +// fnum); +// *j_dst = json_loadb (res, +// slen, +// JSON_REJECT_DUPLICATES, +// &json_error); +// if (NULL == *j_dst) +// { +// GNUNET_log (GNUNET_ERROR_TYPE_ERROR, +// "Failed to parse JSON result for field `%s': %s (%s)\n", +// fname, +// json_error.text, +// json_error.source); +// return GNUNET_SYSERR; +// } +// return GNUNET_OK; +// } + + +// /** +// * Function called to clean up memory allocated +// * by a #GNUNET_PQ_ResultConverter. +// * +// * @param cls closure +// * @param rd result data to clean up +// */ +// static void +// clean_json (void *cls, +// void *rd) +// { +// json_t **dst = rd; + +// (void) cls; +// if (NULL != *dst) +// { +// json_decref (*dst); +// *dst = NULL; +// } +// } + + +// struct GNUNET_PQ_ResultSpec +// TALER_PQ_result_spec_json (const char *name, +// json_t **jp) +// { +// struct GNUNET_PQ_ResultSpec res = { +// .conv = &extract_json, +// .cleaner = &clean_json, +// .dst = (void *) jp, +// .fname = name +// }; + +// return res; +// } + + +// /** +// * Extract data from a Postgres database @a result at row @a row. +// * +// * @param cls closure +// * @param result where to extract data from +// * @param row the row to extract data from +// * @param fname name (or prefix) of the fields to extract from +// * @param[in,out] dst_size where to store size of result, may be NULL +// * @param[out] dst where to store the result +// * @return +// * #GNUNET_YES if all results could be extracted +// * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL) +// */ +// static enum GNUNET_GenericReturnValue +// extract_denom_pub (void *cls, +// PGresult *result, +// int row, +// const char *fname, +// size_t *dst_size, +// void *dst) +// { +// struct TALER_DenominationPublicKey *pk = dst; +// size_t len; +// const char *res; +// int fnum; +// uint32_t be[2]; + +// (void) cls; +// (void) dst_size; +// fnum = PQfnumber (result, +// fname); +// if (fnum < 0) +// { +// GNUNET_break (0); +// return GNUNET_SYSERR; +// } +// if (PQgetisnull (result, +// row, +// fnum)) +// return GNUNET_NO; + +// /* if a field is null, continue but +// * remember that we now return a different result */ +// len = PQgetlength (result, +// row, +// fnum); +// res = PQgetvalue (result, +// row, +// fnum); +// if (len < sizeof (be)) +// { +// GNUNET_break (0); +// return GNUNET_SYSERR; +// } +// GNUNET_memcpy (be, +// res, +// sizeof (be)); +// res += sizeof (be); +// len -= sizeof (be); +// pk->cipher = ntohl (be[0]); +// pk->age_mask.bits = ntohl (be[1]); +// switch (pk->cipher) +// { +// case TALER_DENOMINATION_RSA: +// pk->details.rsa_public_key +// = GNUNET_CRYPTO_rsa_public_key_decode (res, +// len); +// if (NULL == pk->details.rsa_public_key) +// { +// GNUNET_break (0); +// return GNUNET_SYSERR; +// } +// return GNUNET_OK; +// case TALER_DENOMINATION_CS: +// if (sizeof (pk->details.cs_public_key) != len) +// { +// GNUNET_break (0); +// return GNUNET_SYSERR; +// } +// GNUNET_memcpy (&pk->details.cs_public_key, +// res, +// len); +// return GNUNET_OK; +// default: +// GNUNET_break (0); +// } +// return GNUNET_SYSERR; +// } + + +// /** +// * Function called to clean up memory allocated +// * by a #GNUNET_PQ_ResultConverter. +// * +// * @param cls closure +// * @param rd result data to clean up +// */ +// static void +// clean_denom_pub (void *cls, +// void *rd) +// { +// struct TALER_DenominationPublicKey *denom_pub = rd; + +// (void) cls; +// TALER_denom_pub_free (denom_pub); +// } + + +// struct GNUNET_PQ_ResultSpec +// TALER_PQ_result_spec_denom_pub (const char *name, +// struct TALER_DenominationPublicKey *denom_pub) +// { +// struct GNUNET_PQ_ResultSpec res = { +// .conv = &extract_denom_pub, +// .cleaner = &clean_denom_pub, +// .dst = (void *) denom_pub, +// .fname = name +// }; + +// return res; +// } + + +// /** +// * Extract data from a Postgres database @a result at row @a row. +// * +// * @param cls closure +// * @param result where to extract data from +// * @param row the row to extract data from +// * @param fname name (or prefix) of the fields to extract from +// * @param[in,out] dst_size where to store size of result, may be NULL +// * @param[out] dst where to store the result +// * @return +// * #GNUNET_YES if all results could be extracted +// * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL) +// */ +// static enum GNUNET_GenericReturnValue +// extract_denom_sig (void *cls, +// PGresult *result, +// int row, +// const char *fname, +// size_t *dst_size, +// void *dst) +// { +// struct TALER_DenominationSignature *sig = dst; +// size_t len; +// const char *res; +// int fnum; +// uint32_t be[2]; + +// (void) cls; +// (void) dst_size; +// fnum = PQfnumber (result, +// fname); +// if (fnum < 0) +// { +// GNUNET_break (0); +// return GNUNET_SYSERR; +// } +// if (PQgetisnull (result, +// row, +// fnum)) +// return GNUNET_NO; + +// /* if a field is null, continue but +// * remember that we now return a different result */ +// len = PQgetlength (result, +// row, +// fnum); +// res = PQgetvalue (result, +// row, +// fnum); +// if (len < sizeof (be)) +// { +// GNUNET_break (0); +// return GNUNET_SYSERR; +// } +// GNUNET_memcpy (&be, +// res, +// sizeof (be)); +// if (0x00 != ntohl (be[1])) +// { +// GNUNET_break (0); +// return GNUNET_SYSERR; +// } +// res += sizeof (be); +// len -= sizeof (be); +// sig->cipher = ntohl (be[0]); +// switch (sig->cipher) +// { +// case TALER_DENOMINATION_RSA: +// sig->details.rsa_signature +// = GNUNET_CRYPTO_rsa_signature_decode (res, +// len); +// if (NULL == sig->details.rsa_signature) +// { +// GNUNET_break (0); +// return GNUNET_SYSERR; +// } +// return GNUNET_OK; +// case TALER_DENOMINATION_CS: +// if (sizeof (sig->details.cs_signature) != len) +// { +// GNUNET_break (0); +// return GNUNET_SYSERR; +// } +// GNUNET_memcpy (&sig->details.cs_signature, +// res, +// len); +// return GNUNET_OK; +// default: +// GNUNET_break (0); +// } +// return GNUNET_SYSERR; +// } + + +// /** +// * Function called to clean up memory allocated +// * by a #GNUNET_PQ_ResultConverter. +// * +// * @param cls closure +// * @param rd result data to clean up +// */ +// static void +// clean_denom_sig (void *cls, +// void *rd) +// { +// struct TALER_DenominationSignature *denom_sig = rd; + +// (void) cls; +// TALER_denom_sig_free (denom_sig); +// } + + +// struct GNUNET_PQ_ResultSpec +// TALER_PQ_result_spec_denom_sig (const char *name, +// struct TALER_DenominationSignature *denom_sig) +// { +// struct GNUNET_PQ_ResultSpec res = { +// .conv = &extract_denom_sig, +// .cleaner = &clean_denom_sig, +// .dst = (void *) denom_sig, +// .fname = name +// }; + +// return res; +// } + + +// /** +// * Extract data from a Postgres database @a result at row @a row. +// * +// * @param cls closure +// * @param result where to extract data from +// * @param row the row to extract data from +// * @param fname name (or prefix) of the fields to extract from +// * @param[in,out] dst_size where to store size of result, may be NULL +// * @param[out] dst where to store the result +// * @return +// * #GNUNET_YES if all results could be extracted +// * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL) +// */ +// static enum GNUNET_GenericReturnValue +// extract_blinded_denom_sig (void *cls, +// PGresult *result, +// int row, +// const char *fname, +// size_t *dst_size, +// void *dst) +// { +// struct TALER_BlindedDenominationSignature *sig = dst; +// size_t len; +// const char *res; +// int fnum; +// uint32_t be[2]; + +// (void) cls; +// (void) dst_size; +// fnum = PQfnumber (result, +// fname); +// if (fnum < 0) +// { +// GNUNET_break (0); +// return GNUNET_SYSERR; +// } +// if (PQgetisnull (result, +// row, +// fnum)) +// return GNUNET_NO; + +// /* if a field is null, continue but +// * remember that we now return a different result */ +// len = PQgetlength (result, +// row, +// fnum); +// res = PQgetvalue (result, +// row, +// fnum); +// if (len < sizeof (be)) +// { +// GNUNET_break (0); +// return GNUNET_SYSERR; +// } +// GNUNET_memcpy (&be, +// res, +// sizeof (be)); +// if (0x01 != ntohl (be[1])) /* magic marker: blinded */ +// { +// GNUNET_break (0); +// return GNUNET_SYSERR; +// } +// res += sizeof (be); +// len -= sizeof (be); +// sig->cipher = ntohl (be[0]); +// switch (sig->cipher) +// { +// case TALER_DENOMINATION_RSA: +// sig->details.blinded_rsa_signature +// = GNUNET_CRYPTO_rsa_signature_decode (res, +// len); +// if (NULL == sig->details.blinded_rsa_signature) +// { +// GNUNET_break (0); +// return GNUNET_SYSERR; +// } +// return GNUNET_OK; +// case TALER_DENOMINATION_CS: +// if (sizeof (sig->details.blinded_cs_answer) != len) +// { +// GNUNET_break (0); +// return GNUNET_SYSERR; +// } +// GNUNET_memcpy (&sig->details.blinded_cs_answer, +// res, +// len); +// return GNUNET_OK; +// default: +// GNUNET_break (0); +// } +// return GNUNET_SYSERR; +// } + + +// /** +// * Function called to clean up memory allocated +// * by a #GNUNET_PQ_ResultConverter. +// * +// * @param cls closure +// * @param rd result data to clean up +// */ +// static void +// clean_blinded_denom_sig (void *cls, +// void *rd) +// { +// struct TALER_BlindedDenominationSignature *denom_sig = rd; + +// (void) cls; +// TALER_blinded_denom_sig_free (denom_sig); +// } + + +// struct GNUNET_PQ_ResultSpec +// TALER_PQ_result_spec_blinded_denom_sig ( +// const char *name, +// struct TALER_BlindedDenominationSignature *denom_sig) +// { +// struct GNUNET_PQ_ResultSpec res = { +// .conv = &extract_blinded_denom_sig, +// .cleaner = &clean_blinded_denom_sig, +// .dst = (void *) denom_sig, +// .fname = name +// }; + +// return res; +// } + + +// /** +// * Extract data from a Postgres database @a result at row @a row. +// * +// * @param cls closure +// * @param result where to extract data from +// * @param row the row to extract data from +// * @param fname name (or prefix) of the fields to extract from +// * @param[in,out] dst_size where to store size of result, may be NULL +// * @param[out] dst where to store the result +// * @return +// * #GNUNET_YES if all results could be extracted +// * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL) +// */ +// static enum GNUNET_GenericReturnValue +// extract_blinded_planchet (void *cls, +// PGresult *result, +// int row, +// const char *fname, +// size_t *dst_size, +// void *dst) +// { +// struct TALER_BlindedPlanchet *bp = dst; +// size_t len; +// const char *res; +// int fnum; +// uint32_t be[2]; + +// (void) cls; +// (void) dst_size; +// fnum = PQfnumber (result, +// fname); +// if (fnum < 0) +// { +// GNUNET_break (0); +// return GNUNET_SYSERR; +// } +// if (PQgetisnull (result, +// row, +// fnum)) +// return GNUNET_NO; + +// /* if a field is null, continue but +// * remember that we now return a different result */ +// len = PQgetlength (result, +// row, +// fnum); +// res = PQgetvalue (result, +// row, +// fnum); +// if (len < sizeof (be)) +// { +// GNUNET_break (0); +// return GNUNET_SYSERR; +// } +// GNUNET_memcpy (&be, +// res, +// sizeof (be)); +// if (0x0100 != ntohl (be[1])) /* magic marker: blinded */ +// { +// GNUNET_break (0); +// return GNUNET_SYSERR; +// } +// res += sizeof (be); +// len -= sizeof (be); +// bp->cipher = ntohl (be[0]); +// switch (bp->cipher) +// { +// case TALER_DENOMINATION_RSA: +// bp->details.rsa_blinded_planchet.blinded_msg_size +// = len; +// bp->details.rsa_blinded_planchet.blinded_msg +// = GNUNET_memdup (res, +// len); +// return GNUNET_OK; +// case TALER_DENOMINATION_CS: +// if (sizeof (bp->details.cs_blinded_planchet) != len) +// { +// GNUNET_break (0); +// return GNUNET_SYSERR; +// } +// GNUNET_memcpy (&bp->details.cs_blinded_planchet, +// res, +// len); +// return GNUNET_OK; +// default: +// GNUNET_break (0); +// } +// return GNUNET_SYSERR; +// } + + +// /** +// * Function called to clean up memory allocated +// * by a #GNUNET_PQ_ResultConverter. +// * +// * @param cls closure +// * @param rd result data to clean up +// */ +// static void +// clean_blinded_planchet (void *cls, +// void *rd) +// { +// struct TALER_BlindedPlanchet *bp = rd; + +// (void) cls; +// TALER_blinded_planchet_free (bp); +// } + + +// struct GNUNET_PQ_ResultSpec +// TALER_PQ_result_spec_blinded_planchet ( +// const char *name, +// struct TALER_BlindedPlanchet *bp) +// { +// struct GNUNET_PQ_ResultSpec res = { +// .conv = &extract_blinded_planchet, +// .cleaner = &clean_blinded_planchet, +// .dst = (void *) bp, +// .fname = name +// }; + +// return res; +// } + + +// /** +// * Extract data from a Postgres database @a result at row @a row. +// * +// * @param cls closure +// * @param result where to extract data from +// * @param row row to extract data from +// * @param fname name (or prefix) of the fields to extract from +// * @param[in,out] dst_size where to store size of result, may be NULL +// * @param[out] dst where to store the result +// * @return +// * #GNUNET_YES if all results could be extracted +// * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL) +// */ +// static enum GNUNET_GenericReturnValue +// extract_exchange_withdraw_values (void *cls, +// PGresult *result, +// int row, +// const char *fname, +// size_t *dst_size, +// void *dst) +// { +// struct TALER_ExchangeWithdrawValues *alg_values = dst; +// size_t len; +// const char *res; +// int fnum; +// uint32_t be[2]; + +// (void) cls; +// (void) dst_size; +// fnum = PQfnumber (result, +// fname); +// if (fnum < 0) +// { +// GNUNET_break (0); +// return GNUNET_SYSERR; +// } +// if (PQgetisnull (result, +// row, +// fnum)) +// return GNUNET_NO; + +// /* if a field is null, continue but +// * remember that we now return a different result */ +// len = PQgetlength (result, +// row, +// fnum); +// res = PQgetvalue (result, +// row, +// fnum); +// if (len < sizeof (be)) +// { +// GNUNET_break (0); +// return GNUNET_SYSERR; +// } +// GNUNET_memcpy (&be, +// res, +// sizeof (be)); +// if (0x010000 != ntohl (be[1])) /* magic marker: EWV */ +// { +// GNUNET_break (0); +// return GNUNET_SYSERR; +// } +// res += sizeof (be); +// len -= sizeof (be); +// alg_values->cipher = ntohl (be[0]); +// switch (alg_values->cipher) +// { +// case TALER_DENOMINATION_RSA: +// if (0 != len) +// { +// GNUNET_break (0); +// return GNUNET_SYSERR; +// } +// return GNUNET_OK; +// case TALER_DENOMINATION_CS: +// if (sizeof (struct TALER_DenominationCSPublicRPairP) != len) +// { +// GNUNET_break (0); +// return GNUNET_SYSERR; +// } +// GNUNET_memcpy (&alg_values->details.cs_values, +// res, +// len); +// return GNUNET_OK; +// default: +// GNUNET_break (0); +// } +// return GNUNET_SYSERR; +// } + + +// struct GNUNET_PQ_ResultSpec +// TALER_PQ_result_spec_exchange_withdraw_values ( +// const char *name, +// struct TALER_ExchangeWithdrawValues *ewv) +// { +// struct GNUNET_PQ_ResultSpec res = { +// .conv = &extract_exchange_withdraw_values, +// .dst = (void *) ewv, +// .fname = name +// }; + +// return res; +// } + + +// /** +// * Closure for the array result specifications. Contains type information +// * for the generic parser extract_array_generic and out-pointers for the results. +// */ +// struct ArrayResultCls +// { +// /* Oid of the expected type, must match the oid in the header of the PQResult struct */ +// Oid oid; + +// /* Target type */ +// enum TALER_PQ_ArrayType typ; + +// /* If not 0, defines the expected size of each entry */ +// size_t same_size; + +// /* Out-pointer to write the number of elements in the array */ +// size_t *num; + +// /* Out-pointer. If @a typ is TALER_PQ_array_of_byte and @a same_size is 0, +// * allocate and put the array of @a num sizes here. NULL otherwise */ +// size_t **sizes; + +// /* DB_connection, needed for OID-lookup for composite types */ +// const struct GNUNET_PQ_Context *db; + +// /* Currency information for amount composites */ +// char currency[TALER_CURRENCY_LEN]; +// }; + +// /** +// * Extract data from a Postgres database @a result as array of a specific type +// * from row @a row. The type information and optionally additional +// * out-parameters are given in @a cls which is of type array_result_cls. +// * +// * @param cls closure of type array_result_cls +// * @param result where to extract data from +// * @param row row to extract data from +// * @param fname name (or prefix) of the fields to extract from +// * @param[in,out] dst_size where to store size of result, may be NULL +// * @param[out] dst where to store the result +// * @return +// * #GNUNET_YES if all results could be extracted +// * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL) +// */ +// static enum GNUNET_GenericReturnValue +// extract_array_generic ( +// void *cls, +// PGresult *result, +// int row, +// const char *fname, +// size_t *dst_size, +// void *dst) +// { +// const struct ArrayResultCls *info = cls; +// int data_sz; +// char *data; +// void *out = NULL; +// struct GNUNET_PQ_ArrayHeader_P header; +// int col_num; + +// GNUNET_assert (NULL != dst); +// *((void **) dst) = NULL; + +// #define FAIL_IF(cond) \ +// do { \ +// if ((cond)) \ +// { \ +// GNUNET_break (! (cond)); \ +// goto FAIL; \ +// } \ +// } while (0) + +// col_num = PQfnumber (result, fname); +// FAIL_IF (0 > col_num); + +// data_sz = PQgetlength (result, row, col_num); +// FAIL_IF (0 > data_sz); +// FAIL_IF (sizeof(header) > (size_t) data_sz); + +// data = PQgetvalue (result, row, col_num); +// FAIL_IF (NULL == data); + +// { +// struct GNUNET_PQ_ArrayHeader_P *h = +// (struct GNUNET_PQ_ArrayHeader_P *) data; + +// header.ndim = ntohl (h->ndim); +// header.has_null = ntohl (h->has_null); +// header.oid = ntohl (h->oid); +// header.dim = ntohl (h->dim); +// header.lbound = ntohl (h->lbound); + +// FAIL_IF (1 != header.ndim); +// FAIL_IF (INT_MAX <= header.dim); +// FAIL_IF (0 != header.has_null); +// FAIL_IF (1 != header.lbound); +// FAIL_IF (info->oid != header.oid); +// } + +// if (NULL != info->num) +// *info->num = header.dim; + +// { +// char *in = data + sizeof(header); + +// switch (info->typ) +// { +// case TALER_PQ_array_of_amount: +// { +// struct TALER_Amount *amounts; +// if (NULL != dst_size) +// *dst_size = sizeof(struct TALER_Amount) * (header.dim); + +// amounts = GNUNET_new_array (header.dim, struct TALER_Amount); +// *((void **) dst) = amounts; + +// for (uint32_t i = 0; i < header.dim; i++) +// { +// struct TALER_PQ_AmountP ap; +// struct TALER_Amount *amount = &amounts[i]; +// uint32_t val; +// size_t sz; + +// GNUNET_memcpy (&val, +// in, +// sizeof(val)); +// sz = ntohl (val); +// in += sizeof(val); + +// /* total size for this array-entry */ +// FAIL_IF (sizeof(ap) > sz); + +// GNUNET_memcpy (&ap, +// in, +// sz); +// FAIL_IF (2 != ntohl (ap.cnt)); + +// amount->value = GNUNET_ntohll (ap.v); +// amount->fraction = ntohl (ap.f); +// GNUNET_memcpy (amount->currency, +// info->currency, +// TALER_CURRENCY_LEN); + +// in += sizeof(struct TALER_PQ_AmountP); +// } +// return GNUNET_OK; +// } +// case TALER_PQ_array_of_denom_hash: +// if (NULL != dst_size) +// *dst_size = sizeof(struct TALER_DenominationHashP) * (header.dim); +// out = GNUNET_new_array (header.dim, struct TALER_DenominationHashP); +// *((void **) dst) = out; +// for (uint32_t i = 0; i < header.dim; i++) +// { +// uint32_t val; +// size_t sz; + +// GNUNET_memcpy (&val, +// in, +// sizeof(val)); +// sz = ntohl (val); +// FAIL_IF (sz != sizeof(struct TALER_DenominationHashP)); +// in += sizeof(uint32_t); +// *(struct TALER_DenominationHashP *) out = +// *(struct TALER_DenominationHashP *) in; +// in += sz; +// out += sz; +// } +// return GNUNET_OK; + +// case TALER_PQ_array_of_blinded_coin_hash: +// if (NULL != dst_size) +// *dst_size = sizeof(struct TALER_BlindedCoinHashP) * (header.dim); +// out = GNUNET_new_array (header.dim, struct TALER_BlindedCoinHashP); +// *((void **) dst) = out; +// for (uint32_t i = 0; i < header.dim; i++) +// { +// uint32_t val; +// size_t sz; + +// GNUNET_memcpy (&val, +// in, +// sizeof(val)); +// sz = ntohl (val); +// FAIL_IF (sz != sizeof(struct TALER_BlindedCoinHashP)); +// in += sizeof(uint32_t); +// *(struct TALER_BlindedCoinHashP *) out = +// *(struct TALER_BlindedCoinHashP *) in; +// in += sz; +// out += sz; +// } +// return GNUNET_OK; + +// case TALER_PQ_array_of_blinded_denom_sig: +// { +// struct TALER_BlindedDenominationSignature *denom_sigs; +// if (0 == header.dim) +// { +// if (NULL != dst_size) +// *dst_size = 0; +// break; +// } + +// denom_sigs = GNUNET_new_array (header.dim, +// struct TALER_BlindedDenominationSignature); +// *((void **) dst) = denom_sigs; + +// /* copy data */ +// for (uint32_t i = 0; i < header.dim; i++) +// { +// struct TALER_BlindedDenominationSignature *denom_sig = &denom_sigs[i]; +// uint32_t be[2]; +// uint32_t val; +// size_t sz; + +// GNUNET_memcpy (&val, +// in, +// sizeof(val)); +// sz = ntohl (val); +// FAIL_IF (sizeof(be) > sz); + +// in += sizeof(val); +// GNUNET_memcpy (&be, +// in, +// sizeof(be)); +// FAIL_IF (0x01 != ntohl (be[1])); /* magic marker: blinded */ + +// in += sizeof(be); +// sz -= sizeof(be); + +// denom_sig->cipher = ntohl (be[0]); +// switch (denom_sig->cipher) +// { +// case TALER_DENOMINATION_RSA: +// denom_sig->details.blinded_rsa_signature = +// GNUNET_CRYPTO_rsa_signature_decode (in, +// sz); +// FAIL_IF (NULL == denom_sig->details.blinded_rsa_signature); +// break; + +// case TALER_DENOMINATION_CS: +// FAIL_IF (sizeof(denom_sig->details.blinded_cs_answer) != sz); +// GNUNET_memcpy (&denom_sig->details.blinded_cs_answer, +// in, +// sz); +// break; + +// default: +// FAIL_IF (true); +// } + +// in += sz; +// } +// return GNUNET_OK; +// } +// default: +// FAIL_IF (true); +// } +// } + +// FAIL: +// GNUNET_free (*(void **) dst); +// return GNUNET_SYSERR; +// #undef FAIL_IF + +// } + + +// /** +// * Cleanup of the data and closure of an array spec. +// */ +// static void +// array_cleanup (void *cls, +// void *rd) +// { + +// struct ArrayResultCls *info = cls; +// void **dst = rd; + +// if ((0 == info->same_size) && +// (NULL != info->sizes)) +// GNUNET_free (*(info->sizes)); + +// GNUNET_free (cls); +// GNUNET_free (*dst); +// *dst = NULL; +// } + + +// struct GNUNET_PQ_ResultSpec +// TALER_PQ_result_spec_array_blinded_denom_sig ( +// struct GNUNET_PQ_Context *db, +// const char *name, +// size_t *num, +// struct TALER_BlindedDenominationSignature **denom_sigs) +// { +// struct ArrayResultCls *info = GNUNET_new (struct ArrayResultCls); + +// info->num = num; +// info->typ = TALER_PQ_array_of_blinded_denom_sig; +// GNUNET_assert (GNUNET_OK == +// GNUNET_PQ_get_oid_by_name (db, +// "bytea", +// &info->oid)); + +// struct GNUNET_PQ_ResultSpec res = { +// .conv = extract_array_generic, +// .cleaner = array_cleanup, +// .dst = (void *) denom_sigs, +// .fname = name, +// .cls = info +// }; +// return res; + +// }; + +// struct GNUNET_PQ_ResultSpec +// TALER_PQ_result_spec_array_blinded_coin_hash ( +// struct GNUNET_PQ_Context *db, +// const char *name, +// size_t *num, +// struct TALER_BlindedCoinHashP **h_coin_evs) +// { +// struct ArrayResultCls *info = GNUNET_new (struct ArrayResultCls); + +// info->num = num; +// info->typ = TALER_PQ_array_of_blinded_coin_hash; +// GNUNET_assert (GNUNET_OK == +// GNUNET_PQ_get_oid_by_name (db, +// "bytea", +// &info->oid)); + +// struct GNUNET_PQ_ResultSpec res = { +// .conv = extract_array_generic, +// .cleaner = array_cleanup, +// .dst = (void *) h_coin_evs, +// .fname = name, +// .cls = info +// }; +// return res; + +// }; + +// struct GNUNET_PQ_ResultSpec +// TALER_PQ_result_spec_array_denom_hash ( +// struct GNUNET_PQ_Context *db, +// const char *name, +// size_t *num, +// struct TALER_DenominationHashP **denom_hs) +// { +// struct ArrayResultCls *info = GNUNET_new (struct ArrayResultCls); + +// info->num = num; +// info->typ = TALER_PQ_array_of_denom_hash; +// GNUNET_assert (GNUNET_OK == +// GNUNET_PQ_get_oid_by_name (db, +// "bytea", +// &info->oid)); + +// struct GNUNET_PQ_ResultSpec res = { +// .conv = extract_array_generic, +// .cleaner = array_cleanup, +// .dst = (void *) denom_hs, +// .fname = name, +// .cls = info +// }; +// return res; + +// }; + +// struct GNUNET_PQ_ResultSpec +// TALER_PQ_result_spec_array_amount ( +// struct GNUNET_PQ_Context *db, +// const char *name, +// const char *currency, +// size_t *num, +// struct TALER_Amount **amounts) +// { +// struct ArrayResultCls *info = GNUNET_new (struct ArrayResultCls); + +// info->num = num; +// info->typ = TALER_PQ_array_of_amount; +// info->db = db; +// GNUNET_assert (GNUNET_OK == +// GNUNET_PQ_get_oid_by_name (db, +// "taler_amount", +// &info->oid)); + +// { +// size_t clen = GNUNET_MIN (TALER_CURRENCY_LEN - 1, +// strlen (currency)); +// GNUNET_memcpy (&info->currency, +// currency, +// clen); +// } + +// struct GNUNET_PQ_ResultSpec res = { +// .conv = extract_array_generic, +// .cleaner = array_cleanup, +// .dst = (void *) amounts, +// .fname = name, +// .cls = info, +// }; +// return res; + + +// } /* end of pq_result_helper.c */