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 /src/lib | |
parent | ef6fed10b06bef0ba7d9003b594c8e994665229f (diff) | |
download | merchant-119de8db9e317e46ebe800524b806809d2b435b0.tar.gz merchant-119de8db9e317e46ebe800524b806809d2b435b0.tar.bz2 merchant-119de8db9e317e46ebe800524b806809d2b435b0.zip |
implement parser for taler_pay_uri
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/merchant_api_common.c | 220 |
1 files changed, 220 insertions, 0 deletions
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); +} |