diff options
Diffstat (limited to 'utils')
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, ¶ms); 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, ¶ms); 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, ¶ms); 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); |