diff options
-rw-r--r-- | test/nsurl.c | 26 | ||||
-rw-r--r-- | utils/nsurl.h | 3 | ||||
-rw-r--r-- | utils/nsurl/nsurl.c | 65 | ||||
-rw-r--r-- | utils/nsurl/parse.c | 20 | ||||
-rw-r--r-- | utils/nsurl/private.h | 7 |
5 files changed, 77 insertions, 44 deletions
diff --git a/test/nsurl.c b/test/nsurl.c index ba024291b..631e7ae2c 100644 --- a/test/nsurl.c +++ b/test/nsurl.c @@ -428,9 +428,9 @@ static const struct test_pairs join_tests[] = { { " ", "http://a/b/c/d;p?q" }, { "/", "http://a/" }, { " / ", "http://a/" }, - { " ? ", "http://a/b/c/d;p?" }, + { " ? ", "http://a/b/c/d;p" }, { " h ", "http://a/b/c/h" }, - { "//foo?", "http://foo/?" }, + { "//foo?", "http://foo/" }, { "//foo#bar", "http://foo/#bar" }, { "//foo/", "http://foo/" }, { "http://<!--#echo var=", "http://<!--/#echo%20var="}, @@ -531,21 +531,25 @@ END_TEST */ static const struct test_triplets replace_query_tests[] = { { "http://netsurf-browser.org/?magical=true", - "?magical=true&result=win", + "magical=true&result=win", "http://netsurf-browser.org/?magical=true&result=win"}, { "http://netsurf-browser.org/?magical=true#fragment", - "?magical=true&result=win", + "magical=true&result=win", "http://netsurf-browser.org/?magical=true&result=win#fragment"}, { "http://netsurf-browser.org/#fragment", - "?magical=true&result=win", + "magical=true&result=win", "http://netsurf-browser.org/?magical=true&result=win#fragment"}, { "http://netsurf-browser.org/path", - "?magical=true", + "magical=true", "http://netsurf-browser.org/path?magical=true"}, + { "http://netsurf-browser.org/path?magical=true", + "", + "http://netsurf-browser.org/path"}, + }; /** @@ -655,7 +659,7 @@ static const struct test_compare component_tests[] = { { "http://u:p@a:66/b/c/d;p?q#f", "a", NSURL_HOST, true }, { "http://u:p@a:66/b/c/d;p?q#f", "66", NSURL_PORT, true }, { "http://u:p@a:66/b/c/d;p?q#f", "/b/c/d;p", NSURL_PATH, true }, - { "http://u:p@a:66/b/c/d;p?q#f", "?q", NSURL_QUERY, true }, + { "http://u:p@a:66/b/c/d;p?q#f", "q", NSURL_QUERY, true }, { "http://u:p@a:66/b/c/d;p?q#f", "f", NSURL_FRAGMENT, true }, { "file:", "file", NSURL_SCHEME, true }, @@ -667,6 +671,11 @@ static const struct test_compare component_tests[] = { { "file:", NULL, NSURL_QUERY, false }, { "file:", NULL, NSURL_FRAGMENT, false }, + { "http://u:p@a:66/b/c/d;p?q=v#f", "q=v", NSURL_QUERY, true }, + { "http://u:p@a:66/b/c/d;p?q=v", "q=v", NSURL_QUERY, true }, + { "http://u:p@a:66/b/c/d;p?q=v&q1=v1#f", "q=v&q1=v1", NSURL_QUERY, true }, + { "http://u:p@a:66/b/c/d;p?q=v&q1=v1", "q=v&q1=v1", NSURL_QUERY, true }, + }; @@ -1167,12 +1176,11 @@ START_TEST(nsurl_api_assert_replace_query3_test) nsurl *url; nsurl *res; nserror err; - const char *rel = "moo"; err = nsurl_create(base_str, &url); ck_assert(err == NSERROR_OK); - err = nsurl_replace_query(url, rel, &res); + err = nsurl_replace_query(url, NULL, &res); ck_assert(err != NSERROR_OK); nsurl_unref(url); diff --git a/utils/nsurl.h b/utils/nsurl.h index bc6e910a6..c6590bdbb 100644 --- a/utils/nsurl.h +++ b/utils/nsurl.h @@ -313,6 +313,9 @@ nserror nsurl_refragment(const nsurl *url, lwc_string *frag, nsurl **new_url); * the created object. * * Any query component in url is replaced with query in new_url. + * + * Passing the empty string as a replacement will result in the query + * component being removed. */ nserror nsurl_replace_query(const nsurl *url, const char *query, nsurl **new_url); diff --git a/utils/nsurl/nsurl.c b/utils/nsurl/nsurl.c index 4dbbe96e3..38c0e53e8 100644 --- a/utils/nsurl/nsurl.c +++ b/utils/nsurl/nsurl.c @@ -54,7 +54,7 @@ * Does nothing if the components are the same, so ensure match is * preset to true. */ -#define nsurl__component_compare(c1, c2, match) \ +#define nsurl__component_compare(c1, c2, match) \ if (c1 && c2 && lwc_error_ok == \ lwc_string_isequal(c1, c2, match)) { \ /* do nothing */ \ @@ -364,7 +364,7 @@ nserror nsurl_get_utf8(const nsurl *url, char **url_s, size_t *url_l) } *url_l = scheme_len + idna_host_len + path_len + 1; /* +1 for \0 */ - *url_s = malloc(*url_l); + *url_s = malloc(*url_l); if (*url_s == NULL) { err = NSERROR_NOMEM; @@ -574,57 +574,67 @@ nserror nsurl_refragment(const nsurl *url, lwc_string *frag, nsurl **new_url) nserror nsurl_replace_query(const nsurl *url, const char *query, nsurl **new_url) { - int query_len; /* Length of new query string, including '?' */ - int frag_len = 0; /* Length of fragment, including '#' */ - int base_len; /* Length of URL up to start of query */ - char *pos; - size_t len; - lwc_string *lwc_query; + int query_len; /* Length of new query string excluding '?' */ + int frag_len = 0; /* Length of fragment, excluding '#' */ + int base_len; /* Length of URL up to start of query */ + char *pos; /* current position in output string */ + size_t length; /* new url string length */ + lwc_string *lwc_query = NULL; assert(url != NULL); assert(query != NULL); - assert(query[0] == '?'); - /* Get the length of the new query */ - query_len = strlen(query); + length = query_len = strlen(query); + if (query_len > 0) { + length++; /* allow for '?' */ + + /* intern string */ + if (lwc_intern_string(query, + query_len, + &lwc_query) != lwc_error_ok) { + return NSERROR_NOMEM; + } + } /* Find the change in length from url to new_url */ base_len = url->length; if (url->components.query != NULL) { - base_len -= lwc_string_length(url->components.query); + base_len -= (1 + lwc_string_length(url->components.query)); } if (url->components.fragment != NULL) { - frag_len = 1 + lwc_string_length(url->components.fragment); - base_len -= frag_len; + frag_len = lwc_string_length(url->components.fragment); + base_len -= (1 + frag_len); + length += frag_len + 1; /* allow for '#' */ } - /* Set new_url's length */ - len = base_len + query_len + frag_len; + /* compute new url string length */ + length += base_len; /* Create NetSurf URL object */ - *new_url = malloc(sizeof(nsurl) + len + 1); /* Add 1 for \0 */ + *new_url = malloc(sizeof(nsurl) + length + 1); /* Add 1 for \0 */ if (*new_url == NULL) { + if (query_len > 0) { + lwc_string_unref(lwc_query); + } return NSERROR_NOMEM; } - if (lwc_intern_string(query, query_len, &lwc_query) != lwc_error_ok) { - free(*new_url); - return NSERROR_NOMEM; - } - - (*new_url)->length = len; + (*new_url)->length = length; /* Set string */ pos = (*new_url)->string; memcpy(pos, url->string, base_len); pos += base_len; - memcpy(pos, query, query_len); - pos += query_len; + if (query_len > 0) { + *pos = '?'; + memcpy(++pos, query, query_len); + pos += query_len; + } if (url->components.fragment != NULL) { const char *frag = lwc_string_data(url->components.fragment); *pos = '#'; - memcpy(++pos, frag, frag_len - 1); - pos += frag_len - 1; + memcpy(++pos, frag, frag_len); + pos += frag_len; } *pos = '\0'; @@ -945,4 +955,3 @@ nserror nsurl_parent(const nsurl *url, nsurl **new_url) return NSERROR_OK; } - diff --git a/utils/nsurl/parse.c b/utils/nsurl/parse.c index 3e3c52165..3b8816dd8 100644 --- a/utils/nsurl/parse.c +++ b/utils/nsurl/parse.c @@ -344,7 +344,7 @@ static void nsurl__get_string_markers(const char * const url_s, * and in the case of mailto: when we assume there is an authority. */ if ((*pos == '/' && *(pos + 1) == '/') || - (is_http && ((joining && *pos == '/') || + (is_http && ((joining && *pos == '/') || (joining == false && marker.scheme_end != marker.start))) || marker.scheme_type == NSURL_SCHEME_MAILTO) { @@ -577,7 +577,7 @@ static size_t nsurl__remove_dot_segments(char *path, char *output) /* Copy up to but not including next '/' */ while ((*path_pos != '/') && (*path_pos != '\0')) - *output_pos++ = *path_pos++; + *output_pos++ = *path_pos++; } return output_pos - output; @@ -671,7 +671,9 @@ static nserror nsurl__create_from_section(const char * const url_s, break; case URL_QUERY: - start = pegs->query; + start = (*(url_s + pegs->query) != '?') ? + pegs->query : + pegs->query + 1; end = pegs->fragment; break; @@ -1085,6 +1087,15 @@ static void nsurl__get_string_data(const struct nsurl_components *url, *url_l += SLEN("@"); } + /* spanned query question mark */ + if ((flags & ~(NSURL_F_QUERY | NSURL_F_FRAGMENT)) && + (flags & NSURL_F_QUERY)) { + flags |= NSURL_F_QUERY_PUNCTUATION; + + *url_l += SLEN("?"); + } + + /* spanned fragment hash mark */ if ((flags & ~NSURL_F_FRAGMENT) && (flags & NSURL_F_FRAGMENT)) { flags |= NSURL_F_FRAGMENT_PUNCTUATION; @@ -1158,6 +1169,8 @@ static void nsurl__get_string(const struct nsurl_components *url, char *url_s, } if (flags & NSURL_F_QUERY) { + if (flags & NSURL_F_QUERY_PUNCTUATION) + *(pos++) = '?'; memcpy(pos, lwc_string_data(url->query), l->query); pos += l->query; } @@ -1557,4 +1570,3 @@ nserror nsurl_join(const nsurl *base, const char *rel, nsurl **joined) return NSERROR_OK; } - diff --git a/utils/nsurl/private.h b/utils/nsurl/private.h index 4366ff68c..06f143f4d 100644 --- a/utils/nsurl/private.h +++ b/utils/nsurl/private.h @@ -105,9 +105,10 @@ enum nsurl_string_flags { NSURL_F_HOST | NSURL_F_PORT), NSURL_F_PATH = (1 << 8), - NSURL_F_QUERY = (1 << 9), - NSURL_F_FRAGMENT_PUNCTUATION = (1 << 10), - NSURL_F_FRAGMENT = (1 << 11) + NSURL_F_QUERY_PUNCTUATION = (1 << 9), + NSURL_F_QUERY = (1 << 10), + NSURL_F_FRAGMENT_PUNCTUATION = (1 << 11), + NSURL_F_FRAGMENT = (1 << 12) }; /** |