Like camel_url_encode, but works directly on an existing GString.

* 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

svn path=/trunk/; revision=20545
This commit is contained in:
Dan Winship
2003-03-27 15:37:47 +00:00
parent b3293f0d99
commit be9db81541
6 changed files with 117 additions and 79 deletions

View File

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

View File

@ -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, "/?()'*");
}

View File

@ -4,7 +4,6 @@
/*
* Authors:
* Dan Winship <danw@ximian.com>
* Tiago Ant<6E>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;
GString *str;
char *encoded;
/* worst case scenario = 3 times the initial */
p = work = g_malloc (3 * strlen (part) + 1);
str = g_string_new (NULL);
append_url_encoded (str, part, escape_extra);
encoded = str->str;
g_string_free (str, FALSE);
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';
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)
{

View File

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

View File

@ -9,4 +9,6 @@ Makefile.in
*.bbg
*.da
*.gcov
split
url
utf7

View File

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