aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--camel/ChangeLog16
-rw-r--r--camel/camel-file-utils.c2
-rw-r--r--camel/camel-url.c152
-rw-r--r--camel/camel-url.h3
-rw-r--r--camel/tests/misc/.cvsignore4
-rw-r--r--camel/tests/misc/url.c19
6 files changed, 117 insertions, 79 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog
index 8a01527f99..94dad5c5e1 100644
--- a/camel/ChangeLog
+++ b/camel/ChangeLog
@@ -1,3 +1,19 @@
+2003-03-27 Dan Winship <danw@ximian.com>
+
+ * camel-url.c (append_url_encoded): Like camel_url_encode, but
+ works directly on an existing GString.
+ (camel_url_to_string, output_param): Use it.
+ (camel_url_encode): Likewise. Remove "escape_unsafe" arg since the
+ "unsafe" chars are the ones that should *always* be escaped, and
+ the places we were passing FALSE were wrong.
+ (camel_url_decode): replace with a new version
+
+ * camel-file-utils.c (camel_file_util_safe_filename): Remove extra
+ arg to camel_url_encode.
+
+ * tests/misc/url.c (main): Add tests of basic URL parsing and
+ unparsing
+
2003-03-28 Not Zed <NotZed@Ximian.com>
*
diff --git a/camel/camel-file-utils.c b/camel/camel-file-utils.c
index 33f599d463..f0e400ebac 100644
--- a/camel/camel-file-utils.c
+++ b/camel/camel-file-utils.c
@@ -328,5 +328,5 @@ camel_file_util_safe_filename(const char *name)
if (name == NULL)
return NULL;
- return camel_url_encode(name, TRUE, "/?()'*");
+ return camel_url_encode(name, "/?()'*");
}
diff --git a/camel/camel-url.c b/camel/camel-url.c
index a78ba44b6a..7b1c31db5c 100644
--- a/camel/camel-url.c
+++ b/camel/camel-url.c
@@ -4,7 +4,6 @@
/*
* Authors:
* Dan Winship <danw@ximian.com>
- * Tiago Antào <tiagoantao@bigfoot.com>
* Jeffrey Stedfast <fejj@ximian.com>
*
* Copyright 1999-2001 Ximian, Inc. (www.ximian.com)
@@ -42,6 +41,8 @@
static void copy_param (GQuark key_id, gpointer data, gpointer user_data);
static void output_param (GQuark key_id, gpointer data, gpointer user_data);
+static void append_url_encoded (GString *str, const char *in, const char *extra_enc_chars);
+
/**
* camel_url_new_with_base:
* @base: a base URL
@@ -304,7 +305,7 @@ char *
camel_url_to_string (CamelURL *url, guint32 flags)
{
GString *str;
- char *enc, *return_result;
+ char *return_result;
/* IF YOU CHANGE ANYTHING IN THIS FUNCTION, RUN
* tests/misc/url AFTERWARD.
@@ -318,47 +319,35 @@ camel_url_to_string (CamelURL *url, guint32 flags)
if (url->host) {
g_string_append (str, "//");
if (url->user) {
- enc = camel_url_encode (url->user, TRUE, ":;@/");
- g_string_append (str, enc);
- g_free (enc);
- }
- if (url->authmech && *url->authmech) {
- enc = camel_url_encode (url->authmech, TRUE, ":@/");
- g_string_append_printf (str, ";auth=%s", enc);
- g_free (enc);
- }
- if (url->passwd && !(flags & CAMEL_URL_HIDE_PASSWORD)) {
- enc = camel_url_encode (url->passwd, TRUE, "@/");
- g_string_append_printf (str, ":%s", enc);
- g_free (enc);
- }
- if (url->host) {
- enc = camel_url_encode (url->host, TRUE, ":/");
- g_string_append_printf (str, "%s%s", url->user ? "@" : "", enc);
- g_free (enc);
+ append_url_encoded (str, url->user, ":;@/");
+ if (url->authmech && *url->authmech) {
+ g_string_append (str, ";auth=");
+ append_url_encoded (str, url->authmech, ":@/");
+ }
+ if (url->passwd && !(flags & CAMEL_URL_HIDE_PASSWORD)) {
+ g_string_append_c (str, ':');
+ append_url_encoded (str, url->passwd, "@/");
+ }
+ g_string_append_c (str, '@');
}
+ append_url_encoded (str, url->host, ":/");
if (url->port)
g_string_append_printf (str, ":%d", url->port);
if (!url->path && (url->params || url->query || url->fragment))
g_string_append_c (str, '/');
}
- if (url->path) {
- enc = camel_url_encode (url->path, FALSE, ";?#");
- g_string_append_printf (str, "%s", enc);
- g_free (enc);
- }
+ if (url->path)
+ append_url_encoded (str, url->path, ";?");
if (url->params && !(flags & CAMEL_URL_HIDE_PARAMS))
g_datalist_foreach (&url->params, output_param, str);
if (url->query) {
- enc = camel_url_encode (url->query, FALSE, "#");
- g_string_append_printf (str, "?%s", enc);
- g_free (enc);
+ g_string_append_c (str, '?');
+ append_url_encoded (str, url->query, NULL);
}
if (url->fragment) {
- enc = camel_url_encode (url->fragment, FALSE, NULL);
- g_string_append_printf (str, "#%s", enc);
- g_free (enc);
+ g_string_append_c (str, '#');
+ append_url_encoded (str, url->fragment, NULL);
}
return_result = str->str;
@@ -371,15 +360,12 @@ static void
output_param (GQuark key_id, gpointer data, gpointer user_data)
{
GString *str = user_data;
- char *enc;
-
- enc = camel_url_encode (g_quark_to_string (key_id), FALSE, "?#");
- g_string_append_printf (str, ";%s", enc);
- g_free (enc);
+
+ g_string_append_c (str, ';');
+ append_url_encoded (str, g_quark_to_string (key_id), "?=");
if (*(char *)data) {
- enc = camel_url_encode (data, FALSE, "?#");
- g_string_append_printf (str, "=%s", enc);
- g_free (enc);
+ g_string_append_c (str, '=');
+ append_url_encoded (str, data, "?");
}
}
@@ -443,42 +429,63 @@ camel_url_get_param (CamelURL *url, const char *name)
return g_datalist_get_data (&url->params, name);
}
+/* From RFC 2396 2.4.3, the characters that should always be encoded */
+static const char url_encoded_char[] = {
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x00 - 0x0f */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x10 - 0x1f */
+ 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ' ' - '/' */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, /* '0' - '?' */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* '@' - 'O' */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, /* 'P' - '_' */
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* '`' - 'o' */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /* 'p' - 0x7f */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+};
+
+static void
+append_url_encoded (GString *str, const char *in, const char *extra_enc_chars)
+{
+ const unsigned char *s = (const unsigned char *)in;
+
+ while (*s) {
+ if (url_encoded_char[*s] ||
+ (extra_enc_chars && strchr (extra_enc_chars, *s)))
+ g_string_append_printf (str, "%%%02x", (int)*s++);
+ else
+ g_string_append_c (str, *s++);
+ }
+}
/**
* camel_url_encode:
* @part: a URL part
- * @escape_unsafe: whether or not to %-escape "unsafe" characters.
- * ("%#<>{}|\^~[]`)
- * @escape_extra: additional characters to escape.
+ * @escape_extra: additional characters beyond " \"%#<>{}|\^[]`"
+ * to escape (or %NULL)
*
* This %-encodes the given URL part and returns the escaped version
* in allocated memory, which the caller must free when it is done.
**/
char *
-camel_url_encode (const char *part, gboolean escape_unsafe,
- const char *escape_extra)
+camel_url_encode (const char *part, const char *escape_extra)
{
- char *work, *p;
-
- /* worst case scenario = 3 times the initial */
- p = work = g_malloc (3 * strlen (part) + 1);
+ GString *str;
+ char *encoded;
- while (*part) {
- if (((guchar) *part >= 127) || ((guchar) *part <= ' ') ||
- (escape_unsafe && strchr ("\"%#<>{}|\\^~[]`", *part)) ||
- (escape_extra && strchr (escape_extra, *part))) {
- sprintf (p, "%%%.02hX", (guchar) *part++);
- p += 3;
- } else
- *p++ = *part++;
- }
- *p = '\0';
+ str = g_string_new (NULL);
+ append_url_encoded (str, part, escape_extra);
+ encoded = str->str;
+ g_string_free (str, FALSE);
- return work;
+ return encoded;
}
-#define HEXVAL(c) (isdigit (c) ? (c) - '0' : tolower (c) - 'a' + 10)
-
/**
* camel_url_decode:
* @part: a URL part
@@ -490,22 +497,21 @@ camel_url_encode (const char *part, gboolean escape_unsafe,
void
camel_url_decode (char *part)
{
- guchar *s, *d;
+ unsigned char *s, *d;
- s = d = (guchar *)part;
- while (*s) {
- if (*s == '%') {
- if (isxdigit (s[1]) && isxdigit (s[2])) {
- *d++ = HEXVAL (s[1]) * 16 + HEXVAL (s[2]);
- s += 3;
- } else
- *d++ = *s++;
+#define XDIGIT(c) ((c) <= '9' ? (c) - '0' : ((c) & 0x4F) - 'A' + 10)
+
+ s = d = (unsigned char *)part;
+ do {
+ if (*s == '%' && s[1] && s[2]) {
+ *d++ = (XDIGIT (s[1]) << 4) + XDIGIT (s[2]);
+ s += 2;
} else
- *d++ = *s++;
- }
- *d = '\0';
+ *d++ = *s;
+ } while (*s++);
}
+
guint
camel_url_hash (const void *v)
{
diff --git a/camel/camel-url.h b/camel/camel-url.h
index 6bce26c8ad..562befa83e 100644
--- a/camel/camel-url.h
+++ b/camel/camel-url.h
@@ -59,8 +59,7 @@ CamelURL *camel_url_new (const char *url_string, CamelException *ex);
char *camel_url_to_string (CamelURL *url, guint32 flags);
void camel_url_free (CamelURL *url);
-char *camel_url_encode (const char *part, gboolean escape_unsafe,
- const char *escape_extra);
+char *camel_url_encode (const char *part, const char *escape_extra);
void camel_url_decode (char *part);
/* for editing url's */
diff --git a/camel/tests/misc/.cvsignore b/camel/tests/misc/.cvsignore
index 7ef94ab5fa..fbb8316a8b 100644
--- a/camel/tests/misc/.cvsignore
+++ b/camel/tests/misc/.cvsignore
@@ -9,4 +9,6 @@ Makefile.in
*.bbg
*.da
*.gcov
-url \ No newline at end of file
+split
+url
+utf7 \ No newline at end of file
diff --git a/camel/tests/misc/url.c b/camel/tests/misc/url.c
index adc6278bae..c2db806621 100644
--- a/camel/tests/misc/url.c
+++ b/camel/tests/misc/url.c
@@ -52,7 +52,22 @@ struct {
{ "g/./h", "http://a/b/c/g/h" },
{ "g/../h", "http://a/b/c/h" },
{ "http:g", "http:g" },
- { "http:", "http:" }
+ { "http:", "http:" },
+
+ /* (not from rfc 1808) */
+ { "sendmail:", "sendmail:" },
+ { "mbox:/var/mail/user", "mbox:/var/mail/user" },
+ { "pop://user@host", "pop://user@host" },
+ { "pop://user@host:99", "pop://user@host:99" },
+ { "pop://user:password@host", "pop://user:password@host" },
+ { "pop://user:password@host:99", "pop://user:password@host:99" },
+ { "pop://user;auth=APOP@host", "pop://user;auth=APOP@host" },
+ { "pop://user@host/;keep_on_server", "pop://user@host/;keep_on_server" },
+ { "pop://user@host/;keep_on_server=1", "pop://user@host/;keep_on_server=1" },
+ { "pop://us%65r@host", "pop://user@host" },
+ { "pop://us%40r@host", "pop://us%40r@host" },
+ { "pop://us%3ar@host", "pop://us%3ar@host" },
+ { "pop://us%2fr@host", "pop://us%2fr@host" }
};
int num_tests = sizeof (tests) / sizeof (tests[0]);
@@ -66,7 +81,7 @@ main (int argc, char **argv)
camel_test_init (argc, argv);
- camel_test_start ("RFC1808 relative URL parsing");
+ camel_test_start ("URL parsing");
camel_test_push ("base URL parsing");
camel_exception_init (&ex);