diff options
author | Jonathan Buchanan <jonathan.russ.buchanan@gmail.com> | 2020-08-09 23:28:56 -0400 |
---|---|---|
committer | Jonathan Buchanan <jonathan.russ.buchanan@gmail.com> | 2020-08-09 23:28:56 -0400 |
commit | 119de8db9e317e46ebe800524b806809d2b435b0 (patch) | |
tree | 737423707c1004bf86bcbb801c97cda1b256e8e3 | |
parent | ef6fed10b06bef0ba7d9003b594c8e994665229f (diff) | |
download | merchant-119de8db9e317e46ebe800524b806809d2b435b0.tar.gz merchant-119de8db9e317e46ebe800524b806809d2b435b0.tar.bz2 merchant-119de8db9e317e46ebe800524b806809d2b435b0.zip |
implement parser for taler_pay_uri
-rw-r--r-- | src/include/taler_merchant_service.h | 67 | ||||
-rw-r--r-- | src/lib/merchant_api_common.c | 220 | ||||
-rw-r--r-- | src/testing/testing_api_cmd_merchant_get_order.c | 25 |
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, |