gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-merchant] branch master updated: -fix bugs, FTBFS


From: gnunet
Subject: [taler-merchant] branch master updated: -fix bugs, FTBFS
Date: Wed, 21 Jul 2021 15:29:58 +0200

This is an automated email from the git hooks/post-receive script.

grothoff pushed a commit to branch master
in repository merchant.

The following commit(s) were added to refs/heads/master by this push:
     new 4c184f7e -fix bugs, FTBFS
4c184f7e is described below

commit 4c184f7e685817b565013c3afb2a5c30ecf10161
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Wed Jul 21 15:29:48 2021 +0200

    -fix bugs, FTBFS
---
 src/backend/taler-merchant-httpd_helper.c          |  68 +++++++++++
 src/backend/taler-merchant-httpd_helper.h          |  21 ++++
 ...er-merchant-httpd_private-delete-instances-ID.c |  23 ++--
 ...ler-merchant-httpd_private-delete-products-ID.c |  12 +-
 .../taler-merchant-httpd_private-get-products-ID.c |  30 ++---
 ...aler-merchant-httpd_private-patch-products-ID.c |  88 ++++++++++----
 .../taler-merchant-httpd_private-post-products.c   | 135 +++++++++++++++------
 src/backenddb/plugin_merchantdb_postgres.c         |  85 +++++++------
 8 files changed, 335 insertions(+), 127 deletions(-)

diff --git a/src/backend/taler-merchant-httpd_helper.c 
b/src/backend/taler-merchant-httpd_helper.c
index fb0cf318..20be2b45 100644
--- a/src/backend/taler-merchant-httpd_helper.c
+++ b/src/backend/taler-merchant-httpd_helper.c
@@ -80,6 +80,74 @@ TMH_payto_uri_array_valid (const json_t *payto_uris)
 }
 
 
