1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.apache.struts2.views.util;
23
24
25 /***
26 * This class handles HTML escaping of text.
27 * It was written and optimized to be as fast as possible.
28 *
29 */
30 public class TextUtil {
31
32 protected static final int MAX_LENGTH = 300;
33
34 /***
35 * We use arrays of char in the lookup table because it is faster
36 * appending this to a StringBuilder than appending a String
37 */
38 protected static final char[][] _stringChars = new char[MAX_LENGTH][];
39
40 static {
41
42 initMapping();
43 }
44
45
46 /***
47 * Call escapeHTML(s, false)
48 */
49 public static final String escapeHTML(String s) {
50 return escapeHTML(s, false);
51 }
52
53 /***
54 * Escape HTML.
55 *
56 * @param s string to be escaped
57 * @param escapeEmpty if true, then empty string will be escaped.
58 */
59 public static final String escapeHTML(String s, boolean escapeEmpty) {
60 int len = s.length();
61
62 if (len == 0) {
63 return s;
64 }
65
66 if (!escapeEmpty) {
67 String trimmed = s.trim();
68
69 if ((trimmed.length() == 0) || ("\"\"").equals(trimmed)) {
70 return s;
71 }
72 }
73
74 int i = 0;
75
76
77
78 do {
79 int index = s.charAt(i);
80
81 if (index >= MAX_LENGTH) {
82 if (index != 0x20AC) {
83
84 continue;
85 }
86
87 break;
88 } else if (_stringChars[index] != null) {
89 break;
90 }
91 } while (++i < len);
92
93
94
95 if (i == len) {
96 return s;
97 }
98
99
100
101
102
103 StringBuilder sb = new StringBuilder(len + 40);
104 char[] chars = new char[len];
105
106
107 s.getChars(0, len, chars, 0);
108
109
110 sb.append(chars, 0, i);
111
112 int last = i;
113 char[] subst;
114
115 for (; i < len; i++) {
116 char c = chars[i];
117 int index = c;
118
119 if (index < MAX_LENGTH) {
120 subst = _stringChars[index];
121
122
123 if (subst != null) {
124 if (i > last) {
125 sb.append(chars, last, i - last);
126 }
127
128 sb.append(subst);
129 last = i + 1;
130 }
131 }
132
133
134 else if (index == 0x20AC) {
135 if (i > last) {
136 sb.append(chars, last, i - last);
137 }
138
139 sb.append("€");
140 last = i + 1;
141 }
142 }
143
144 if (i > last) {
145 sb.append(chars, last, i - last);
146 }
147
148 return sb.toString();
149 }
150
151 protected static void addMapping(int c, String txt, String[] strings) {
152 strings[c] = txt;
153 }
154
155 protected static void initMapping() {
156 String[] strings = new String[MAX_LENGTH];
157
158 addMapping(0x22, """, strings);
159 addMapping(0x26, "&", strings);
160 addMapping(0x3c, "<", strings);
161 addMapping(0x3e, ">", strings);
162
163 addMapping(0xa1, "¡", strings);
164 addMapping(0xa2, "¢", strings);
165 addMapping(0xa3, "£", strings);
166 addMapping(0xa9, "©", strings);
167 addMapping(0xae, "®", strings);
168 addMapping(0xbf, "¿", strings);
169
170 addMapping(0xc0, "À", strings);
171 addMapping(0xc1, "Á", strings);
172 addMapping(0xc2, "Â", strings);
173 addMapping(0xc3, "Ã", strings);
174 addMapping(0xc4, "Ä", strings);
175 addMapping(0xc5, "Å", strings);
176 addMapping(0xc6, "Æ", strings);
177 addMapping(0xc7, "Ç", strings);
178 addMapping(0xc8, "È", strings);
179 addMapping(0xc9, "É", strings);
180 addMapping(0xca, "Ê", strings);
181 addMapping(0xcb, "Ë", strings);
182 addMapping(0xcc, "Ì", strings);
183 addMapping(0xcd, "Í", strings);
184 addMapping(0xce, "Î", strings);
185 addMapping(0xcf, "Ï", strings);
186
187 addMapping(0xd0, "Ð", strings);
188 addMapping(0xd1, "Ñ", strings);
189 addMapping(0xd2, "Ò", strings);
190 addMapping(0xd3, "Ó", strings);
191 addMapping(0xd4, "Ô", strings);
192 addMapping(0xd5, "Õ", strings);
193 addMapping(0xd6, "Ö", strings);
194 addMapping(0xd7, "×", strings);
195 addMapping(0xd8, "Ø", strings);
196 addMapping(0xd9, "Ù", strings);
197 addMapping(0xda, "Ú", strings);
198 addMapping(0xdb, "Û", strings);
199 addMapping(0xdc, "Ü", strings);
200 addMapping(0xdd, "Ý", strings);
201 addMapping(0xde, "Þ", strings);
202 addMapping(0xdf, "ß", strings);
203
204 addMapping(0xe0, "à", strings);
205 addMapping(0xe1, "á", strings);
206 addMapping(0xe2, "â", strings);
207 addMapping(0xe3, "ã", strings);
208 addMapping(0xe4, "ä", strings);
209 addMapping(0xe5, "å", strings);
210 addMapping(0xe6, "æ", strings);
211 addMapping(0xe7, "ç", strings);
212 addMapping(0xe8, "è", strings);
213 addMapping(0xe9, "é", strings);
214 addMapping(0xea, "ê", strings);
215 addMapping(0xeb, "ë", strings);
216 addMapping(0xec, "ì", strings);
217 addMapping(0xed, "í", strings);
218 addMapping(0xee, "î", strings);
219 addMapping(0xef, "ï", strings);
220
221 addMapping(0xf0, "ð", strings);
222 addMapping(0xf1, "ñ", strings);
223 addMapping(0xf2, "ò", strings);
224 addMapping(0xf3, "ó", strings);
225 addMapping(0xf4, "ô", strings);
226 addMapping(0xf5, "õ", strings);
227 addMapping(0xf6, "ö", strings);
228 addMapping(0xf7, "÷", strings);
229 addMapping(0xf8, "ø", strings);
230 addMapping(0xf9, "ù", strings);
231 addMapping(0xfa, "ú", strings);
232 addMapping(0xfb, "û", strings);
233 addMapping(0xfc, "ü", strings);
234 addMapping(0xfd, "ý", strings);
235 addMapping(0xfe, "þ", strings);
236 addMapping(0xff, "ÿ", strings);
237
238 for (int i = 0; i < strings.length; i++) {
239 String str = strings[i];
240
241 if (str != null) {
242 _stringChars[i] = str.toCharArray();
243 }
244 }
245 }
246 }