88 lines
2.1 KiB
C
88 lines
2.1 KiB
C
|
#include <assert.h>
|
||
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
|
||
|
#include "houdini.h"
|
||
|
|
||
|
#define ESCAPE_GROW_FACTOR(x) (((x) * 12) / 10) /* this is very scientific, yes */
|
||
|
|
||
|
/**
|
||
|
* According to the OWASP rules:
|
||
|
*
|
||
|
* & --> &
|
||
|
* < --> <
|
||
|
* > --> >
|
||
|
* " --> "
|
||
|
* ' --> ' ' is not recommended
|
||
|
* / --> / forward slash is included as it helps end an HTML entity
|
||
|
*
|
||
|
*/
|
||
|
static const char HTML_ESCAPE_TABLE[] = {
|
||
|
7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 7, 7, 0, 7, 7,
|
||
|
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||
|
0, 0, 1, 0, 0, 0, 2, 3, 0, 0, 0, 0, 0, 0, 0, 4,
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 6, 0,
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
};
|
||
|
|
||
|
static const char *HTML_ESCAPES[] = {
|
||
|
"",
|
||
|
""",
|
||
|
"&",
|
||
|
"'",
|
||
|
"/",
|
||
|
"<",
|
||
|
">",
|
||
|
"", // throw out control characters
|
||
|
};
|
||
|
|
||
|
void
|
||
|
houdini_escape_html0(struct buf *ob, const uint8_t *src, size_t size, int secure)
|
||
|
{
|
||
|
size_t i = 0, org, esc = 0;
|
||
|
|
||
|
bufgrow(ob, ESCAPE_GROW_FACTOR(size));
|
||
|
|
||
|
while (i < size) {
|
||
|
org = i;
|
||
|
while (i < size && (esc = HTML_ESCAPE_TABLE[src[i]]) == 0)
|
||
|
i++;
|
||
|
|
||
|
if (i > org)
|
||
|
bufput(ob, src + org, i - org);
|
||
|
|
||
|
/* escaping */
|
||
|
if (i >= size)
|
||
|
break;
|
||
|
|
||
|
/* The forward slash is only escaped in secure mode */
|
||
|
if (src[i] == '/' && !secure) {
|
||
|
bufputc(ob, '/');
|
||
|
} else if (HTML_ESCAPE_TABLE[src[i]] == 7) {
|
||
|
/* skip control characters */
|
||
|
} else {
|
||
|
bufputs(ob, HTML_ESCAPES[esc]);
|
||
|
}
|
||
|
|
||
|
i++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void
|
||
|
houdini_escape_html(struct buf *ob, const uint8_t *src, size_t size)
|
||
|
{
|
||
|
houdini_escape_html0(ob, src, size, 1);
|
||
|
}
|
||
|
|