de-duplicate url.c

This commit is contained in:
Christian Grothoff 2020-03-01 13:04:06 +01:00
parent effa6451a2
commit d11a13c825
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
4 changed files with 144 additions and 106 deletions

View File

@ -281,7 +281,7 @@ static struct GNUNET_CURL_RescheduleContext *rc;
/**
* How long should we sleep when idle before trying to find more work?
*/
static struct GNUNET_TIME_Relative aggreator_idle_sleep_interval;
static struct GNUNET_TIME_Relative aggregator_idle_sleep_interval;
/**
* Value to return from main(). #GNUNET_OK on success, #GNUNET_SYSERR

View File

@ -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);
}

View File

@ -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,11 +109,95 @@ 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.
*
@ -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 */
va_start (args,
path);
len = strlen (base_url) + strlen (path) + 1;
len += calculate_argument_length (args);
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);
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);
}
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);
len += calculate_argument_length (args);
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);
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;
}

View File

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