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:
@ -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>
|
||||
|
||||
*
|
||||
|
@ -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, "/?()'*");
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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 */
|
||||
|
@ -9,4 +9,6 @@ Makefile.in
|
||||
*.bbg
|
||||
*.da
|
||||
*.gcov
|
||||
split
|
||||
url
|
||||
utf7
|
@ -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);
|
||||
|
Reference in New Issue
Block a user