summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Buchanan <jonathan.russ.buchanan@gmail.com>2020-08-09 23:28:56 -0400
committerJonathan Buchanan <jonathan.russ.buchanan@gmail.com>2020-08-09 23:28:56 -0400
commit119de8db9e317e46ebe800524b806809d2b435b0 (patch)
tree737423707c1004bf86bcbb801c97cda1b256e8e3
parentef6fed10b06bef0ba7d9003b594c8e994665229f (diff)
downloadmerchant-119de8db9e317e46ebe800524b806809d2b435b0.tar.gz
merchant-119de8db9e317e46ebe800524b806809d2b435b0.tar.bz2
merchant-119de8db9e317e46ebe800524b806809d2b435b0.zip
implement parser for taler_pay_uri
-rw-r--r--src/include/taler_merchant_service.h67
-rw-r--r--src/lib/merchant_api_common.c220
-rw-r--r--src/testing/testing_api_cmd_merchant_get_order.c25
3 files changed, 296 insertions, 16 deletions
diff --git a/src/include/taler_merchant_service.h b/src/include/taler_merchant_service.h
index 19438f97..b33941aa 100644
--- a/src/include/taler_merchant_service.h
+++ b/src/include/taler_merchant_service.h
@@ -137,28 +137,63 @@ TALER_MERCHANT_baseurl_add_instance (const char *base_url,
/**
+ * Contains information gathered from parsing a taler://pay URI.
+ */
+struct TALER_MERCHANT_PayUriData
+{
+ /**
+ * Hostname (and possibly port) of the merchant.
+ */
+ char *merchant_host;
+
+ /**
+ * Prefix to the base url of the merchant backend. May be NULL.
+ */
+ char *merchant_prefix_path;
+
+ /**
+ * The id of the order to pay.
+ */
+ char *order_id;
+
+ /**
+ * Session id to use when paying the order. May be NULL.
+ */
+ char *session_id;
+
+ /**
+ * Claim token to use when claiming the order. May be NULL.
+ */
+ struct TALER_ClaimTokenP *claim_token;
+
+ /**
+ * A WLAN SSID that the wallet can use to connect to the internet in order to
+ * to pay. May be NULL.
+ */
+ char *ssid;
+};
+
+
+/**
* Extracts information from a taler://pay URI.
*
* @param pay_uri the URI to parse.
- * @param[out] merchant_host the hostname of the merchant.
- * @param[out] merchant_prefix_path prefix of the base URL
- * (NULL if not present).
- * @param[out] order_id the id of the order to pay.
- * @param[out] session_id the session id to use for payment
- * (NULL if not present).
- * @param[out] claim_token the claim token needed to claim the order
- * (zeroed if not present).
- * @param[out] ssid the ssid for internet connectivity (NULL if not present).
- * @return GNUNET_OK on success, GNUNET_SYSERR otherwise.
+ * @param[out] parse_data data extracted from the URI. Must be free'd.
+ * @return GNUNET_SYSERR if @e pay_uri is malformed, GNUNET_OK otherwise.
*/
int
TALER_MERCHANT_parse_pay_uri (const char *pay_uri,
- const char **merchant_host,
- const char **merchant_prefix_path,
- const char **order_id,
- const char **session_id,
- struct GNUNET_HashCode *claim_token,
- const char **ssid);
+ struct TALER_MERCHANT_PayUriData *parse_data);
+
+
+/**
+ * Frees data contained in the result of parsing a taler://pay URI.
+ *
+ * @param parse_data the data to free.
+ */
+void
+TALER_MERCHANT_parse_pay_uri_free (
+ struct TALER_MERCHANT_PayUriData *parse_data);
/**
diff --git a/src/lib/merchant_api_common.c b/src/lib/merchant_api_common.c
index 4d69e720..9745f772 100644
--- a/src/lib/merchant_api_common.c
+++ b/src/lib/merchant_api_common.c
@@ -150,3 +150,223 @@ TALER_MERCHANT_baseurl_add_instance (const char *base_url,
instance_id);
return ret;
}
+
+
+/**
+ * Parses the URI scheme and action of a URI. Ensures that the scheme is either
+ * 'taler' or 'taler+http'.
+ *
+ * @param uri the uri to parse.
+ * @param[out] action the action the URI is indicating.
+ * @param[out] rest the substring of the URI following the action.
+ * @return GNUNET_SYSERR if the URI is malformed, GNUNET_OK otherwise.
+ */
+static int
+parse_taler_uri_scheme_action (const char *uri,
+ char **action,
+ char **rest)
+{
+ char *scheme = GNUNET_strdup (uri);
+ /* Check that the uri starts with "taler://pay" or "taler+http://pay" and
+ then remove it */
+ char *path = strchr (scheme, ':');
+ if ((NULL == path) ||
+ (strlen (path) < 3))
+ {
+ GNUNET_free (scheme);
+ return GNUNET_SYSERR;
+ }
+ path += 3;
+
+ {
+ char path_begin = *path;
+ *path = '\0';
+ if ((0 != strcmp ("taler://",
+ scheme)) &&
+ (0 != strcmp ("taler+http://",
+ scheme)))
+ {
+ GNUNET_free (scheme);
+ return GNUNET_SYSERR;
+ }
+ *path = path_begin;
+ }
+
+ {
+ char *pqf = strchr (path, '/');
+ if (NULL == pqf)
+ {
+ GNUNET_free (scheme);
+ return GNUNET_SYSERR;
+ }
+ *pqf = '\0';
+ ++pqf;
+ *rest = GNUNET_strdup (pqf);
+ }
+ *action = GNUNET_strdup (path);
+
+ GNUNET_free (scheme);
+ return GNUNET_OK;
+}
+
+
+/**
+ * Finds the last occurrence of @e c in the string @e str.
+ *
+ * @param str the string to search in.
+ * @param c the character to search for.
+ * @return pointer to the last occurrence of @e c in @e str, if it exists,
+ * otherwise NULL.
+ */
+static char *
+strchr_last (char *str,
+ char c)
+{
+ for (size_t i = strlen (str) - 1; i >= 0; --i)
+ {
+ if (c == str[i])
+ return &str[i];
+ }
+ return NULL;
+}
+
+
+/**
+ * Extracts information from a taler://pay URI.
+ *
+ * @param pay_uri the URI to parse.
+ * @param[out] parse_data data extracted from the URI. Must be free'd.
+ * @return GNUNET_SYSERR if @e pay_uri is malformed, GNUNET_OK otherwise.
+ */
+int
+TALER_MERCHANT_parse_pay_uri (const char *pay_uri,
+ struct TALER_MERCHANT_PayUriData *parse_data)
+{
+ char *path;
+ {
+ char *action;
+
+ if ((GNUNET_OK !=
+ parse_taler_uri_scheme_action (pay_uri,
+ &action,
+ &path)) ||
+ (0 != strcmp ("pay",
+ action)))
+ {
+ GNUNET_free (action);
+ GNUNET_free (path);
+ return GNUNET_SYSERR;
+ }
+ GNUNET_free (action);
+ }
+
+ {
+ char *mpp;
+ char *order_id;
+ char *session_id = strchr_last (path,
+ '/');
+ struct TALER_ClaimTokenP *claim_token = NULL;
+ char *ssid;
+
+ if (NULL == session_id)
+ {
+ GNUNET_free (path);
+ return GNUNET_SYSERR;
+ }
+ *session_id = '\0';
+ ++session_id;
+
+ order_id = strchr_last (path,
+ '/');
+ if (NULL == order_id)
+ {
+ GNUNET_free (path);
+ return GNUNET_SYSERR;
+ }
+ *order_id = '\0';
+ ++order_id;
+
+ {
+ char *ct_str = strchr (session_id,
+ '?');
+ char *ct_data;
+ if (NULL != ct_str)
+ {
+ *ct_str = '\0';
+ ++ct_str;
+ }
+
+ ssid = strchr (session_id,
+ '#');
+ if (NULL != ssid)
+ {
+ *ssid = '\0';
+ ++ssid;
+ }
+
+ if (NULL != ct_str)
+ {
+ ct_data = strchr (ct_str,
+ '=');
+ if (NULL == ct_data)
+ {
+ GNUNET_free (order_id);
+ return GNUNET_SYSERR;
+ }
+ *ct_data = '\0';
+ ++ct_data;
+ claim_token = GNUNET_new (struct TALER_ClaimTokenP);
+ if ((0 != strcmp ("c",
+ ct_str)) ||
+ (GNUNET_OK !=
+ GNUNET_STRINGS_string_to_data (ct_data,
+ strlen (ct_data),
+ claim_token,
+ sizeof (*claim_token))))
+ {
+ GNUNET_free (order_id);
+ GNUNET_free (claim_token);
+ return GNUNET_SYSERR;
+ }
+ }
+ }
+
+ mpp = strchr (path,
+ '/');
+ if (NULL != mpp)
+ {
+ *mpp = '\0';
+ ++mpp;
+ }
+
+ parse_data->merchant_host = GNUNET_strdup (path);
+ parse_data->merchant_prefix_path =
+ (NULL == mpp) ? NULL : GNUNET_strdup (mpp);
+ parse_data->order_id = GNUNET_strdup (order_id);
+ parse_data->session_id =
+ (0 < strlen (session_id)) ? GNUNET_strdup (session_id) : NULL;
+ parse_data->claim_token = claim_token;
+ parse_data->ssid =
+ (NULL == ssid) ? NULL : GNUNET_strdup (ssid);
+ }
+ GNUNET_free (path);
+ return GNUNET_OK;
+}
+
+
+/**
+ * Frees data contained in the result of parsing a taler://pay URI.
+ *
+ * @param parse_data the data to free.
+ */
+void
+TALER_MERCHANT_parse_pay_uri_free (
+ struct TALER_MERCHANT_PayUriData *parse_data)
+{
+ GNUNET_free (parse_data->merchant_host);
+ GNUNET_free (parse_data->merchant_prefix_path);
+ GNUNET_free (parse_data->order_id);
+ GNUNET_free (parse_data->session_id);
+ GNUNET_free (parse_data->claim_token);
+ GNUNET_free (parse_data->ssid);
+}
diff --git a/src/testing/testing_api_cmd_merchant_get_order.c b/src/testing/testing_api_cmd_merchant_get_order.c
index 4ae459a3..1da6b7b6 100644
--- a/src/testing/testing_api_cmd_merchant_get_order.c
+++ b/src/testing/testing_api_cmd_merchant_get_order.c
@@ -441,6 +441,31 @@ merchant_get_order_cb (
return;
}
}
+ else
+ {
+ /* FIXME: Check all of the members of `pud` */
+ struct TALER_MERCHANT_PayUriData pud;
+ if (GNUNET_OK !=
+ TALER_MERCHANT_parse_pay_uri (osr->details.unpaid.taler_pay_uri,
+ &pud))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Taler pay uri is malformed\n");
+ TALER_TESTING_interpreter_fail (gos->is);
+ return;
+ }
+
+ if ((0 != strcmp ("localhost:8080",
+ pud.merchant_host)) ||
+ (NULL != pud.merchant_prefix_path))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Taler pay uri is incorrect\n");
+ TALER_TESTING_interpreter_fail (gos->is);
+ TALER_MERCHANT_parse_pay_uri_free (&pud);
+ return;
+ }
+ }
break;
default:
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,