summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--!NetSurf/Resources/CSS,f794
-rw-r--r--Makefile14
-rw-r--r--frontends/amiga/os3support.h1
-rw-r--r--frontends/riscos/gui.c6
-rw-r--r--render/box_textarea.c13
-rw-r--r--test/Makefile13
-rw-r--r--utils/Makefile1
-rw-r--r--utils/nsurl/Makefile7
-rw-r--r--utils/nsurl/nsurl.c850
-rw-r--r--utils/nsurl/parse.c (renamed from utils/nsurl.c)1053
-rw-r--r--utils/nsurl/private.h215
11 files changed, 1165 insertions, 1012 deletions
diff --git a/!NetSurf/Resources/CSS,f79 b/!NetSurf/Resources/CSS,f79
index 44268d6a7..2aee83b7c 100644
--- a/!NetSurf/Resources/CSS,f79
+++ b/!NetSurf/Resources/CSS,f79
@@ -115,7 +115,7 @@ input, button { background-color: #fff; color: #000; text-align: left;
font-family: sans-serif; width: auto; height: auto; overflow: hidden;
border: 1px solid #444; padding: 2px 3px; line-height: 1.33;
margin: 1px; }
-input[readonly] { background-color: #ddd; color: #333; }
+input[disabled] { background-color: #ddd; color: #333; }
input[type=button], input[type=reset], input[type=submit], button {
background-color: #d9d9d9; color: #000; text-align: center;
border: 2px outset #d9d9d9; padding: 1px 0.5em; }
@@ -137,7 +137,7 @@ select:after { content: "\25bc"; border-left: 2px ridge #d9d9d9; }
textarea { background-color: #fff; color: #000; text-align: left;
font-family: monospace; width: auto; height: auto; overflow: scroll;
margin: 1px; border: 1px solid #333; padding: 1px 3px; }
-textarea[readonly] { background-color: #ddd; color: #333; }
+textarea[disabled] { background-color: #ddd; color: #333; }
fieldset { display: block; border: thin solid #888; margin: 1.12em 0; }
diff --git a/Makefile b/Makefile
index 5f2697fdc..97a81280f 100644
--- a/Makefile
+++ b/Makefile
@@ -621,12 +621,22 @@ include utils/Makefile
# http utility sources
include utils/http/Makefile
+# nsurl utility sources
+include utils/nsurl/Makefile
+
# Desktop sources
include desktop/Makefile
# S_COMMON are sources common to all builds
-S_COMMON := $(S_CONTENT) $(S_FETCHERS) $(S_RENDER) $(S_UTILS) $(S_HTTP) \
- $(S_DESKTOP) $(S_JAVASCRIPT_BINDING)
+S_COMMON := \
+ $(S_CONTENT) \
+ $(S_FETCHERS) \
+ $(S_RENDER) \
+ $(S_UTILS) \
+ $(S_HTTP) \
+ $(S_NSURL) \
+ $(S_DESKTOP) \
+ $(S_JAVASCRIPT_BINDING)
# ----------------------------------------------------------------------------
diff --git a/frontends/amiga/os3support.h b/frontends/amiga/os3support.h
index 856439bd8..aa3027d36 100644
--- a/frontends/amiga/os3support.h
+++ b/frontends/amiga/os3support.h
@@ -116,6 +116,7 @@
#define BGBACKFILL JAM1
#define OFF_OPEN 0
#define AFF_OTAG 0
+#define ML_SEPARATOR NM_BARLABEL
/* Renamed structures */
#define AnchorPathOld AnchorPath
diff --git a/frontends/riscos/gui.c b/frontends/riscos/gui.c
index 27b81d92e..540a8be54 100644
--- a/frontends/riscos/gui.c
+++ b/frontends/riscos/gui.c
@@ -1179,6 +1179,9 @@ static nserror gui_init(int argc, char** argv)
/* Initialise save complete functionality */
save_complete_init();
+ /* Initialise the font subsystem */
+ nsfont_init();
+
/* Load in visited URLs, Cookies, and hostlist */
urldb_load(nsoption_charp(url_path));
urldb_load_cookies(nsoption_charp(cookie_file));
@@ -1212,9 +1215,6 @@ static nserror gui_init(int argc, char** argv)
ro_message_register_route(message_WINDOW_INFO,
ro_msg_window_info);
- /* Initialise the font subsystem */
- nsfont_init();
-
/* Initialise global information */
ro_gui_get_screen_properties();
ro_gui_wimp_get_desktop_font();
diff --git a/render/box_textarea.c b/render/box_textarea.c
index 44f5c0b16..1586d71c4 100644
--- a/render/box_textarea.c
+++ b/render/box_textarea.c
@@ -239,6 +239,7 @@ bool box_textarea_create_textarea(html_content *html,
textarea_flags ta_flags;
plot_font_style_t fstyle;
bool read_only = false;
+ bool disabled = false;
struct form_control *gadget = box->gadget;
const char *text;
@@ -257,6 +258,11 @@ bool box_textarea_create_textarea(html_content *html,
if (err != DOM_NO_ERR)
return false;
+ err = dom_html_text_area_element_get_disabled(
+ textarea, &disabled);
+ if (err != DOM_NO_ERR)
+ return false;
+
/* Get the textarea's initial content */
err = dom_html_text_area_element_get_value(textarea, &dom_text);
if (err != DOM_NO_ERR)
@@ -270,6 +276,11 @@ bool box_textarea_create_textarea(html_content *html,
if (err != DOM_NO_ERR)
return false;
+ err = dom_html_input_element_get_disabled(
+ input, &disabled);
+ if (err != DOM_NO_ERR)
+ return false;
+
if (gadget->type == GADGET_PASSWORD)
ta_flags = TEXTAREA_PASSWORD;
else
@@ -289,7 +300,7 @@ bool box_textarea_create_textarea(html_content *html,
text = "";
}
- if (read_only)
+ if (read_only || disabled)
ta_flags |= TEXTAREA_READONLY;
gadget->data.text.data.gadget = gadget;
diff --git a/test/Makefile b/test/Makefile
index d5e9d0033..1f884dcc9 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -13,12 +13,15 @@ TESTS := \
time #llcache
# nsurl sources
-nsurl_SRCS := utils/corestrings.c utils/nsurl.c utils/idna.c utils/punycode.c \
+nsurl_SRCS := utils/corestrings.c utils/nsurl/nsurl.c \
+ utils/nsurl/parse.c \
+ utils/idna.c utils/punycode.c \
test/log.c test/nsurl.c
# url database test sources
urldbtest_SRCS := content/urldb.c \
- utils/idna.c utils/bloom.c utils/nsoption.c utils/nsurl.c \
+ utils/idna.c utils/bloom.c utils/nsoption.c \
+ utils/nsurl/nsurl.c utils/nsurl/parse.c \
utils/corestrings.c utils/punycode.c \
utils/hashtable.c utils/messages.c utils/time.c utils/utils.c \
test/log.c test/urldbtest.c
@@ -30,7 +33,8 @@ llcache_SRCS := content/fetch.c content/fetchers/curl.c \
content/urldb.c \
image/image_cache.c \
utils/base64.c utils/corestrings.c utils/hashtable.c \
- utils/nsurl.c utils/messages.c utils/url.c utils/useragent.c \
+ utils/nsurl/nsurl.c utils/nsurl/parse.c \
+ utils/messages.c utils/url.c utils/useragent.c \
utils/utils.c \
test/log.c test/llcache.c
@@ -51,7 +55,8 @@ urlescape_SRCS := utils/url.c test/log.c test/urlescape.c
# utility test sources
utils_SRCS := utils/utils.c utils/messages.c utils/hashtable.c \
- utils/corestrings.c utils/nsurl.c utils/idna.c utils/punycode.c \
+ utils/corestrings.c utils/nsurl/nsurl.c \
+ utils/nsurl/parse.c utils/idna.c utils/punycode.c \
test/log.c test/utils.c
# time test sources
diff --git a/utils/Makefile b/utils/Makefile
index 62b7e05e7..2f59501c2 100644
--- a/utils/Makefile
+++ b/utils/Makefile
@@ -12,7 +12,6 @@ S_UTILS := \
log.c \
messages.c \
nsoption.c \
- nsurl.c \
punycode.c \
talloc.c \
time.c \
diff --git a/utils/nsurl/Makefile b/utils/nsurl/Makefile
new file mode 100644
index 000000000..71304b292
--- /dev/null
+++ b/utils/nsurl/Makefile
@@ -0,0 +1,7 @@
+# nsurl utils sources
+
+S_NSURL := \
+ nsurl.c \
+ parse.c
+
+S_NSURL := $(addprefix utils/nsurl/,$(S_NSURL)) \ No newline at end of file
diff --git a/utils/nsurl/nsurl.c b/utils/nsurl/nsurl.c
new file mode 100644
index 000000000..7166a2707
--- /dev/null
+++ b/utils/nsurl/nsurl.c
@@ -0,0 +1,850 @@
+/*
+ * Copyright 2011 Michael Drake <tlsa@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * NetSurf URL handling implementation.
+ *
+ * This is the common implementation of all URL handling within the
+ * browser. This implementation is based upon RFC3986 although this has
+ * been superceeded by https://url.spec.whatwg.org/ which is based on
+ * actual contemporary implementations.
+ *
+ * Care must be taken with character encodings within this module as
+ * the specifications work with specific ascii ranges and must not be
+ * affected by locale. Hence the c library character type functions
+ * are not used.
+ */
+
+#include <assert.h>
+#include <libwapcaplet/libwapcaplet.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+
+#include "utils/ascii.h"
+#include "utils/corestrings.h"
+#include "utils/errors.h"
+#include "utils/idna.h"
+#include "utils/log.h"
+#include "utils/nsurl/private.h"
+#include "utils/nsurl.h"
+#include "utils/utils.h"
+
+
+/**
+ * Compare two component values.
+ *
+ * Sets match to false if the components are not the same.
+ * Does nothing if the components are the same, so ensure match is
+ * preset to true.
+ */
+#define nsurl__component_compare(c1, c2, match) \
+ if (c1 && c2 && lwc_error_ok == \
+ lwc_string_isequal(c1, c2, match)) { \
+ /* do nothing */ \
+ } else if (c1 || c2) { \
+ *match = false; \
+ }
+
+
+
+/******************************************************************************
+ * NetSurf URL Public API *
+ ******************************************************************************/
+
+/* exported interface, documented in nsurl.h */
+nsurl *nsurl_ref(nsurl *url)
+{
+ assert(url != NULL);
+
+ url->count++;
+
+ return url;
+}
+
+
+/* exported interface, documented in nsurl.h */
+void nsurl_unref(nsurl *url)
+{
+ assert(url != NULL);
+ assert(url->count > 0);
+
+ if (--url->count > 0)
+ return;
+
+#ifdef NSURL_DEBUG
+ nsurl__dump(url);
+#endif
+
+ /* Release lwc strings */
+ nsurl__components_destroy(&url->components);
+
+ /* Free the NetSurf URL */
+ free(url);
+}
+
+
+/* exported interface, documented in nsurl.h */
+bool nsurl_compare(const nsurl *url1, const nsurl *url2, nsurl_component parts)
+{
+ bool match = true;
+
+ assert(url1 != NULL);
+ assert(url2 != NULL);
+
+ /* Compare URL components */
+
+ /* Path, host and query first, since they're most likely to differ */
+
+ if (parts & NSURL_PATH) {
+ nsurl__component_compare(url1->components.path,
+ url2->components.path, &match);
+
+ if (match == false)
+ return false;
+ }
+
+ if (parts & NSURL_HOST) {
+ nsurl__component_compare(url1->components.host,
+ url2->components.host, &match);
+
+ if (match == false)
+ return false;
+ }
+
+ if (parts & NSURL_QUERY) {
+ nsurl__component_compare(url1->components.query,
+ url2->components.query, &match);
+
+ if (match == false)
+ return false;
+ }
+
+ if (parts & NSURL_SCHEME) {
+ nsurl__component_compare(url1->components.scheme,
+ url2->components.scheme, &match);
+
+ if (match == false)
+ return false;
+ }
+
+ if (parts & NSURL_USERNAME) {
+ nsurl__component_compare(url1->components.username,
+ url2->components.username, &match);
+
+ if (match == false)
+ return false;
+ }
+
+ if (parts & NSURL_PASSWORD) {
+ nsurl__component_compare(url1->components.password,
+ url2->components.password, &match);
+
+ if (match == false)
+ return false;
+ }
+
+ if (parts & NSURL_PORT) {
+ nsurl__component_compare(url1->components.port,
+ url2->components.port, &match);
+
+ if (match == false)
+ return false;
+ }
+
+ if (parts & NSURL_FRAGMENT) {
+ nsurl__component_compare(url1->components.fragment,
+ url2->components.fragment, &match);
+
+ if (match == false)
+ return false;
+ }
+
+ return true;
+}
+
+
+/* exported interface, documented in nsurl.h */
+nserror nsurl_get(const nsurl *url, nsurl_component parts,
+ char **url_s, size_t *url_l)
+{
+ assert(url != NULL);
+
+ return nsurl__components_to_string(&(url->components), parts, 0,
+ url_s, url_l);
+}
+
+
+/* exported interface, documented in nsurl.h */
+lwc_string *nsurl_get_component(const nsurl *url, nsurl_component part)
+{
+ assert(url != NULL);
+
+ switch (part) {
+ case NSURL_SCHEME:
+ return (url->components.scheme != NULL) ?
+ lwc_string_ref(url->components.scheme) : NULL;
+
+ case NSURL_USERNAME:
+ return (url->components.username != NULL) ?
+ lwc_string_ref(url->components.username) : NULL;
+
+ case NSURL_PASSWORD:
+ return (url->components.password != NULL) ?
+ lwc_string_ref(url->components.password) : NULL;
+
+ case NSURL_HOST:
+ return (url->components.host != NULL) ?
+ lwc_string_ref(url->components.host) : NULL;
+
+ case NSURL_PORT:
+ return (url->components.port != NULL) ?
+ lwc_string_ref(url->components.port) : NULL;
+
+ case NSURL_PATH:
+ return (url->components.path != NULL) ?
+ lwc_string_ref(url->components.path) : NULL;
+
+ case NSURL_QUERY:
+ return (url->components.query != NULL) ?
+ lwc_string_ref(url->components.query) : NULL;
+
+ case NSURL_FRAGMENT:
+ return (url->components.fragment != NULL) ?
+ lwc_string_ref(url->components.fragment) : NULL;
+
+ default:
+ LOG("Unsupported value passed to part param.");
+ assert(0);
+ }
+
+ return NULL;
+}
+
+
+/* exported interface, documented in nsurl.h */
+bool nsurl_has_component(const nsurl *url, nsurl_component part)
+{
+ assert(url != NULL);
+
+ switch (part) {
+ case NSURL_SCHEME:
+ if (url->components.scheme != NULL)
+ return true;
+ else
+ return false;
+
+ case NSURL_CREDENTIALS:
+ /* Only username required for credentials section */
+ /* Fall through */
+ case NSURL_USERNAME:
+ if (url->components.username != NULL)
+ return true;
+ else
+ return false;
+
+ case NSURL_PASSWORD:
+ if (url->components.password != NULL)
+ return true;
+ else
+ return false;
+
+ case NSURL_HOST:
+ if (url->components.host != NULL)
+ return true;
+ else
+ return false;
+
+ case NSURL_PORT:
+ if (url->components.port != NULL)
+ return true;
+ else
+ return false;
+
+ case NSURL_PATH:
+ if (url->components.path != NULL)
+ return true;
+ else
+ return false;
+
+ case NSURL_QUERY:
+ if (url->components.query != NULL)
+ return true;
+ else
+ return false;
+
+ case NSURL_FRAGMENT:
+ if (url->components.fragment != NULL)
+ return true;
+ else
+ return false;
+
+ default:
+ LOG("Unsupported value passed to part param.");
+ assert(0);
+ }
+
+ return false;
+}
+
+
+/* exported interface, documented in nsurl.h */
+const char *nsurl_access(const nsurl *url)
+{
+ assert(url != NULL);
+
+ return url->string;
+}
+
+
+/* exported interface, documented in nsurl.h */
+nserror nsurl_get_utf8(const nsurl *url, char **url_s, size_t *url_l)
+{
+ nserror err;
+ lwc_string *host;
+ char *idna_host = NULL;
+ size_t idna_host_len;
+ char *scheme = NULL;
+ size_t scheme_len;
+ char *path = NULL;
+ size_t path_len;
+
+ assert(url != NULL);
+
+ if (url->components.host == NULL) {
+ return nsurl_get(url, NSURL_WITH_FRAGMENT, url_s, url_l);
+ }
+
+ host = url->components.host;
+ err = idna_decode(lwc_string_data(host), lwc_string_length(host),
+ &idna_host, &idna_host_len);
+ if (err != NSERROR_OK) {
+ goto cleanup;
+ }
+
+ err = nsurl_get(url,
+ NSURL_SCHEME | NSURL_CREDENTIALS,
+ &scheme, &scheme_len);
+ if (err != NSERROR_OK) {
+ goto cleanup;
+ }
+
+ err = nsurl_get(url,
+ NSURL_PORT | NSURL_PATH | NSURL_QUERY | NSURL_FRAGMENT,
+ &path, &path_len);
+ if (err != NSERROR_OK) {
+ goto cleanup;
+ }
+
+ *url_l = scheme_len + idna_host_len + path_len + 1; /* +1 for \0 */
+ *url_s = malloc(*url_l);
+
+ if (*url_s == NULL) {
+ err = NSERROR_NOMEM;
+ goto cleanup;
+ }
+
+ snprintf(*url_s, *url_l, "%s%s%s", scheme, idna_host, path);
+
+ err = NSERROR_OK;
+
+cleanup:
+ free(idna_host);
+ free(scheme);
+ free(path);
+
+ return err;
+}
+
+
+/* exported interface, documented in nsurl.h */
+const char *nsurl_access_leaf(const nsurl *url)
+{
+ size_t path_len;
+ const char *path;
+ const char *leaf;
+
+ assert(url != NULL);
+
+ if (url->components.path == NULL)
+ return "";
+
+ path = lwc_string_data(url->components.path);
+ path_len = lwc_string_length(url->components.path);
+
+ if (path_len == 0)
+ return "";
+
+ if (path_len == 1 && *path == '/')
+ return "/";
+
+ leaf = path + path_len;
+
+ do {
+ leaf--;
+ } while ((leaf != path) && (*leaf != '/'));
+
+ if (*leaf == '/')
+ leaf++;
+
+ return leaf;
+}
+
+
+/* exported interface, documented in nsurl.h */
+size_t nsurl_length(const nsurl *url)
+{
+ assert(url != NULL);
+
+ return url->length;
+}
+
+
+/* exported interface, documented in nsurl.h */
+uint32_t nsurl_hash(const nsurl *url)
+{
+ assert(url != NULL);
+
+ return url->hash;
+}
+
+
+/* exported interface, documented in nsurl.h */
+nserror nsurl_defragment(const nsurl *url, nsurl **no_frag)
+{
+ size_t length;
+ char *pos;
+
+ assert(url != NULL);
+
+ /* check for source url having no fragment already */
+ if (url->components.fragment == NULL) {
+ *no_frag = (nsurl *)url;
+
+ (*no_frag)->count++;
+
+ return NSERROR_OK;
+ }
+
+ /* Find the change in length from url to new_url */
+ length = url->length;
+ if (url->components.fragment != NULL) {
+ length -= 1 + lwc_string_length(url->components.fragment);
+ }
+
+ /* Create NetSurf URL object */
+ *no_frag = malloc(sizeof(nsurl) + length + 1); /* Add 1 for \0 */
+ if (*no_frag == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ /* Copy components */
+ (*no_frag)->components.scheme =
+ nsurl__component_copy(url->components.scheme);
+ (*no_frag)->components.username =
+ nsurl__component_copy(url->components.username);
+ (*no_frag)->components.password =
+ nsurl__component_copy(url->components.password);
+ (*no_frag)->components.host =
+ nsurl__component_copy(url->components.host);
+ (*no_frag)->components.port =
+ nsurl__component_copy(url->components.port);
+ (*no_frag)->components.path =
+ nsurl__component_copy(url->components.path);
+ (*no_frag)->components.query =
+ nsurl__component_copy(url->components.query);
+ (*no_frag)->components.fragment = NULL;
+
+ (*no_frag)->components.scheme_type = url->components.scheme_type;
+
+ (*no_frag)->length = length;
+
+ /* Fill out the url string */
+ pos = (*no_frag)->string;
+ memcpy(pos, url->string, length);
+ pos += length;
+ *pos = '\0';
+
+ /* Get the nsurl's hash */
+ nsurl__calc_hash(*no_frag);
+
+ /* Give the URL a reference */
+ (*no_frag)->count = 1;
+
+ return NSERROR_OK;
+}
+
+
+/* exported interface, documented in nsurl.h */
+nserror nsurl_refragment(const nsurl *url, lwc_string *frag, nsurl **new_url)
+{
+ int frag_len;
+ int base_len;
+ char *pos;
+ size_t len;
+
+ assert(url != NULL);
+ assert(frag != NULL);
+
+ /* Find the change in length from url to new_url */
+ base_len = url->length;
+ if (url->components.fragment != NULL) {
+ base_len -= 1 + lwc_string_length(url->components.fragment);
+ }
+ frag_len = lwc_string_length(frag);
+
+ /* Set new_url's length */
+ len = base_len + 1 /* # */ + frag_len;
+
+ /* Create NetSurf URL object */
+ *new_url = malloc(sizeof(nsurl) + len + 1); /* Add 1 for \0 */
+ if (*new_url == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ (*new_url)->length = len;
+
+ /* Set string */
+ pos = (*new_url)->string;
+ memcpy(pos, url->string, base_len);
+ pos += base_len;
+ *pos = '#';
+ memcpy(++pos, lwc_string_data(frag), frag_len);
+ pos += frag_len;
+ *pos = '\0';
+
+ /* Copy components */
+ (*new_url)->components.scheme =
+ nsurl__component_copy(url->components.scheme);
+ (*new_url)->components.username =
+ nsurl__component_copy(url->components.username);
+ (*new_url)->components.password =
+ nsurl__component_copy(url->components.password);
+ (*new_url)->components.host =
+ nsurl__component_copy(url->components.host);
+ (*new_url)->components.port =
+ nsurl__component_copy(url->components.port);
+ (*new_url)->components.path =
+ nsurl__component_copy(url->components.path);
+ (*new_url)->components.query =
+ nsurl__component_copy(url->components.query);
+ (*new_url)->components.fragment =
+ lwc_string_ref(frag);
+
+ (*new_url)->components.scheme_type = url->components.scheme_type;
+
+ /* Get the nsurl's hash */
+ nsurl__calc_hash(*new_url);
+
+ /* Give the URL a reference */
+ (*new_url)->count = 1;
+
+ return NSERROR_OK;
+}
+
+
+/* exported interface, documented in nsurl.h */
+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;
+
+ assert(url != NULL);
+ assert(query != NULL);
+ assert(query[0] == '?');
+
+ /* Get the length of the new query */
+ query_len = strlen(query);
+
+ /* 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);
+ }
+ if (url->components.fragment != NULL) {
+ frag_len = 1 + lwc_string_length(url->components.fragment);
+ base_len -= frag_len;
+ }
+
+ /* Set new_url's length */
+ len = base_len + query_len + frag_len;
+
+ /* Create NetSurf URL object */
+ *new_url = malloc(sizeof(nsurl) + len + 1); /* Add 1 for \0 */
+ if (*new_url == NULL) {
+ 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;
+
+ /* Set string */
+ pos = (*new_url)->string;
+ memcpy(pos, url->string, base_len);
+ pos += base_len;
+ 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;
+ }
+ *pos = '\0';
+
+ /* Copy components */
+ (*new_url)->components.scheme =
+ nsurl__component_copy(url->components.scheme);
+ (*new_url)->components.username =
+ nsurl__component_copy(url->components.username);
+ (*new_url)->components.password =
+ nsurl__component_copy(url->components.password);
+ (*new_url)->components.host =
+ nsurl__component_copy(url->components.host);
+ (*new_url)->components.port =
+ nsurl__component_copy(url->components.port);
+ (*new_url)->components.path =
+ nsurl__component_copy(url->components.path);
+ (*new_url)->components.query = lwc_query;
+ (*new_url)->components.fragment =
+ nsurl__component_copy(url->components.fragment);
+
+ (*new_url)->components.scheme_type = url->components.scheme_type;
+
+ /* Get the nsurl's hash */
+ nsurl__calc_hash(*new_url);
+
+ /* Give the URL a reference */
+ (*new_url)->count = 1;
+
+ return NSERROR_OK;
+}
+
+
+/* exported interface documented in utils/nsurl.h */
+nserror nsurl_nice(const nsurl *url, char **result, bool remove_extensions)
+{
+ const char *data;
+ size_t len;
+ size_t pos;
+ bool match;
+ char *name;
+
+ assert(url != NULL);
+
+ *result = 0;
+
+ /* extract the last component of the path, if possible */
+ if ((url->components.path != NULL) &&
+ (lwc_string_length(url->components.path) != 0) &&
+ (lwc_string_isequal(url->components.path,
+ corestring_lwc_slash_, &match) == lwc_error_ok) &&
+ (match == false)) {
+ bool first = true;
+ bool keep_looking;
+
+ /* Get hold of the string data we're examining */
+ data = lwc_string_data(url->components.path);
+ len = lwc_string_length(url->components.path);
+ pos = len;
+
+ do {
+ keep_looking = false;
+ pos--;
+
+ /* Find last '/' with stuff after it */
+ while (pos != 0) {
+ if (data[pos] == '/' && pos < len - 1) {
+ break;
+ }
+ pos--;
+ }
+
+ if (pos == 0) {
+ break;
+ }
+
+ if (first) {
+ if (strncasecmp("/default.", data + pos,
+ SLEN("/default.")) == 0) {
+ keep_looking = true;
+
+ } else if (strncasecmp("/index.",
+ data + pos,
+ 6) == 0) {
+ keep_looking = true;
+
+ }
+ first = false;
+ }
+
+ } while (keep_looking);
+
+ if (data[pos] == '/')
+ pos++;
+
+ if (strncasecmp("default.", data + pos, 8) != 0 &&
+ strncasecmp("index.", data + pos, 6) != 0) {
+ size_t end = pos;
+ while (data[end] != '\0' && data[end] != '/') {
+ end++;
+ }
+ if (end - pos != 0) {
+ name = malloc(end - pos + 1);
+ if (name == NULL) {
+ return NSERROR_NOMEM;
+ }
+ memcpy(name, data + pos, end - pos);
+ name[end - pos] = '\0';
+ if (remove_extensions) {
+ /* strip any extenstion */
+ char *dot = strchr(name, '.');
+ if (dot && dot != name) {
+ *dot = '\0';
+ }
+ }
+ *result = name;
+ return NSERROR_OK;
+ }
+ }
+ }
+
+ if (url->components.host != NULL) {
+ name = strdup(lwc_string_data(url->components.host));
+
+ for (pos = 0; name[pos] != '\0'; pos++) {
+ if (name[pos] == '.') {
+ name[pos] = '_';
+ }
+ }
+
+ *result = name;
+ return NSERROR_OK;
+ }
+
+ return NSERROR_NOT_FOUND;
+}
+
+
+/* exported interface, documented in nsurl.h */
+nserror nsurl_parent(const nsurl *url, nsurl **new_url)
+{
+ lwc_string *lwc_path;
+ size_t old_path_len, new_path_len;
+ size_t len;
+ const char* path = NULL;
+ char *pos;
+
+ assert(url != NULL);
+
+ old_path_len = (url->components.path == NULL) ? 0 :
+ lwc_string_length(url->components.path);
+
+ /* Find new path length */
+ if (old_path_len == 0) {
+ new_path_len = old_path_len;
+ } else {
+ path = lwc_string_data(url->components.path);
+
+ new_path_len = old_path_len;
+ if (old_path_len > 1) {
+ /* Skip over any trailing / */
+ if (path[new_path_len - 1] == '/')
+ new_path_len--;
+
+ /* Work back to next / */
+ while (new_path_len > 0 &&
+ path[new_path_len - 1] != '/')
+ new_path_len--;
+ }
+ }
+
+ /* Find the length of new_url */
+ len = url->length;
+ if (url->components.query != NULL) {
+ len -= lwc_string_length(url->components.query);
+ }
+ if (url->components.fragment != NULL) {
+ len -= 1; /* # */
+ len -= lwc_string_length(url->components.fragment);
+ }
+ len -= old_path_len - new_path_len;
+
+ /* Create NetSurf URL object */
+ *new_url = malloc(sizeof(nsurl) + len + 1); /* Add 1 for \0 */
+ if (*new_url == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ /* Make new path */
+ if (old_path_len == 0) {
+ lwc_path = NULL;
+ } else if (old_path_len == new_path_len) {
+ lwc_path = lwc_string_ref(url->components.path);
+ } else {
+ if (lwc_intern_string(path, old_path_len - new_path_len,
+ &lwc_path) != lwc_error_ok) {
+ free(*new_url);
+ return NSERROR_NOMEM;
+ }
+ }
+
+ (*new_url)->length = len;
+
+ /* Set string */
+ pos = (*new_url)->string;
+ memcpy(pos, url->string, len);
+ pos += len;
+ *pos = '\0';
+
+ /* Copy components */
+ (*new_url)->components.scheme =
+ nsurl__component_copy(url->components.scheme);
+ (*new_url)->components.username =
+ nsurl__component_copy(url->components.username);
+ (*new_url)->components.password =
+ nsurl__component_copy(url->components.password);
+ (*new_url)->components.host =
+ nsurl__component_copy(url->components.host);
+ (*new_url)->components.port =
+ nsurl__component_copy(url->components.port);
+ (*new_url)->components.path = lwc_path;
+ (*new_url)->components.query = NULL;
+ (*new_url)->components.fragment = NULL;
+
+ (*new_url)->components.scheme_type = url->components.scheme_type;
+
+ /* Get the nsurl's hash */
+ nsurl__calc_hash(*new_url);
+
+ /* Give the URL a reference */
+ (*new_url)->count = 1;
+
+ return NSERROR_OK;
+}
+
diff --git a/utils/nsurl.c b/utils/nsurl/parse.c
index c5c614c55..89a10d244 100644
--- a/utils/nsurl.c
+++ b/utils/nsurl/parse.c
@@ -43,61 +43,9 @@
#include "utils/idna.h"
#include "utils/log.h"
#include "utils/nsurl.h"
+#include "utils/nsurl/private.h"
#include "utils/utils.h"
-/* Define to enable NSURL debugging */
-#undef NSURL_DEBUG
-
-/**
- * nsurl scheme type
- */
-enum scheme_type {
- NSURL_SCHEME_OTHER,
- NSURL_SCHEME_HTTP,
- NSURL_SCHEME_HTTPS,
- NSURL_SCHEME_FTP,
- NSURL_SCHEME_MAILTO
-};
-
-/**
- * nsurl components
- *
- * [scheme]://[username]:[password]@[host]:[port][path][?query]#[fragment]
- *
- * Note:
- * "path" string includes preceding '/', if needed for the scheme
- * "query" string always includes preceding '?'
- *
- * The other spanned punctuation is to be inserted when building URLs from
- * components.
- */
-struct nsurl_components {
- lwc_string *scheme;
- lwc_string *username;
- lwc_string *password;
- lwc_string *host;
- lwc_string *port;
- lwc_string *path;
- lwc_string *query;
- lwc_string *fragment;
-
- enum scheme_type scheme_type;
-};
-
-
-/**
- * NetSurf URL object
- */
-struct nsurl {
- struct nsurl_components components;
-
- int count; /* Number of references to NetSurf URL object */
- uint32_t hash; /* Hash value for nsurl identification */
-
- size_t length; /* Length of string */
- char string[FLEX_ARRAY_LEN_DECL]; /* Full URL as a string */
-};
-
/** Marker set, indicating positions of sections within a URL string */
struct url_markers {
@@ -115,41 +63,7 @@ struct url_markers {
size_t end; /** end of URL */
- enum scheme_type scheme_type;
-};
-
-
-/** Marker set, indicating positions of sections within a URL string */
-struct nsurl_component_lengths {
- size_t scheme;
- size_t username;
- size_t password;
- size_t host;
- size_t port;
- size_t path;
- size_t query;
- size_t fragment;
-};
-
-
-/** Flags indicating which parts of a URL string are required for a nsurl */
-enum nsurl_string_flags {
- NSURL_F_SCHEME = (1 << 0),
- NSURL_F_SCHEME_PUNCTUATION = (1 << 1),
- NSURL_F_AUTHORITY_PUNCTUATION = (1 << 2),
- NSURL_F_USERNAME = (1 << 3),
- NSURL_F_PASSWORD = (1 << 4),
- NSURL_F_CREDENTIALS_PUNCTUATION = (1 << 5),
- NSURL_F_HOST = (1 << 6),
- NSURL_F_PORT = (1 << 7),
- NSURL_F_AUTHORITY = (NSURL_F_USERNAME |
- NSURL_F_PASSWORD |
- 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)
+ enum nsurl_scheme_type scheme_type;
};
@@ -164,16 +78,6 @@ enum url_sections {
};
-#define nsurl__component_copy(c) (c == NULL) ? NULL : lwc_string_ref(c)
-
-#define nsurl__component_compare(c1, c2, match) \
- if (c1 && c2 && lwc_error_ok == \
- lwc_string_isequal(c1, c2, match)) { \
- /* do nothing */ \
- } else if (c1 || c2) { \
- *match = false; \
- }
-
/**
* Return a hex digit for the given numerical value.
*
@@ -1187,14 +1091,14 @@ static void nsurl__get_string_data(const struct nsurl_components *url,
/**
- * Get nsurl string info; total length, component lengths, & components present
+ * Copy url string into provided buffer
*
* \param url NetSurf URL components
* \param url_s Updated to contain the string
* \param l Individual component lengths
* \param flags String flags
*/
-static void nsurl_get_string(const struct nsurl_components *url, char *url_s,
+static void nsurl__get_string(const struct nsurl_components *url, char *url_s,
struct nsurl_component_lengths *l,
enum nsurl_string_flags flags)
{
@@ -1264,12 +1168,49 @@ static void nsurl_get_string(const struct nsurl_components *url, char *url_s,
}
+/* exported interface, documented in nsurl.h */
+nserror nsurl__components_to_string(
+ const struct nsurl_components *components,
+ nsurl_component parts, size_t pre_padding,
+ char **url_s_out, size_t *url_l_out)
+{
+ struct nsurl_component_lengths str_len = { 0, 0, 0, 0, 0, 0, 0, 0 };
+ enum nsurl_string_flags str_flags = 0;
+ size_t url_l;
+ char *url_s;
+
+ assert(components != NULL);
+
+ /* Get the string length and find which parts of url need copied */
+ nsurl__get_string_data(components, parts, &url_l,
+ &str_len, &str_flags);
+
+ if (url_l == 0) {
+ return NSERROR_BAD_URL;
+ }
+
+ /* Allocate memory for url string */
+ url_s = malloc(pre_padding + url_l + 1); /* adding 1 for '\0' */
+ if (url_s == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ /* Copy the required parts into the url string */
+ nsurl__get_string(components, url_s + pre_padding, &str_len, str_flags);
+
+ *url_s_out = url_s;
+ *url_l_out = url_l;
+
+ return NSERROR_OK;
+}
+
+
/**
* Calculate hash value
*
* \param url NetSurf URL object to set hash value for
*/
-static void nsurl_calc_hash(nsurl *url)
+void nsurl__calc_hash(nsurl *url)
{
uint32_t hash = 0;
@@ -1298,73 +1239,6 @@ static void nsurl_calc_hash(nsurl *url)
}
-/**
- * Destroy components
- *
- * \param c url components
- */
-static void nsurl_destroy_components(struct nsurl_components *c)
-{
- if (c->scheme)
- lwc_string_unref(c->scheme);
-
- if (c->username)
- lwc_string_unref(c->username);
-
- if (c->password)
- lwc_string_unref(c->password);
-
- if (c->host)
- lwc_string_unref(c->host);
-
- if (c->port)
- lwc_string_unref(c->port);
-
- if (c->path)
- lwc_string_unref(c->path);
-
- if (c->query)
- lwc_string_unref(c->query);
-
- if (c->fragment)
- lwc_string_unref(c->fragment);
-}
-
-
-#ifdef NSURL_DEBUG
-/**
- * Dump a NetSurf URL's internal components
- *
- * \param url The NetSurf URL to dump components of
- */
-static void nsurl__dump(const nsurl *url)
-{
- if (url->components.scheme)
- LOG(" Scheme: %s", lwc_string_data(url->components.scheme));
-
- if (url->components.username)
- LOG("Username: %s", lwc_string_data(url->components.username));
-
- if (url->components.password)
- LOG("Password: %s", lwc_string_data(url->components.password));
-
- if (url->components.host)
- LOG(" Host: %s", lwc_string_data(url->components.host));
-
- if (url->components.port)
- LOG(" Port: %s", lwc_string_data(url->components.port));
-
- if (url->components.path)
- LOG(" Path: %s", lwc_string_data(url->components.path));
-
- if (url->components.query)
- LOG(" Query: %s", lwc_string_data(url->components.query));
-
- if (url->components.fragment)
- LOG("Fragment: %s", lwc_string_data(url->components.fragment));
-}
-#endif
-
/******************************************************************************
* NetSurf URL Public API *
******************************************************************************/
@@ -1376,8 +1250,6 @@ nserror nsurl_create(const char * const url_s, nsurl **url)
struct nsurl_components c;
size_t length;
char *buff;
- struct nsurl_component_lengths str_len = { 0, 0, 0, 0, 0, 0, 0, 0 };
- enum nsurl_string_flags str_flags = 0;
nserror e = NSERROR_OK;
bool match;
@@ -1409,7 +1281,7 @@ nserror nsurl_create(const char * const url_s, nsurl **url)
free(buff);
if (e != NSERROR_OK) {
- nsurl_destroy_components(&c);
+ nsurl__components_destroy(&c);
return NSERROR_NOMEM;
}
@@ -1420,30 +1292,22 @@ nserror nsurl_create(const char * const url_s, nsurl **url)
&match) == lwc_error_ok && match == true)) {
/* http, https must have host */
if (c.host == NULL) {
- nsurl_destroy_components(&c);
+ nsurl__components_destroy(&c);
return NSERROR_BAD_URL;
}
}
- /* Get the string length and find which parts of url are present */
- nsurl__get_string_data(&c, NSURL_WITH_FRAGMENT, &length,
- &str_len, &str_flags);
-
- /* Create NetSurf URL object */
- *url = malloc(sizeof(nsurl) + length + 1); /* Add 1 for \0 */
- if (*url == NULL) {
- nsurl_destroy_components(&c);
- return NSERROR_NOMEM;
+ e = nsurl__components_to_string(&c, NSURL_WITH_FRAGMENT,
+ sizeof(nsurl), (char **)url, &length);
+ if (e != NSERROR_OK) {
+ return e;
}
(*url)->components = c;
(*url)->length = length;
- /* Fill out the url string */
- nsurl_get_string(&c, (*url)->string, &str_len, str_flags);
-
/* Get the nsurl's hash */
- nsurl_calc_hash(*url);
+ nsurl__calc_hash(*url);
/* Give the URL a reference */
(*url)->count = 1;
@@ -1453,382 +1317,6 @@ nserror nsurl_create(const char * const url_s, nsurl **url)
/* exported interface, documented in nsurl.h */
-nsurl *nsurl_ref(nsurl *url)
-{
- assert(url != NULL);
-
- url->count++;
-
- return url;
-}
-
-
-/* exported interface, documented in nsurl.h */
-void nsurl_unref(nsurl *url)
-{
- assert(url != NULL);
- assert(url->count > 0);
-
- if (--url->count > 0)
- return;
-
-#ifdef NSURL_DEBUG
- nsurl__dump(url);
-#endif
-
- /* Release lwc strings */
- nsurl_destroy_components(&url->components);
-
- /* Free the NetSurf URL */
- free(url);
-}
-
-
-/* exported interface, documented in nsurl.h */
-bool nsurl_compare(const nsurl *url1, const nsurl *url2, nsurl_component parts)
-{
- bool match = true;
-
- assert(url1 != NULL);
- assert(url2 != NULL);
-
- /* Compare URL components */
-
- /* Path, host and query first, since they're most likely to differ */
-
- if (parts & NSURL_PATH) {
- nsurl__component_compare(url1->components.path,
- url2->components.path, &match);
-
- if (match == false)
- return false;
- }
-
- if (parts & NSURL_HOST) {
- nsurl__component_compare(url1->components.host,
- url2->components.host, &match);
-
- if (match == false)
- return false;
- }
-
- if (parts & NSURL_QUERY) {
- nsurl__component_compare(url1->components.query,
- url2->components.query, &match);
-
- if (match == false)
- return false;
- }
-
- if (parts & NSURL_SCHEME) {
- nsurl__component_compare(url1->components.scheme,
- url2->components.scheme, &match);
-
- if (match == false)
- return false;
- }
-
- if (parts & NSURL_USERNAME) {
- nsurl__component_compare(url1->components.username,
- url2->components.username, &match);
-
- if (match == false)
- return false;
- }
-
- if (parts & NSURL_PASSWORD) {
- nsurl__component_compare(url1->components.password,
- url2->components.password, &match);
-
- if (match == false)
- return false;
- }
-
- if (parts & NSURL_PORT) {
- nsurl__component_compare(url1->components.port,
- url2->components.port, &match);
-
- if (match == false)
- return false;
- }
-
- if (parts & NSURL_FRAGMENT) {
- nsurl__component_compare(url1->components.fragment,
- url2->components.fragment, &match);
-
- if (match == false)
- return false;
- }
-
- return true;
-}
-
-
-/* exported interface, documented in nsurl.h */
-nserror nsurl_get(const nsurl *url, nsurl_component parts,
- char **url_s, size_t *url_l)
-{
- struct nsurl_component_lengths str_len = { 0, 0, 0, 0, 0, 0, 0, 0 };
- enum nsurl_string_flags str_flags = 0;
-
- assert(url != NULL);
-
- /* Get the string length and find which parts of url need copied */
- nsurl__get_string_data(&(url->components), parts, url_l,
- &str_len, &str_flags);
-
- if (*url_l == 0) {
- return NSERROR_BAD_URL;
- }
-
- /* Allocate memory for url string */
- *url_s = malloc(*url_l + 1); /* adding 1 for '\0' */
- if (*url_s == NULL) {
- return NSERROR_NOMEM;
- }
-
- /* Copy the required parts into the url string */
- nsurl_get_string(&(url->components), *url_s, &str_len, str_flags);
-
- return NSERROR_OK;
-}
-
-
-/* exported interface, documented in nsurl.h */
-lwc_string *nsurl_get_component(const nsurl *url, nsurl_component part)
-{
- assert(url != NULL);
-
- switch (part) {
- case NSURL_SCHEME:
- return (url->components.scheme != NULL) ?
- lwc_string_ref(url->components.scheme) : NULL;
-
- case NSURL_USERNAME:
- return (url->components.username != NULL) ?
- lwc_string_ref(url->components.username) : NULL;
-
- case NSURL_PASSWORD:
- return (url->components.password != NULL) ?
- lwc_string_ref(url->components.password) : NULL;
-
- case NSURL_HOST:
- return (url->components.host != NULL) ?
- lwc_string_ref(url->components.host) : NULL;
-
- case NSURL_PORT:
- return (url->components.port != NULL) ?
- lwc_string_ref(url->components.port) : NULL;
-
- case NSURL_PATH:
- return (url->components.path != NULL) ?
- lwc_string_ref(url->components.path) : NULL;
-
- case NSURL_QUERY:
- return (url->components.query != NULL) ?
- lwc_string_ref(url->components.query) : NULL;
-
- case NSURL_FRAGMENT:
- return (url->components.fragment != NULL) ?
- lwc_string_ref(url->components.fragment) : NULL;
-
- default:
- LOG("Unsupported value passed to part param.");
- assert(0);
- }
-
- return NULL;
-}
-
-
-/* exported interface, documented in nsurl.h */
-bool nsurl_has_component(const nsurl *url, nsurl_component part)
-{
- assert(url != NULL);
-
- switch (part) {
- case NSURL_SCHEME:
- if (url->components.scheme != NULL)
- return true;
- else
- return false;
-
- case NSURL_CREDENTIALS:
- /* Only username required for credentials section */
- /* Fall through */
- case NSURL_USERNAME:
- if (url->components.username != NULL)
- return true;
- else
- return false;
-
- case NSURL_PASSWORD:
- if (url->components.password != NULL)
- return true;
- else
- return false;
-
- case NSURL_HOST:
- if (url->components.host != NULL)
- return true;
- else
- return false;
-
- case NSURL_PORT:
- if (url->components.port != NULL)
- return true;
- else
- return false;
-
- case NSURL_PATH:
- if (url->components.path != NULL)
- return true;
- else
- return false;
-
- case NSURL_QUERY:
- if (url->components.query != NULL)
- return true;
- else
- return false;
-
- case NSURL_FRAGMENT:
- if (url->components.fragment != NULL)
- return true;
- else
- return false;
-
- default:
- LOG("Unsupported value passed to part param.");
- assert(0);
- }
-
- return false;
-}
-
-
-/* exported interface, documented in nsurl.h */
-const char *nsurl_access(const nsurl *url)
-{
- assert(url != NULL);
-
- return url->string;
-}
-
-
-/* exported interface, documented in nsurl.h */
-nserror nsurl_get_utf8(const nsurl *url, char **url_s, size_t *url_l)
-{
- nserror err;
- lwc_string *host;
- char *idna_host = NULL;
- size_t idna_host_len;
- char *scheme = NULL;
- size_t scheme_len;
- char *path = NULL;
- size_t path_len;
-
- assert(url != NULL);
-
- if (url->components.host == NULL) {
- return nsurl_get(url, NSURL_WITH_FRAGMENT, url_s, url_l);
- }
-
- host = url->components.host;
- err = idna_decode(lwc_string_data(host), lwc_string_length(host),
- &idna_host, &idna_host_len);
- if (err != NSERROR_OK) {
- goto cleanup;
- }
-
- err = nsurl_get(url,
- NSURL_SCHEME | NSURL_CREDENTIALS,
- &scheme, &scheme_len);
- if (err != NSERROR_OK) {
- goto cleanup;
- }
-
- err = nsurl_get(url,
- NSURL_PORT | NSURL_PATH | NSURL_QUERY | NSURL_FRAGMENT,
- &path, &path_len);
- if (err != NSERROR_OK) {
- goto cleanup;
- }
-
- *url_l = scheme_len + idna_host_len + path_len + 1; /* +1 for \0 */
- *url_s = malloc(*url_l);
-
- if (*url_s == NULL) {
- err = NSERROR_NOMEM;
- goto cleanup;
- }
-
- snprintf(*url_s, *url_l, "%s%s%s", scheme, idna_host, path);
-
- err = NSERROR_OK;
-
-cleanup:
- free(idna_host);
- free(scheme);
- free(path);
-
- return err;
-}
-
-
-/* exported interface, documented in nsurl.h */
-const char *nsurl_access_leaf(const nsurl *url)
-{
- size_t path_len;
- const char *path;
- const char *leaf;
-
- assert(url != NULL);
-
- if (url->components.path == NULL)
- return "";
-
- path = lwc_string_data(url->components.path);
- path_len = lwc_string_length(url->components.path);
-
- if (path_len == 0)
- return "";
-
- if (path_len == 1 && *path == '/')
- return "/";
-
- leaf = path + path_len;
-
- do {
- leaf--;
- } while ((leaf != path) && (*leaf != '/'));
-
- if (*leaf == '/')
- leaf++;
-
- return leaf;
-}
-
-
-/* exported interface, documented in nsurl.h */
-size_t nsurl_length(const nsurl *url)
-{
- assert(url != NULL);
-
- return url->length;
-}
-
-
-/* exported interface, documented in nsurl.h */
-uint32_t nsurl_hash(const nsurl *url)
-{
- assert(url != NULL);
-
- return url->hash;
-}
-
-
-/* exported interface, documented in nsurl.h */
nserror nsurl_join(const nsurl *base, const char *rel, nsurl **joined)
{
struct url_markers m;
@@ -1837,8 +1325,6 @@ nserror nsurl_join(const nsurl *base, const char *rel, nsurl **joined)
char *buff;
char *buff_pos;
char *buff_start;
- struct nsurl_component_lengths str_len = { 0, 0, 0, 0, 0, 0, 0, 0 };
- enum nsurl_string_flags str_flags = 0;
nserror error = 0;
enum {
NSURL_F_REL = 0,
@@ -2049,24 +1535,17 @@ nserror nsurl_join(const nsurl *base, const char *rel, nsurl **joined)
return error;
}
- /* Get the string length and find which parts of url are present */
- nsurl__get_string_data(&c, NSURL_WITH_FRAGMENT, &length,
- &str_len, &str_flags);
-
- /* Create NetSurf URL object */
- *joined = malloc(sizeof(nsurl) + length + 1); /* Add 1 for \0 */
- if (*joined == NULL) {
- return NSERROR_NOMEM;
+ error = nsurl__components_to_string(&c, NSURL_WITH_FRAGMENT,
+ sizeof(nsurl), (char **)joined, &length);
+ if (error != NSERROR_OK) {
+ return error;
}
(*joined)->components = c;
(*joined)->length = length;
- /* Fill out the url string */
- nsurl_get_string(&c, (*joined)->string, &str_len, str_flags);
-
/* Get the nsurl's hash */
- nsurl_calc_hash(*joined);
+ nsurl__calc_hash(*joined);
/* Give the URL a reference */
(*joined)->count = 1;
@@ -2074,427 +1553,3 @@ nserror nsurl_join(const nsurl *base, const char *rel, nsurl **joined)
return NSERROR_OK;
}
-
-/* exported interface, documented in nsurl.h */
-nserror nsurl_defragment(const nsurl *url, nsurl **no_frag)
-{
- size_t length;
- char *pos;
-
- assert(url != NULL);
-
- /* check for source url having no fragment already */
- if (url->components.fragment == NULL) {
- *no_frag = (nsurl *)url;
-
- (*no_frag)->count++;
-
- return NSERROR_OK;
- }
-
- /* Find the change in length from url to new_url */
- length = url->length;
- if (url->components.fragment != NULL) {
- length -= 1 + lwc_string_length(url->components.fragment);
- }
-
- /* Create NetSurf URL object */
- *no_frag = malloc(sizeof(nsurl) + length + 1); /* Add 1 for \0 */
- if (*no_frag == NULL) {
- return NSERROR_NOMEM;
- }
-
- /* Copy components */
- (*no_frag)->components.scheme =
- nsurl__component_copy(url->components.scheme);
- (*no_frag)->components.username =
- nsurl__component_copy(url->components.username);
- (*no_frag)->components.password =
- nsurl__component_copy(url->components.password);
- (*no_frag)->components.host =
- nsurl__component_copy(url->components.host);
- (*no_frag)->components.port =
- nsurl__component_copy(url->components.port);
- (*no_frag)->components.path =
- nsurl__component_copy(url->components.path);
- (*no_frag)->components.query =
- nsurl__component_copy(url->components.query);
- (*no_frag)->components.fragment = NULL;
-
- (*no_frag)->components.scheme_type = url->components.scheme_type;
-
- (*no_frag)->length = length;
-
- /* Fill out the url string */
- pos = (*no_frag)->string;
- memcpy(pos, url->string, length);
- pos += length;
- *pos = '\0';
-
- /* Get the nsurl's hash */
- nsurl_calc_hash(*no_frag);
-
- /* Give the URL a reference */
- (*no_frag)->count = 1;
-
- return NSERROR_OK;
-}
-
-
-/* exported interface, documented in nsurl.h */
-nserror nsurl_refragment(const nsurl *url, lwc_string *frag, nsurl **new_url)
-{
- int frag_len;
- int base_len;
- char *pos;
- size_t len;
-
- assert(url != NULL);
- assert(frag != NULL);
-
- /* Find the change in length from url to new_url */
- base_len = url->length;
- if (url->components.fragment != NULL) {
- base_len -= 1 + lwc_string_length(url->components.fragment);
- }
- frag_len = lwc_string_length(frag);
-
- /* Set new_url's length */
- len = base_len + 1 /* # */ + frag_len;
-
- /* Create NetSurf URL object */
- *new_url = malloc(sizeof(nsurl) + len + 1); /* Add 1 for \0 */
- if (*new_url == NULL) {
- return NSERROR_NOMEM;
- }
-
- (*new_url)->length = len;
-
- /* Set string */
- pos = (*new_url)->string;
- memcpy(pos, url->string, base_len);
- pos += base_len;
- *pos = '#';
- memcpy(++pos, lwc_string_data(frag), frag_len);
- pos += frag_len;
- *pos = '\0';
-
- /* Copy components */
- (*new_url)->components.scheme =
- nsurl__component_copy(url->components.scheme);
- (*new_url)->components.username =
- nsurl__component_copy(url->components.username);
- (*new_url)->components.password =
- nsurl__component_copy(url->components.password);
- (*new_url)->components.host =
- nsurl__component_copy(url->components.host);
- (*new_url)->components.port =
- nsurl__component_copy(url->components.port);
- (*new_url)->components.path =
- nsurl__component_copy(url->components.path);
- (*new_url)->components.query =
- nsurl__component_copy(url->components.query);
- (*new_url)->components.fragment =
- lwc_string_ref(frag);
-
- (*new_url)->components.scheme_type = url->components.scheme_type;
-
- /* Get the nsurl's hash */
- nsurl_calc_hash(*new_url);
-
- /* Give the URL a reference */
- (*new_url)->count = 1;
-
- return NSERROR_OK;
-}
-
-
-/* exported interface, documented in nsurl.h */
-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;
-
- assert(url != NULL);
- assert(query != NULL);
- assert(query[0] == '?');
-
- /* Get the length of the new query */
- query_len = strlen(query);
-
- /* 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);
- }
- if (url->components.fragment != NULL) {
- frag_len = 1 + lwc_string_length(url->components.fragment);
- base_len -= frag_len;
- }
-
- /* Set new_url's length */
- len = base_len + query_len + frag_len;
-
- /* Create NetSurf URL object */
- *new_url = malloc(sizeof(nsurl) + len + 1); /* Add 1 for \0 */
- if (*new_url == NULL) {
- 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;
-
- /* Set string */
- pos = (*new_url)->string;
- memcpy(pos, url->string, base_len);
- pos += base_len;
- 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;
- }
- *pos = '\0';
-
- /* Copy components */
- (*new_url)->components.scheme =
- nsurl__component_copy(url->components.scheme);
- (*new_url)->components.username =
- nsurl__component_copy(url->components.username);
- (*new_url)->components.password =
- nsurl__component_copy(url->components.password);
- (*new_url)->components.host =
- nsurl__component_copy(url->components.host);
- (*new_url)->components.port =
- nsurl__component_copy(url->components.port);
- (*new_url)->components.path =
- nsurl__component_copy(url->components.path);
- (*new_url)->components.query = lwc_query;
- (*new_url)->components.fragment =
- nsurl__component_copy(url->components.fragment);
-
- (*new_url)->components.scheme_type = url->components.scheme_type;
-
- /* Get the nsurl's hash */
- nsurl_calc_hash(*new_url);
-
- /* Give the URL a reference */
- (*new_url)->count = 1;
-
- return NSERROR_OK;
-}
-
-
-/* exported interface documented in utils/nsurl.h */
-nserror nsurl_nice(const nsurl *url, char **result, bool remove_extensions)
-{
- const char *data;
- size_t len;
- size_t pos;
- bool match;
- char *name;
-
- assert(url != NULL);
-
- *result = 0;
-
- /* extract the last component of the path, if possible */
- if ((url->components.path != NULL) &&
- (lwc_string_length(url->components.path) != 0) &&
- (lwc_string_isequal(url->components.path,
- corestring_lwc_slash_, &match) == lwc_error_ok) &&
- (match == false)) {
- bool first = true;
- bool keep_looking;
-
- /* Get hold of the string data we're examining */
- data = lwc_string_data(url->components.path);
- len = lwc_string_length(url->components.path);
- pos = len;
-
- do {
- keep_looking = false;
- pos--;
-
- /* Find last '/' with stuff after it */
- while (pos != 0) {
- if (data[pos] == '/' && pos < len - 1) {
- break;
- }
- pos--;
- }
-
- if (pos == 0) {
- break;
- }
-
- if (first) {
- if (strncasecmp("/default.", data + pos,
- SLEN("/default.")) == 0) {
- keep_looking = true;
-
- } else if (strncasecmp("/index.",
- data + pos,
- 6) == 0) {
- keep_looking = true;
-
- }
- first = false;
- }
-
- } while (keep_looking);
-
- if (data[pos] == '/')
- pos++;
-
- if (strncasecmp("default.", data + pos, 8) != 0 &&
- strncasecmp("index.", data + pos, 6) != 0) {
- size_t end = pos;
- while (data[end] != '\0' && data[end] != '/') {
- end++;
- }
- if (end - pos != 0) {
- name = malloc(end - pos + 1);
- if (name == NULL) {
- return NSERROR_NOMEM;
- }
- memcpy(name, data + pos, end - pos);
- name[end - pos] = '\0';
- if (remove_extensions) {
- /* strip any extenstion */
- char *dot = strchr(name, '.');
- if (dot && dot != name) {
- *dot = '\0';
- }
- }
- *result = name;
- return NSERROR_OK;
- }
- }
- }
-
- if (url->components.host != NULL) {
- name = strdup(lwc_string_data(url->components.host));
-
- for (pos = 0; name[pos] != '\0'; pos++) {
- if (name[pos] == '.') {
- name[pos] = '_';
- }
- }
-
- *result = name;
- return NSERROR_OK;
- }
-
- return NSERROR_NOT_FOUND;
-}
-
-
-/* exported interface, documented in nsurl.h */
-nserror nsurl_parent(const nsurl *url, nsurl **new_url)
-{
- lwc_string *lwc_path;
- size_t old_path_len, new_path_len;
- size_t len;
- const char* path = NULL;
- char *pos;
-
- assert(url != NULL);
-
- old_path_len = (url->components.path == NULL) ? 0 :
- lwc_string_length(url->components.path);
-
- /* Find new path length */
- if (old_path_len == 0) {
- new_path_len = old_path_len;
- } else {
- path = lwc_string_data(url->components.path);
-
- new_path_len = old_path_len;
- if (old_path_len > 1) {
- /* Skip over any trailing / */
- if (path[new_path_len - 1] == '/')
- new_path_len--;
-
- /* Work back to next / */
- while (new_path_len > 0 &&
- path[new_path_len - 1] != '/')
- new_path_len--;
- }
- }
-
- /* Find the length of new_url */
- len = url->length;
- if (url->components.query != NULL) {
- len -= lwc_string_length(url->components.query);
- }
- if (url->components.fragment != NULL) {
- len -= 1; /* # */
- len -= lwc_string_length(url->components.fragment);
- }
- len -= old_path_len - new_path_len;
-
- /* Create NetSurf URL object */
- *new_url = malloc(sizeof(nsurl) + len + 1); /* Add 1 for \0 */
- if (*new_url == NULL) {
- return NSERROR_NOMEM;
- }
-
- /* Make new path */
- if (old_path_len == 0) {
- lwc_path = NULL;
- } else if (old_path_len == new_path_len) {
- lwc_path = lwc_string_ref(url->components.path);
- } else {
- if (lwc_intern_string(path, old_path_len - new_path_len,
- &lwc_path) != lwc_error_ok) {
- free(*new_url);
- return NSERROR_NOMEM;
- }
- }
-
- (*new_url)->length = len;
-
- /* Set string */
- pos = (*new_url)->string;
- memcpy(pos, url->string, len);
- pos += len;
- *pos = '\0';
-
- /* Copy components */
- (*new_url)->components.scheme =
- nsurl__component_copy(url->components.scheme);
- (*new_url)->components.username =
- nsurl__component_copy(url->components.username);
- (*new_url)->components.password =
- nsurl__component_copy(url->components.password);
- (*new_url)->components.host =
- nsurl__component_copy(url->components.host);
- (*new_url)->components.port =
- nsurl__component_copy(url->components.port);
- (*new_url)->components.path = lwc_path;
- (*new_url)->components.query = NULL;
- (*new_url)->components.fragment = NULL;
-
- (*new_url)->components.scheme_type = url->components.scheme_type;
-
- /* Get the nsurl's hash */
- nsurl_calc_hash(*new_url);
-
- /* Give the URL a reference */
- (*new_url)->count = 1;
-
- return NSERROR_OK;
-}
-
diff --git a/utils/nsurl/private.h b/utils/nsurl/private.h
new file mode 100644
index 000000000..e78f83042
--- /dev/null
+++ b/utils/nsurl/private.h
@@ -0,0 +1,215 @@
+/*
+ * Copyright 2011-2017 Michael Drake <tlsa@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NETSURF_UTILS_NSURL_PRIVATE_H_
+#define NETSURF_UTILS_NSURL_PRIVATE_H_
+
+#include <libwapcaplet/libwapcaplet.h>
+
+#include "utils/nsurl.h"
+#include "utils/utils.h"
+
+
+/* Define to enable NSURL debugging */
+#undef NSURL_DEBUG
+
+
+/** A type for URL schemes */
+enum nsurl_scheme_type {
+ NSURL_SCHEME_OTHER,
+ NSURL_SCHEME_HTTP,
+ NSURL_SCHEME_HTTPS,
+ NSURL_SCHEME_FTP,
+ NSURL_SCHEME_MAILTO
+};
+
+
+/**
+ * nsurl components
+ *
+ * [scheme]://[username]:[password]@[host]:[port][path][?query]#[fragment]
+ *
+ * Note:
+ * "path" string includes preceding '/', if needed for the scheme
+ * "query" string always includes preceding '?'
+ *
+ * The other spanned punctuation is to be inserted when building URLs from
+ * components.
+ */
+struct nsurl_components {
+ lwc_string *scheme;
+ lwc_string *username;
+ lwc_string *password;
+ lwc_string *host;
+ lwc_string *port;
+ lwc_string *path;
+ lwc_string *query;
+ lwc_string *fragment;
+
+ enum nsurl_scheme_type scheme_type;
+};
+
+
+/**
+ * NetSurf URL object
+ */
+struct nsurl {
+ struct nsurl_components components;
+
+ int count; /* Number of references to NetSurf URL object */
+ uint32_t hash; /* Hash value for nsurl identification */
+
+ size_t length; /* Length of string */
+ char string[FLEX_ARRAY_LEN_DECL]; /* Full URL as a string */
+};
+
+
+/** Marker set, indicating positions of sections within a URL string */
+struct nsurl_component_lengths {
+ size_t scheme;
+ size_t username;
+ size_t password;
+ size_t host;
+ size_t port;
+ size_t path;
+ size_t query;
+ size_t fragment;
+};
+
+
+/** Flags indicating which parts of a URL string are required for a nsurl */
+enum nsurl_string_flags {
+ NSURL_F_SCHEME = (1 << 0),
+ NSURL_F_SCHEME_PUNCTUATION = (1 << 1),
+ NSURL_F_AUTHORITY_PUNCTUATION = (1 << 2),
+ NSURL_F_USERNAME = (1 << 3),
+ NSURL_F_PASSWORD = (1 << 4),
+ NSURL_F_CREDENTIALS_PUNCTUATION = (1 << 5),
+ NSURL_F_HOST = (1 << 6),
+ NSURL_F_PORT = (1 << 7),
+ NSURL_F_AUTHORITY = (NSURL_F_USERNAME |
+ NSURL_F_PASSWORD |
+ 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)
+};
+
+/**
+ * NULL-safe lwc_string_ref
+ */
+#define nsurl__component_copy(c) (c == NULL) ? NULL : lwc_string_ref(c)
+
+
+/**
+ * Convert a set of nsurl components to a single string
+ *
+ * \param[in] components The URL components to stitch together.
+ * \param[in] parts The set of parts wanted in the string.
+ * \param[in] pre_padding Amount in bytes to pad the start of the string by.
+ * \param[out] url_s_out Returns allocated URL string.
+ * \param[out] url_l_out Returns byte length of string, excluding pre_padding.
+ * \return NSERROR_OK on success, appropriate error otherwise.
+ */
+nserror nsurl__components_to_string(
+ const struct nsurl_components *components,
+ nsurl_component parts, size_t pre_padding,
+ char **url_s_out, size_t *url_l_out);
+
+/**
+ * Calculate hash value
+ *
+ * \param url NetSurf URL object to set hash value for
+ */
+void nsurl__calc_hash(nsurl *url);
+
+
+
+
+/**
+ * Destroy components
+ *
+ * \param c url components
+ */
+static inline void nsurl__components_destroy(struct nsurl_components *c)
+{
+ if (c->scheme)
+ lwc_string_unref(c->scheme);
+
+ if (c->username)
+ lwc_string_unref(c->username);
+
+ if (c->password)
+ lwc_string_unref(c->password);
+
+ if (c->host)
+ lwc_string_unref(c->host);
+
+ if (c->port)
+ lwc_string_unref(c->port);
+
+ if (c->path)
+ lwc_string_unref(c->path);
+
+ if (c->query)
+ lwc_string_unref(c->query);
+
+ if (c->fragment)
+ lwc_string_unref(c->fragment);
+}
+
+
+
+#ifdef NSURL_DEBUG
+/**
+ * Dump a NetSurf URL's internal components
+ *
+ * \param url The NetSurf URL to dump components of
+ */
+static inline void nsurl__dump(const nsurl *url)
+{
+ if (url->components.scheme)
+ LOG(" Scheme: %s", lwc_string_data(url->components.scheme));
+
+ if (url->components.username)
+ LOG("Username: %s", lwc_string_data(url->components.username));
+
+ if (url->components.password)
+ LOG("Password: %s", lwc_string_data(url->components.password));
+
+ if (url->components.host)
+ LOG(" Host: %s", lwc_string_data(url->components.host));
+
+ if (url->components.port)
+ LOG(" Port: %s", lwc_string_data(url->components.port));
+
+ if (url->components.path)
+ LOG(" Path: %s", lwc_string_data(url->components.path));
+
+ if (url->components.query)
+ LOG(" Query: %s", lwc_string_data(url->components.query));
+
+ if (url->components.fragment)
+ LOG("Fragment: %s", lwc_string_data(url->components.fragment));
+}
+#endif
+
+
+#endif