md2html: Implement URL escaping.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
diff --git a/md2html/md2html.c b/md2html/md2html.c
index 5d830ff..221ac50 100644
--- a/md2html/md2html.c
+++ b/md2html/md2html.c
@@ -98,7 +98,10 @@ membuf_append(struct membuffer* buf, const char* data, MD_SIZE size)
#define MEMBUF_APPEND_LITERAL(buf, literal) membuf_append((buf), (literal), strlen(literal))
-#define HTML_NEED_ESCAPE(ch) ((ch) == '&' || (ch) == '<' || (ch) == '>' || (ch) == '"')
+#define ISDIGIT(ch) ('0' <= (ch) && (ch) <= '9')
+#define ISLOWER(ch) ('a' <= (ch) && (ch) <= 'z')
+#define ISUPPER(ch) ('A' <= (ch) && (ch) <= 'Z')
+#define ISALNUM(ch) (ISLOWER(ch) || ISUPPER(ch) || ISDIGIT(ch))
static void
membuf_append_escaped(struct membuffer* buf, const char* data, MD_SIZE size)
@@ -107,6 +110,8 @@ membuf_append_escaped(struct membuffer* buf, const char* data, MD_SIZE size)
MD_OFFSET off = 0;
/* Some characters need to be escaped in normal HTML text. */
+ #define HTML_NEED_ESCAPE(ch) \
+ ((ch) == '&' || (ch) == '<' || (ch) == '>' || (ch) == '"')
while(1) {
while(off < size && !HTML_NEED_ESCAPE(data[off]))
@@ -129,6 +134,44 @@ membuf_append_escaped(struct membuffer* buf, const char* data, MD_SIZE size)
}
}
+static void
+membuf_append_url_escaped(struct membuffer* buf, const char* data, MD_SIZE size)
+{
+ static const uint8_t hex_chars[] = "0123456789ABCDEF";
+ MD_OFFSET beg = 0;
+ MD_OFFSET off = 0;
+
+ #define URL_NEED_ESCAPE(ch) \
+ (!ISALNUM(ch) && strchr("-_.+!*'(),%#@?=;:/,+&$", ch) == NULL)
+
+ while(1) {
+ while(off < size && !URL_NEED_ESCAPE(data[off]))
+ off++;
+ if(off > beg)
+ membuf_append(buf, data + beg, off - beg);
+
+ if(off < size) {
+ char hex[3];
+
+ switch(data[off]) {
+ case '&': MEMBUF_APPEND_LITERAL(buf, "&"); break;
+ case '\'': MEMBUF_APPEND_LITERAL(buf, "'"); break;
+ default:
+ hex[0] = '%';
+ hex[1] = hex_chars[((unsigned)data[off] >> 4) & 0xf];
+ hex[2] = hex_chars[((unsigned)data[off] >> 0) & 0xf];
+ membuf_append(buf, hex, 3);
+ break;
+ }
+ off++;
+ } else {
+ break;
+ }
+
+ beg = off;
+ }
+}
+
/*****************************************
*** HTML rendering helper functions ***
@@ -153,7 +196,7 @@ static void
open_a_span(struct membuffer* out, const MD_SPAN_A_DETAIL* det)
{
MEMBUF_APPEND_LITERAL(out, "<a href=\"");
- membuf_append_escaped(out, det->href, det->href_size);
+ membuf_append_url_escaped(out, det->href, det->href_size);
if(det->title != NULL) {
MEMBUF_APPEND_LITERAL(out, "\" title=\"");
@@ -167,7 +210,7 @@ static void
open_img_span(struct membuffer* out, const MD_SPAN_IMG_DETAIL* det)
{
MEMBUF_APPEND_LITERAL(out, "<img src=\"");
- membuf_append_escaped(out, det->src, det->src_size);
+ membuf_append_url_escaped(out, det->src, det->src_size);
MEMBUF_APPEND_LITERAL(out, "\" alt=\"");
membuf_append_escaped(out, det->alt, det->alt_size);