]> git.lizzy.rs Git - rust.git/blob - src/rt/sundown/html/houdini_href_e.c
Ignore tests broken by failing on ICE
[rust.git] / src / rt / sundown / html / houdini_href_e.c
1 #include <assert.h>
2 #include <stdio.h>
3 #include <string.h>
4
5 #include "houdini.h"
6
7 #define ESCAPE_GROW_FACTOR(x) (((x) * 12) / 10)
8
9 /*
10  * The following characters will not be escaped:
11  *
12  *              -_.+!*'(),%#@?=;:/,+&$ alphanum
13  *
14  * Note that this character set is the addition of:
15  *
16  *      - The characters which are safe to be in an URL
17  *      - The characters which are *not* safe to be in
18  *      an URL because they are RESERVED characters.
19  *
20  * We asume (lazily) that any RESERVED char that
21  * appears inside an URL is actually meant to
22  * have its native function (i.e. as an URL 
23  * component/separator) and hence needs no escaping.
24  *
25  * There are two exceptions: the chacters & (amp)
26  * and ' (single quote) do not appear in the table.
27  * They are meant to appear in the URL as components,
28  * yet they require special HTML-entity escaping
29  * to generate valid HTML markup.
30  *
31  * All other characters will be escaped to %XX.
32  *
33  */
34 static const char HREF_SAFE[] = {
35         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
36         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
37         0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 
38         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 
39         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
40         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 
41         0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
42         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 
43         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
44         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
45         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
46         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
47         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
48         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
49         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
50         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
51 };
52
53 void
54 houdini_escape_href(struct buf *ob, const uint8_t *src, size_t size)
55 {
56         static const char hex_chars[] = "0123456789ABCDEF";
57         size_t  i = 0, org;
58         char hex_str[3];
59
60         bufgrow(ob, ESCAPE_GROW_FACTOR(size));
61         hex_str[0] = '%';
62
63         while (i < size) {
64                 org = i;
65                 while (i < size && HREF_SAFE[src[i]] != 0)
66                         i++;
67
68                 if (i > org)
69                         bufput(ob, src + org, i - org);
70
71                 /* escaping */
72                 if (i >= size)
73                         break;
74
75                 switch (src[i]) {
76                 /* amp appears all the time in URLs, but needs
77                  * HTML-entity escaping to be inside an href */
78                 case '&': 
79                         BUFPUTSL(ob, "&amp;");
80                         break;
81
82                 /* the single quote is a valid URL character
83                  * according to the standard; it needs HTML
84                  * entity escaping too */
85                 case '\'':
86                         BUFPUTSL(ob, "&#x27;");
87                         break;
88                 
89                 /* the space can be escaped to %20 or a plus
90                  * sign. we're going with the generic escape
91                  * for now. the plus thing is more commonly seen
92                  * when building GET strings */
93 #if 0
94                 case ' ':
95                         bufputc(ob, '+');
96                         break;
97 #endif
98
99                 /* every other character goes with a %XX escaping */
100                 default:
101                         hex_str[1] = hex_chars[(src[i] >> 4) & 0xF];
102                         hex_str[2] = hex_chars[src[i] & 0xF];
103                         bufput(ob, hex_str, 3);
104                 }
105
106                 i++;
107         }
108 }