gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] [taler-exchange] branch master updated: url construction he


From: gnunet
Subject: [GNUnet-SVN] [taler-exchange] branch master updated: url construction helpers
Date: Wed, 31 Jan 2018 17:47:09 +0100

This is an automated email from the git hooks/post-receive script.

dold pushed a commit to branch master
in repository exchange.

The following commit(s) were added to refs/heads/master by this push:
     new 3859a40  url construction helpers
3859a40 is described below

commit 3859a40f24e27ae6b825f0f4163d43bc95cc10d3
Author: Florian Dold <address@hidden>
AuthorDate: Wed Jan 31 17:47:01 2018 +0100

    url construction helpers
---
 src/include/taler_util.h |  59 ++++++++++
 src/util/Makefile.am     |  12 +-
 src/util/util.c          | 300 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 369 insertions(+), 2 deletions(-)

diff --git a/src/include/taler_util.h b/src/include/taler_util.h
index 84d4f5d..407521c 100644
--- a/src/include/taler_util.h
+++ b/src/include/taler_util.h
@@ -22,6 +22,7 @@
 #define TALER_UTIL_H
 
 #include <gnunet/gnunet_util_lib.h>
+#include <microhttpd.h>
 #include "taler_amount_lib.h"
 #include "taler_crypto_lib.h"
 
@@ -134,4 +135,62 @@ const struct GNUNET_OS_ProjectData *
 TALER_project_data_default (void);
 
 
+/**
+ * URL-encode a string according to rfc3986.
+ *
+ * @param s string to encode
+ * @returns the urlencoded string, the caller must free it with GNUNET_free
+ */
+char *
+TALER_urlencode (const char *s);
+
+
+/**
+ * Make an absolute URL with query parameters.
+ *
+ * @param base_url absolute base URL to use
+ * @param path path of the url
+ * @param ... NULL-terminated key-value pairs (char *) for query parameters,
+ *        only the value will be url-encoded
+ * @returns the URL, must be freed with #GNUNET_free
+ */
+char *
+TALER_url_join (const char *base_url,
+                const char *path,
+                ...);
+
+
+/**
+ * Make an absolute URL for the given parameters.
+ *
+ * @param proto protocol for the URL (typically https)
+ * @param host hostname for the URL
+ * @param prefix prefix for the URL
+ * @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
+ */
+char *
+TALER_url_absolute_raw (const char *proto,
+                        const char *host,
+                        const char *prefix,
+                        const char *path,
+                        ...);
+
+
+/**
+ * Make an absolute URL for a given MHD connection.
+ *
+ * @param path path of 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
+ */
+char *
+TALER_url_absolute_mhd (struct MHD_Connection *connection,
+                        const char *path,
+                        ...);
+
+
 #endif
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
index c05f756..4f9a636 100644
--- a/src/util/Makefile.am
+++ b/src/util/Makefile.am
@@ -57,11 +57,13 @@ libtalerutil_la_LDFLAGS = \
 
 TESTS = \
  test_amount \
- test_crypto
+ test_crypto \
+ test_url
 
 check_PROGRAMS = \
  test_amount \
- test_crypto
+ test_crypto \
+ test_url
 
 
 test_amount_SOURCES = \
@@ -75,3 +77,9 @@ test_crypto_SOURCES = \
 test_crypto_LDADD = \
   -lgnunetutil \
   libtalerutil.la
+
+test_url_SOURCES = \
+  test_url.c
+test_url_LDADD = \
+  -lgnunetutil \
+  libtalerutil.la
diff --git a/src/util/util.c b/src/util/util.c
index 8976b0a..00b67e2 100644
--- a/src/util/util.c
+++ b/src/util/util.c
@@ -159,4 +159,304 @@ TALER_getopt_get_amount (char shortName,
 }
 
 
