Commit 796d9b68 authored by Pekka Pessi's avatar Pekka Pessi

url.c: do not un-escape %40 in URI parameters.

Do not unescape %2C, %3B, %3D, or %40 in URI parameters, nor
%2C, %2F, %3B, %3D, or %40 in URI path.

The @ sign can be ambiguous in the SIP URL, e.g.,

<sip:test.info;p

darcs-hash:20070903141455-65a35-61e1bee07ac93f94b9b67e51ed18a4a7e8b8eaf3.gz
parent 2b405629
......@@ -120,11 +120,12 @@ int test_quote(void)
d = url_as_string(home, u); TEST_1(d);
TEST_S(d, c);
d = "sip:&=+$,;?/:&=+$,@[::1]:56001;param=+$,/:@&;another=@"
d = "sip:&=+$,;?/:&=+$,@[::1]:56001;param=+$,/:@&;another=@%40%2F"
"?header=" RESERVED "&%3b%2f%3f%3a%40%26%3d%2b%24%2c";
u = url_hdup(home, (url_t *)d); TEST_1(u);
TEST_S(u->url_user, "&=+$,;?/");
TEST_S(u->url_host, "[::1]");
TEST_S(u->url_params, "param=+$,/:@&;another=@%40/");
TEST_S(u->url_headers, "header=" RESERVED "&%3B%2F%3F%3A%40%26%3D%2B%24%2C");
url_digest(hash1, sizeof(hash1), u, NULL);
url_digest(hash2, sizeof(hash2), (url_t const *)d, NULL);
......
......@@ -143,10 +143,10 @@
/* Internal prototypes */
static char *url_canonize(char *d, char const *s, size_t n,
char syn1, char syn2, char syn3,
unsigned syn33,
char const allowed[]);
static char *url_canonize2(char *d, char const *s, size_t n,
char syn1, char syn2, char syn3,
unsigned syn33,
unsigned m32, unsigned m64, unsigned m96);
static int url_tel_cmp_numbers(char const *A, char const *B);
......@@ -327,20 +327,23 @@ char *url_unescape(char *d, char const *s)
/** Canonize a URL component */
static
char *url_canonize(char *d, char const *s, size_t n,
char syn1, char syn2, char syn3,
unsigned syn33,
char const allowed[])
{
unsigned mask32 = 0xbe19003f, mask64 = 0x8000001e, mask96 = 0x8000001d;
MASKS_WITH_ALLOWED(allowed, mask32, mask64, mask96);
return url_canonize2(d, s, n, syn1, syn2, syn3, mask32, mask64, mask96);
return url_canonize2(d, s, n, syn33, mask32, mask64, mask96);
}
#define SYN33(c) (1 << (c - 33))
#define IS_SYN33(syn33, c) ((syn33 & (1 << (c - 33))) != 0)
/** Canonize a URL component (with precomputed mask) */
static
char *url_canonize2(char *d, char const * const s, size_t n,
char syn1, char syn2, char syn3,
unsigned syn33,
unsigned m32, unsigned m64, unsigned m96)
{
size_t i = 0;
......@@ -354,7 +357,7 @@ char *url_canonize2(char *d, char const * const s, size_t n,
unsigned char c = s[i], h1, h2;
if (c != '%') {
if (c != syn1 && c != syn2 && c != syn3 && IS_EXCLUDED(c, m32, m64, m96))
if (!IS_SYN33(syn33, c) && IS_EXCLUDED(c, m32, m64, m96))
return NULL;
*d = c;
continue;
......@@ -582,7 +585,7 @@ int _url_d(url_t *url, char *s)
char *scheme;
url->url_scheme = scheme = s; s[n] = '\0'; s = s + n + 1;
if (!(scheme = url_canonize(scheme, scheme, SIZE_MAX, NULNULNUL, "+")))
if (!(scheme = url_canonize(scheme, scheme, SIZE_MAX, 0, "+")))
return -1;
n = scheme - url->url_scheme;
......@@ -701,7 +704,7 @@ int _url_d(url_t *url, char *s)
case url_file:
case url_rtsp:
case url_rtspu:
if (!url_canonize2(port, port, SIZE_MAX, NULNULNUL, RESERVED_MASK))
if (!url_canonize2(port, port, SIZE_MAX, 0, RESERVED_MASK))
return -1;
/* Check that port is really numeric or wildcard */
......@@ -765,14 +768,14 @@ int url_d(url_t *url, char *s)
# define SIP_USER_UNRESERVED "&=+$,;?/"
s = (char *)url->url_user;
if (s && !url_canonize(s, s, SIZE_MAX, NULNULNUL, SIP_USER_UNRESERVED))
if (s && !url_canonize(s, s, SIZE_MAX, 0, SIP_USER_UNRESERVED))
return -1;
/* Having different charset in user and password does not make sense */
/* but that is how it is defined in RFC 3261 */
# define SIP_PASS_UNRESERVED "&=+$,"
s = (char *)url->url_password;
if (s && !url_canonize(s, s, SIZE_MAX, NULNULNUL, SIP_PASS_UNRESERVED))
if (s && !url_canonize(s, s, SIZE_MAX, 0, SIP_PASS_UNRESERVED))
return -1;
}
......@@ -780,31 +783,37 @@ int url_d(url_t *url, char *s)
# define USER_UNRESERVED "&=+$,;"
s = (char *)url->url_user;
if (s && !url_canonize(s, s, SIZE_MAX, NULNULNUL, USER_UNRESERVED))
if (s && !url_canonize(s, s, SIZE_MAX, 0, USER_UNRESERVED))
return -1;
# define PASS_UNRESERVED "&=+$,;:"
s = (char *)url->url_password;
if (s && !url_canonize(s, s, SIZE_MAX, NULNULNUL, PASS_UNRESERVED))
if (s && !url_canonize(s, s, SIZE_MAX, 0, PASS_UNRESERVED))
return -1;
}
s = (char *)url->url_host;
if (s && !url_canonize2(s, s, SIZE_MAX, NULNULNUL, RESERVED_MASK))
if (s && !url_canonize2(s, s, SIZE_MAX, 0, RESERVED_MASK))
return -1;
/* port is canonized by _url_d() */
/* Allow all URI characters but ? and ; */
# define PATH_UNRESERVED ":@&+$,"
s = (char *)url->url_path;
if (s && !url_canonize(s, s, SIZE_MAX, '/', ';', '=', PATH_UNRESERVED))
if (s && !url_canonize(s, s, SIZE_MAX,
/* Allow all URI characters but ? */
/* Allow unescaped /;?@, - but do not convert */
SYN33('/') | SYN33(';') | SYN33('=') | SYN33('@') |
SYN33(','),
/* Convert escaped :&+$ to unescaped */
":&+$"))
return -1;
/* Allow all URI characters but ? */
# define PARAMS_UNRESERVED ":@&+$,"
s = (char *)url->url_params;
if (s && !url_canonize(s, s, SIZE_MAX, ';', '=', NUL, PARAMS_UNRESERVED))
if (s && !url_canonize(s, s, SIZE_MAX,
/* Allow all URI characters but ? */
/* Allow unescaped ;=@, - but do not convert */
SYN33(';') | SYN33('=') | SYN33('@') | SYN33(','),
/* Convert escaped /:&+$ to unescaped */
"/:&+$"))
return -1;
/* Unhex alphanumeric and unreserved URI characters */
......@@ -814,7 +823,7 @@ int url_d(url_t *url, char *s)
/* Allow all URI characters (including reserved ones) */
s = (char *)url->url_fragment;
if (s && !url_canonize2(s, s, SIZE_MAX, NULNULNUL, URIC_MASK))
if (s && !url_canonize2(s, s, SIZE_MAX, 0, URIC_MASK))
return -1;
return 0;
......@@ -1934,7 +1943,7 @@ void url_string_update(su_md5_t *md5, char const *s)
su_md5_update(md5, ":", 1);
}
else if (n && s[n] == ':' ) {
at = url_canonize(schema, s, n, NULNULNUL, "+");
at = url_canonize(schema, s, n, 0, "+");
type = url_get_type(schema, at - schema);
su_md5_iupdate(md5, schema, at - schema);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment