|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
namespace voku\helper; |
|
4
|
|
|
|
|
5
|
|
|
/** |
|
6
|
|
|
* Anti XSS library |
|
7
|
|
|
* |
|
8
|
|
|
* ported from "CodeIgniter" |
|
9
|
|
|
* |
|
10
|
|
|
* @author EllisLab Dev Team |
|
11
|
|
|
* @author Lars Moelleken |
|
12
|
|
|
* @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/) |
|
13
|
|
|
* @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/) |
|
14
|
|
|
* @copyright Copyright (c) 2015 - 2017, Lars Moelleken (https://moelleken.org/) |
|
15
|
|
|
* |
|
16
|
|
|
* @license http://opensource.org/licenses/MIT MIT License |
|
17
|
|
|
*/ |
|
18
|
|
|
final class AntiXSS |
|
19
|
|
|
{ |
|
20
|
|
|
|
|
21
|
|
|
/** |
|
22
|
|
|
* @var array |
|
23
|
|
|
*/ |
|
24
|
|
|
private static $entitiesFallback = array( |
|
25
|
|
|
"\t" => '	', |
|
26
|
|
|
"\n" => '
', |
|
27
|
|
|
'!' => '!', |
|
28
|
|
|
'"' => '"', |
|
29
|
|
|
'#' => '#', |
|
30
|
|
|
'$' => '$', |
|
31
|
|
|
'%' => '%', |
|
32
|
|
|
'&' => '&', |
|
33
|
|
|
"'" => ''', |
|
34
|
|
|
'(' => '(', |
|
35
|
|
|
')' => ')', |
|
36
|
|
|
'*' => '*', |
|
37
|
|
|
'+' => '+', |
|
38
|
|
|
',' => ',', |
|
39
|
|
|
'.' => '.', |
|
40
|
|
|
'/' => '/', |
|
41
|
|
|
':' => ':', |
|
42
|
|
|
';' => ';', |
|
43
|
|
|
'<' => '<', |
|
44
|
|
|
'<⃒' => '<⃒', |
|
45
|
|
|
'=' => '=', |
|
46
|
|
|
'=⃥' => '=⃥', |
|
47
|
|
|
'>' => '>', |
|
48
|
|
|
'>⃒' => '&nvgt', |
|
49
|
|
|
'?' => '?', |
|
50
|
|
|
'@' => '@', |
|
51
|
|
|
'[' => '[', |
|
52
|
|
|
']' => ']', |
|
53
|
|
|
'^' => '^', |
|
54
|
|
|
'_' => '_', |
|
55
|
|
|
'`' => '`', |
|
56
|
|
|
'fj' => 'fj', |
|
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
|
|
|
'Ò' => 'Ò', |
|
111
|
|
|
'Ó' => 'Ó', |
|
112
|
|
|
'Ô' => 'Ô', |
|
113
|
|
|
'Õ' => 'Õ', |
|
114
|
|
|
'Ö' => 'Ö', |
|
115
|
|
|
'×' => '×', |
|
116
|
|
|
'Ø' => 'Ø', |
|
117
|
|
|
'Ù' => 'Ù', |
|
118
|
|
|
'Ú' => 'Ú', |
|
119
|
|
|
'Û' => 'Û', |
|
120
|
|
|
'Ü' => 'Ü', |
|
121
|
|
|
'Ý' => 'Ý', |
|
122
|
|
|
'Þ' => 'Þ', |
|
123
|
|
|
'ß' => 'ß', |
|
124
|
|
|
'à' => 'à', |
|
125
|
|
|
'á' => 'á', |
|
126
|
|
|
'â' => 'â', |
|
127
|
|
|
'ã' => 'ã', |
|
128
|
|
|
'ä' => 'ä', |
|
129
|
|
|
'å' => 'å', |
|
130
|
|
|
'æ' => 'æ', |
|
131
|
|
|
'ç' => 'ç', |
|
132
|
|
|
'è' => 'è', |
|
133
|
|
|
'é' => 'é', |
|
134
|
|
|
'ê' => 'ê', |
|
135
|
|
|
'ë' => 'ë', |
|
136
|
|
|
'ì' => 'ì', |
|
137
|
|
|
'í' => 'í', |
|
138
|
|
|
'î' => 'î', |
|
139
|
|
|
'ï' => 'ï', |
|
140
|
|
|
'ð' => 'ð', |
|
141
|
|
|
'ñ' => 'ñ', |
|
142
|
|
|
'ò' => 'ò', |
|
143
|
|
|
'ó' => 'ó', |
|
144
|
|
|
'ô' => 'ô', |
|
145
|
|
|
'õ' => 'õ', |
|
146
|
|
|
'ö' => 'ö', |
|
147
|
|
|
'÷' => '÷', |
|
148
|
|
|
'ø' => 'ø', |
|
149
|
|
|
'ù' => 'ù', |
|
150
|
|
|
'ú' => 'ú', |
|
151
|
|
|
'û' => 'û', |
|
152
|
|
|
'ü' => 'ü', |
|
153
|
|
|
'ý' => 'ý', |
|
154
|
|
|
'þ' => 'þ', |
|
155
|
|
|
'ÿ' => 'ÿ', |
|
156
|
|
|
'Ā' => 'Ā', |
|
157
|
|
|
'ā' => 'ā', |
|
158
|
|
|
'Ă' => 'Ă', |
|
159
|
|
|
'ă' => 'ă', |
|
160
|
|
|
'Ą' => 'Ą', |
|
161
|
|
|
'ą' => 'ą', |
|
162
|
|
|
'Ć' => 'Ć', |
|
163
|
|
|
'ć' => 'ć', |
|
164
|
|
|
'Ĉ' => 'Ĉ', |
|
165
|
|
|
'ĉ' => 'ĉ', |
|
166
|
|
|
'Ċ' => 'Ċ', |
|
167
|
|
|
'ċ' => 'ċ', |
|
168
|
|
|
'Č' => 'Č', |
|
169
|
|
|
'č' => 'č', |
|
170
|
|
|
'Ď' => 'Ď', |
|
171
|
|
|
'ď' => 'ď', |
|
172
|
|
|
'Đ' => 'Đ', |
|
173
|
|
|
'đ' => 'đ', |
|
174
|
|
|
'Ē' => 'Ē', |
|
175
|
|
|
'ē' => 'ē', |
|
176
|
|
|
'Ė' => 'Ė', |
|
177
|
|
|
'ė' => 'ė', |
|
178
|
|
|
'Ę' => 'Ę', |
|
179
|
|
|
'ę' => 'ę', |
|
180
|
|
|
'Ě' => 'Ě', |
|
181
|
|
|
'ě' => 'ě', |
|
182
|
|
|
'Ĝ' => 'Ĝ', |
|
183
|
|
|
'ĝ' => 'ĝ', |
|
184
|
|
|
'Ğ' => 'Ğ', |
|
185
|
|
|
'ğ' => 'ğ', |
|
186
|
|
|
'Ġ' => 'Ġ', |
|
187
|
|
|
'ġ' => 'ġ', |
|
188
|
|
|
'Ģ' => 'Ģ', |
|
189
|
|
|
'Ĥ' => 'Ĥ', |
|
190
|
|
|
'ĥ' => 'ĥ', |
|
191
|
|
|
'Ħ' => 'Ħ', |
|
192
|
|
|
'ħ' => 'ħ', |
|
193
|
|
|
'Ĩ' => 'Ĩ', |
|
194
|
|
|
'ĩ' => 'ĩ', |
|
195
|
|
|
'Ī' => 'Ī', |
|
196
|
|
|
'ī' => 'ī', |
|
197
|
|
|
'Į' => 'Į', |
|
198
|
|
|
'į' => 'į', |
|
199
|
|
|
'İ' => 'İ', |
|
200
|
|
|
'ı' => 'ı', |
|
201
|
|
|
'IJ' => 'IJ', |
|
202
|
|
|
'ij' => 'ij', |
|
203
|
|
|
'Ĵ' => 'Ĵ', |
|
204
|
|
|
'ĵ' => 'ĵ', |
|
205
|
|
|
'Ķ' => 'Ķ', |
|
206
|
|
|
'ķ' => 'ķ', |
|
207
|
|
|
'ĸ' => 'ĸ', |
|
208
|
|
|
'Ĺ' => 'Ĺ', |
|
209
|
|
|
'ĺ' => 'ĺ', |
|
210
|
|
|
'Ļ' => 'Ļ', |
|
211
|
|
|
'ļ' => 'ļ', |
|
212
|
|
|
'Ľ' => 'Ľ', |
|
213
|
|
|
'ľ' => 'ľ', |
|
214
|
|
|
'Ŀ' => 'Ŀ', |
|
215
|
|
|
'ŀ' => 'ŀ', |
|
216
|
|
|
'Ł' => 'Ł', |
|
217
|
|
|
'ł' => 'ł', |
|
218
|
|
|
'Ń' => 'Ń', |
|
219
|
|
|
'ń' => 'ń', |
|
220
|
|
|
'Ņ' => 'Ņ', |
|
221
|
|
|
'ņ' => 'ņ', |
|
222
|
|
|
'Ň' => 'Ň', |
|
223
|
|
|
'ň' => 'ň', |
|
224
|
|
|
'ʼn' => 'ʼn', |
|
225
|
|
|
'Ŋ' => 'Ŋ', |
|
226
|
|
|
'ŋ' => 'ŋ', |
|
227
|
|
|
'Ō' => 'Ō', |
|
228
|
|
|
'ō' => 'ō', |
|
229
|
|
|
'Ő' => 'Ő', |
|
230
|
|
|
'ő' => 'ő', |
|
231
|
|
|
'Œ' => 'Œ', |
|
232
|
|
|
'œ' => 'œ', |
|
233
|
|
|
'Ŕ' => 'Ŕ', |
|
234
|
|
|
'ŕ' => 'ŕ', |
|
235
|
|
|
'Ŗ' => 'Ŗ', |
|
236
|
|
|
'ŗ' => 'ŗ', |
|
237
|
|
|
'Ř' => 'Ř', |
|
238
|
|
|
'ř' => 'ř', |
|
239
|
|
|
'Ś' => 'Ś', |
|
240
|
|
|
'ś' => 'ś', |
|
241
|
|
|
'Ŝ' => 'Ŝ', |
|
242
|
|
|
'ŝ' => 'ŝ', |
|
243
|
|
|
'Ş' => 'Ş', |
|
244
|
|
|
'ş' => 'ş', |
|
245
|
|
|
'Š' => 'Š', |
|
246
|
|
|
'š' => 'š', |
|
247
|
|
|
'Ţ' => 'Ţ', |
|
248
|
|
|
'ţ' => 'ţ', |
|
249
|
|
|
'Ť' => 'Ť', |
|
250
|
|
|
'ť' => 'ť', |
|
251
|
|
|
'Ŧ' => 'Ŧ', |
|
252
|
|
|
'ŧ' => 'ŧ', |
|
253
|
|
|
'Ũ' => 'Ũ', |
|
254
|
|
|
'ũ' => 'ũ', |
|
255
|
|
|
'Ū' => 'Ū', |
|
256
|
|
|
'ū' => 'ū', |
|
257
|
|
|
'Ŭ' => 'Ŭ', |
|
258
|
|
|
'ŭ' => 'ŭ', |
|
259
|
|
|
'Ů' => 'Ů', |
|
260
|
|
|
'ů' => 'ů', |
|
261
|
|
|
'Ű' => 'Ű', |
|
262
|
|
|
'ű' => 'ű', |
|
263
|
|
|
'Ų' => 'Ų', |
|
264
|
|
|
'ų' => 'ų', |
|
265
|
|
|
'Ŵ' => 'Ŵ', |
|
266
|
|
|
'ŵ' => 'ŵ', |
|
267
|
|
|
'Ŷ' => 'Ŷ', |
|
268
|
|
|
'ŷ' => 'ŷ', |
|
269
|
|
|
'Ÿ' => 'Ÿ', |
|
270
|
|
|
'Ź' => 'Ź', |
|
271
|
|
|
'ź' => 'ź', |
|
272
|
|
|
'Ż' => 'Ż', |
|
273
|
|
|
'ż' => 'ż', |
|
274
|
|
|
'Ž' => 'Ž', |
|
275
|
|
|
'ž' => 'ž', |
|
276
|
|
|
'ƒ' => 'ƒ', |
|
277
|
|
|
'Ƶ' => 'Ƶ', |
|
278
|
|
|
'ǵ' => 'ǵ', |
|
279
|
|
|
'ȷ' => 'ȷ', |
|
280
|
|
|
'ˆ' => 'ˆ', |
|
281
|
|
|
'ˇ' => 'ˇ', |
|
282
|
|
|
'˘' => '˘', |
|
283
|
|
|
'˙' => '˙', |
|
284
|
|
|
'˚' => '˚', |
|
285
|
|
|
'˛' => '˛', |
|
286
|
|
|
'˜' => '˜', |
|
287
|
|
|
'˝' => '˝', |
|
288
|
|
|
'̑' => '̑', |
|
289
|
|
|
'Α' => 'Α', |
|
290
|
|
|
'Β' => 'Β', |
|
291
|
|
|
'Γ' => 'Γ', |
|
292
|
|
|
'Δ' => 'Δ', |
|
293
|
|
|
'Ε' => 'Ε', |
|
294
|
|
|
'Ζ' => 'Ζ', |
|
295
|
|
|
'Η' => 'Η', |
|
296
|
|
|
'Θ' => 'Θ', |
|
297
|
|
|
'Ι' => 'Ι', |
|
298
|
|
|
'Κ' => 'Κ', |
|
299
|
|
|
'Λ' => 'Λ', |
|
300
|
|
|
'Μ' => 'Μ', |
|
301
|
|
|
'Ν' => 'Ν', |
|
302
|
|
|
'Ξ' => 'Ξ', |
|
303
|
|
|
'Ο' => 'Ο', |
|
304
|
|
|
'Π' => 'Π', |
|
305
|
|
|
'Ρ' => 'Ρ', |
|
306
|
|
|
'Σ' => 'Σ', |
|
307
|
|
|
'Τ' => 'Τ', |
|
308
|
|
|
'Υ' => 'Υ', |
|
309
|
|
|
'Φ' => 'Φ', |
|
310
|
|
|
'Χ' => 'Χ', |
|
311
|
|
|
'Ψ' => 'Ψ', |
|
312
|
|
|
'Ω' => 'Ω', |
|
313
|
|
|
'α' => 'α', |
|
314
|
|
|
'β' => 'β', |
|
315
|
|
|
'γ' => 'γ', |
|
316
|
|
|
'δ' => 'δ', |
|
317
|
|
|
'ε' => 'ε', |
|
318
|
|
|
'ζ' => 'ζ', |
|
319
|
|
|
'η' => 'η', |
|
320
|
|
|
'θ' => 'θ', |
|
321
|
|
|
'ι' => 'ι', |
|
322
|
|
|
'κ' => 'κ', |
|
323
|
|
|
'λ' => 'λ', |
|
324
|
|
|
'μ' => 'μ', |
|
325
|
|
|
'ν' => 'ν', |
|
326
|
|
|
'ξ' => 'ξ', |
|
327
|
|
|
'ο' => 'ο', |
|
328
|
|
|
'π' => 'π', |
|
329
|
|
|
'ρ' => 'ρ', |
|
330
|
|
|
'ς' => 'ς', |
|
331
|
|
|
'σ' => 'σ', |
|
332
|
|
|
'τ' => 'τ', |
|
333
|
|
|
'υ' => 'υ', |
|
334
|
|
|
'φ' => 'φ', |
|
335
|
|
|
'χ' => 'χ', |
|
336
|
|
|
'ψ' => 'ψ', |
|
337
|
|
|
'ω' => 'ω', |
|
338
|
|
|
'ϑ' => 'ϑ', |
|
339
|
|
|
'ϒ' => 'ϒ', |
|
340
|
|
|
'ϕ' => 'ϕ', |
|
341
|
|
|
'ϖ' => 'ϖ', |
|
342
|
|
|
'Ϝ' => 'Ϝ', |
|
343
|
|
|
'ϝ' => 'ϝ', |
|
344
|
|
|
'ϰ' => 'ϰ', |
|
345
|
|
|
'ϱ' => 'ϱ', |
|
346
|
|
|
'ϵ' => 'ϵ', |
|
347
|
|
|
'϶' => '϶', |
|
348
|
|
|
'Ё' => 'Ё', |
|
349
|
|
|
'Ђ' => 'Ђ', |
|
350
|
|
|
'Ѓ' => 'Ѓ', |
|
351
|
|
|
'Є' => 'Є', |
|
352
|
|
|
'Ѕ' => 'Ѕ', |
|
353
|
|
|
'І' => 'І', |
|
354
|
|
|
'Ї' => 'Ї', |
|
355
|
|
|
'Ј' => 'Ј', |
|
356
|
|
|
'Љ' => 'Љ', |
|
357
|
|
|
'Њ' => 'Њ', |
|
358
|
|
|
'Ћ' => 'Ћ', |
|
359
|
|
|
'Ќ' => 'Ќ', |
|
360
|
|
|
'Ў' => 'Ў', |
|
361
|
|
|
'Џ' => 'Џ', |
|
362
|
|
|
'А' => 'А', |
|
363
|
|
|
'Б' => 'Б', |
|
364
|
|
|
'В' => 'В', |
|
365
|
|
|
'Г' => 'Г', |
|
366
|
|
|
'Д' => 'Д', |
|
367
|
|
|
'Е' => 'Е', |
|
368
|
|
|
'Ж' => 'Ж', |
|
369
|
|
|
'З' => 'З', |
|
370
|
|
|
'И' => 'И', |
|
371
|
|
|
'Й' => 'Й', |
|
372
|
|
|
'К' => 'К', |
|
373
|
|
|
'Л' => 'Л', |
|
374
|
|
|
'М' => 'М', |
|
375
|
|
|
'Н' => 'Н', |
|
376
|
|
|
'О' => 'О', |
|
377
|
|
|
'П' => 'П', |
|
378
|
|
|
'Р' => 'Р', |
|
379
|
|
|
'С' => 'С', |
|
380
|
|
|
'Т' => 'Т', |
|
381
|
|
|
'У' => 'У', |
|
382
|
|
|
'Ф' => 'Ф', |
|
383
|
|
|
'Х' => 'Х', |
|
384
|
|
|
'Ц' => 'Ц', |
|
385
|
|
|
'Ч' => 'Ч', |
|
386
|
|
|
'Ш' => 'Ш', |
|
387
|
|
|
'Щ' => 'Щ', |
|
388
|
|
|
'Ъ' => 'Ъ', |
|
389
|
|
|
'Ы' => 'Ы', |
|
390
|
|
|
'Ь' => 'Ь', |
|
391
|
|
|
'Э' => 'Э', |
|
392
|
|
|
'Ю' => 'Ю', |
|
393
|
|
|
'Я' => 'Я', |
|
394
|
|
|
'а' => 'а', |
|
395
|
|
|
'б' => 'б', |
|
396
|
|
|
'в' => 'в', |
|
397
|
|
|
'г' => 'г', |
|
398
|
|
|
'д' => 'д', |
|
399
|
|
|
'е' => 'е', |
|
400
|
|
|
'ж' => 'ж', |
|
401
|
|
|
'з' => 'з', |
|
402
|
|
|
'и' => 'и', |
|
403
|
|
|
'й' => 'й', |
|
404
|
|
|
'к' => 'к', |
|
405
|
|
|
'л' => 'л', |
|
406
|
|
|
'м' => 'м', |
|
407
|
|
|
'н' => 'н', |
|
408
|
|
|
'о' => 'о', |
|
409
|
|
|
'п' => 'п', |
|
410
|
|
|
'р' => 'р', |
|
411
|
|
|
'с' => 'с', |
|
412
|
|
|
'т' => 'т', |
|
413
|
|
|
'у' => 'у', |
|
414
|
|
|
'ф' => 'ф', |
|
415
|
|
|
'х' => 'х', |
|
416
|
|
|
'ц' => 'ц', |
|
417
|
|
|
'ч' => 'ч', |
|
418
|
|
|
'ш' => 'ш', |
|
419
|
|
|
'щ' => 'щ', |
|
420
|
|
|
'ъ' => 'ъ', |
|
421
|
|
|
'ы' => 'ы', |
|
422
|
|
|
'ь' => 'ь', |
|
423
|
|
|
'э' => 'э', |
|
424
|
|
|
'ю' => 'ю', |
|
425
|
|
|
'я' => 'я', |
|
426
|
|
|
'ё' => 'ё', |
|
427
|
|
|
'ђ' => 'ђ', |
|
428
|
|
|
'ѓ' => 'ѓ', |
|
429
|
|
|
'є' => 'є', |
|
430
|
|
|
'ѕ' => 'ѕ', |
|
431
|
|
|
'і' => 'і', |
|
432
|
|
|
'ї' => 'ї', |
|
433
|
|
|
'ј' => 'ј', |
|
434
|
|
|
'љ' => 'љ', |
|
435
|
|
|
'њ' => 'њ', |
|
436
|
|
|
'ћ' => 'ћ', |
|
437
|
|
|
'ќ' => 'ќ', |
|
438
|
|
|
'ў' => 'ў', |
|
439
|
|
|
'џ' => 'џ', |
|
440
|
|
|
' ' => ' ', |
|
441
|
|
|
' ' => ' ', |
|
442
|
|
|
' ' => ' ', |
|
443
|
|
|
' ' => ' ', |
|
444
|
|
|
' ' => ' ', |
|
445
|
|
|
' ' => ' ', |
|
446
|
|
|
' ' => ' ', |
|
447
|
|
|
' ' => ' ', |
|
448
|
|
|
'' => '​', |
|
449
|
|
|
'' => '‌', |
|
450
|
|
|
'' => '‍', |
|
451
|
|
|
'' => '‎', |
|
452
|
|
|
'' => '‏', |
|
453
|
|
|
'‐' => '‐', |
|
454
|
|
|
'–' => '–', |
|
455
|
|
|
'—' => '—', |
|
456
|
|
|
'―' => '―', |
|
457
|
|
|
'‖' => '‖', |
|
458
|
|
|
'‘' => '‘', |
|
459
|
|
|
'’' => '’', |
|
460
|
|
|
'‚' => '‚', |
|
461
|
|
|
'“' => '“', |
|
462
|
|
|
'”' => '”', |
|
463
|
|
|
'„' => '„', |
|
464
|
|
|
'†' => '†', |
|
465
|
|
|
'‡' => '‡', |
|
466
|
|
|
'•' => '•', |
|
467
|
|
|
'‥' => '‥', |
|
468
|
|
|
'…' => '…', |
|
469
|
|
|
'‰' => '‰', |
|
470
|
|
|
'‱' => '‱', |
|
471
|
|
|
'′' => '′', |
|
472
|
|
|
'″' => '″', |
|
473
|
|
|
'‴' => '‴', |
|
474
|
|
|
'‵' => '‵', |
|
475
|
|
|
'‹' => '‹', |
|
476
|
|
|
'›' => '›', |
|
477
|
|
|
'‾' => '‾', |
|
478
|
|
|
'⁁' => '⁁', |
|
479
|
|
|
'⁃' => '⁃', |
|
480
|
|
|
'⁄' => '⁄', |
|
481
|
|
|
'⁏' => '⁏', |
|
482
|
|
|
'⁗' => '⁗', |
|
483
|
|
|
' ' => ' ', |
|
484
|
|
|
' ' => '  ', |
|
485
|
|
|
'' => '⁠', |
|
486
|
|
|
'' => '⁡', |
|
487
|
|
|
'' => '⁢', |
|
488
|
|
|
'' => '⁣', |
|
489
|
|
|
'€' => '€', |
|
490
|
|
|
'⃛' => '⃛', |
|
491
|
|
|
'⃜' => '⃜', |
|
492
|
|
|
'ℂ' => 'ℂ', |
|
493
|
|
|
'℅' => '℅', |
|
494
|
|
|
'ℊ' => 'ℊ', |
|
495
|
|
|
'ℋ' => 'ℋ', |
|
496
|
|
|
'ℌ' => 'ℌ', |
|
497
|
|
|
'ℍ' => 'ℍ', |
|
498
|
|
|
'ℎ' => 'ℎ', |
|
499
|
|
|
'ℏ' => 'ℏ', |
|
500
|
|
|
'ℐ' => 'ℐ', |
|
501
|
|
|
'ℑ' => 'ℑ', |
|
502
|
|
|
'ℒ' => 'ℒ', |
|
503
|
|
|
'ℓ' => 'ℓ', |
|
504
|
|
|
'ℕ' => 'ℕ', |
|
505
|
|
|
'№' => '№', |
|
506
|
|
|
'℗' => '℗', |
|
507
|
|
|
'℘' => '℘', |
|
508
|
|
|
'ℙ' => 'ℙ', |
|
509
|
|
|
'ℚ' => 'ℚ', |
|
510
|
|
|
'ℛ' => 'ℛ', |
|
511
|
|
|
'ℜ' => 'ℜ', |
|
512
|
|
|
'ℝ' => 'ℝ', |
|
513
|
|
|
'℞' => '℞', |
|
514
|
|
|
'™' => '™', |
|
515
|
|
|
'ℤ' => 'ℤ', |
|
516
|
|
|
'℧' => '℧', |
|
517
|
|
|
'ℨ' => 'ℨ', |
|
518
|
|
|
'℩' => '℩', |
|
519
|
|
|
'ℬ' => 'ℬ', |
|
520
|
|
|
'ℭ' => 'ℭ', |
|
521
|
|
|
'ℯ' => 'ℯ', |
|
522
|
|
|
'ℰ' => 'ℰ', |
|
523
|
|
|
'ℱ' => 'ℱ', |
|
524
|
|
|
'ℳ' => 'ℳ', |
|
525
|
|
|
'ℴ' => 'ℴ', |
|
526
|
|
|
'ℵ' => 'ℵ', |
|
527
|
|
|
'ℶ' => 'ℶ', |
|
528
|
|
|
'ℷ' => 'ℷ', |
|
529
|
|
|
'ℸ' => 'ℸ', |
|
530
|
|
|
'ⅅ' => 'ⅅ', |
|
531
|
|
|
'ⅆ' => 'ⅆ', |
|
532
|
|
|
'ⅇ' => 'ⅇ', |
|
533
|
|
|
'ⅈ' => 'ⅈ', |
|
534
|
|
|
'⅓' => '⅓', |
|
535
|
|
|
'⅔' => '⅔', |
|
536
|
|
|
'⅕' => '⅕', |
|
537
|
|
|
'⅖' => '⅖', |
|
538
|
|
|
'⅗' => '⅗', |
|
539
|
|
|
'⅘' => '⅘', |
|
540
|
|
|
'⅙' => '⅙', |
|
541
|
|
|
'⅚' => '⅚', |
|
542
|
|
|
'⅛' => '⅛', |
|
543
|
|
|
'⅜' => '⅜', |
|
544
|
|
|
'⅝' => '⅝', |
|
545
|
|
|
'⅞' => '⅞', |
|
546
|
|
|
'←' => '←', |
|
547
|
|
|
'↑' => '↑', |
|
548
|
|
|
'→' => '→', |
|
549
|
|
|
'↓' => '↓', |
|
550
|
|
|
'↔' => '↔', |
|
551
|
|
|
'↕' => '↕', |
|
552
|
|
|
'↖' => '↖', |
|
553
|
|
|
'↗' => '↗', |
|
554
|
|
|
'↘' => '↘', |
|
555
|
|
|
'↙' => '↙', |
|
556
|
|
|
'↚' => '↚', |
|
557
|
|
|
'↛' => '↛', |
|
558
|
|
|
'↝' => '↝', |
|
559
|
|
|
'↝̸' => '↝̸', |
|
560
|
|
|
'↞' => '↞', |
|
561
|
|
|
'↟' => '↟', |
|
562
|
|
|
'↠' => '↠', |
|
563
|
|
|
'↡' => '↡', |
|
564
|
|
|
'↢' => '↢', |
|
565
|
|
|
'↣' => '↣', |
|
566
|
|
|
'↤' => '↤', |
|
567
|
|
|
'↥' => '↥', |
|
568
|
|
|
'↦' => '↦', |
|
569
|
|
|
'↧' => '↧', |
|
570
|
|
|
'↩' => '↩', |
|
571
|
|
|
'↪' => '↪', |
|
572
|
|
|
'↫' => '↫', |
|
573
|
|
|
'↬' => '↬', |
|
574
|
|
|
'↭' => '↭', |
|
575
|
|
|
'↮' => '↮', |
|
576
|
|
|
'↰' => '↰', |
|
577
|
|
|
'↱' => '↱', |
|
578
|
|
|
'↲' => '↲', |
|
579
|
|
|
'↳' => '↳', |
|
580
|
|
|
'↵' => '↵', |
|
581
|
|
|
'↶' => '↶', |
|
582
|
|
|
'↷' => '↷', |
|
583
|
|
|
'↺' => '↺', |
|
584
|
|
|
'↻' => '↻', |
|
585
|
|
|
'↼' => '↼', |
|
586
|
|
|
'↽' => '↽', |
|
587
|
|
|
'↾' => '↾', |
|
588
|
|
|
'↿' => '↿', |
|
589
|
|
|
'⇀' => '⇀', |
|
590
|
|
|
'⇁' => '⇁', |
|
591
|
|
|
'⇂' => '⇂', |
|
592
|
|
|
'⇃' => '⇃', |
|
593
|
|
|
'⇄' => '⇄', |
|
594
|
|
|
'⇅' => '⇅', |
|
595
|
|
|
'⇆' => '⇆', |
|
596
|
|
|
'⇇' => '⇇', |
|
597
|
|
|
'⇈' => '⇈', |
|
598
|
|
|
'⇉' => '⇉', |
|
599
|
|
|
'⇊' => '⇊', |
|
600
|
|
|
'⇋' => '⇋', |
|
601
|
|
|
'⇌' => '⇌', |
|
602
|
|
|
'⇍' => '⇍', |
|
603
|
|
|
'⇎' => '⇎', |
|
604
|
|
|
'⇏' => '⇏', |
|
605
|
|
|
'⇐' => '⇐', |
|
606
|
|
|
'⇑' => '⇑', |
|
607
|
|
|
'⇒' => '⇒', |
|
608
|
|
|
'⇓' => '⇓', |
|
609
|
|
|
'⇔' => '⇔', |
|
610
|
|
|
'⇕' => '⇕', |
|
611
|
|
|
'⇖' => '⇖', |
|
612
|
|
|
'⇗' => '⇗', |
|
613
|
|
|
'⇘' => '⇘', |
|
614
|
|
|
'⇙' => '⇙', |
|
615
|
|
|
'⇚' => '⇚', |
|
616
|
|
|
'⇛' => '⇛', |
|
617
|
|
|
'⇝' => '⇝', |
|
618
|
|
|
'⇤' => '⇤', |
|
619
|
|
|
'⇥' => '⇥', |
|
620
|
|
|
'⇵' => '⇵', |
|
621
|
|
|
'⇽' => '⇽', |
|
622
|
|
|
'⇾' => '⇾', |
|
623
|
|
|
'⇿' => '⇿', |
|
624
|
|
|
'∀' => '∀', |
|
625
|
|
|
'∁' => '∁', |
|
626
|
|
|
'∂' => '∂', |
|
627
|
|
|
'∂̸' => '∂̸', |
|
628
|
|
|
'∃' => '∃', |
|
629
|
|
|
'∄' => '∄', |
|
630
|
|
|
'∅' => '∅', |
|
631
|
|
|
'∇' => '∇', |
|
632
|
|
|
'∈' => '∈', |
|
633
|
|
|
'∉' => '∉', |
|
634
|
|
|
'∋' => '∋', |
|
635
|
|
|
'∌' => '∌', |
|
636
|
|
|
'∏' => '∏', |
|
637
|
|
|
'∐' => '∐', |
|
638
|
|
|
'∑' => '∑', |
|
639
|
|
|
'−' => '−', |
|
640
|
|
|
'∓' => '∓', |
|
641
|
|
|
'∔' => '∔', |
|
642
|
|
|
'∖' => '∖', |
|
643
|
|
|
'∗' => '∗', |
|
644
|
|
|
'∘' => '∘', |
|
645
|
|
|
'√' => '√', |
|
646
|
|
|
'∝' => '∝', |
|
647
|
|
|
'∞' => '∞', |
|
648
|
|
|
'∟' => '∟', |
|
649
|
|
|
'∠' => '∠', |
|
650
|
|
|
'∠⃒' => '∠⃒', |
|
651
|
|
|
'∡' => '∡', |
|
652
|
|
|
'∢' => '∢', |
|
653
|
|
|
'∣' => '∣', |
|
654
|
|
|
'∤' => '∤', |
|
655
|
|
|
'∥' => '∥', |
|
656
|
|
|
'∦' => '∦', |
|
657
|
|
|
'∧' => '∧', |
|
658
|
|
|
'∨' => '∨', |
|
659
|
|
|
'∩' => '∩', |
|
660
|
|
|
'∩︀' => '∩︀', |
|
661
|
|
|
'∪' => '∪', |
|
662
|
|
|
'∪︀' => '&cups', |
|
663
|
|
|
'∫' => '∫', |
|
664
|
|
|
'∬' => '∬', |
|
665
|
|
|
'∭' => '∭', |
|
666
|
|
|
'∮' => '∮', |
|
667
|
|
|
'∯' => '∯', |
|
668
|
|
|
'∰' => '∰', |
|
669
|
|
|
'∱' => '∱', |
|
670
|
|
|
'∲' => '∲', |
|
671
|
|
|
'∳' => '∳', |
|
672
|
|
|
'∴' => '∴', |
|
673
|
|
|
'∵' => '∵', |
|
674
|
|
|
'∶' => '∶', |
|
675
|
|
|
'∷' => '∷', |
|
676
|
|
|
'∸' => '∸', |
|
677
|
|
|
'∺' => '∺', |
|
678
|
|
|
'∻' => '∻', |
|
679
|
|
|
'∼' => '∼', |
|
680
|
|
|
'∼⃒' => '∼⃒', |
|
681
|
|
|
'∽' => '∽', |
|
682
|
|
|
'∽̱' => '∽̱', |
|
683
|
|
|
'∾' => '∾', |
|
684
|
|
|
'∾̳' => '∾̳', |
|
685
|
|
|
'∿' => '∿', |
|
686
|
|
|
'≀' => '≀', |
|
687
|
|
|
'≁' => '≁', |
|
688
|
|
|
'≂' => '≂', |
|
689
|
|
|
'≂̸' => '≂̸', |
|
690
|
|
|
'≃' => '≃', |
|
691
|
|
|
'≄' => '≄', |
|
692
|
|
|
'≅' => '≅', |
|
693
|
|
|
'≆' => '≆', |
|
694
|
|
|
'≇' => '≇', |
|
695
|
|
|
'≈' => '≈', |
|
696
|
|
|
'≉' => '≉', |
|
697
|
|
|
'≊' => '≊', |
|
698
|
|
|
'≋' => '≋', |
|
699
|
|
|
'≋̸' => '≋̸', |
|
700
|
|
|
'≌' => '≌', |
|
701
|
|
|
'≍' => '≍', |
|
702
|
|
|
'≍⃒' => '≍⃒', |
|
703
|
|
|
'≎' => '≎', |
|
704
|
|
|
'≎̸' => '≎̸', |
|
705
|
|
|
'≏' => '≏', |
|
706
|
|
|
'≏̸' => '≏̸', |
|
707
|
|
|
'≐' => '≐', |
|
708
|
|
|
'≐̸' => '≐̸', |
|
709
|
|
|
'≑' => '≑', |
|
710
|
|
|
'≒' => '≒', |
|
711
|
|
|
'≓' => '≓', |
|
712
|
|
|
'≔' => '≔', |
|
713
|
|
|
'≕' => '≕', |
|
714
|
|
|
'≖' => '≖', |
|
715
|
|
|
'≗' => '≗', |
|
716
|
|
|
'≙' => '≙', |
|
717
|
|
|
'≚' => '≚', |
|
718
|
|
|
'≜' => '≜', |
|
719
|
|
|
'≟' => '≟', |
|
720
|
|
|
'≠' => '≠', |
|
721
|
|
|
'≡' => '≡', |
|
722
|
|
|
'≡⃥' => '≡⃥', |
|
723
|
|
|
'≢' => '≢', |
|
724
|
|
|
'≤' => '≤', |
|
725
|
|
|
'≤⃒' => '≤⃒', |
|
726
|
|
|
'≥' => '≥', |
|
727
|
|
|
'≥⃒' => '≥⃒', |
|
728
|
|
|
'≦' => '≦', |
|
729
|
|
|
'≦̸' => '≦̸', |
|
730
|
|
|
'≧' => '≧', |
|
731
|
|
|
'≧̸' => '≧̸', |
|
732
|
|
|
'≨' => '≨', |
|
733
|
|
|
'≨︀' => '≨︀', |
|
734
|
|
|
'≩' => '≩', |
|
735
|
|
|
'≩︀' => '≩︀', |
|
736
|
|
|
'≪' => '≪', |
|
737
|
|
|
'≪̸' => '≪̸', |
|
738
|
|
|
'≪⃒' => '≪⃒', |
|
739
|
|
|
'≫' => '≫', |
|
740
|
|
|
'≫̸' => '≫̸', |
|
741
|
|
|
'≫⃒' => '≫⃒', |
|
742
|
|
|
'≬' => '≬', |
|
743
|
|
|
'≭' => '≭', |
|
744
|
|
|
'≮' => '≮', |
|
745
|
|
|
'≯' => '≯', |
|
746
|
|
|
'≰' => '≰', |
|
747
|
|
|
'≱' => '≱', |
|
748
|
|
|
'≲' => '≲', |
|
749
|
|
|
'≳' => '≳', |
|
750
|
|
|
'≴' => '≴', |
|
751
|
|
|
'≵' => '≵', |
|
752
|
|
|
'≶' => '≶', |
|
753
|
|
|
'≷' => '≷', |
|
754
|
|
|
'≸' => '≸', |
|
755
|
|
|
'≹' => '≹', |
|
756
|
|
|
'≺' => '≺', |
|
757
|
|
|
'≻' => '≻', |
|
758
|
|
|
'≼' => '≼', |
|
759
|
|
|
'≽' => '≽', |
|
760
|
|
|
'≾' => '≾', |
|
761
|
|
|
'≿' => '≿', |
|
762
|
|
|
'≿̸' => '≿̸', |
|
763
|
|
|
'⊀' => '⊀', |
|
764
|
|
|
'⊁' => '⊁', |
|
765
|
|
|
'⊂' => '⊂', |
|
766
|
|
|
'⊂⃒' => '⊂⃒', |
|
767
|
|
|
'⊃' => '⊃', |
|
768
|
|
|
'⊃⃒' => '⊃⃒', |
|
769
|
|
|
'⊄' => '⊄', |
|
770
|
|
|
'⊅' => '⊅', |
|
771
|
|
|
'⊆' => '⊆', |
|
772
|
|
|
'⊇' => '⊇', |
|
773
|
|
|
'⊈' => '⊈', |
|
774
|
|
|
'⊉' => '⊉', |
|
775
|
|
|
'⊊' => '⊊', |
|
776
|
|
|
'⊊︀' => '⊊︀', |
|
777
|
|
|
'⊋' => '⊋', |
|
778
|
|
|
'⊋︀' => '⊋︀', |
|
779
|
|
|
'⊍' => '⊍', |
|
780
|
|
|
'⊎' => '⊎', |
|
781
|
|
|
'⊏' => '⊏', |
|
782
|
|
|
'⊏̸' => '⊏̸', |
|
783
|
|
|
'⊐' => '⊐', |
|
784
|
|
|
'⊐̸' => '⊐̸', |
|
785
|
|
|
'⊑' => '⊑', |
|
786
|
|
|
'⊒' => '⊒', |
|
787
|
|
|
'⊓' => '⊓', |
|
788
|
|
|
'⊓︀' => '⊓︀', |
|
789
|
|
|
'⊔' => '⊔', |
|
790
|
|
|
'⊔︀' => '⊔︀', |
|
791
|
|
|
'⊕' => '⊕', |
|
792
|
|
|
'⊖' => '⊖', |
|
793
|
|
|
'⊗' => '⊗', |
|
794
|
|
|
'⊘' => '⊘', |
|
795
|
|
|
'⊙' => '⊙', |
|
796
|
|
|
'⊚' => '⊚', |
|
797
|
|
|
'⊛' => '⊛', |
|
798
|
|
|
'⊝' => '⊝', |
|
799
|
|
|
'⊞' => '⊞', |
|
800
|
|
|
'⊟' => '⊟', |
|
801
|
|
|
'⊠' => '⊠', |
|
802
|
|
|
'⊡' => '⊡', |
|
803
|
|
|
'⊢' => '⊢', |
|
804
|
|
|
'⊣' => '⊣', |
|
805
|
|
|
'⊤' => '⊤', |
|
806
|
|
|
'⊥' => '⊥', |
|
807
|
|
|
'⊧' => '⊧', |
|
808
|
|
|
'⊨' => '⊨', |
|
809
|
|
|
'⊩' => '⊩', |
|
810
|
|
|
'⊪' => '⊪', |
|
811
|
|
|
'⊫' => '⊫', |
|
812
|
|
|
'⊬' => '⊬', |
|
813
|
|
|
'⊭' => '⊭', |
|
814
|
|
|
'⊮' => '⊮', |
|
815
|
|
|
'⊯' => '⊯', |
|
816
|
|
|
'⊰' => '⊰', |
|
817
|
|
|
'⊲' => '⊲', |
|
818
|
|
|
'⊳' => '⊳', |
|
819
|
|
|
'⊴' => '⊴', |
|
820
|
|
|
'⊴⃒' => '⊴⃒', |
|
821
|
|
|
'⊵' => '⊵', |
|
822
|
|
|
'⊵⃒' => '⊵⃒', |
|
823
|
|
|
'⊶' => '⊶', |
|
824
|
|
|
'⊷' => '⊷', |
|
825
|
|
|
'⊸' => '⊸', |
|
826
|
|
|
'⊹' => '⊹', |
|
827
|
|
|
'⊺' => '⊺', |
|
828
|
|
|
'⊻' => '⊻', |
|
829
|
|
|
'⊽' => '⊽', |
|
830
|
|
|
'⊾' => '⊾', |
|
831
|
|
|
'⊿' => '⊿', |
|
832
|
|
|
'⋀' => '⋀', |
|
833
|
|
|
'⋁' => '⋁', |
|
834
|
|
|
'⋂' => '⋂', |
|
835
|
|
|
'⋃' => '⋃', |
|
836
|
|
|
'⋄' => '⋄', |
|
837
|
|
|
'⋅' => '⋅', |
|
838
|
|
|
'⋆' => '⋆', |
|
839
|
|
|
'⋇' => '⋇', |
|
840
|
|
|
'⋈' => '⋈', |
|
841
|
|
|
'⋉' => '⋉', |
|
842
|
|
|
'⋊' => '⋊', |
|
843
|
|
|
'⋋' => '⋋', |
|
844
|
|
|
'⋌' => '⋌', |
|
845
|
|
|
'⋍' => '⋍', |
|
846
|
|
|
'⋎' => '⋎', |
|
847
|
|
|
'⋏' => '⋏', |
|
848
|
|
|
'⋐' => '⋐', |
|
849
|
|
|
'⋑' => '⋑', |
|
850
|
|
|
'⋒' => '⋒', |
|
851
|
|
|
'⋓' => '⋓', |
|
852
|
|
|
'⋔' => '⋔', |
|
853
|
|
|
'⋕' => '⋕', |
|
854
|
|
|
'⋖' => '⋖', |
|
855
|
|
|
'⋗' => '⋗', |
|
856
|
|
|
'⋘' => '⋘', |
|
857
|
|
|
'⋘̸' => '⋘̸', |
|
858
|
|
|
'⋙' => '⋙', |
|
859
|
|
|
'⋙̸' => '⋙̸', |
|
860
|
|
|
'⋚' => '⋚', |
|
861
|
|
|
'⋚︀' => '⋚︀', |
|
862
|
|
|
'⋛' => '⋛', |
|
863
|
|
|
'⋛︀' => '⋛︀', |
|
864
|
|
|
'⋞' => '⋞', |
|
865
|
|
|
'⋟' => '⋟', |
|
866
|
|
|
'⋠' => '⋠', |
|
867
|
|
|
'⋡' => '⋡', |
|
868
|
|
|
'⋢' => '⋢', |
|
869
|
|
|
'⋣' => '⋣', |
|
870
|
|
|
'⋦' => '⋦', |
|
871
|
|
|
'⋧' => '⋧', |
|
872
|
|
|
'⋨' => '⋨', |
|
873
|
|
|
'⋩' => '⋩', |
|
874
|
|
|
'⋪' => '⋪', |
|
875
|
|
|
'⋫' => '⋫', |
|
876
|
|
|
'⋬' => '⋬', |
|
877
|
|
|
'⋭' => '⋭', |
|
878
|
|
|
'⋮' => '⋮', |
|
879
|
|
|
'⋯' => '⋯', |
|
880
|
|
|
'⋰' => '⋰', |
|
881
|
|
|
'⋱' => '⋱', |
|
882
|
|
|
'⋲' => '⋲', |
|
883
|
|
|
'⋳' => '⋳', |
|
884
|
|
|
'⋴' => '⋴', |
|
885
|
|
|
'⋵' => '⋵', |
|
886
|
|
|
'⋵̸' => '⋵̸', |
|
887
|
|
|
'⋶' => '⋶', |
|
888
|
|
|
'⋷' => '⋷', |
|
889
|
|
|
'⋹' => '⋹', |
|
890
|
|
|
'⋹̸' => '⋹̸', |
|
891
|
|
|
'⋺' => '⋺', |
|
892
|
|
|
'⋻' => '⋻', |
|
893
|
|
|
'⋼' => '⋼', |
|
894
|
|
|
'⋽' => '⋽', |
|
895
|
|
|
'⋾' => '⋾', |
|
896
|
|
|
'⌅' => '⌅', |
|
897
|
|
|
'⌆' => '⌆', |
|
898
|
|
|
'⌈' => '⌈', |
|
899
|
|
|
'⌉' => '⌉', |
|
900
|
|
|
'⌊' => '⌊', |
|
901
|
|
|
'⌋' => '⌋', |
|
902
|
|
|
'⌌' => '⌌', |
|
903
|
|
|
'⌍' => '⌍', |
|
904
|
|
|
'⌎' => '⌎', |
|
905
|
|
|
'⌏' => '⌏', |
|
906
|
|
|
'⌐' => '⌐', |
|
907
|
|
|
'⌒' => '⌒', |
|
908
|
|
|
'⌓' => '⌓', |
|
909
|
|
|
'⌕' => '⌕', |
|
910
|
|
|
'⌖' => '⌖', |
|
911
|
|
|
'⌜' => '⌜', |
|
912
|
|
|
'⌝' => '⌝', |
|
913
|
|
|
'⌞' => '⌞', |
|
914
|
|
|
'⌟' => '⌟', |
|
915
|
|
|
'⌢' => '⌢', |
|
916
|
|
|
'⌣' => '⌣', |
|
917
|
|
|
'⌭' => '⌭', |
|
918
|
|
|
'⌮' => '⌮', |
|
919
|
|
|
'⌶' => '⌶', |
|
920
|
|
|
'⌽' => '⌽', |
|
921
|
|
|
'⌿' => '⌿', |
|
922
|
|
|
'⍼' => '⍼', |
|
923
|
|
|
'⎰' => '⎰', |
|
924
|
|
|
'⎱' => '⎱', |
|
925
|
|
|
'⎴' => '⎴', |
|
926
|
|
|
'⎵' => '⎵', |
|
927
|
|
|
'⎶' => '⎶', |
|
928
|
|
|
'⏜' => '⏜', |
|
929
|
|
|
'⏝' => '⏝', |
|
930
|
|
|
'⏞' => '⏞', |
|
931
|
|
|
'⏟' => '⏟', |
|
932
|
|
|
'⏢' => '⏢', |
|
933
|
|
|
'⏧' => '⏧', |
|
934
|
|
|
'␣' => '␣', |
|
935
|
|
|
'Ⓢ' => 'Ⓢ', |
|
936
|
|
|
'─' => '─', |
|
937
|
|
|
'│' => '│', |
|
938
|
|
|
'┌' => '┌', |
|
939
|
|
|
'┐' => '┐', |
|
940
|
|
|
'└' => '└', |
|
941
|
|
|
'┘' => '┘', |
|
942
|
|
|
'├' => '├', |
|
943
|
|
|
'┤' => '┤', |
|
944
|
|
|
'┬' => '┬', |
|
945
|
|
|
'┴' => '┴', |
|
946
|
|
|
'┼' => '┼', |
|
947
|
|
|
'═' => '═', |
|
948
|
|
|
'║' => '║', |
|
949
|
|
|
'╒' => '╒', |
|
950
|
|
|
'╓' => '╓', |
|
951
|
|
|
'╔' => '╔', |
|
952
|
|
|
'╕' => '╕', |
|
953
|
|
|
'╖' => '╖', |
|
954
|
|
|
'╗' => '╗', |
|
955
|
|
|
'╘' => '╘', |
|
956
|
|
|
'╙' => '╙', |
|
957
|
|
|
'╚' => '╚', |
|
958
|
|
|
'╛' => '╛', |
|
959
|
|
|
'╜' => '╜', |
|
960
|
|
|
'╝' => '╝', |
|
961
|
|
|
'╞' => '╞', |
|
962
|
|
|
'╟' => '╟', |
|
963
|
|
|
'╠' => '╠', |
|
964
|
|
|
'╡' => '╡', |
|
965
|
|
|
'╢' => '╢', |
|
966
|
|
|
'╣' => '╣', |
|
967
|
|
|
'╤' => '╤', |
|
968
|
|
|
'╥' => '╥', |
|
969
|
|
|
'╦' => '╦', |
|
970
|
|
|
'╧' => '╧', |
|
971
|
|
|
'╨' => '╨', |
|
972
|
|
|
'╩' => '╩', |
|
973
|
|
|
'╪' => '╪', |
|
974
|
|
|
'╫' => '╫', |
|
975
|
|
|
'╬' => '╬', |
|
976
|
|
|
'▀' => '▀', |
|
977
|
|
|
'▄' => '▄', |
|
978
|
|
|
'█' => '█', |
|
979
|
|
|
'░' => '░', |
|
980
|
|
|
'▒' => '▒', |
|
981
|
|
|
'▓' => '▓', |
|
982
|
|
|
'□' => '□', |
|
983
|
|
|
'▪' => '▪', |
|
984
|
|
|
'▫' => '▫', |
|
985
|
|
|
'▭' => '▭', |
|
986
|
|
|
'▮' => '▮', |
|
987
|
|
|
'▱' => '▱', |
|
988
|
|
|
'△' => '△', |
|
989
|
|
|
'▴' => '▴', |
|
990
|
|
|
'▵' => '▵', |
|
991
|
|
|
'▸' => '▸', |
|
992
|
|
|
'▹' => '▹', |
|
993
|
|
|
'▽' => '▽', |
|
994
|
|
|
'▾' => '▾', |
|
995
|
|
|
'▿' => '▿', |
|
996
|
|
|
'◂' => '◂', |
|
997
|
|
|
'◃' => '◃', |
|
998
|
|
|
'◊' => '◊', |
|
999
|
|
|
'○' => '○', |
|
1000
|
|
|
'◬' => '◬', |
|
1001
|
|
|
'◯' => '◯', |
|
1002
|
|
|
'◸' => '◸', |
|
1003
|
|
|
'◹' => '◹', |
|
1004
|
|
|
'◺' => '◺', |
|
1005
|
|
|
'◻' => '◻', |
|
1006
|
|
|
'◼' => '◼', |
|
1007
|
|
|
'★' => '★', |
|
1008
|
|
|
'☆' => '☆', |
|
1009
|
|
|
'☎' => '☎', |
|
1010
|
|
|
'♀' => '♀', |
|
1011
|
|
|
'♂' => '♂', |
|
1012
|
|
|
'♠' => '♠', |
|
1013
|
|
|
'♣' => '♣', |
|
1014
|
|
|
'♥' => '♥', |
|
1015
|
|
|
'♦' => '♦', |
|
1016
|
|
|
'♪' => '♪', |
|
1017
|
|
|
'♭' => '♭', |
|
1018
|
|
|
'♮' => '♮', |
|
1019
|
|
|
'♯' => '♯', |
|
1020
|
|
|
'✓' => '✓', |
|
1021
|
|
|
'✗' => '✗', |
|
1022
|
|
|
'✠' => '✠', |
|
1023
|
|
|
'✶' => '✶', |
|
1024
|
|
|
'❘' => '❘', |
|
1025
|
|
|
'❲' => '❲', |
|
1026
|
|
|
'❳' => '❳', |
|
1027
|
|
|
'⟈' => '⟈', |
|
1028
|
|
|
'⟉' => '⟉', |
|
1029
|
|
|
'⟦' => '⟦', |
|
1030
|
|
|
'⟧' => '⟧', |
|
1031
|
|
|
'⟨' => '⟨', |
|
1032
|
|
|
'⟩' => '⟩', |
|
1033
|
|
|
'⟪' => '⟪', |
|
1034
|
|
|
'⟫' => '⟫', |
|
1035
|
|
|
'⟬' => '⟬', |
|
1036
|
|
|
'⟭' => '⟭', |
|
1037
|
|
|
'⟵' => '⟵', |
|
1038
|
|
|
'⟶' => '⟶', |
|
1039
|
|
|
'⟷' => '⟷', |
|
1040
|
|
|
'⟸' => '⟸', |
|
1041
|
|
|
'⟹' => '⟹', |
|
1042
|
|
|
'⟺' => '⟺', |
|
1043
|
|
|
'⟼' => '⟼', |
|
1044
|
|
|
'⟿' => '⟿', |
|
1045
|
|
|
'⤂' => '⤂', |
|
1046
|
|
|
'⤃' => '⤃', |
|
1047
|
|
|
'⤄' => '⤄', |
|
1048
|
|
|
'⤅' => '⤅', |
|
1049
|
|
|
'⤌' => '⤌', |
|
1050
|
|
|
'⤍' => '⤍', |
|
1051
|
|
|
'⤎' => '⤎', |
|
1052
|
|
|
'⤏' => '⤏', |
|
1053
|
|
|
'⤐' => '⤐', |
|
1054
|
|
|
'⤑' => '⤑', |
|
1055
|
|
|
'⤒' => '⤒', |
|
1056
|
|
|
'⤓' => '⤓', |
|
1057
|
|
|
'⤖' => '⤖', |
|
1058
|
|
|
'⤙' => '⤙', |
|
1059
|
|
|
'⤚' => '⤚', |
|
1060
|
|
|
'⤛' => '⤛', |
|
1061
|
|
|
'⤜' => '⤜', |
|
1062
|
|
|
'⤝' => '⤝', |
|
1063
|
|
|
'⤞' => '⤞', |
|
1064
|
|
|
'⤟' => '⤟', |
|
1065
|
|
|
'⤠' => '⤠', |
|
1066
|
|
|
'⤣' => '⤣', |
|
1067
|
|
|
'⤤' => '⤤', |
|
1068
|
|
|
'⤥' => '⤥', |
|
1069
|
|
|
'⤦' => '⤦', |
|
1070
|
|
|
'⤧' => '⤧', |
|
1071
|
|
|
'⤨' => '⤨', |
|
1072
|
|
|
'⤩' => '⤩', |
|
1073
|
|
|
'⤪' => '⤪', |
|
1074
|
|
|
'⤳' => '⤳', |
|
1075
|
|
|
'⤳̸' => '⤳̸', |
|
1076
|
|
|
'⤵' => '⤵', |
|
1077
|
|
|
'⤶' => '⤶', |
|
1078
|
|
|
'⤷' => '⤷', |
|
1079
|
|
|
'⤸' => '⤸', |
|
1080
|
|
|
'⤹' => '⤹', |
|
1081
|
|
|
'⤼' => '⤼', |
|
1082
|
|
|
'⤽' => '⤽', |
|
1083
|
|
|
'⥅' => '⥅', |
|
1084
|
|
|
'⥈' => '⥈', |
|
1085
|
|
|
'⥉' => '⥉', |
|
1086
|
|
|
'⥊' => '⥊', |
|
1087
|
|
|
'⥋' => '⥋', |
|
1088
|
|
|
'⥎' => '⥎', |
|
1089
|
|
|
'⥏' => '⥏', |
|
1090
|
|
|
'⥐' => '⥐', |
|
1091
|
|
|
'⥑' => '⥑', |
|
1092
|
|
|
'⥒' => '⥒', |
|
1093
|
|
|
'⥓' => '⥓', |
|
1094
|
|
|
'⥔' => '⥔', |
|
1095
|
|
|
'⥕' => '⥕', |
|
1096
|
|
|
'⥖' => '⥖', |
|
1097
|
|
|
'⥗' => '⥗', |
|
1098
|
|
|
'⥘' => '⥘', |
|
1099
|
|
|
'⥙' => '⥙', |
|
1100
|
|
|
'⥚' => '⥚', |
|
1101
|
|
|
'⥛' => '⥛', |
|
1102
|
|
|
'⥜' => '⥜', |
|
1103
|
|
|
'⥝' => '⥝', |
|
1104
|
|
|
'⥞' => '⥞', |
|
1105
|
|
|
'⥟' => '⥟', |
|
1106
|
|
|
'⥠' => '⥠', |
|
1107
|
|
|
'⥡' => '⥡', |
|
1108
|
|
|
'⥢' => '⥢', |
|
1109
|
|
|
'⥣' => '⥣', |
|
1110
|
|
|
'⥤' => '⥤', |
|
1111
|
|
|
'⥥' => '⥥', |
|
1112
|
|
|
'⥦' => '⥦', |
|
1113
|
|
|
'⥧' => '⥧', |
|
1114
|
|
|
'⥨' => '⥨', |
|
1115
|
|
|
'⥩' => '⥩', |
|
1116
|
|
|
'⥪' => '⥪', |
|
1117
|
|
|
'⥫' => '⥫', |
|
1118
|
|
|
'⥬' => '⥬', |
|
1119
|
|
|
'⥭' => '⥭', |
|
1120
|
|
|
'⥮' => '⥮', |
|
1121
|
|
|
'⥯' => '⥯', |
|
1122
|
|
|
'⥰' => '⥰', |
|
1123
|
|
|
'⥱' => '⥱', |
|
1124
|
|
|
'⥲' => '⥲', |
|
1125
|
|
|
'⥳' => '⥳', |
|
1126
|
|
|
'⥴' => '⥴', |
|
1127
|
|
|
'⥵' => '⥵', |
|
1128
|
|
|
'⥶' => '⥶', |
|
1129
|
|
|
'⥸' => '⥸', |
|
1130
|
|
|
'⥹' => '⥹', |
|
1131
|
|
|
'⥻' => '⥻', |
|
1132
|
|
|
'⥼' => '⥼', |
|
1133
|
|
|
'⥽' => '⥽', |
|
1134
|
|
|
'⥾' => '⥾', |
|
1135
|
|
|
'⥿' => '⥿', |
|
1136
|
|
|
'⦅' => '⦅', |
|
1137
|
|
|
'⦆' => '⦆', |
|
1138
|
|
|
'⦋' => '⦋', |
|
1139
|
|
|
'⦌' => '⦌', |
|
1140
|
|
|
'⦍' => '⦍', |
|
1141
|
|
|
'⦎' => '⦎', |
|
1142
|
|
|
'⦏' => '⦏', |
|
1143
|
|
|
'⦐' => '⦐', |
|
1144
|
|
|
'⦑' => '⦑', |
|
1145
|
|
|
'⦒' => '⦒', |
|
1146
|
|
|
'⦓' => '⦓', |
|
1147
|
|
|
'⦔' => '⦔', |
|
1148
|
|
|
'⦕' => '⦕', |
|
1149
|
|
|
'⦖' => '⦖', |
|
1150
|
|
|
'⦚' => '⦚', |
|
1151
|
|
|
'⦜' => '⦜', |
|
1152
|
|
|
'⦝' => '⦝', |
|
1153
|
|
|
'⦤' => '⦤', |
|
1154
|
|
|
'⦥' => '⦥', |
|
1155
|
|
|
'⦦' => '⦦', |
|
1156
|
|
|
'⦧' => '⦧', |
|
1157
|
|
|
'⦨' => '⦨', |
|
1158
|
|
|
'⦩' => '⦩', |
|
1159
|
|
|
'⦪' => '⦪', |
|
1160
|
|
|
'⦫' => '⦫', |
|
1161
|
|
|
'⦬' => '⦬', |
|
1162
|
|
|
'⦭' => '⦭', |
|
1163
|
|
|
'⦮' => '⦮', |
|
1164
|
|
|
'⦯' => '⦯', |
|
1165
|
|
|
'⦰' => '⦰', |
|
1166
|
|
|
'⦱' => '⦱', |
|
1167
|
|
|
'⦲' => '⦲', |
|
1168
|
|
|
'⦳' => '⦳', |
|
1169
|
|
|
'⦴' => '⦴', |
|
1170
|
|
|
'⦵' => '⦵', |
|
1171
|
|
|
'⦶' => '⦶', |
|
1172
|
|
|
'⦷' => '⦷', |
|
1173
|
|
|
'⦹' => '⦹', |
|
1174
|
|
|
'⦻' => '⦻', |
|
1175
|
|
|
'⦼' => '⦼', |
|
1176
|
|
|
'⦾' => '⦾', |
|
1177
|
|
|
'⦿' => '⦿', |
|
1178
|
|
|
'⧀' => '⧀', |
|
1179
|
|
|
'⧁' => '⧁', |
|
1180
|
|
|
'⧂' => '⧂', |
|
1181
|
|
|
'⧃' => '⧃', |
|
1182
|
|
|
'⧄' => '⧄', |
|
1183
|
|
|
'⧅' => '⧅', |
|
1184
|
|
|
'⧉' => '⧉', |
|
1185
|
|
|
'⧍' => '⧍', |
|
1186
|
|
|
'⧎' => '⧎', |
|
1187
|
|
|
'⧏' => '⧏', |
|
1188
|
|
|
'⧏̸' => '⧏̸', |
|
1189
|
|
|
'⧐' => '⧐', |
|
1190
|
|
|
'⧐̸' => '⧐̸', |
|
1191
|
|
|
'⧜' => '⧜', |
|
1192
|
|
|
'⧝' => '⧝', |
|
1193
|
|
|
'⧞' => '⧞', |
|
1194
|
|
|
'⧣' => '⧣', |
|
1195
|
|
|
'⧤' => '⧤', |
|
1196
|
|
|
'⧥' => '⧥', |
|
1197
|
|
|
'⧫' => '⧫', |
|
1198
|
|
|
'⧴' => '⧴', |
|
1199
|
|
|
'⧶' => '⧶', |
|
1200
|
|
|
'⨀' => '⨀', |
|
1201
|
|
|
'⨁' => '⨁', |
|
1202
|
|
|
'⨂' => '⨂', |
|
1203
|
|
|
'⨄' => '⨄', |
|
1204
|
|
|
'⨆' => '⨆', |
|
1205
|
|
|
'⨌' => '⨌', |
|
1206
|
|
|
'⨍' => '⨍', |
|
1207
|
|
|
'⨐' => '⨐', |
|
1208
|
|
|
'⨑' => '⨑', |
|
1209
|
|
|
'⨒' => '⨒', |
|
1210
|
|
|
'⨓' => '⨓', |
|
1211
|
|
|
'⨔' => '⨔', |
|
1212
|
|
|
'⨕' => '⨕', |
|
1213
|
|
|
'⨖' => '⨖', |
|
1214
|
|
|
'⨗' => '⨗', |
|
1215
|
|
|
'⨢' => '⨢', |
|
1216
|
|
|
'⨣' => '⨣', |
|
1217
|
|
|
'⨤' => '⨤', |
|
1218
|
|
|
'⨥' => '⨥', |
|
1219
|
|
|
'⨦' => '⨦', |
|
1220
|
|
|
'⨧' => '⨧', |
|
1221
|
|
|
'⨩' => '⨩', |
|
1222
|
|
|
'⨪' => '⨪', |
|
1223
|
|
|
'⨭' => '⨭', |
|
1224
|
|
|
'⨮' => '⨮', |
|
1225
|
|
|
'⨯' => '⨯', |
|
1226
|
|
|
'⨰' => '⨰', |
|
1227
|
|
|
'⨱' => '⨱', |
|
1228
|
|
|
'⨳' => '⨳', |
|
1229
|
|
|
'⨴' => '⨴', |
|
1230
|
|
|
'⨵' => '⨵', |
|
1231
|
|
|
'⨶' => '⨶', |
|
1232
|
|
|
'⨷' => '⨷', |
|
1233
|
|
|
'⨸' => '⨸', |
|
1234
|
|
|
'⨹' => '⨹', |
|
1235
|
|
|
'⨺' => '⨺', |
|
1236
|
|
|
'⨻' => '⨻', |
|
1237
|
|
|
'⨼' => '⨼', |
|
1238
|
|
|
'⨿' => '⨿', |
|
1239
|
|
|
'⩀' => '⩀', |
|
1240
|
|
|
'⩂' => '⩂', |
|
1241
|
|
|
'⩃' => '⩃', |
|
1242
|
|
|
'⩄' => '⩄', |
|
1243
|
|
|
'⩅' => '⩅', |
|
1244
|
|
|
'⩆' => '⩆', |
|
1245
|
|
|
'⩇' => '⩇', |
|
1246
|
|
|
'⩈' => '⩈', |
|
1247
|
|
|
'⩉' => '⩉', |
|
1248
|
|
|
'⩊' => '⩊', |
|
1249
|
|
|
'⩋' => '⩋', |
|
1250
|
|
|
'⩌' => '⩌', |
|
1251
|
|
|
'⩍' => '⩍', |
|
1252
|
|
|
'⩐' => '⩐', |
|
1253
|
|
|
'⩓' => '⩓', |
|
1254
|
|
|
'⩔' => '⩔', |
|
1255
|
|
|
'⩕' => '⩕', |
|
1256
|
|
|
'⩖' => '⩖', |
|
1257
|
|
|
'⩗' => '⩗', |
|
1258
|
|
|
'⩘' => '⩘', |
|
1259
|
|
|
'⩚' => '⩚', |
|
1260
|
|
|
'⩛' => '⩛', |
|
1261
|
|
|
'⩜' => '⩜', |
|
1262
|
|
|
'⩝' => '⩝', |
|
1263
|
|
|
'⩟' => '⩟', |
|
1264
|
|
|
'⩦' => '⩦', |
|
1265
|
|
|
'⩪' => '⩪', |
|
1266
|
|
|
'⩭' => '⩭', |
|
1267
|
|
|
'⩭̸' => '⩭̸', |
|
1268
|
|
|
'⩮' => '⩮', |
|
1269
|
|
|
'⩯' => '⩯', |
|
1270
|
|
|
'⩰' => '⩰', |
|
1271
|
|
|
'⩰̸' => '⩰̸', |
|
1272
|
|
|
'⩱' => '⩱', |
|
1273
|
|
|
'⩲' => '⩲', |
|
1274
|
|
|
'⩳' => '⩳', |
|
1275
|
|
|
'⩴' => '⩴', |
|
1276
|
|
|
'⩵' => '⩵', |
|
1277
|
|
|
'⩷' => '⩷', |
|
1278
|
|
|
'⩸' => '⩸', |
|
1279
|
|
|
'⩹' => '⩹', |
|
1280
|
|
|
'⩺' => '⩺', |
|
1281
|
|
|
'⩻' => '⩻', |
|
1282
|
|
|
'⩼' => '⩼', |
|
1283
|
|
|
'⩽' => '⩽', |
|
1284
|
|
|
'⩽̸' => '⩽̸', |
|
1285
|
|
|
'⩾' => '⩾', |
|
1286
|
|
|
'⩾̸' => '⩾̸', |
|
1287
|
|
|
'⩿' => '⩿', |
|
1288
|
|
|
'⪀' => '⪀', |
|
1289
|
|
|
'⪁' => '⪁', |
|
1290
|
|
|
'⪂' => '⪂', |
|
1291
|
|
|
'⪃' => '⪃', |
|
1292
|
|
|
'⪄' => '⪄', |
|
1293
|
|
|
'⪅' => '⪅', |
|
1294
|
|
|
'⪆' => '⪆', |
|
1295
|
|
|
'⪇' => '⪇', |
|
1296
|
|
|
'⪈' => '⪈', |
|
1297
|
|
|
'⪉' => '⪉', |
|
1298
|
|
|
'⪊' => '⪊', |
|
1299
|
|
|
'⪋' => '⪋', |
|
1300
|
|
|
'⪌' => '⪌', |
|
1301
|
|
|
'⪍' => '⪍', |
|
1302
|
|
|
'⪎' => '⪎', |
|
1303
|
|
|
'⪏' => '⪏', |
|
1304
|
|
|
'⪐' => '⪐', |
|
1305
|
|
|
'⪑' => '⪑', |
|
1306
|
|
|
'⪒' => '⪒', |
|
1307
|
|
|
'⪓' => '⪓', |
|
1308
|
|
|
'⪔' => '⪔', |
|
1309
|
|
|
'⪕' => '⪕', |
|
1310
|
|
|
'⪖' => '⪖', |
|
1311
|
|
|
'⪗' => '⪗', |
|
1312
|
|
|
'⪘' => '⪘', |
|
1313
|
|
|
'⪙' => '⪙', |
|
1314
|
|
|
'⪚' => '⪚', |
|
1315
|
|
|
'⪝' => '⪝', |
|
1316
|
|
|
'⪞' => '⪞', |
|
1317
|
|
|
'⪟' => '⪟', |
|
1318
|
|
|
'⪠' => '⪠', |
|
1319
|
|
|
'⪡' => '⪡', |
|
1320
|
|
|
'⪡̸' => '⪡̸', |
|
1321
|
|
|
'⪢' => '⪢', |
|
1322
|
|
|
'⪢̸' => '⪢̸', |
|
1323
|
|
|
'⪤' => '⪤', |
|
1324
|
|
|
'⪥' => '⪥', |
|
1325
|
|
|
'⪦' => '⪦', |
|
1326
|
|
|
'⪧' => '⪧', |
|
1327
|
|
|
'⪨' => '⪨', |
|
1328
|
|
|
'⪩' => '⪩', |
|
1329
|
|
|
'⪪' => '⪪', |
|
1330
|
|
|
'⪫' => '⪫', |
|
1331
|
|
|
'⪬' => '⪬', |
|
1332
|
|
|
'⪬︀' => '⪬︀', |
|
1333
|
|
|
'⪭' => '⪭', |
|
1334
|
|
|
'⪭︀' => '⪭︀', |
|
1335
|
|
|
'⪮' => '⪮', |
|
1336
|
|
|
'⪯' => '⪯', |
|
1337
|
|
|
'⪯̸' => '⪯̸', |
|
1338
|
|
|
'⪰' => '⪰', |
|
1339
|
|
|
'⪰̸' => '⪰̸', |
|
1340
|
|
|
'⪳' => '⪳', |
|
1341
|
|
|
'⪴' => '⪴', |
|
1342
|
|
|
'⪵' => '⪵', |
|
1343
|
|
|
'⪶' => '⪶', |
|
1344
|
|
|
'⪷' => '⪷', |
|
1345
|
|
|
'⪸' => '⪸', |
|
1346
|
|
|
'⪹' => '⪹', |
|
1347
|
|
|
'⪺' => '⪺', |
|
1348
|
|
|
'⪻' => '⪻', |
|
1349
|
|
|
'⪼' => '⪼', |
|
1350
|
|
|
'⪽' => '⪽', |
|
1351
|
|
|
'⪾' => '⪾', |
|
1352
|
|
|
'⪿' => '⪿', |
|
1353
|
|
|
'⫀' => '⫀', |
|
1354
|
|
|
'⫁' => '⫁', |
|
1355
|
|
|
'⫂' => '⫂', |
|
1356
|
|
|
'⫃' => '⫃', |
|
1357
|
|
|
'⫄' => '⫄', |
|
1358
|
|
|
'⫅' => '⫅', |
|
1359
|
|
|
'⫅̸' => '⫅̸', |
|
1360
|
|
|
'⫆' => '⫆', |
|
1361
|
|
|
'⫆̸' => '⫆̸', |
|
1362
|
|
|
'⫇' => '⫇', |
|
1363
|
|
|
'⫈' => '⫈', |
|
1364
|
|
|
'⫋' => '⫋', |
|
1365
|
|
|
'⫋︀' => '⫋︀', |
|
1366
|
|
|
'⫌' => '⫌', |
|
1367
|
|
|
'⫌︀' => '⫌︀', |
|
1368
|
|
|
'⫏' => '⫏', |
|
1369
|
|
|
'⫐' => '⫐', |
|
1370
|
|
|
'⫑' => '⫑', |
|
1371
|
|
|
'⫒' => '⫒', |
|
1372
|
|
|
'⫓' => '⫓', |
|
1373
|
|
|
'⫔' => '⫔', |
|
1374
|
|
|
'⫕' => '⫕', |
|
1375
|
|
|
'⫖' => '⫖', |
|
1376
|
|
|
'⫗' => '⫗', |
|
1377
|
|
|
'⫘' => '⫘', |
|
1378
|
|
|
'⫙' => '⫙', |
|
1379
|
|
|
'⫚' => '⫚', |
|
1380
|
|
|
'⫛' => '⫛', |
|
1381
|
|
|
'⫤' => '⫤', |
|
1382
|
|
|
'⫦' => '⫦', |
|
1383
|
|
|
'⫧' => '⫧', |
|
1384
|
|
|
'⫨' => '⫨', |
|
1385
|
|
|
'⫩' => '⫩', |
|
1386
|
|
|
'⫫' => '⫫', |
|
1387
|
|
|
'⫬' => '⫬', |
|
1388
|
|
|
'⫭' => '⫭', |
|
1389
|
|
|
'⫮' => '⫮', |
|
1390
|
|
|
'⫯' => '⫯', |
|
1391
|
|
|
'⫰' => '⫰', |
|
1392
|
|
|
'⫱' => '⫱', |
|
1393
|
|
|
'⫲' => '⫲', |
|
1394
|
|
|
'⫳' => '⫳', |
|
1395
|
|
|
'⫽' => '⫽', |
|
1396
|
|
|
'⫽⃥' => '⫽⃥', |
|
1397
|
|
|
'ff' => 'ff', |
|
1398
|
|
|
'fi' => 'fi', |
|
1399
|
|
|
'fl' => 'fl', |
|
1400
|
|
|
'ffi' => 'ffi', |
|
1401
|
|
|
'ffl' => 'ffl', |
|
1402
|
|
|
'𝒜' => '𝒜', |
|
1403
|
|
|
'𝒞' => '𝒞', |
|
1404
|
|
|
'𝒟' => '𝒟', |
|
1405
|
|
|
'𝒢' => '𝒢', |
|
1406
|
|
|
'𝒥' => '𝒥', |
|
1407
|
|
|
'𝒦' => '𝒦', |
|
1408
|
|
|
'𝒩' => '𝒩', |
|
1409
|
|
|
'𝒪' => '𝒪', |
|
1410
|
|
|
'𝒫' => '𝒫', |
|
1411
|
|
|
'𝒬' => '𝒬', |
|
1412
|
|
|
'𝒮' => '𝒮', |
|
1413
|
|
|
'𝒯' => '𝒯', |
|
1414
|
|
|
'𝒰' => '𝒰', |
|
1415
|
|
|
'𝒱' => '𝒱', |
|
1416
|
|
|
'𝒲' => '𝒲', |
|
1417
|
|
|
'𝒳' => '𝒳', |
|
1418
|
|
|
'𝒴' => '𝒴', |
|
1419
|
|
|
'𝒵' => '𝒵', |
|
1420
|
|
|
'𝒶' => '𝒶', |
|
1421
|
|
|
'𝒷' => '𝒷', |
|
1422
|
|
|
'𝒸' => '𝒸', |
|
1423
|
|
|
'𝒹' => '𝒹', |
|
1424
|
|
|
'𝒻' => '𝒻', |
|
1425
|
|
|
'𝒽' => '𝒽', |
|
1426
|
|
|
'𝒾' => '𝒾', |
|
1427
|
|
|
'𝒿' => '𝒿', |
|
1428
|
|
|
'𝓀' => '𝓀', |
|
1429
|
|
|
'𝓁' => '𝓁', |
|
1430
|
|
|
'𝓂' => '𝓂', |
|
1431
|
|
|
'𝓃' => '𝓃', |
|
1432
|
|
|
'𝓅' => '𝓅', |
|
1433
|
|
|
'𝓆' => '𝓆', |
|
1434
|
|
|
'𝓇' => '𝓇', |
|
1435
|
|
|
'𝓈' => '𝓈', |
|
1436
|
|
|
'𝓉' => '𝓉', |
|
1437
|
|
|
'𝓊' => '𝓊', |
|
1438
|
|
|
'𝓋' => '𝓋', |
|
1439
|
|
|
'𝓌' => '𝓌', |
|
1440
|
|
|
'𝓍' => '𝓍', |
|
1441
|
|
|
'𝓎' => '𝓎', |
|
1442
|
|
|
'𝓏' => '𝓏', |
|
1443
|
|
|
'𝔄' => '𝔄', |
|
1444
|
|
|
'𝔅' => '𝔅', |
|
1445
|
|
|
'𝔇' => '𝔇', |
|
1446
|
|
|
'𝔈' => '𝔈', |
|
1447
|
|
|
'𝔉' => '𝔉', |
|
1448
|
|
|
'𝔊' => '𝔊', |
|
1449
|
|
|
'𝔍' => '𝔍', |
|
1450
|
|
|
'𝔎' => '𝔎', |
|
1451
|
|
|
'𝔏' => '𝔏', |
|
1452
|
|
|
'𝔐' => '𝔐', |
|
1453
|
|
|
'𝔑' => '𝔑', |
|
1454
|
|
|
'𝔒' => '𝔒', |
|
1455
|
|
|
'𝔓' => '𝔓', |
|
1456
|
|
|
'𝔔' => '𝔔', |
|
1457
|
|
|
'𝔖' => '𝔖', |
|
1458
|
|
|
'𝔗' => '𝔗', |
|
1459
|
|
|
'𝔘' => '𝔘', |
|
1460
|
|
|
'𝔙' => '𝔙', |
|
1461
|
|
|
'𝔚' => '𝔚', |
|
1462
|
|
|
'𝔛' => '𝔛', |
|
1463
|
|
|
'𝔜' => '𝔜', |
|
1464
|
|
|
'𝔞' => '𝔞', |
|
1465
|
|
|
'𝔟' => '𝔟', |
|
1466
|
|
|
'𝔠' => '𝔠', |
|
1467
|
|
|
'𝔡' => '𝔡', |
|
1468
|
|
|
'𝔢' => '𝔢', |
|
1469
|
|
|
'𝔣' => '𝔣', |
|
1470
|
|
|
'𝔤' => '𝔤', |
|
1471
|
|
|
'𝔥' => '𝔥', |
|
1472
|
|
|
'𝔦' => '𝔦', |
|
1473
|
|
|
'𝔧' => '𝔧', |
|
1474
|
|
|
'𝔨' => '𝔨', |
|
1475
|
|
|
'𝔩' => '𝔩', |
|
1476
|
|
|
'𝔪' => '𝔪', |
|
1477
|
|
|
'𝔫' => '𝔫', |
|
1478
|
|
|
'𝔬' => '𝔬', |
|
1479
|
|
|
'𝔭' => '𝔭', |
|
1480
|
|
|
'𝔮' => '𝔮', |
|
1481
|
|
|
'𝔯' => '𝔯', |
|
1482
|
|
|
'𝔰' => '𝔰', |
|
1483
|
|
|
'𝔱' => '𝔱', |
|
1484
|
|
|
'𝔲' => '𝔲', |
|
1485
|
|
|
'𝔳' => '𝔳', |
|
1486
|
|
|
'𝔴' => '𝔴', |
|
1487
|
|
|
'𝔵' => '𝔵', |
|
1488
|
|
|
'𝔶' => '𝔶', |
|
1489
|
|
|
'𝔷' => '𝔷', |
|
1490
|
|
|
'𝔸' => '𝔸', |
|
1491
|
|
|
'𝔹' => '𝔹', |
|
1492
|
|
|
'𝔻' => '𝔻', |
|
1493
|
|
|
'𝔼' => '𝔼', |
|
1494
|
|
|
'𝔽' => '𝔽', |
|
1495
|
|
|
'𝔾' => '𝔾', |
|
1496
|
|
|
'𝕀' => '𝕀', |
|
1497
|
|
|
'𝕁' => '𝕁', |
|
1498
|
|
|
'𝕂' => '𝕂', |
|
1499
|
|
|
'𝕃' => '𝕃', |
|
1500
|
|
|
'𝕄' => '𝕄', |
|
1501
|
|
|
'𝕆' => '𝕆', |
|
1502
|
|
|
'𝕊' => '𝕊', |
|
1503
|
|
|
'𝕋' => '𝕋', |
|
1504
|
|
|
'𝕌' => '𝕌', |
|
1505
|
|
|
'𝕍' => '𝕍', |
|
1506
|
|
|
'𝕎' => '𝕎', |
|
1507
|
|
|
'𝕏' => '𝕏', |
|
1508
|
|
|
'𝕐' => '𝕐', |
|
1509
|
|
|
'𝕒' => '𝕒', |
|
1510
|
|
|
'𝕓' => '𝕓', |
|
1511
|
|
|
'𝕔' => '𝕔', |
|
1512
|
|
|
'𝕕' => '𝕕', |
|
1513
|
|
|
'𝕖' => '𝕖', |
|
1514
|
|
|
'𝕗' => '𝕗', |
|
1515
|
|
|
'𝕘' => '𝕘', |
|
1516
|
|
|
'𝕙' => '𝕙', |
|
1517
|
|
|
'𝕚' => '𝕚', |
|
1518
|
|
|
'𝕛' => '𝕛', |
|
1519
|
|
|
'𝕜' => '𝕜', |
|
1520
|
|
|
'𝕝' => '𝕝', |
|
1521
|
|
|
'𝕞' => '𝕞', |
|
1522
|
|
|
'𝕟' => '𝕟', |
|
1523
|
|
|
'𝕠' => '𝕠', |
|
1524
|
|
|
'𝕡' => '𝕡', |
|
1525
|
|
|
'𝕢' => '𝕢', |
|
1526
|
|
|
'𝕣' => '𝕣', |
|
1527
|
|
|
'𝕤' => '𝕤', |
|
1528
|
|
|
'𝕥' => '𝕥', |
|
1529
|
|
|
'𝕦' => '𝕦', |
|
1530
|
|
|
'𝕧' => '𝕧', |
|
1531
|
|
|
'𝕨' => '𝕨', |
|
1532
|
|
|
'𝕩' => '𝕩', |
|
1533
|
|
|
'𝕪' => '𝕪', |
|
1534
|
|
|
'𝕫' => '𝕫', |
|
1535
|
|
|
); |
|
1536
|
|
|
|
|
1537
|
|
|
/** |
|
1538
|
|
|
* List of never allowed regex replacements. |
|
1539
|
|
|
* |
|
1540
|
|
|
* @var array |
|
1541
|
|
|
*/ |
|
1542
|
|
|
private static $_never_allowed_regex = array( |
|
1543
|
|
|
// default javascript |
|
1544
|
|
|
'javascript\s*:', |
|
1545
|
|
|
// default javascript |
|
1546
|
|
|
'(document|(document\.)?window)\.(location|on\w*)', |
|
1547
|
|
|
// Java: jar-protocol is an XSS hazard |
|
1548
|
|
|
'jar\s*:', |
|
1549
|
|
|
// Mac (will not run the script, but open it in AppleScript Editor) |
|
1550
|
|
|
'applescript\s*:', |
|
1551
|
|
|
// IE: https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#VBscript_in_an_image |
|
1552
|
|
|
'vbscript\s*:', |
|
1553
|
|
|
// IE, surprise! |
|
1554
|
|
|
'wscript\s*:', |
|
1555
|
|
|
// IE |
|
1556
|
|
|
'jscript\s*:', |
|
1557
|
|
|
// IE: https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#VBscript_in_an_image |
|
1558
|
|
|
'vbs\s*:', |
|
1559
|
|
|
// https://html5sec.org/#behavior |
|
1560
|
|
|
'behavior\s:', |
|
1561
|
|
|
// ? |
|
1562
|
|
|
'Redirect\s+30\d', |
|
1563
|
|
|
// data-attribute + base64 |
|
1564
|
|
|
"([\"'])?data\s*:[^\\1]*?base64[^\\1]*?,[^\\1]*?\\1?", |
|
1565
|
|
|
// remove Netscape 4 JS entities |
|
1566
|
|
|
'&\s*\{[^}]*(\}\s*;?|$)', |
|
1567
|
|
|
// old IE, old Netscape |
|
1568
|
|
|
'expression\s*(\(|&\#40;)', |
|
1569
|
|
|
// old Netscape |
|
1570
|
|
|
'mocha\s*:', |
|
1571
|
|
|
// old Netscape |
|
1572
|
|
|
'livescript\s*:', |
|
1573
|
|
|
// default view source |
|
1574
|
|
|
'view-source\s*:', |
|
1575
|
|
|
); |
|
1576
|
|
|
|
|
1577
|
|
|
/** |
|
1578
|
|
|
* List of never allowed strings, afterwards. |
|
1579
|
|
|
* |
|
1580
|
|
|
* @var array |
|
1581
|
|
|
*/ |
|
1582
|
|
|
private static $_never_allowed_str_afterwards = array( |
|
1583
|
|
|
'FSCommand', |
|
1584
|
|
|
'onAbort', |
|
1585
|
|
|
'onActivate', |
|
1586
|
|
|
'onAttribute', |
|
1587
|
|
|
'onAfterPrint', |
|
1588
|
|
|
'onAfterScriptExecute', |
|
1589
|
|
|
'onAfterUpdate', |
|
1590
|
|
|
'onAnimationEnd', |
|
1591
|
|
|
'onAnimationIteration', |
|
1592
|
|
|
'onAnimationStart', |
|
1593
|
|
|
'onAriaRequest', |
|
1594
|
|
|
'onAutoComplete', |
|
1595
|
|
|
'onAutoCompleteError', |
|
1596
|
|
|
'onBeforeActivate', |
|
1597
|
|
|
'onBeforeCopy', |
|
1598
|
|
|
'onBeforeCut', |
|
1599
|
|
|
'onBeforeDeactivate', |
|
1600
|
|
|
'onBeforeEditFocus', |
|
1601
|
|
|
'onBeforePaste', |
|
1602
|
|
|
'onBeforePrint', |
|
1603
|
|
|
'onBeforeScriptExecute', |
|
1604
|
|
|
'onBeforeUnload', |
|
1605
|
|
|
'onBeforeUpdate', |
|
1606
|
|
|
'onBegin', |
|
1607
|
|
|
'onBlur', |
|
1608
|
|
|
'onBounce', |
|
1609
|
|
|
'onCancel', |
|
1610
|
|
|
'onCanPlay', |
|
1611
|
|
|
'onCanPlayThrough', |
|
1612
|
|
|
'onCellChange', |
|
1613
|
|
|
'onChange', |
|
1614
|
|
|
'onClick', |
|
1615
|
|
|
'onClose', |
|
1616
|
|
|
'onCommand', |
|
1617
|
|
|
'onCompassNeedsCalibration', |
|
1618
|
|
|
'onContextMenu', |
|
1619
|
|
|
'onControlSelect', |
|
1620
|
|
|
'onCopy', |
|
1621
|
|
|
'onCueChange', |
|
1622
|
|
|
'onCut', |
|
1623
|
|
|
'onDataAvailable', |
|
1624
|
|
|
'onDataSetChanged', |
|
1625
|
|
|
'onDataSetComplete', |
|
1626
|
|
|
'onDblClick', |
|
1627
|
|
|
'onDeactivate', |
|
1628
|
|
|
'onDeviceLight', |
|
1629
|
|
|
'onDeviceMotion', |
|
1630
|
|
|
'onDeviceOrientation', |
|
1631
|
|
|
'onDeviceProximity', |
|
1632
|
|
|
'onDrag', |
|
1633
|
|
|
'onDragDrop', |
|
1634
|
|
|
'onDragEnd', |
|
1635
|
|
|
'onDragEnter', |
|
1636
|
|
|
'onDragLeave', |
|
1637
|
|
|
'onDragOver', |
|
1638
|
|
|
'onDragStart', |
|
1639
|
|
|
'onDrop', |
|
1640
|
|
|
'onDurationChange', |
|
1641
|
|
|
'onEmptied', |
|
1642
|
|
|
'onEnd', |
|
1643
|
|
|
'onEnded', |
|
1644
|
|
|
'onError', |
|
1645
|
|
|
'onErrorUpdate', |
|
1646
|
|
|
'onExit', |
|
1647
|
|
|
'onFilterChange', |
|
1648
|
|
|
'onFinish', |
|
1649
|
|
|
'onFocus', |
|
1650
|
|
|
'onFocusIn', |
|
1651
|
|
|
'onFocusOut', |
|
1652
|
|
|
'onFormChange', |
|
1653
|
|
|
'onFormInput', |
|
1654
|
|
|
'onFullScreenChange', |
|
1655
|
|
|
'onFullScreenError', |
|
1656
|
|
|
'onGotPointerCapture', |
|
1657
|
|
|
'onHashChange', |
|
1658
|
|
|
'onHelp', |
|
1659
|
|
|
'onInput', |
|
1660
|
|
|
'onInvalid', |
|
1661
|
|
|
'onKeyDown', |
|
1662
|
|
|
'onKeyPress', |
|
1663
|
|
|
'onKeyUp', |
|
1664
|
|
|
'onLanguageChange', |
|
1665
|
|
|
'onLayoutComplete', |
|
1666
|
|
|
'onLoad', |
|
1667
|
|
|
'onLoadedData', |
|
1668
|
|
|
'onLoadedMetaData', |
|
1669
|
|
|
'onLoadStart', |
|
1670
|
|
|
'onLoseCapture', |
|
1671
|
|
|
'onLostPointerCapture', |
|
1672
|
|
|
'onMediaComplete', |
|
1673
|
|
|
'onMediaError', |
|
1674
|
|
|
'onMessage', |
|
1675
|
|
|
'onMouseDown', |
|
1676
|
|
|
'onMouseEnter', |
|
1677
|
|
|
'onMouseLeave', |
|
1678
|
|
|
'onMouseMove', |
|
1679
|
|
|
'onMouseOut', |
|
1680
|
|
|
'onMouseOver', |
|
1681
|
|
|
'onMouseUp', |
|
1682
|
|
|
'onMouseWheel', |
|
1683
|
|
|
'onMove', |
|
1684
|
|
|
'onMoveEnd', |
|
1685
|
|
|
'onMoveStart', |
|
1686
|
|
|
'onMozFullScreenChange', |
|
1687
|
|
|
'onMozFullScreenError', |
|
1688
|
|
|
'onMozPointerLockChange', |
|
1689
|
|
|
'onMozPointerLockError', |
|
1690
|
|
|
'onMsContentZoom', |
|
1691
|
|
|
'onMsFullScreenChange', |
|
1692
|
|
|
'onMsFullScreenError', |
|
1693
|
|
|
'onMsGestureChange', |
|
1694
|
|
|
'onMsGestureDoubleTap', |
|
1695
|
|
|
'onMsGestureEnd', |
|
1696
|
|
|
'onMsGestureHold', |
|
1697
|
|
|
'onMsGestureStart', |
|
1698
|
|
|
'onMsGestureTap', |
|
1699
|
|
|
'onMsGotPointerCapture', |
|
1700
|
|
|
'onMsInertiaStart', |
|
1701
|
|
|
'onMsLostPointerCapture', |
|
1702
|
|
|
'onMsManipulationStateChanged', |
|
1703
|
|
|
'onMsPointerCancel', |
|
1704
|
|
|
'onMsPointerDown', |
|
1705
|
|
|
'onMsPointerEnter', |
|
1706
|
|
|
'onMsPointerLeave', |
|
1707
|
|
|
'onMsPointerMove', |
|
1708
|
|
|
'onMsPointerOut', |
|
1709
|
|
|
'onMsPointerOver', |
|
1710
|
|
|
'onMsPointerUp', |
|
1711
|
|
|
'onMsSiteModeJumpListItemRemoved', |
|
1712
|
|
|
'onMsThumbnailClick', |
|
1713
|
|
|
'onOffline', |
|
1714
|
|
|
'onOnline', |
|
1715
|
|
|
'onOutOfSync', |
|
1716
|
|
|
'onPage', |
|
1717
|
|
|
'onPageHide', |
|
1718
|
|
|
'onPageShow', |
|
1719
|
|
|
'onPaste', |
|
1720
|
|
|
'onPause', |
|
1721
|
|
|
'onPlay', |
|
1722
|
|
|
'onPlaying', |
|
1723
|
|
|
'onPointerCancel', |
|
1724
|
|
|
'onPointerDown', |
|
1725
|
|
|
'onPointerEnter', |
|
1726
|
|
|
'onPointerLeave', |
|
1727
|
|
|
'onPointerLockChange', |
|
1728
|
|
|
'onPointerLockError', |
|
1729
|
|
|
'onPointerMove', |
|
1730
|
|
|
'onPointerOut', |
|
1731
|
|
|
'onPointerOver', |
|
1732
|
|
|
'onPointerUp', |
|
1733
|
|
|
'onPopState', |
|
1734
|
|
|
'onProgress', |
|
1735
|
|
|
'onPropertyChange', |
|
1736
|
|
|
'onRateChange', |
|
1737
|
|
|
'onReadyStateChange', |
|
1738
|
|
|
'onReceived', |
|
1739
|
|
|
'onRepeat', |
|
1740
|
|
|
'onReset', |
|
1741
|
|
|
'onResize', |
|
1742
|
|
|
'onResizeEnd', |
|
1743
|
|
|
'onResizeStart', |
|
1744
|
|
|
'onResume', |
|
1745
|
|
|
'onReverse', |
|
1746
|
|
|
'onRowDelete', |
|
1747
|
|
|
'onRowEnter', |
|
1748
|
|
|
'onRowExit', |
|
1749
|
|
|
'onRowInserted', |
|
1750
|
|
|
'onRowsDelete', |
|
1751
|
|
|
'onRowsEnter', |
|
1752
|
|
|
'onRowsExit', |
|
1753
|
|
|
'onRowsInserted', |
|
1754
|
|
|
'onScroll', |
|
1755
|
|
|
'onSearch', |
|
1756
|
|
|
'onSeek', |
|
1757
|
|
|
'onSeeked', |
|
1758
|
|
|
'onSeeking', |
|
1759
|
|
|
'onSelect', |
|
1760
|
|
|
'onSelectionChange', |
|
1761
|
|
|
'onSelectStart', |
|
1762
|
|
|
'onStalled', |
|
1763
|
|
|
'onStorage', |
|
1764
|
|
|
'onStorageCommit', |
|
1765
|
|
|
'onStart', |
|
1766
|
|
|
'onStop', |
|
1767
|
|
|
'onShow', |
|
1768
|
|
|
'onSyncRestored', |
|
1769
|
|
|
'onSubmit', |
|
1770
|
|
|
'onSuspend', |
|
1771
|
|
|
'onSynchRestored', |
|
1772
|
|
|
'onTimeError', |
|
1773
|
|
|
'onTimeUpdate', |
|
1774
|
|
|
'onTrackChange', |
|
1775
|
|
|
'onTransitionEnd', |
|
1776
|
|
|
'onToggle', |
|
1777
|
|
|
'onUnload', |
|
1778
|
|
|
'onURLFlip', |
|
1779
|
|
|
'onUserProximity', |
|
1780
|
|
|
'onVolumeChange', |
|
1781
|
|
|
'onWaiting', |
|
1782
|
|
|
'onWebKitAnimationEnd', |
|
1783
|
|
|
'onWebKitAnimationIteration', |
|
1784
|
|
|
'onWebKitAnimationStart', |
|
1785
|
|
|
'onWebKitFullScreenChange', |
|
1786
|
|
|
'onWebKitFullScreenError', |
|
1787
|
|
|
'onWebKitTransitionEnd', |
|
1788
|
|
|
'onWheel', |
|
1789
|
|
|
'seekSegmentTime', |
|
1790
|
|
|
'userid', |
|
1791
|
|
|
'datasrc', |
|
1792
|
|
|
'datafld', |
|
1793
|
|
|
'dataformatas', |
|
1794
|
|
|
'ev:handler', |
|
1795
|
|
|
'ev:event', |
|
1796
|
|
|
'0;url', |
|
1797
|
|
|
); |
|
1798
|
|
|
|
|
1799
|
|
|
/** |
|
1800
|
|
|
* https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#Event_Handlers |
|
1801
|
|
|
* |
|
1802
|
|
|
* @var array |
|
1803
|
|
|
*/ |
|
1804
|
|
|
private $_evil_attributes = array( |
|
1805
|
|
|
'on\w*', |
|
1806
|
|
|
'style', |
|
1807
|
|
|
'xmlns', |
|
1808
|
|
|
'formaction', |
|
1809
|
|
|
'form', |
|
1810
|
|
|
'xlink:href', |
|
1811
|
|
|
'seekSegmentTime', |
|
1812
|
|
|
'FSCommand', |
|
1813
|
|
|
'eval', |
|
1814
|
|
|
); |
|
1815
|
|
|
|
|
1816
|
|
|
/** |
|
1817
|
|
|
* XSS Hash - random Hash for protecting URLs. |
|
1818
|
|
|
* |
|
1819
|
|
|
* @var string |
|
1820
|
|
|
*/ |
|
1821
|
|
|
private $_xss_hash; |
|
1822
|
|
|
|
|
1823
|
|
|
/** |
|
1824
|
|
|
* The replacement-string for not allowed strings. |
|
1825
|
|
|
* |
|
1826
|
|
|
* @var string |
|
1827
|
|
|
*/ |
|
1828
|
|
|
private $_replacement = ''; |
|
1829
|
|
|
|
|
1830
|
|
|
/** |
|
1831
|
|
|
* List of never allowed strings. |
|
1832
|
|
|
* |
|
1833
|
|
|
* @var array |
|
1834
|
|
|
*/ |
|
1835
|
|
|
private $_never_allowed_str = array(); |
|
1836
|
|
|
|
|
1837
|
|
|
/** |
|
1838
|
|
|
* If your DB (MySQL) encoding is "utf8" and not "utf8mb4", then |
|
1839
|
|
|
* you can't save 4-Bytes chars from UTF-8 and someone can create stored XSS-attacks. |
|
1840
|
|
|
* |
|
1841
|
|
|
* @var bool |
|
1842
|
|
|
*/ |
|
1843
|
|
|
private $_stripe_4byte_chars = false; |
|
1844
|
|
|
|
|
1845
|
|
|
/** |
|
1846
|
|
|
* @var bool|null |
|
1847
|
|
|
*/ |
|
1848
|
|
|
private $xss_found = null; |
|
1849
|
|
|
|
|
1850
|
|
|
/** |
|
1851
|
|
|
* __construct() |
|
1852
|
|
|
*/ |
|
1853
|
|
|
public function __construct() |
|
1854
|
|
|
{ |
|
1855
|
|
|
$this->_initNeverAllowedStr(); |
|
1856
|
|
|
} |
|
1857
|
|
|
|
|
1858
|
|
|
/** |
|
1859
|
|
|
* Compact exploded words. |
|
1860
|
|
|
* |
|
1861
|
|
|
* <p> |
|
1862
|
|
|
* <br /> |
|
1863
|
|
|
* INFO: Callback method for xss_clean() to remove whitespace from things like 'j a v a s c r i p t'. |
|
1864
|
|
|
* </p> |
|
1865
|
|
|
* |
|
1866
|
|
|
* @param array $matches |
|
1867
|
|
|
* |
|
1868
|
|
|
* @return string |
|
1869
|
|
|
*/ |
|
1870
|
|
|
private function _compact_exploded_words_callback($matches) |
|
1871
|
|
|
{ |
|
1872
|
|
|
return preg_replace('/(?:\s+|"|\042|\'|\047|\+)*+/', '', $matches[1]) . $matches[2]; |
|
1873
|
|
|
} |
|
1874
|
|
|
|
|
1875
|
|
|
/** |
|
1876
|
|
|
* HTML-Entity decode callback. |
|
1877
|
|
|
* |
|
1878
|
|
|
* @param array $match |
|
1879
|
|
|
* |
|
1880
|
|
|
* @return string |
|
1881
|
|
|
*/ |
|
1882
|
|
|
private function _decode_entity($match) |
|
1883
|
|
|
{ |
|
1884
|
|
|
// init |
|
1885
|
|
|
$this->_xss_hash(); |
|
1886
|
|
|
|
|
1887
|
|
|
$match = $match[0]; |
|
1888
|
|
|
|
|
1889
|
|
|
// protect GET variables in URLs |
|
1890
|
|
|
$match = preg_replace('|\?([a-z\_0-9\-]+)\=([a-z\_0-9\-/]+)|i', $this->_xss_hash . '::GET_FIRST' . '\\1=\\2', $match); |
|
1891
|
|
|
$match = preg_replace('|\&([a-z\_0-9\-]+)\=([a-z\_0-9\-/]+)|i', $this->_xss_hash . '::GET_NEXT' . '\\1=\\2', $match); |
|
1892
|
|
|
|
|
1893
|
|
|
// un-protect URL GET vars |
|
1894
|
|
|
return str_replace( |
|
1895
|
|
|
array( |
|
1896
|
|
|
$this->_xss_hash . '::GET_FIRST', |
|
1897
|
|
|
$this->_xss_hash . '::GET_NEXT', |
|
1898
|
|
|
), |
|
1899
|
|
|
array( |
|
1900
|
|
|
'?', |
|
1901
|
|
|
'&', |
|
1902
|
|
|
), |
|
1903
|
|
|
$this->_entity_decode($match) |
|
1904
|
|
|
); |
|
1905
|
|
|
} |
|
1906
|
|
|
|
|
1907
|
|
|
/** |
|
1908
|
|
|
* @param string $str |
|
1909
|
|
|
* |
|
1910
|
|
|
* @return mixed |
|
1911
|
|
|
*/ |
|
1912
|
|
|
private function _do($str) |
|
1913
|
|
|
{ |
|
1914
|
|
|
$str = (string)$str; |
|
1915
|
|
|
$strInt = (int)$str; |
|
1916
|
|
|
$strFloat = (float)$str; |
|
1917
|
|
|
if ( |
|
1918
|
|
|
!$str |
|
1919
|
|
|
|| |
|
1920
|
|
|
"$strInt" == $str |
|
1921
|
|
|
|| |
|
1922
|
|
|
"$strFloat" == $str |
|
1923
|
|
|
) { |
|
1924
|
|
|
|
|
1925
|
|
|
// no xss found |
|
1926
|
|
|
if ($this->xss_found !== true) { |
|
1927
|
|
|
$this->xss_found = false; |
|
1928
|
|
|
} |
|
1929
|
|
|
|
|
1930
|
|
|
return $str; |
|
1931
|
|
|
} |
|
1932
|
|
|
|
|
1933
|
|
|
// removes all non-UTF-8 characters |
|
1934
|
|
|
// && |
|
1935
|
|
|
// remove NULL characters (ignored by some browsers) |
|
1936
|
|
|
$str = UTF8::clean($str, true, true, false); |
|
1937
|
|
|
|
|
1938
|
|
|
// decode UTF-7 characters |
|
1939
|
|
|
$str = $this->_repack_utf7($str); |
|
1940
|
|
|
|
|
1941
|
|
|
// decode the string |
|
1942
|
|
|
$str = $this->_decode_string($str); |
|
1943
|
|
|
|
|
1944
|
|
|
// remove all >= 4-Byte chars if needed |
|
1945
|
|
|
if ($this->_stripe_4byte_chars === true) { |
|
1946
|
|
|
$str = preg_replace('/[\x{10000}-\x{10FFFF}]/u', '', $str); |
|
1947
|
|
|
} |
|
1948
|
|
|
|
|
1949
|
|
|
// backup the string (for later comparision) |
|
1950
|
|
|
$str_backup = $str; |
|
1951
|
|
|
|
|
1952
|
|
|
// remove strings that are never allowed |
|
1953
|
|
|
$str = $this->_do_never_allowed($str); |
|
1954
|
|
|
|
|
1955
|
|
|
// corrects words before the browser will do it |
|
1956
|
|
|
$str = $this->_compact_exploded_javascript($str); |
|
1957
|
|
|
|
|
1958
|
|
|
// remove disallowed javascript calls in links, images etc. |
|
1959
|
|
|
$str = $this->_remove_disallowed_javascript($str); |
|
1960
|
|
|
|
|
1961
|
|
|
// remove evil attributes such as style, onclick and xmlns |
|
1962
|
|
|
$str = $this->_remove_evil_attributes($str); |
|
1963
|
|
|
|
|
1964
|
|
|
// sanitize naughty HTML elements |
|
1965
|
|
|
$str = $this->_sanitize_naughty_html($str); |
|
1966
|
|
|
|
|
1967
|
|
|
// sanitize naughty JavaScript elements |
|
1968
|
|
|
$str = $this->_sanitize_naughty_javascript($str); |
|
1969
|
|
|
|
|
1970
|
|
|
// final clean up |
|
1971
|
|
|
// |
|
1972
|
|
|
// -> This adds a bit of extra precaution in case something got through the above filters. |
|
1973
|
|
|
$str = $this->_do_never_allowed_afterwards($str); |
|
1974
|
|
|
|
|
1975
|
|
|
// check for xss |
|
1976
|
|
|
if ($this->xss_found !== true) { |
|
1977
|
|
|
$this->xss_found = !($str_backup === $str); |
|
1978
|
|
|
} |
|
1979
|
|
|
|
|
1980
|
|
|
return $str; |
|
1981
|
|
|
} |
|
1982
|
|
|
|
|
1983
|
|
|
/** |
|
1984
|
|
|
* Remove never allowed strings. |
|
1985
|
|
|
* |
|
1986
|
|
|
* @param string $str |
|
1987
|
|
|
* |
|
1988
|
|
|
* @return string |
|
1989
|
|
|
*/ |
|
1990
|
|
|
private function _do_never_allowed($str) |
|
1991
|
|
|
{ |
|
1992
|
|
|
static $NEVER_ALLOWED_CACHE = array(); |
|
1993
|
|
|
$NEVER_ALLOWED_CACHE['keys'] = null; |
|
1994
|
|
|
$NEVER_ALLOWED_CACHE['regex'] = null; |
|
1995
|
|
|
|
|
1996
|
|
|
if (null === $NEVER_ALLOWED_CACHE['keys']) { |
|
1997
|
|
|
$NEVER_ALLOWED_CACHE['keys'] = array_keys($this->_never_allowed_str); |
|
1998
|
|
|
} |
|
1999
|
|
|
$str = str_ireplace($NEVER_ALLOWED_CACHE['keys'], $this->_never_allowed_str, $str); |
|
2000
|
|
|
|
|
2001
|
|
|
if (null === $NEVER_ALLOWED_CACHE['regex']) { |
|
2002
|
|
|
$NEVER_ALLOWED_CACHE['regex'] = implode('|', self::$_never_allowed_regex); |
|
2003
|
|
|
} |
|
2004
|
|
|
$str = preg_replace('#' . $NEVER_ALLOWED_CACHE['regex'] . '#is', $this->_replacement, $str); |
|
2005
|
|
|
|
|
2006
|
|
|
return (string)$str; |
|
2007
|
|
|
} |
|
2008
|
|
|
|
|
2009
|
|
|
/** |
|
2010
|
|
|
* Remove never allowed string, afterwards. |
|
2011
|
|
|
* |
|
2012
|
|
|
* <p> |
|
2013
|
|
|
* <br /> |
|
2014
|
|
|
* INFO: clean-up also some string, if there is no html-tag |
|
2015
|
|
|
* </p> |
|
2016
|
|
|
* |
|
2017
|
|
|
* @param string $str |
|
2018
|
|
|
* |
|
2019
|
|
|
* @return string |
|
2020
|
|
|
*/ |
|
2021
|
|
|
private function _do_never_allowed_afterwards($str) |
|
2022
|
|
|
{ |
|
2023
|
|
|
static $NEVER_ALLOWED_STR_AFTERWARDS_CACHE; |
|
2024
|
|
|
|
|
2025
|
|
|
if (null === $NEVER_ALLOWED_STR_AFTERWARDS_CACHE) { |
|
2026
|
|
|
foreach (self::$_never_allowed_str_afterwards as &$neverAllowedStr) { |
|
2027
|
|
|
$neverAllowedStr .= '.*='; |
|
2028
|
|
|
} |
|
2029
|
|
|
|
|
2030
|
|
|
$NEVER_ALLOWED_STR_AFTERWARDS_CACHE = implode('|', self::$_never_allowed_str_afterwards); |
|
2031
|
|
|
} |
|
2032
|
|
|
|
|
2033
|
|
|
$str = preg_replace('#' . $NEVER_ALLOWED_STR_AFTERWARDS_CACHE . '#isU', $this->_replacement, $str); |
|
2034
|
|
|
|
|
2035
|
|
|
return (string)$str; |
|
2036
|
|
|
} |
|
2037
|
|
|
|
|
2038
|
|
|
/** |
|
2039
|
|
|
* Entity-decoding. |
|
2040
|
|
|
* |
|
2041
|
|
|
* @param string $str |
|
2042
|
|
|
* |
|
2043
|
|
|
* @return string |
|
2044
|
|
|
*/ |
|
2045
|
|
|
private function _entity_decode($str) |
|
2046
|
|
|
{ |
|
2047
|
|
|
static $HTML_ENTITIES_CACHE; |
|
2048
|
|
|
|
|
2049
|
|
|
/** @noinspection UsageOfSilenceOperatorInspection */ |
|
2050
|
|
|
/** @noinspection PhpUsageOfSilenceOperatorInspection */ |
|
2051
|
|
|
// HHVM dons't support "ENT_DISALLOWED" && "ENT_SUBSTITUTE" |
|
2052
|
|
|
$flags = Bootup::is_php('5.4') ? |
|
2053
|
|
|
ENT_QUOTES | ENT_HTML5 | @ENT_DISALLOWED | @ENT_SUBSTITUTE : |
|
2054
|
|
|
ENT_QUOTES; |
|
2055
|
|
|
|
|
2056
|
|
|
// decode |
|
2057
|
|
|
if (strpos($str, $this->_xss_hash) !== false) { |
|
2058
|
|
|
$str = UTF8::html_entity_decode($str, $flags); |
|
2059
|
|
|
} else { |
|
2060
|
|
|
$str = UTF8::rawurldecode($str); |
|
2061
|
|
|
} |
|
2062
|
|
|
|
|
2063
|
|
|
// decode-again, for e.g. HHVM, PHP 5.3, miss configured applications ... |
|
2064
|
|
|
if (preg_match_all('/&[A-Za-z]{2,}[;]{0}/', $str, $matches)) { |
|
2065
|
|
|
|
|
2066
|
|
|
if (null === $HTML_ENTITIES_CACHE) { |
|
2067
|
|
|
|
|
2068
|
|
|
// links: |
|
2069
|
|
|
// - http://dev.w3.org/html5/html-author/charref |
|
2070
|
|
|
// - http://www.w3schools.com/charsets/ref_html_entities_n.asp |
|
2071
|
|
|
$entitiesSecurity = array( |
|
2072
|
|
|
'�' => '', |
|
2073
|
|
|
'�' => '', |
|
2074
|
|
|
'' => '', |
|
2075
|
|
|
'' => '', |
|
2076
|
|
|
'>⃒' => '', |
|
2077
|
|
|
'' => '', |
|
2078
|
|
|
'' => '', |
|
2079
|
|
|
'­' => '', |
|
2080
|
|
|
'­' => '', |
|
2081
|
|
|
'­' => '', |
|
2082
|
|
|
':' => ':', |
|
2083
|
|
|
':' => ':', |
|
2084
|
|
|
':' => ':', |
|
2085
|
|
|
'(' => '(', |
|
2086
|
|
|
'(' => '(', |
|
2087
|
|
|
'(' => '(', |
|
2088
|
|
|
')' => ')', |
|
2089
|
|
|
')' => ')', |
|
2090
|
|
|
')' => ')', |
|
2091
|
|
|
'?' => '?', |
|
2092
|
|
|
'?' => '?', |
|
2093
|
|
|
'?' => '?', |
|
2094
|
|
|
'/' => '/', |
|
2095
|
|
|
'/' => '/', |
|
2096
|
|
|
'/' => '/', |
|
2097
|
|
|
''' => '\'', |
|
2098
|
|
|
''' => '\'', |
|
2099
|
|
|
''' => '\'', |
|
2100
|
|
|
''' => '\'', |
|
2101
|
|
|
''' => '\'', |
|
2102
|
|
|
'\' => '\'', |
|
2103
|
|
|
'\' => '\\', |
|
2104
|
|
|
'\' => '\\', |
|
2105
|
|
|
',' => ',', |
|
2106
|
|
|
',' => ',', |
|
2107
|
|
|
',' => ',', |
|
2108
|
|
|
'.' => '.', |
|
2109
|
|
|
'.' => '.', |
|
2110
|
|
|
'"' => '"', |
|
2111
|
|
|
'"' => '"', |
|
2112
|
|
|
'"' => '"', |
|
2113
|
|
|
'"' => '"', |
|
2114
|
|
|
'`' => '`', |
|
2115
|
|
|
'`' => '`', |
|
2116
|
|
|
'`' => '`', |
|
2117
|
|
|
'`' => '`', |
|
2118
|
|
|
'.' => '.', |
|
2119
|
|
|
'=' => '=', |
|
2120
|
|
|
'=' => '=', |
|
2121
|
|
|
'=' => '=', |
|
2122
|
|
|
'&newline;' => "\n", |
|
2123
|
|
|
'
' => "\n", |
|
2124
|
|
|
' ' => "\n", |
|
2125
|
|
|
'&tab;' => "\t", |
|
2126
|
|
|
'	' => "\t", |
|
2127
|
|
|
'	' => "\t", |
|
2128
|
|
|
); |
|
2129
|
|
|
|
|
2130
|
|
|
$HTML_ENTITIES_CACHE = array_merge( |
|
2131
|
|
|
$entitiesSecurity, |
|
2132
|
|
|
array_flip(get_html_translation_table(HTML_ENTITIES, $flags)), |
|
2133
|
|
|
array_flip(self::$entitiesFallback) |
|
2134
|
|
|
); |
|
2135
|
|
|
} |
|
2136
|
|
|
|
|
2137
|
|
|
$replace = array(); |
|
2138
|
|
|
foreach ($matches[0] as $match) { |
|
2139
|
|
|
$match .= ';'; |
|
2140
|
|
|
if (isset($HTML_ENTITIES_CACHE[$match])) { |
|
2141
|
|
|
$replace[$match] = $HTML_ENTITIES_CACHE[$match]; |
|
2142
|
|
|
} |
|
2143
|
|
|
} |
|
2144
|
|
|
|
|
2145
|
|
|
if (count($replace) > 0) { |
|
2146
|
|
|
$str = str_replace(array_keys($replace), array_values($replace), $str); |
|
2147
|
|
|
} |
|
2148
|
|
|
} |
|
2149
|
|
|
|
|
2150
|
|
|
return $str; |
|
2151
|
|
|
} |
|
2152
|
|
|
|
|
2153
|
|
|
/** |
|
2154
|
|
|
* Filters tag attributes for consistency and safety. |
|
2155
|
|
|
* |
|
2156
|
|
|
* @param string $str |
|
2157
|
|
|
* |
|
2158
|
|
|
* @return string |
|
2159
|
|
|
*/ |
|
2160
|
|
|
private function _filter_attributes($str) |
|
2161
|
|
|
{ |
|
2162
|
|
|
if ($str === '') { |
|
2163
|
|
|
return ''; |
|
2164
|
|
|
} |
|
2165
|
|
|
|
|
2166
|
|
|
$out = ''; |
|
2167
|
|
|
if ( |
|
2168
|
|
|
preg_match_all('#\s*[A-Za-z\-]+\s*=\s*("|\042|\'|\047)([^\\1]*?)\\1#', $str, $matches) |
|
2169
|
|
|
|| |
|
2170
|
|
|
( |
|
2171
|
|
|
$this->_replacement |
|
2172
|
|
|
&& |
|
2173
|
|
|
preg_match_all('#\s*[a-zA-Z\-]+\s*=' . preg_quote($this->_replacement, '#') . '$#', $str, $matches) |
|
2174
|
|
|
) |
|
2175
|
|
|
) { |
|
2176
|
|
|
foreach ($matches[0] as $match) { |
|
2177
|
|
|
$out .= $match; |
|
2178
|
|
|
} |
|
2179
|
|
|
} |
|
2180
|
|
|
|
|
2181
|
|
|
return $out; |
|
2182
|
|
|
} |
|
2183
|
|
|
|
|
2184
|
|
|
/** |
|
2185
|
|
|
* initialize "$this->_never_allowed_str" |
|
2186
|
|
|
*/ |
|
2187
|
|
|
private function _initNeverAllowedStr() |
|
2188
|
|
|
{ |
|
2189
|
|
|
$this->_never_allowed_str = array( |
|
2190
|
|
|
'document.cookie' => $this->_replacement, |
|
2191
|
|
|
'document.write' => $this->_replacement, |
|
2192
|
|
|
'.parentNode' => $this->_replacement, |
|
2193
|
|
|
'.innerHTML' => $this->_replacement, |
|
2194
|
|
|
'.appendChild' => $this->_replacement, |
|
2195
|
|
|
'-moz-binding' => $this->_replacement, |
|
2196
|
|
|
'<!--' => '<!--', |
|
2197
|
|
|
'-->' => '-->', |
|
2198
|
|
|
'<?' => '<?', |
|
2199
|
|
|
'?>' => '?>', |
|
2200
|
|
|
'<![CDATA[' => '<![CDATA[', |
|
2201
|
|
|
'<!ENTITY' => '<!ENTITY', |
|
2202
|
|
|
'<!DOCTYPE' => '<!DOCTYPE', |
|
2203
|
|
|
'<!ATTLIST' => '<!ATTLIST', |
|
2204
|
|
|
'<comment>' => '<comment>', |
|
2205
|
|
|
); |
|
2206
|
|
|
} |
|
2207
|
|
|
|
|
2208
|
|
|
/** |
|
2209
|
|
|
* Callback method for xss_clean() to sanitize links. |
|
2210
|
|
|
* |
|
2211
|
|
|
* <p> |
|
2212
|
|
|
* <br /> |
|
2213
|
|
|
* INFO: This limits the PCRE backtracks, making it more performance friendly |
|
2214
|
|
|
* and prevents PREG_BACKTRACK_LIMIT_ERROR from being triggered in |
|
2215
|
|
|
* PHP 5.2+ on link-heavy strings. |
|
2216
|
|
|
* </p> |
|
2217
|
|
|
* |
|
2218
|
|
|
* @param array $match |
|
2219
|
|
|
* |
|
2220
|
|
|
* @return string |
|
2221
|
|
|
*/ |
|
2222
|
|
|
private function _js_link_removal_callback($match) |
|
2223
|
|
|
{ |
|
2224
|
|
|
return $this->_js_removal_calback($match, 'href'); |
|
2225
|
|
|
} |
|
2226
|
|
|
|
|
2227
|
|
|
/** |
|
2228
|
|
|
* Callback method for xss_clean() to sanitize tags. |
|
2229
|
|
|
* |
|
2230
|
|
|
* <p> |
|
2231
|
|
|
* <br /> |
|
2232
|
|
|
* INFO: This limits the PCRE backtracks, making it more performance friendly |
|
2233
|
|
|
* and prevents PREG_BACKTRACK_LIMIT_ERROR from being triggered in |
|
2234
|
|
|
* PHP 5.2+ on image tag heavy strings. |
|
2235
|
|
|
* </p> |
|
2236
|
|
|
* |
|
2237
|
|
|
* @param array $match |
|
2238
|
|
|
* @param string $search |
|
2239
|
|
|
* |
|
2240
|
|
|
* @return string |
|
2241
|
|
|
*/ |
|
2242
|
|
|
private function _js_removal_calback($match, $search) |
|
2243
|
|
|
{ |
|
2244
|
|
|
if (!$match[0]) { |
|
2245
|
|
|
return ''; |
|
2246
|
|
|
} |
|
2247
|
|
|
|
|
2248
|
|
|
// init |
|
2249
|
|
|
$replacer = $this->_filter_attributes(str_replace(array('<', '>',), '', $match[1])); |
|
2250
|
|
|
$pattern = '#' . $search . '=.*(?:\(.+([^\)]*?)(?:\)|$)|javascript:|view-source:|livescript:|wscript:|vbscript:|mocha:|charset=|window\.|document\.|\.cookie|<script|d\s*a\s*t\s*a\s*:)#is'; |
|
2251
|
|
|
|
|
2252
|
|
|
$matchInner = array(); |
|
2253
|
|
|
preg_match($pattern, $match[1], $matchInner); |
|
2254
|
|
|
if (count($matchInner) > 0) { |
|
2255
|
|
|
$replacer = (string)preg_replace( |
|
2256
|
|
|
$pattern, |
|
2257
|
|
|
$search . '="' . $this->_replacement . '"', |
|
2258
|
|
|
$replacer |
|
2259
|
|
|
); |
|
2260
|
|
|
} |
|
2261
|
|
|
|
|
2262
|
|
|
return str_ireplace($match[1], $replacer, $match[0]); |
|
2263
|
|
|
} |
|
2264
|
|
|
|
|
2265
|
|
|
/** |
|
2266
|
|
|
* Callback method for xss_clean() to sanitize image tags. |
|
2267
|
|
|
* |
|
2268
|
|
|
* <p> |
|
2269
|
|
|
* <br /> |
|
2270
|
|
|
* INFO: This limits the PCRE backtracks, making it more performance friendly |
|
2271
|
|
|
* and prevents PREG_BACKTRACK_LIMIT_ERROR from being triggered in |
|
2272
|
|
|
* PHP 5.2+ on image tag heavy strings. |
|
2273
|
|
|
* </p> |
|
2274
|
|
|
* |
|
2275
|
|
|
* @param array $match |
|
2276
|
|
|
* |
|
2277
|
|
|
* @return string |
|
2278
|
|
|
*/ |
|
2279
|
|
|
private function _js_src_removal_callback($match) |
|
2280
|
|
|
{ |
|
2281
|
|
|
return $this->_js_removal_calback($match, 'src'); |
|
2282
|
|
|
} |
|
2283
|
|
|
|
|
2284
|
|
|
/** |
|
2285
|
|
|
* Sanitize naughty HTML. |
|
2286
|
|
|
* |
|
2287
|
|
|
* <p> |
|
2288
|
|
|
* <br /> |
|
2289
|
|
|
* Callback method for AntiXSS->sanitize_naughty_html() to remove naughty HTML elements. |
|
2290
|
|
|
* </p> |
|
2291
|
|
|
* |
|
2292
|
|
|
* @param array $matches |
|
2293
|
|
|
* |
|
2294
|
|
|
* @return string |
|
2295
|
|
|
*/ |
|
2296
|
|
|
private function _sanitize_naughty_html_callback($matches) |
|
2297
|
|
|
{ |
|
2298
|
|
|
return '<' . $matches[1] . $matches[2] . $matches[3] // encode opening brace |
|
2299
|
|
|
// encode captured opening or closing brace to prevent recursive vectors: |
|
2300
|
|
|
. str_replace( |
|
2301
|
|
|
array( |
|
2302
|
|
|
'>', |
|
2303
|
|
|
'<', |
|
2304
|
|
|
), |
|
2305
|
|
|
array( |
|
2306
|
|
|
'>', |
|
2307
|
|
|
'<', |
|
2308
|
|
|
), |
|
2309
|
|
|
$matches[4] |
|
2310
|
|
|
); |
|
2311
|
|
|
} |
|
2312
|
|
|
|
|
2313
|
|
|
/** |
|
2314
|
|
|
* Add some strings to the "_evil_attributes"-array. |
|
2315
|
|
|
* |
|
2316
|
|
|
* @param array $strings |
|
2317
|
|
|
* |
|
2318
|
|
|
* @return $this |
|
2319
|
|
|
*/ |
|
2320
|
|
|
public function addEvilAttributes(array $strings) |
|
2321
|
|
|
{ |
|
2322
|
|
|
$this->_evil_attributes = array_merge($strings, $this->_evil_attributes); |
|
2323
|
|
|
|
|
2324
|
|
|
return $this; |
|
2325
|
|
|
} |
|
2326
|
|
|
|
|
2327
|
|
|
/** |
|
2328
|
|
|
* Compact any exploded words. |
|
2329
|
|
|
* |
|
2330
|
|
|
* <p> |
|
2331
|
|
|
* <br /> |
|
2332
|
|
|
* INFO: This corrects words like: j a v a s c r i p t |
|
2333
|
|
|
* <br /> |
|
2334
|
|
|
* These words are compacted back to their correct state. |
|
2335
|
|
|
* </p> |
|
2336
|
|
|
* |
|
2337
|
|
|
* @param string $str |
|
2338
|
|
|
* |
|
2339
|
|
|
* @return string |
|
2340
|
|
|
*/ |
|
2341
|
|
|
private function _compact_exploded_javascript($str) |
|
2342
|
|
|
{ |
|
2343
|
|
|
static $WORDS_CACHE; |
|
2344
|
|
|
|
|
2345
|
|
|
$words = array( |
|
2346
|
|
|
'javascript', |
|
2347
|
|
|
'expression', |
|
2348
|
|
|
'view-source', |
|
2349
|
|
|
'vbscript', |
|
2350
|
|
|
'jscript', |
|
2351
|
|
|
'wscript', |
|
2352
|
|
|
'vbs', |
|
2353
|
|
|
'script', |
|
2354
|
|
|
'base64', |
|
2355
|
|
|
'applet', |
|
2356
|
|
|
'alert', |
|
2357
|
|
|
'document', |
|
2358
|
|
|
'write', |
|
2359
|
|
|
'cookie', |
|
2360
|
|
|
'window', |
|
2361
|
|
|
'confirm', |
|
2362
|
|
|
'prompt', |
|
2363
|
|
|
'eval', |
|
2364
|
|
|
); |
|
2365
|
|
|
|
|
2366
|
|
|
foreach ($words as $word) { |
|
2367
|
|
|
|
|
2368
|
|
|
if (!isset($WORDS_CACHE[$word])) { |
|
2369
|
|
|
$regex = '(?:\s|\+|"|\042|\'|\047)*'; |
|
2370
|
|
|
$word = $WORDS_CACHE[$word] = substr( |
|
2371
|
|
|
chunk_split($word, 1, $regex), |
|
2372
|
|
|
0, |
|
2373
|
|
|
-strlen($regex) |
|
2374
|
|
|
); |
|
2375
|
|
|
} else { |
|
2376
|
|
|
$word = $WORDS_CACHE[$word]; |
|
2377
|
|
|
} |
|
2378
|
|
|
|
|
2379
|
|
|
// We only want to do this when it is followed by a non-word character |
|
2380
|
|
|
// That way valid stuff like "dealer to" does not become "dealerto". |
|
2381
|
|
|
$str = preg_replace_callback( |
|
2382
|
|
|
'#(' . $word . ')(\W)#is', |
|
2383
|
|
|
array( |
|
2384
|
|
|
$this, |
|
2385
|
|
|
'_compact_exploded_words_callback', |
|
2386
|
|
|
), |
|
2387
|
|
|
$str |
|
2388
|
|
|
); |
|
2389
|
|
|
} |
|
2390
|
|
|
|
|
2391
|
|
|
return (string)$str; |
|
2392
|
|
|
} |
|
2393
|
|
|
|
|
2394
|
|
|
/** |
|
2395
|
|
|
* Decode the html-tags via "UTF8::html_entity_decode()" or the string via "UTF8::rawurldecode()". |
|
2396
|
|
|
* |
|
2397
|
|
|
* @param string $str |
|
2398
|
|
|
* |
|
2399
|
|
|
* @return string |
|
2400
|
|
|
*/ |
|
2401
|
|
|
private function _decode_string($str) |
|
2402
|
|
|
{ |
|
2403
|
|
|
// init |
|
2404
|
|
|
$regExForHtmlTags = '/<\w+.*+/si'; |
|
2405
|
|
|
|
|
2406
|
|
|
if (preg_match($regExForHtmlTags, $str, $matches) === 1) { |
|
2407
|
|
|
$str = preg_replace_callback( |
|
2408
|
|
|
$regExForHtmlTags, |
|
2409
|
|
|
array( |
|
2410
|
|
|
$this, |
|
2411
|
|
|
'_decode_entity', |
|
2412
|
|
|
), |
|
2413
|
|
|
$str |
|
2414
|
|
|
); |
|
2415
|
|
|
} else { |
|
2416
|
|
|
$str = UTF8::rawurldecode($str); |
|
2417
|
|
|
} |
|
2418
|
|
|
|
|
2419
|
|
|
return $str; |
|
2420
|
|
|
} |
|
2421
|
|
|
|
|
2422
|
|
|
/** |
|
2423
|
|
|
* Check if the "AntiXSS->xss_clean()"-method found an XSS attack in the last run. |
|
2424
|
|
|
* |
|
2425
|
|
|
* @return bool|null <p>Will return null if the "xss_clean()" wan't running at all.</p> |
|
2426
|
|
|
*/ |
|
2427
|
|
|
public function isXssFound() |
|
2428
|
|
|
{ |
|
2429
|
|
|
return $this->xss_found; |
|
2430
|
|
|
} |
|
2431
|
|
|
|
|
2432
|
|
|
/** |
|
2433
|
|
|
* Remove some strings from the "_evil_attributes"-array. |
|
2434
|
|
|
* |
|
2435
|
|
|
* <p> |
|
2436
|
|
|
* <br /> |
|
2437
|
|
|
* WARNING: Use this method only if you have a really good reason. |
|
2438
|
|
|
* </p> |
|
2439
|
|
|
* |
|
2440
|
|
|
* @param array $strings |
|
2441
|
|
|
* |
|
2442
|
|
|
* @return $this |
|
2443
|
|
|
*/ |
|
2444
|
|
|
public function removeEvilAttributes(array $strings) |
|
2445
|
|
|
{ |
|
2446
|
|
|
$this->_evil_attributes = array_diff( |
|
2447
|
|
|
array_intersect($strings, $this->_evil_attributes), |
|
2448
|
|
|
$this->_evil_attributes |
|
2449
|
|
|
); |
|
2450
|
|
|
|
|
2451
|
|
|
return $this; |
|
2452
|
|
|
} |
|
2453
|
|
|
|
|
2454
|
|
|
/** |
|
2455
|
|
|
* Remove disallowed Javascript in links or img tags |
|
2456
|
|
|
* |
|
2457
|
|
|
* <p> |
|
2458
|
|
|
* <br /> |
|
2459
|
|
|
* We used to do some version comparisons and use of stripos(), |
|
2460
|
|
|
* but it is dog slow compared to these simplified non-capturing |
|
2461
|
|
|
* preg_match(), especially if the pattern exists in the string |
|
2462
|
|
|
* </p> |
|
2463
|
|
|
* |
|
2464
|
|
|
* <p> |
|
2465
|
|
|
* <br /> |
|
2466
|
|
|
* Note: It was reported that not only space characters, but all in |
|
2467
|
|
|
* the following pattern can be parsed as separators between a tag name |
|
2468
|
|
|
* and its attributes: [\d\s"\'`;,\/\=\(\x00\x0B\x09\x0C] |
|
2469
|
|
|
* ... however, UTF8::clean() above already strips the |
|
2470
|
|
|
* hex-encoded ones, so we'll skip them below. |
|
2471
|
|
|
* </p> |
|
2472
|
|
|
* |
|
2473
|
|
|
* @param string $str |
|
2474
|
|
|
* |
|
2475
|
|
|
* @return string |
|
2476
|
|
|
*/ |
|
2477
|
|
|
private function _remove_disallowed_javascript($str) |
|
2478
|
|
|
{ |
|
2479
|
|
|
do { |
|
2480
|
|
|
$original = $str; |
|
2481
|
|
|
|
|
2482
|
|
|
if (stripos($str, '<a') !== false) { |
|
2483
|
|
|
$str = preg_replace_callback( |
|
2484
|
|
|
'#<a[^a-z0-9>]+([^>]*?)(?:>|$)#i', |
|
2485
|
|
|
array( |
|
2486
|
|
|
$this, |
|
2487
|
|
|
'_js_link_removal_callback', |
|
2488
|
|
|
), |
|
2489
|
|
|
$str |
|
2490
|
|
|
); |
|
2491
|
|
|
} |
|
2492
|
|
|
|
|
2493
|
|
View Code Duplication |
if (stripos($str, '<img') !== false) { |
|
2494
|
|
|
$str = preg_replace_callback( |
|
2495
|
|
|
'#<img[^a-z0-9]+([^>]*?)(?:\s?/?>|$)#i', |
|
2496
|
|
|
array( |
|
2497
|
|
|
$this, |
|
2498
|
|
|
'_js_src_removal_callback', |
|
2499
|
|
|
), |
|
2500
|
|
|
$str |
|
2501
|
|
|
); |
|
2502
|
|
|
} |
|
2503
|
|
|
|
|
2504
|
|
View Code Duplication |
if (stripos($str, '<audio') !== false) { |
|
2505
|
|
|
$str = preg_replace_callback( |
|
2506
|
|
|
'#<audio[^a-z0-9]+([^>]*?)(?:\s?/?>|$)#i', |
|
2507
|
|
|
array( |
|
2508
|
|
|
$this, |
|
2509
|
|
|
'_js_src_removal_callback', |
|
2510
|
|
|
), |
|
2511
|
|
|
$str |
|
2512
|
|
|
); |
|
2513
|
|
|
} |
|
2514
|
|
|
|
|
2515
|
|
View Code Duplication |
if (stripos($str, '<video') !== false) { |
|
2516
|
|
|
$str = preg_replace_callback( |
|
2517
|
|
|
'#<video[^a-z0-9]+([^>]*?)(?:\s?/?>|$)#i', |
|
2518
|
|
|
array( |
|
2519
|
|
|
$this, |
|
2520
|
|
|
'_js_src_removal_callback', |
|
2521
|
|
|
), |
|
2522
|
|
|
$str |
|
2523
|
|
|
); |
|
2524
|
|
|
} |
|
2525
|
|
|
|
|
2526
|
|
View Code Duplication |
if (stripos($str, '<source') !== false) { |
|
2527
|
|
|
$str = preg_replace_callback( |
|
2528
|
|
|
'#<source[^a-z0-9]+([^>]*?)(?:\s?/?>|$)#i', |
|
2529
|
|
|
array( |
|
2530
|
|
|
$this, |
|
2531
|
|
|
'_js_src_removal_callback', |
|
2532
|
|
|
), |
|
2533
|
|
|
$str |
|
2534
|
|
|
); |
|
2535
|
|
|
} |
|
2536
|
|
|
|
|
2537
|
|
|
if (stripos($str, 'script') !== false) { |
|
2538
|
|
|
// US-ASCII: ¼ === < |
|
2539
|
|
|
$str = preg_replace('#(?:¼|<)/*(?:script).*(?:¾|>)#isuU', $this->_replacement, $str); |
|
2540
|
|
|
} |
|
2541
|
|
|
} while ($original !== $str); |
|
2542
|
|
|
|
|
2543
|
|
|
return (string)$str; |
|
2544
|
|
|
} |
|
2545
|
|
|
|
|
2546
|
|
|
/** |
|
2547
|
|
|
* Remove Evil HTML Attributes (like event handlers and style). |
|
2548
|
|
|
* |
|
2549
|
|
|
* It removes the evil attribute and either: |
|
2550
|
|
|
* |
|
2551
|
|
|
* - Everything up until a space. For example, everything between the pipes: |
|
2552
|
|
|
* |
|
2553
|
|
|
* <code> |
|
2554
|
|
|
* <a |style=document.write('hello');alert('world');| class=link> |
|
2555
|
|
|
* </code> |
|
2556
|
|
|
* |
|
2557
|
|
|
* - Everything inside the quotes. For example, everything between the pipes: |
|
2558
|
|
|
* |
|
2559
|
|
|
* <code> |
|
2560
|
|
|
* <a |style="document.write('hello'); alert('world');"| class="link"> |
|
2561
|
|
|
* </code> |
|
2562
|
|
|
* |
|
2563
|
|
|
* @param string $str <p>The string to check.</p> |
|
2564
|
|
|
* |
|
2565
|
|
|
* @return string <p>The string with the evil attributes removed.</p> |
|
2566
|
|
|
*/ |
|
2567
|
|
|
private function _remove_evil_attributes($str) |
|
2568
|
|
|
{ |
|
2569
|
|
|
$evil_attributes_string = implode('|', $this->_evil_attributes); |
|
2570
|
|
|
|
|
2571
|
|
|
// replace style-attribute, first (if needed) |
|
2572
|
|
|
if (in_array('style', $this->_evil_attributes, true)) { |
|
2573
|
|
View Code Duplication |
do { |
|
2574
|
|
|
$count = $temp_count = 0; |
|
2575
|
|
|
|
|
2576
|
|
|
$str = preg_replace('/(<[^>]+)(?<!\w)(style="(:?[^"]*?)"|style=\'(:?[^\']*?)\')/i', '$1' . $this->_replacement, $str, -1, $temp_count); |
|
2577
|
|
|
$count += $temp_count; |
|
2578
|
|
|
|
|
2579
|
|
|
} while ($count); |
|
2580
|
|
|
} |
|
2581
|
|
|
|
|
2582
|
|
View Code Duplication |
do { |
|
2583
|
|
|
$count = $temp_count = 0; |
|
2584
|
|
|
|
|
2585
|
|
|
// find occurrences of illegal attribute strings with and without quotes (042 ["] and 047 ['] are octal quotes) |
|
2586
|
|
|
$str = preg_replace('/(<[^>]+)(?<!\w)(' . $evil_attributes_string . ')\s*=\s*(?:(?:"|\042|\'|\047)(?:[^\\2]*?)(?:\\2)|[^\s>]*)/is', '$1' . $this->_replacement, $str, -1, $temp_count); |
|
2587
|
|
|
$count += $temp_count; |
|
2588
|
|
|
|
|
2589
|
|
|
} while ($count); |
|
2590
|
|
|
|
|
2591
|
|
|
return (string)$str; |
|
2592
|
|
|
} |
|
2593
|
|
|
|
|
2594
|
|
|
/** |
|
2595
|
|
|
* UTF-7 decoding function. |
|
2596
|
|
|
* |
|
2597
|
|
|
* @param string $str <p>HTML document for recode ASCII part of UTF-7 back to ASCII.</p> |
|
2598
|
|
|
* |
|
2599
|
|
|
* @return string |
|
2600
|
|
|
*/ |
|
2601
|
|
|
private function _repack_utf7($str) |
|
2602
|
|
|
{ |
|
2603
|
|
|
return preg_replace_callback( |
|
2604
|
|
|
'#\+([0-9a-zA-Z/]+)\-#', |
|
2605
|
|
|
array($this, '_repack_utf7_callback'), |
|
2606
|
|
|
$str |
|
2607
|
|
|
); |
|
2608
|
|
|
} |
|
2609
|
|
|
|
|
2610
|
|
|
/** |
|
2611
|
|
|
* Additional UTF-7 decoding function. |
|
2612
|
|
|
* |
|
2613
|
|
|
* @param string $str <p>String for recode ASCII part of UTF-7 back to ASCII.</p> |
|
2614
|
|
|
* |
|
2615
|
|
|
* @return string |
|
2616
|
|
|
*/ |
|
2617
|
|
|
private function _repack_utf7_callback($str) |
|
2618
|
|
|
{ |
|
2619
|
|
|
$strTmp = base64_decode($str[1]); |
|
2620
|
|
|
|
|
2621
|
|
|
if ($strTmp === false) { |
|
2622
|
|
|
return $str; |
|
2623
|
|
|
} |
|
2624
|
|
|
|
|
2625
|
|
|
$str = preg_replace_callback( |
|
2626
|
|
|
'/^((?:\x00.)*?)((?:[^\x00].)+)/us', |
|
2627
|
|
|
array($this, '_repack_utf7_callback_back'), |
|
2628
|
|
|
$strTmp |
|
2629
|
|
|
); |
|
2630
|
|
|
|
|
2631
|
|
|
return preg_replace('/\x00(.)/us', '$1', $str); |
|
2632
|
|
|
} |
|
2633
|
|
|
|
|
2634
|
|
|
/** |
|
2635
|
|
|
* Additional UTF-7 encoding function. |
|
2636
|
|
|
* |
|
2637
|
|
|
* @param string $str <p>String for recode ASCII part of UTF-7 back to ASCII.</p> |
|
2638
|
|
|
* |
|
2639
|
|
|
* @return string |
|
2640
|
|
|
*/ |
|
2641
|
|
|
private function _repack_utf7_callback_back($str) |
|
2642
|
|
|
{ |
|
2643
|
|
|
return $str[1] . '+' . rtrim(base64_encode($str[2]), '=') . '-'; |
|
2644
|
|
|
} |
|
2645
|
|
|
|
|
2646
|
|
|
/** |
|
2647
|
|
|
* Sanitize naughty HTML elements. |
|
2648
|
|
|
* |
|
2649
|
|
|
* <p> |
|
2650
|
|
|
* <br /> |
|
2651
|
|
|
* |
|
2652
|
|
|
* If a tag containing any of the words in the list |
|
2653
|
|
|
* below is found, the tag gets converted to entities. |
|
2654
|
|
|
* |
|
2655
|
|
|
* <br /><br /> |
|
2656
|
|
|
* |
|
2657
|
|
|
* So this: <blink> |
|
2658
|
|
|
* <br /> |
|
2659
|
|
|
* Becomes: <blink> |
|
2660
|
|
|
* </p> |
|
2661
|
|
|
* |
|
2662
|
|
|
* @param string $str |
|
2663
|
|
|
* |
|
2664
|
|
|
* @return string |
|
2665
|
|
|
*/ |
|
2666
|
|
|
private function _sanitize_naughty_html($str) |
|
2667
|
|
|
{ |
|
2668
|
|
|
$naughty = 'alert|prompt|confirm|applet|audio|basefont|base|behavior|bgsound|blink|body|embed|expression|form|frameset|frame|head|html|ilayer|iframe|input|button|select|isindex|layer|link|meta|keygen|object|plaintext|style|script|textarea|title|math|video|source|svg|xml|xss|eval'; |
|
2669
|
|
|
$str = preg_replace_callback( |
|
2670
|
|
|
'#<(/*\s*)(' . $naughty . ')([^><]*)([><]*)#i', |
|
2671
|
|
|
array( |
|
2672
|
|
|
$this, |
|
2673
|
|
|
'_sanitize_naughty_html_callback', |
|
2674
|
|
|
), |
|
2675
|
|
|
$str |
|
2676
|
|
|
); |
|
2677
|
|
|
|
|
2678
|
|
|
return (string)$str; |
|
2679
|
|
|
} |
|
2680
|
|
|
|
|
2681
|
|
|
/** |
|
2682
|
|
|
* Sanitize naughty scripting elements |
|
2683
|
|
|
* |
|
2684
|
|
|
* <p> |
|
2685
|
|
|
* <br /> |
|
2686
|
|
|
* |
|
2687
|
|
|
* Similar to above, only instead of looking for |
|
2688
|
|
|
* tags it looks for PHP and JavaScript commands |
|
2689
|
|
|
* that are disallowed. Rather than removing the |
|
2690
|
|
|
* code, it simply converts the parenthesis to entities |
|
2691
|
|
|
* rendering the code un-executable. |
|
2692
|
|
|
* |
|
2693
|
|
|
* <br /><br /> |
|
2694
|
|
|
* |
|
2695
|
|
|
* For example: <pre>eval('some code')</pre> |
|
2696
|
|
|
* <br /> |
|
2697
|
|
|
* Becomes: <pre>eval('some code')</pre> |
|
2698
|
|
|
* </p> |
|
2699
|
|
|
* |
|
2700
|
|
|
* @param string $str |
|
2701
|
|
|
* |
|
2702
|
|
|
* @return string |
|
2703
|
|
|
*/ |
|
2704
|
|
|
private function _sanitize_naughty_javascript($str) |
|
2705
|
|
|
{ |
|
2706
|
|
|
$str = preg_replace( |
|
2707
|
|
|
'#(alert|eval|prompt|confirm|cmd|passthru|eval|exec|expression|system|fopen|fsockopen|file|file_get_contents|readfile|unlink)(\s*)\((.*)\)#siU', |
|
2708
|
|
|
'\\1\\2(\\3)', |
|
2709
|
|
|
$str |
|
2710
|
|
|
); |
|
2711
|
|
|
|
|
2712
|
|
|
return (string)$str; |
|
2713
|
|
|
} |
|
2714
|
|
|
|
|
2715
|
|
|
/** |
|
2716
|
|
|
* Set the replacement-string for not allowed strings. |
|
2717
|
|
|
* |
|
2718
|
|
|
* @param string $string |
|
2719
|
|
|
* |
|
2720
|
|
|
* @return $this |
|
2721
|
|
|
*/ |
|
2722
|
|
|
public function setReplacement($string) |
|
2723
|
|
|
{ |
|
2724
|
|
|
$this->_replacement = (string)$string; |
|
2725
|
|
|
|
|
2726
|
|
|
$this->_initNeverAllowedStr(); |
|
2727
|
|
|
|
|
2728
|
|
|
return $this; |
|
2729
|
|
|
} |
|
2730
|
|
|
|
|
2731
|
|
|
/** |
|
2732
|
|
|
* Set the option to stripe 4-Byte chars. |
|
2733
|
|
|
* |
|
2734
|
|
|
* <p> |
|
2735
|
|
|
* <br /> |
|
2736
|
|
|
* INFO: use it if your DB (MySQL) can't use "utf8mb4" -> preventing stored XSS-attacks |
|
2737
|
|
|
* </p> |
|
2738
|
|
|
* |
|
2739
|
|
|
* @param $bool |
|
2740
|
|
|
* |
|
2741
|
|
|
* @return $this |
|
2742
|
|
|
*/ |
|
2743
|
|
|
public function setStripe4byteChars($bool) |
|
2744
|
|
|
{ |
|
2745
|
|
|
$this->_stripe_4byte_chars = (bool)$bool; |
|
2746
|
|
|
|
|
2747
|
|
|
return $this; |
|
2748
|
|
|
} |
|
2749
|
|
|
|
|
2750
|
|
|
/** |
|
2751
|
|
|
* XSS Clean |
|
2752
|
|
|
* |
|
2753
|
|
|
* <p> |
|
2754
|
|
|
* <br /> |
|
2755
|
|
|
* Sanitizes data so that "Cross Site Scripting" hacks can be |
|
2756
|
|
|
* prevented. This method does a fair amount of work but |
|
2757
|
|
|
* it is extremely thorough, designed to prevent even the |
|
2758
|
|
|
* most obscure XSS attempts. But keep in mind that nothing |
|
2759
|
|
|
* is ever 100% foolproof... |
|
2760
|
|
|
* </p> |
|
2761
|
|
|
* |
|
2762
|
|
|
* <p> |
|
2763
|
|
|
* <br /> |
|
2764
|
|
|
* <strong>Note:</strong> Should only be used to deal with data upon submission. |
|
2765
|
|
|
* It's not something that should be used for general |
|
2766
|
|
|
* runtime processing. |
|
2767
|
|
|
* </p> |
|
2768
|
|
|
* |
|
2769
|
|
|
* @link http://channel.bitflux.ch/wiki/XSS_Prevention |
|
2770
|
|
|
* Based in part on some code and ideas from Bitflux. |
|
2771
|
|
|
* |
|
2772
|
|
|
* @link http://ha.ckers.org/xss.html |
|
2773
|
|
|
* To help develop this script I used this great list of |
|
2774
|
|
|
* vulnerabilities along with a few other hacks I've |
|
2775
|
|
|
* harvested from examining vulnerabilities in other programs. |
|
2776
|
|
|
* |
|
2777
|
|
|
* @param string|array $str <p>input data e.g. string or array</p> |
|
2778
|
|
|
* |
|
2779
|
|
|
* @return string|array|boolean <p> |
|
2780
|
|
|
* boolean: will return a boolean, if the "is_image"-parameter is true<br /> |
|
2781
|
|
|
* string: will return a string, if the input is a string<br /> |
|
2782
|
|
|
* array: will return a array, if the input is a array<br /> |
|
2783
|
|
|
* </p> |
|
2784
|
|
|
*/ |
|
2785
|
|
|
public function xss_clean($str) |
|
2786
|
|
|
{ |
|
2787
|
|
|
// reset |
|
2788
|
|
|
$this->xss_found = null; |
|
2789
|
|
|
|
|
2790
|
|
|
// check for an array of strings |
|
2791
|
|
|
if (is_array($str) === true) { |
|
2792
|
|
|
foreach ($str as $key => &$value) { |
|
2793
|
|
|
$str[$key] = $this->xss_clean($value); |
|
2794
|
|
|
} |
|
2795
|
|
|
|
|
2796
|
|
|
return $str; |
|
2797
|
|
|
} |
|
2798
|
|
|
|
|
2799
|
|
|
// process |
|
2800
|
|
|
do { |
|
2801
|
|
|
$old_str = $str; |
|
2802
|
|
|
$str = $this->_do($str); |
|
2803
|
|
|
} while ($old_str !== $str); |
|
2804
|
|
|
|
|
2805
|
|
|
return $str; |
|
2806
|
|
|
} |
|
2807
|
|
|
|
|
2808
|
|
|
/** |
|
2809
|
|
|
* Generates the XSS hash if needed and returns it. |
|
2810
|
|
|
* |
|
2811
|
|
|
* @return string <p>XSS hash</p> |
|
2812
|
|
|
*/ |
|
2813
|
|
|
private function _xss_hash() |
|
2814
|
|
|
{ |
|
2815
|
|
|
if ($this->_xss_hash === null) { |
|
2816
|
|
|
$rand = Bootup::get_random_bytes(16); |
|
2817
|
|
|
|
|
2818
|
|
|
if (!$rand) { |
|
2819
|
|
|
$this->_xss_hash = md5(uniqid(mt_rand(), true)); |
|
2820
|
|
|
} else { |
|
2821
|
|
|
$this->_xss_hash = bin2hex($rand); |
|
2822
|
|
|
} |
|
2823
|
|
|
} |
|
2824
|
|
|
|
|
2825
|
|
|
return 'voku::anti-xss::' . $this->_xss_hash; |
|
2826
|
|
|
} |
|
2827
|
|
|
|
|
2828
|
|
|
} |