[PATCH] Display decoded IDNs

Chris Young chris.young at unsatisfactorysoftware.co.uk
Mon Jul 20 19:29:24 BST 2015


Hi

I finally got round to the second part of my IDNA work, which is
allowing the decoded versions of the domain names to be displayed in
the status and URL bars.

This adds an option display_decoded_idn (default is false) which, when
enabled, will pass decoded UTF-8 URLs to the status bar and - with an
appropriate frontend tweak (I've done GTK, RISC OS and Amiga) - also
to the URL bar.  When switched off operation is as at present and the
code change is minimal.

This is in branch chris/display-idna and attached for convenience.

Chris
-------------- next part --------------
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.


More information about the netsurf-dev mailing list