8aa20a7f9c0ba348f99c4b0ab8fa4c3b2fc633e3
galt
  Fri Dec 13 13:12:33 2013 -0800
fixes #12337. better way to allow colons in urls by splitting htmlExpandUrl into two functions. the new one is called expandUrlOnBase and includes ftp support as well as http(s).
diff --git src/lib/htmlPage.c src/lib/htmlPage.c
index 74f9cf9..7f7be68 100644
--- src/lib/htmlPage.c
+++ src/lib/htmlPage.c
@@ -1086,58 +1086,39 @@
 		{
 		code = '?';
 		}
 	    in = e;
 	    in++;
 	    *out++ = code;
 	    }
 	}
     else
 	*out++ = c;
     }
 *out++ = 0;
 }
 
 
-char *htmlExpandUrl(char *base, char *url)
-/* Expand URL that is relative to base to stand on its own. 
- * Return NULL if it's not http or https. */
+char *expandUrlOnBase(char *base, char *url)
+/* Figure out first character past host name. Load up
+ * return string with protocol (if any) and host name. 
+ * It is assumed that url is relative to base and does not contain a protocol.*/
 {
 struct dyString *dy = NULL;
 char *hostName, *pastHostName;
-
-/* some mailto: have SGML char encoding, e.g a to hide from spambots */
-url = cloneString(url);	/* Clone because asciiEntityDecode may modify it. */
-asciiEntityDecode(url, url, strlen(url));
-
-/* In easiest case URL is actually absolute and begins with
- * protocol.  Just return clone of url. */
-if (startsWith("http:", url) || startsWith("https:", url))
-    return url;
-
-/* If it's got a colon, but no http or https, then it's some
- * protocol we don't understand, like a mailto.  Just return NULL. */
-if (strchr(url, ':') != NULL)
-    {
-    freez(&url);
-    return NULL;
-    }
-
-/* Figure out first character past host name. Load up
- * return string with protocol (if any) and host name. */
 dy = dyStringNew(256);
-if (startsWith("http:", base) || startsWith("https:", base))
+if (startsWith("http:", base) || startsWith("https:", base) || startsWith("ftp:", base))
     hostName = (strchr(base, ':') + 3);
 else
     hostName = base;
 pastHostName = strchr(hostName, '/');
 if (pastHostName == NULL)
     pastHostName = hostName + strlen(hostName);
 dyStringAppendN(dy, base, pastHostName - base);
 
 /* Add url to return string after host name. */
 if (startsWith("/", url))	/* New URL is absolute, just append to hostName */
     {
     dyStringAppend(dy, url);
     }
 else
     {
@@ -1156,34 +1137,59 @@
 	if (path != NULL)
 	     {
 	     dyStringAppend(dy, path);
 	     }
 	freez(&dir);
 	freez(&path);
 	}
     else
 	{
 	dyStringAppendN(dy, curDir, endDir-curDir);
 	if (lastChar(dy->string) != '/')
 	    dyStringAppendC(dy, '/');
 	dyStringAppend(dy, url);
 	}
     }
-freez(&url);
 return dyStringCannibalize(&dy);
 }
 
+char *htmlExpandUrl(char *base, char *url)
+/* Expand URL that is relative to base to stand on its own. 
+ * Return NULL if it's not http or https. */
+{
+
+/* some mailto: have SGML char encoding, e.g a to hide from spambots */
+url = cloneString(url);	/* Clone because asciiEntityDecode may modify it. */
+asciiEntityDecode(url, url, strlen(url));
+
+/* In easiest case URL is actually absolute and begins with
+ * protocol.  Just return clone of url. */
+if (startsWith("http:", url) || startsWith("https:", url))
+    return url;
+
+/* If it's got a colon, but no http or https, then it's some
+ * protocol we don't understand, like a mailto.  Just return NULL. */
+if (strchr(url, ':') != NULL)
+    {
+    freez(&url);
+    return NULL;
+    }
+char *result = expandUrlOnBase(base, url);
+freez(&url);
+return result;
+}
+
 static void appendCgiVar(struct dyString *dy, char *name, char *value)
 /* Append cgiVar with cgi-encoded value to dy. */
 {
 char *enc = NULL;
 if (value == NULL)
     value = "";
 enc = cgiEncode(value);
 if (dy->stringSize != 0)
     dyStringAppendC(dy, '&');
 dyStringAppend(dy, name);
 dyStringAppendC(dy, '=');
 dyStringAppend(dy, enc);
 freez(&enc);
 }