[yelp] Allow special characters in info links.



commit 1914a15d9881bf8175bab4d790e7671557589064
Author: Rupert Swarbrick <rswarbrick gmail com>
Date:   Wed Sep 15 10:42:56 2010 +0100

    Allow special characters in info links.
    
    If an info file has a '<' in the title for example (section 12.1 of
    info:autoconf has) then when clicked the url gets "url-encoded" to
    something like "%3c-...". This patch adds a url-decode stage to the
    parsing of info xrefs, which undoes this mangling.

 libyelp/yelp-uri.c |   72 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 72 insertions(+), 0 deletions(-)
---
diff --git a/libyelp/yelp-uri.c b/libyelp/yelp-uri.c
index 7010a24..a58e288 100644
--- a/libyelp/yelp-uri.c
+++ b/libyelp/yelp-uri.c
@@ -958,6 +958,66 @@ resolve_man_uri (YelpUri *uri)
     g_free (newarg);
 }
 
+/*
+  Return 1 if ch is a number from 0 to 9 or a letter a-f or A-F and 0
+  otherwise. This is sort of not utf8-safe, but since we are only
+  looking for 7-bit things, it doesn't matter.
+ */
+static int
+is_hex (gchar ch)
+{
+    if (((48 <= ch) && (ch <= 57)) ||
+        ((65 <= ch) && (ch <= 70)) ||
+        ((97 <= ch) && (ch <= 102)))
+        return 1;
+    return 0;
+}
+
+/*
+  Return a newly allocated string, where %ab for a,b in [0, f] is
+  replaced by the character it represents.
+ */
+static gchar*
+decode_url (const gchar *url)
+{
+    if (!url) return NULL;
+
+    unsigned int len = strlen (url) + 1;
+    int hex;
+    gchar *ret = g_new (gchar, len);
+    const gchar *ptr = url, *end = url+len;
+    gchar *retptr = ret, *tmp;
+
+    while (ptr < end) {
+        if (*ptr == '%' && is_hex(*(ptr + 1)) && is_hex(*(ptr + 2))) {
+            *retptr = *(ptr+1);
+            *(retptr+1) = *(ptr+2);
+            *(retptr+2) = '\0';
+
+            sscanf (retptr, "%x", &hex);
+
+            if (hex < 0 || hex > 127) {
+                g_warning ("Skipping non-7-bit character.");
+                ptr++;
+                continue;
+            }
+            *retptr = (gchar)hex;
+
+            retptr++;
+            ptr += 3;
+        }
+        else {
+            tmp = g_utf8_next_char(ptr);
+            memcpy (retptr, ptr, (tmp-ptr));
+            retptr += tmp-ptr;
+            ptr = tmp;
+        }
+    }
+    *retptr = '\0';
+
+    return ret;
+}
+
 static void
 resolve_info_uri (YelpUri *uri)
 {
@@ -1094,6 +1154,18 @@ resolve_xref_uri (YelpUri *uri)
         }
     }
 
+    if (priv->page_id &&
+        g_str_has_prefix (priv->docuri, "info:")) {
+        /*
+          Special characters get url-encoded when they get clicked on
+          as links. Info files, at least, don't want that so decode
+          the url again here.
+         */
+        gchar* tmp = priv->page_id;
+        priv->page_id = decode_url (priv->page_id);
+        g_free (tmp);
+    }
+
     if (g_str_has_prefix (priv->docuri, "ghelp:"))
         priv->fulluri = g_strconcat (priv->docuri,
                                      priv->page_id ? "?" : "",



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]