+
+bool uh_path_match(const char *prefix, const char *url)
+{
+ int len = strlen(prefix);
+
+ /* A prefix of "/" will - by definition - match any url */
+ if (prefix[0] == '/' && len == 1)
+ return true;
+
+ if (strncmp(url, prefix, len) != 0)
+ return false;
+
+ return url[len] == '/' || url[len] == 0;
+}
+
+char *uh_split_header(char *str)
+{
+ char *val;
+
+ val = strchr(str, ':');
+ if (!val)
+ return NULL;
+
+ *val = 0;
+ val++;
+
+ while (isspace(*val))
+ val++;
+
+ return val;
+}
+
+bool uh_addr_rfc1918(struct uh_addr *addr)
+{
+ uint32_t a;
+
+ if (addr->family != AF_INET)
+ return false;
+
+ a = htonl(addr->in.s_addr);
+ return ((a >= 0x0A000000) && (a <= 0x0AFFFFFF)) ||
+ ((a >= 0xAC100000) && (a <= 0xAC1FFFFF)) ||
+ ((a >= 0xC0A80000) && (a <= 0xC0A8FFFF));
+
+ return 0;
+}
+
+
+static bool is_html_special_char(char c)
+{
+ switch (c)
+ {
+ case 0x22:
+ case 0x26:
+ case 0x27:
+ case 0x3C:
+ case 0x3E:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+char *uh_htmlescape(const char *str)
+{
+ size_t len;
+ char *p, *copy;
+
+ for (p = str, len = 1; *p; p++)
+ if (is_html_special_char(*p))
+ len += 6; /* &#x??; */
+ else
+ len++;
+
+ copy = calloc(1, len);
+
+ if (!copy)
+ return NULL;
+
+ for (p = copy; *str; str++)
+ if (is_html_special_char(*str))
+ p += sprintf(p, "&#x%02x;", (unsigned int)*str);
+ else
+ *p++ = *str;
+
+ return copy;
+}