-
Notifications
You must be signed in to change notification settings - Fork 284
Expand file tree
/
Copy pathHtmlEscaper.java
More file actions
110 lines (104 loc) · 3.55 KB
/
HtmlEscaper.java
File metadata and controls
110 lines (104 loc) · 3.55 KB
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
package com.github.mustachejava.util;
import com.github.mustachejava.MustacheException;
import java.io.IOException;
import java.io.Writer;
/**
* Escapes user data that you wish to include in HTML pages.
*/
public class HtmlEscaper {
public static void escape(String value, Writer writer, boolean escapeEscaped) {
try {
int position = 0;
int length = value.length();
for (int i = 0; i < length; i++) {
char c = value.charAt(i);
if (c <= 13) {
writer.append(value, position, i);
writer.append("&#");
writer.append(String.valueOf((int)c));
writer.append(";");
position = i + 1;
} else {
switch (c) {
case '&':
// If we match an entity or char ref then keep it
// as is in the text. Otherwise, replace it.
if (!escapeEscaped && matchesEntityRef(i + 1, length, value)) {
// If we are at the beginning we can just keep going
if (position != 0) {
position = append(value, writer, position, i, "&");
}
} else {
position = append(value, writer, position, i, "&");
}
break;
case '<':
position = append(value, writer, position, i, "<");
break;
case '>':
position = append(value, writer, position, i, ">");
break;
case '"':
position = append(value, writer, position, i, """);
break;
case '\'':
position = append(value, writer, position, i, "'");
break;
case '=':
position = append(value, writer, position, i, "=");
break;
case '`':
position = append(value, writer, position, i, "`");
break;
}
}
}
writer.append(value, position, length);
} catch (IOException e) {
throw new MustacheException("Failed to encode value: " + value);
}
}
private static int append(String value, Writer writer, int position, int i, String replace) throws IOException {
// Append the clean text
writer.append(value, position, i);
// Append the encoded value
writer.append(replace);
// and advance the position past it
return i + 1;
}
// Matches all HTML named and character entity references
private static boolean matchesEntityRef(int position, int length, String value) {
for (int i = position; i < length; i++) {
char c = value.charAt(i);
switch (c) {
case ';':
// End of the entity
return i != position;
case '#':
// Switch to char reference
return i == position && matchesCharRef(i + 1, length, value);
default:
// Letters can be at the start
if (c >= 'a' && c <= 'z') continue;
if (c >= 'A' && c <= 'Z') continue;
if (i != position) {
// Can only appear in the middle
if (c >= '0' && c <= '9') continue;
}
return false;
}
}
// Didn't find ending ;
return false;
}
private static boolean matchesCharRef(int position, int length, String value) {
for (int i = position; i < length; i++) {
char c = value.charAt(i);
if (c == ';') {
return i != position;
} else if ((c >= '0' && c <= '9') || c == 'x' || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) {
} else return false;
}
return false;
}
}