gnunet-svn
[Top][All Lists]
Advanced

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

[taler-exchange] branch master updated: more strict spec parsers for pay


From: gnunet
Subject: [taler-exchange] branch master updated: more strict spec parsers for payto URIs, Web URLs, and AML decision states
Date: Sat, 25 Nov 2023 07:04:53 +0100

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

grothoff pushed a commit to branch master
in repository exchange.

The following commit(s) were added to refs/heads/master by this push:
     new 9a4407f7 more strict spec parsers for payto URIs, Web URLs, and AML 
decision states
9a4407f7 is described below

commit 9a4407f7a58af8cfe208436152fa32233a5ca0b3
Author: Christian Grothoff <grothoff@gnunet.org>
AuthorDate: Sat Nov 25 15:04:44 2023 +0900

    more strict spec parsers for payto URIs, Web URLs, and AML decision states
---
 contrib/gana                                       |   2 +-
 contrib/wallet-core                                |   2 +-
 src/exchange-tools/taler-exchange-offline.c        |  18 +-
 src/exchange/taler-exchange-httpd_aml-decision.c   |   6 +-
 src/exchange/taler-exchange-httpd_batch-deposit.c  |   4 +-
 .../taler-exchange-httpd_management_auditors.c     |   2 +-
 .../taler-exchange-httpd_management_drain.c        |   4 +-
 .../taler-exchange-httpd_management_partners.c     |   2 +-
 .../taler-exchange-httpd_management_wire_disable.c |   4 +-
 .../taler-exchange-httpd_management_wire_enable.c  |   6 +-
 src/exchange/taler-exchange-httpd_purses_merge.c   |   4 +-
 src/exchange/taler-exchange-httpd_reserves_close.c |   4 +-
 src/include/taler_crypto_lib.h                     |   6 +-
 src/include/taler_exchange_service.h               |   2 +-
 src/include/taler_json_lib.h                       | 100 +++++++-
 src/include/taler_util.h                           |  11 +
 src/json/json_helper.c                             | 270 +++++++++++++++++++++
 src/lib/auditor_api_exchanges.c                    |   2 +-
 src/lib/auditor_api_get_config.c                   |  25 +-
 src/lib/exchange_api_batch_deposit.c               |   2 +-
 src/lib/exchange_api_coins_history.c               |   2 +-
 src/lib/exchange_api_common.c                      |  22 +-
 src/lib/exchange_api_deposits_get.c                |   7 +-
 src/lib/exchange_api_handle.c                      |  37 +--
 src/lib/exchange_api_kyc_check.c                   |  24 +-
 src/lib/exchange_api_lookup_aml_decision.c         |   6 +-
 src/lib/exchange_api_lookup_aml_decisions.c        |   6 +-
 src/lib/exchange_api_reserves_history.c            |  10 +-
 src/util/url.c                                     |  16 ++
 29 files changed, 474 insertions(+), 132 deletions(-)

