summaryrefslogtreecommitdiff
path: root/utils/nsurl/nsurl.c
diff options
context:
space:
mode:
Diffstat (limited to 'utils/nsurl/nsurl.c')
-rw-r--r--utils/nsurl/nsurl.c212
1 files changed, 180 insertions, 32 deletions
diff --git a/utils/nsurl/nsurl.c b/utils/nsurl/nsurl.c
index 3b0af9328..63619af15 100644
--- a/utils/nsurl/nsurl.c
+++ b/utils/nsurl/nsurl.c
@@ -36,6 +36,7 @@
#include <stdlib.h>
#include <string.h>
#include <strings.h>
+#include <inttypes.h>
#include "utils/ascii.h"
#include "utils/corestrings.h"
@@ -54,7 +55,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 */ \
@@ -88,10 +89,6 @@ void nsurl_unref(nsurl *url)
if (--url->count > 0)
return;
-#ifdef NSURL_DEBUG
- nsurl__dump(url);
-#endif
-
/* Release lwc strings */
nsurl__components_destroy(&url->components);
@@ -240,6 +237,15 @@ lwc_string *nsurl_get_component(const nsurl *url, nsurl_component part)
/* exported interface, documented in nsurl.h */
+enum nsurl_scheme_type nsurl_get_scheme_type(const nsurl *url)
+{
+ assert(url != NULL);
+
+ return url->components.scheme_type;
+}
+
+
+/* exported interface, documented in nsurl.h */
bool nsurl_has_component(const nsurl *url, nsurl_component part)
{
assert(url != NULL);
@@ -316,6 +322,19 @@ const char *nsurl_access(const nsurl *url)
/* exported interface, documented in nsurl.h */
+const char *nsurl_access_log(const nsurl *url)
+{
+ assert(url != NULL);
+
+ if (url->components.scheme_type == NSURL_SCHEME_DATA) {
+ return "[data url]";
+ }
+
+ 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;
@@ -355,7 +374,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;
@@ -565,57 +584,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';
@@ -648,6 +677,93 @@ nserror nsurl_replace_query(const nsurl *url, const char *query,
}
+/* exported interface, documented in nsurl.h */
+nserror nsurl_replace_scheme(const nsurl *url, lwc_string *scheme,
+ nsurl **new_url)
+{
+ int scheme_len;
+ int base_len;
+ char *pos;
+ size_t len;
+ bool match;
+
+ assert(url != NULL);
+ assert(scheme != NULL);
+
+ /* Get the length of the new scheme */
+ scheme_len = lwc_string_length(scheme);
+
+ /* Find the change in length from url to new_url */
+ base_len = url->length;
+ if (url->components.scheme != NULL) {
+ base_len -= lwc_string_length(url->components.scheme);
+ }
+
+ /* Set new_url's length */
+ len = base_len + scheme_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, lwc_string_data(scheme), scheme_len);
+ memcpy(pos + scheme_len,
+ url->string + url->length - base_len, base_len);
+ pos[len] = '\0';
+
+ /* Copy components */
+ (*new_url)->components.scheme = lwc_string_ref(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 =
+ nsurl__component_copy(url->components.fragment);
+
+ /* Compute new scheme type */
+ if (lwc_string_caseless_isequal(scheme, corestring_lwc_http,
+ &match) == lwc_error_ok && match == true) {
+ (*new_url)->components.scheme_type = NSURL_SCHEME_HTTP;
+ } else if (lwc_string_caseless_isequal(scheme, corestring_lwc_https,
+ &match) == lwc_error_ok && match == true) {
+ (*new_url)->components.scheme_type = NSURL_SCHEME_HTTPS;
+ } else if (lwc_string_caseless_isequal(scheme, corestring_lwc_file,
+ &match) == lwc_error_ok && match == true) {
+ (*new_url)->components.scheme_type = NSURL_SCHEME_FILE;
+ } else if (lwc_string_caseless_isequal(scheme, corestring_lwc_ftp,
+ &match) == lwc_error_ok && match == true) {
+ (*new_url)->components.scheme_type = NSURL_SCHEME_FTP;
+ } else if (lwc_string_caseless_isequal(scheme, corestring_lwc_mailto,
+ &match) == lwc_error_ok && match == true) {
+ (*new_url)->components.scheme_type = NSURL_SCHEME_MAILTO;
+ } else {
+ (*new_url)->components.scheme_type = NSURL_SCHEME_OTHER;
+ }
+
+ /* 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)
{
@@ -809,7 +925,7 @@ nserror nsurl_parent(const nsurl *url, nsurl **new_url)
} 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,
+ if (lwc_intern_string(path, new_path_len,
&lwc_path) != lwc_error_ok) {
free(*new_url);
return NSERROR_NOMEM;
@@ -850,3 +966,35 @@ nserror nsurl_parent(const nsurl *url, nsurl **new_url)
return NSERROR_OK;
}
+/* exported interface, documented in nsurl.h */
+void nsurl_dump(const nsurl *url)
+{
+ fprintf(stderr, "nsurl components for %p "
+ "(refs: %i hash: %"PRIx32"):\n",
+ url, url->count, url->hash);
+
+ if (url->components.scheme)
+ fprintf(stderr, " Scheme: %s\n",
+ lwc_string_data(url->components.scheme));
+ if (url->components.username)
+ fprintf(stderr, "Username: %s\n",
+ lwc_string_data(url->components.username));
+ if (url->components.password)
+ fprintf(stderr, "Password: %s\n",
+ lwc_string_data(url->components.password));
+ if (url->components.host)
+ fprintf(stderr, " Host: %s\n",
+ lwc_string_data(url->components.host));
+ if (url->components.port)
+ fprintf(stderr, " Port: %s\n",
+ lwc_string_data(url->components.port));
+ if (url->components.path)
+ fprintf(stderr, " Path: %s\n",
+ lwc_string_data(url->components.path));
+ if (url->components.query)
+ fprintf(stderr, " Query: %s\n",
+ lwc_string_data(url->components.query));
+ if (url->components.fragment)
+ fprintf(stderr, "Fragment: %s\n",
+ lwc_string_data(url->components.fragment));
+}