On Mon, 20 Jul 2015 22:09:33 +0100, Michael Drake wrote: > The nsurl_access function is purely a convenience to access an internal > string that the caller does not own. > > If you make a function which passes ownership of the string to the > caller, it should be in the style of nsurl_get and return an nserror.
Thanks for your comments. I've updated that function to return an nserror. I haven't renamed it, as it always returns something very similar to nsurl_access. Chris
diff --git a/amiga/gui.c b/amiga/gui.c index b7f3285..207a496 100644 --- a/amiga/gui.c +++ b/amiga/gui.c @@ -4993,12 +4993,28 @@ static void gui_window_set_status(struct gui_window *g, const char *text) static nserror gui_window_set_url(struct gui_window *g, nsurl *url) { + size_t idn_url_l; + char *idn_url_s = NULL; + char *url_lc = NULL; + if(!g) return NSERROR_OK; - if (g == g->shared->gw) { + if(g == g->shared->gw) { + if(nsoption_bool(display_decoded_idn) == true) { + if (nsurl_access_utf8(url, &idn_url_s, &idn_url_l) == NSERROR_OK) { + url_lc = ami_utf8_easy(idn_url_s); + } + } + RefreshSetGadgetAttrs((struct Gadget *)g->shared->objects[GID_URL], - g->shared->win, NULL, STRINGA_TextVal, - nsurl_access(url), TAG_DONE); + g->shared->win, NULL, + STRINGA_TextVal, url_lc ? url_lc : nsurl_access(url), + TAG_DONE); + + if(url_lc) { + ami_utf8_free(url_lc); + if(idn_url_s) free(idn_url_s); + } } ami_update_buttons(g->shared); diff --git a/desktop/options.h b/desktop/options.h index 33ecb75..f01261e 100644 --- a/desktop/options.h +++ b/desktop/options.h @@ -185,6 +185,9 @@ NSOPTION_UINT(min_reflow_period, DEFAULT_REFLOW_PERIOD) /* use core selection menu */ NSOPTION_BOOL(core_select_menu, false) +/* display decoded international domain names */ +NSOPTION_BOOL(display_decoded_idn, false) + /******** Fetcher options ********/ /** Maximum simultaneous active fetchers */ diff --git a/gtk/scaffolding.c b/gtk/scaffolding.c index 4506ac2..a9904de 100644 --- a/gtk/scaffolding.c +++ b/gtk/scaffolding.c @@ -2343,10 +2343,21 @@ void nsgtk_window_set_title(struct gui_window *gw, const char *title) nserror gui_window_set_url(struct gui_window *gw, nsurl *url) { struct nsgtk_scaffolding *g; + size_t idn_url_l; + char *idn_url_s = NULL; g = nsgtk_get_scaffold(gw); if (g->top_level == gw) { - gtk_entry_set_text(GTK_ENTRY(g->url_bar), nsurl_access(url)); + if (nsoption_bool(display_decoded_idn) == true) { + if (nsurl_access_utf8(url, &idn_url_s, &idn_url_l) != NSERROR_OK) + idn_url_s = NULL; + } + + gtk_entry_set_text(GTK_ENTRY(g->url_bar), idn_url_s ? idn_url_s : nsurl_access(url)); + + if(idn_url_s) + free(idn_url_s); + gtk_editable_set_position(GTK_EDITABLE(g->url_bar), -1); } return NSERROR_OK; diff --git a/render/html_interaction.c b/render/html_interaction.c index 6e2a2df..1b2e5b9 100644 --- a/render/html_interaction.c +++ b/render/html_interaction.c @@ -300,6 +300,8 @@ void html_mouse_action(struct content *c, struct browser_window *bw, enum { ACTION_NONE, ACTION_SUBMIT, ACTION_GO } action = ACTION_NONE; const char *title = 0; nsurl *url = 0; + char *url_s = NULL; + size_t url_l = 0; const char *target = 0; char status_buffer[200]; const char *status = 0; @@ -814,12 +816,26 @@ void html_mouse_action(struct content *c, struct browser_window *bw, y - html_object_pos_y); } } else if (url) { + if (nsoption_bool(display_decoded_idn) == true) { + if (nsurl_access_utf8(url, &url_s, &url_l) != NSERROR_OK) { + /* Unable to obtain a decoded IDN. This is not a fatal error. + * Ensure the string pointer is NULL so we use the encoded version. */ + url_s = NULL; + } + } + if (title) { snprintf(status_buffer, sizeof status_buffer, "%s: %s", - nsurl_access(url), title); - status = status_buffer; - } else - status = nsurl_access(url); + url_s ? url_s : nsurl_access(url), title); + } else { + snprintf(status_buffer, sizeof status_buffer, "%s", + url_s ? url_s : nsurl_access(url)); + } + + status = status_buffer; + + if (url_s != NULL) + free(url_s); pointer = get_pointer_shape(url_box, imagemap); diff --git a/riscos/window.c b/riscos/window.c index 097ab9e..59c24ac 100644 --- a/riscos/window.c +++ b/riscos/window.c @@ -1038,8 +1038,20 @@ void gui_window_set_pointer(struct gui_window *g, gui_pointer_shape shape) /* exported function documented in riscos/window.h */ nserror ro_gui_window_set_url(struct gui_window *g, nsurl *url) { + size_t idn_url_l; + char *idn_url_s = NULL; + if (g->toolbar) { - ro_toolbar_set_url(g->toolbar, nsurl_access(url), true, false); + if (nsoption_bool(display_decoded_idn) == true) { + if (nsurl_access_utf8(url, &idn_url_s, &idn_url_l) != NSERROR_OK) + idn_url_s = NULL; + } + + ro_toolbar_set_url(g->toolbar, idn_url_s ? idn_url_s : nsurl_access(url), true, false); + + if (idn_url_s) + free(idn_url_s); + ro_gui_url_complete_start(g->toolbar); } diff --git a/utils/nsurl.c b/utils/nsurl.c index 8d53be8..ed6d896 100644 --- a/utils/nsurl.c +++ b/utils/nsurl.c @@ -1700,6 +1700,57 @@ const char *nsurl_access(const nsurl *url) /* exported interface, documented in nsurl.h */ +nserror nsurl_access_utf8(const nsurl *url, char **url_s, size_t *url_l) +{ + nserror err; + lwc_string *host; + char *idna_host; + size_t idna_host_len; + char *scheme; + size_t scheme_len; + char *path; + size_t path_len; + + assert(url != NULL); + + host = nsurl_get_component(url, NSURL_HOST); + + if(host == NULL) + return NSERROR_BAD_URL; + + err = idna_decode(lwc_string_data(host), lwc_string_length(host), + &idna_host, &idna_host_len); + + lwc_string_unref(host); + + if (err != NSERROR_OK) + return err; + + err = nsurl_get(url, NSURL_SCHEME | NSURL_CREDENTIALS, + &scheme, &scheme_len); + + if (err != NSERROR_OK) + return err; + + err = nsurl_get(url, NSURL_PORT | NSURL_PATH | NSURL_QUERY | NSURL_FRAGMENT, + &path, &path_len); + + if (err != NSERROR_OK) + return err; + + *url_l = scheme_len + idna_host_len + path_len + 1; /* +1 for \0 */ + *url_s = malloc(*url_l); + + if (*url_s == NULL) + return NSERROR_NOMEM; + + snprintf(*url_s, *url_l, "%s%s%s", scheme, idna_host, path); + + return NSERROR_OK; +} + + +/* exported interface, documented in nsurl.h */ const char *nsurl_access_leaf(const nsurl *url) { size_t path_len; diff --git a/utils/nsurl.h b/utils/nsurl.h index b84f55e..85e46df 100644 --- a/utils/nsurl.h +++ b/utils/nsurl.h @@ -181,6 +181,24 @@ const char *nsurl_access(const nsurl *url); /** + * Access a NetSurf URL object as a UTF-8 string (for human readable IDNs) + * + * \param url NetSurf URL object + * \param url_s Returns a url string + * \param url_l Returns length of url_s + * \return NSERROR_OK on success, appropriate error otherwise + * + * If return value != NSERROR_OK, nothing will be returned in url_s or url_l. + * + * The string returned in url_s is owned by the client and it is up to them + * to free it. It includes a trailing '\0'. + * + * The length returned in url_l excludes the trailing '\0'. + */ +nserror nsurl_access_utf8(const nsurl *url, char **url_s, size_t *url_l); + + +/** * Access a URL's path leaf as a string * * \param url NetSurf URL to retrieve a string pointer for.