diff options
author | Christian Grothoff <christian@grothoff.org> | 2020-03-01 13:04:06 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2020-03-01 13:04:06 +0100 |
commit | d11a13c825a169e3cc42efa8dca679c14e627d40 (patch) | |
tree | 57d9f7ff91a65b48d250a590ff0a694b7f4f993f /src/util | |
parent | effa6451a265d0a4d745443e9ee022c3f24e1bb8 (diff) |
de-duplicate url.c
Diffstat (limited to 'src/util')
-rw-r--r-- | src/util/payto.c | 25 | ||||
-rw-r--r-- | src/util/url.c | 222 | ||||
-rw-r--r-- | src/util/util.c | 5 |
3 files changed, 145 insertions, 107 deletions
diff --git a/src/util/payto.c b/src/util/payto.c index 484db0bb2..3540052c1 100644 --- a/src/util/payto.c +++ b/src/util/payto.c @@ -29,7 +29,9 @@ /** - * Obtain the payment method from a @a payto_uri + * Obtain the payment method from a @a payto_uri. The + * format of a payto URI is 'payto://$METHOD/$SOMETHING'. + * We return $METHOD. * * @param payto_uri the URL to parse * @return NULL on error (malformed @a payto_uri) @@ -40,9 +42,9 @@ TALER_payto_get_method (const char *payto_uri) const char *start; const char *end; - if (0 != strncmp (payto_uri, - PAYTO, - strlen (PAYTO))) + if (0 != strncasecmp (payto_uri, + PAYTO, + strlen (PAYTO))) return NULL; start = &payto_uri[strlen (PAYTO)]; end = strchr (start, @@ -55,7 +57,10 @@ TALER_payto_get_method (const char *payto_uri) /** - * Obtain the account name from a payto URL. + * Obtain the account name from a payto URL. The format + * of the @a payto URL is 'payto://x-taler-bank/$HOSTNAME/$ACCOUNT[?PARAMS]'. + * We check the first part matches, skip over the $HOSTNAME + * and return the $ACCOUNT portion. * * @param payto an x-taler-bank payto URL * @return only the account name from the @a payto URL, NULL if not an x-taler-bank @@ -68,18 +73,18 @@ TALER_xtalerbank_account_from_payto (const char *payto) const char *end; if (0 != strncasecmp (payto, - "payto://x-taler-bank/", - strlen ("payto://x-taler-bank/"))) + PAYTO "x-taler-bank/", + strlen (PAYTO "x-taler-bank/"))) return NULL; - beg = strchr (&payto[strlen ("payto://x-taler-bank/")], + beg = strchr (&payto[strlen (PAYTO "x-taler-bank/")], '/'); if (NULL == beg) return NULL; - beg++; + beg++; /* now points to $ACCOUNT */ end = strchr (beg, '?'); if (NULL == end) - return GNUNET_strdup (beg); + return GNUNET_strdup (beg); /* optional part is missing */ return GNUNET_strndup (beg, end - beg); } diff --git a/src/util/url.c b/src/util/url.c index 2096ebd8b..22bdd3fc6 100644 --- a/src/util/url.c +++ b/src/util/url.c @@ -84,12 +84,14 @@ static void buffer_write_urlencode (struct GNUNET_Buffer *buf, const char *s) { - GNUNET_buffer_ensure_remaining (buf, urlencode_len (s) + 1); - + GNUNET_buffer_ensure_remaining (buf, + urlencode_len (s) + 1); for (size_t i = 0; i < strlen (s); i++) { if (GNUNET_YES == is_reserved (s[i])) - GNUNET_buffer_write_fstr (buf, "%%%02X", s[i]); + GNUNET_buffer_write_fstr (buf, + "%%%02X", + s[i]); else buf->mem[buf->position++] = s[i]; } @@ -107,12 +109,96 @@ TALER_urlencode (const char *s) { struct GNUNET_Buffer buf = { 0 }; - buffer_write_urlencode (&buf, s); + buffer_write_urlencode (&buf, + s); return GNUNET_buffer_reap_str (&buf); } /** + * Compute the total length of the @a args given. The args are a + * NULL-terminated list of key-value pairs, where the values + * must be URL-encoded. When serializing, the pairs will be separated + * via '?' or '&' and an '=' between key and value. Hence each + * pair takes an extra 2 characters to encode. This function computes + * how many bytes are needed. It must match the #serialize_arguments() + * function. + * + * @param args NULL-terminated key-value pairs (char *) for query parameters + * @return number of bytes needed (excluding 0-terminator) for the string buffer + */ +static size_t +calculate_argument_length (va_list args) +{ + size_t len = 0; + va_list ap; + + va_copy (ap, + args); + while (1) + { + char *key; + char *value; + + key = va_arg (ap, + char *); + if (NULL == key) + break; + value = va_arg (ap, + char *); + if (NULL == value) + continue; + len += urlencode_len (value) + strlen (key) + 2; + } + va_end (ap); + return len; +} + + +/** + * Take the key-value pairs in @a args and serialize them into + * @a buf, using URL encoding for the values. + * + * @param buf where to write the values + * @param args NULL-terminated key-value pairs (char *) for query parameters, + * the value will be url-encoded + */ +static void +serialize_arguments (struct GNUNET_Buffer *buf, + va_list args) +{ + /* used to indicate if we are processing the initial + parameter which starts with '?' or subsequent + parameters which are separated with '&' */ + unsigned int iparam = 0; + + while (1) + { + char *key; + char *value; + + key = va_arg (args, + char *); + if (NULL == key) + break; + value = va_arg (args, + char *); + if (NULL == value) + continue; + GNUNET_buffer_write_str (buf, + (0 == iparam) ? "?" : "&"); + iparam = 1; + GNUNET_buffer_write_str (buf, + key); + GNUNET_buffer_write_str (buf, + "="); + buffer_write_urlencode (buf, + value); + } +} + + +/** * Make an absolute URL with query parameters. * * @param base_url absolute base URL to use @@ -127,9 +213,8 @@ TALER_url_join (const char *base_url, const char *path, ...) { - unsigned int iparam = 0; - va_list args; struct GNUNET_Buffer buf = { 0 }; + va_list args; size_t len; GNUNET_assert (NULL != base_url); @@ -157,46 +242,20 @@ TALER_url_join (const char *base_url, return NULL; } - /* 1st pass: compute length */ - len = strlen (base_url) + strlen (path) + 1; - - va_start (args, path); - while (1) - { - char *key; - char *value; - key = va_arg (args, char *); - if (NULL == key) - break; - value = va_arg (args, char *); - if (NULL == value) - continue; - len += urlencode_len (value) + strlen (key) + 2; - } - va_end (args); - - GNUNET_buffer_prealloc (&buf, len); - GNUNET_buffer_write_str (&buf, base_url); - GNUNET_buffer_write_str (&buf, path); + va_start (args, + path); - va_start (args, path); - while (1) - { - char *key; - char *value; - - key = va_arg (args, char *); - if (NULL == key) - break; - value = va_arg (args, char *); - if (NULL == value) - continue; - GNUNET_buffer_write_str (&buf, (0 == iparam) ? "?" : "&"); - iparam++; - GNUNET_buffer_write_str (&buf, key); - GNUNET_buffer_write_str (&buf, "="); - buffer_write_urlencode (&buf, value); - } + len = strlen (base_url) + strlen (path) + 1; + len += calculate_argument_length (args); + + GNUNET_buffer_prealloc (&buf, + len); + GNUNET_buffer_write_str (&buf, + base_url); + GNUNET_buffer_write_str (&buf, + path); + serialize_arguments (&buf, + args); va_end (args); return GNUNET_buffer_reap_str (&buf); @@ -222,56 +281,26 @@ TALER_url_absolute_raw_va (const char *proto, va_list args) { struct GNUNET_Buffer buf = { 0 }; - unsigned int iparam = 0; size_t len = 0; - va_list args2; len += strlen (proto) + strlen ("://") + strlen (host); len += strlen (prefix) + strlen (path); - - va_copy (args2, args); - while (1) - { - char *key; - char *value; - key = va_arg (args2, char *); - if (NULL == key) - break; - value = va_arg (args2, char *); - if (NULL == value) - continue; - len += urlencode_len (value) + strlen (key) + 2; - } - va_end (args2); - - GNUNET_buffer_prealloc (&buf, len); - - GNUNET_buffer_write_str (&buf, proto); - GNUNET_buffer_write_str (&buf, "://"); - GNUNET_buffer_write_str (&buf, host); - - GNUNET_buffer_write_path (&buf, prefix); - GNUNET_buffer_write_path (&buf, path); - - va_copy (args2, args); - while (1) - { - char *key; - char *value; - key = va_arg (args, char *); - if (NULL == key) - break; - value = va_arg (args, char *); - if (NULL == value) - continue; - GNUNET_buffer_write_str (&buf, (0 == iparam) ? "?" : "&"); - iparam++; - GNUNET_buffer_write_str (&buf, key); - GNUNET_buffer_write_str (&buf, "="); - buffer_write_urlencode (&buf, value); - } - va_end (args2); - + len += calculate_argument_length (args); + + GNUNET_buffer_prealloc (&buf, + len); + GNUNET_buffer_write_str (&buf, + proto); + GNUNET_buffer_write_str (&buf, + "://"); + GNUNET_buffer_write_str (&buf, + host); + GNUNET_buffer_write_path (&buf, + prefix); + GNUNET_buffer_write_path (&buf, + path); + serialize_arguments (&buf, + args); return GNUNET_buffer_reap_str (&buf); } @@ -285,7 +314,7 @@ TALER_url_absolute_raw_va (const char *proto, * @param path path for the URL * @param ... NULL-terminated key-value pairs (char *) for query parameters, * the value will be url-encoded - * @returns the URL, must be freed with #GNUNET_free + * @return the URL, must be freed with #GNUNET_free */ char * TALER_url_absolute_raw (const char *proto, @@ -297,8 +326,13 @@ TALER_url_absolute_raw (const char *proto, char *result; va_list args; - va_start (args, path); - result = TALER_url_absolute_raw_va (proto, host, prefix, path, args); + va_start (args, + path); + result = TALER_url_absolute_raw_va (proto, + host, + prefix, + path, + args); va_end (args); return result; } diff --git a/src/util/util.c b/src/util/util.c index f49bc7c2e..489928dd4 100644 --- a/src/util/util.c +++ b/src/util/util.c @@ -25,9 +25,8 @@ /** - * Convert a buffer to an 8-character string - * representative of the contents. This is used - * for logging binary data when debugging. + * Convert a buffer to an 8-character string representative of the + * contents. This is used for logging binary data when debugging. * * @param buf buffer to log * @param buf_size number of bytes in @a buf |