diff --git a/contrib/gana b/contrib/gana
index 27de0765..2ccbe6a2 160000
--- a/contrib/gana
+++ b/contrib/gana
@@ -1 +1 @@
-Subproject commit 27de076550489d6ca0b99822121579e02fee4cf2
+Subproject commit 2ccbe6a28c86fb1618d30b3d76d9fd70c95203ae
diff --git a/contrib/wallet-core b/contrib/wallet-core
index 621dad2c..6eca153b 160000
--- a/contrib/wallet-core
+++ b/contrib/wallet-core
@@ -1 +1 @@
-Subproject commit 621dad2c2ec9a2adc52076cebf65891d6764c802
+Subproject commit 6eca153b329953b703d0517dbd65001715431c6c
diff --git a/src/exchange-tools/taler-exchange-offline.c 
b/src/exchange-tools/taler-exchange-offline.c
index 3eb0ba46..1a8d61e7 100644
--- a/src/exchange-tools/taler-exchange-offline.c
+++ b/src/exchange-tools/taler-exchange-offline.c
@@ -1350,7 +1350,7 @@ upload_auditor_add (const char *exchange_url,
   const char *err_name;
   unsigned int err_line;
   struct GNUNET_JSON_Specification spec[] = {
-    GNUNET_JSON_spec_string ("auditor_url",
+    TALER_JSON_spec_web_url ("auditor_url",
                              &auditor_url),
     GNUNET_JSON_spec_string ("auditor_name",
                              &auditor_name),
@@ -1547,10 +1547,10 @@ upload_wire_add (const char *exchange_url,
   const json_t *credit_restrictions;
   unsigned int err_line;
   struct GNUNET_JSON_Specification spec[] = {
-    GNUNET_JSON_spec_string ("payto_uri",
-                             &payto_uri),
+    TALER_JSON_spec_payto_uri ("payto_uri",
+                               &payto_uri),
     GNUNET_JSON_spec_mark_optional (
-      GNUNET_JSON_spec_string ("conversion_url",
+      TALER_JSON_spec_web_url ("conversion_url",
                                &conversion_url),
       NULL),
     GNUNET_JSON_spec_array_const ("debit_restrictions",
@@ -1683,8 +1683,8 @@ upload_wire_del (const char *exchange_url,
   const char *err_name;
   unsigned int err_line;
   struct GNUNET_JSON_Specification spec[] = {
-    GNUNET_JSON_spec_string ("payto_uri",
-                             &payto_uri),
+    TALER_JSON_spec_payto_uri ("payto_uri",
+                               &payto_uri),
     GNUNET_JSON_spec_timestamp ("validity_end",
                                 &end_time),
     GNUNET_JSON_spec_fixed_auto ("master_sig",
@@ -2012,8 +2012,8 @@ upload_drain (const char *exchange_url,
                                 &date),
     GNUNET_JSON_spec_string ("account_section",
                              &account_section),
-    GNUNET_JSON_spec_string ("payto_uri",
-                             &payto_uri),
+    TALER_JSON_spec_payto_uri ("payto_uri",
+                               &payto_uri),
     GNUNET_JSON_spec_fixed_auto ("master_sig",
                                  &master_sig),
     GNUNET_JSON_spec_end ()
@@ -2424,7 +2424,7 @@ add_partner (const char *exchange_url,
                                 &start_date),
     GNUNET_JSON_spec_timestamp ("end_date",
                                 &end_date),
-    GNUNET_JSON_spec_string ("partner_base_url",
+    TALER_JSON_spec_web_url ("partner_base_url",
                              &partner_base_url),
     GNUNET_JSON_spec_fixed_auto ("master_sig",
                                  &master_sig),
diff --git a/src/exchange/taler-exchange-httpd_aml-decision.c 
b/src/exchange/taler-exchange-httpd_aml-decision.c
index e688b2ba..bf43fdbf 100644
--- a/src/exchange/taler-exchange-httpd_aml-decision.c
+++ b/src/exchange/taler-exchange-httpd_aml-decision.c
@@ -246,7 +246,6 @@ TEH_handler_post_aml_decision (
   struct DecisionContext dc = {
     .officer_pub = officer_pub
   };
-  uint32_t new_state32;
   struct GNUNET_JSON_Specification spec[] = {
     GNUNET_JSON_spec_fixed_auto ("officer_sig",
                                  &dc.officer_sig),
@@ -259,8 +258,8 @@ TEH_handler_post_aml_decision (
                              &dc.justification),
     GNUNET_JSON_spec_timestamp ("decision_time",
                                 &dc.decision_time),
-    GNUNET_JSON_spec_uint32 ("new_state",
-                             &new_state32),
+    TALER_JSON_spec_aml_decision ("new_state",
+                                  &dc.new_state),
     GNUNET_JSON_spec_mark_optional (
       GNUNET_JSON_spec_array_const ("kyc_requirements",
                                     &dc.kyc_requirements),
@@ -282,7 +281,6 @@ TEH_handler_post_aml_decision (
       return MHD_YES; /* failure */
     }
   }
-  dc.new_state = (enum TALER_AmlDecisionState) new_state32;
   TEH_METRICS_num_verifications[TEH_MT_SIGNATURE_EDDSA]++;
   if (GNUNET_OK !=
       TALER_officer_aml_decision_verify (dc.justification,
diff --git a/src/exchange/taler-exchange-httpd_batch-deposit.c 
b/src/exchange/taler-exchange-httpd_batch-deposit.c
index 516739f7..baf2b964 100644
--- a/src/exchange/taler-exchange-httpd_batch-deposit.c
+++ b/src/exchange/taler-exchange-httpd_batch-deposit.c
@@ -476,8 +476,8 @@ TEH_handler_batch_deposit (struct TEH_RequestContext *rc,
   const json_t *coins;
   bool no_refund_deadline = true;
   struct GNUNET_JSON_Specification spec[] = {
-    GNUNET_JSON_spec_string ("merchant_payto_uri",
-                             &bd->receiver_wire_account),
+    TALER_JSON_spec_payto_uri ("merchant_payto_uri",
+                               &bd->receiver_wire_account),
     GNUNET_JSON_spec_fixed_auto ("wire_salt",
                                  &bd->wire_salt),
     GNUNET_JSON_spec_fixed_auto ("merchant_pub",
diff --git a/src/exchange/taler-exchange-httpd_management_auditors.c 
b/src/exchange/taler-exchange-httpd_management_auditors.c
index 9c7a5c47..7e059353 100644
--- a/src/exchange/taler-exchange-httpd_management_auditors.c
+++ b/src/exchange/taler-exchange-httpd_management_auditors.c
@@ -153,7 +153,7 @@ TEH_handler_management_auditors (
                                  &aac.master_sig),
     GNUNET_JSON_spec_fixed_auto ("auditor_pub",
                                  &aac.auditor_pub),
-    GNUNET_JSON_spec_string ("auditor_url",
+    TALER_JSON_spec_web_url ("auditor_url",
                              &aac.auditor_url),
     GNUNET_JSON_spec_string ("auditor_name",
                              &aac.auditor_name),
diff --git a/src/exchange/taler-exchange-httpd_management_drain.c 
b/src/exchange/taler-exchange-httpd_management_drain.c
index 565c292f..1e490d79 100644
--- a/src/exchange/taler-exchange-httpd_management_drain.c
+++ b/src/exchange/taler-exchange-httpd_management_drain.c
@@ -124,8 +124,8 @@ TEH_handler_management_post_drain (
   struct GNUNET_JSON_Specification spec[] = {
     GNUNET_JSON_spec_string ("debit_account_section",
                              &dc.account_section),
-    GNUNET_JSON_spec_string ("credit_payto_uri",
-                             &dc.payto_uri),
+    TALER_JSON_spec_payto_uri ("credit_payto_uri",
+                               &dc.payto_uri),
     GNUNET_JSON_spec_fixed_auto ("wtid",
                                  &dc.wtid),
     GNUNET_JSON_spec_fixed_auto ("master_sig",
diff --git a/src/exchange/taler-exchange-httpd_management_partners.c 
b/src/exchange/taler-exchange-httpd_management_partners.c
index e336d24e..fc8a4207 100644
--- a/src/exchange/taler-exchange-httpd_management_partners.c
+++ b/src/exchange/taler-exchange-httpd_management_partners.c
@@ -48,7 +48,7 @@ TEH_handler_management_partners (
                                  &partner_pub),
     GNUNET_JSON_spec_fixed_auto ("master_sig",
                                  &master_sig),
-    GNUNET_JSON_spec_string ("partner_base_url",
+    TALER_JSON_spec_web_url ("partner_base_url",
                              &partner_base_url),
     TALER_JSON_spec_amount ("wad_fee",
                             TEH_currency,
diff --git a/src/exchange/taler-exchange-httpd_management_wire_disable.c 
b/src/exchange/taler-exchange-httpd_management_wire_disable.c
index 5bca5736..d3015fb6 100644
--- a/src/exchange/taler-exchange-httpd_management_wire_disable.c
+++ b/src/exchange/taler-exchange-httpd_management_wire_disable.c
@@ -143,8 +143,8 @@ TEH_handler_management_post_wire_disable (
   struct GNUNET_JSON_Specification spec[] = {
     GNUNET_JSON_spec_fixed_auto ("master_sig_del",
                                  &awc.master_sig),
-    GNUNET_JSON_spec_string ("payto_uri",
-                             &awc.payto_uri),
+    TALER_JSON_spec_payto_uri ("payto_uri",
+                               &awc.payto_uri),
     GNUNET_JSON_spec_timestamp ("validity_end",
                                 &awc.validity_end),
     GNUNET_JSON_spec_end ()
diff --git a/src/exchange/taler-exchange-httpd_management_wire_enable.c 
b/src/exchange/taler-exchange-httpd_management_wire_enable.c
index b0db390a..ca5b4ee7 100644
--- a/src/exchange/taler-exchange-httpd_management_wire_enable.c
+++ b/src/exchange/taler-exchange-httpd_management_wire_enable.c
@@ -170,10 +170,10 @@ TEH_handler_management_post_wire (
                                  &awc.master_sig_wire),
     GNUNET_JSON_spec_fixed_auto ("master_sig_add",
                                  &awc.master_sig_add),
-    GNUNET_JSON_spec_string ("payto_uri",
-                             &awc.payto_uri),
+    TALER_JSON_spec_payto_uri ("payto_uri",
+                               &awc.payto_uri),
     GNUNET_JSON_spec_mark_optional (
-      GNUNET_JSON_spec_string ("conversion_url",
+      TALER_JSON_spec_web_url ("conversion_url",
                                &awc.conversion_url),
       NULL),
     GNUNET_JSON_spec_array_const ("credit_restrictions",
diff --git a/src/exchange/taler-exchange-httpd_purses_merge.c 
b/src/exchange/taler-exchange-httpd_purses_merge.c
index d1edc49b..5b66254f 100644
--- a/src/exchange/taler-exchange-httpd_purses_merge.c
+++ b/src/exchange/taler-exchange-httpd_purses_merge.c
@@ -421,8 +421,8 @@ TEH_handler_purses_merge (
     .exchange_timestamp = GNUNET_TIME_timestamp_get ()
   };
   struct GNUNET_JSON_Specification spec[] = {
-    GNUNET_JSON_spec_string ("payto_uri",
-                             &pcc.payto_uri),
+    TALER_JSON_spec_payto_uri ("payto_uri",
+                               &pcc.payto_uri),
     GNUNET_JSON_spec_fixed_auto ("reserve_sig",
                                  &pcc.reserve_sig),
     GNUNET_JSON_spec_fixed_auto ("merge_sig",
diff --git a/src/exchange/taler-exchange-httpd_reserves_close.c 
b/src/exchange/taler-exchange-httpd_reserves_close.c
index bcde8088..bbf23442 100644
--- a/src/exchange/taler-exchange-httpd_reserves_close.c
+++ b/src/exchange/taler-exchange-httpd_reserves_close.c
@@ -367,8 +367,8 @@ TEH_handler_reserves_close (struct TEH_RequestContext *rc,
     GNUNET_JSON_spec_timestamp ("request_timestamp",
                                 &rcc.timestamp),
     GNUNET_JSON_spec_mark_optional (
-      GNUNET_JSON_spec_string ("payto_uri",
-                               &rcc.payto_uri),
+      TALER_JSON_spec_payto_uri ("payto_uri",
+                                 &rcc.payto_uri),
       NULL),
     GNUNET_JSON_spec_fixed_auto ("reserve_sig",
                                  &rcc.reserve_sig),
diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h
index 2089d77a..0d393523 100644
--- a/src/include/taler_crypto_lib.h
+++ b/src/include/taler_crypto_lib.h
@@ -69,8 +69,12 @@ enum TALER_AmlDecisionState
   /**
    * An AML decision has concluded that the funds must be frozen.
    */
-  TALER_AML_FROZEN = 2
+  TALER_AML_FROZEN = 2,
 
+  /**
+   * Maximum allowed numeric value for AML status.
+   */
+  TALER_AML_MAX = 2
 };
 
 
diff --git a/src/include/taler_exchange_service.h 
b/src/include/taler_exchange_service.h
index d2bf918d..7b9b1dd4 100644
--- a/src/include/taler_exchange_service.h
+++ b/src/include/taler_exchange_service.h
@@ -2075,7 +2075,7 @@ struct TALER_EXCHANGE_ReserveHistoryEntry
     struct
     {
       /**
-       * Receiver account information for the outgoing wire transfer.
+       * Receiver account information for the outgoing wire transfer as a 
payto://-URI.
        */
       const char *receiver_account_details;
 
diff --git a/src/include/taler_json_lib.h b/src/include/taler_json_lib.h
index 1a146670..dc806170 100644
--- a/src/include/taler_json_lib.h
+++ b/src/include/taler_json_lib.h
@@ -355,6 +355,98 @@ struct GNUNET_JSON_Specification
 TALER_JSON_spec_denom_pub (const char *field,
                            struct TALER_DenominationPublicKey *pk);
 
+
+/**
+ * Generate line in parser specification for error codes.
+ *
+ * @param field name of the field
+ * @param[out] ec error code to initialize
+ * @return corresponding field spec
+ */
+struct GNUNET_JSON_Specification
+TALER_JSON_spec_ec (const char *field,
+                    enum TALER_ErrorCode *ec);
+
+
+/**
+ * Generate line in parser specification for
+ * HTTP/HTTPS URLs.
+ *
+ * @param field name of the field
+ * @param[out] url web URL to initialize
+ * @return corresponding field spec
+ */
+struct GNUNET_JSON_Specification
+TALER_JSON_spec_web_url (const char *field,
+                         const char **url);
+
+
+/**
+ * Generate line in parser specification for
+ * "payto://" URIs.
+ *
+ * @param field name of the field
+ * @param[out] payto_uri RFC 8905 URI to initialize
+ * @return corresponding field spec
+ */
+struct GNUNET_JSON_Specification
+TALER_JSON_spec_payto_uri (const char *field,
+                           const char **payto_uri);
+
+
+/**
+ * Generate line in parser specification for AML decision states.
+ *
+ * @param field name of the field
+ * @param[out] aml_state AML state to initialize
+ * @return corresponding field spec
+ */
+struct GNUNET_JSON_Specification
+TALER_JSON_spec_aml_decision (const char *field,
+                              enum TALER_AmlDecisionState *aml_state);
+
+
+/**
+ * Representation of a protocol version.
+ */
+struct TALER_JSON_ProtocolVersion
+{
+  /**
+   * Current version of the protocol.
+   */
+  unsigned int current;
+
+  /**
+   * Implementation revision for the @e current
+   * version.
+   */
+  unsigned int revision;
+
+  /**
+   * Number of protocol versions this @e revision is
+   * backwards-compatible with.  Subtract this number
+   * from @a current to get the minimum protocol version
+   * required from the client.
+   */
+  unsigned int age;
+};
+
+
+/**
+ * Generate line in parser specification for protocol
+ * versions (``/config``). The field must be a string
+ * encoding the version as "$CURRENT:$REVISION:$AGE".
+ *
+ * @param field name of the field (usually "version")
+ * @param[out] current protocol current to initialize
+ * @param[out] revision protocol revision to initialize
+ * @param[out] age protocol age to initialize
+ * @return corresponding field spec
+ */
+struct GNUNET_JSON_Specification
+TALER_JSON_spec_version (const char *field,
+                         struct TALER_JSON_ProtocolVersion *ver);
+
 /**
  * Generate a parser specification for a denomination public key of a given
  * cipher.
@@ -365,10 +457,10 @@ TALER_JSON_spec_denom_pub (const char *field,
  * @return corresponding field spec
  */
 struct GNUNET_JSON_Specification
-TALER_JSON_spec_denom_pub_cipher (const char *field,
-                                  enum GNUNET_CRYPTO_BlindSignatureAlgorithm
-                                  cipher,
-                                  struct TALER_DenominationPublicKey *pk);
+TALER_JSON_spec_denom_pub_cipher (
+  const char *field,
+  enum GNUNET_CRYPTO_BlindSignatureAlgorithm cipher,
+  struct TALER_DenominationPublicKey *pk);
 
 
 /**
diff --git a/src/include/taler_util.h b/src/include/taler_util.h
index 19dc84fc..7c2cc688 100644
--- a/src/include/taler_util.h
+++ b/src/include/taler_util.h
@@ -366,6 +366,17 @@ bool
 TALER_url_valid_charset (const char *url);
 
 
+/**
+ * Test if the URL is a valid "http" (or "https")
+ * URL (includes test for #TALER_url_valid_charset()).
+ *
+ * @param url a string to test if it could be a valid URL
+ * @return true if @a url is well-formed
+ */
+bool
+TALER_is_web_url (const char *url);
+
+
 /**
  * Check if @a lang matches the @a language_pattern, and if so with
  * which preference.
diff --git a/src/json/json_helper.c b/src/json/json_helper.c
index fd2a8d27..19dec217 100644
--- a/src/json/json_helper.c
+++ b/src/json/json_helper.c
@@ -1426,4 +1426,274 @@ TALER_JSON_spec_i18n_str (const char *name,
 }
 
 
+/**
+ * Parse given JSON object with Taler error code.
+ *
+ * @param cls closure, NULL
+ * @param root the json object representing data
+ * @param[out] spec where to write the data
+ * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
+ */
+static enum GNUNET_GenericReturnValue
+parse_ec (void *cls,
+          json_t *root,
+          struct GNUNET_JSON_Specification *spec)
+{
+  enum TALER_ErrorCode *ec = spec->ptr;
+  uint32_t num;
+  struct GNUNET_JSON_Specification dspec[] = {
+    GNUNET_JSON_spec_uint32 (spec->field,
+                             &num),
+    GNUNET_JSON_spec_end ()
+  };
+  const char *emsg;
+  unsigned int eline;
+
+  (void) cls;
+  if (GNUNET_OK !=
+      GNUNET_JSON_parse (root,
+                         dspec,
+                         &emsg,
+                         &eline))
+  {
+    GNUNET_break_op (0);
+    *ec = TALER_EC_INVALID;
+    return GNUNET_SYSERR;
+  }
+  *ec = (enum TALER_ErrorCode) num;
+  return GNUNET_OK;
+}
+
+
+struct GNUNET_JSON_Specification
+TALER_JSON_spec_ec (const char *field,
+                    enum TALER_ErrorCode *ec)
+{
+  struct GNUNET_JSON_Specification ret = {
+    .parser = &parse_ec,
+    .field = field,
+    .ptr = ec
+  };
+
+  *ec = TALER_EC_NONE;
+  return ret;
+}
+
+
+/**
+ * Parse given JSON object with AML decision.
+ *
+ * @param cls closure, NULL
+ * @param root the json object representing data
+ * @param[out] spec where to write the data
+ * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
+ */
+static enum GNUNET_GenericReturnValue
+parse_aml_decision (void *cls,
+                    json_t *root,
+                    struct GNUNET_JSON_Specification *spec)
+{
+  enum TALER_AmlDecisionState *aml = spec->ptr;
+  uint32_t num;
+  struct GNUNET_JSON_Specification dspec[] = {
+    GNUNET_JSON_spec_uint32 (spec->field,
+                             &num),
+    GNUNET_JSON_spec_end ()
+  };
+  const char *emsg;
+  unsigned int eline;
+
+  (void) cls;
+  if (GNUNET_OK !=
+      GNUNET_JSON_parse (root,
+                         dspec,
+                         &emsg,
+                         &eline))
+  {
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+  if (num > TALER_AML_MAX)
+  {
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+  *aml = (enum TALER_AmlDecisionState) num;
+  return GNUNET_OK;
+}
+
+
+struct GNUNET_JSON_Specification
+TALER_JSON_spec_aml_decision (const char *field,
+                              enum TALER_AmlDecisionState *aml_state)
+{
+  struct GNUNET_JSON_Specification ret = {
+    .parser = &parse_aml_decision,
+    .field = field,
+    .ptr = aml_state
+  };
+
+  return ret;
+}
+
+
+/**
+ * Parse given JSON object to web URL.
+ *
+ * @param cls closure, NULL
+ * @param root the json object representing data
+ * @param[out] spec where to write the data
+ * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
+ */
+static enum GNUNET_GenericReturnValue
+parse_web_url (void *cls,
+               json_t *root,
+               struct GNUNET_JSON_Specification *spec)
+{
+  const char *str;
+
+  (void) cls;
+  str = json_string_value (root);
+  if (NULL == str)
+  {
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+  if (! TALER_is_web_url (str))
+  {
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+  *(const char **) spec->ptr = str;
+  return GNUNET_OK;
+}
+
+
+struct GNUNET_JSON_Specification
+TALER_JSON_spec_web_url (const char *field,
+                         const char **url)
+{
+  struct GNUNET_JSON_Specification ret = {
+    .parser = &parse_web_url,
+    .field = field,
+    .ptr = url
+  };
+
+  *url = NULL;
+  return ret;
+}
+
+
+/**
+ * Parse given JSON object to payto:// URI.
+ *
+ * @param cls closure, NULL
+ * @param root the json object representing data
+ * @param[out] spec where to write the data
+ * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
+ */
+static enum GNUNET_GenericReturnValue
+parse_payto_uri (void *cls,
+                 json_t *root,
+                 struct GNUNET_JSON_Specification *spec)
+{
+  const char *str;
+  char *err;
+
+  (void) cls;
+  str = json_string_value (root);
+  if (NULL == str)
+  {
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+  err = TALER_payto_validate (str);
+  if (NULL != err)
+  {
+    GNUNET_break_op (0);
+    GNUNET_free (err);
+    return GNUNET_SYSERR;
+  }
+  *(const char **) spec->ptr = str;
+  return GNUNET_OK;
+}
+
+
+struct GNUNET_JSON_Specification
+TALER_JSON_spec_payto_uri (const char *field,
+                           const char **payto_uri)
+{
+  struct GNUNET_JSON_Specification ret = {
+    .parser = &parse_payto_uri,
+    .field = field,
+    .ptr = payto_uri
+  };
+
+  *payto_uri = NULL;
+  return ret;
+}
+
+
+/**
+ * Parse given JSON object with protocol version.
+ *
+ * @param cls closure, NULL
+ * @param root the json object representing data
+ * @param[out] spec where to write the data
+ * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
+ */
+static enum GNUNET_GenericReturnValue
+parse_protocol_version (void *cls,
+                        json_t *root,
+                        struct GNUNET_JSON_Specification *spec)
+{
+  struct TALER_JSON_ProtocolVersion *pv = spec->ptr;
+  const char *ver;
+  struct GNUNET_JSON_Specification dspec[] = {
+    GNUNET_JSON_spec_string (spec->field,
+                             &ver),
+    GNUNET_JSON_spec_end ()
+  };
+  const char *emsg;
+  unsigned int eline;
+  char dummy;
+
+  (void) cls;
+  if (GNUNET_OK !=
+      GNUNET_JSON_parse (root,
+                         dspec,
+                         &emsg,
+                         &eline))
+  {
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+  if (3 != sscanf (ver,
+                   "%u:%u:%u%c",
+                   &pv->current,
+                   &pv->revision,
+                   &pv->age,
+                   &dummy))
+  {
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
+}
+
+
+struct GNUNET_JSON_Specification
+TALER_JSON_spec_version (const char *field,
+                         struct TALER_JSON_ProtocolVersion *ver)
+{
+  struct GNUNET_JSON_Specification ret = {
+    .parser = &parse_protocol_version,
+    .field = field,
+    .ptr = ver
+  };
+
+  return ret;
+}
+
+
 /* end of json/json_helper.c */
diff --git a/src/lib/auditor_api_exchanges.c b/src/lib/auditor_api_exchanges.c
index 897dfe60..1988c2fa 100644
--- a/src/lib/auditor_api_exchanges.c
+++ b/src/lib/auditor_api_exchanges.c
@@ -125,7 +125,7 @@ handle_exchanges_finished (void *cls,
         struct GNUNET_JSON_Specification spec[] = {
           GNUNET_JSON_spec_fixed_auto ("master_pub",
                                        &ei[i].master_pub),
-          GNUNET_JSON_spec_string ("exchange_url",
+          TALER_JSON_spec_web_url ("exchange_url",
                                    &ei[i].exchange_url),
           GNUNET_JSON_spec_end ()
         };
diff --git a/src/lib/auditor_api_get_config.c b/src/lib/auditor_api_get_config.c
index c9f36656..5d0b4db8 100644
--- a/src/lib/auditor_api_get_config.c
+++ b/src/lib/auditor_api_get_config.c
@@ -104,12 +104,11 @@ decode_config_json (const json_t *resp_obj,
                     struct TALER_AUDITOR_ConfigInformation *vi,
                     enum TALER_AUDITOR_VersionCompatibility *vc)
 {
-  unsigned int age;
-  unsigned int revision;
-  unsigned int current;
-  char dummy;
+  struct TALER_JSON_ProtocolVersion pv;
   const char *ver;
   struct GNUNET_JSON_Specification spec[] = {
+    TALER_JSON_spec_version ("version",
+                             &pv),
     GNUNET_JSON_spec_string ("version",
                              &ver),
     GNUNET_JSON_spec_fixed_auto ("auditor_public_key",
@@ -131,28 +130,18 @@ decode_config_json (const json_t *resp_obj,
     GNUNET_break_op (0);
     return TALER_EC_GENERIC_JSON_INVALID;
   }
-  if (3 != sscanf (ver,
-                   "%u:%u:%u%c",
-                   &current,
-                   &revision,
-                   &age,
-                   &dummy))
-  {
-    GNUNET_break_op (0);
-    return TALER_EC_GENERIC_VERSION_MALFORMED;
-  }
   vi->version = ver;
   *vc = TALER_AUDITOR_VC_MATCH;
-  if (TALER_PROTOCOL_CURRENT < current)
+  if (TALER_PROTOCOL_CURRENT < pv.current)
   {
     *vc |= TALER_AUDITOR_VC_NEWER;
-    if (TALER_PROTOCOL_CURRENT < current - age)
+    if (TALER_PROTOCOL_CURRENT < pv.current - pv.age)
       *vc |= TALER_AUDITOR_VC_INCOMPATIBLE;
   }
-  if (TALER_PROTOCOL_CURRENT > current)
+  if (TALER_PROTOCOL_CURRENT > pv.current)
   {
     *vc |= TALER_AUDITOR_VC_OLDER;
-    if (TALER_PROTOCOL_CURRENT - TALER_PROTOCOL_AGE > current)
+    if (TALER_PROTOCOL_CURRENT - TALER_PROTOCOL_AGE > pv.current)
       *vc |= TALER_AUDITOR_VC_INCOMPATIBLE;
   }
   return TALER_EC_NONE;
diff --git a/src/lib/exchange_api_batch_deposit.c 
b/src/lib/exchange_api_batch_deposit.c
index f9d505dc..56b9b11e 100644
--- a/src/lib/exchange_api_batch_deposit.c
+++ b/src/lib/exchange_api_batch_deposit.c
@@ -360,7 +360,7 @@ handle_deposit_finished (void *cls,
         GNUNET_JSON_spec_fixed_auto ("exchange_pub",
                                      &dh->exchange_pub),
         GNUNET_JSON_spec_mark_optional (
-          GNUNET_JSON_spec_string ("transaction_base_url",
+          TALER_JSON_spec_web_url ("transaction_base_url",
                                    &dr->details.ok.transaction_base_url),
           NULL),
         GNUNET_JSON_spec_timestamp ("exchange_timestamp",
diff --git a/src/lib/exchange_api_coins_history.c 
b/src/lib/exchange_api_coins_history.c
index 34eca62d..6981fad5 100644
--- a/src/lib/exchange_api_coins_history.c
+++ b/src/lib/exchange_api_coins_history.c
@@ -576,7 +576,7 @@ help_purse_deposit (struct CoinHistoryParseContext *pc,
       GNUNET_JSON_spec_fixed_auto ("h_age_commitment",
                                    &rh->details.purse_deposit.phac),
       NULL),
-    GNUNET_JSON_spec_string ("exchange_base_url",
+    TALER_JSON_spec_web_url ("exchange_base_url",
                              &rh->details.purse_deposit.exchange_base_url),
     GNUNET_JSON_spec_bool ("refunded",
                            &rh->details.purse_deposit.refunded),
diff --git a/src/lib/exchange_api_common.c b/src/lib/exchange_api_common.c
index 4846e118..23963265 100644
--- a/src/lib/exchange_api_common.c
+++ b/src/lib/exchange_api_common.c
@@ -119,7 +119,7 @@ TALER_EXCHANGE_check_purse_merge_conflict_ (
   struct TALER_ReservePublicKeyP reserve_pub;
   struct GNUNET_JSON_Specification spec[] = {
     GNUNET_JSON_spec_mark_optional (
-      GNUNET_JSON_spec_string ("partner_url",
+      TALER_JSON_spec_web_url ("partner_url",
                                &partner_url),
       NULL),
     GNUNET_JSON_spec_timestamp ("merge_timestamp",
@@ -191,7 +191,7 @@ TALER_EXCHANGE_check_purse_coin_conflict_ (
     GNUNET_JSON_spec_fixed_auto ("coin_pub",
                                  coin_pub),
     GNUNET_JSON_spec_mark_optional (
-      GNUNET_JSON_spec_string ("partner_url",
+      TALER_JSON_spec_web_url ("partner_url",
                                &partner_url),
       NULL),
     TALER_JSON_spec_amount_any ("amount",
@@ -515,10 +515,10 @@ TALER_EXCHANGE_parse_accounts (
     const json_t *credit_restrictions;
     const json_t *debit_restrictions;
     struct GNUNET_JSON_Specification spec_account[] = {
-      GNUNET_JSON_spec_string ("payto_uri",
-                               &payto_uri),
+      TALER_JSON_spec_payto_uri ("payto_uri",
+                                 &payto_uri),
       GNUNET_JSON_spec_mark_optional (
-        GNUNET_JSON_spec_string ("conversion_url",
+        TALER_JSON_spec_web_url ("conversion_url",
                                  &conversion_url),
         NULL),
       GNUNET_JSON_spec_array_const ("credit_restrictions",
@@ -542,18 +542,6 @@ TALER_EXCHANGE_parse_accounts (
       GNUNET_break_op (0);
       return GNUNET_SYSERR;
     }
-    {
-      char *err;
-
-      err = TALER_payto_validate (payto_uri);
-      if (NULL != err)
-      {
-        GNUNET_break_op (0);
-        GNUNET_free (err);
-        return GNUNET_SYSERR;
-      }
-    }
-
     if ( (NULL != master_pub) &&
          (GNUNET_OK !=
           TALER_exchange_wire_signature_check (
diff --git a/src/lib/exchange_api_deposits_get.c 
b/src/lib/exchange_api_deposits_get.c
index 8b145dab..ee5f9dc6 100644
--- a/src/lib/exchange_api_deposits_get.c
+++ b/src/lib/exchange_api_deposits_get.c
@@ -177,7 +177,6 @@ handle_deposit_wtid_finished (void *cls,
     {
       /* Transaction known, but not executed yet */
       bool no_legi = false;
-      uint32_t state32;
       struct GNUNET_JSON_Specification spec[] = {
         GNUNET_JSON_spec_timestamp ("execution_time",
                                     &dr.details.accepted.execution_time),
@@ -185,8 +184,8 @@ handle_deposit_wtid_finished (void *cls,
           GNUNET_JSON_spec_uint64 ("requirement_row",
                                    &dr.details.accepted.requirement_row),
           &no_legi),
-        GNUNET_JSON_spec_uint32 ("aml_decision",
-                                 &state32),
+        TALER_JSON_spec_aml_decision ("aml_decision",
+                                      &dr.details.accepted.aml_decision),
         GNUNET_JSON_spec_bool ("kyc_ok",
                                &dr.details.accepted.kyc_ok),
         GNUNET_JSON_spec_end ()
@@ -202,8 +201,6 @@ handle_deposit_wtid_finished (void *cls,
         dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
         break;
       }
-      dr.details.accepted.aml_decision
-        = (enum TALER_AmlDecisionState) state32;
       if (no_legi)
         dr.details.accepted.requirement_row = 0;
       dwh->cb (dwh->cb_cls,
diff --git a/src/lib/exchange_api_handle.c b/src/lib/exchange_api_handle.c
index 410c0124..ab3c387d 100644
--- a/src/lib/exchange_api_handle.c
+++ b/src/lib/exchange_api_handle.c
@@ -550,7 +550,7 @@ parse_json_auditor (struct 
TALER_EXCHANGE_AuditorInformation *auditor,
   struct GNUNET_JSON_Specification spec[] = {
     GNUNET_JSON_spec_fixed_auto ("auditor_pub",
                                  &auditor->auditor_pub),
-    GNUNET_JSON_spec_string ("auditor_url",
+    TALER_JSON_spec_web_url ("auditor_url",
                              &auditor_url),
     GNUNET_JSON_spec_array_const ("denomination_keys",
                                   &keys),
@@ -791,14 +791,10 @@ decode_keys_json (const json_t *resp_obj,
 #endif
   /* check the version first */
   {
-    const char *ver;
-    unsigned int age;
-    unsigned int revision;
-    unsigned int current;
-    char dummy;
+    struct TALER_JSON_ProtocolVersion pv;
     struct GNUNET_JSON_Specification spec[] = {
-      GNUNET_JSON_spec_string ("version",
-                               &ver),
+      TALER_JSON_spec_version ("version",
+                               &pv),
       GNUNET_JSON_spec_end ()
     };
 
@@ -810,33 +806,23 @@ decode_keys_json (const json_t *resp_obj,
       GNUNET_break_op (0);
       return GNUNET_SYSERR;
     }
-    if (3 != sscanf (ver,
-                     "%u:%u:%u%c",
-                     &current,
-                     &revision,
-                     &age,
-                     &dummy))
-    {
-      GNUNET_break_op (0);
-      return GNUNET_SYSERR;
-    }
     *vc = TALER_EXCHANGE_VC_MATCH;
-    if (EXCHANGE_PROTOCOL_CURRENT < current)
+    if (EXCHANGE_PROTOCOL_CURRENT < pv.current)
     {
       *vc |= TALER_EXCHANGE_VC_NEWER;
-      if (EXCHANGE_PROTOCOL_CURRENT < current - age)
+      if (EXCHANGE_PROTOCOL_CURRENT < pv.current - pv.age)
         *vc |= TALER_EXCHANGE_VC_INCOMPATIBLE;
     }
-    if (EXCHANGE_PROTOCOL_CURRENT > current)
+    if (EXCHANGE_PROTOCOL_CURRENT > pv.current)
     {
       *vc |= TALER_EXCHANGE_VC_OLDER;
-      if (EXCHANGE_PROTOCOL_CURRENT - EXCHANGE_PROTOCOL_AGE > current)
+      if (EXCHANGE_PROTOCOL_CURRENT - EXCHANGE_PROTOCOL_AGE > pv.current)
         *vc |= TALER_EXCHANGE_VC_INCOMPATIBLE;
     }
-    key_data->version = GNUNET_strdup (ver);
   }
 
   {
+    const char *ver;
     const char *currency;
     const char *asset_type;
     struct GNUNET_JSON_Specification mspec[] = {
@@ -901,6 +887,8 @@ decode_keys_json (const json_t *resp_obj,
           "extensions_sig",
           &key_data->extensions_sig),
         &no_signature),
+      GNUNET_JSON_spec_string ("version",
+                               &ver),
       GNUNET_JSON_spec_mark_optional (
         GNUNET_JSON_spec_array_const (
           "wallet_balance_limit_without_kyc",
@@ -946,6 +934,7 @@ decode_keys_json (const json_t *resp_obj,
     }
 
     key_data->currency = GNUNET_strdup (currency);
+    key_data->version = GNUNET_strdup (ver);
     key_data->asset_type = GNUNET_strdup (asset_type);
     if (! no_extensions)
       key_data->extensions = json_incref ((json_t *) manifests);
@@ -1896,7 +1885,7 @@ TALER_EXCHANGE_keys_from_json (const json_t *j)
                              &version),
     GNUNET_JSON_spec_object_const ("keys",
                                    &jkeys),
-    GNUNET_JSON_spec_string ("exchange_url",
+    TALER_JSON_spec_web_url ("exchange_url",
                              &url),
     GNUNET_JSON_spec_mark_optional (
       GNUNET_JSON_spec_timestamp ("expire",
diff --git a/src/lib/exchange_api_kyc_check.c b/src/lib/exchange_api_kyc_check.c
index 373dd89a..5d3b3792 100644
--- a/src/lib/exchange_api_kyc_check.c
+++ b/src/lib/exchange_api_kyc_check.c
@@ -97,7 +97,6 @@ handle_kyc_check_finished (void *cls,
   case MHD_HTTP_OK:
     {
       const json_t *kyc_details;
-      uint32_t status;
       struct GNUNET_JSON_Specification spec[] = {
         GNUNET_JSON_spec_fixed_auto ("exchange_sig",
                                      &ks.details.ok.exchange_sig),
@@ -107,8 +106,8 @@ handle_kyc_check_finished (void *cls,
                                     &ks.details.ok.timestamp),
         GNUNET_JSON_spec_object_const ("kyc_details",
                                        &kyc_details),
-        GNUNET_JSON_spec_uint32 ("aml_status",
-                                 &status),
+        TALER_JSON_spec_aml_decision ("aml_status",
+                                      &ks.details.ok.aml_status),
         GNUNET_JSON_spec_end ()
       };
 
@@ -123,8 +122,6 @@ handle_kyc_check_finished (void *cls,
         break;
       }
       ks.details.ok.kyc_details = kyc_details;
-      ks.details.ok.aml_status
-        = (enum TALER_AmlDecisionState) status;
       if (GNUNET_OK !=
           TALER_EXCHANGE_test_signing_key (kch->keys,
                                            &ks.details.ok.exchange_pub))
@@ -158,12 +155,11 @@ handle_kyc_check_finished (void *cls,
     }
   case MHD_HTTP_ACCEPTED:
     {
-      uint32_t status;
       struct GNUNET_JSON_Specification spec[] = {
-        GNUNET_JSON_spec_string ("kyc_url",
+        TALER_JSON_spec_web_url ("kyc_url",
                                  &ks.details.accepted.kyc_url),
-        GNUNET_JSON_spec_uint32 ("aml_status",
-                                 &status),
+        TALER_JSON_spec_aml_decision ("aml_status",
+                                      &ks.details.accepted.aml_status),
         GNUNET_JSON_spec_end ()
       };
 
@@ -177,8 +173,6 @@ handle_kyc_check_finished (void *cls,
         ks.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
         break;
       }
-      ks.details.accepted.aml_status
-        = (enum TALER_AmlDecisionState) status;
       kch->cb (kch->cb_cls,
                &ks);
       GNUNET_JSON_parse_free (spec);
@@ -200,10 +194,10 @@ handle_kyc_check_finished (void *cls,
     break;
   case MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS:
     {
-      uint32_t status;
       struct GNUNET_JSON_Specification spec[] = {
-        GNUNET_JSON_spec_uint32 ("aml_status",
-                                 &status),
+        TALER_JSON_spec_aml_decision (
+          "aml_status",
+          &ks.details.unavailable_for_legal_reasons.aml_status),
         GNUNET_JSON_spec_end ()
       };
 
@@ -217,8 +211,6 @@ handle_kyc_check_finished (void *cls,
         ks.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
         break;
       }
-      ks.details.unavailable_for_legal_reasons.aml_status
-        = (enum TALER_AmlDecisionState) status;
       kch->cb (kch->cb_cls,
                &ks);
       GNUNET_JSON_parse_free (spec);
diff --git a/src/lib/exchange_api_lookup_aml_decision.c 
b/src/lib/exchange_api_lookup_aml_decision.c
index 01e98213..501b9d18 100644
--- a/src/lib/exchange_api_lookup_aml_decision.c
+++ b/src/lib/exchange_api_lookup_aml_decision.c
@@ -80,7 +80,6 @@ parse_aml_history (const json_t *aml_history,
   json_array_foreach (aml_history, idx, obj)
   {
     struct TALER_EXCHANGE_AmlDecisionDetail *aml = &aml_history_ar[idx];
-    uint32_t state32;
     struct GNUNET_JSON_Specification spec[] = {
       GNUNET_JSON_spec_timestamp ("decision_time",
                                   &aml->decision_time),
@@ -88,8 +87,8 @@ parse_aml_history (const json_t *aml_history,
                                &aml->justification),
       TALER_JSON_spec_amount_any ("new_threshold",
                                   &aml->new_threshold),
-      GNUNET_JSON_spec_uint32 ("new_state",
-                               &state32),
+      TALER_JSON_spec_aml_decision ("new_state",
+                                    &aml->new_state),
       GNUNET_JSON_spec_fixed_auto ("decider_pub",
                                    &aml->decider_pub),
       GNUNET_JSON_spec_end ()
@@ -104,7 +103,6 @@ parse_aml_history (const json_t *aml_history,
       GNUNET_break_op (0);
       return GNUNET_SYSERR;
     }
-    aml->new_state = (enum TALER_AmlDecisionState) state32;
   }
   return GNUNET_OK;
 }
diff --git a/src/lib/exchange_api_lookup_aml_decisions.c 
b/src/lib/exchange_api_lookup_aml_decisions.c
index 22222b1e..bb3c18b6 100644
--- a/src/lib/exchange_api_lookup_aml_decisions.c
+++ b/src/lib/exchange_api_lookup_aml_decisions.c
@@ -80,12 +80,11 @@ parse_aml_decisions (const json_t *decisions,
   json_array_foreach (decisions, idx, obj)
   {
     struct TALER_EXCHANGE_AmlDecisionSummary *decision = &decision_ar[idx];
-    uint32_t state32;
     struct GNUNET_JSON_Specification spec[] = {
       GNUNET_JSON_spec_fixed_auto ("h_payto",
                                    &decision->h_payto),
-      GNUNET_JSON_spec_uint32 ("current_state",
-                               &state32),
+      TALER_JSON_spec_aml_decision ("current_state",
+                                    &decision->current_state),
       TALER_JSON_spec_amount_any ("threshold",
                                   &decision->threshold),
       GNUNET_JSON_spec_uint64 ("rowid",
@@ -102,7 +101,6 @@ parse_aml_decisions (const json_t *decisions,
       GNUNET_break_op (0);
       return GNUNET_SYSERR;
     }
-    decision->current_state = (enum TALER_AmlDecisionState) state32;
   }
   return GNUNET_OK;
 }
diff --git a/src/lib/exchange_api_reserves_history.c 
b/src/lib/exchange_api_reserves_history.c
index 7b8eb95e..0654ad83 100644
--- a/src/lib/exchange_api_reserves_history.c
+++ b/src/lib/exchange_api_reserves_history.c
@@ -148,7 +148,7 @@ parse_credit (struct TALER_EXCHANGE_ReserveHistoryEntry *rh,
               struct HistoryParseContext *uc,
               const json_t *transaction)
 {
-  const char *wire_url;
+  const char *wire_uri;
   uint64_t wire_reference;
   struct GNUNET_TIME_Timestamp timestamp;
   struct GNUNET_JSON_Specification withdraw_spec[] = {
@@ -156,8 +156,8 @@ parse_credit (struct TALER_EXCHANGE_ReserveHistoryEntry *rh,
                              &wire_reference),
     GNUNET_JSON_spec_timestamp ("timestamp",
                                 &timestamp),
-    GNUNET_JSON_spec_string ("sender_account_url",
-                             &wire_url),
+    TALER_JSON_spec_payto_uri ("sender_account_url",
+                               &wire_uri),
     GNUNET_JSON_spec_end ()
   };
 
@@ -179,7 +179,7 @@ parse_credit (struct TALER_EXCHANGE_ReserveHistoryEntry *rh,
     GNUNET_break_op (0);
     return GNUNET_SYSERR;
   }
-  rh->details.in_details.sender_url = GNUNET_strdup (wire_url);
+  rh->details.in_details.sender_url = GNUNET_strdup (wire_uri);
   rh->details.in_details.wire_reference = wire_reference;
   rh->details.in_details.timestamp = timestamp;
   return GNUNET_OK;
@@ -379,7 +379,7 @@ parse_closing (struct TALER_EXCHANGE_ReserveHistoryEntry 
*rh,
 {
   const struct TALER_EXCHANGE_Keys *key_state;
   struct GNUNET_JSON_Specification closing_spec[] = {
-    GNUNET_JSON_spec_string (
+    TALER_JSON_spec_payto_uri (
       "receiver_account_details",
       &rh->details.close_details.receiver_account_details),
     GNUNET_JSON_spec_fixed_auto ("wtid",
diff --git a/src/util/url.c b/src/util/url.c
index 1ac19755..73f61dee 100644
--- a/src/util/url.c
+++ b/src/util/url.c
@@ -332,4 +332,20 @@ TALER_url_valid_charset (const char *url)
 }
 
 
+bool
+TALER_is_web_url (const char *url)
+{
+  if ( (0 != strncasecmp (url,
+                          "https://";,
+                          strlen ("https://";))) &&
+       (0 != strncasecmp (url,
+                          "http://";,
+                          strlen ("http://";))) )
+    return false;
+  if (! TALER_url_valid_charset (url) )
+    return false;
+  return true;
+}
+
+
 /* end of url.c */

-- 
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]