+/**
+ * Check if a character is reserved and should
+ * be urlencoded.
+ *
+ * @param c character to look at
+ * @return #GNUNET_YES if @a c needs to be urlencoded,
+ *         #GNUNET_NO otherwise
+ */
+static bool
+is_reserved(char c)
+{
+  switch (c) {
+    case '0': case '1': case '2': case '3': case '4':
+    case '5': case '6': case '7': case '8': case '9':
+    case 'a': case 'b': case 'c': case 'd': case 'e':
+    case 'f': case 'g': case 'h': case 'i': case 'j':
+    case 'k': case 'l': case 'm': case 'n': case 'o':
+    case 'p': case 'q': case 'r': case 's': case 't':
+    case 'u': case 'v': case 'w': case 'x': case 'y': case 'z':
+    case 'A': case 'B': case 'C': case 'D': case 'E':
+    case 'F': case 'G': case 'H': case 'I': case 'J':
+    case 'K': case 'L': case 'M': case 'N': case 'O':
+    case 'P': case 'Q': case 'R': case 'S': case 'T':
+    case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z':
+    case '-': case '.': case '_': case '~':
+      return GNUNET_NO;
+    default:
+      break;
+  }
+  return GNUNET_YES;
+}
+
+
+/**
+ * URL-encode a string according to rfc3986.
+ *
+ * @param s string to encode
+ * @returns the urlencoded string, the caller must free it with GNUNET_free
+ */
+char *
+TALER_urlencode (const char *s)
+{
+  unsigned int new_size;
+  unsigned int i;
+  unsigned int t;
+  char *out;
+
+  new_size = strlen (s);
+  for (i = 0; i < strlen (s); i++)
+    if (GNUNET_YES == is_reserved (s[i]))
+      new_size += 2;
+  out = GNUNET_malloc (new_size + 1);
+  for (i = 0, t = 0; i < strlen (s); i++, t++)
+  {
+    if (GNUNET_YES == is_reserved (s[i]))
+    {
+      snprintf(&out[t], 4, "%%%02X", s[i]);
+      t += 2;
+      continue;
+    }
+    out[t] = s[i];
+  }
+  return out;
+}
+
+
+/**
+ * Grow a string in a buffer with the given size.
+ * The buffer is re-allocated if necessary.
+ *
+ * @param s string buffer
+ * @param p the string to append
+ * @param n pointer to the allocated size of n
+ * @returns pointer to the resulting buffer,
+ *          might differ from @a s (!!)
+ */
+static char *
+grow_string (char *s, const char *p, size_t *n)
+{
+  for (; strlen (s) + strlen (p) >= *n; *n *= 2);
+  s = GNUNET_realloc (s, *n);
+  GNUNET_assert (NULL != s);
+  strncat (s, p, *n);
+  return s;
+}
+
+
+/**
+ * Grow a string in a buffer with the given size.
+ * The buffer is re-allocated if necessary.
+ *
+ * Ensures that slashes are removed or added when joining paths.
+ *
+ * @param s string buffer
+ * @param p the string to append
+ * @param n pointer to the allocated size of n
+ * @returns pointer to the resulting buffer,
+ *          might differ from @a s (!!)
+ */
+static char *
+grow_string_path (char *s, const char *p, size_t *n)
+{
+  char a = (0 == strlen (s)) ? '\0' : s[strlen (s) - 1];
+  char b = (0 == strlen (p)) ? '\0' : p[0];
+
+  if ( (a == '/') && (b == '/'))
+  {
+    p++;
+  }
+  else if ( (a != '/') && (b != '/'))
+  {
+    if (NULL == (s = grow_string (s, "/", n)))
+      return NULL;
+  }
+  return grow_string (s, p, n);
+}
+
+
+/**
+ * Make an absolute URL with query parameters.
+ *
+ * @param base_url absolute base URL to use
+ * @param path path of 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
+ */
+char *
+TALER_url_join (const char *base_url,
+                const char *path,
+                ...)
+{
+  size_t n = 256;
+  char *res = GNUNET_malloc (n);
+  unsigned int iparam = 0;
+  char *enc;
+  va_list args;
+
+  GNUNET_assert (NULL != res);
+
+  grow_string (res, base_url, &n);
+
+  grow_string_path (res, path, &n);
+
+  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;
+    grow_string (res, (0 == iparam) ? "?" : "&", &n);
+    iparam++;
+    grow_string (res, key, &n);
+    grow_string (res, "=", &n);
+    enc = TALER_urlencode (value);
+    grow_string (res, enc, &n);
+    GNUNET_free (enc);
+  }
+
+  va_end (args);
+
+  return res;
+}
+
+
+/**
+ * Make an absolute URL for the given parameters.
+ *
+ * @param proto protocol for the URL (typically https)
+ * @param host hostname for the URL
+ * @param prefix prefix for the URL
+ * @param path path for the URL
+ * @param args NULL-terminated key-value pairs (char *) for query parameters,
+ *        the value will be url-encoded
+ * @returns the URL, must be freed with #GNUNET_free
+ */
+char *
+url_absolute_raw_va (const char *proto,
+                     const char *host,
+                     const char *prefix,
+                     const char *path,
+                     va_list args)
+{
+  size_t n = 256;
+  char *res = GNUNET_malloc (n);
+  char *enc;
+  unsigned int iparam = 0;
+
+  grow_string (res, proto, &n);
+  grow_string (res, "://", &n);
+  grow_string (res, host, &n);
+
+  grow_string_path (res, prefix, &n);
+
+  grow_string_path (res, path, &n);
+
+  while (1) {
+    char *key;
+    char *value;
+    key = va_arg (args, char *);
+    if (NULL == key)
+      break;
+    value = va_arg (args, char *);
+    if (NULL == value)
+      continue;
+    grow_string (res, (0 == iparam) ? "?" : "&", &n);
+    iparam++;
+    grow_string (res, key, &n);
+    grow_string (res, "=", &n);
+    enc = TALER_urlencode (value);
+    grow_string (res, enc, &n);
+    GNUNET_free (enc);
+  }
+
+  return res;
+}
+
+
+/**
+ * Make an absolute URL for the given parameters.
+ *
+ * @param proto protocol for the URL (typically https)
+ * @param host hostname for the URL
+ * @param prefix prefix for the URL
+ * @param path path for the URL
+ * @param args NULL-terminated key-value pairs (char *) for query parameters,
+ *        the value will be url-encoded
+ * @returns the URL, must be freed with #GNUNET_free
+ */
+char *
+TALER_url_absolute_raw (const char *proto,
+                        const char *host,
+                        const char *prefix,
+                        const char *path,
+                        ...)
+{
+  char *result;
+  va_list args;
+
+  va_start (args, path);
+  result = url_absolute_raw_va (proto, host, prefix, path, args);
+  va_end (args);
+  return result;
+}
+
+
+/**
+ * Make an absolute URL for a given MHD connection.
+ *
+ * @param path path of 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
+ */
+char *
+TALER_url_absolute_mhd (struct MHD_Connection *connection,
+                        const char *path,
+                        ...)
+{
+  /* By default we assume we're running under HTTPS */
+  const char *proto = "https";
+  const char *forwarded_proto = MHD_lookup_connection_value (connection, 
MHD_HEADER_KIND, "X-Forwarded-Proto");
+  const char *host;
+  const char *forwarded_host;
+  const char *prefix;
+  va_list args;
+  char *result;
+
+  if (NULL != forwarded_proto)
+    proto = forwarded_proto;
+
+  host = MHD_lookup_connection_value (connection, MHD_HEADER_KIND, "Host");
+  forwarded_host = MHD_lookup_connection_value (connection, MHD_HEADER_KIND, 
"X-Forwarded-Host");
+
+  prefix = MHD_lookup_connection_value (connection, MHD_HEADER_KIND, 
"X-Forwarded-Prefix");
+  if (NULL == prefix)
+    prefix = "";
+
+  if (NULL != forwarded_host)
+    host = forwarded_host;
+
+  if (NULL == host)
+  {
+    /* Should never happen, at last the host header should be defined */
+    GNUNET_break (0);
+    return NULL;
+  }
+
+  va_start (args, path);
+  result = TALER_url_absolute_raw (proto, host, prefix, path, args);
+  va_end (args);
+  return result;
+}
+
+
 /* end of util.c */

-- 
To stop receiving notification emails like this one, please contact
address@hidden



reply via email to

[Prev in Thread] Current Thread [Next in Thread]