diff --git a/amiga/gui.c b/amiga/gui.c index b7f3285..dc49a69 100644 --- a/amiga/gui.c +++ b/amiga/gui.c @@ -4996,9 +4996,21 @@ static nserror gui_window_set_url(struct gui_window *g, nsurl *url) if(!g) return NSERROR_OK; if (g == g->shared->gw) { - RefreshSetGadgetAttrs((struct Gadget *)g->shared->objects[GID_URL], - g->shared->win, NULL, STRINGA_TextVal, - nsurl_access(url), TAG_DONE); + if(nsoption_bool(display_decoded_idn) == false) { + RefreshSetGadgetAttrs((struct Gadget *)g->shared->objects[GID_URL], + g->shared->win, NULL, + STRINGA_TextVal, nsurl_access(url), + TAG_DONE); + } else { + char *idn_url = nsurl_access_utf8(url); + char *idn_url_lc = ami_utf8_easy(idn_url); + RefreshSetGadgetAttrs((struct Gadget *)g->shared->objects[GID_URL], + g->shared->win, NULL, + STRINGA_TextVal, idn_url_lc, + TAG_DONE); + free(idn_url); + ami_utf8_free(idn_url_lc); + } } 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..dc03d94 100644 --- a/gtk/scaffolding.c +++ b/gtk/scaffolding.c @@ -2346,7 +2346,13 @@ nserror gui_window_set_url(struct gui_window *gw, nsurl *url) 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) == false) { + gtk_entry_set_text(GTK_ENTRY(g->url_bar), nsurl_access(url)); + } else { + char *idn_url = nsurl_access_utf8(url); + gtk_entry_set_text(GTK_ENTRY(g->url_bar), idn_url); + free(idn_url); + } 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..af84174 100644 --- a/render/html_interaction.c +++ b/render/html_interaction.c @@ -300,6 +300,7 @@ 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 *idn_url = NULL; const char *target = 0; char status_buffer[200]; const char *status = 0; @@ -814,12 +815,22 @@ 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) { + idn_url = nsurl_access_utf8(url); + } + if (title) { snprintf(status_buffer, sizeof status_buffer, "%s: %s", - nsurl_access(url), title); - status = status_buffer; - } else - status = nsurl_access(url); + idn_url ? idn_url : nsurl_access(url), title); + } else { + snprintf(status_buffer, sizeof status_buffer, "%s", + idn_url ? idn_url : nsurl_access(url)); + } + + status = status_buffer; + + if (idn_url != NULL) + free(idn_url); pointer = get_pointer_shape(url_box, imagemap); diff --git a/riscos/window.c b/riscos/window.c index 097ab9e..dbed46d 100644 --- a/riscos/window.c +++ b/riscos/window.c @@ -1038,8 +1038,16 @@ 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) { + char *idn_url = NULL; + if (g->toolbar) { - ro_toolbar_set_url(g->toolbar, nsurl_access(url), true, false); + if (nsoption_bool(display_decoded_idn) == false) { + ro_toolbar_set_url(g->toolbar, nsurl_access(url), true, false); + } else { + idn_url = nsurl_access_utf8(url); + ro_toolbar_set_url(g->toolbar, idn_url, true, false); + free(idn_url); + } ro_gui_url_complete_start(g->toolbar); } diff --git a/utils/nsurl.c b/utils/nsurl.c index 8d53be8..78647b4 100644 --- a/utils/nsurl.c +++ b/utils/nsurl.c @@ -1698,6 +1698,56 @@ const char *nsurl_access(const nsurl *url) return url->string; } +char *nsurl_access_utf8(const nsurl *url) +{ + lwc_string *host; + char *idna_host; + size_t idna_host_len; + char *scheme; + size_t scheme_len; + char *path; + size_t path_len; + char *idna_url; + size_t idna_url_len; + + assert(url != NULL); + + host = nsurl_get_component(url, NSURL_HOST); + + if(host == NULL) { + return strdup(url->string); + } + + if (idna_decode(lwc_string_data(host), lwc_string_length(host), + &idna_host, &idna_host_len) != NSERROR_OK) { + lwc_string_unref(host); + return strdup(url->string); + } + + lwc_string_unref(host); + + if (nsurl_get(url, NSURL_SCHEME | NSURL_CREDENTIALS, + &scheme, &scheme_len) != NSERROR_OK) { + return strdup(url->string); + } + + if (nsurl_get(url, NSURL_PORT | NSURL_PATH | NSURL_QUERY | NSURL_FRAGMENT, + &path, &path_len) != NSERROR_OK) { + return strdup(url->string); + } + + idna_url_len = scheme_len + idna_host_len + path_len + 1; /* +1 for \0 */ + idna_url = malloc(idna_url_len); + + if (idna_url == NULL) { + return strdup(url->string); + } + + snprintf(idna_url, idna_url_len, "%s%s%s", scheme, idna_host, path); + + return(idna_url); +} + /* exported interface, documented in nsurl.h */ const char *nsurl_access_leaf(const nsurl *url) diff --git a/utils/nsurl.h b/utils/nsurl.h index b84f55e..07d73f1 100644 --- a/utils/nsurl.h +++ b/utils/nsurl.h @@ -181,6 +181,20 @@ const char *nsurl_access(const nsurl *url); /** + * Access a NetSurf URL object as a UTF-8 string (for human readable IDNA) + * + * \param url NetSurf URL to retrieve a string pointer for. + * \return the required string + * + * It is up to the client to free the returned string when they have + * finished with it. + * + * The returned string has a trailing '\0'. + */ +char *nsurl_access_utf8(const nsurl *url); + + +/** * Access a URL's path leaf as a string * * \param url NetSurf URL to retrieve a string pointer for.