From 2d607c9fcd1a5ca1c6920d7ce7748cae497ad77f Mon Sep 17 00:00:00 2001 From: Benny Prijono Date: Fri, 1 Oct 2010 06:43:17 +0000 Subject: Re #1136 (Basic and digest authentication in the HTTP client): fixed error in parsing URL if the path contains at ("@") character git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@3332 74dad513-b988-da41-8d7b-12977e46ad98 --- pjlib-util/src/pjlib-util-test/http_client.c | 12 +++++++++++ pjlib-util/src/pjlib-util/http_client.c | 32 ++++++++++++++++++++++++++-- 2 files changed, 42 insertions(+), 2 deletions(-) (limited to 'pjlib-util') diff --git a/pjlib-util/src/pjlib-util-test/http_client.c b/pjlib-util/src/pjlib-util-test/http_client.c index d8445092..9194f2bb 100644 --- a/pjlib-util/src/pjlib-util-test/http_client.c +++ b/pjlib-util/src/pjlib-util-test/http_client.c @@ -303,6 +303,15 @@ static int parse_url_test() /* empty username and passwd*/ {"http://:@pjsip.org", PJ_SUCCESS, "", "", "pjsip.org", 80, "/"}, + /* '@' character in username and path */ + {"http://user@pjsip.org/@", PJ_SUCCESS, "user", "", "pjsip.org", 80, "/@"}, + + /* '@' character in path */ + {"http://pjsip.org/@", PJ_SUCCESS, "", "", "pjsip.org", 80, "/@"}, + + /* '@' character in path */ + {"http://pjsip.org/one@", PJ_SUCCESS, "", "", "pjsip.org", 80, "/one@"}, + /* Invalid URL */ {"http://:", PJ_EINVAL, "", "", "", 0, ""}, @@ -324,6 +333,9 @@ static int parse_url_test() /* Invalid URL */ {"http://@/", PJ_EINVAL, "", "", "", 0, ""}, + /* Invalid URL */ + {"http:///@", PJ_EINVAL, "", "", "", 0, ""}, + /* Invalid URL */ {"http://:::", PJ_EINVAL, "", "", "", 0, ""}, }; diff --git a/pjlib-util/src/pjlib-util/http_client.c b/pjlib-util/src/pjlib-util/http_client.c index 31c46b45..2e966387 100644 --- a/pjlib-util/src/pjlib-util/http_client.c +++ b/pjlib-util/src/pjlib-util/http_client.c @@ -766,6 +766,34 @@ PJ_DEF(void) pj_http_req_param_default(pj_http_req_param *param) pj_time_val_normalize(¶m->timeout); } +/* Get the location of '@' character to indicate the end of + * user:passwd part of an URI. If user:passwd part is not + * present, NULL will be returned. + */ +static char *get_url_at_pos(const char *str, long len) +{ + const char *end = str + len; + const char *p = str; + + /* skip scheme: */ + while (p!=end && *p!='/') ++p; + if (p!=end && *p=='/') ++p; + if (p!=end && *p=='/') ++p; + if (p==end) return NULL; + + for (; p!=end; ++p) { + switch (*p) { + case '/': + return NULL; + case '@': + return (char*)p; + } + } + + return NULL; +} + + PJ_DEF(pj_status_t) pj_http_req_parse_url(const pj_str_t *url, pj_http_url *hurl) { @@ -801,7 +829,7 @@ PJ_DEF(pj_status_t) pj_http_req_parse_url(const pj_str_t *url, } pj_scan_advance_n(&scanner, 3, PJ_FALSE); - if (pj_memchr(url->ptr, '@', url->slen)) { + if (get_url_at_pos(url->ptr, url->slen)) { /* Parse username and password */ pj_scan_get_until_chr(&scanner, ":@", &hurl->username); if (*scanner.curptr == ':') { @@ -924,7 +952,7 @@ PJ_DEF(pj_status_t) pj_http_req_create(pj_pool_t *pool, /* If URL contains username/password, move them to credential and * remove them from the URL. */ - if ((at_pos=pj_strchr(&hreq->url, '@')) != NULL) { + if ((at_pos=get_url_at_pos(hreq->url.ptr, hreq->url.slen)) != NULL) { pj_str_t tmp; char *user_pos = pj_strchr(&hreq->url, '/'); int removed_len; -- cgit v1.2.3