Commit 5f44484c authored by Pekka Pessi's avatar Pekka Pessi
Browse files

url.c: updated url_update() with # in username and IPv6 reference handling.

darcs-hash:20070124161401-65a35-11bd806701cb603833aeb986a2dc282b8bc0b4e9.gz
parent 6a2373d9
......@@ -108,7 +108,7 @@ int test_quote(void)
TEST_S(url_escape(unreserved, UNRESERVED, NULL), UNRESERVED);
TEST_S(url_unescape(unreserved, UNRESERVED), UNRESERVED);
d = "%73ip:%55@%68";
d = "%53ip:%75@%48"; /* Sip:u@H */
u = url_hdup(home, (url_t *)d); TEST_1(u);
url_digest(hash1, sizeof(hash1), u, NULL);
url_digest(hash2, sizeof(hash2), (url_t const *)d, NULL);
......@@ -125,9 +125,11 @@ int test_quote(void)
d = url_as_string(home, u); TEST_1(d);
TEST_S(d, c);
d = "sip:&=+$,;?/:&=+$,@host:56001;param=+$,/:@&;another=@"
d = "sip:&=+$,;?/:&=+$,@[::1]:56001;param=+$,/:@&;another=@"
"?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_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);
......@@ -137,8 +139,10 @@ int test_quote(void)
d = url_as_string(home, u); TEST_1(d);
TEST_S(d, c);
d = "http://&=+$,;:&=+$,;@host:8080/foo;param=+$,/:@&;another=@?query=" RESERVED;
d = "http://&=+$,;:&=+$,;@host:8080/foo;param=+$,/:@&;another=@"
"?query=" RESERVED;
u = url_hdup(home, (url_t *)d); TEST_1(u);
TEST_S(u->url_user, "&=+$,;"); TEST_S(u->url_password, "&=+$,;");
url_digest(hash1, sizeof(hash1), u, NULL);
url_digest(hash2, sizeof(hash2), (url_t const *)d, NULL);
TEST(memcmp(hash1, hash2, sizeof(hash1)), 0);
......@@ -337,6 +341,9 @@ int test_sip(void)
TEST(u->url_type, url_sip);
TEST_S(u->url_user, "#**00**#;foo=/bar");
TEST_1(!url_hdup(home, (url_t*)"SIP:#**00**#;foo=/bar@#127.0.0.1"));
TEST_1(!url_hdup(home, (url_t*)"SIP:#**00**#;foo=/bar;127.0.0.1"));
for (i = 32; i <= 256; i++) {
char pu[512];
char param[512];
......@@ -832,6 +839,16 @@ int test_http(void)
TEST_S(url->url_headers, "query");
TEST_S(url->url_params, NULL);
TEST_1(u = url_hdup(home, (void *)"http://[::1]/test;ing?here"));
TEST_S(u->url_host, "[::1]");
TEST_S(u->url_path, "test;ing");
TEST_S(u->url_headers, "here");
url_digest(hash1, sizeof(hash1), u, NULL);
url_digest(hash2, sizeof(hash2), (url_t *)"http://[::1]/test;ing?here",
NULL);
TEST(memcmp(hash1, hash2, sizeof(hash1)), 0);
su_home_deinit(home);
END();
......
......@@ -556,8 +556,8 @@ static
int _url_d(url_t *url, char *s)
{
size_t n, p;
char *s0, rest_c, *host;
int net_path = 1;
char *s0, rest_c, *host, *user;
int have_authority = 1;
memset(url, 0, sizeof(*url));
......@@ -582,89 +582,99 @@ int _url_d(url_t *url, char *s)
url->url_type = url_get_type(url->url_scheme, n);
net_path = !url_type_is_opaque(url->url_type);
have_authority = !url_type_is_opaque(url->url_type);
}
else {
url->url_type = url_unknown;
}
host = s;
user = NULL, host = s;
if (url->url_type == url_sip || url->url_type == url_sips) {
/* SIP URL may have /; in user part */
/* SIP URL may have /;? in user part but no path */
/* user-unreserved = "&" / "=" / "+" / "$" / "," / ";" / "?" / "/" */
/* Some #*@#* phones include unescaped # there, too */
n = strcspn(s, "@#"); /* Opaque part */
if (s[n] == '#') {
p = strcspn(s + n + 1, "@") + 1;
if (s[n + p] == '@')
n = strcspn(s, "@/;?#");
p = strcspn(s + n, "@");
if (s[n + p] == '@') {
n += p;
else
n = 0;
user = s;
host = s + n + 1;
}
n += strcspn(s + n, "/;?#");
}
else if (url->url_type == url_wv) {
else if (have_authority) {
if (url->url_type == url_wv) {
/* WV URL may have / in user part */
n = strcspn(s, "@#?;");
if (s[n] == '@')
if (s[n] == '@') {
user = s;
host = s + n + 1;
n += strcspn(s + n, ";?#");
}
else if (url->url_type == url_invalid) {
n = strcspn(s, "#");
}
else if (net_path && host[0] == '/') {
url->url_root = host[0]; /* Absolute path */
if (host[1] == '/') { /* We have host-part */
host += 2; s += 2;
}
else
host = NULL;
n = strcspn(s, "/;?#"); /* Find path, query and/or fragment */
else if (host[0] == '/' && host[1] != '/') {
/* foo:/bar or /bar - no authority, just path */
url->url_root = '/'; /* Absolute path */
host = NULL, n = 0;
}
else {
n = strcspn(s, "/;?#"); /* Find params, query and/or fragment */
if (host[0] == '/' && host[1] == '/') {
/* We have authority, / / foo or foo */
host += 2; s += 2, url->url_root = '/';
n = strcspn(s, "/?#@[]");
}
else
n = strcspn(s, "@;/?#");
rest_c = s[n]; s[n] = 0; s = rest_c ? s + n + 1 : NULL;
if (host) {
char *atsign, *port;
if (s[n] == '@')
user = host, host = user + n + 1;
if (!net_path) {
url->url_user = host;
host = NULL;
n += strcspn(s + n, ";/?#"); /* Find path, query and/or fragment */
}
}
else /* !have_authority */ {
user = host, host = NULL;
if (url->url_type != url_invalid)
n = strcspn(s, "/;?#"); /* Find params, query and/or fragment */
else
n = strcspn(s, "#");
}
else if ((atsign = strchr(host, '@'))) {
char *user;
url->url_user = user = host;
if (atsign)
*atsign++ = '\0';
host = atsign;
rest_c = s[n]; s[n] = 0; s = rest_c ? s + n + 1 : NULL;
if (user) {
if (host) host[-1] = '\0';
url->url_user = user;
if (url->url_type != url_unknown) {
char *colon = strchr(user, ':');
if (colon)
*colon++ = '\0';
url->url_password = colon;
n = strcspn(user, ":");
if (user[n]) {
user[n] = '\0';
url->url_password = user + n + 1;
}
}
}
if ((url->url_host = host)) {
if (host) {
url->url_host = host;
/* IPv6 (and in some cases, IPv4) addresses are quoted with [] */
if (host[0] == '[') {
port = strchr(host, ']');
if (!port)
return -1;
port = strchr(port + 1, ':');
}
n = strcspn(host, "]");
if (host[n] && (host[n + 1] == '\0' || host[n + 1] == ':'))
n++;
else
port = strchr(host, ':');
n = 0;
}
else {
n = strcspn(host, ":");
}
if (port) {
*port++ = '\0';
if (n == 0 && url->url_type != url_unknown)
return -1;
if (host[n] == ':') {
char *port = host + n + 1;
url->url_port = port;
switch (url->url_type) {
case url_any:
......@@ -676,7 +686,6 @@ int _url_d(url_t *url, char *s)
case url_file:
case url_rtsp:
case url_rtspu:
if (!url_canonize2(port, port, SIZE_MAX, RESERVED_MASK))
return -1;
......@@ -684,13 +693,12 @@ int _url_d(url_t *url, char *s)
/* Port can be *digit, empty string or "*" */
while (*port >= '0' && *port <= '9')
port++;
if (port != url->url_port
? port[0] != '\0'
: port[0] != '\0'
&& (port[0] != '*' || port[1] != '\0'))
if (port != url->url_port ? port[0] != '\0'
: (port[0] != '*' || port[1] != '\0'))
return -1;
}
}
host[n] = 0;
}
}
......@@ -745,12 +753,15 @@ int url_d(url_t *url, char *s)
if (s && !url_canonize(s, s, SIZE_MAX, 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, SIP_PASS_UNRESERVED))
return -1;
} else {
}
else {
# define USER_UNRESERVED "&=+$,;"
s = (char *)url->url_user;
......@@ -946,7 +957,7 @@ issize_t url_e(char buffer[], isize_t n, url_t const *url)
}
/** Calculate the lengh of URL when encoded.
/** Calculate the length of URL when encoded.
*
*/
isize_t url_len(url_t const * url)
......@@ -1892,8 +1903,8 @@ void canon_update(su_md5_t *md5, char const *s, size_t n, char const *allow)
static
void url_string_update(su_md5_t *md5, char const *s)
{
size_t n;
int hostpart = 1;
size_t n, p;
int have_authority = 1;
enum url_type_e type = url_any;
char const *at, *colon;
char schema[48];
......@@ -1913,7 +1924,7 @@ void url_string_update(su_md5_t *md5, char const *s)
type = url_get_type(schema, at - schema);
su_md5_iupdate(md5, schema, at - schema);
hostpart = !url_type_is_opaque(type);
have_authority = !url_type_is_opaque(type);
s += n + 1;
}
else {
......@@ -1921,62 +1932,71 @@ void url_string_update(su_md5_t *md5, char const *s)
}
if (type == url_sip || type == url_sips) {
n = strcspn(s, "@#"); /* Opaque part */
if (s[n] != '@')
n = 0;
n += strcspn(s + n, "/;?#");
/* SIP URL may have /;? in user part but no path */
/* user-unreserved = "&" / "=" / "+" / "$" / "," / ";" / "?" / "/" */
/* Some #*@#* phones include unescaped # there, too */
n = strcspn(s, "@/;?#");
p = strcspn(s + n, "@");
if (s[n + p] == '@') {
n += p;
/* Ignore password in hash */
colon = memchr(s, ':', n);
p = colon ? colon - s : n;
canon_update(md5, s, p, SIP_USER_UNRESERVED);
s += n + 1; n = 0;
}
else if (type == url_wv) { /* WV URL may have / in user part */
n = strcspn(s, "@#?;");
if (s[n] == '@')
n += strcspn(s + n, ";?#");
else
su_md5_iupdate(md5, "", 1); /* user */
n += strcspn(s + n, "/;?#");
}
else if (!hostpart || s[0] != '/') {
n = strcspn(s, "/;?#"); /* Opaque part */
else if (have_authority) {
if (type == url_wv) { /* WV URL may have / in user part */
n = strcspn(s, "@;?#");
}
else if (s[1] == '/') {
s += 2;
n = strcspn(s, "/;?#"); /* Until host, path, query or fragment */
}
else {
else if (type != url_wv && s[0] == '/' && s[1] != '/') {
/* foo:/bar */
su_md5_update(md5, "\0\0", 2); /* user, host */
su_md5_striupdate(md5, url_port_default(type));
return;
}
else if (s[0] == '/' && s[1] == '/') {
/* We have authority, / / foo or foo */
s += 2;
n = strcspn(s, "/?#@[]");
}
else
n = strcspn(s, "@;/?#");
if (!hostpart) {
char const *colon = memchr(s, ':', n);
if (s[n] == '@') {
/* Ignore password in hash */
colon = type != url_unknown ? memchr(s, ':', n) : NULL;
p = colon ? colon - s : n;
canon_update(md5, s, p, SIP_USER_UNRESERVED);
s += n + 1;
n = strcspn(s, "/;?#"); /* Until path, query or fragment */
}
else {
su_md5_iupdate(md5, "", 1); /* user */
n += strcspn(s + n, "/;?#"); /* Until path, query or fragment */
}
}
else /* if (!have_authority) */ {
n = strcspn(s, ":/;?#"); /* Until pass, path, query or fragment */
if (colon) n = colon - s;
canon_update(md5, s, n, ""); /* user */
su_md5_update(md5, "\0", 1); /* host, no port */
su_md5_striupdate(md5, url_port_default(type));
return;
}
at = memchr(s, '@', n);
if (at) {
char const *allow =
(type == url_sip || type == url_sips)
? SIP_USER_UNRESERVED
: USER_UNRESERVED;
colon = type == url_unknown ? NULL : memchr(s, ':', at - s);
/* Updated only user part */
if (colon)
canon_update(md5, s, colon - s, allow);
else
canon_update(md5, s, at - s, allow);
n = n - (at + 1 - s);
s = at + 1;
if (n > 0 && s[0] == '[') { /* IPv6reference */
colon = memchr(s, ']', n);
if (colon == NULL || ++colon == s + n || *colon != ':')
colon = NULL;
}
else
su_md5_iupdate(md5, "", 1); /* user */
colon = memchr(s, ':', n);
colon = memchr(s, ':', n); /* XXX - IPv6! */
if (colon) {
canon_update(md5, s, colon - s, ""); /* host */
canon_update(md5, colon + 1, (s + n) - (colon + 1), "");
......
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