diff options
Diffstat (limited to 'utils')
-rw-r--r-- | utils/config.h | 9 | ||||
-rw-r--r-- | utils/corestringlist.h | 1 | ||||
-rw-r--r-- | utils/file.c | 57 | ||||
-rw-r--r-- | utils/filename.c | 88 | ||||
-rw-r--r-- | utils/idna.c | 8 | ||||
-rw-r--r-- | utils/inet.h | 11 | ||||
-rw-r--r-- | utils/libdom.c | 123 | ||||
-rw-r--r-- | utils/libdom.h | 23 | ||||
-rw-r--r-- | utils/log.c | 5 | ||||
-rw-r--r-- | utils/log.h | 1 | ||||
-rw-r--r-- | utils/nscolour.c | 31 | ||||
-rw-r--r-- | utils/nsoption.c | 13 | ||||
-rw-r--r-- | utils/ssl_certs.c | 35 | ||||
-rw-r--r-- | utils/useragent.c | 15 | ||||
-rw-r--r-- | utils/utf8.c | 206 | ||||
-rw-r--r-- | utils/utils.h | 27 |
16 files changed, 278 insertions, 375 deletions
diff --git a/utils/config.h b/utils/config.h index 0227f4177..f54326dba 100644 --- a/utils/config.h +++ b/utils/config.h @@ -146,6 +146,15 @@ char *realpath(const char *path, char *resolved_path); #undef HAVE_SCANDIR #endif +#define HAVE_DIRFD +#define HAVE_UNLINKAT +#define HAVE_FSTATAT +#if (defined(_WIN32) || defined(__riscos__) || defined(__HAIKU__) || defined(__BEOS__) || defined(__amigaos4__) || defined(__AMIGA__) || defined(__MINT__)) +#undef HAVE_DIRFD +#undef HAVE_UNLINKAT +#undef HAVE_FSTATAT +#endif + #define HAVE_REGEX #if (defined(__serenity__)) #undef HAVE_REGEX diff --git a/utils/corestringlist.h b/utils/corestringlist.h index b253b3b56..5cdbb3af7 100644 --- a/utils/corestringlist.h +++ b/utils/corestringlist.h @@ -167,6 +167,7 @@ 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_jxl, "image/jxl"); 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"); diff --git a/utils/file.c b/utils/file.c index c460e49e9..75a8a1c03 100644 --- a/utils/file.c +++ b/utils/file.c @@ -26,6 +26,7 @@ #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> +#include <fcntl.h> #include <errno.h> #include "desktop/gui_internal.h" @@ -318,16 +319,13 @@ nserror netsurf_mkdir_all(const char *fname) nserror netsurf_recursive_rm(const char *path) { - struct dirent **listing = NULL; /* directory entry listing */ - int nentries, ent; + DIR *parent; + struct dirent *entry; nserror ret = NSERROR_OK; struct stat ent_stat; /* stat result of leaf entry */ - char *leafpath = NULL; - const char *leafname; - - nentries = scandir(path, &listing, 0, alphasort); - if (nentries < 0) { + parent = opendir(path); + if (parent == NULL) { switch (errno) { case ENOENT: return NSERROR_NOT_FOUND; @@ -336,26 +334,44 @@ netsurf_recursive_rm(const char *path) } } - for (ent = 0; ent < nentries; ent++) { - leafname = listing[ent]->d_name; - if (strcmp(leafname, ".") == 0 || - strcmp(leafname, "..") == 0) + while ((entry = readdir(parent))) { + char *leafpath = NULL; + + if (strcmp(entry->d_name, ".") == 0 || + strcmp(entry->d_name, "..") == 0) continue; - ret = netsurf_mkpath(&leafpath, NULL, 2, path, leafname); - if (ret != NSERROR_OK) goto out; + + ret = netsurf_mkpath(&leafpath, NULL, 2, path, entry->d_name); + if (ret != NSERROR_OK) + goto out; + +#if (defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)) + if (fstatat(dirfd(parent), entry->d_name, &ent_stat, + AT_SYMLINK_NOFOLLOW) != 0) { +#else if (stat(leafpath, &ent_stat) != 0) { +#endif + free(leafpath); goto out_via_errno; } if (S_ISDIR(ent_stat.st_mode)) { ret = netsurf_recursive_rm(leafpath); - if (ret != NSERROR_OK) goto out; + if (ret != NSERROR_OK) { + free(leafpath); + goto out; + } } else { +#if (defined(HAVE_DIRFD) && defined(HAVE_UNLINKAT)) + if (unlinkat(dirfd(parent), entry->d_name, 0) != 0) { +#else if (unlink(leafpath) != 0) { +#endif + free(leafpath); goto out_via_errno; } } + free(leafpath); - leafpath = NULL; } if (rmdir(path) != 0) { @@ -373,16 +389,7 @@ out_via_errno: ret = NSERROR_UNKNOWN; } out: - if (listing != NULL) { - for (ent = 0; ent < nentries; ent++) { - free(listing[ent]); - } - free(listing); - } - - if (leafpath != NULL) { - free(leafpath); - } + closedir(parent); return ret; } diff --git a/utils/filename.c b/utils/filename.c index 00ade7409..346fa85cc 100644 --- a/utils/filename.c +++ b/utils/filename.c @@ -29,10 +29,13 @@ #include <stdio.h> #include <stdlib.h> #include <errno.h> +#include <fcntl.h> #include <sys/stat.h> #include <unistd.h> #include "utils/dirent.h" +#include "utils/errors.h" +#include "utils/file.h" #include "utils/filename.h" #include "utils/log.h" #include "utils/utils.h" @@ -55,7 +58,6 @@ static char filename_directory[256]; static struct directory *filename_create_directory(const char *prefix); static bool filename_flush_directory(const char *folder, int depth); -static bool filename_delete_recursive(char *folder); /** * Request a new, unique, filename. @@ -272,6 +274,8 @@ bool filename_flush_directory(const char *folder, int depth) } parent = opendir(folder); + if (parent == NULL) + return false; while ((entry = readdir(parent))) { int written; @@ -288,7 +292,12 @@ bool filename_flush_directory(const char *folder, int depth) child[sizeof(child) - 1] = '\0'; } +#if (defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)) + if (fstatat(dirfd(parent), entry->d_name, &statbuf, + AT_SYMLINK_NOFOLLOW) == -1) { +#else if (stat(child, &statbuf) == -1) { +#endif NSLOG(netsurf, INFO, "Unable to stat %s: %s", child, strerror(errno)); continue; @@ -354,14 +363,20 @@ bool filename_flush_directory(const char *folder, int depth) /* delete or recurse */ if (del) { - if (S_ISDIR(statbuf.st_mode)) - filename_delete_recursive(child); - - if (remove(child)) - NSLOG(netsurf, INFO, "Failed to remove '%s'", - child); - else - changed = true; + if (S_ISDIR(statbuf.st_mode)) { + changed = (netsurf_recursive_rm(child) == + NSERROR_OK); + } else { +#if (defined(HAVE_DIRFD) && defined(HAVE_UNLINKAT)) + if (unlinkat(dirfd(parent), entry->d_name, 0)) { +#else + if (unlink(child)) { +#endif + NSLOG(netsurf, INFO, + "Failed to remove '%s'", child); + } else + changed = true; + } } else { while (filename_flush_directory(child, depth + 1)); } @@ -374,61 +389,6 @@ bool filename_flush_directory(const char *folder, int depth) /** - * Recursively deletes the contents of a directory - * - * \param folder the directory to delete - * \return true on success, false otherwise - */ -bool filename_delete_recursive(char *folder) -{ - DIR *parent; - struct dirent *entry; - char child[256]; - struct stat statbuf; - - parent = opendir(folder); - - while ((entry = readdir(parent))) { - int written; - - /* Ignore '.' and '..' */ - if (strcmp(entry->d_name, ".") == 0 || - strcmp(entry->d_name, "..") == 0) - continue; - - 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) { - NSLOG(netsurf, INFO, "Unable to stat %s: %s", child, - strerror(errno)); - continue; - } - - if (S_ISDIR(statbuf.st_mode)) { - if (!filename_delete_recursive(child)) { - closedir(parent); - return false; - } - } - - if (remove(child)) { - NSLOG(netsurf, INFO, "Failed to remove '%s'", child); - closedir(parent); - return false; - } - } - - closedir(parent); - - return true; -} - - -/** * Creates a new directory. * * \param prefix the prefix to use, or NULL to allocate a new one diff --git a/utils/idna.c b/utils/idna.c index 628ef1fac..3ce3e1be1 100644 --- a/utils/idna.c +++ b/utils/idna.c @@ -440,7 +440,7 @@ static bool idna__is_valid(int32_t *label, size_t len) /* 4. Check characters not DISALLOWED by RFC5892 */ if (idna_prop == IDNA_P_DISALLOWED) { NSLOG(netsurf, INFO, - "Check failed: character %"PRIsizet" (%x) is DISALLOWED", + "Check failed: character %"PRIsizet" (%"PRIx32") is DISALLOWED", i, label[i]); return false; @@ -450,7 +450,7 @@ static bool idna__is_valid(int32_t *label, size_t len) if (idna_prop == IDNA_P_CONTEXTJ) { if (idna__contextj_rule(label, i, len) == false) { NSLOG(netsurf, INFO, - "Check failed: character %"PRIsizet" (%x) does not conform to CONTEXTJ rule", + "Check failed: character %"PRIsizet" (%"PRIx32") does not conform to CONTEXTJ rule", i, label[i]); return false; @@ -462,7 +462,7 @@ static bool idna__is_valid(int32_t *label, size_t len) if (idna_prop == IDNA_P_CONTEXTO) { if (idna__contexto_rule(label[i]) == false) { NSLOG(netsurf, INFO, - "Check failed: character %"PRIsizet" (%x) has no CONTEXTO rule defined", + "Check failed: character %"PRIsizet" (%"PRIx32") has no CONTEXTO rule defined", i, label[i]); return false; @@ -472,7 +472,7 @@ static bool idna__is_valid(int32_t *label, size_t len) /* 7. Check characters are not UNASSIGNED */ if (idna_prop == IDNA_P_UNASSIGNED) { NSLOG(netsurf, INFO, - "Check failed: character %"PRIsizet" (%x) is UNASSIGNED", + "Check failed: character %"PRIsizet" (%"PRIx32") is UNASSIGNED", i, label[i]); return false; diff --git a/utils/inet.h b/utils/inet.h index da1798432..29010efc1 100644 --- a/utils/inet.h +++ b/utils/inet.h @@ -40,6 +40,15 @@ #include <arpa/inet.h> #include <sys/select.h> +#define ns_close_socket close + +#ifdef WITH_AMISSL +/* AmiSSL needs everything to be using bsdsocket directly to avoid conflicts */ +#include <proto/bsdsocket.h> +#undef ns_close_socket +#define ns_close_socket CloseSocket +#endif + #else #include <winsock2.h> @@ -49,6 +58,8 @@ #define EAFNOSUPPORT WSAEAFNOSUPPORT #endif +#define ns_close_socket closesocket + #endif diff --git a/utils/libdom.c b/utils/libdom.c index a996e98bf..c39aad343 100644 --- a/utils/libdom.c +++ b/utils/libdom.c @@ -28,129 +28,6 @@ #include "utils/log.h" #include "utils/libdom.h" -/* exported interface documented in libdom.h */ -bool libdom_treewalk(dom_node *root, - bool (*callback)(dom_node *node, dom_string *name, void *ctx), - void *ctx) -{ - dom_node *node; - bool result = true; - - node = dom_node_ref(root); /* tree root */ - - while (node != NULL) { - dom_node *next = NULL; - dom_node_type type; - dom_string *name; - dom_exception exc; - - exc = dom_node_get_first_child(node, &next); - if (exc != DOM_NO_ERR) { - dom_node_unref(node); - break; - } - - if (next != NULL) { - /* 1. Got children */ - dom_node_unref(node); - node = next; - } else { - /* No children; siblings & ancestor's siblings */ - while (node != NULL) { - exc = dom_node_get_next_sibling(node, &next); - if (exc != DOM_NO_ERR) { - dom_node_unref(node); - node = NULL; - break; - } - - if (next != NULL) { - /* 2. Got sibling */ - break; - } - - exc = dom_node_get_parent_node(node, &next); - if (exc != DOM_NO_ERR) { - dom_node_unref(node); - node = NULL; - break; - } - - /* 3. Try parent */ - dom_node_unref(node); - node = next; - } - - if (node == NULL) - break; - - dom_node_unref(node); - node = next; - } - - assert(node != NULL); - - exc = dom_node_get_node_type(node, &type); - if ((exc != DOM_NO_ERR) || (type != DOM_ELEMENT_NODE)) - continue; - - exc = dom_node_get_node_name(node, &name); - if (exc != DOM_NO_ERR) - continue; - - result = callback(node, name, ctx); - - dom_string_unref(name); - - if (result == false) { - break; /* callback caused early termination */ - } - - } - return result; -} - - -/* libdom_treewalk context for libdom_find_element */ -struct find_element_ctx { - lwc_string *search; - dom_node *found; -}; - -/* libdom_treewalk callback for libdom_find_element */ -static bool libdom_find_element_callback(dom_node *node, dom_string *name, - void *ctx) -{ - struct find_element_ctx *data = ctx; - - if (dom_string_caseless_lwc_isequal(name, data->search)) { - /* Found element */ - data->found = node; - return false; /* Discontinue search */ - } - - return true; /* Continue search */ -} - - -/* exported interface documented in libdom.h */ -dom_node *libdom_find_element(dom_node *node, lwc_string *element_name) -{ - struct find_element_ctx data; - - assert(element_name != NULL); - - if (node == NULL) - return NULL; - - data.search = element_name; - data.found = NULL; - - libdom_treewalk(node, libdom_find_element_callback, &data); - - return data.found; -} - /* exported interface documented in libdom.h */ dom_node *libdom_find_first_element(dom_node *parent, lwc_string *element_name) diff --git a/utils/libdom.h b/utils/libdom.h index 306aa0f8b..63841934f 100644 --- a/utils/libdom.h +++ b/utils/libdom.h @@ -33,29 +33,6 @@ #include <dom/bindings/hubbub/errors.h> /** - * depth-first walk the dom calling callback for each element - * - * \param root the dom node to use as the root of the tree walk - * \param callback The function called for each element - * \param ctx The context passed to the callback. - * \return true if all nodes were examined, false if the callback terminated - * the walk early. - */ -bool libdom_treewalk(dom_node *root, - bool (*callback)(dom_node *node, dom_string *name, void *ctx), - void *ctx); - -/** - * Search the descendants of a node for an element. - * - * \param node dom_node to search children of, or NULL - * \param element_name name of element to find - * \return first child of node which is an element and matches name, or - * NULL if not found or parameter node is NULL - */ -dom_node *libdom_find_element(dom_node *node, lwc_string *element_name); - -/** * Search children of a node for first named element * \param parent dom_node to search children of, or NULL * \param element_name name of element to find diff --git a/utils/log.c b/utils/log.c index 68b188e0f..a083b5720 100644 --- a/utils/log.c +++ b/utils/log.c @@ -99,6 +99,7 @@ NSLOG_DEFINE_CATEGORY(plot, "Rendering system"); NSLOG_DEFINE_CATEGORY(schedule, "Scheduler"); NSLOG_DEFINE_CATEGORY(fbtk, "Framebuffer toolkit"); NSLOG_DEFINE_CATEGORY(layout, "Layout"); +NSLOG_DEFINE_CATEGORY(flex, "Flex"); NSLOG_DEFINE_CATEGORY(dukky, "Duktape JavaScript Binding"); NSLOG_DEFINE_CATEGORY(jserrors, "JavaScript error messages"); @@ -285,7 +286,7 @@ nserror nslog_init(nslog_ensure_t *ensure, int *pargc, char **argv) /* exported interface documented in utils/log.h */ nserror -nslog_set_filter_by_options() +nslog_set_filter_by_options(void) { if (verbose_log) return nslog_set_filter(nsoption_charp(verbose_filter)); @@ -295,7 +296,7 @@ nslog_set_filter_by_options() /* exported interface documented in utils/log.h */ void -nslog_finalise() +nslog_finalise(void) { NSLOG(netsurf, INFO, "Finalising logging, please report any further messages"); diff --git a/utils/log.h b/utils/log.h index 02a886c01..b7aa83358 100644 --- a/utils/log.h +++ b/utils/log.h @@ -84,6 +84,7 @@ NSLOG_DECLARE_CATEGORY(plot); NSLOG_DECLARE_CATEGORY(schedule); NSLOG_DECLARE_CATEGORY(fbtk); NSLOG_DECLARE_CATEGORY(layout); +NSLOG_DECLARE_CATEGORY(flex); NSLOG_DECLARE_CATEGORY(dukky); NSLOG_DECLARE_CATEGORY(jserrors); diff --git a/utils/nscolour.c b/utils/nscolour.c index a07175201..5a772b8a6 100644 --- a/utils/nscolour.c +++ b/utils/nscolour.c @@ -28,6 +28,7 @@ #include <stddef.h> #include <stdbool.h> +#include "netsurf/inttypes.h" #include "netsurf/plot_style.h" #include "utils/errors.h" @@ -211,49 +212,49 @@ nserror nscolour_get_stylesheet(const char **stylesheet_out) ret = snprintf(buffer, sizeof(buffer), ".ns-odd-bg {\n" - "\tbackground-color: #%06x;\n" + "\tbackground-color: #%06"PRIx32";\n" "}\n" ".ns-odd-bg-hover {\n" - "\tbackground-color: #%06x;\n" + "\tbackground-color: #%06"PRIx32";\n" "}\n" ".ns-odd-fg {\n" - "\tcolor: #%06x;\n" + "\tcolor: #%06"PRIx32";\n" "}\n" ".ns-odd-fg-subtle {\n" - "\tcolor: #%06x;\n" + "\tcolor: #%06"PRIx32";\n" "}\n" ".ns-odd-fg-faded {\n" - "\tcolor: #%06x;\n" + "\tcolor: #%06"PRIx32";\n" "}\n" ".ns-odd-fg-good {\n" - "\tcolor: #%06x;\n" + "\tcolor: #%06"PRIx32";\n" "}\n" ".ns-odd-fg-bad {\n" - "\tcolor: #%06x;\n" + "\tcolor: #%06"PRIx32";\n" "}\n" ".ns-even-bg {\n" - "\tbackground-color: #%06x;\n" + "\tbackground-color: #%06"PRIx32";\n" "}\n" ".ns-even-bg-hover {\n" - "\tbackground-color: #%06x;\n" + "\tbackground-color: #%06"PRIx32";\n" "}\n" ".ns-even-fg {\n" - "\tcolor: #%06x;\n" + "\tcolor: #%06"PRIx32";\n" "}\n" ".ns-even-fg-subtle {\n" - "\tcolor: #%06x;\n" + "\tcolor: #%06"PRIx32";\n" "}\n" ".ns-even-fg-faded {\n" - "\tcolor: #%06x;\n" + "\tcolor: #%06"PRIx32";\n" "}\n" ".ns-even-fg-good {\n" - "\tcolor: #%06x;\n" + "\tcolor: #%06"PRIx32";\n" "}\n" ".ns-even-fg-bad {\n" - "\tcolor: #%06x;\n" + "\tcolor: #%06"PRIx32";\n" "}\n" ".ns-border {\n" - "\tborder-color: #%06x;\n" + "\tborder-color: #%06"PRIx32";\n" "}\n", colour_rb_swap(nscolours[NSCOLOUR_WIN_ODD_BG]), colour_rb_swap(nscolours[NSCOLOUR_WIN_ODD_BG_HOVER]), diff --git a/utils/nsoption.c b/utils/nsoption.c index a8a29b3bf..7306dee1b 100644 --- a/utils/nsoption.c +++ b/utils/nsoption.c @@ -32,6 +32,7 @@ #include <string.h> #include <strings.h> +#include "netsurf/inttypes.h" #include "netsurf/plot_style.h" #include "utils/errors.h" #include "utils/log.h" @@ -112,7 +113,7 @@ strtooption(const char *value, struct nsoption_s *option) break; case OPTION_COLOUR: - if (sscanf(value, "%x", &rgbcolour) == 1) { + if (sscanf(value, "%"SCNx32"", &rgbcolour) == 1) { option->value.c = (((0x000000FF & rgbcolour) << 16) | ((0x0000FF00 & rgbcolour) << 0) | ((0x00FF0000 & rgbcolour) >> 16)); @@ -323,7 +324,7 @@ nsoption_output(FILE *fp, rgbcolour = (((0x000000FF & opts[entry].value.c) << 16) | ((0x0000FF00 & opts[entry].value.c) << 0) | ((0x00FF0000 & opts[entry].value.c) >> 16)); - fprintf(fp, "%s:%06x\n", + fprintf(fp, "%s:%06"PRIx32"\n", opts[entry].key, rgbcolour); @@ -387,10 +388,10 @@ nsoption_output_value_html(struct nsoption_s *option, slen = snprintf(string + pos, size - pos, "<span style=\"font-family:Monospace;\">" - "#%06X" + "#%06"PRIX32 "</span> " - "<span style=\"background-color: #%06x; " - "border: 1px solid #%06x; " + "<span style=\"background-color: #%06"PRIx32"; " + "border: 1px solid #%06"PRIx32"; " "display: inline-block; " "width: 1em; height: 1em;\">" "</span>", @@ -459,7 +460,7 @@ nsoption_output_value_text(struct nsoption_s *option, rgbcolour = (((0x000000FF & option->value.c) << 16) | ((0x0000FF00 & option->value.c) << 0) | ((0x00FF0000 & option->value.c) >> 16)); - slen = snprintf(string + pos, size - pos, "%06x", rgbcolour); + slen = snprintf(string + pos, size - pos, "%06"PRIx32, rgbcolour); break; case OPTION_STRING: diff --git a/utils/ssl_certs.c b/utils/ssl_certs.c index d0f2a6c18..8546165ac 100644 --- a/utils/ssl_certs.c +++ b/utils/ssl_certs.c @@ -248,12 +248,23 @@ nserror cert_chain_to_query(struct cert_chain *chain, struct nsurl **url_out ) urlstrlen = snprintf((char *)urlstr, allocsize, "about:certificate"); for (depth = 0; depth < chain->depth; depth++) { + int written; nsuerror nsures; size_t output_length; - urlstrlen += snprintf((char *)urlstr + urlstrlen, - allocsize - urlstrlen, - "&cert="); + written = snprintf((char *)urlstr + urlstrlen, + allocsize - urlstrlen, + "&cert="); + if (written < 0) { + free(urlstr); + return NSERROR_UNKNOWN; + } + if ((size_t)written >= allocsize - urlstrlen) { + free(urlstr); + return NSERROR_UNKNOWN; + } + + urlstrlen += (size_t)written; output_length = allocsize - urlstrlen; nsures = nsu_base64_encode_url( @@ -268,10 +279,20 @@ nserror cert_chain_to_query(struct cert_chain *chain, struct nsurl **url_out ) urlstrlen += output_length; if (chain->certs[depth].err != SSL_CERT_ERR_OK) { - urlstrlen += snprintf((char *)urlstr + urlstrlen, - allocsize - urlstrlen, - "&certerr=%d", - chain->certs[depth].err); + written = snprintf((char *)urlstr + urlstrlen, + allocsize - urlstrlen, + "&certerr=%d", + chain->certs[depth].err); + if (written < 0) { + free(urlstr); + return NSERROR_UNKNOWN; + } + if ((size_t)written >= allocsize - urlstrlen) { + free(urlstr); + return NSERROR_UNKNOWN; + } + + urlstrlen += (size_t)written; } } diff --git a/utils/useragent.c b/utils/useragent.c index 3d93a97b2..547999c7c 100644 --- a/utils/useragent.c +++ b/utils/useragent.c @@ -19,6 +19,7 @@ #include <stdio.h> #include <stdlib.h> +#include <string.h> #include "utils/config.h" #include "utils/utsname.h" @@ -29,7 +30,7 @@ static const char *core_user_agent_string = NULL; #ifndef NETSURF_UA_FORMAT_STRING -#define NETSURF_UA_FORMAT_STRING "NetSurf/%d.%d (%s)" +#define NETSURF_UA_FORMAT_STRING "Mozilla/5.0 (%s) NetSurf/%d.%d" #endif /** @@ -46,12 +47,16 @@ user_agent_build_string(void) if (uname(&un) >= 0) { sysname = un.sysname; + if (strcmp(sysname, "Linux") == 0) { + /* Force desktop, not mobile */ + sysname = "X11; Linux"; + } } len = snprintf(NULL, 0, NETSURF_UA_FORMAT_STRING, + sysname, netsurf_version_major, - netsurf_version_minor, - sysname); + netsurf_version_minor); ua_string = malloc(len + 1); if (!ua_string) { /** \todo this needs handling better */ @@ -59,9 +64,9 @@ user_agent_build_string(void) } snprintf(ua_string, len + 1, NETSURF_UA_FORMAT_STRING, + sysname, netsurf_version_major, - netsurf_version_minor, - sysname); + netsurf_version_minor); core_user_agent_string = ua_string; diff --git a/utils/utf8.c b/utils/utf8.c index f0ac0c9b2..3eedd0810 100644 --- a/utils/utf8.c +++ b/utils/utf8.c @@ -32,6 +32,7 @@ #include "utils/log.h" #include "utils/utf8.h" +#include "netsurf/inttypes.h" #include "netsurf/utf8.h" #include "desktop/gui_internal.h" @@ -44,7 +45,7 @@ uint32_t utf8_to_ucs4(const char *s_in, size_t l) parserutils_error perror; perror = parserutils_charset_utf8_to_ucs4((const uint8_t *) s_in, l, - &ucs4, &len); + &ucs4, &len); if (perror != PARSERUTILS_OK) ucs4 = 0xfffd; @@ -106,7 +107,7 @@ size_t utf8_char_byte_length(const char *s) parserutils_error perror; perror = parserutils_charset_utf8_char_byte_length((const uint8_t *) s, - &len); + &len); assert(perror == PARSERUTILS_OK); return len; @@ -131,7 +132,7 @@ size_t utf8_next(const char *s, size_t l, size_t o) parserutils_error perror; perror = parserutils_charset_utf8_next((const uint8_t *) s, l, o, - &next); + &next); assert(perror == PARSERUTILS_OK); return next; @@ -151,6 +152,47 @@ static inline void utf8_clear_cd_cache(void) last_cd.cd = 0; } +/** + * obtain a cached conversion descriptor + * + * either return the cached conversion descriptor or create one if required + */ +static nserror +get_cached_cd(const char *enc_from, const char *enc_to, iconv_t *cd_out) +{ + iconv_t cd; + /* we cache the last used conversion descriptor, + * so check if we're trying to use it here */ + if (strncasecmp(last_cd.from, enc_from, sizeof(last_cd.from)) == 0 && + strncasecmp(last_cd.to, enc_to, sizeof(last_cd.to)) == 0 && + last_cd.cd != 0) { + *cd_out = last_cd.cd; + return NSERROR_OK; + } + + /* no match, so create a new cd */ + cd = iconv_open(enc_to, enc_from); + if (cd == (iconv_t) -1) { + if (errno == EINVAL) { + return NSERROR_BAD_ENCODING; + } + /* default to no memory */ + return NSERROR_NOMEM; + } + + /* close the last cd - we don't care if this fails */ + if (last_cd.cd) { + iconv_close(last_cd.cd); + } + + /* and safely copy the to/from/cd data into last_cd */ + snprintf(last_cd.from, sizeof(last_cd.from), "%s", enc_from); + snprintf(last_cd.to, sizeof(last_cd.to), "%s", enc_to); + *cd_out = last_cd.cd = cd; + + return NSERROR_OK; +} + /* exported interface documented in utils/utf8.h */ nserror utf8_finalise(void) { @@ -168,95 +210,72 @@ nserror utf8_finalise(void) * Convert a string from one encoding to another * * \param string The NULL-terminated string to convert - * \param len Length of input string to consider (in bytes), or 0 + * \param slen Length of input string to consider (in bytes), or 0 * \param from The encoding name to convert from * \param to The encoding name to convert to - * \param result Pointer to location in which to store result. - * \param result_len Pointer to location in which to store result length. + * \param result_out Pointer to location in which to store result. + * \param result_len_out Pointer to location in which to store result length. * \return NSERROR_OK for no error, NSERROR_NOMEM on allocation error, * NSERROR_BAD_ENCODING for a bad character encoding */ static nserror utf8_convert(const char *string, - size_t len, + size_t slen, const char *from, const char *to, - char **result, - size_t *result_len) + char **result_out, + size_t *result_len_out) { iconv_t cd; - char *temp, *out, *in; - size_t slen, rlen; - - assert(string && from && to && result); - - if (string[0] == '\0') { - /* On AmigaOS, iconv() returns an error if we pass an - * empty string. This prevents iconv() being called as - * there is no conversion necessary anyway. */ - *result = strdup(""); - if (!(*result)) { - *result = NULL; - return NSERROR_NOMEM; - } + char *temp, *out, *in, *result; + size_t result_len; + nserror res; - return NSERROR_OK; + assert(string && from && to && result_out); + + /* calculate the source length if not given */ + if (slen==0) { + slen = strlen(string); } - if (strcasecmp(from, to) == 0) { - /* conversion from an encoding to itself == strdup */ - slen = len ? len : strlen(string); - *(result) = strndup(string, slen); - if (!(*result)) { - *(result) = NULL; + /* process the empty string separately avoiding any conversion + * check for the source and destination encoding being the same + * + * This optimisation is necessary on AmigaOS as iconv() + * returns an error if an empty string is passed. + */ + if ((slen == 0) || (strcasecmp(from, to) == 0)) { + *result_out = strndup(string, slen); + if (*result_out == NULL) { return NSERROR_NOMEM; } + if (result_len_out != NULL) { + *result_len_out = slen; + } return NSERROR_OK; } in = (char *)string; - /* we cache the last used conversion descriptor, - * so check if we're trying to use it here */ - if (strncasecmp(last_cd.from, from, sizeof(last_cd.from)) == 0 && - strncasecmp(last_cd.to, to, sizeof(last_cd.to)) == 0) { - cd = last_cd.cd; - } - else { - /* no match, so create a new cd */ - cd = iconv_open(to, from); - if (cd == (iconv_t)-1) { - if (errno == EINVAL) - return NSERROR_BAD_ENCODING; - /* default to no memory */ - return NSERROR_NOMEM; - } - - /* close the last cd - we don't care if this fails */ - if (last_cd.cd) - iconv_close(last_cd.cd); - - /* and copy the to/from/cd data into last_cd */ - snprintf(last_cd.from, sizeof(last_cd.from), "%s", from); - snprintf(last_cd.to, sizeof(last_cd.to), "%s", to); - last_cd.cd = cd; + res = get_cached_cd(from, to, &cd); + if (res != NSERROR_OK) { + return res; } - slen = len ? len : strlen(string); /* Worst case = ASCII -> UCS4, so allocate an output buffer * 4 times larger than the input buffer, and add 4 bytes at * the end for the NULL terminator */ - rlen = slen * 4 + 4; + result_len = slen * 4 + 4; - temp = out = malloc(rlen); + temp = out = malloc(result_len); if (!out) { return NSERROR_NOMEM; } /* perform conversion */ - if (iconv(cd, (void *) &in, &slen, &out, &rlen) == (size_t)-1) { + if (iconv(cd, (void *) &in, &slen, &out, &result_len) == (size_t)-1) { free(temp); /* clear the cached conversion descriptor as it's invalid */ if (last_cd.cd) @@ -270,19 +289,22 @@ utf8_convert(const char *string, return NSERROR_NOMEM; } - *(result) = realloc(temp, out - temp + 4); - if (!(*result)) { + result_len = out - temp; + + /* resize buffer allowing for null termination */ + result = realloc(temp, result_len + 4); + if (result == NULL) { free(temp); - *(result) = NULL; /* for sanity's sake */ return NSERROR_NOMEM; } /* NULL terminate - needs 4 characters as we may have * converted to UTF-32 */ - memset((*result) + (out - temp), 0, 4); + memset(result + result_len, 0, 4); - if (result_len != NULL) { - *result_len = (out - temp); + *result_out = result; + if (result_len_out != NULL) { + *result_len_out = result_len; } return NSERROR_OK; @@ -290,14 +312,14 @@ utf8_convert(const char *string, /* exported interface documented in utils/utf8.h */ nserror utf8_to_enc(const char *string, const char *encname, - size_t len, char **result) + size_t len, char **result) { return utf8_convert(string, len, "UTF-8", encname, result, NULL); } /* exported interface documented in utils/utf8.h */ nserror utf8_from_enc(const char *string, const char *encname, - size_t len, char **result, size_t *result_len) + size_t len, char **result, size_t *result_len) { return utf8_convert(string, len, encname, "UTF-8", result, result_len); } @@ -325,10 +347,10 @@ utf8_convert_html_chunk(iconv_t cd, return NSERROR_NOMEM; ucs4 = utf8_to_ucs4(chunk, inlen); - esclen = snprintf(escape, sizeof(escape), "&#x%06x;", ucs4); + esclen = snprintf(escape, sizeof(escape), "&#x%06"PRIx32";", ucs4); pescape = escape; ret = iconv(cd, (void *) &pescape, &esclen, - (void *) out, outlen); + (void *) out, outlen); if (ret == (size_t) -1) return NSERROR_NOMEM; @@ -340,45 +362,26 @@ utf8_convert_html_chunk(iconv_t cd, return NSERROR_OK; } + + /* exported interface documented in utils/utf8.h */ nserror -utf8_to_html(const char *string, const char *encname, size_t len, char **result) +utf8_to_html(const char *string, const char *encname, size_t len, char **result_out) { iconv_t cd; const char *in; - char *out, *origout; + char *out, *origout, *result; size_t off, prev_off, inlen, outlen, origoutlen, esclen; nserror ret; char *pescape, escape[11]; + nserror res; if (len == 0) len = strlen(string); - /* we cache the last used conversion descriptor, - * so check if we're trying to use it here */ - if (strncasecmp(last_cd.from, "UTF-8", sizeof(last_cd.from)) == 0 && - strncasecmp(last_cd.to, encname, - sizeof(last_cd.to)) == 0 && - last_cd.cd != 0) { - cd = last_cd.cd; - } else { - /* no match, so create a new cd */ - cd = iconv_open(encname, "UTF-8"); - if (cd == (iconv_t) -1) { - if (errno == EINVAL) - return NSERROR_BAD_ENCODING; - /* default to no memory */ - return NSERROR_NOMEM; - } - - /* close the last cd - we don't care if this fails */ - if (last_cd.cd) - iconv_close(last_cd.cd); - - /* and safely copy the to/from/cd data into last_cd */ - snprintf(last_cd.from, sizeof(last_cd.from), "UTF-8"); - snprintf(last_cd.to, sizeof(last_cd.to), "%s", encname); - last_cd.cd = cd; + res = get_cached_cd("UTF-8", encname, &cd); + if (res != NSERROR_OK) { + return res; } /* Worst case is ASCII -> UCS4, with all characters escaped: @@ -398,13 +401,13 @@ utf8_to_html(const char *string, const char *encname, size_t len, char **result) while (off < len) { /* Must escape '&', '<', and '>' */ if (string[off] == '&' || string[off] == '<' || - string[off] == '>') { + string[off] == '>') { if (off - prev_off > 0) { /* Emit chunk */ in = string + prev_off; inlen = off - prev_off; ret = utf8_convert_html_chunk(cd, in, inlen, - &out, &outlen); + &out, &outlen); if (ret != NSERROR_OK) { free(origout); iconv_close(cd); @@ -415,10 +418,10 @@ utf8_to_html(const char *string, const char *encname, size_t len, char **result) /* Emit mandatory escape */ esclen = snprintf(escape, sizeof(escape), - "&#x%06x;", string[off]); + "&#x%06x;", string[off]); pescape = escape; ret = utf8_convert_html_chunk(cd, pescape, esclen, - &out, &outlen); + &out, &outlen); if (ret != NSERROR_OK) { free(origout); iconv_close(cd); @@ -450,11 +453,12 @@ utf8_to_html(const char *string, const char *encname, size_t len, char **result) outlen -= 4; /* Shrink-wrap */ - *result = realloc(origout, origoutlen - outlen); - if (*result == NULL) { + result = realloc(origout, origoutlen - outlen); + if (result == NULL) { free(origout); return NSERROR_NOMEM; } + *result_out = result; return NSERROR_OK; } diff --git a/utils/utils.h b/utils/utils.h index 3995071cd..cb9e04b45 100644 --- a/utils/utils.h +++ b/utils/utils.h @@ -89,4 +89,31 @@ */ bool is_dir(const char *path); +/** + * switch fall through + */ +#if defined __cplusplus && defined __has_cpp_attribute + #if __has_cpp_attribute(fallthrough) && __cplusplus >= __has_cpp_attribute(fallthrough) + #define fallthrough [[fallthrough]] + #elif __has_cpp_attribute(gnu::fallthrough) && __STDC_VERSION__ >= __has_cpp_attribute(gnu::fallthrough) + #define fallthrough [[gnu::fallthrough]] + #elif __has_cpp_attribute(clang::fallthrough) && __STDC_VERSION__ >= __has_cpp_attribute(clang::fallthrough) + #define fallthrough [[clang::fallthrough]] + #endif +#elif defined __STDC_VERSION__ && defined __has_c_attribute + #if __has_c_attribute(fallthrough) && __STDC_VERSION__ >= __has_c_attribute(fallthrough) + #define fallthrough [[fallthrough]] + #endif +#endif +#if !defined fallthrough && defined __has_attribute + #if __has_attribute(__fallthrough__) + #define fallthrough __attribute__((__fallthrough__)) + #endif +#endif +#if !defined fallthrough +/* early gcc and clang have no implicit fallthrough warning */ + #define fallthrough do {} while(0) +#endif + + #endif |