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.

Reply via email to