summaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
Diffstat (limited to 'utils')
-rw-r--r--utils/Makefile1
-rw-r--r--utils/ascii.h65
-rw-r--r--utils/corestringlist.h357
-rw-r--r--utils/corestrings.c943
-rw-r--r--utils/corestrings.h298
-rw-r--r--utils/errors.h75
-rw-r--r--utils/filename.c51
-rw-r--r--utils/hashtable.c237
-rw-r--r--utils/hashtable.h53
-rw-r--r--utils/http.h1
-rw-r--r--utils/http/Makefile5
-rw-r--r--utils/http/challenge.c2
-rw-r--r--utils/http/content-disposition.c2
-rw-r--r--utils/http/content-type.c2
-rw-r--r--utils/http/generics.h2
-rw-r--r--utils/http/strict-transport-security.c341
-rw-r--r--utils/http/strict-transport-security.h64
-rw-r--r--utils/idna.c38
-rwxr-xr-xutils/jenkins-build.sh28
-rw-r--r--utils/log.c284
-rw-r--r--utils/log.h68
-rwxr-xr-xutils/merge-messages.lua83
-rw-r--r--utils/messages.c233
-rw-r--r--utils/nsoption.c17
-rw-r--r--utils/nsoption.h4
-rw-r--r--utils/nsurl.h19
-rw-r--r--utils/nsurl/Makefile7
-rw-r--r--utils/nsurl/nsurl.c939
-rw-r--r--utils/nsurl/parse.c (renamed from utils/nsurl.c)1166
-rw-r--r--utils/nsurl/private.h232
-rw-r--r--utils/split-messages.pl17
-rw-r--r--utils/useragent.c3
-rw-r--r--utils/utf8.c5
33 files changed, 2972 insertions, 2670 deletions
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/ascii.h b/utils/ascii.h
index f08e756a0..94d988aed 100644
--- a/utils/ascii.h
+++ b/utils/ascii.h
@@ -111,6 +111,17 @@ static inline bool ascii_is_alphanumerical(char c)
}
/**
+ * Test whether a character is 'a' to 'f' (lowercase).
+ *
+ * \param[in] c Character to test.
+ * \return true iff `c` is 'a' to 'f' (lowercase), else false.
+ */
+static inline bool ascii_is_af_lower(char c)
+{
+ return (c >= 'a' && c <= 'f');
+}
+
+/**
* Test whether a character is hexadecimal (lower case).
*
* \param[in] c Character to test.
@@ -118,8 +129,18 @@ static inline bool ascii_is_alphanumerical(char c)
*/
static inline bool ascii_is_hex_lower(char c)
{
- return (ascii_is_digit(c) ||
- (c >= 'a' && c <= 'f'));
+ return (ascii_is_digit(c) || ascii_is_af_lower(c));
+}
+
+/**
+ * Test whether a character is 'A' to 'F' (uppercase).
+ *
+ * \param[in] c Character to test.
+ * \return true iff `c` is 'A' to 'F' (uppercase), else false.
+ */
+static inline bool ascii_is_af_upper(char c)
+{
+ return (c >= 'A' && c <= 'F');
}
/**
@@ -130,8 +151,7 @@ static inline bool ascii_is_hex_lower(char c)
*/
static inline bool ascii_is_hex_upper(char c)
{
- return (ascii_is_digit(c) ||
- (c >= 'A' && c <= 'F'));
+ return (ascii_is_digit(c) || ascii_is_af_upper(c));
}
/**
@@ -143,8 +163,41 @@ static inline bool ascii_is_hex_upper(char c)
static inline bool ascii_is_hex(char c)
{
return (ascii_is_digit(c) ||
- (c >= 'A' && c <= 'F') ||
- (c >= 'a' && c <= 'f'));
+ ascii_is_af_upper(c) ||
+ ascii_is_af_lower(c));
+}
+
+/**
+ * Convert a hexadecimal character to its value.
+ *
+ * \param[in] c Character to convert.
+ * \return value of character (0-15), or -256 if not a hexadecimal character.
+ */
+static inline int ascii_hex_to_value(char c)
+{
+ if (ascii_is_digit(c)) {
+ return c - '0';
+ } else if (ascii_is_af_lower(c)) {
+ return c - 'a' + 10;
+ } else if (ascii_is_af_upper(c)) {
+ return c - 'A' + 10;
+ }
+
+ /* Invalid hex */
+ return -256;
+}
+
+/**
+ * Converts two hexadecimal characters to a single number
+ *
+ * \param[in] c1 most significant hex digit.
+ * \param[in] c2 least significant hex digit.
+ * \return the total value of the two digit hex number (0-255),
+ * or -ve if input not hex.
+ */
+static inline int ascii_hex_to_value_2_chars(char c1, char c2)
+{
+ return 16 * ascii_hex_to_value(c1) + ascii_hex_to_value(c2);
}
/**
diff --git a/utils/corestringlist.h b/utils/corestringlist.h
new file mode 100644
index 000000000..90dd796a7
--- /dev/null
+++ b/utils/corestringlist.h
@@ -0,0 +1,357 @@
+/*
+ * Copyright 2012 Vincent Sanders <vince@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
+ * Core string lists
+ *
+ * three macros must be defined to use this header
+ * CORESTRING_LWC_VALUE - wapcaplet strings with a value not derived from name
+ * CORESTRING_DOM_VALUE - dom strings with a value not derived from name
+ * CORESTRING_NSURL - nsurl from given url
+ *
+ * two helper macros are defined that allow simple mapping strings
+ * CORESTRING_LWC_STRING - libwapcaplet strings with a simple name value mapping
+ * CORESTRING_DOM_STRING - dom strings with a simple name value mapping
+ *
+ * \note This header is specificaly intented to be included multiple
+ * times with different macro definitions so there is no guard.
+ */
+
+#if !defined(CORESTRING_LWC_VALUE) | !defined(CORESTRING_DOM_VALUE) | !defined(CORESTRING_NSURL)
+#error "missing macro definition. This header must not be directly included"
+#endif
+
+#undef CORESTRING_LWC_STRING
+#define CORESTRING_LWC_STRING(NAME) CORESTRING_LWC_VALUE(NAME, #NAME)
+
+#undef CORESTRING_DOM_STRING
+#define CORESTRING_DOM_STRING(NAME) CORESTRING_DOM_VALUE(NAME, #NAME);
+
+/* lwc_string strings */
+CORESTRING_LWC_STRING(a);
+CORESTRING_LWC_STRING(about);
+CORESTRING_LWC_STRING(abscenter);
+CORESTRING_LWC_STRING(absmiddle);
+CORESTRING_LWC_STRING(align);
+CORESTRING_LWC_STRING(applet);
+CORESTRING_LWC_STRING(base);
+CORESTRING_LWC_STRING(baseline);
+CORESTRING_LWC_STRING(body);
+CORESTRING_LWC_STRING(bottom);
+CORESTRING_LWC_STRING(button);
+CORESTRING_LWC_STRING(caption);
+CORESTRING_LWC_STRING(charset);
+CORESTRING_LWC_STRING(center);
+CORESTRING_LWC_STRING(checkbox);
+CORESTRING_LWC_STRING(circle);
+CORESTRING_LWC_STRING(col);
+CORESTRING_LWC_STRING(data);
+CORESTRING_LWC_STRING(default);
+CORESTRING_LWC_STRING(div);
+CORESTRING_LWC_STRING(embed);
+CORESTRING_LWC_STRING(file);
+CORESTRING_LWC_STRING(filename);
+CORESTRING_LWC_STRING(font);
+CORESTRING_LWC_STRING(frame);
+CORESTRING_LWC_STRING(frameset);
+CORESTRING_LWC_STRING(ftp);
+CORESTRING_LWC_STRING(h1);
+CORESTRING_LWC_STRING(h2);
+CORESTRING_LWC_STRING(h3);
+CORESTRING_LWC_STRING(h4);
+CORESTRING_LWC_STRING(h5);
+CORESTRING_LWC_STRING(h6);
+CORESTRING_LWC_STRING(head);
+CORESTRING_LWC_STRING(hidden);
+CORESTRING_LWC_STRING(hr);
+CORESTRING_LWC_STRING(html);
+CORESTRING_LWC_STRING(http);
+CORESTRING_LWC_STRING(https);
+CORESTRING_LWC_STRING(icon);
+CORESTRING_LWC_STRING(iframe);
+CORESTRING_LWC_STRING(image);
+CORESTRING_LWC_STRING(img);
+CORESTRING_LWC_STRING(includesubdomains);
+CORESTRING_LWC_STRING(input);
+CORESTRING_LWC_STRING(javascript);
+CORESTRING_LWC_STRING(justify);
+CORESTRING_LWC_STRING(left);
+CORESTRING_LWC_STRING(li);
+CORESTRING_LWC_STRING(link);
+CORESTRING_LWC_STRING(mailto);
+CORESTRING_LWC_STRING(meta);
+CORESTRING_LWC_STRING(middle);
+CORESTRING_LWC_STRING(no);
+CORESTRING_LWC_STRING(noscript);
+CORESTRING_LWC_STRING(object);
+CORESTRING_LWC_STRING(optgroup);
+CORESTRING_LWC_STRING(option);
+CORESTRING_LWC_STRING(p);
+CORESTRING_LWC_STRING(param);
+CORESTRING_LWC_STRING(password);
+CORESTRING_LWC_STRING(poly);
+CORESTRING_LWC_STRING(polygon);
+CORESTRING_LWC_STRING(post);
+CORESTRING_LWC_STRING(radio);
+CORESTRING_LWC_STRING(rect);
+CORESTRING_LWC_STRING(rectangle);
+CORESTRING_LWC_STRING(refresh);
+CORESTRING_LWC_STRING(reset);
+CORESTRING_LWC_STRING(resource);
+CORESTRING_LWC_STRING(right);
+CORESTRING_LWC_STRING(search);
+CORESTRING_LWC_STRING(select);
+CORESTRING_LWC_STRING(src);
+CORESTRING_LWC_STRING(style);
+CORESTRING_LWC_STRING(submit);
+CORESTRING_LWC_STRING(table);
+CORESTRING_LWC_STRING(tbody);
+CORESTRING_LWC_STRING(td);
+CORESTRING_LWC_STRING(text);
+CORESTRING_LWC_STRING(textarea);
+CORESTRING_LWC_STRING(texttop);
+CORESTRING_LWC_STRING(tfoot);
+CORESTRING_LWC_STRING(th);
+CORESTRING_LWC_STRING(thead);
+CORESTRING_LWC_STRING(title);
+CORESTRING_LWC_STRING(top);
+CORESTRING_LWC_STRING(tr);
+CORESTRING_LWC_STRING(ul);
+CORESTRING_LWC_STRING(url);
+CORESTRING_LWC_STRING(yes);
+CORESTRING_LWC_STRING(_blank);
+CORESTRING_LWC_STRING(_parent);
+CORESTRING_LWC_STRING(_self);
+CORESTRING_LWC_STRING(_top);
+
+/* unusual lwc strings */
+CORESTRING_LWC_VALUE(shortcut_icon, "shortcut icon");
+CORESTRING_LWC_VALUE(slash_, "/");
+CORESTRING_LWC_VALUE(max_age, "max-age");
+
+/* mime types */
+CORESTRING_LWC_VALUE(multipart_form_data, "multipart/form-data");
+CORESTRING_LWC_VALUE(text_css, "text/css");
+CORESTRING_LWC_VALUE(unknown_unknown, "unknown/unknown");
+CORESTRING_LWC_VALUE(application_unknown, "application/unknown");
+CORESTRING_LWC_VALUE(any, "*/*");
+CORESTRING_LWC_VALUE(text_xml, "text/xml");
+CORESTRING_LWC_VALUE(application_xml, "application/xml");
+CORESTRING_LWC_VALUE(text_html, "text/html");
+CORESTRING_LWC_VALUE(text_plain, "text/plain");
+CORESTRING_LWC_VALUE(application_octet_stream, "application/octet-stream");
+CORESTRING_LWC_VALUE(image_gif, "image/gif");
+CORESTRING_LWC_VALUE(image_png, "image/png");
+CORESTRING_LWC_VALUE(image_jpeg, "image/jpeg");
+CORESTRING_LWC_VALUE(image_bmp, "image/bmp");
+CORESTRING_LWC_VALUE(image_vnd_microsoft_icon, "image/vnd.microsoft.icon");
+CORESTRING_LWC_VALUE(image_webp, "image/webp");
+CORESTRING_LWC_VALUE(application_rss_xml, "application/rss+xml");
+CORESTRING_LWC_VALUE(application_atom_xml, "application/atom+xml");
+CORESTRING_LWC_VALUE(audio_wave, "audio/wave");
+CORESTRING_LWC_VALUE(application_ogg, "application/ogg");
+CORESTRING_LWC_VALUE(video_webm, "video/webm");
+CORESTRING_LWC_VALUE(application_x_rar_compressed, "application/x-rar-compressed");
+CORESTRING_LWC_VALUE(application_zip, "application/zip");
+CORESTRING_LWC_VALUE(application_x_gzip, "application/x-gzip");
+CORESTRING_LWC_VALUE(application_postscript, "application/postscript");
+CORESTRING_LWC_VALUE(application_pdf, "application/pdf");
+CORESTRING_LWC_VALUE(video_mp4, "video/mp4");
+CORESTRING_LWC_VALUE(image_svg, "image/svg+xml");
+
+
+/* DOM strings */
+CORESTRING_DOM_STRING(a);
+CORESTRING_DOM_STRING(abort);
+CORESTRING_DOM_STRING(afterprint);
+CORESTRING_DOM_STRING(align);
+CORESTRING_DOM_STRING(alt);
+CORESTRING_DOM_STRING(area);
+CORESTRING_DOM_STRING(async);
+CORESTRING_DOM_STRING(background);
+CORESTRING_DOM_STRING(beforeprint);
+CORESTRING_DOM_STRING(beforeunload);
+CORESTRING_DOM_STRING(bgcolor);
+CORESTRING_DOM_STRING(blur);
+CORESTRING_DOM_STRING(border);
+CORESTRING_DOM_STRING(bordercolor);
+CORESTRING_DOM_STRING(cancel);
+CORESTRING_DOM_STRING(canplay);
+CORESTRING_DOM_STRING(canplaythrough);
+CORESTRING_DOM_STRING(cellpadding);
+CORESTRING_DOM_STRING(cellspacing);
+CORESTRING_DOM_STRING(change);
+CORESTRING_DOM_STRING(charset);
+CORESTRING_DOM_STRING(class);
+CORESTRING_DOM_STRING(classid);
+CORESTRING_DOM_STRING(click);
+CORESTRING_DOM_STRING(close);
+CORESTRING_DOM_STRING(codebase);
+CORESTRING_DOM_STRING(color);
+CORESTRING_DOM_STRING(cols);
+CORESTRING_DOM_STRING(colspan);
+CORESTRING_DOM_STRING(content);
+CORESTRING_DOM_STRING(contextmenu);
+CORESTRING_DOM_STRING(coords);
+CORESTRING_DOM_STRING(cuechange);
+CORESTRING_DOM_STRING(data);
+CORESTRING_DOM_STRING(dblclick);
+CORESTRING_DOM_STRING(defer);
+CORESTRING_DOM_STRING(DOMAttrModified);
+CORESTRING_DOM_STRING(DOMNodeInserted);
+CORESTRING_DOM_STRING(DOMNodeInsertedIntoDocument);
+CORESTRING_DOM_STRING(DOMSubtreeModified);
+CORESTRING_DOM_STRING(drag);
+CORESTRING_DOM_STRING(dragend);
+CORESTRING_DOM_STRING(dragenter);
+CORESTRING_DOM_STRING(dragleave);
+CORESTRING_DOM_STRING(dragover);
+CORESTRING_DOM_STRING(dragstart);
+CORESTRING_DOM_STRING(drop);
+CORESTRING_DOM_STRING(durationchange);
+CORESTRING_DOM_STRING(emptied);
+CORESTRING_DOM_STRING(ended);
+CORESTRING_DOM_STRING(error);
+CORESTRING_DOM_STRING(focus);
+CORESTRING_DOM_STRING(frameborder);
+CORESTRING_DOM_STRING(hashchange);
+CORESTRING_DOM_STRING(height);
+CORESTRING_DOM_STRING(href);
+CORESTRING_DOM_STRING(hreflang);
+CORESTRING_DOM_STRING(hspace);
+/* http-equiv: see below */
+CORESTRING_DOM_STRING(id);
+CORESTRING_DOM_STRING(input);
+CORESTRING_DOM_STRING(invalid);
+CORESTRING_DOM_STRING(keydown);
+CORESTRING_DOM_STRING(keypress);
+CORESTRING_DOM_STRING(keyup);
+CORESTRING_DOM_STRING(link);
+CORESTRING_DOM_STRING(load);
+CORESTRING_DOM_STRING(loadeddata);
+CORESTRING_DOM_STRING(loadedmetadata);
+CORESTRING_DOM_STRING(loadstart);
+CORESTRING_DOM_STRING(map);
+CORESTRING_DOM_STRING(marginheight);
+CORESTRING_DOM_STRING(marginwidth);
+CORESTRING_DOM_STRING(media);
+CORESTRING_DOM_STRING(message);
+CORESTRING_DOM_STRING(mousedown);
+CORESTRING_DOM_STRING(mousemove);
+CORESTRING_DOM_STRING(mouseout);
+CORESTRING_DOM_STRING(mouseover);
+CORESTRING_DOM_STRING(mouseup);
+CORESTRING_DOM_STRING(mousewheel);
+CORESTRING_DOM_STRING(name);
+CORESTRING_DOM_STRING(nohref);
+CORESTRING_DOM_STRING(noresize);
+CORESTRING_DOM_STRING(nowrap);
+CORESTRING_DOM_STRING(offline);
+CORESTRING_DOM_STRING(online);
+CORESTRING_DOM_STRING(pagehide);
+CORESTRING_DOM_STRING(pageshow);
+CORESTRING_DOM_STRING(pause);
+CORESTRING_DOM_STRING(play);
+CORESTRING_DOM_STRING(playing);
+CORESTRING_DOM_STRING(popstate);
+CORESTRING_DOM_STRING(progress);
+CORESTRING_DOM_STRING(ratechange);
+CORESTRING_DOM_STRING(readystatechange);
+CORESTRING_DOM_STRING(rect);
+CORESTRING_DOM_STRING(rel);
+CORESTRING_DOM_STRING(reset);
+CORESTRING_DOM_STRING(resize);
+CORESTRING_DOM_STRING(rows);
+CORESTRING_DOM_STRING(rowspan);
+CORESTRING_DOM_STRING(scroll);
+CORESTRING_DOM_STRING(scrolling);
+CORESTRING_DOM_STRING(seeked);
+CORESTRING_DOM_STRING(seeking);
+CORESTRING_DOM_STRING(select);
+CORESTRING_DOM_STRING(selected);
+CORESTRING_DOM_STRING(shape);
+CORESTRING_DOM_STRING(show);
+CORESTRING_DOM_STRING(size);
+CORESTRING_DOM_STRING(sizes);
+CORESTRING_DOM_STRING(src);
+CORESTRING_DOM_STRING(stalled);
+CORESTRING_DOM_STRING(storage);
+CORESTRING_DOM_STRING(style);
+CORESTRING_DOM_STRING(submit);
+CORESTRING_DOM_STRING(suspend);
+CORESTRING_DOM_STRING(target);
+CORESTRING_DOM_STRING(text);
+CORESTRING_DOM_STRING(timeupdate);
+CORESTRING_DOM_STRING(title);
+CORESTRING_DOM_STRING(type);
+CORESTRING_DOM_STRING(unload);
+CORESTRING_DOM_STRING(valign);
+CORESTRING_DOM_STRING(value);
+CORESTRING_DOM_STRING(vlink);
+CORESTRING_DOM_STRING(volumechange);
+CORESTRING_DOM_STRING(vspace);
+CORESTRING_DOM_STRING(waiting);
+CORESTRING_DOM_STRING(width);
+/* DOM node names, not really CSS */
+CORESTRING_DOM_STRING(BUTTON);
+CORESTRING_DOM_STRING(INPUT);
+CORESTRING_DOM_STRING(SELECT);
+CORESTRING_DOM_STRING(TEXTAREA);
+CORESTRING_DOM_STRING(BODY);
+CORESTRING_DOM_STRING(HEAD);
+/* DOM input types, not really CSS */
+CORESTRING_DOM_STRING(button);
+CORESTRING_DOM_STRING(image);
+CORESTRING_DOM_STRING(radio);
+CORESTRING_DOM_STRING(checkbox);
+CORESTRING_DOM_STRING(file);
+/* DOM event prefix */
+CORESTRING_DOM_STRING(on);
+/* DOM events forwarded from body to window */
+CORESTRING_DOM_STRING(onblur);
+CORESTRING_DOM_STRING(onerror);
+CORESTRING_DOM_STRING(onfocus);
+CORESTRING_DOM_STRING(onload);
+CORESTRING_DOM_STRING(onresize);
+CORESTRING_DOM_STRING(onscroll);
+/* Corestrings used by DOM event registration */
+CORESTRING_DOM_STRING(autocomplete);
+CORESTRING_DOM_STRING(autocompleteerror);
+CORESTRING_DOM_STRING(dragexit);
+CORESTRING_DOM_STRING(mouseenter);
+CORESTRING_DOM_STRING(mouseleave);
+CORESTRING_DOM_STRING(wheel);
+CORESTRING_DOM_STRING(sort);
+CORESTRING_DOM_STRING(toggle);
+/* DOM userdata keys, not really CSS */
+CORESTRING_DOM_STRING(__ns_key_box_node_data);
+CORESTRING_DOM_STRING(__ns_key_libcss_node_data);
+CORESTRING_DOM_STRING(__ns_key_file_name_node_data);
+CORESTRING_DOM_STRING(__ns_key_image_coords_node_data);
+CORESTRING_DOM_STRING(__ns_key_html_content_data);
+
+/* unusual DOM strings */
+CORESTRING_DOM_VALUE(text_javascript, "text/javascript");
+CORESTRING_DOM_VALUE(http_equiv, "http-equiv");
+CORESTRING_DOM_VALUE(html_namespace, "http://www.w3.org/1999/xhtml");
+
+CORESTRING_NSURL(about_blank, "about:blank");
+
+#undef CORESTRING_LWC_STRING
+#undef CORESTRING_DOM_STRING
diff --git a/utils/corestrings.c b/utils/corestrings.c
index 87a342313..d8934b739 100644
--- a/utils/corestrings.c
+++ b/utils/corestrings.c
@@ -16,8 +16,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
- * Useful interned string pointers (implementation).
+/**
+ * \file
+ * Useful interned string tables implementation.
*/
#include <dom/dom.h>
@@ -26,280 +27,19 @@
#include "utils/nsurl.h"
#include "utils/utils.h"
-/* lwc_string strings */
-lwc_string *corestring_lwc_a;
-lwc_string *corestring_lwc_about;
-lwc_string *corestring_lwc_abscenter;
-lwc_string *corestring_lwc_absmiddle;
-lwc_string *corestring_lwc_align;
-lwc_string *corestring_lwc_applet;
-lwc_string *corestring_lwc_base;
-lwc_string *corestring_lwc_baseline;
-lwc_string *corestring_lwc_body;
-lwc_string *corestring_lwc_bottom;
-lwc_string *corestring_lwc_button;
-lwc_string *corestring_lwc_caption;
-lwc_string *corestring_lwc_center;
-lwc_string *corestring_lwc_charset;
-lwc_string *corestring_lwc_checkbox;
-lwc_string *corestring_lwc_circle;
-lwc_string *corestring_lwc_col;
-lwc_string *corestring_lwc_data;
-lwc_string *corestring_lwc_default;
-lwc_string *corestring_lwc_div;
-lwc_string *corestring_lwc_embed;
-lwc_string *corestring_lwc_file;
-lwc_string *corestring_lwc_filename;
-lwc_string *corestring_lwc_font;
-lwc_string *corestring_lwc_frame;
-lwc_string *corestring_lwc_frameset;
-lwc_string *corestring_lwc_h1;
-lwc_string *corestring_lwc_h2;
-lwc_string *corestring_lwc_h3;
-lwc_string *corestring_lwc_h4;
-lwc_string *corestring_lwc_h5;
-lwc_string *corestring_lwc_h6;
-lwc_string *corestring_lwc_head;
-lwc_string *corestring_lwc_hidden;
-lwc_string *corestring_lwc_hr;
-lwc_string *corestring_lwc_html;
-lwc_string *corestring_lwc_http;
-lwc_string *corestring_lwc_https;
-lwc_string *corestring_lwc_icon;
-lwc_string *corestring_lwc_iframe;
-lwc_string *corestring_lwc_image;
-lwc_string *corestring_lwc_img;
-lwc_string *corestring_lwc_input;
-lwc_string *corestring_lwc_javascript;
-lwc_string *corestring_lwc_justify;
-lwc_string *corestring_lwc_left;
-lwc_string *corestring_lwc_li;
-lwc_string *corestring_lwc_link;
-lwc_string *corestring_lwc_mailto;
-lwc_string *corestring_lwc_meta;
-lwc_string *corestring_lwc_middle;
-lwc_string *corestring_lwc_multipart_form_data;
-lwc_string *corestring_lwc_no;
-lwc_string *corestring_lwc_noscript;
-lwc_string *corestring_lwc_object;
-lwc_string *corestring_lwc_optgroup;
-lwc_string *corestring_lwc_option;
-lwc_string *corestring_lwc_p;
-lwc_string *corestring_lwc_param;
-lwc_string *corestring_lwc_password;
-lwc_string *corestring_lwc_poly;
-lwc_string *corestring_lwc_polygon;
-lwc_string *corestring_lwc_post;
-lwc_string *corestring_lwc_radio;
-lwc_string *corestring_lwc_rect;
-lwc_string *corestring_lwc_rectangle;
-lwc_string *corestring_lwc_refresh;
-lwc_string *corestring_lwc_reset;
-lwc_string *corestring_lwc_resource;
-lwc_string *corestring_lwc_right;
-lwc_string *corestring_lwc_search;
-lwc_string *corestring_lwc_select;
-lwc_string *corestring_lwc_shortcut_icon;
-lwc_string *corestring_lwc_src;
-lwc_string *corestring_lwc_style;
-lwc_string *corestring_lwc_submit;
-lwc_string *corestring_lwc_table;
-lwc_string *corestring_lwc_tbody;
-lwc_string *corestring_lwc_td;
-lwc_string *corestring_lwc_text;
-lwc_string *corestring_lwc_textarea;
-lwc_string *corestring_lwc_texttop;
-lwc_string *corestring_lwc_text_css;
-lwc_string *corestring_lwc_tfoot;
-lwc_string *corestring_lwc_th;
-lwc_string *corestring_lwc_thead;
-lwc_string *corestring_lwc_title;
-lwc_string *corestring_lwc_top;
-lwc_string *corestring_lwc_tr;
-lwc_string *corestring_lwc_ul;
-lwc_string *corestring_lwc_url;
-lwc_string *corestring_lwc_yes;
-lwc_string *corestring_lwc__blank;
-lwc_string *corestring_lwc__parent;
-lwc_string *corestring_lwc__self;
-lwc_string *corestring_lwc__top;
-lwc_string *corestring_lwc_slash_;
-
-/* dom_string strings */
-dom_string *corestring_dom_a;
-dom_string *corestring_dom_alt;
-dom_string *corestring_dom_abort;
-dom_string *corestring_dom_afterprint;
-dom_string *corestring_dom_align;
-dom_string *corestring_dom_area;
-dom_string *corestring_dom_async;
-dom_string *corestring_dom_background;
-dom_string *corestring_dom_beforeprint;
-dom_string *corestring_dom_beforeunload;
-dom_string *corestring_dom_bgcolor;
-dom_string *corestring_dom_blur;
-dom_string *corestring_dom_border;
-dom_string *corestring_dom_bordercolor;
-dom_string *corestring_dom_cancel;
-dom_string *corestring_dom_canplay;
-dom_string *corestring_dom_canplaythrough;
-dom_string *corestring_dom_cellpadding;
-dom_string *corestring_dom_cellspacing;
-dom_string *corestring_dom_change;
-dom_string *corestring_dom_charset;
-dom_string *corestring_dom_class;
-dom_string *corestring_dom_classid;
-dom_string *corestring_dom_click;
-dom_string *corestring_dom_close;
-dom_string *corestring_dom_codebase;
-dom_string *corestring_dom_color;
-dom_string *corestring_dom_cols;
-dom_string *corestring_dom_colspan;
-dom_string *corestring_dom_content;
-dom_string *corestring_dom_contextmenu;
-dom_string *corestring_dom_coords;
-dom_string *corestring_dom_cuechange;
-dom_string *corestring_dom_data;
-dom_string *corestring_dom_dblclick;
-dom_string *corestring_dom_defer;
-dom_string *corestring_dom_DOMAttrModified;
-dom_string *corestring_dom_DOMNodeInserted;
-dom_string *corestring_dom_DOMNodeInsertedIntoDocument;
-dom_string *corestring_dom_DOMSubtreeModified;
-dom_string *corestring_dom_drag;
-dom_string *corestring_dom_dragend;
-dom_string *corestring_dom_dragenter;
-dom_string *corestring_dom_dragleave;
-dom_string *corestring_dom_dragover;
-dom_string *corestring_dom_dragstart;
-dom_string *corestring_dom_drop;
-dom_string *corestring_dom_durationchange;
-dom_string *corestring_dom_emptied;
-dom_string *corestring_dom_ended;
-dom_string *corestring_dom_error;
-dom_string *corestring_dom_focus;
-dom_string *corestring_dom_frameborder;
-dom_string *corestring_dom_hashchange;
-dom_string *corestring_dom_height;
-dom_string *corestring_dom_href;
-dom_string *corestring_dom_hreflang;
-dom_string *corestring_dom_hspace;
-dom_string *corestring_dom_http_equiv;
-dom_string *corestring_dom_id;
-dom_string *corestring_dom_input;
-dom_string *corestring_dom_invalid;
-dom_string *corestring_dom_keydown;
-dom_string *corestring_dom_keypress;
-dom_string *corestring_dom_keyup;
-dom_string *corestring_dom_link;
-dom_string *corestring_dom_load;
-dom_string *corestring_dom_loadeddata;
-dom_string *corestring_dom_loadedmetadata;
-dom_string *corestring_dom_loadstart;
-dom_string *corestring_dom_map;
-dom_string *corestring_dom_marginheight;
-dom_string *corestring_dom_marginwidth;
-dom_string *corestring_dom_media;
-dom_string *corestring_dom_message;
-dom_string *corestring_dom_mousedown;
-dom_string *corestring_dom_mousemove;
-dom_string *corestring_dom_mouseout;
-dom_string *corestring_dom_mouseover;
-dom_string *corestring_dom_mouseup;
-dom_string *corestring_dom_mousewheel;
-dom_string *corestring_dom_name;
-dom_string *corestring_dom_nohref;
-dom_string *corestring_dom_noresize;
-dom_string *corestring_dom_nowrap;
-dom_string *corestring_dom_offline;
-dom_string *corestring_dom_online;
-dom_string *corestring_dom_pagehide;
-dom_string *corestring_dom_pageshow;
-dom_string *corestring_dom_pause;
-dom_string *corestring_dom_play;
-dom_string *corestring_dom_playing;
-dom_string *corestring_dom_popstate;
-dom_string *corestring_dom_progress;
-dom_string *corestring_dom_ratechange;
-dom_string *corestring_dom_readystatechange;
-dom_string *corestring_dom_rect;
-dom_string *corestring_dom_rel;
-dom_string *corestring_dom_reset;
-dom_string *corestring_dom_resize;
-dom_string *corestring_dom_rows;
-dom_string *corestring_dom_rowspan;
-dom_string *corestring_dom_scroll;
-dom_string *corestring_dom_scrolling;
-dom_string *corestring_dom_seeked;
-dom_string *corestring_dom_seeking;
-dom_string *corestring_dom_select;
-dom_string *corestring_dom_selected;
-dom_string *corestring_dom_shape;
-dom_string *corestring_dom_show;
-dom_string *corestring_dom_size;
-dom_string *corestring_dom_sizes;
-dom_string *corestring_dom_src;
-dom_string *corestring_dom_stalled;
-dom_string *corestring_dom_storage;
-dom_string *corestring_dom_style;
-dom_string *corestring_dom_submit;
-dom_string *corestring_dom_suspend;
-dom_string *corestring_dom_target;
-dom_string *corestring_dom_text;
-dom_string *corestring_dom_text_javascript;
-dom_string *corestring_dom_timeupdate;
-dom_string *corestring_dom_title;
-dom_string *corestring_dom_type;
-dom_string *corestring_dom_unload;
-dom_string *corestring_dom_valign;
-dom_string *corestring_dom_value;
-dom_string *corestring_dom_vlink;
-dom_string *corestring_dom_volumechange;
-dom_string *corestring_dom_vspace;
-dom_string *corestring_dom_waiting;
-dom_string *corestring_dom_width;
-dom_string *corestring_dom_BUTTON;
-dom_string *corestring_dom_INPUT;
-dom_string *corestring_dom_SELECT;
-dom_string *corestring_dom_TEXTAREA;
-dom_string *corestring_dom_BODY;
-dom_string *corestring_dom_HEAD;
-dom_string *corestring_dom_html_namespace;
-dom_string *corestring_dom_button;
-dom_string *corestring_dom_image;
-dom_string *corestring_dom_radio;
-dom_string *corestring_dom_checkbox;
-dom_string *corestring_dom_file;
-dom_string *corestring_dom_on;
-dom_string *corestring_dom_onblur;
-dom_string *corestring_dom_onerror;
-dom_string *corestring_dom_onfocus;
-dom_string *corestring_dom_onload;
-dom_string *corestring_dom_onresize;
-dom_string *corestring_dom_onscroll;
-dom_string *corestring_dom_autocomplete;
-dom_string *corestring_dom_autocompleteerror;
-dom_string *corestring_dom_dragexit;
-dom_string *corestring_dom_mouseenter;
-dom_string *corestring_dom_mouseleave;
-dom_string *corestring_dom_wheel;
-dom_string *corestring_dom_sort;
-dom_string *corestring_dom_toggle;
-dom_string *corestring_dom___ns_key_box_node_data;
-dom_string *corestring_dom___ns_key_libcss_node_data;
-dom_string *corestring_dom___ns_key_file_name_node_data;
-dom_string *corestring_dom___ns_key_image_coords_node_data;
-dom_string *corestring_dom___ns_key_html_content_data;
-
-/* nsurl URLs */
-nsurl *corestring_nsurl_about_blank;
-
-/*
- * Free the core strings
- */
-void corestrings_fini(void)
+/* define corestrings */
+#define CORESTRING_LWC_VALUE(NAME,VALUE) lwc_string *corestring_lwc_##NAME
+#define CORESTRING_DOM_VALUE(NAME,VALUE) dom_string *corestring_dom_##NAME
+#define CORESTRING_NSURL(NAME,VALUE) nsurl *corestring_nsurl_##NAME
+#include "utils/corestringlist.h"
+#undef CORESTRING_LWC_VALUE
+#undef CORESTRING_DOM_VALUE
+#undef CORESTRING_NSURL
+
+/* exported interface documented in utils/corestrings.h */
+nserror corestrings_fini(void)
{
-#define CSS_LWC_STRING_UNREF(NAME) \
+#define CORESTRING_LWC_VALUE(NAME,VALUE) \
do { \
if (corestring_lwc_##NAME != NULL) { \
lwc_string_unref(corestring_lwc_##NAME); \
@@ -307,107 +47,7 @@ void corestrings_fini(void)
} \
} while (0)
- CSS_LWC_STRING_UNREF(a);
- CSS_LWC_STRING_UNREF(about);
- CSS_LWC_STRING_UNREF(abscenter);
- CSS_LWC_STRING_UNREF(absmiddle);
- CSS_LWC_STRING_UNREF(align);
- CSS_LWC_STRING_UNREF(applet);
- CSS_LWC_STRING_UNREF(base);
- CSS_LWC_STRING_UNREF(baseline);
- CSS_LWC_STRING_UNREF(body);
- CSS_LWC_STRING_UNREF(bottom);
- CSS_LWC_STRING_UNREF(button);
- CSS_LWC_STRING_UNREF(caption);
- CSS_LWC_STRING_UNREF(charset);
- CSS_LWC_STRING_UNREF(center);
- CSS_LWC_STRING_UNREF(checkbox);
- CSS_LWC_STRING_UNREF(circle);
- CSS_LWC_STRING_UNREF(col);
- CSS_LWC_STRING_UNREF(data);
- CSS_LWC_STRING_UNREF(default);
- CSS_LWC_STRING_UNREF(div);
- CSS_LWC_STRING_UNREF(embed);
- CSS_LWC_STRING_UNREF(file);
- CSS_LWC_STRING_UNREF(filename);
- CSS_LWC_STRING_UNREF(font);
- CSS_LWC_STRING_UNREF(frame);
- CSS_LWC_STRING_UNREF(frameset);
- CSS_LWC_STRING_UNREF(h1);
- CSS_LWC_STRING_UNREF(h2);
- CSS_LWC_STRING_UNREF(h3);
- CSS_LWC_STRING_UNREF(h4);
- CSS_LWC_STRING_UNREF(h5);
- CSS_LWC_STRING_UNREF(h6);
- CSS_LWC_STRING_UNREF(head);
- CSS_LWC_STRING_UNREF(hidden);
- CSS_LWC_STRING_UNREF(hr);
- CSS_LWC_STRING_UNREF(html);
- CSS_LWC_STRING_UNREF(http);
- CSS_LWC_STRING_UNREF(https);
- CSS_LWC_STRING_UNREF(icon);
- CSS_LWC_STRING_UNREF(iframe);
- CSS_LWC_STRING_UNREF(image);
- CSS_LWC_STRING_UNREF(img);
- CSS_LWC_STRING_UNREF(input);
- CSS_LWC_STRING_UNREF(javascript);
- CSS_LWC_STRING_UNREF(justify);
- CSS_LWC_STRING_UNREF(left);
- CSS_LWC_STRING_UNREF(li);
- CSS_LWC_STRING_UNREF(link);
- CSS_LWC_STRING_UNREF(mailto);
- CSS_LWC_STRING_UNREF(meta);
- CSS_LWC_STRING_UNREF(middle);
- CSS_LWC_STRING_UNREF(multipart_form_data);
- CSS_LWC_STRING_UNREF(no);
- CSS_LWC_STRING_UNREF(noscript);
- CSS_LWC_STRING_UNREF(object);
- CSS_LWC_STRING_UNREF(optgroup);
- CSS_LWC_STRING_UNREF(option);
- CSS_LWC_STRING_UNREF(p);
- CSS_LWC_STRING_UNREF(param);
- CSS_LWC_STRING_UNREF(password);
- CSS_LWC_STRING_UNREF(poly);
- CSS_LWC_STRING_UNREF(polygon);
- CSS_LWC_STRING_UNREF(post);
- CSS_LWC_STRING_UNREF(radio);
- CSS_LWC_STRING_UNREF(rect);
- CSS_LWC_STRING_UNREF(rectangle);
- CSS_LWC_STRING_UNREF(refresh);
- CSS_LWC_STRING_UNREF(reset);
- CSS_LWC_STRING_UNREF(resource);
- CSS_LWC_STRING_UNREF(right);
- CSS_LWC_STRING_UNREF(search);
- CSS_LWC_STRING_UNREF(select);
- CSS_LWC_STRING_UNREF(shortcut_icon);
- CSS_LWC_STRING_UNREF(src);
- CSS_LWC_STRING_UNREF(style);
- CSS_LWC_STRING_UNREF(submit);
- CSS_LWC_STRING_UNREF(table);
- CSS_LWC_STRING_UNREF(tbody);
- CSS_LWC_STRING_UNREF(td);
- CSS_LWC_STRING_UNREF(text);
- CSS_LWC_STRING_UNREF(textarea);
- CSS_LWC_STRING_UNREF(texttop);
- CSS_LWC_STRING_UNREF(text_css);
- CSS_LWC_STRING_UNREF(tfoot);
- CSS_LWC_STRING_UNREF(th);
- CSS_LWC_STRING_UNREF(thead);
- CSS_LWC_STRING_UNREF(title);
- CSS_LWC_STRING_UNREF(top);
- CSS_LWC_STRING_UNREF(tr);
- CSS_LWC_STRING_UNREF(ul);
- CSS_LWC_STRING_UNREF(url);
- CSS_LWC_STRING_UNREF(yes);
- CSS_LWC_STRING_UNREF(_blank);
- CSS_LWC_STRING_UNREF(_parent);
- CSS_LWC_STRING_UNREF(_self);
- CSS_LWC_STRING_UNREF(_top);
- CSS_LWC_STRING_UNREF(slash_);
-
-#undef CSS_LWC_STRING_UNREF
-
-#define CSS_DOM_STRING_UNREF(NAME) \
+#define CORESTRING_DOM_VALUE(NAME,VALUE) \
do { \
if (corestring_dom_##NAME != NULL) { \
dom_string_unref(corestring_dom_##NAME); \
@@ -415,547 +55,72 @@ void corestrings_fini(void)
} \
} while (0)
- CSS_DOM_STRING_UNREF(a);
- CSS_DOM_STRING_UNREF(abort);
- CSS_DOM_STRING_UNREF(afterprint);
- CSS_DOM_STRING_UNREF(align);
- CSS_DOM_STRING_UNREF(alt);
- CSS_DOM_STRING_UNREF(area);
- CSS_DOM_STRING_UNREF(async);
- CSS_DOM_STRING_UNREF(background);
- CSS_DOM_STRING_UNREF(beforeprint);
- CSS_DOM_STRING_UNREF(beforeunload);
- CSS_DOM_STRING_UNREF(bgcolor);
- CSS_DOM_STRING_UNREF(blur);
- CSS_DOM_STRING_UNREF(border);
- CSS_DOM_STRING_UNREF(bordercolor);
- CSS_DOM_STRING_UNREF(cancel);
- CSS_DOM_STRING_UNREF(canplay);
- CSS_DOM_STRING_UNREF(canplaythrough);
- CSS_DOM_STRING_UNREF(cellpadding);
- CSS_DOM_STRING_UNREF(cellspacing);
- CSS_DOM_STRING_UNREF(change);
- CSS_DOM_STRING_UNREF(charset);
- CSS_DOM_STRING_UNREF(class);
- CSS_DOM_STRING_UNREF(classid);
- CSS_DOM_STRING_UNREF(click);
- CSS_DOM_STRING_UNREF(close);
- CSS_DOM_STRING_UNREF(codebase);
- CSS_DOM_STRING_UNREF(color);
- CSS_DOM_STRING_UNREF(cols);
- CSS_DOM_STRING_UNREF(colspan);
- CSS_DOM_STRING_UNREF(content);
- CSS_DOM_STRING_UNREF(contextmenu);
- CSS_DOM_STRING_UNREF(coords);
- CSS_DOM_STRING_UNREF(cuechange);
- CSS_DOM_STRING_UNREF(data);
- CSS_DOM_STRING_UNREF(dblclick);
- CSS_DOM_STRING_UNREF(defer);
- CSS_DOM_STRING_UNREF(DOMAttrModified);
- CSS_DOM_STRING_UNREF(DOMNodeInserted);
- CSS_DOM_STRING_UNREF(DOMNodeInsertedIntoDocument);
- CSS_DOM_STRING_UNREF(DOMSubtreeModified);
- CSS_DOM_STRING_UNREF(drag);
- CSS_DOM_STRING_UNREF(dragend);
- CSS_DOM_STRING_UNREF(dragenter);
- CSS_DOM_STRING_UNREF(dragleave);
- CSS_DOM_STRING_UNREF(dragover);
- CSS_DOM_STRING_UNREF(dragstart);
- CSS_DOM_STRING_UNREF(drop);
- CSS_DOM_STRING_UNREF(durationchange);
- CSS_DOM_STRING_UNREF(emptied);
- CSS_DOM_STRING_UNREF(ended);
- CSS_DOM_STRING_UNREF(error);
- CSS_DOM_STRING_UNREF(focus);
- CSS_DOM_STRING_UNREF(frameborder);
- CSS_DOM_STRING_UNREF(hashchange);
- CSS_DOM_STRING_UNREF(height);
- CSS_DOM_STRING_UNREF(href);
- CSS_DOM_STRING_UNREF(hreflang);
- CSS_DOM_STRING_UNREF(hspace);
- CSS_DOM_STRING_UNREF(http_equiv);
- CSS_DOM_STRING_UNREF(id);
- CSS_DOM_STRING_UNREF(input);
- CSS_DOM_STRING_UNREF(invalid);
- CSS_DOM_STRING_UNREF(keydown);
- CSS_DOM_STRING_UNREF(keypress);
- CSS_DOM_STRING_UNREF(keyup);
- CSS_DOM_STRING_UNREF(link);
- CSS_DOM_STRING_UNREF(load);
- CSS_DOM_STRING_UNREF(loadeddata);
- CSS_DOM_STRING_UNREF(loadedmetadata);
- CSS_DOM_STRING_UNREF(loadstart);
- CSS_DOM_STRING_UNREF(map);
- CSS_DOM_STRING_UNREF(marginheight);
- CSS_DOM_STRING_UNREF(marginwidth);
- CSS_DOM_STRING_UNREF(media);
- CSS_DOM_STRING_UNREF(message);
- CSS_DOM_STRING_UNREF(mousedown);
- CSS_DOM_STRING_UNREF(mousemove);
- CSS_DOM_STRING_UNREF(mouseout);
- CSS_DOM_STRING_UNREF(mouseover);
- CSS_DOM_STRING_UNREF(mouseup);
- CSS_DOM_STRING_UNREF(mousewheel);
- CSS_DOM_STRING_UNREF(name);
- CSS_DOM_STRING_UNREF(nohref);
- CSS_DOM_STRING_UNREF(noresize);
- CSS_DOM_STRING_UNREF(nowrap);
- CSS_DOM_STRING_UNREF(offline);
- CSS_DOM_STRING_UNREF(online);
- CSS_DOM_STRING_UNREF(pagehide);
- CSS_DOM_STRING_UNREF(pageshow);
- CSS_DOM_STRING_UNREF(pause);
- CSS_DOM_STRING_UNREF(play);
- CSS_DOM_STRING_UNREF(playing);
- CSS_DOM_STRING_UNREF(popstate);
- CSS_DOM_STRING_UNREF(progress);
- CSS_DOM_STRING_UNREF(ratechange);
- CSS_DOM_STRING_UNREF(readystatechange);
- CSS_DOM_STRING_UNREF(rect);
- CSS_DOM_STRING_UNREF(rel);
- CSS_DOM_STRING_UNREF(reset);
- CSS_DOM_STRING_UNREF(resize);
- CSS_DOM_STRING_UNREF(rows);
- CSS_DOM_STRING_UNREF(rowspan);
- CSS_DOM_STRING_UNREF(scroll);
- CSS_DOM_STRING_UNREF(scrolling);
- CSS_DOM_STRING_UNREF(seeked);
- CSS_DOM_STRING_UNREF(seeking);
- CSS_DOM_STRING_UNREF(select);
- CSS_DOM_STRING_UNREF(selected);
- CSS_DOM_STRING_UNREF(shape);
- CSS_DOM_STRING_UNREF(show);
- CSS_DOM_STRING_UNREF(size);
- CSS_DOM_STRING_UNREF(sizes);
- CSS_DOM_STRING_UNREF(src);
- CSS_DOM_STRING_UNREF(stalled);
- CSS_DOM_STRING_UNREF(storage);
- CSS_DOM_STRING_UNREF(style);
- CSS_DOM_STRING_UNREF(submit);
- CSS_DOM_STRING_UNREF(suspend);
- CSS_DOM_STRING_UNREF(target);
- CSS_DOM_STRING_UNREF(text);
- CSS_DOM_STRING_UNREF(text_javascript);
- CSS_DOM_STRING_UNREF(timeupdate);
- CSS_DOM_STRING_UNREF(title);
- CSS_DOM_STRING_UNREF(type);
- CSS_DOM_STRING_UNREF(unload);
- CSS_DOM_STRING_UNREF(valign);
- CSS_DOM_STRING_UNREF(value);
- CSS_DOM_STRING_UNREF(vlink);
- CSS_DOM_STRING_UNREF(volumechange);
- CSS_DOM_STRING_UNREF(vspace);
- CSS_DOM_STRING_UNREF(waiting);
- CSS_DOM_STRING_UNREF(width);
- /* DOM node names, not really CSS */
- CSS_DOM_STRING_UNREF(BUTTON);
- CSS_DOM_STRING_UNREF(INPUT);
- CSS_DOM_STRING_UNREF(SELECT);
- CSS_DOM_STRING_UNREF(TEXTAREA);
- CSS_DOM_STRING_UNREF(BODY);
- CSS_DOM_STRING_UNREF(HEAD);
- /* DOM namespaces, not really CSS */
- CSS_DOM_STRING_UNREF(html_namespace);
- /* DOM input types, not really CSS */
- CSS_DOM_STRING_UNREF(button);
- CSS_DOM_STRING_UNREF(image);
- CSS_DOM_STRING_UNREF(radio);
- CSS_DOM_STRING_UNREF(checkbox);
- CSS_DOM_STRING_UNREF(file);
- /* DOM event prefix */
- CSS_DOM_STRING_UNREF(on);
- /* DOM events forwarded from body to window */
- CSS_DOM_STRING_UNREF(onblur);
- CSS_DOM_STRING_UNREF(onerror);
- CSS_DOM_STRING_UNREF(onfocus);
- CSS_DOM_STRING_UNREF(onload);
- CSS_DOM_STRING_UNREF(onresize);
- CSS_DOM_STRING_UNREF(onscroll);
- /* Corestrings used by DOM event registration */
- CSS_DOM_STRING_UNREF(autocomplete);
- CSS_DOM_STRING_UNREF(autocompleteerror);
- CSS_DOM_STRING_UNREF(dragexit);
- CSS_DOM_STRING_UNREF(mouseenter);
- CSS_DOM_STRING_UNREF(mouseleave);
- CSS_DOM_STRING_UNREF(wheel);
- CSS_DOM_STRING_UNREF(sort);
- CSS_DOM_STRING_UNREF(toggle);
- /* DOM userdata keys, not really CSS */
- CSS_DOM_STRING_UNREF(__ns_key_box_node_data);
- CSS_DOM_STRING_UNREF(__ns_key_libcss_node_data);
- CSS_DOM_STRING_UNREF(__ns_key_file_name_node_data);
- CSS_DOM_STRING_UNREF(__ns_key_image_coords_node_data);
- CSS_DOM_STRING_UNREF(__ns_key_html_content_data);
-#undef CSS_DOM_STRING_UNREF
+#define CORESTRING_NSURL(NAME,VALUE) \
+ do { \
+ if (corestring_nsurl_##NAME != NULL) { \
+ nsurl_unref(corestring_nsurl_##NAME); \
+ corestring_nsurl_##NAME = NULL; \
+ } \
+ } while (0)
+
+
+#include "utils/corestringlist.h"
- /* nsurl URLs */
- if (corestring_nsurl_about_blank != NULL) {
- nsurl_unref(corestring_nsurl_about_blank);
- corestring_nsurl_about_blank = NULL;
- }
+#undef CORESTRING_LWC_VALUE
+#undef CORESTRING_DOM_VALUE
+#undef CORESTRING_NSURL
+
+ return NSERROR_OK;
}
-/*
- * Create the core strings
- */
+/* exported interface documented in utils/corestrings.h */
nserror corestrings_init(void)
{
lwc_error lerror;
nserror error;
dom_exception exc;
-#define CSS_LWC_STRING_INTERN(NAME) \
+#define CORESTRING_LWC_VALUE(NAME,VALUE) \
do { \
lerror = lwc_intern_string( \
- (const char *)#NAME, \
- sizeof(#NAME) - 1, \
- &corestring_lwc_##NAME ); \
- if ((lerror != lwc_error_ok) || \
- (corestring_lwc_##NAME == NULL)) { \
+ (const char *)VALUE, \
+ sizeof(VALUE) - 1, \
+ &corestring_lwc_##NAME ); \
+ if ((lerror != lwc_error_ok) || \
+ (corestring_lwc_##NAME == NULL)) { \
error = NSERROR_NOMEM; \
goto error; \
} \
} while(0)
- CSS_LWC_STRING_INTERN(a);
- CSS_LWC_STRING_INTERN(about);
- CSS_LWC_STRING_INTERN(abscenter);
- CSS_LWC_STRING_INTERN(absmiddle);
- CSS_LWC_STRING_INTERN(align);
- CSS_LWC_STRING_INTERN(applet);
- CSS_LWC_STRING_INTERN(base);
- CSS_LWC_STRING_INTERN(baseline);
- CSS_LWC_STRING_INTERN(body);
- CSS_LWC_STRING_INTERN(bottom);
- CSS_LWC_STRING_INTERN(button);
- CSS_LWC_STRING_INTERN(caption);
- CSS_LWC_STRING_INTERN(charset);
- CSS_LWC_STRING_INTERN(center);
- CSS_LWC_STRING_INTERN(checkbox);
- CSS_LWC_STRING_INTERN(circle);
- CSS_LWC_STRING_INTERN(col);
- CSS_LWC_STRING_INTERN(data);
- CSS_LWC_STRING_INTERN(default);
- CSS_LWC_STRING_INTERN(div);
- CSS_LWC_STRING_INTERN(embed);
- CSS_LWC_STRING_INTERN(file);
- CSS_LWC_STRING_INTERN(filename);
- CSS_LWC_STRING_INTERN(font);
- CSS_LWC_STRING_INTERN(frame);
- CSS_LWC_STRING_INTERN(frameset);
- CSS_LWC_STRING_INTERN(h1);
- CSS_LWC_STRING_INTERN(h2);
- CSS_LWC_STRING_INTERN(h3);
- CSS_LWC_STRING_INTERN(h4);
- CSS_LWC_STRING_INTERN(h5);
- CSS_LWC_STRING_INTERN(h6);
- CSS_LWC_STRING_INTERN(head);
- CSS_LWC_STRING_INTERN(hidden);
- CSS_LWC_STRING_INTERN(hr);
- CSS_LWC_STRING_INTERN(html);
- CSS_LWC_STRING_INTERN(http);
- CSS_LWC_STRING_INTERN(https);
- CSS_LWC_STRING_INTERN(icon);
- CSS_LWC_STRING_INTERN(iframe);
- CSS_LWC_STRING_INTERN(image);
- CSS_LWC_STRING_INTERN(img);
- CSS_LWC_STRING_INTERN(input);
- CSS_LWC_STRING_INTERN(javascript);
- CSS_LWC_STRING_INTERN(justify);
- CSS_LWC_STRING_INTERN(left);
- CSS_LWC_STRING_INTERN(li);
- CSS_LWC_STRING_INTERN(link);
- CSS_LWC_STRING_INTERN(mailto);
- CSS_LWC_STRING_INTERN(meta);
- CSS_LWC_STRING_INTERN(middle);
- CSS_LWC_STRING_INTERN(no);
- CSS_LWC_STRING_INTERN(noscript);
- CSS_LWC_STRING_INTERN(object);
- CSS_LWC_STRING_INTERN(optgroup);
- CSS_LWC_STRING_INTERN(option);
- CSS_LWC_STRING_INTERN(p);
- CSS_LWC_STRING_INTERN(param);
- CSS_LWC_STRING_INTERN(password);
- CSS_LWC_STRING_INTERN(poly);
- CSS_LWC_STRING_INTERN(polygon);
- CSS_LWC_STRING_INTERN(post);
- CSS_LWC_STRING_INTERN(radio);
- CSS_LWC_STRING_INTERN(rect);
- CSS_LWC_STRING_INTERN(rectangle);
- CSS_LWC_STRING_INTERN(refresh);
- CSS_LWC_STRING_INTERN(reset);
- CSS_LWC_STRING_INTERN(resource);
- CSS_LWC_STRING_INTERN(right);
- CSS_LWC_STRING_INTERN(search);
- CSS_LWC_STRING_INTERN(select);
- CSS_LWC_STRING_INTERN(src);
- CSS_LWC_STRING_INTERN(style);
- CSS_LWC_STRING_INTERN(submit);
- CSS_LWC_STRING_INTERN(table);
- CSS_LWC_STRING_INTERN(tbody);
- CSS_LWC_STRING_INTERN(td);
- CSS_LWC_STRING_INTERN(text);
- CSS_LWC_STRING_INTERN(textarea);
- CSS_LWC_STRING_INTERN(texttop);
- CSS_LWC_STRING_INTERN(tfoot);
- CSS_LWC_STRING_INTERN(th);
- CSS_LWC_STRING_INTERN(thead);
- CSS_LWC_STRING_INTERN(title);
- CSS_LWC_STRING_INTERN(top);
- CSS_LWC_STRING_INTERN(tr);
- CSS_LWC_STRING_INTERN(ul);
- CSS_LWC_STRING_INTERN(url);
- CSS_LWC_STRING_INTERN(yes);
- CSS_LWC_STRING_INTERN(_blank);
- CSS_LWC_STRING_INTERN(_parent);
- CSS_LWC_STRING_INTERN(_self);
- CSS_LWC_STRING_INTERN(_top);
-#undef CSS_LWC_STRING_INTERN
-
-
- lerror = lwc_intern_string("multipart/form-data",
- SLEN("multipart/form-data"),
- &corestring_lwc_multipart_form_data);
- if ((lerror != lwc_error_ok) ||
- (corestring_lwc_multipart_form_data == NULL)) {
- error = NSERROR_NOMEM;
- goto error;
- }
-
- lerror = lwc_intern_string("shortcut icon", SLEN("shortcut icon"),
- &corestring_lwc_shortcut_icon);
- if ((lerror != lwc_error_ok) || (corestring_lwc_shortcut_icon == NULL)) {
- error = NSERROR_NOMEM;
- goto error;
- }
-
- lerror = lwc_intern_string("text/css", SLEN("text/css"),
- &corestring_lwc_text_css);
- if ((lerror != lwc_error_ok) || (corestring_lwc_text_css == NULL)) {
- error = NSERROR_NOMEM;
- goto error;
- }
-
- lerror = lwc_intern_string("/", SLEN("/"),
- &corestring_lwc_slash_);
- if ((lerror != lwc_error_ok) || (corestring_lwc_slash_ == NULL)) {
- error = NSERROR_NOMEM;
- goto error;
- }
-
-
-#define CSS_DOM_STRING_INTERN(NAME) \
+#define CORESTRING_DOM_VALUE(NAME,VALUE) \
do { \
exc = dom_string_create_interned( \
- (const uint8_t *)#NAME, \
- sizeof(#NAME) - 1, \
+ (const uint8_t *)VALUE, \
+ sizeof(VALUE) - 1, \
&corestring_dom_##NAME ); \
- if ((exc != DOM_NO_ERR) || \
+ if ((exc != DOM_NO_ERR) || \
(corestring_dom_##NAME == NULL)) { \
error = NSERROR_NOMEM; \
goto error; \
} \
} while(0)
- CSS_DOM_STRING_INTERN(a);
- CSS_DOM_STRING_INTERN(abort);
- CSS_DOM_STRING_INTERN(afterprint);
- CSS_DOM_STRING_INTERN(align);
- CSS_DOM_STRING_INTERN(alt);
- CSS_DOM_STRING_INTERN(area);
- CSS_DOM_STRING_INTERN(async);
- CSS_DOM_STRING_INTERN(background);
- CSS_DOM_STRING_INTERN(beforeprint);
- CSS_DOM_STRING_INTERN(beforeunload);
- CSS_DOM_STRING_INTERN(bgcolor);
- CSS_DOM_STRING_INTERN(blur);
- CSS_DOM_STRING_INTERN(border);
- CSS_DOM_STRING_INTERN(bordercolor);
- CSS_DOM_STRING_INTERN(cancel);
- CSS_DOM_STRING_INTERN(canplay);
- CSS_DOM_STRING_INTERN(canplaythrough);
- CSS_DOM_STRING_INTERN(cellpadding);
- CSS_DOM_STRING_INTERN(cellspacing);
- CSS_DOM_STRING_INTERN(change);
- CSS_DOM_STRING_INTERN(charset);
- CSS_DOM_STRING_INTERN(class);
- CSS_DOM_STRING_INTERN(classid);
- CSS_DOM_STRING_INTERN(click);
- CSS_DOM_STRING_INTERN(close);
- CSS_DOM_STRING_INTERN(codebase);
- CSS_DOM_STRING_INTERN(color);
- CSS_DOM_STRING_INTERN(cols);
- CSS_DOM_STRING_INTERN(colspan);
- CSS_DOM_STRING_INTERN(content);
- CSS_DOM_STRING_INTERN(contextmenu);
- CSS_DOM_STRING_INTERN(coords);
- CSS_DOM_STRING_INTERN(cuechange);
- CSS_DOM_STRING_INTERN(data);
- CSS_DOM_STRING_INTERN(dblclick);
- CSS_DOM_STRING_INTERN(defer);
- CSS_DOM_STRING_INTERN(DOMAttrModified);
- CSS_DOM_STRING_INTERN(DOMNodeInserted);
- CSS_DOM_STRING_INTERN(DOMNodeInsertedIntoDocument);
- CSS_DOM_STRING_INTERN(DOMSubtreeModified);
- CSS_DOM_STRING_INTERN(drag);
- CSS_DOM_STRING_INTERN(dragend);
- CSS_DOM_STRING_INTERN(dragenter);
- CSS_DOM_STRING_INTERN(dragleave);
- CSS_DOM_STRING_INTERN(dragover);
- CSS_DOM_STRING_INTERN(dragstart);
- CSS_DOM_STRING_INTERN(drop);
- CSS_DOM_STRING_INTERN(durationchange);
- CSS_DOM_STRING_INTERN(emptied);
- CSS_DOM_STRING_INTERN(ended);
- CSS_DOM_STRING_INTERN(error);
- CSS_DOM_STRING_INTERN(focus);
- CSS_DOM_STRING_INTERN(frameborder);
- CSS_DOM_STRING_INTERN(hashchange);
- CSS_DOM_STRING_INTERN(height);
- CSS_DOM_STRING_INTERN(href);
- CSS_DOM_STRING_INTERN(hreflang);
- CSS_DOM_STRING_INTERN(hspace);
- /* http-equiv: see below */
- CSS_DOM_STRING_INTERN(id);
- CSS_DOM_STRING_INTERN(input);
- CSS_DOM_STRING_INTERN(invalid);
- CSS_DOM_STRING_INTERN(keydown);
- CSS_DOM_STRING_INTERN(keypress);
- CSS_DOM_STRING_INTERN(keyup);
- CSS_DOM_STRING_INTERN(link);
- CSS_DOM_STRING_INTERN(load);
- CSS_DOM_STRING_INTERN(loadeddata);
- CSS_DOM_STRING_INTERN(loadedmetadata);
- CSS_DOM_STRING_INTERN(loadstart);
- CSS_DOM_STRING_INTERN(map);
- CSS_DOM_STRING_INTERN(marginheight);
- CSS_DOM_STRING_INTERN(marginwidth);
- CSS_DOM_STRING_INTERN(media);
- CSS_DOM_STRING_INTERN(message);
- CSS_DOM_STRING_INTERN(mousedown);
- CSS_DOM_STRING_INTERN(mousemove);
- CSS_DOM_STRING_INTERN(mouseout);
- CSS_DOM_STRING_INTERN(mouseover);
- CSS_DOM_STRING_INTERN(mouseup);
- CSS_DOM_STRING_INTERN(mousewheel);
- CSS_DOM_STRING_INTERN(name);
- CSS_DOM_STRING_INTERN(nohref);
- CSS_DOM_STRING_INTERN(noresize);
- CSS_DOM_STRING_INTERN(nowrap);
- CSS_DOM_STRING_INTERN(offline);
- CSS_DOM_STRING_INTERN(online);
- CSS_DOM_STRING_INTERN(pagehide);
- CSS_DOM_STRING_INTERN(pageshow);
- CSS_DOM_STRING_INTERN(pause);
- CSS_DOM_STRING_INTERN(play);
- CSS_DOM_STRING_INTERN(playing);
- CSS_DOM_STRING_INTERN(popstate);
- CSS_DOM_STRING_INTERN(progress);
- CSS_DOM_STRING_INTERN(ratechange);
- CSS_DOM_STRING_INTERN(readystatechange);
- CSS_DOM_STRING_INTERN(rect);
- CSS_DOM_STRING_INTERN(rel);
- CSS_DOM_STRING_INTERN(reset);
- CSS_DOM_STRING_INTERN(resize);
- CSS_DOM_STRING_INTERN(rows);
- CSS_DOM_STRING_INTERN(rowspan);
- CSS_DOM_STRING_INTERN(scroll);
- CSS_DOM_STRING_INTERN(scrolling);
- CSS_DOM_STRING_INTERN(seeked);
- CSS_DOM_STRING_INTERN(seeking);
- CSS_DOM_STRING_INTERN(select);
- CSS_DOM_STRING_INTERN(selected);
- CSS_DOM_STRING_INTERN(shape);
- CSS_DOM_STRING_INTERN(show);
- CSS_DOM_STRING_INTERN(size);
- CSS_DOM_STRING_INTERN(sizes);
- CSS_DOM_STRING_INTERN(src);
- CSS_DOM_STRING_INTERN(stalled);
- CSS_DOM_STRING_INTERN(storage);
- CSS_DOM_STRING_INTERN(style);
- CSS_DOM_STRING_INTERN(submit);
- CSS_DOM_STRING_INTERN(suspend);
- CSS_DOM_STRING_INTERN(target);
- CSS_DOM_STRING_INTERN(text);
- CSS_DOM_STRING_INTERN(timeupdate);
- CSS_DOM_STRING_INTERN(title);
- CSS_DOM_STRING_INTERN(type);
- CSS_DOM_STRING_INTERN(unload);
- CSS_DOM_STRING_INTERN(valign);
- CSS_DOM_STRING_INTERN(value);
- CSS_DOM_STRING_INTERN(vlink);
- CSS_DOM_STRING_INTERN(volumechange);
- CSS_DOM_STRING_INTERN(vspace);
- CSS_DOM_STRING_INTERN(waiting);
- CSS_DOM_STRING_INTERN(width);
- /* DOM node names, not really CSS */
- CSS_DOM_STRING_INTERN(BUTTON);
- CSS_DOM_STRING_INTERN(INPUT);
- CSS_DOM_STRING_INTERN(SELECT);
- CSS_DOM_STRING_INTERN(TEXTAREA);
- CSS_DOM_STRING_INTERN(BODY);
- CSS_DOM_STRING_INTERN(HEAD);
- /* DOM input types, not really CSS */
- CSS_DOM_STRING_INTERN(button);
- CSS_DOM_STRING_INTERN(image);
- CSS_DOM_STRING_INTERN(radio);
- CSS_DOM_STRING_INTERN(checkbox);
- CSS_DOM_STRING_INTERN(file);
- /* DOM event prefix */
- CSS_DOM_STRING_INTERN(on);
- /* DOM events forwarded from body to window */
- CSS_DOM_STRING_INTERN(onblur);
- CSS_DOM_STRING_INTERN(onerror);
- CSS_DOM_STRING_INTERN(onfocus);
- CSS_DOM_STRING_INTERN(onload);
- CSS_DOM_STRING_INTERN(onresize);
- CSS_DOM_STRING_INTERN(onscroll);
- /* Corestrings used by DOM event registration */
- CSS_DOM_STRING_INTERN(autocomplete);
- CSS_DOM_STRING_INTERN(autocompleteerror);
- CSS_DOM_STRING_INTERN(dragexit);
- CSS_DOM_STRING_INTERN(mouseenter);
- CSS_DOM_STRING_INTERN(mouseleave);
- CSS_DOM_STRING_INTERN(wheel);
- CSS_DOM_STRING_INTERN(sort);
- CSS_DOM_STRING_INTERN(toggle);
- /* DOM userdata keys, not really CSS */
- CSS_DOM_STRING_INTERN(__ns_key_box_node_data);
- CSS_DOM_STRING_INTERN(__ns_key_libcss_node_data);
- CSS_DOM_STRING_INTERN(__ns_key_file_name_node_data);
- CSS_DOM_STRING_INTERN(__ns_key_image_coords_node_data);
- CSS_DOM_STRING_INTERN(__ns_key_html_content_data);
-#undef CSS_DOM_STRING_INTERN
-
- exc = dom_string_create_interned((const uint8_t *) "text/javascript",
- SLEN("text/javascript"),
- &corestring_dom_text_javascript);
- if ((exc != DOM_NO_ERR) || (corestring_dom_text_javascript == NULL)) {
- error = NSERROR_NOMEM;
- goto error;
- }
-
- exc = dom_string_create_interned((const uint8_t *) "http-equiv",
- SLEN("http-equiv"),
- &corestring_dom_http_equiv);
- if ((exc != DOM_NO_ERR) || (corestring_dom_http_equiv == NULL)) {
- error = NSERROR_NOMEM;
- goto error;
- }
+#define CORESTRING_NSURL(NAME,VALUE) \
+ do { \
+ error = nsurl_create(VALUE, \
+ &corestring_nsurl_##NAME); \
+ if (error != NSERROR_OK) { \
+ goto error; \
+ } \
+ } while(0)
- exc = dom_string_create_interned((const uint8_t *) "http://www.w3.org/1999/xhtml",
- SLEN("http://www.w3.org/1999/xhtml"),
- &corestring_dom_html_namespace);
- if ((exc != DOM_NO_ERR) || (corestring_dom_html_namespace == NULL)) {
- error = NSERROR_NOMEM;
- goto error;
- }
+#include "utils/corestringlist.h"
- error = nsurl_create("about:blank", &corestring_nsurl_about_blank);
- if (error != NSERROR_OK) {
- goto error;
- }
+#undef CORESTRING_LWC_VALUE
+#undef CORESTRING_DOM_VALUE
+#undef CORESTRING_NSURL
return NSERROR_OK;
diff --git a/utils/corestrings.h b/utils/corestrings.h
index 88dc2ce3d..e4bf91e58 100644
--- a/utils/corestrings.h
+++ b/utils/corestrings.h
@@ -32,286 +32,32 @@
/** File url prefix length. */
#define FILE_SCHEME_PREFIX_LEN 8
+/**
+ * Initialise the core string tables
+ *
+ * \return NSERROR_OK on success else appropriate error code
+ */
nserror corestrings_init(void);
-void corestrings_fini(void);
-/* lwc_string strings */
-extern lwc_string *corestring_lwc_a;
-extern lwc_string *corestring_lwc_about;
-extern lwc_string *corestring_lwc_abscenter;
-extern lwc_string *corestring_lwc_absmiddle;
-extern lwc_string *corestring_lwc_align;
-extern lwc_string *corestring_lwc_applet;
-extern lwc_string *corestring_lwc_base;
-extern lwc_string *corestring_lwc_baseline;
-extern lwc_string *corestring_lwc_body;
-extern lwc_string *corestring_lwc_bottom;
-extern lwc_string *corestring_lwc_button;
-extern lwc_string *corestring_lwc_caption;
-extern lwc_string *corestring_lwc_center;
-extern lwc_string *corestring_lwc_charset;
-extern lwc_string *corestring_lwc_checkbox;
-extern lwc_string *corestring_lwc_circle;
-extern lwc_string *corestring_lwc_col;
-extern lwc_string *corestring_lwc_data;
-extern lwc_string *corestring_lwc_default;
-extern lwc_string *corestring_lwc_div;
-extern lwc_string *corestring_lwc_embed;
-extern lwc_string *corestring_lwc_file;
-extern lwc_string *corestring_lwc_filename;
-extern lwc_string *corestring_lwc_font;
-extern lwc_string *corestring_lwc_frame;
-extern lwc_string *corestring_lwc_frameset;
-extern lwc_string *corestring_lwc_h1;
-extern lwc_string *corestring_lwc_h2;
-extern lwc_string *corestring_lwc_h3;
-extern lwc_string *corestring_lwc_h4;
-extern lwc_string *corestring_lwc_h5;
-extern lwc_string *corestring_lwc_h6;
-extern lwc_string *corestring_lwc_head;
-extern lwc_string *corestring_lwc_hidden;
-extern lwc_string *corestring_lwc_hr;
-extern lwc_string *corestring_lwc_html;
-extern lwc_string *corestring_lwc_http;
-extern lwc_string *corestring_lwc_https;
-extern lwc_string *corestring_lwc_icon;
-extern lwc_string *corestring_lwc_iframe;
-extern lwc_string *corestring_lwc_image;
-extern lwc_string *corestring_lwc_img;
-extern lwc_string *corestring_lwc_input;
-extern lwc_string *corestring_lwc_javascript;
-extern lwc_string *corestring_lwc_justify;
-extern lwc_string *corestring_lwc_left;
-extern lwc_string *corestring_lwc_li;
-extern lwc_string *corestring_lwc_link;
-extern lwc_string *corestring_lwc_mailto;
-extern lwc_string *corestring_lwc_meta;
-extern lwc_string *corestring_lwc_middle;
-extern lwc_string *corestring_lwc_multipart_form_data; /* multipart/form-data */
-extern lwc_string *corestring_lwc_no;
-extern lwc_string *corestring_lwc_noscript;
-extern lwc_string *corestring_lwc_object;
-extern lwc_string *corestring_lwc_optgroup;
-extern lwc_string *corestring_lwc_option;
-extern lwc_string *corestring_lwc_p;
-extern lwc_string *corestring_lwc_param;
-extern lwc_string *corestring_lwc_password;
-extern lwc_string *corestring_lwc_poly;
-extern lwc_string *corestring_lwc_polygon;
-extern lwc_string *corestring_lwc_post;
-extern lwc_string *corestring_lwc_radio;
-extern lwc_string *corestring_lwc_rect;
-extern lwc_string *corestring_lwc_rectangle;
-extern lwc_string *corestring_lwc_refresh;
-extern lwc_string *corestring_lwc_reset;
-extern lwc_string *corestring_lwc_resource;
-extern lwc_string *corestring_lwc_right;
-extern lwc_string *corestring_lwc_search;
-extern lwc_string *corestring_lwc_select;
-extern lwc_string *corestring_lwc_shortcut_icon; /* shortcut icon */
-extern lwc_string *corestring_lwc_src;
-extern lwc_string *corestring_lwc_style;
-extern lwc_string *corestring_lwc_submit;
-extern lwc_string *corestring_lwc_table;
-extern lwc_string *corestring_lwc_tbody;
-extern lwc_string *corestring_lwc_td;
-extern lwc_string *corestring_lwc_text;
-extern lwc_string *corestring_lwc_textarea;
-extern lwc_string *corestring_lwc_texttop;
-extern lwc_string *corestring_lwc_text_css; /* text/css */
-extern lwc_string *corestring_lwc_tfoot;
-extern lwc_string *corestring_lwc_th;
-extern lwc_string *corestring_lwc_thead;
-extern lwc_string *corestring_lwc_title;
-extern lwc_string *corestring_lwc_top;
-extern lwc_string *corestring_lwc_tr;
-extern lwc_string *corestring_lwc_ul;
-extern lwc_string *corestring_lwc_url;
-extern lwc_string *corestring_lwc_yes;
-extern lwc_string *corestring_lwc__blank;
-extern lwc_string *corestring_lwc__parent;
-extern lwc_string *corestring_lwc__self;
-extern lwc_string *corestring_lwc__top;
-extern lwc_string *corestring_lwc_slash_; /* / */
+/**
+ * free resources of core string tables.
+ *
+ * \return NSERROR_OK on success else appropriate error code
+ */
+nserror corestrings_fini(void);
struct dom_string;
-/* dom_string strings */
-extern struct dom_string *corestring_dom_a;
-extern struct dom_string *corestring_dom_alt;
-extern struct dom_string *corestring_dom_abort;
-extern struct dom_string *corestring_dom_afterprint;
-extern struct dom_string *corestring_dom_align;
-extern struct dom_string *corestring_dom_area;
-extern struct dom_string *corestring_dom_async;
-extern struct dom_string *corestring_dom_background;
-extern struct dom_string *corestring_dom_beforeprint;
-extern struct dom_string *corestring_dom_beforeunload;
-extern struct dom_string *corestring_dom_bgcolor;
-extern struct dom_string *corestring_dom_blur;
-extern struct dom_string *corestring_dom_border;
-extern struct dom_string *corestring_dom_bordercolor;
-extern struct dom_string *corestring_dom_cancel;
-extern struct dom_string *corestring_dom_canplay;
-extern struct dom_string *corestring_dom_canplaythrough;
-extern struct dom_string *corestring_dom_cellpadding;
-extern struct dom_string *corestring_dom_cellspacing;
-extern struct dom_string *corestring_dom_change;
-extern struct dom_string *corestring_dom_charset;
-extern struct dom_string *corestring_dom_class;
-extern struct dom_string *corestring_dom_classid;
-extern struct dom_string *corestring_dom_click;
-extern struct dom_string *corestring_dom_close;
-extern struct dom_string *corestring_dom_codebase;
-extern struct dom_string *corestring_dom_color;
-extern struct dom_string *corestring_dom_cols;
-extern struct dom_string *corestring_dom_colspan;
-extern struct dom_string *corestring_dom_content;
-extern struct dom_string *corestring_dom_contextmenu;
-extern struct dom_string *corestring_dom_coords;
-extern struct dom_string *corestring_dom_cuechange;
-extern struct dom_string *corestring_dom_data;
-extern struct dom_string *corestring_dom_dblclick;
-extern struct dom_string *corestring_dom_defer;
-extern struct dom_string *corestring_dom_DOMAttrModified;
-extern struct dom_string *corestring_dom_DOMNodeInserted;
-extern struct dom_string *corestring_dom_DOMNodeInsertedIntoDocument;
-extern struct dom_string *corestring_dom_DOMSubtreeModified;
-extern struct dom_string *corestring_dom_drag;
-extern struct dom_string *corestring_dom_dragend;
-extern struct dom_string *corestring_dom_dragenter;
-extern struct dom_string *corestring_dom_dragleave;
-extern struct dom_string *corestring_dom_dragover;
-extern struct dom_string *corestring_dom_dragstart;
-extern struct dom_string *corestring_dom_drop;
-extern struct dom_string *corestring_dom_durationchange;
-extern struct dom_string *corestring_dom_emptied;
-extern struct dom_string *corestring_dom_ended;
-extern struct dom_string *corestring_dom_error;
-extern struct dom_string *corestring_dom_focus;
-extern struct dom_string *corestring_dom_frameborder;
-extern struct dom_string *corestring_dom_hashchange;
-extern struct dom_string *corestring_dom_height;
-extern struct dom_string *corestring_dom_href;
-extern struct dom_string *corestring_dom_hreflang;
-extern struct dom_string *corestring_dom_hspace;
-extern struct dom_string *corestring_dom_http_equiv; /* http-equiv */
-extern struct dom_string *corestring_dom_id;
-extern struct dom_string *corestring_dom_input;
-extern struct dom_string *corestring_dom_invalid;
-extern struct dom_string *corestring_dom_keydown;
-extern struct dom_string *corestring_dom_keypress;
-extern struct dom_string *corestring_dom_keyup;
-extern struct dom_string *corestring_dom_link;
-extern struct dom_string *corestring_dom_load;
-extern struct dom_string *corestring_dom_loadeddata;
-extern struct dom_string *corestring_dom_loadedmetadata;
-extern struct dom_string *corestring_dom_loadstart;
-extern struct dom_string *corestring_dom_map;
-extern struct dom_string *corestring_dom_marginheight;
-extern struct dom_string *corestring_dom_marginwidth;
-extern struct dom_string *corestring_dom_media;
-extern struct dom_string *corestring_dom_message;
-extern struct dom_string *corestring_dom_mousedown;
-extern struct dom_string *corestring_dom_mousemove;
-extern struct dom_string *corestring_dom_mouseout;
-extern struct dom_string *corestring_dom_mouseover;
-extern struct dom_string *corestring_dom_mouseup;
-extern struct dom_string *corestring_dom_mousewheel;
-extern struct dom_string *corestring_dom_name;
-extern struct dom_string *corestring_dom_nohref;
-extern struct dom_string *corestring_dom_noresize;
-extern struct dom_string *corestring_dom_nowrap;
-extern struct dom_string *corestring_dom_offline;
-extern struct dom_string *corestring_dom_online;
-extern struct dom_string *corestring_dom_pagehide;
-extern struct dom_string *corestring_dom_pageshow;
-extern struct dom_string *corestring_dom_pause;
-extern struct dom_string *corestring_dom_play;
-extern struct dom_string *corestring_dom_playing;
-extern struct dom_string *corestring_dom_popstate;
-extern struct dom_string *corestring_dom_progress;
-extern struct dom_string *corestring_dom_ratechange;
-extern struct dom_string *corestring_dom_readystatechange;
-extern struct dom_string *corestring_dom_rect;
-extern struct dom_string *corestring_dom_rel;
-extern struct dom_string *corestring_dom_reset;
-extern struct dom_string *corestring_dom_resize;
-extern struct dom_string *corestring_dom_rows;
-extern struct dom_string *corestring_dom_rowspan;
-extern struct dom_string *corestring_dom_scroll;
-extern struct dom_string *corestring_dom_scrolling;
-extern struct dom_string *corestring_dom_seeked;
-extern struct dom_string *corestring_dom_seeking;
-extern struct dom_string *corestring_dom_select;
-extern struct dom_string *corestring_dom_selected;
-extern struct dom_string *corestring_dom_shape;
-extern struct dom_string *corestring_dom_show;
-extern struct dom_string *corestring_dom_size;
-extern struct dom_string *corestring_dom_sizes;
-extern struct dom_string *corestring_dom_src;
-extern struct dom_string *corestring_dom_stalled;
-extern struct dom_string *corestring_dom_storage;
-extern struct dom_string *corestring_dom_style;
-extern struct dom_string *corestring_dom_submit;
-extern struct dom_string *corestring_dom_suspend;
-extern struct dom_string *corestring_dom_target;
-extern struct dom_string *corestring_dom_text;
-extern struct dom_string *corestring_dom_text_javascript; /* text/javascript */
-extern struct dom_string *corestring_dom_timeupdate;
-extern struct dom_string *corestring_dom_title;
-extern struct dom_string *corestring_dom_type;
-extern struct dom_string *corestring_dom_unload;
-extern struct dom_string *corestring_dom_valign;
-extern struct dom_string *corestring_dom_value;
-extern struct dom_string *corestring_dom_vlink;
-extern struct dom_string *corestring_dom_volumechange;
-extern struct dom_string *corestring_dom_vspace;
-extern struct dom_string *corestring_dom_waiting;
-extern struct dom_string *corestring_dom_width;
-/* DOM node types */
-extern struct dom_string *corestring_dom_BUTTON;
-extern struct dom_string *corestring_dom_INPUT;
-extern struct dom_string *corestring_dom_SELECT;
-extern struct dom_string *corestring_dom_TEXTAREA;
-extern struct dom_string *corestring_dom_BODY;
-extern struct dom_string *corestring_dom_HEAD;
-/* DOM namespaces */
-extern struct dom_string *corestring_dom_html_namespace;
-/* DOM input node types */
-extern struct dom_string *corestring_dom_button;
-/* extern struct dom_string *corestring_dom_submit; */
-/* extern struct dom_string *corestring_dom_reset; */
-extern struct dom_string *corestring_dom_image;
-extern struct dom_string *corestring_dom_radio;
-extern struct dom_string *corestring_dom_checkbox;
-extern struct dom_string *corestring_dom_file;
-/* Event prefix */
-extern struct dom_string *corestring_dom_on;
-/* These are the event attributes which forward from body to window */
-extern struct dom_string *corestring_dom_onblur;
-extern struct dom_string *corestring_dom_onerror;
-extern struct dom_string *corestring_dom_onfocus;
-extern struct dom_string *corestring_dom_onload;
-extern struct dom_string *corestring_dom_onresize;
-extern struct dom_string *corestring_dom_onscroll;
-/* Corestrings used by DOM event registration */
-extern struct dom_string *corestring_dom_autocomplete;
-extern struct dom_string *corestring_dom_autocompleteerror;
-extern struct dom_string *corestring_dom_dragexit;
-extern struct dom_string *corestring_dom_mouseenter;
-extern struct dom_string *corestring_dom_mouseleave;
-extern struct dom_string *corestring_dom_wheel;
-extern struct dom_string *corestring_dom_sort;
-extern struct dom_string *corestring_dom_toggle;
-/* DOM userdata keys */
-extern struct dom_string *corestring_dom___ns_key_box_node_data;
-extern struct dom_string *corestring_dom___ns_key_libcss_node_data;
-extern struct dom_string *corestring_dom___ns_key_file_name_node_data;
-extern struct dom_string *corestring_dom___ns_key_image_coords_node_data;
-extern struct dom_string *corestring_dom___ns_key_html_content_data;
-
-/* URLs */
-extern struct nsurl *corestring_nsurl_about_blank;
+/* declare corestrings */
+#define CORESTRING_LWC_VALUE(NAME,VALUE) \
+ extern lwc_string *corestring_lwc_##NAME
+#define CORESTRING_DOM_VALUE(NAME,VALUE) \
+ extern struct dom_string *corestring_dom_##NAME
+#define CORESTRING_NSURL(NAME,VALUE) \
+ extern struct nsurl *corestring_nsurl_##NAME
+#include "utils/corestringlist.h"
+#undef CORESTRING_LWC_VALUE
+#undef CORESTRING_DOM_VALUE
+#undef CORESTRING_NSURL
#endif
diff --git a/utils/errors.h b/utils/errors.h
index b9e157c66..9a0a9bc04 100644
--- a/utils/errors.h
+++ b/utils/errors.h
@@ -27,58 +27,37 @@
* Enumeration of error codes
*/
typedef enum {
- NSERROR_OK, /**< No error */
-
- NSERROR_UNKNOWN, /**< Unknown error - DO *NOT* USE */
-
- NSERROR_NOMEM, /**< Memory exhaustion */
-
- NSERROR_NO_FETCH_HANDLER, /**< No fetch handler for URL scheme */
-
- NSERROR_NOT_FOUND, /**< Requested item not found */
-
- NSERROR_NOT_DIRECTORY, /**< Missing directory */
-
- NSERROR_SAVE_FAILED, /**< Failed to save data */
-
- NSERROR_CLONE_FAILED, /**< Failed to clone handle */
-
- NSERROR_INIT_FAILED, /**< Initialisation failed */
-
- NSERROR_MNG_ERROR, /**< An MNG error occurred */
-
- NSERROR_BAD_ENCODING, /**< The character set is unknown */
-
- NSERROR_NEED_DATA, /**< More data needed */
-
- NSERROR_ENCODING_CHANGE, /**< The character changed */
-
- NSERROR_BAD_PARAMETER, /**< Bad Parameter */
-
- NSERROR_INVALID, /**< Invalid data */
-
- NSERROR_BOX_CONVERT, /**< Box conversion failed */
-
- NSERROR_STOPPED, /**< Content conversion stopped */
-
- NSERROR_DOM, /**< DOM call returned error */
-
- NSERROR_CSS, /**< CSS call returned error */
-
+ NSERROR_OK, /**< No error */
+ NSERROR_UNKNOWN, /**< Unknown error - DO *NOT* USE */
+ NSERROR_NOMEM, /**< Memory exhaustion */
+ NSERROR_NO_FETCH_HANDLER, /**< No fetch handler for URL scheme */
+ NSERROR_NOT_FOUND, /**< Requested item not found */
+ NSERROR_NOT_DIRECTORY, /**< Missing directory */
+ NSERROR_SAVE_FAILED, /**< Failed to save data */
+ NSERROR_CLONE_FAILED, /**< Failed to clone handle */
+ NSERROR_INIT_FAILED, /**< Initialisation failed */
+ NSERROR_BMP_ERROR, /**< A BMP error occurred */
+ NSERROR_GIF_ERROR, /**< A GIF error occurred */
+ NSERROR_ICO_ERROR, /**< A ICO error occurred */
+ NSERROR_PNG_ERROR, /**< A PNG error occurred */
+ NSERROR_SPRITE_ERROR, /**< A RISC OS Sprite error occurred */
+ NSERROR_SVG_ERROR, /**< A SVG error occurred */
+ NSERROR_BAD_ENCODING, /**< The character set is unknown */
+ NSERROR_NEED_DATA, /**< More data needed */
+ NSERROR_ENCODING_CHANGE, /**< The character changed */
+ NSERROR_BAD_PARAMETER, /**< Bad Parameter */
+ NSERROR_INVALID, /**< Invalid data */
+ NSERROR_BOX_CONVERT, /**< Box conversion failed */
+ NSERROR_STOPPED, /**< Content conversion stopped */
+ NSERROR_DOM, /**< DOM call returned error */
+ NSERROR_CSS, /**< CSS call returned error */
NSERROR_CSS_BASE, /**< CSS base sheet failed */
-
- NSERROR_BAD_URL, /**< Bad URL */
-
- NSERROR_BAD_CONTENT, /**< Bad Content */
-
+ NSERROR_BAD_URL, /**< Bad URL */
+ NSERROR_BAD_CONTENT, /**< Bad Content */
NSERROR_FRAME_DEPTH, /**< Exceeded frame depth */
-
NSERROR_PERMISSION, /**< Permission error */
-
- NSERROR_NOSPACE, /**< Insufficient space */
-
+ NSERROR_NOSPACE, /**< Insufficient space */
NSERROR_BAD_SIZE, /**< Bad size */
-
NSERROR_NOT_IMPLEMENTED, /**< Functionality is not implemented */
} nserror;
diff --git a/utils/filename.c b/utils/filename.c
index 9c95901a1..f0e1bb0f5 100644
--- a/utils/filename.c
+++ b/utils/filename.c
@@ -84,7 +84,8 @@ const char *filename_request(void)
/* no available slots - create a new directory */
dir = filename_create_directory(NULL);
if (dir == NULL) {
- LOG("Failed to create a new directory.");
+ NSLOG(netsurf, INFO,
+ "Failed to create a new directory.");
return NULL;
}
i = 63;
@@ -182,10 +183,12 @@ bool filename_initialise(void)
for (start = directory; *start != '\0'; start++) {
if (*start == '/') {
*start = '\0';
- LOG("Creating \"%s\"", directory);
+ NSLOG(netsurf, INFO, "Creating \"%s\"", directory);
ret = nsmkdir(directory, S_IRWXU);
if (ret != 0 && errno != EEXIST) {
- LOG("Failed to create directory \"%s\"", directory);
+ NSLOG(netsurf, INFO,
+ "Failed to create directory \"%s\"",
+ directory);
free(directory);
return false;
}
@@ -194,7 +197,7 @@ bool filename_initialise(void)
}
}
- LOG("Temporary directory location: %s", directory);
+ NSLOG(netsurf, INFO, "Temporary directory location: %s", directory);
ret = nsmkdir(directory, S_IRWXU);
free(directory);
@@ -269,18 +272,23 @@ bool filename_flush_directory(const char *folder, int depth)
parent = opendir(folder);
while ((entry = readdir(parent))) {
- struct stat statbuf;
+ int written;
+ struct stat statbuf;
/* Ignore '.' and '..' */
if (strcmp(entry->d_name, ".") == 0 ||
strcmp(entry->d_name, "..") == 0)
continue;
- snprintf(child, sizeof(child), "%s/%s", folder, entry->d_name);
- child[sizeof(child) - 1] = '\0';
+ written = snprintf(child, sizeof(child), "%s/%s",
+ folder, entry->d_name);
+ if (written == sizeof(child)) {
+ child[sizeof(child) - 1] = '\0';
+ }
if (stat(child, &statbuf) == -1) {
- LOG("Unable to stat %s: %s", child, strerror(errno));
+ NSLOG(netsurf, INFO, "Unable to stat %s: %s", child,
+ strerror(errno));
continue;
}
@@ -348,7 +356,8 @@ bool filename_flush_directory(const char *folder, int depth)
filename_delete_recursive(child);
if (remove(child))
- LOG("Failed to remove '%s'", child);
+ NSLOG(netsurf, INFO, "Failed to remove '%s'",
+ child);
else
changed = true;
} else {
@@ -378,16 +387,22 @@ bool filename_delete_recursive(char *folder)
parent = opendir(folder);
while ((entry = readdir(parent))) {
+ int written;
+
/* Ignore '.' and '..' */
if (strcmp(entry->d_name, ".") == 0 ||
strcmp(entry->d_name, "..") == 0)
continue;
- snprintf(child, sizeof(child), "%s/%s", folder, entry->d_name);
- child[sizeof(child) - 1] = '\0';
+ written = snprintf(child, sizeof(child), "%s/%s",
+ folder, entry->d_name);
+ if (written == sizeof(child)) {
+ child[sizeof(child) - 1] = '\0';
+ }
if (stat(child, &statbuf) == -1) {
- LOG("Unable to stat %s: %s", child, strerror(errno));
+ NSLOG(netsurf, INFO, "Unable to stat %s: %s", child,
+ strerror(errno));
continue;
}
@@ -399,7 +414,7 @@ bool filename_delete_recursive(char *folder)
}
if (remove(child)) {
- LOG("Failed to remove '%s'", child);
+ NSLOG(netsurf, INFO, "Failed to remove '%s'", child);
closedir(parent);
return false;
}
@@ -465,7 +480,7 @@ static struct directory *filename_create_directory(const char *prefix)
/* allocate a new directory */
new_dir = malloc(sizeof(struct directory));
if (new_dir == NULL) {
- LOG("No memory for malloc()");
+ NSLOG(netsurf, INFO, "No memory for malloc()");
return NULL;
}
@@ -499,7 +514,9 @@ static struct directory *filename_create_directory(const char *prefix)
* whilst we are running if there is an error, so we
* don't report this yet and try to create the
* structure normally. */
- LOG("Failed to create optimised structure '%s'", filename_directory);
+ NSLOG(netsurf, INFO,
+ "Failed to create optimised structure '%s'",
+ filename_directory);
}
}
@@ -519,7 +536,9 @@ static struct directory *filename_create_directory(const char *prefix)
if (!is_dir(filename_directory)) {
if (nsmkdir(filename_directory, S_IRWXU)) {
- LOG("Failed to create directory '%s'", filename_directory);
+ NSLOG(netsurf, INFO,
+ "Failed to create directory '%s'",
+ filename_directory);
return NULL;
}
}
diff --git a/utils/hashtable.c b/utils/hashtable.c
index af100dfc9..4935d6b3f 100644
--- a/utils/hashtable.c
+++ b/utils/hashtable.c
@@ -28,11 +28,15 @@
* it that has good coverage along side the other tests.
*/
+#include <stdint.h>
+#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
-#include <stdbool.h>
-#include "utils/hashtable.h"
+#include <zlib.h>
+#include <errno.h>
+
#include "utils/log.h"
+#include "utils/hashtable.h"
struct hash_entry {
@@ -46,6 +50,8 @@ struct hash_table {
struct hash_entry **chain;
};
+/** maximum length of line for file or inline add */
+#define LINE_BUFFER_SIZE 512
/**
* Hash a string, returning a 32bit value. The hash algorithm used is
@@ -75,13 +81,182 @@ static inline unsigned int hash_string_fnv(const char *datum, unsigned int *len)
}
+
+/**
+ * process a line of input.
+ *
+ * \param hash The hash table to add the line to
+ * \param ln The line to process
+ * \param lnlen The length of \ln
+ * \return NSERROR_OK on success else NSERROR_INVALID
+ */
+static nserror
+process_line(struct hash_table *hash, uint8_t *ln, int lnlen)
+{
+ uint8_t *key;
+ uint8_t *value;
+ uint8_t *colon;
+
+ key = ln; /* set key to start of line */
+ value = ln + lnlen; /* set value to end of line */
+
+ /* skip leading whitespace */
+ while ((key < value) &&
+ ((*key == ' ') || (*key == '\t'))) {
+ key++;
+ }
+
+ /* empty or comment lines */
+ if ((*key == 0) || (*key == '#')) {
+ return NSERROR_OK;
+ }
+
+ /* find first colon as key/value separator */
+ for (colon = key; colon < value; colon++) {
+ if (*colon == ':') {
+ break;
+ }
+ }
+ if (colon == value) {
+ /* no colon found */
+ return NSERROR_INVALID;
+ }
+
+ *colon = 0; /* terminate key */
+ value = colon + 1;
+
+ if (hash_add(hash, (char *)key, (char *)value) == false) {
+ NSLOG(netsurf, INFO,
+ "Unable to add %s:%s to hash table", ln, value);
+ return NSERROR_INVALID;
+ }
+ return NSERROR_OK;
+}
+
+
+/**
+ * adds key/value pairs to a hash from a memory area
+ */
+static nserror
+hash_add_inline_plain(struct hash_table *ht, const uint8_t *data, size_t size)
+{
+ uint8_t s[LINE_BUFFER_SIZE]; /* line buffer */
+ unsigned int slen = 0;
+ nserror res = NSERROR_OK;
+
+ while (size > 0) {
+ s[slen] = *data;
+
+ if (s[slen] == '\n') {
+ s[slen] = 0; /* replace newline with null termination */
+ res = process_line(ht, s, slen);
+ slen = 0;
+ if (res != NSERROR_OK) {
+ break;
+ }
+ } else {
+ slen++;
+ if (slen > sizeof s) {
+ NSLOG(netsurf, INFO, "Overlength line\n");
+ slen = 0;
+ }
+ }
+
+ size--;
+ data++;
+ }
+ if (slen > 0) {
+ s[slen] = 0;
+ res = process_line(ht, s, slen);
+ }
+
+ return res;
+}
+
+/**
+ * adds key/value pairs to a hash from a compressed memory area
+ */
+static nserror
+hash_add_inline_gzip(struct hash_table *ht, const uint8_t *data, size_t size)
+{
+ nserror res;
+ int ret; /* zlib return value */
+ z_stream strm;
+ uint8_t s[LINE_BUFFER_SIZE]; /* line buffer */
+ size_t used = 0; /* number of bytes in buffer in use */
+ uint8_t *nl;
+
+ strm.zalloc = Z_NULL;
+ strm.zfree = Z_NULL;
+ strm.opaque = Z_NULL;
+
+ strm.next_in = (uint8_t *)data;
+ strm.avail_in = size;
+
+ ret = inflateInit2(&strm, 32 + MAX_WBITS);
+ if (ret != Z_OK) {
+ NSLOG(netsurf, INFO, "inflateInit returned %d", ret);
+ return NSERROR_INVALID;
+ }
+
+ do {
+ strm.next_out = s + used;
+ strm.avail_out = sizeof(s) - used;
+
+ ret = inflate(&strm, Z_NO_FLUSH);
+ if ((ret != Z_OK) && (ret != Z_STREAM_END)) {
+ break;
+ }
+
+ used = sizeof(s) - strm.avail_out;
+ while (used > 0) {
+ /* find nl */
+ for (nl = &s[0]; nl < &s[used]; nl++) {
+ if (*nl == '\n') {
+ break;
+ }
+ }
+ if (nl == &s[used]) {
+ /* no nl found */
+ break;
+ }
+ /* found newline */
+ *nl = 0; /* null terminate line */
+ res = process_line(ht, &s[0], nl - &s[0]);
+ if (res != NSERROR_OK) {
+ inflateEnd(&strm);
+ return res;
+ }
+
+ /* move data down */
+ memmove(&s[0], nl + 1, used - ((nl + 1) - &s[0]) );
+ used -= ((nl +1) - &s[0]);
+ }
+ if (used == sizeof(s)) {
+ /* entire buffer used and no newline */
+ NSLOG(netsurf, INFO, "Overlength line");
+ used = 0;
+ }
+ } while (ret != Z_STREAM_END);
+
+ inflateEnd(&strm);
+
+ if (ret != Z_STREAM_END) {
+ NSLOG(netsurf, INFO, "inflate returned %d", ret);
+ return NSERROR_INVALID;
+ }
+ return NSERROR_OK;
+
+}
+
+
/* exported interface documented in utils/hashtable.h */
struct hash_table *hash_create(unsigned int chains)
{
struct hash_table *r = malloc(sizeof(struct hash_table));
if (r == NULL) {
- LOG("Not enough memory for hash table.");
+ NSLOG(netsurf, INFO, "Not enough memory for hash table.");
return NULL;
}
@@ -89,7 +264,8 @@ struct hash_table *hash_create(unsigned int chains)
r->chain = calloc(chains, sizeof(struct hash_entry *));
if (r->chain == NULL) {
- LOG("Not enough memory for %d hash table chains.", chains);
+ NSLOG(netsurf, INFO,
+ "Not enough memory for %d hash table chains.", chains);
free(r);
return NULL;
}
@@ -134,7 +310,7 @@ bool hash_add(struct hash_table *ht, const char *key, const char *value)
e = malloc(sizeof(struct hash_entry));
if (e == NULL) {
- LOG("Not enough memory for hash entry.");
+ NSLOG(netsurf, INFO, "Not enough memory for hash entry.");
return false;
}
@@ -144,7 +320,8 @@ bool hash_add(struct hash_table *ht, const char *key, const char *value)
v = strlen(value) ;
e->pairing = malloc(v + e->key_length + 2);
if (e->pairing == NULL) {
- LOG("Not enough memory for string duplication.");
+ NSLOG(netsurf, INFO,
+ "Not enough memory for string duplication.");
free(e);
return false;
}
@@ -177,3 +354,51 @@ const char *hash_get(struct hash_table *ht, const char *key)
return NULL;
}
+
+
+
+/* exported interface documented in utils/hashtable.h */
+nserror hash_add_file(struct hash_table *ht, const char *path)
+{
+ nserror res = NSERROR_OK;
+ char s[LINE_BUFFER_SIZE]; /* line buffer */
+ gzFile fp; /* compressed file handle */
+
+ if (path == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ fp = gzopen(path, "r");
+ if (!fp) {
+ NSLOG(netsurf, INFO,
+ "Unable to open file \"%.100s\": %s", path,
+ strerror(errno));
+
+ return NSERROR_NOT_FOUND;
+ }
+
+ while (gzgets(fp, s, sizeof s)) {
+ int slen = strlen(s);
+ s[--slen] = 0; /* remove \n at end */
+
+ res = process_line(ht, (uint8_t *)s, slen);
+ if (res != NSERROR_OK) {
+ break;
+ }
+ }
+
+ gzclose(fp);
+
+ return res;
+}
+
+
+/* exported interface documented in utils/hashtable.h */
+nserror hash_add_inline(struct hash_table *ht, const uint8_t *data, size_t size)
+{
+ if ((data[0]==0x1f) && (data[1] == 0x8b)) {
+ /* gzip header detected */
+ return hash_add_inline_gzip(ht, data, size);
+ }
+ return hash_add_inline_plain(ht, data, size);
+}
diff --git a/utils/hashtable.h b/utils/hashtable.h
index b0e7392c6..b1c0d5c41 100644
--- a/utils/hashtable.h
+++ b/utils/hashtable.h
@@ -29,8 +29,11 @@
struct hash_table;
/**
- * Create a new hash table, and return a context for it. The memory consumption
- * of a hash table is approximately 8 + (nchains * 12) bytes if it is empty.
+ * Create a new hash table
+ *
+ * Allocate a new hash table and return a context for it. The memory
+ * consumption of a hash table is approximately 8 + (nchains * 12)
+ * bytes if it is empty.
*
* \param chains Number of chains/buckets this hash table will have. This
* should be a prime number, and ideally a prime number just
@@ -41,18 +44,22 @@ struct hash_table;
struct hash_table *hash_create(unsigned int chains);
/**
- * Destroys a hash table, freeing all memory associated with it.
+ * Destroys a hash table
+ *
+ * Destroy a hash table freeing all memory associated with it.
*
* \param ht Hash table to destroy. After the function returns, this
- * will nolonger be valid.
+ * will no longer be valid.
*/
void hash_destroy(struct hash_table *ht);
/**
- * Adds a key/value pair to a hash table. If the key you're adding is already
- * in the hash table, it does not replace it, but it does take precedent over
- * it. The old key/value pair will be inaccessable but still in memory until
- * hash_destroy() is called on the hash table.
+ * Adds a key/value pair to a hash table.
+ *
+ * If the key you're adding is already in the hash table, it does not
+ * replace it, but it does take precedent over it. The old key/value
+ * pair will be inaccessable but still in memory until hash_destroy()
+ * is called on the hash table.
*
* \param ht The hash table context to add the key/value pair to.
* \param key The key to associate the value with. A copy is made.
@@ -71,4 +78,34 @@ bool hash_add(struct hash_table *ht, const char *key, const char *value);
*/
const char *hash_get(struct hash_table *ht, const char *key);
+/**
+ * Add key/value pairs to a hash table with data from a file
+ *
+ * The file should be formatted as a series of lines terminated with
+ * newline character. Each line should contain a key/value pair
+ * separated by a colon. If a line is empty or starts with a #
+ * character it will be ignored.
+ *
+ * The file may be optionally gzip compressed.
+ *
+ * \param ht The hash table context to add the key/value pairs to.
+ * \param path Path to file with key/value pairs in.
+ * \return NSERROR_OK on success else error code
+ */
+nserror hash_add_file(struct hash_table *ht, const char *path);
+
+/**
+ * Add key/value pairs to a hash table with data from a memory buffer
+ *
+ * The data format is the same as in hash_add_file() but held in memory
+ *
+ * The data may optionally be gzip compressed.
+ *
+ * \param ht The hash table context to add the key/value pairs to.
+ * \param data Source of key/value pairs
+ * \param size length of \a data
+ * \return NSERROR_OK on success else error code
+ */
+nserror hash_add_inline(struct hash_table *ht, const uint8_t *data, size_t size);
+
#endif
diff --git a/utils/http.h b/utils/http.h
index 173604fb4..00caf8954 100644
--- a/utils/http.h
+++ b/utils/http.h
@@ -29,6 +29,7 @@
#include "utils/http/content-disposition.h"
#include "utils/http/content-type.h"
+#include "utils/http/strict-transport-security.h"
#include "utils/http/www-authenticate.h"
#endif
diff --git a/utils/http/Makefile b/utils/http/Makefile
index 198588bd4..f3bb765f0 100644
--- a/utils/http/Makefile
+++ b/utils/http/Makefile
@@ -1,6 +1,7 @@
# http utils sources
S_HTTP := challenge.c generics.c primitives.c parameter.c \
- content-disposition.c content-type.c www-authenticate.c
+ content-disposition.c content-type.c \
+ strict-transport-security.c www-authenticate.c
-S_HTTP := $(addprefix utils/http/,$(S_HTTP)) \ No newline at end of file
+S_HTTP := $(addprefix utils/http/,$(S_HTTP))
diff --git a/utils/http/challenge.c b/utils/http/challenge.c
index 578532e97..9b85fccbc 100644
--- a/utils/http/challenge.c
+++ b/utils/http/challenge.c
@@ -92,7 +92,7 @@ nserror http__parse_challenge(const char **input, http_challenge **challenge)
http__skip_LWS(&pos);
if (*pos == ',') {
- error = http__item_list_parse(&pos,
+ error = http__item_list_parse(&pos,
http__parse_parameter, first, &params);
if (error != NSERROR_OK && error != NSERROR_NOT_FOUND) {
lwc_string_unref(scheme);
diff --git a/utils/http/content-disposition.c b/utils/http/content-disposition.c
index 5d5e94c26..03bd12bd3 100644
--- a/utils/http/content-disposition.c
+++ b/utils/http/content-disposition.c
@@ -45,7 +45,7 @@ nserror http_parse_content_disposition(const char *header_value,
http__skip_LWS(&pos);
if (*pos == ';') {
- error = http__item_list_parse(&pos,
+ error = http__item_list_parse(&pos,
http__parse_parameter, NULL, &params);
if (error != NSERROR_OK && error != NSERROR_NOT_FOUND) {
lwc_string_unref(mtype);
diff --git a/utils/http/content-type.c b/utils/http/content-type.c
index f84da8c8e..d4279f512 100644
--- a/utils/http/content-type.c
+++ b/utils/http/content-type.c
@@ -68,7 +68,7 @@ nserror http_parse_content_type(const char *header_value,
http__skip_LWS(&pos);
if (*pos == ';') {
- error = http__item_list_parse(&pos,
+ error = http__item_list_parse(&pos,
http__parse_parameter, NULL, &params);
if (error != NSERROR_OK && error != NSERROR_NOT_FOUND) {
lwc_string_unref(subtype);
diff --git a/utils/http/generics.h b/utils/http/generics.h
index 8c391c4af..a5af73458 100644
--- a/utils/http/generics.h
+++ b/utils/http/generics.h
@@ -19,6 +19,8 @@
#ifndef NETSURF_UTILS_HTTP_GENERICS_H_
#define NETSURF_UTILS_HTTP_GENERICS_H_
+#include <stdbool.h>
+
#include "utils/errors.h"
/**
diff --git a/utils/http/strict-transport-security.c b/utils/http/strict-transport-security.c
new file mode 100644
index 000000000..9de610c73
--- /dev/null
+++ b/utils/http/strict-transport-security.c
@@ -0,0 +1,341 @@
+/*
+ * Copyright 2018 John-Mark Bell <jmb@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/>.
+ */
+
+#include <limits.h>
+#include <stdlib.h>
+
+#include "utils/corestrings.h"
+#include "utils/http.h"
+
+#include "utils/http/generics.h"
+#include "utils/http/primitives.h"
+
+/**
+ * Representation of a Strict-Transport-Security
+ */
+struct http_strict_transport_security {
+ uint32_t max_age; /**< Max age (delta seconds) */
+ bool include_sub_domains; /**< Whether subdomains are included */
+};
+
+/**
+ * Representation of a directive
+ */
+typedef struct http_directive {
+ http__item base;
+
+ lwc_string *name; /**< Parameter name */
+ lwc_string *value; /**< Parameter value (optional) */
+} http_directive;
+
+
+static void http_destroy_directive(http_directive *self)
+{
+ lwc_string_unref(self->name);
+ if (self->value != NULL) {
+ lwc_string_unref(self->value);
+ }
+ free(self);
+}
+
+static nserror http__parse_directive(const char **input,
+ http_directive **result)
+{
+ const char *pos = *input;
+ lwc_string *name;
+ lwc_string *value = NULL;
+ http_directive *directive;
+ nserror error;
+
+ /* token [ "=" ( token | quoted-string ) ] */
+
+ error = http__parse_token(&pos, &name);
+ if (error != NSERROR_OK)
+ return error;
+
+ http__skip_LWS(&pos);
+
+ if (*pos == '=') {
+ pos++;
+
+ http__skip_LWS(&pos);
+
+ if (*pos == '"')
+ error = http__parse_quoted_string(&pos, &value);
+ else
+ error = http__parse_token(&pos, &value);
+
+ if (error != NSERROR_OK) {
+ lwc_string_unref(name);
+ return error;
+ }
+ }
+
+ directive = malloc(sizeof(*directive));
+ if (directive == NULL) {
+ if (value != NULL) {
+ lwc_string_unref(value);
+ }
+ lwc_string_unref(name);
+ return NSERROR_NOMEM;
+ }
+
+ HTTP__ITEM_INIT(directive, NULL, http_destroy_directive);
+ directive->name = name;
+ directive->value = value;
+
+ *result = directive;
+ *input = pos;
+
+ return NSERROR_OK;
+}
+
+static void http_directive_list_destroy(http_directive *list)
+{
+ http__item_list_destroy(list);
+}
+
+static nserror http_directive_list_find_item(const http_directive *list,
+ lwc_string *name, lwc_string **value)
+{
+ bool match;
+
+ while (list != NULL) {
+ if (lwc_string_caseless_isequal(name, list->name,
+ &match) == lwc_error_ok && match)
+ break;
+
+ list = (http_directive *) list->base.next;
+ }
+
+ if (list == NULL)
+ return NSERROR_NOT_FOUND;
+
+ if (list->value != NULL) {
+ *value = lwc_string_ref(list->value);
+ } else {
+ *value = NULL;
+ }
+
+ return NSERROR_OK;
+}
+
+static const http_directive *http_directive_list_iterate(
+ const http_directive *cur,
+ lwc_string **name, lwc_string **value)
+{
+ if (cur == NULL)
+ return NULL;
+
+ *name = lwc_string_ref(cur->name);
+ if (cur->value != NULL) {
+ *value = lwc_string_ref(cur->value);
+ } else {
+ *value = NULL;
+ }
+
+ return (http_directive *) cur->base.next;
+}
+
+static uint32_t count(const http_directive *list, lwc_string *key)
+{
+ uint32_t count = 0;
+ bool match;
+
+ while (list != NULL) {
+ if (lwc_string_caseless_isequal(key, list->name,
+ &match) == lwc_error_ok && match) {
+ count++;
+ }
+
+ list = (http_directive *) list->base.next;
+ }
+
+ return count;
+}
+
+static bool check_duplicates(const http_directive *directives)
+{
+ bool result = true;
+ const http_directive *key = directives;
+
+ if (key == NULL) {
+ /* No directives, so there can't be any duplicates */
+ return true;
+ }
+
+ do {
+ lwc_string *name = NULL, *value = NULL;
+
+ key = http_directive_list_iterate(key, &name, &value);
+
+ result &= (count(directives, name) == 1);
+
+ lwc_string_unref(name);
+ if (value != NULL) {
+ lwc_string_unref(value);
+ }
+ } while (key != NULL);
+
+ return result;
+}
+
+static nserror parse_max_age(lwc_string *value, uint32_t *result)
+{
+ const char *pos = lwc_string_data(value);
+ const char *end = pos + lwc_string_length(value);
+ uint32_t val = 0;
+
+ /* 1*DIGIT */
+
+ if (pos == end) {
+ /* Blank value */
+ return NSERROR_NOT_FOUND;
+ }
+
+ while (pos < end) {
+ if ('0' <= *pos && *pos <= '9') {
+ uint32_t nv = val * 10 + (*pos - '0');
+ if (nv < val) {
+ val = UINT_MAX;
+ } else {
+ val = nv;
+ }
+ } else {
+ /* Non-digit */
+ return NSERROR_NOT_FOUND;
+ }
+
+ pos++;
+ }
+
+ *result = val;
+
+ return NSERROR_OK;
+}
+
+/* See strict-transport-security.h for documentation */
+nserror http_parse_strict_transport_security(const char *header_value,
+ http_strict_transport_security **result)
+{
+ const char *pos = header_value;
+ http_strict_transport_security *sts;
+ http_directive *first = NULL;
+ http_directive *directives = NULL;
+ lwc_string *max_age_str = NULL, *isd_str = NULL;
+ uint32_t max_age;
+ bool include_sub_domains = false;
+ nserror error;
+
+ /* directive *( ";" directive ) */
+
+ http__skip_LWS(&pos);
+
+ error = http__parse_directive(&pos, &first);
+ if (error != NSERROR_OK) {
+ return error;
+ }
+
+ http__skip_LWS(&pos);
+
+ if (*pos == ';') {
+ error = http__item_list_parse(&pos,
+ http__parse_directive, first, &directives);
+ if (error != NSERROR_OK) {
+ if (directives != NULL) {
+ http_directive_list_destroy(directives);
+ }
+ return error;
+ }
+ } else {
+ directives = first;
+ }
+
+ /* Each directive must only appear once */
+ if (check_duplicates(directives) == false) {
+ http_directive_list_destroy(directives);
+ return NSERROR_NOT_FOUND;
+ }
+
+ /* max-age is required */
+ error = http_directive_list_find_item(directives,
+ corestring_lwc_max_age, &max_age_str);
+ if (error != NSERROR_OK || max_age_str == NULL) {
+ http_directive_list_destroy(directives);
+ return NSERROR_NOT_FOUND;
+ }
+
+ error = parse_max_age(max_age_str, &max_age);
+ if (error != NSERROR_OK) {
+ lwc_string_unref(max_age_str);
+ http_directive_list_destroy(directives);
+ return NSERROR_NOT_FOUND;
+ }
+ lwc_string_unref(max_age_str);
+
+ /* includeSubDomains is optional and valueless */
+ error = http_directive_list_find_item(directives,
+ corestring_lwc_includesubdomains, &isd_str);
+ if (error != NSERROR_OK && error != NSERROR_NOT_FOUND) {
+ http_directive_list_destroy(directives);
+ return NSERROR_NOT_FOUND;
+ } else if (error == NSERROR_OK) {
+ if (isd_str != NULL) {
+ /* Present, but not valueless: invalid */
+ lwc_string_unref(isd_str);
+ http_directive_list_destroy(directives);
+ return NSERROR_NOT_FOUND;
+ }
+ include_sub_domains = true;
+ }
+ http_directive_list_destroy(directives);
+
+ sts = malloc(sizeof(*sts));
+ if (sts == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ sts->max_age = max_age;
+ sts->include_sub_domains = include_sub_domains;
+
+ *result = sts;
+
+ return NSERROR_OK;
+}
+
+/* See strict-transport-security.h for documentation */
+void http_strict_transport_security_destroy(
+ http_strict_transport_security *victim)
+{
+ free(victim);
+}
+
+/* See strict-transport-security.h for documentation */
+uint32_t http_strict_transport_security_max_age(
+ http_strict_transport_security *sts)
+{
+ return sts->max_age;
+}
+
+/* See strict-transport-security.h for documentation */
+bool http_strict_transport_security_include_subdomains(
+ http_strict_transport_security *sts)
+{
+ return sts->include_sub_domains;
+}
+
diff --git a/utils/http/strict-transport-security.h b/utils/http/strict-transport-security.h
new file mode 100644
index 000000000..4e52419fc
--- /dev/null
+++ b/utils/http/strict-transport-security.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2018 John-Mark Bell <jmb@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_HTTP_STRICT_TRANSPORT_SECURITY_H_
+#define NETSURF_UTILS_HTTP_STRICT_TRANSPORT_SECURITY_H_
+
+#include <libwapcaplet/libwapcaplet.h>
+
+typedef struct http_strict_transport_security http_strict_transport_security;
+
+/**
+ * Parse an HTTP Strict-Transport-Security header value
+ *
+ * \param header_value Header value to parse
+ * \param result Pointer to location to receive result
+ * \return NSERROR_OK on success,
+ * NSERROR_NOMEM on memory exhaustion,
+ * appropriate error otherwise
+ */
+nserror http_parse_strict_transport_security(const char *header_value,
+ http_strict_transport_security **result);
+
+/**
+ * Destroy a strict transport security object
+ *
+ * \param victim Object to destroy
+ */
+void http_strict_transport_security_destroy(
+ http_strict_transport_security *victim);
+
+/**
+ * Get the value of a strict transport security's max-age
+ *
+ * \param sts Object to inspect
+ * \return Max age, in delta-seconds
+ */
+uint32_t http_strict_transport_security_max_age(
+ http_strict_transport_security *sts);
+
+/**
+ * Get the value of a strict transport security's includeSubDomains flag
+ *
+ * \param sts Object to inspect
+ * \return Whether subdomains should be included
+ */
+bool http_strict_transport_security_include_subdomains(
+ http_strict_transport_security *sts);
+
+#endif
diff --git a/utils/idna.c b/utils/idna.c
index 34cc40f83..572882ecb 100644
--- a/utils/idna.c
+++ b/utils/idna.c
@@ -63,17 +63,17 @@ static nserror punycode_status_to_nserror(enum punycode_status status)
break;
case punycode_bad_input:
- LOG("Bad input");
+ NSLOG(netsurf, INFO, "Bad input");
ret = NSERROR_BAD_ENCODING;
break;
case punycode_big_output:
- LOG("Output too big");
+ NSLOG(netsurf, INFO, "Output too big");
ret = NSERROR_BAD_SIZE;
break;
case punycode_overflow:
- LOG("Overflow");
+ NSLOG(netsurf, INFO, "Overflow");
ret = NSERROR_NOSPACE;
break;
@@ -437,7 +437,8 @@ static bool idna__is_valid(int32_t *label, size_t len)
/* 2. Check characters 3 and 4 are not '--'. */
if ((label[2] == 0x002d) && (label[3] == 0x002d)) {
- LOG("Check failed: characters 2 and 3 are '--'");
+ NSLOG(netsurf, INFO,
+ "Check failed: characters 2 and 3 are '--'");
return false;
}
@@ -447,7 +448,8 @@ static bool idna__is_valid(int32_t *label, size_t len)
if ((unicode_props->category == UTF8PROC_CATEGORY_MN) ||
(unicode_props->category == UTF8PROC_CATEGORY_MC) ||
(unicode_props->category == UTF8PROC_CATEGORY_ME)) {
- LOG("Check failed: character 0 is a combining mark");
+ NSLOG(netsurf, INFO,
+ "Check failed: character 0 is a combining mark");
return false;
}
@@ -456,14 +458,20 @@ static bool idna__is_valid(int32_t *label, size_t len)
/* 4. Check characters not DISALLOWED by RFC5892 */
if (idna_prop == IDNA_P_DISALLOWED) {
- LOG("Check failed: character %" PRIsizet " (%x) is DISALLOWED", i, label[i]);
+ NSLOG(netsurf, INFO,
+ "Check failed: character %"PRIsizet" (%x) is DISALLOWED",
+ i,
+ label[i]);
return false;
}
/* 5. Check CONTEXTJ characters conform to defined rules */
if (idna_prop == IDNA_P_CONTEXTJ) {
if (idna__contextj_rule(label, i, len) == false) {
- LOG("Check failed: character %" PRIsizet " (%x) does not conform to CONTEXTJ rule", i, label[i]);
+ NSLOG(netsurf, INFO,
+ "Check failed: character %"PRIsizet" (%x) does not conform to CONTEXTJ rule",
+ i,
+ label[i]);
return false;
}
}
@@ -472,14 +480,20 @@ static bool idna__is_valid(int32_t *label, size_t len)
/** \todo optionally we can check conformance to this rule */
if (idna_prop == IDNA_P_CONTEXTO) {
if (idna__contexto_rule(label[i]) == false) {
- LOG("Check failed: character %" PRIsizet " (%x) has no CONTEXTO rule defined", i, label[i]);
+ NSLOG(netsurf, INFO,
+ "Check failed: character %"PRIsizet" (%x) has no CONTEXTO rule defined",
+ i,
+ label[i]);
return false;
}
}
/* 7. Check characters are not UNASSIGNED */
if (idna_prop == IDNA_P_UNASSIGNED) {
- LOG("Check failed: character %" PRIsizet " (%x) is UNASSIGNED", i, label[i]);
+ NSLOG(netsurf, INFO,
+ "Check failed: character %"PRIsizet" (%x) is UNASSIGNED",
+ i,
+ label[i]);
return false;
}
@@ -588,7 +602,8 @@ static bool idna__verify(const char *label, size_t len)
return true;
}
- LOG("Re-encoded ACE label %s does not match input", ace);
+ NSLOG(netsurf, INFO, "Re-encoded ACE label %s does not match input",
+ ace);
free(ace);
return false;
@@ -641,7 +656,8 @@ idna_encode(const char *host, size_t len, char **ace_host, size_t *ace_len)
/* This is already a DNS-valid ASCII string */
if ((idna__is_ace(host, label_len) == true) &&
(idna__verify(host, label_len) == false)) {
- LOG("Cannot verify ACE label %s", host);
+ NSLOG(netsurf, INFO,
+ "Cannot verify ACE label %s", host);
return NSERROR_BAD_URL;
}
strncpy(fqdn_p, host, label_len);
diff --git a/utils/jenkins-build.sh b/utils/jenkins-build.sh
index b6ca21dd7..de6c25944 100755
--- a/utils/jenkins-build.sh
+++ b/utils/jenkins-build.sh
@@ -147,6 +147,23 @@ case ${TARGET} in
;;
+ "amigaos3")
+ case ${HOST} in
+ "m68k-unknown-amigaos")
+ ;;
+
+ *)
+ echo "Target \"${TARGET}\" cannot be built on \"${HOST})\""
+ exit 1
+ ;;
+
+ esac
+
+ PKG_SRC=NetSurf_Amiga/netsurf
+ PKG_SFX=.lha
+ ;;
+
+
"atari")
case ${HOST} in
"m68k-atari-mint")
@@ -291,6 +308,11 @@ case ${TARGET} in
export GCCSDK_INSTALL_CROSSBIN=/opt/netsurf/${HOST}/cross/bin
;;
+ "m68k-unknown-amigaos")
+ export GCCSDK_INSTALL_ENV=/opt/netsurf/${HOST}/env
+ export GCCSDK_INSTALL_CROSSBIN=/opt/netsurf/${HOST}/cross/bin
+ ;;
+
*)
echo "Target \"${TARGET}\" cannot be built on \"${HOST})\""
exit 1
@@ -389,6 +411,12 @@ if [ ${HAVE_DISTCC} = "true" ];then
fi
+########### Prepare a Makefile.config ##################
+
+rm -f Makefile.config
+cat > Makefile.config <<EOF
+override NETSURF_LOG_LEVEL := DEBUG
+EOF
########### Build from source ##################
diff --git a/utils/log.c b/utils/log.c
index 15a7a9e75..e267b3179 100644
--- a/utils/log.c
+++ b/utils/log.c
@@ -1,9 +1,5 @@
/*
- * Copyright 2007 Rob Kendrick <rjek@netsurf-browser.org>
- * Copyright 2004-2007 James Bursa <bursa@users.sourceforge.net>
- * Copyright 2003 Phil Mellor <monkeyson@users.sourceforge.net>
- * Copyright 2003 John M Bell <jmb202@ecs.soton.ac.uk>
- * Copyright 2004 John Tytgat <joty@netsurf-browser.org>
+ * Copyright 2017 Vincent Sanders <vince@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -24,6 +20,7 @@
#include <stdio.h>
#include "utils/config.h"
+#include "utils/nsoption.h"
#include "utils/sys_time.h"
#include "utils/utsname.h"
#include "desktop/version.h"
@@ -36,6 +33,154 @@ bool verbose_log = false;
/** The stream to which logging is sent */
static FILE *logfile;
+/** Subtract the `struct timeval' values X and Y
+ *
+ * \param result The timeval structure to store the result in
+ * \param x The first value
+ * \param y The second value
+ * \return 1 if the difference is negative, otherwise 0.
+ */
+static int
+timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y)
+{
+ /* Perform the carry for the later subtraction by updating y. */
+ if (x->tv_usec < y->tv_usec) {
+ int nsec = (int)(y->tv_usec - x->tv_usec) / 1000000 + 1;
+ y->tv_usec -= 1000000 * nsec;
+ y->tv_sec += nsec;
+ }
+ if ((int)(x->tv_usec - y->tv_usec) > 1000000) {
+ int nsec = (int)(x->tv_usec - y->tv_usec) / 1000000;
+ y->tv_usec += 1000000 * nsec;
+ y->tv_sec -= nsec;
+ }
+
+ /* Compute the time remaining to wait.
+ tv_usec is certainly positive. */
+ result->tv_sec = x->tv_sec - y->tv_sec;
+ result->tv_usec = x->tv_usec - y->tv_usec;
+
+ /* Return 1 if result is negative. */
+ return x->tv_sec < y->tv_sec;
+}
+
+/**
+ * Obtain a formatted string suitable for prepending to a log message
+ *
+ * \return formatted string of the time since first log call
+ */
+static const char *nslog_gettime(void)
+{
+ static struct timeval start_tv;
+ static char buff[32];
+
+ struct timeval tv;
+ struct timeval now_tv;
+
+ if (!timerisset(&start_tv)) {
+ gettimeofday(&start_tv, NULL);
+ }
+ gettimeofday(&now_tv, NULL);
+
+ timeval_subtract(&tv, &now_tv, &start_tv);
+
+ snprintf(buff, sizeof(buff),"(%ld.%06ld)",
+ (long)tv.tv_sec, (long)tv.tv_usec);
+
+ return buff;
+}
+
+#ifdef WITH_NSLOG
+
+NSLOG_DEFINE_CATEGORY(netsurf, "NetSurf default logging");
+NSLOG_DEFINE_CATEGORY(llcache, "Low level cache");
+NSLOG_DEFINE_CATEGORY(fetch, "objet fetching");
+NSLOG_DEFINE_CATEGORY(plot, "rendering system");
+NSLOG_DEFINE_CATEGORY(schedule, "scheduler");
+NSLOG_DEFINE_CATEGORY(fbtk, "Framebuffer toolkit");
+NSLOG_DEFINE_CATEGORY(layout, "Layout");
+
+static void
+netsurf_render_log(void *_ctx,
+ nslog_entry_context_t *ctx,
+ const char *fmt,
+ va_list args)
+{
+ fprintf(logfile,
+ "%s %.*s:%i %.*s: ",
+ nslog_gettime(),
+ ctx->filenamelen,
+ ctx->filename,
+ ctx->lineno,
+ ctx->funcnamelen,
+ ctx->funcname);
+
+ vfprintf(logfile, fmt, args);
+
+ /* Log entries aren't newline terminated add one for clarity */
+ fputc('\n', logfile);
+}
+
+/* exported interface documented in utils/log.h */
+nserror
+nslog_set_filter(const char *filter)
+{
+ nslog_error err;
+ nslog_filter_t *filt = NULL;
+
+ err = nslog_filter_from_text(filter, &filt);
+ if (err != NSLOG_NO_ERROR) {
+ if (err == NSLOG_NO_MEMORY)
+ return NSERROR_NOMEM;
+ else
+ return NSERROR_INVALID;
+ }
+
+ err = nslog_filter_set_active(filt, NULL);
+ filt = nslog_filter_unref(filt);
+ if (err != NSLOG_NO_ERROR) {
+ return NSERROR_NOSPACE;
+ }
+
+ return NSERROR_OK;
+}
+
+#else
+
+void
+nslog_log(const char *file, const char *func, int ln, const char *format, ...)
+{
+ va_list ap;
+
+ if (verbose_log) {
+ fprintf(logfile,
+ "%s %s:%i %s: ",
+ nslog_gettime(),
+ file,
+ ln,
+ func);
+
+ va_start(ap, format);
+
+ vfprintf(logfile, format, ap);
+
+ va_end(ap);
+
+ fputc('\n', logfile);
+ }
+}
+
+/* exported interface documented in utils/log.h */
+nserror
+nslog_set_filter(const char *filter)
+{
+ (void)(filter);
+ return NSERROR_OK;
+}
+
+
+#endif
+
nserror nslog_init(nslog_ensure_t *ensure, int *pargc, char **argv)
{
struct utsname utsname;
@@ -59,9 +204,9 @@ nserror nslog_init(nslog_ensure_t *ensure, int *pargc, char **argv)
/* ensure we actually show logging */
verbose_log = true;
} else if (((*pargc) > 2) &&
- (argv[1][0] == '-') &&
- (argv[1][1] == 'V') &&
- (argv[1][2] == 0)) {
+ (argv[1][0] == '-') &&
+ (argv[1][1] == 'V') &&
+ (argv[1][2] == 0)) {
int argcmv;
/* verbose logging to file */
@@ -82,7 +227,7 @@ nserror nslog_init(nslog_ensure_t *ensure, int *pargc, char **argv)
/* ensure we actually show logging */
verbose_log = true;
}
- } else if (verbose_log == true) {
+ } else {
/* default is logging to stderr */
logfile = stderr;
}
@@ -96,94 +241,65 @@ nserror nslog_init(nslog_ensure_t *ensure, int *pargc, char **argv)
verbose_log = false;
}
+#ifdef WITH_NSLOG
+
+ if (nslog_set_filter(verbose_log ?
+ NETSURF_BUILTIN_VERBOSE_FILTER :
+ NETSURF_BUILTIN_LOG_FILTER) != NSERROR_OK) {
+ ret = NSERROR_INIT_FAILED;
+ verbose_log = false;
+ } else if (nslog_set_render_callback(netsurf_render_log, NULL) != NSLOG_NO_ERROR) {
+ ret = NSERROR_INIT_FAILED;
+ verbose_log = false;
+ } else if (nslog_uncork() != NSLOG_NO_ERROR) {
+ ret = NSERROR_INIT_FAILED;
+ verbose_log = false;
+ }
+
+#endif
+
/* sucessfull logging initialisation so log system info */
if (ret == NSERROR_OK) {
- LOG("NetSurf version '%s'", netsurf_version);
+ NSLOG(netsurf, INFO, "NetSurf version '%s'", netsurf_version);
if (uname(&utsname) < 0) {
- LOG("Failed to extract machine information");
+ NSLOG(netsurf, INFO,
+ "Failed to extract machine information");
} else {
- LOG("NetSurf on <%s>, node <%s>, release <%s>, version <%s>, machine <%s>",
- utsname.sysname,
- utsname.nodename,
- utsname.release,
- utsname.version,
- utsname.machine);
+ NSLOG(netsurf, INFO,
+ "NetSurf on <%s>, node <%s>, release <%s>, version <%s>, machine <%s>",
+ utsname.sysname,
+ utsname.nodename,
+ utsname.release,
+ utsname.version,
+ utsname.machine);
}
}
return ret;
}
-#ifndef NDEBUG
-
-/* Subtract the `struct timeval' values X and Y,
- storing the result in RESULT.
- Return 1 if the difference is negative, otherwise 0.
-*/
-
-static int
-timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y)
+/* exported interface documented in utils/log.h */
+nserror
+nslog_set_filter_by_options()
{
- /* Perform the carry for the later subtraction by updating y. */
- if (x->tv_usec < y->tv_usec) {
- int nsec = (int)(y->tv_usec - x->tv_usec) / 1000000 + 1;
- y->tv_usec -= 1000000 * nsec;
- y->tv_sec += nsec;
- }
- if ((int)(x->tv_usec - y->tv_usec) > 1000000) {
- int nsec = (int)(x->tv_usec - y->tv_usec) / 1000000;
- y->tv_usec += 1000000 * nsec;
- y->tv_sec -= nsec;
- }
-
- /* Compute the time remaining to wait.
- tv_usec is certainly positive. */
- result->tv_sec = x->tv_sec - y->tv_sec;
- result->tv_usec = x->tv_usec - y->tv_usec;
-
- /* Return 1 if result is negative. */
- return x->tv_sec < y->tv_sec;
+ if (verbose_log)
+ return nslog_set_filter(nsoption_charp(verbose_filter));
+ else
+ return nslog_set_filter(nsoption_charp(log_filter));
}
-/**
- * Obtain a formatted string suitable for prepending to a log message
- *
- * \return formatted string of the time since first log call
- */
-static const char *nslog_gettime(void)
+/* exported interface documented in utils/log.h */
+void
+nslog_finalise()
{
- static struct timeval start_tv;
- static char buff[32];
-
- struct timeval tv;
- struct timeval now_tv;
-
- if (!timerisset(&start_tv)) {
- gettimeofday(&start_tv, NULL);
+ NSLOG(netsurf, INFO,
+ "Finalising logging, please report any further messages");
+ verbose_log = true;
+ if (logfile != stderr) {
+ fclose(logfile);
+ logfile = stderr;
}
- gettimeofday(&now_tv, NULL);
-
- timeval_subtract(&tv, &now_tv, &start_tv);
-
- snprintf(buff, sizeof(buff),"(%ld.%06ld)",
- (long)tv.tv_sec, (long)tv.tv_usec);
-
- return buff;
-}
-
-void nslog_log(const char *file, const char *func, int ln, const char *format, ...)
-{
- va_list ap;
-
- fprintf(logfile, "%s %s:%i %s: ", nslog_gettime(), file, ln, func);
-
- va_start(ap, format);
-
- vfprintf(logfile, format, ap);
-
- va_end(ap);
-
- fputc('\n', logfile);
-}
-
+#ifdef WITH_NSLOG
+ nslog_cleanup();
#endif
+}
diff --git a/utils/log.h b/utils/log.h
index 708016b18..b773ec4a2 100644
--- a/utils/log.h
+++ b/utils/log.h
@@ -17,8 +17,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef _NETSURF_LOG_H_
-#define _NETSURF_LOG_H_
+#ifndef NETSURF_LOG_H
+#define NETSURF_LOG_H
#include <stdio.h>
#include <stdbool.h>
@@ -43,9 +43,59 @@ typedef bool(nslog_ensure_t)(FILE *fptr);
*/
extern nserror nslog_init(nslog_ensure_t *ensure, int *pargc, char **argv);
-#ifdef NDEBUG
-# define LOG(format, ...) ((void) 0)
-#else
+/**
+ * Shut down the logging system.
+ *
+ * Shuts down the logging subsystem, resetting to verbose logging and output
+ * to stderr. Note, if logging is done after calling this, it will be sent
+ * to stderr without filtering.
+ */
+extern void nslog_finalise(void);
+
+/**
+ * Set the logging filter.
+ *
+ * Compiles and enables the given logging filter.
+ */
+extern nserror nslog_set_filter(const char *filter);
+
+/**
+ * Set the logging filter according to the options.
+ */
+extern nserror nslog_set_filter_by_options(void);
+
+/* ensure a logging level is defined */
+#ifndef NETSURF_LOG_LEVEL
+#define NETSURF_LOG_LEVEL INFO
+#endif
+
+#define NSLOG_LVL(level) NSLOG_LEVEL_ ## level
+#define NSLOG_EVL(level) NSLOG_LVL(level)
+#define NSLOG_COMPILED_MIN_LEVEL NSLOG_EVL(NETSURF_LOG_LEVEL)
+
+#ifdef WITH_NSLOG
+
+#include <nslog/nslog.h>
+
+NSLOG_DECLARE_CATEGORY(netsurf);
+NSLOG_DECLARE_CATEGORY(llcache);
+NSLOG_DECLARE_CATEGORY(fetch);
+NSLOG_DECLARE_CATEGORY(plot);
+NSLOG_DECLARE_CATEGORY(schedule);
+NSLOG_DECLARE_CATEGORY(fbtk);
+NSLOG_DECLARE_CATEGORY(layout);
+
+#else /* WITH_NSLOG */
+
+enum nslog_level {
+ NSLOG_LEVEL_DEEPDEBUG = 0,
+ NSLOG_LEVEL_DEBUG = 1,
+ NSLOG_LEVEL_VERBOSE = 2,
+ NSLOG_LEVEL_INFO = 3,
+ NSLOG_LEVEL_WARNING = 4,
+ NSLOG_LEVEL_ERROR = 5,
+ NSLOG_LEVEL_CRITICAL = 6
+};
extern void nslog_log(const char *file, const char *func, int ln, const char *format, ...) __attribute__ ((format (printf, 4, 5)));
@@ -60,13 +110,13 @@ extern void nslog_log(const char *file, const char *func, int ln, const char *fo
# define LOG_LN __LINE__
# endif
-#define LOG(format, args...) \
+#define NSLOG(catname, level, logmsg, args...) \
do { \
- if (verbose_log) { \
- nslog_log(__FILE__, LOG_FN, LOG_LN, format , ##args); \
+ if (NSLOG_LEVEL_##level >= NSLOG_COMPILED_MIN_LEVEL) { \
+ nslog_log(__FILE__, LOG_FN, LOG_LN, logmsg , ##args); \
} \
} while(0)
-#endif
+#endif /* WITH_NSLOG */
#endif
diff --git a/utils/merge-messages.lua b/utils/merge-messages.lua
deleted file mode 100755
index 3aeac697c..000000000
--- a/utils/merge-messages.lua
+++ /dev/null
@@ -1,83 +0,0 @@
-#!/usr/bin/env lua5.1
-
-local lfs = require "lfs"
-
-local en_stat = assert(lfs.attributes "!NetSurf/Resources/en/Messages")
-local language = { }
-local sorted = { }
-
-io.stderr:write("loading non-en languages...\n");
-
-for dir in lfs.dir "!NetSurf/Resources" do
- local path = "!NetSurf/Resources/" .. dir
- if dir ~= "en" and lfs.attributes(path .. "/Messages") then
- local f = io.open(path .. "/Messages", "r")
- local c = 0
- io.stderr:write(dir, ":")
- language[dir] = { }
- sorted[#sorted + 1] = dir
- for l in f:lines() do
- if l:sub(1, 1) ~= "#" then
- local tag, msg = l:match "^([^:]*):(.*)$"
- if tag then
- language[dir][tag] = msg
- c = c + 1
- end
- end
- end
- f:close()
- io.stderr:write(tostring(c), " entries.\n")
- end
-end
-
-table.sort(sorted)
-
-io.stderr:write("working through en...\n")
-
-local manipulators = {
- { "^(ami.*)", "ami.%1" },
- { "^(gtk.*)", "gtk.%1" },
- { "^(Help.*)", "ro.%1" },
- { "^(ARexx.*)", "ami.%1" },
-
- { "^(.*)$", "all.%1" } -- must be last
-}
-
-local function manipulate_tag(t)
- for _, m in ipairs(manipulators) do
- local r, s = t:gsub(m[1], m[2])
- if s > 0 then return r end
- end
- return t
-end
-
-local f = io.open("!NetSurf/Resources/en/Messages", "r")
-
-for l in f:lines() do
- if l:sub(1,1) == "#" then
- print(l)
- else
- local tag, msg = l:match "^([^:]*):(.*)$"
- if not tag then
- print(l)
- else
- local mtag = manipulate_tag(tag)
- io.stdout:write("en.", mtag, ":", msg, "\n")
- for _, langname in ipairs(sorted) do
- local trans = language[langname][tag]
- if not trans then
- io.stderr:write("*** language ", langname, " lacks translation for ", mtag, "/", tag, "\n")
- trans = msg
- end
- io.stdout:write(langname, ".", mtag, ":", trans, "\n")
- language[langname][tag] = nil
- end
- end
- end
-end
-
-for _, langname in ipairs(sorted) do
- for tag in pairs(language[langname]) do
- io.stderr:write("*** language ", langname, " contains orphan tag ", tag, "\n")
- end
-end \ No newline at end of file
diff --git a/utils/messages.c b/utils/messages.c
index 0c558cdfc..2e22cc731 100644
--- a/utils/messages.c
+++ b/utils/messages.c
@@ -45,106 +45,43 @@
/** The hash table used to store the standard Messages file for the old API */
static struct hash_table *messages_hash = NULL;
-/**
- * process a line of input.
- */
-static nserror
-message_process_line(struct hash_table *hash, uint8_t *ln, int lnlen)
-{
- uint8_t *value;
- uint8_t *colon;
-
- /* empty or comment lines */
- if (ln[0] == 0 || ln[0] == '#') {
- return NSERROR_OK;
- }
-
- /* find first colon as key/value separator */
- for (colon = ln; colon < (ln + lnlen); colon++) {
- if (*colon == ':') {
- break;
- }
- }
- if (colon == (ln + lnlen)) {
- /* no colon found */
- return NSERROR_INVALID;
- }
-
- *colon = 0; /* terminate key */
- value = colon + 1;
-
- if (hash_add(hash, (char *)ln, (char *)value) == false) {
- LOG("Unable to add %s:%s to hash table", ln, value);
- return NSERROR_INVALID;
- }
- return NSERROR_OK;
-}
/**
* Read keys and values from messages file.
*
* \param path pathname of messages file
- * \param ctx reference of hash table to merge with.
+ * \param ctx reference of hash table to merge with or NULL to create one.
* \return NSERROR_OK on sucess and ctx updated or error code on faliure.
*/
static nserror messages_load_ctx(const char *path, struct hash_table **ctx)
{
- char s[400]; /* line buffer */
- gzFile fp; /* compressed file handle */
struct hash_table *nctx; /* new context */
+ nserror res;
- assert(path != NULL);
-
- fp = gzopen(path, "r");
- if (!fp) {
- LOG("Unable to open messages file \"%.100s\": %s", path, strerror(errno));
-
- return NSERROR_NOT_FOUND;
- }
-
- if (*ctx == NULL) {
- nctx = hash_create(HASH_SIZE);
- } else {
+ if (*ctx != NULL) {
/**
* \note The passed hash is not copied here so this
* updates in place.
*/
- nctx = *ctx;
+ return hash_add_file(*ctx, path);
}
+
+ nctx = hash_create(HASH_SIZE);
if (nctx == NULL) {
- LOG("Unable to create hash table for messages file %s", path);
- gzclose(fp);
+ NSLOG(netsurf, INFO,
+ "Unable to create hash table for messages file %s",
+ path);
return NSERROR_NOMEM;
}
- while (gzgets(fp, s, sizeof s)) {
- char *colon, *value;
-
- if (s[0] == 0 || s[0] == '#')
- continue;
-
- s[strlen(s) - 1] = 0; /* remove \n at end */
- colon = strchr(s, ':');
- if (!colon)
- continue;
- *colon = 0; /* terminate key */
- value = colon + 1;
-
- if (hash_add(nctx, s, value) == false) {
- LOG("Unable to add %s:%s to hash table of %s", s, value, path);
- gzclose(fp);
- if (*ctx == NULL) {
- hash_destroy(nctx);
- }
- return NSERROR_INVALID;
- }
+ res = hash_add_file(nctx, path);
+ if (res == NSERROR_OK) {
+ *ctx = nctx;
+ } else {
+ hash_destroy(nctx);
}
- gzclose(fp);
-
- *ctx = nctx;
-
- return NSERROR_OK;
+ return res;
}
@@ -196,93 +133,28 @@ static void messages_destroy_ctx(struct hash_table *ctx)
/* exported interface documented in messages.h */
nserror messages_add_from_file(const char *path)
{
- nserror err;
-
if (path == NULL) {
return NSERROR_BAD_PARAMETER;
}
- LOG("Loading Messages from '%s'", path);
-
- err = messages_load_ctx(path, &messages_hash);
+ NSLOG(netsurf, INFO, "Loading Messages from '%s'", path);
-
- return err;
+ return messages_load_ctx(path, &messages_hash);
}
/* exported interface documented in messages.h */
-nserror messages_add_from_inline(const uint8_t *data, size_t data_size)
+nserror messages_add_from_inline(const uint8_t *data, size_t size)
{
- z_stream strm;
- int ret;
- uint8_t s[512]; /* line buffer */
- size_t used = 0; /* number of bytes in buffer in use */
- uint8_t *nl;
-
/* ensure the hash table is initialised */
if (messages_hash == NULL) {
messages_hash = hash_create(HASH_SIZE);
}
if (messages_hash == NULL) {
- LOG("Unable to create hash table");
+ NSLOG(netsurf, INFO, "Unable to create hash table");
return NSERROR_NOMEM;
}
-
- strm.zalloc = Z_NULL;
- strm.zfree = Z_NULL;
- strm.opaque = Z_NULL;
-
- strm.next_in = (uint8_t *)data;
- strm.avail_in = data_size;
-
- ret = inflateInit2(&strm, 32 + MAX_WBITS);
- if (ret != Z_OK) {
- LOG("inflateInit returned %d", ret);
- return NSERROR_INVALID;
- }
-
- do {
- strm.next_out = s + used;
- strm.avail_out = sizeof(s) - used;
-
- ret = inflate(&strm, Z_NO_FLUSH);
- if ((ret != Z_OK) && (ret != Z_STREAM_END)) {
- break;
- }
-
- used = sizeof(s) - strm.avail_out;
- while (used > 0) {
- /* find nl */
- for (nl = &s[0]; nl < &s[used]; nl++) {
- if (*nl == '\n') {
- break;
- }
- }
- if (nl == &s[used]) {
- /* no nl found */
- break;
- }
- /* found newline */
- *nl = 0; /* null terminate line */
- message_process_line(messages_hash, &s[0], nl - &s[0]);
- memmove(&s[0], nl + 1, used - ((nl + 1) - &s[0]) );
- used -= ((nl +1) - &s[0]);
- }
- if (used == sizeof(s)) {
- /* entire buffer used and no newline */
- LOG("Overlength line");
- used = 0;
- }
- } while (ret != Z_STREAM_END);
-
- inflateEnd(&strm);
-
- if (ret != Z_STREAM_END) {
- LOG("inflate returned %d", ret);
- return NSERROR_INVALID;
- }
- return NSERROR_OK;
+ return hash_add_inline(messages_hash, data, size);
}
/* exported interface documented in messages.h */
@@ -338,6 +210,10 @@ const char *messages_get_errorcode(nserror code)
/* Requested item not found */
return messages_get_ctx("NotFound", messages_hash);
+ case NSERROR_NOT_DIRECTORY:
+ /* Missing directory */
+ return messages_get_ctx("NotDirectory", messages_hash);
+
case NSERROR_SAVE_FAILED:
/* Failed to save data */
return messages_get_ctx("SaveFailed", messages_hash);
@@ -350,9 +226,29 @@ const char *messages_get_errorcode(nserror code)
/* Initialisation failed */
return messages_get_ctx("InitFailed", messages_hash);
- case NSERROR_MNG_ERROR:
- /* An MNG error occurred */
- return messages_get_ctx("MNGError", messages_hash);
+ case NSERROR_BMP_ERROR:
+ /* A BMP error occurred */
+ return messages_get_ctx("BMPError", messages_hash);
+
+ case NSERROR_GIF_ERROR:
+ /* A GIF error occurred */
+ return messages_get_ctx("GIFError", messages_hash);
+
+ case NSERROR_ICO_ERROR:
+ /* A ICO error occurred */
+ return messages_get_ctx("ICOError", messages_hash);
+
+ case NSERROR_PNG_ERROR:
+ /* A PNG error occurred */
+ return messages_get_ctx("PNGError", messages_hash);
+
+ case NSERROR_SPRITE_ERROR:
+ /* A RISC OS Sprite error occurred */
+ return messages_get_ctx("SpriteError", messages_hash);
+
+ case NSERROR_SVG_ERROR:
+ /* A SVG error occurred */
+ return messages_get_ctx("SVGError", messages_hash);
case NSERROR_BAD_ENCODING:
/* The character set is unknown */
@@ -398,12 +294,40 @@ const char *messages_get_errorcode(nserror code)
/* Bad URL */
return messages_get_ctx("BadURL", messages_hash);
- default:
+ case NSERROR_BAD_CONTENT:
+ /* Bad Content */
+ return messages_get_ctx("BadContent", messages_hash);
+
+ case NSERROR_FRAME_DEPTH:
+ /* Exceeded frame depth */
+ return messages_get_ctx("FrameDepth", messages_hash);
+
+ case NSERROR_PERMISSION:
+ /* Permission error */
+ return messages_get_ctx("PermissionError", messages_hash);
+
+ case NSERROR_BAD_SIZE:
+ /* Bad size */
+ return messages_get_ctx("BadSize", messages_hash);
+
+ case NSERROR_NOSPACE:
+ /* Insufficient space */
+ return messages_get_ctx("NoSpace", messages_hash);
+
+ case NSERROR_NOT_IMPLEMENTED:
+ /* Functionality is not implemented */
+ return messages_get_ctx("NotImplemented", messages_hash);
+
case NSERROR_UNKNOWN:
- break;
+ /* Unknown error */
+ return messages_get_ctx("Unknown", messages_hash);
}
- /* Unknown error */
+ /* The switch has no default, so the compiler should tell us when we
+ * forget to add messages for new error codes. As such, we should
+ * never get here.
+ */
+ assert(0);
return messages_get_ctx("Unknown", messages_hash);
}
@@ -414,4 +338,3 @@ void messages_destroy(void)
messages_destroy_ctx(messages_hash);
messages_hash = NULL;
}
-
diff --git a/utils/nsoption.c b/utils/nsoption.c
index 8f05a911b..09529a0d0 100644
--- a/utils/nsoption.c
+++ b/utils/nsoption.c
@@ -187,7 +187,7 @@ static void nsoption_validate(struct nsoption_s *opts, struct nsoption_s *defs)
break;
}
}
- if (black == true) {
+ if (black == true && defs != NULL) {
for (cloop = NSOPTION_SYS_COLOUR_START;
cloop <= NSOPTION_SYS_COLOUR_END;
cloop++) {
@@ -209,6 +209,9 @@ static void nsoption_validate(struct nsoption_s *opts, struct nsoption_s *defs)
opts[NSOPTION_max_retried_fetches].value.u) > 60) &&
(opts[NSOPTION_max_retried_fetches].value.u > 1))
opts[NSOPTION_max_retried_fetches].value.u--;
+
+ /* We ignore the result because we can't fail to validate. Yay */
+ (void)nslog_set_filter_by_options();
}
/**
@@ -648,11 +651,12 @@ nsoption_read(const char *path, struct nsoption_s *opts)
fp = fopen(path, "r");
if (!fp) {
- LOG("Failed to open file '%s'", path);
+ NSLOG(netsurf, INFO, "Failed to open file '%s'", path);
return NSERROR_NOT_FOUND;
}
- LOG("Successfully opened '%s' for Options file", path);
+ NSLOG(netsurf, INFO, "Successfully opened '%s' for Options file",
+ path);
while (fgets(s, NSOPTION_MAX_LINE_LEN, fp)) {
char *colon, *value;
@@ -718,7 +722,8 @@ nsoption_write(const char *path,
fp = fopen(path, "w");
if (!fp) {
- LOG("failed to open file '%s' for writing", path);
+ NSLOG(netsurf, INFO, "failed to open file '%s' for writing",
+ path);
return NSERROR_NOT_FOUND;
}
@@ -798,7 +803,7 @@ nsoption_commandline(int *pargc, char **argv, struct nsoption_s *opts)
/* arg+arglen is the option to set, val is the value */
- LOG("%.*s = %s", arglen, arg, val);
+ NSLOG(netsurf, INFO, "%.*s = %s", arglen, arg, val);
for (entry_loop = 0;
entry_loop < NSOPTION_LISTEND;
@@ -818,6 +823,8 @@ nsoption_commandline(int *pargc, char **argv, struct nsoption_s *opts)
}
*pargc -= (idx - 1);
+ nsoption_validate(opts, nsoptions_default);
+
return NSERROR_OK;
}
diff --git a/utils/nsoption.h b/utils/nsoption.h
index 62c89c464..e60ebd114 100644
--- a/utils/nsoption.h
+++ b/utils/nsoption.h
@@ -18,10 +18,10 @@
/**
* \file
- * Option reading and saving (interface).
+ * Option reading and saving interface.
*
* Global options are defined in desktop/options.h
- * Distinct target options are defined in <TARGET>/options.h
+ * Distinct target options are defined in ${TARGET}/options.h
*
* The implementation API is slightly compromised because it still has
* "global" tables for both the default and current option tables.
diff --git a/utils/nsurl.h b/utils/nsurl.h
index f97562bf0..054baf26b 100644
--- a/utils/nsurl.h
+++ b/utils/nsurl.h
@@ -301,6 +301,25 @@ nserror nsurl_replace_query(const nsurl *url, const char *query,
/**
+ * Create a NetSurf URL object, with scheme replaced
+ *
+ * \param url NetSurf URL to create new NetSurf URL from
+ * \param scheme Scheme to use
+ * \param new_url Returns new NetSurf URL with scheme provided
+ * \return NSERROR_OK on success, appropriate error otherwise
+ *
+ * If return value != NSERROR_OK, nothing will be returned in new_url.
+ *
+ * It is up to the client to call nsurl_unref when they are finished with
+ * the created object.
+ *
+ * Any scheme component in url is replaced with scheme in new_url.
+ */
+nserror nsurl_replace_scheme(const nsurl *url, lwc_string *scheme,
+ nsurl **new_url);
+
+
+/**
* Attempt to find a nice filename for a URL.
*
* \param url A NetSurf URL object to create a filename from
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..8c769cfff
--- /dev/null
+++ b/utils/nsurl/nsurl.c
@@ -0,0 +1,939 @@
+/*
+ * 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:
+ NSLOG(netsurf, INFO,
+ "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:
+ NSLOG(netsurf, INFO,
+ "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 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)
+{
+ 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..ce6f4435d 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.
*
@@ -366,6 +270,16 @@ static void nsurl__get_string_markers(const char * const url_s,
(*(pos - off + 4) == 'S')))) {
marker.scheme_type = NSURL_SCHEME_HTTPS;
is_http = true;
+ } else if (off == SLEN("file") &&
+ (((*(pos - off + 0) == 'f') ||
+ (*(pos - off + 0) == 'F')) &&
+ ((*(pos - off + 1) == 'i') ||
+ (*(pos - off + 1) == 'I')) &&
+ ((*(pos - off + 2) == 'l') ||
+ (*(pos - off + 2) == 'L')) &&
+ ((*(pos - off + 3) == 'e') ||
+ (*(pos - off + 3) == 'E')))) {
+ marker.scheme_type = NSURL_SCHEME_FILE;
} else if (off == SLEN("ftp") &&
(((*(pos - off + 0) == 'f') ||
(*(pos - off + 0) == 'F')) &&
@@ -537,19 +451,19 @@ static void nsurl__get_string_markers(const char * const url_s,
}
#ifdef NSURL_DEBUG
- LOG("marker.start: %i", marker.start);
- LOG("marker.scheme_end: %i", marker.scheme_end);
- LOG("marker.authority: %i", marker.authority);
+ NSLOG(netsurf, INFO, "marker.start: %i", marker.start);
+ NSLOG(netsurf, INFO, "marker.scheme_end: %i", marker.scheme_end);
+ NSLOG(netsurf, INFO, "marker.authority: %i", marker.authority);
- LOG("marker.colon_first: %i", marker.colon_first);
- LOG("marker.at: %i", marker.at);
- LOG("marker.colon_last: %i", marker.colon_last);
+ NSLOG(netsurf, INFO, "marker.colon_first: %i", marker.colon_first);
+ NSLOG(netsurf, INFO, "marker.at: %i", marker.at);
+ NSLOG(netsurf, INFO, "marker.colon_last: %i", marker.colon_last);
- LOG("marker.path: %i", marker.path);
- LOG("marker.query: %i", marker.query);
- LOG("marker.fragment: %i", marker.fragment);
+ NSLOG(netsurf, INFO, "marker.path: %i", marker.path);
+ NSLOG(netsurf, INFO, "marker.query: %i", marker.query);
+ NSLOG(netsurf, INFO, "marker.fragment: %i", marker.fragment);
- LOG("marker.end: %i", marker.end);
+ NSLOG(netsurf, INFO, "marker.end: %i", marker.end);
#endif
/* Got all the URL components pegged out now */
@@ -571,8 +485,8 @@ static size_t nsurl__remove_dot_segments(char *path, char *output)
while (*path_pos != '\0') {
#ifdef NSURL_DEBUG
- LOG(" in:%s", path_pos);
- LOG("out:%.*s", output_pos - output, output);
+ NSLOG(netsurf, INFO, " in:%s", path_pos);
+ NSLOG(netsurf, INFO, "out:%.*s", output_pos - output, output);
#endif
if (*path_pos == '.') {
if (*(path_pos + 1) == '.' &&
@@ -680,45 +594,6 @@ static size_t nsurl__get_longest_section(struct url_markers *m)
/**
- * Converts two hexadecimal digits to a single number
- *
- * \param c1 most significant hex digit
- * \param c2 least significant hex digit
- * \return the total value of the two digit hex number, or -ve if input not hex
- *
- * For unescaping url encoded characters.
- */
-static inline int nsurl__get_ascii_offset(char c1, char c2)
-{
- int offset;
-
- /* Use 1st char as most significant hex digit */
- if (ascii_is_digit(c1))
- offset = 16 * (c1 - '0');
- else if (c1 >= 'a' && c1 <= 'f')
- offset = 16 * (c1 - 'a' + 10);
- else if (c1 >= 'A' && c1 <= 'F')
- offset = 16 * (c1 - 'A' + 10);
- else
- /* Not valid hex */
- return -1;
-
- /* Use 2nd char as least significant hex digit and sum */
- if (ascii_is_digit(c2))
- offset += c2 - '0';
- else if (c2 >= 'a' && c2 <= 'f')
- offset += c2 - 'a' + 10;
- else if (c2 >= 'A' && c2 <= 'F')
- offset += c2 - 'A' + 10;
- else
- /* Not valid hex */
- return -1;
-
- return offset;
-}
-
-
-/**
* Create the components of a NetSurf URL object for a section of a URL string
*
* \param url_s URL string
@@ -802,7 +677,7 @@ static nserror nsurl__create_from_section(const char * const url_s,
/* Might be an escaped character needing unescaped */
/* Find which character which was escaped */
- ascii_offset = nsurl__get_ascii_offset(*(pos + 1),
+ ascii_offset = ascii_hex_to_value_2_chars(*(pos + 1),
*(pos + 2));
if (ascii_offset < 0) {
@@ -904,6 +779,11 @@ static nserror nsurl__create_from_section(const char * const url_s,
url->username = NULL;
url->password = NULL;
+ /* file: URLs don't have credentials */
+ if (url->scheme_type == NSURL_SCHEME_FILE) {
+ break;
+ }
+
if (length != 0 && *norm_start != ':') {
char *sec_start = norm_start;
if (pegs->colon_first != pegs->authority &&
@@ -940,6 +820,11 @@ static nserror nsurl__create_from_section(const char * const url_s,
url->host = NULL;
url->port = NULL;
+ /* file: URLs don't have a host */
+ if (url->scheme_type == NSURL_SCHEME_FILE) {
+ break;
+ }
+
if (length != 0) {
size_t colon = 0;
char *sec_start = norm_start;
@@ -1038,9 +923,13 @@ static nserror nsurl__create_from_section(const char * const url_s,
&url->path) != lwc_error_ok) {
return NSERROR_NOMEM;
}
- } else if (url->host != NULL &&
- url->scheme_type != NSURL_SCHEME_MAILTO) {
- /* Set empty path to "/", if there's a host */
+ } else if ((url->host != NULL &&
+ url->scheme_type != NSURL_SCHEME_MAILTO) ||
+ url->scheme_type == NSURL_SCHEME_FILE) {
+ /* Set empty path to "/" if:
+ * - there's a host and its not a mailto: URL
+ * - its a file: URL
+ */
if (lwc_intern_string("/", SLEN("/"),
&url->path) != lwc_error_ok) {
return NSERROR_NOMEM;
@@ -1187,14 +1076,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 +1153,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 +1224,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 +1235,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 +1266,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 +1277,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 +1302,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 +1310,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,
@@ -1853,7 +1324,8 @@ nserror nsurl_join(const nsurl *base, const char *rel, nsurl **joined)
assert(rel != NULL);
#ifdef NSURL_DEBUG
- LOG("base: \"%s\", rel: \"%s\"", nsurl_access(base), rel);
+ NSLOG(netsurf, INFO, "base: \"%s\", rel: \"%s\"", nsurl_access(base),
+ rel);
#endif
/* Peg out the URL sections */
@@ -1959,14 +1431,15 @@ nserror nsurl_join(const nsurl *base, const char *rel, nsurl **joined)
struct url_markers m_path;
size_t new_length;
- if (base->components.host != NULL &&
- base->components.path == NULL) {
- /* Append relative path to "/". */
- *(buff_pos++) = '/';
- memcpy(buff_pos, rel + m.path, m.query - m.path);
- buff_pos += m.query - m.path;
+ /* RFC3986 said to append relative path to "/" if the
+ * base path had no path and an authority.
+ *
+ * However, that specification is redundant, and base paths
+ * are normalised, so file, http, and https URLs will always
+ * have a non-empty path. (Empty paths become "/".)
+ */
- } else {
+ {
/* Append relative path to all but last segment of
* base path. */
size_t path_end = lwc_string_length(
@@ -2049,24 +1522,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 +1540,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..bc6737cd6
--- /dev/null
+++ b/utils/nsurl/private.h
@@ -0,0 +1,232 @@
+/*
+ * 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_FILE,
+ 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)
+ NSLOG(netsurf, INFO,netsurf, INFO,
+ " Scheme: %s",
+ lwc_string_data(url->components.scheme));
+
+ if (url->components.username)
+ NSLOG(netsurf, INFO,
+ "Username: %s",
+ lwc_string_data(url->components.username));
+
+ if (url->components.password)
+ NSLOG(netsurf, INFO,
+ "Password: %s",
+ lwc_string_data(url->components.password));
+
+ if (url->components.host)
+ NSLOG(netsurf, INFO,
+ " Host: %s",
+ lwc_string_data(url->components.host));
+
+ if (url->components.port)
+ NSLOG(netsurf, INFO,
+ " Port: %s",
+ lwc_string_data(url->components.port));
+
+ if (url->components.path)
+ NSLOG(netsurf, INFO,
+ " Path: %s",
+ lwc_string_data(url->components.path));
+
+ if (url->components.query)
+ NSLOG(netsurf, INFO,
+ " Query: %s",
+ lwc_string_data(url->components.query));
+
+ if (url->components.fragment)
+ NSLOG(netsurf, INFO,
+ "Fragment: %s",
+ lwc_string_data(url->components.fragment));
+}
+#endif
+
+
+#endif
diff --git a/utils/split-messages.pl b/utils/split-messages.pl
index 570ae03ca..4b50dded8 100644
--- a/utils/split-messages.pl
+++ b/utils/split-messages.pl
@@ -34,6 +34,8 @@ use strict;
use Getopt::Long ();
use Fcntl qw( O_CREAT O_EXCL O_WRONLY O_APPEND O_RDONLY O_WRONLY );
+use IO::Compress::Gzip;
+
use constant GETOPT_OPTS => qw( auto_abbrev no_getopt_compat bundling );
use constant GETOPT_SPEC =>
qw( output|o=s
@@ -43,6 +45,7 @@ use constant GETOPT_SPEC =>
plat|platform|p=s
format|fmt|f=s
warning|W=s
+ gzip|z
help|h|? );
# default option values:
@@ -214,7 +217,7 @@ sub input_stream ()
return \*STDIN;
}
-sub output_stream ()
+sub underlying_output_stream ()
{
if( $opt{output} )
{
@@ -229,6 +232,18 @@ sub output_stream ()
return \*STDOUT;
}
+sub output_stream ()
+{
+ my $ofh = underlying_output_stream();
+
+ if( $opt{gzip} )
+ {
+ $ofh = new IO::Compress::Gzip( $ofh, AutoClose => 1, -Level => 9 );
+ }
+
+ return $ofh;
+}
+
sub formatter ()
{
my $name = $opt{format};
diff --git a/utils/useragent.c b/utils/useragent.c
index 72e45aada..b528dce4f 100644
--- a/utils/useragent.c
+++ b/utils/useragent.c
@@ -65,7 +65,8 @@ user_agent_build_string(void)
core_user_agent_string = ua_string;
- LOG("Built user agent \"%s\"", core_user_agent_string);
+ NSLOG(netsurf, INFO, "Built user agent \"%s\"",
+ core_user_agent_string);
}
/* This is a function so that later we can override it trivially */
diff --git a/utils/utf8.c b/utils/utf8.c
index 5c930cd13..f0ac0c9b2 100644
--- a/utils/utf8.c
+++ b/utils/utf8.c
@@ -468,7 +468,8 @@ bool utf8_save_text(const char *utf8_text, const char *path)
ret = guit->utf8->utf8_to_local(utf8_text, strlen(utf8_text), &conv);
if (ret != NSERROR_OK) {
- LOG("failed to convert to local encoding, return %d", ret);
+ NSLOG(netsurf, INFO,
+ "failed to convert to local encoding, return %d", ret);
return false;
}
@@ -476,7 +477,7 @@ bool utf8_save_text(const char *utf8_text, const char *path)
if (out) {
int res = fputs(conv, out);
if (res < 0) {
- LOG("Warning: writing data failed");
+ NSLOG(netsurf, INFO, "Warning: writing data failed");
}
res = fputs("\n", out);