+bool
+TMH_location_object_valid (const json_t *location)
+{
+  return true; // FIXME
+}
+
+
+// FIXME
+bool
+TMH_i18n_object_valid (const json_t *i18n)
+{
+  return true; // FIXME
+}
+
+
+// FIXME
+bool
+TMH_image_data_url_valid (const char *image_data_url)
+{
+  if (0 == strcmp (image_data_url,
+                   ""))
+    return true;
+  if (0 != strncasecmp ("data:image/",
+                        image_data_url,
+                        strlen ("data:image/")))
+    return false;
+  if (NULL == strstr (";base64,",
+                      image_data_url))
+    return false;
+  // FIXME: write generic URI syntax validation */
+  return true;
+}
+
+
+bool
+TMH_taxes_array_valid (const json_t *taxes)
+{
+  json_t *tax;
+  size_t idx;
+
+  if (! json_is_array (taxes))
+    return false;
+  json_array_foreach (taxes, idx, tax)
+  {
+    struct TALER_Amount amount;
+    const char *name;
+    struct GNUNET_JSON_Specification spec[] = {
+      GNUNET_JSON_spec_string ("name",
+                               &name),
+      TALER_JSON_spec_amount ("tax",
+                              &amount),
+      GNUNET_JSON_spec_end ()
+    };
+    enum GNUNET_GenericReturnValue res;
+
+    res = TALER_MHD_parse_json_data (NULL,
+                                     tax,
+                                     spec);
+    if (GNUNET_OK != res)
+    {
+      GNUNET_break_op (0);
+      return false;
+    }
+  }
+  return true;
+}
+
+
 struct TMH_WireMethod *
 TMH_setup_wire_account (const char *payto_uri)
 {
diff --git a/src/backend/taler-merchant-httpd_helper.h 
b/src/backend/taler-merchant-httpd_helper.h
index d15ef2e0..0460665b 100644
--- a/src/backend/taler-merchant-httpd_helper.h
+++ b/src/backend/taler-merchant-httpd_helper.h
@@ -37,6 +37,27 @@ bool
 TMH_payto_uri_array_valid (const json_t *payto_uris);
 
 
+/**
+ * FIXME.
+ */
+bool
+TMH_taxes_array_valid (const json_t *taxes);
+
+
+// FIXME
+bool
+TMH_location_object_valid (const json_t *location);
+
+
+// FIXME
+bool
+TMH_i18n_object_valid (const json_t *i18n);
+
+
+// FIXME
+bool
+TMH_image_data_url_valid (const char *image_data_url);
+
 /**
  * Setup new wire method for the given @ payto_uri.
  *
diff --git a/src/backend/taler-merchant-httpd_private-delete-instances-ID.c 
b/src/backend/taler-merchant-httpd_private-delete-instances-ID.c
index 919c21c9..0de88164 100644
--- a/src/backend/taler-merchant-httpd_private-delete-instances-ID.c
+++ b/src/backend/taler-merchant-httpd_private-delete-instances-ID.c
@@ -34,16 +34,19 @@ static MHD_RESULT
 delete_instances_ID (struct TMH_MerchantInstance *mi,
                      struct MHD_Connection *connection)
 {
-  const char *purge;
+  const char *purge_s;
+  bool purge;
   enum GNUNET_DB_QueryStatus qs;
 
   GNUNET_assert (NULL != mi);
-  purge = MHD_lookup_connection_value (connection,
-                                       MHD_GET_ARGUMENT_KIND,
-                                       "purge");
-  if ( (NULL != purge) &&
-       (0 == strcmp (purge,
-                     "yes")) )
+  purge_s = MHD_lookup_connection_value (connection,
+                                         MHD_GET_ARGUMENT_KIND,
+                                         "purge");
+  if (NULL == purge_s)
+    purge_s = "no";
+  purge = (0 == strcmp (purge_s,
+                        "yes"));
+  if (purge)
     qs = TMH_db->purge_instance (TMH_db->cls,
                                  mi->settings.id);
   else
@@ -66,13 +69,11 @@ delete_instances_ID (struct TMH_MerchantInstance *mi,
     return TALER_MHD_reply_with_error (connection,
                                        MHD_HTTP_NOT_FOUND,
                                        
TALER_EC_MERCHANT_GENERIC_INSTANCE_UNKNOWN,
-                                       ( (NULL != purge) &&
-                                         (0 == strcmp (purge,
-                                                       "yes")) )
+                                       purge
                                        ? "Instance unknown"
                                        : "Private key unknown");
   case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
-    if (NULL != purge)
+    if (purge)
       TMH_instance_decref (mi);
     else
       mi->deleted = true;
diff --git a/src/backend/taler-merchant-httpd_private-delete-products-ID.c 
b/src/backend/taler-merchant-httpd_private-delete-products-ID.c
index 2d17bafc..bb7964aa 100644
--- a/src/backend/taler-merchant-httpd_private-delete-products-ID.c
+++ b/src/backend/taler-merchant-httpd_private-delete-products-ID.c
@@ -40,6 +40,7 @@ TMH_private_delete_products_ID (const struct 
TMH_RequestHandler *rh,
   enum GNUNET_DB_QueryStatus qs;
 
   GNUNET_assert (NULL != mi);
+  GNUNET_assert (NULL != hc->infix);
   qs = TMH_db->delete_product (TMH_db->cls,
                                mi->settings.id,
                                hc->infix);
@@ -49,18 +50,25 @@ TMH_private_delete_products_ID (const struct 
TMH_RequestHandler *rh,
     return TALER_MHD_reply_with_error (connection,
                                        MHD_HTTP_INTERNAL_SERVER_ERROR,
                                        TALER_EC_GENERIC_DB_STORE_FAILED,
-                                       NULL);
+                                       "delete_product");
   case GNUNET_DB_STATUS_SOFT_ERROR:
     GNUNET_break (0);
     return TALER_MHD_reply_with_error (connection,
                                        MHD_HTTP_INTERNAL_SERVER_ERROR,
                                        
TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
-                                       NULL);
+                                       "delete_product (soft)");
   case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+    /* check if deletion must have failed because of locks by
+       checking if the product exists */
     qs = TMH_db->lookup_product (TMH_db->cls,
                                  mi->settings.id,
                                  hc->infix,
                                  NULL);
+    if (GNUNET_DB_STATUS_HARD_ERROR == qs)
+      return TALER_MHD_reply_with_error (connection,
+                                         MHD_HTTP_INTERNAL_SERVER_ERROR,
+                                         TALER_EC_GENERIC_DB_STORE_FAILED,
+                                         "lookup_product");
     if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
       return TALER_MHD_reply_with_error (connection,
                                          MHD_HTTP_NOT_FOUND,
diff --git a/src/backend/taler-merchant-httpd_private-get-products-ID.c 
b/src/backend/taler-merchant-httpd_private-get-products-ID.c
index 1fdabc8f..32be4d7c 100644
--- a/src/backend/taler-merchant-httpd_private-get-products-ID.c
+++ b/src/backend/taler-merchant-httpd_private-get-products-ID.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  (C) 2019, 2020 Taler Systems SA
+  (C) 2019, 2020, 2021 Taler Systems SA
 
   TALER is free software; you can redistribute it and/or modify it under the
   terms of the GNU Affero General Public License as published by the Free 
Software
@@ -51,28 +51,32 @@ TMH_private_get_products_ID (const struct 
TMH_RequestHandler *rh,
     return TALER_MHD_reply_with_error (connection,
                                        MHD_HTTP_INTERNAL_SERVER_ERROR,
                                        TALER_EC_GENERIC_DB_FETCH_FAILED,
-                                       NULL);
+                                       "lookup_product");
   }
-  else if (0 == qs)
+  if (0 == qs)
   {
     return TALER_MHD_reply_with_error (connection,
                                        MHD_HTTP_NOT_FOUND,
                                        
TALER_EC_MERCHANT_GENERIC_PRODUCT_UNKNOWN,
-                                       NULL);
+                                       hc->infix);
   }
   {
     json_t *reply;
     MHD_RESULT ret;
 
     reply = json_pack (
-      "{s:s, s:s, s:o, s:o, s:I,"
-      " s:I, s:I, s:o, s:o, s:s}",
+      "{s:s, s:o, s:s, s:o, s:o,"
+      " s:o, s:I, s:I, s:I, s:o}",
       "description",
       pd.description,
+      "description_i18n",
+      pd.description_i18n,
       "unit",
       pd.unit,
       "price",
       TALER_JSON_from_amount (&pd.price),
+      "image",
+      pd.image,
       "taxes",
       pd.taxes,
       "total_stock",
@@ -84,18 +88,16 @@ TMH_private_get_products_ID (const struct 
TMH_RequestHandler *rh,
       (json_int_t) pd.total_sold,
       "total_lost",
       (json_int_t) pd.total_lost,
-      "description_i18n",
-      pd.description_i18n,
       "address",
-      pd.address,
-      "image",
-      pd.image);
+      pd.address);
     GNUNET_free (pd.description);
     GNUNET_free (pd.unit);
     if (0 != pd.next_restock.abs_value_us)
-      json_object_set_new (reply,
-                           "next_restock",
-                           GNUNET_JSON_from_time_abs (pd.next_restock));
+      GNUNET_assert (0 ==
+                     json_object_set_new (
+                       reply,
+                       "next_restock",
+                       GNUNET_JSON_from_time_abs (pd.next_restock)));
     ret = TALER_MHD_reply_json (connection,
                                 reply,
                                 MHD_HTTP_OK);
diff --git a/src/backend/taler-merchant-httpd_private-patch-products-ID.c 
b/src/backend/taler-merchant-httpd_private-patch-products-ID.c
index 3ea9b112..46436d06 100644
--- a/src/backend/taler-merchant-httpd_private-patch-products-ID.c
+++ b/src/backend/taler-merchant-httpd_private-patch-products-ID.c
@@ -24,6 +24,7 @@
  */
 #include "platform.h"
 #include "taler-merchant-httpd_private-patch-products-ID.h"
+#include "taler-merchant-httpd_helper.h"
 #include <taler/taler_json_lib.h>
 
 
@@ -87,8 +88,6 @@ determine_cause (struct MHD_Connection *connection,
       ec = TALER_EC_MERCHANT_PRIVATE_PATCH_PRODUCTS_TOTAL_SOLD_REDUCED;
     if (pdx.total_stock > pd->total_stock)
       ec = TALER_EC_MERCHANT_PRIVATE_PATCH_PRODUCTS_TOTAL_STOCKED_REDUCED;
-    if (pd->total_stock < pd->total_sold + pd->total_lost)
-      ec = TALER_EC_MERCHANT_PRIVATE_PATCH_PRODUCTS_TOTAL_LOST_EXCEEDS_STOCKS;
     TALER_MERCHANTDB_product_details_free (&pdx);
     GNUNET_break (TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE != ec);
     return TALER_MHD_reply_with_error (connection,
@@ -133,14 +132,14 @@ TMH_private_patch_products_ID (const struct 
TMH_RequestHandler *rh,
     GNUNET_JSON_spec_mark_optional (
       GNUNET_JSON_spec_json ("taxes",
                              &pd.taxes)),
-    GNUNET_JSON_spec_mark_optional (
-      GNUNET_JSON_spec_json ("address",
-                             &pd.address)),
     GNUNET_JSON_spec_int64 ("total_stock",
                             &total_stock),
     GNUNET_JSON_spec_mark_optional (
       GNUNET_JSON_spec_uint64 ("total_lost",
                                &pd.total_lost)),
+    GNUNET_JSON_spec_mark_optional (
+      GNUNET_JSON_spec_json ("address",
+                             &pd.address)),
     GNUNET_JSON_spec_mark_optional (
       TALER_JSON_spec_absolute_time ("next_restock",
                                      &pd.next_restock)),
@@ -170,7 +169,16 @@ TMH_private_patch_products_ID (const struct 
TMH_RequestHandler *rh,
     return TALER_MHD_reply_with_error (connection,
                                        MHD_HTTP_CONFLICT,
                                        TALER_EC_GENERIC_CURRENCY_MISMATCH,
-                                       NULL);
+                                       TMH_currency);
+  }
+  if (total_stock < -1)
+  {
+    GNUNET_break_op (0);
+    GNUNET_JSON_parse_free (spec);
+    return TALER_MHD_reply_with_error (connection,
+                                       MHD_HTTP_BAD_REQUEST,
+                                       TALER_EC_GENERIC_PARAMETER_MALFORMED,
+                                       "total_stock");
   }
   if (-1 == total_stock)
     pd.total_stock = INT64_MAX;
@@ -178,35 +186,63 @@ TMH_private_patch_products_ID (const struct 
TMH_RequestHandler *rh,
     pd.total_stock = (uint64_t) total_stock;
   if (NULL == pd.address)
     pd.address = json_object ();
+
+  if (! TMH_location_object_valid (pd.address))
+  {
+    GNUNET_break_op (0);
+    GNUNET_JSON_parse_free (spec);
+    return TALER_MHD_reply_with_error (connection,
+                                       MHD_HTTP_BAD_REQUEST,
+                                       TALER_EC_GENERIC_PARAMETER_MALFORMED,
+                                       "address");
+  }
   if (NULL == pd.description_i18n)
     pd.description_i18n = json_object ();
+
+  if (! TMH_i18n_object_valid (pd.description_i18n))
+  {
+    GNUNET_break_op (0);
+    GNUNET_JSON_parse_free (spec);
+    return TALER_MHD_reply_with_error (connection,
+                                       MHD_HTTP_BAD_REQUEST,
+                                       TALER_EC_GENERIC_PARAMETER_MALFORMED,
+                                       "description_i18n");
+  }
+
   if (NULL == pd.taxes)
-    pd.taxes = json_object ();
+    pd.taxes = json_array ();
+  /* check taxes is well-formed */
+  if (! TMH_taxes_array_valid (pd.taxes))
+  {
+    GNUNET_break_op (0);
+    GNUNET_JSON_parse_free (spec);
+    return TALER_MHD_reply_with_error (connection,
+                                       MHD_HTTP_BAD_REQUEST,
+                                       TALER_EC_GENERIC_PARAMETER_MALFORMED,
+                                       "taxes");
+  }
   if (NULL == pd.image)
     pd.image = "";
-  if (NULL != json_object_get (hc->request_body,
-                               "next_restock"))
+  if (! TMH_image_data_url_valid (pd.image))
   {
-    enum GNUNET_GenericReturnValue res;
-    struct GNUNET_JSON_Specification spec[] = {
-      TALER_JSON_spec_absolute_time ("next_restock",
-                                     &pd.next_restock),
-      GNUNET_JSON_spec_end ()
-    };
-
-    res = TALER_MHD_parse_json_data (connection,
-                                     hc->request_body,
-                                     spec);
-    if (GNUNET_OK != res)
-      return (GNUNET_NO == res)
-             ? MHD_YES
-             : MHD_NO;
+    GNUNET_break_op (0);
+    GNUNET_JSON_parse_free (spec);
+    return TALER_MHD_reply_with_error (connection,
+                                       MHD_HTTP_BAD_REQUEST,
+                                       TALER_EC_GENERIC_PARAMETER_MALFORMED,
+                                       "image");
   }
-  else
+  if ( (pd.total_stock < pd.total_sold + pd.total_lost) ||
+       (pd.total_sold + pd.total_lost < pd.total_sold) /* integer overflow */)
   {
-    pd.next_restock.abs_value_us = 0;
+    GNUNET_break_op (0);
+    GNUNET_JSON_parse_free (spec);
+    return TALER_MHD_reply_with_error (
+      connection,
+      MHD_HTTP_BAD_REQUEST,
+      TALER_EC_MERCHANT_PRIVATE_PATCH_PRODUCTS_TOTAL_LOST_EXCEEDS_STOCKS,
+      NULL);
   }
-
   qs = TMH_db->update_product (TMH_db->cls,
                                mi->settings.id,
                                product_id,
diff --git a/src/backend/taler-merchant-httpd_private-post-products.c 
b/src/backend/taler-merchant-httpd_private-post-products.c
index 76413cc4..4cf97fd0 100644
--- a/src/backend/taler-merchant-httpd_private-post-products.c
+++ b/src/backend/taler-merchant-httpd_private-post-products.c
@@ -24,6 +24,7 @@
  */
 #include "platform.h"
 #include "taler-merchant-httpd_private-post-products.h"
+#include "taler-merchant-httpd_helper.h"
 #include <taler/taler_json_lib.h>
 
 
@@ -50,8 +51,9 @@ products_equal (const struct TALER_MERCHANTDB_ProductDetails 
*p1,
                              p2->description_i18n)) &&
            (0 == strcmp (p1->unit,
                          p2->unit)) &&
-           (GNUNET_OK == TALER_amount_cmp_currency (&p1->price,
-                                                    &p2->price)) &&
+           (GNUNET_OK ==
+            TALER_amount_cmp_currency (&p1->price,
+                                       &p2->price)) &&
            (0 == TALER_amount_cmp (&p1->price,
                                    &p2->price)) &&
            (1 == json_equal (p1->taxes,
@@ -86,9 +88,6 @@ TMH_private_post_products (const struct TMH_RequestHandler 
*rh,
     GNUNET_JSON_spec_mark_optional (
       GNUNET_JSON_spec_json ("description_i18n",
                              &pd.description_i18n)),
-    GNUNET_JSON_spec_mark_optional (
-      TALER_JSON_spec_absolute_time ("next_restock",
-                                     &pd.next_restock)),
     GNUNET_JSON_spec_string ("unit",
                              (const char **) &pd.unit),
     TALER_JSON_spec_amount ("price",
@@ -99,11 +98,11 @@ TMH_private_post_products (const struct TMH_RequestHandler 
*rh,
     GNUNET_JSON_spec_mark_optional (
       GNUNET_JSON_spec_json ("taxes",
                              &pd.taxes)),
+    GNUNET_JSON_spec_int64 ("total_stock",
+                            &total_stock),
     GNUNET_JSON_spec_mark_optional (
       GNUNET_JSON_spec_json ("address",
                              &pd.address)),
-    GNUNET_JSON_spec_int64 ("total_stock",
-                            &total_stock),
     GNUNET_JSON_spec_mark_optional (
       TALER_JSON_spec_absolute_time ("next_restock",
                                      &pd.next_restock)),
@@ -134,8 +133,19 @@ TMH_private_post_products (const struct TMH_RequestHandler 
*rh,
     return TALER_MHD_reply_with_error (connection,
                                        MHD_HTTP_CONFLICT,
                                        TALER_EC_GENERIC_CURRENCY_MISMATCH,
-                                       NULL);
+                                       TMH_currency);
+  }
+  if (total_stock < -1)
+  {
+    GNUNET_break_op (0);
+    GNUNET_JSON_parse_free (spec);
+    return TALER_MHD_reply_with_error (connection,
+                                       MHD_HTTP_BAD_REQUEST,
+                                       TALER_EC_GENERIC_PARAMETER_MALFORMED,
+                                       "total_stock");
   }
+
+
   if (-1 == total_stock)
     pd.total_stock = INT64_MAX;
   else
@@ -146,9 +156,52 @@ TMH_private_post_products (const struct TMH_RequestHandler 
*rh,
   if (NULL == pd.description_i18n)
     pd.description_i18n = json_object ();
   if (NULL == pd.taxes)
-    pd.taxes = json_object ();
+    pd.taxes = json_array ();
+
+  /* check taxes is well-formed */
+  if (! TMH_taxes_array_valid (pd.taxes))
+  {
+    GNUNET_break_op (0);
+    GNUNET_JSON_parse_free (spec);
+    return TALER_MHD_reply_with_error (connection,
+                                       MHD_HTTP_BAD_REQUEST,
+                                       TALER_EC_GENERIC_PARAMETER_MALFORMED,
+                                       "taxes");
+  }
+
+  if (! TMH_location_object_valid (pd.address))
+  {
+    GNUNET_break_op (0);
+    GNUNET_JSON_parse_free (spec);
+    return TALER_MHD_reply_with_error (connection,
+                                       MHD_HTTP_BAD_REQUEST,
+                                       TALER_EC_GENERIC_PARAMETER_MALFORMED,
+                                       "address");
+  }
+
+  if (! TMH_i18n_object_valid (pd.description_i18n))
+  {
+    GNUNET_break_op (0);
+    GNUNET_JSON_parse_free (spec);
+    return TALER_MHD_reply_with_error (connection,
+                                       MHD_HTTP_BAD_REQUEST,
+                                       TALER_EC_GENERIC_PARAMETER_MALFORMED,
+                                       "description_i18n");
+  }
+
   if (NULL == pd.image)
     pd.image = "";
+  if (! TMH_image_data_url_valid (pd.image))
+  {
+    GNUNET_break_op (0);
+    GNUNET_JSON_parse_free (spec);
+    return TALER_MHD_reply_with_error (connection,
+                                       MHD_HTTP_BAD_REQUEST,
+                                       TALER_EC_GENERIC_PARAMETER_MALFORMED,
+                                       "image");
+  }
+
+  /* finally, interact with DB until no serialization error */
   for (unsigned int i = 0; i<MAX_RETRIES; i++)
   {
     /* Test if an product of this id is known */
@@ -173,7 +226,13 @@ TMH_private_post_products (const struct TMH_RequestHandler 
*rh,
     {
     case GNUNET_DB_STATUS_HARD_ERROR:
       /* Clean up and fail hard */
-      break;
+      GNUNET_break (0);
+      TMH_db->rollback (TMH_db->cls);
+      GNUNET_JSON_parse_free (spec);
+      return TALER_MHD_reply_with_error (connection,
+                                         MHD_HTTP_INTERNAL_SERVER_ERROR,
+                                         TALER_EC_GENERIC_DB_FETCH_FAILED,
+                                         NULL);
     case GNUNET_DB_STATUS_SOFT_ERROR:
       /* restart transaction */
       goto retry;
@@ -182,50 +241,50 @@ TMH_private_post_products (const struct 
TMH_RequestHandler *rh,
       break;
     case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
       /* idempotency check: is epd == pd? */
-      if (products_equal (&pd,
-                          &epd))
-      {
-        TALER_MERCHANTDB_product_details_free (&epd);
-        TMH_db->rollback (TMH_db->cls);
-        GNUNET_JSON_parse_free (spec);
-        return TALER_MHD_reply_static (connection,
-                                       MHD_HTTP_NO_CONTENT,
-                                       NULL,
-                                       NULL,
-                                       0);
-      }
-      else
       {
+        bool eq;
+
+        eq = products_equal (&pd,
+                             &epd);
         TALER_MERCHANTDB_product_details_free (&epd);
         TMH_db->rollback (TMH_db->cls);
         GNUNET_JSON_parse_free (spec);
-        return TALER_MHD_reply_with_error (connection,
-                                           MHD_HTTP_CONFLICT,
-                                           
TALER_EC_MERCHANT_PRIVATE_POST_PRODUCTS_CONFLICT_PRODUCT_EXISTS,
-                                           product_id);
+        return eq
+          ? TALER_MHD_reply_static (connection,
+                                    MHD_HTTP_NO_CONTENT,
+                                    NULL,
+                                    NULL,
+                                    0)
+          : TALER_MHD_reply_with_error (connection,
+                                        MHD_HTTP_CONFLICT,
+                                        
TALER_EC_MERCHANT_PRIVATE_POST_PRODUCTS_CONFLICT_PRODUCT_EXISTS,
+                                        product_id);
       }
-    }
+    } /* end switch (qs) */
 
     qs = TMH_db->insert_product (TMH_db->cls,
                                  mi->settings.id,
                                  product_id,
                                  &pd);
-    if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
-      goto retry;
-    qs = TMH_db->commit (TMH_db->cls);
-    if (GNUNET_DB_STATUS_SOFT_ERROR != qs)
-      break;
-retry:
-    if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
+    if (GNUNET_DB_STATUS_HARD_ERROR == qs)
     {
       TMH_db->rollback (TMH_db->cls);
-      continue;
+      break;
     }
-  }
+    if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
+    {
+      qs = TMH_db->commit (TMH_db->cls);
+      if (GNUNET_DB_STATUS_SOFT_ERROR != qs)
+        break;
+    }
+retry:
+    GNUNET_assert (GNUNET_DB_STATUS_SOFT_ERROR == qs);
+    TMH_db->rollback (TMH_db->cls);
+  } /* for RETRIES loop */
   GNUNET_JSON_parse_free (spec);
   if (qs < 0)
   {
-    GNUNET_break_op (0);
+    GNUNET_break (0);
     return TALER_MHD_reply_with_error (
       connection,
       MHD_HTTP_INTERNAL_SERVER_ERROR,
diff --git a/src/backenddb/plugin_merchantdb_postgres.c 
b/src/backenddb/plugin_merchantdb_postgres.c
index 86e30d0b..54a7241b 100644
--- a/src/backenddb/plugin_merchantdb_postgres.c
+++ b/src/backenddb/plugin_merchantdb_postgres.c
@@ -1000,42 +1000,53 @@ postgres_lookup_product (void *cls,
     GNUNET_PQ_query_param_string (product_id),
     GNUNET_PQ_query_param_end
   };
-  struct GNUNET_PQ_ResultSpec rs[] = {
-    GNUNET_PQ_result_spec_string ("description",
-                                  &pd->description),
-    TALER_PQ_result_spec_json ("description_i18n",
-                               &pd->description_i18n),
-    GNUNET_PQ_result_spec_string ("unit",
-                                  &pd->unit),
-    TALER_PQ_RESULT_SPEC_AMOUNT ("price",
-                                 &pd->price),
-    TALER_PQ_result_spec_json ("taxes",
-                               &pd->taxes),
-    GNUNET_PQ_result_spec_uint64 ("total_stock",
-                                  &pd->total_stock),
-    GNUNET_PQ_result_spec_uint64 ("total_sold",
-                                  &pd->total_sold),
-    GNUNET_PQ_result_spec_uint64 ("total_lost",
-                                  &pd->total_lost),
-    GNUNET_PQ_result_spec_string ("image",
-                                  &pd->image),
-    TALER_PQ_result_spec_json ("address",
-                               &pd->address),
-    GNUNET_PQ_result_spec_absolute_time ("next_restock",
-                                         &pd->next_restock),
-    GNUNET_PQ_result_spec_end
-  };
-  struct GNUNET_PQ_ResultSpec rs_null[] = {
-    GNUNET_PQ_result_spec_end
-  };
 
-  check_connection (pg);
-  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   "lookup_product",
-                                                   params,
-                                                   (NULL == pd)
-                                                   ? rs_null
-                                                   : rs);
+  if (NULL == pd)
+  {
+    struct GNUNET_PQ_ResultSpec rs_null[] = {
+      GNUNET_PQ_result_spec_end
+    };
+
+    check_connection (pg);
+    return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                     "lookup_product",
+                                                     params,
+                                                     rs_null);
+  }
+  else
+  {
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_string ("description",
+                                    &pd->description),
+      TALER_PQ_result_spec_json ("description_i18n",
+                                 &pd->description_i18n),
+      GNUNET_PQ_result_spec_string ("unit",
+                                    &pd->unit),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("price",
+                                   &pd->price),
+      TALER_PQ_result_spec_json ("taxes",
+                                 &pd->taxes),
+      GNUNET_PQ_result_spec_uint64 ("total_stock",
+                                    &pd->total_stock),
+      GNUNET_PQ_result_spec_uint64 ("total_sold",
+                                    &pd->total_sold),
+      GNUNET_PQ_result_spec_uint64 ("total_lost",
+                                    &pd->total_lost),
+      GNUNET_PQ_result_spec_string ("image",
+                                    &pd->image),
+      TALER_PQ_result_spec_json ("address",
+                                 &pd->address),
+      GNUNET_PQ_result_spec_absolute_time ("next_restock",
+                                           &pd->next_restock),
+      GNUNET_PQ_result_spec_end
+    };
+
+    check_connection (pg);
+    return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                     "lookup_product",
+                                                     params,
+                                                     rs);
+  }
 }
 
 
@@ -1148,7 +1159,9 @@ postgres_update_product (void *cls,
     GNUNET_PQ_query_param_end
   };
 
-  if (pd->total_stock < pd->total_lost + pd->total_sold)
+  if ( (pd->total_stock < pd->total_lost + pd->total_sold) ||
+       (pd->total_lost < pd->total_lost
+        + pd->total_sold) /* integer overflow */)
   {
     GNUNET_break (0);
     return GNUNET_DB_STATUS_HARD_ERROR;

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]