@@ -16,7 +16,7 @@ class EscaperTest extends \PHPUnit_Framework_TestCase
16
16
/**
17
17
* @var \Magento\Framework\Escaper
18
18
*/
19
- protected $ _escaper = null ;
19
+ protected $ escaper = null ;
20
20
21
21
/**
22
22
* @var \Magento\Framework\ZendEscaper
@@ -30,12 +30,108 @@ class EscaperTest extends \PHPUnit_Framework_TestCase
30
30
31
31
protected function setUp ()
32
32
{
33
- $ this ->_escaper = new Escaper ();
33
+ $ this ->escaper = new Escaper ();
34
34
$ this ->zendEscaper = new \Magento \Framework \ZendEscaper ();
35
35
$ this ->loggerMock = $ this ->getMockForAbstractClass (\Psr \Log \LoggerInterface::class);
36
36
$ objectManagerHelper = new ObjectManager ($ this );
37
- $ objectManagerHelper ->setBackwardCompatibleProperty ($ this ->_escaper , 'escaper ' , $ this ->zendEscaper );
38
- $ objectManagerHelper ->setBackwardCompatibleProperty ($ this ->_escaper , 'logger ' , $ this ->loggerMock );
37
+ $ objectManagerHelper ->setBackwardCompatibleProperty ($ this ->escaper , 'escaper ' , $ this ->zendEscaper );
38
+ $ objectManagerHelper ->setBackwardCompatibleProperty ($ this ->escaper , 'logger ' , $ this ->loggerMock );
39
+ }
40
+
41
+ /**
42
+ * Convert a Unicode Codepoint to a literal UTF-8 character.
43
+ *
44
+ * @param int $codepoint Unicode codepoint in hex notation
45
+ * @return string UTF-8 literal string
46
+ */
47
+ protected function codepointToUtf8 ($ codepoint )
48
+ {
49
+ if ($ codepoint < 0x80 ) {
50
+ return chr ($ codepoint );
51
+ }
52
+ if ($ codepoint < 0x800 ) {
53
+ return chr ($ codepoint >> 6 & 0x3f | 0xc0 )
54
+ . chr ($ codepoint & 0x3f | 0x80 );
55
+ }
56
+ if ($ codepoint < 0x10000 ) {
57
+ return chr ($ codepoint >> 12 & 0x0f | 0xe0 )
58
+ . chr ($ codepoint >> 6 & 0x3f | 0x80 )
59
+ . chr ($ codepoint & 0x3f | 0x80 );
60
+ }
61
+ if ($ codepoint < 0x110000 ) {
62
+ return chr ($ codepoint >> 18 & 0x07 | 0xf0 )
63
+ . chr ($ codepoint >> 12 & 0x3f | 0x80 )
64
+ . chr ($ codepoint >> 6 & 0x3f | 0x80 )
65
+ . chr ($ codepoint & 0x3f | 0x80 );
66
+ }
67
+ throw new \Exception ('Codepoint requested outside of Unicode range ' );
68
+ }
69
+
70
+ public function testEscapeJsEscapesOwaspRecommendedRanges ()
71
+ {
72
+ $ immune = [', ' , '. ' , '_ ' ]; // Exceptions to escaping ranges
73
+ for ($ chr =0 ; $ chr < 0xFF ; $ chr ++) {
74
+ if ($ chr >= 0x30 && $ chr <= 0x39
75
+ || $ chr >= 0x41 && $ chr <= 0x5A
76
+ || $ chr >= 0x61 && $ chr <= 0x7A
77
+ ) {
78
+ $ literal = $ this ->codepointToUtf8 ($ chr );
79
+ $ this ->assertEquals ($ literal , $ this ->escaper ->escapeJs ($ literal ));
80
+ } else {
81
+ $ literal = $ this ->codepointToUtf8 ($ chr );
82
+ if (in_array ($ literal , $ immune )) {
83
+ $ this ->assertEquals ($ literal , $ this ->escaper ->escapeJs ($ literal ));
84
+ } else {
85
+ $ this ->assertNotEquals (
86
+ $ literal ,
87
+ $ this ->escaper ->escapeJs ($ literal ),
88
+ $ literal . ' should be escaped! '
89
+ );
90
+ }
91
+ }
92
+ }
93
+ }
94
+
95
+ /**
96
+ * @param string $data
97
+ * @param string $expected
98
+ * @dataProvider escapeJsDataProvider
99
+ */
100
+ public function testEscapeJs ($ data , $ expected )
101
+ {
102
+ $ this ->assertEquals ($ expected , $ this ->escaper ->escapeJs ($ data ));
103
+ }
104
+
105
+ public function escapeJsDataProvider ()
106
+ {
107
+ return [
108
+ 'zero length string ' => ['' , '' ],
109
+ 'only digits ' => ['123 ' , '123 ' ],
110
+ '< ' => ['< ' , '\u003C ' ],
111
+ '> ' => ['> ' , '\\u003E ' ],
112
+ '\'' => ['\'' , '\\u0027 ' ],
113
+ '" ' => ['" ' , '\\u0022 ' ],
114
+ '& ' => ['& ' , '\\u0026 ' ],
115
+ 'Characters beyond ASCII value 255 to unicode escape ' => ['Ā ' , '\\u0100 ' ],
116
+ 'Characters beyond Unicode BMP to unicode escape ' => ["\xF0\x90\x80\x80" , '\\uD800DC00 ' ],
117
+ /* Immune chars excluded */
118
+ ', ' => [', ' , ', ' ],
119
+ '. ' => ['. ' , '. ' ],
120
+ '_ ' => ['_ ' , '_ ' ],
121
+ /* Basic alnums exluded */
122
+ 'a ' => ['a ' , 'a ' ],
123
+ 'A ' => ['A ' , 'A ' ],
124
+ 'z ' => ['z ' , 'z ' ],
125
+ 'Z ' => ['Z ' , 'Z ' ],
126
+ '0 ' => ['0 ' , '0 ' ],
127
+ '9 ' => ['9 ' , '9 ' ],
128
+ /* Basic control characters and null */
129
+ "\r" => ["\r" , '\\u000D ' ],
130
+ "\n" => ["\n" , '\\u000A ' ],
131
+ "\t" => ["\t" , '\\u0009 ' ],
132
+ "\0" => ["\0" , '\\u0000 ' ],
133
+ 'Encode spaces for quoteless attribute protection ' => [' ' , '\\u0020 ' ],
134
+ ];
39
135
}
40
136
41
137
/**
@@ -44,7 +140,7 @@ protected function setUp()
44
140
*/
45
141
public function testEscapeHtml ($ data , $ expected , $ allowedTags = [])
46
142
{
47
- $ actual = $ this ->_escaper ->escapeHtml ($ data , $ allowedTags );
143
+ $ actual = $ this ->escaper ->escapeHtml ($ data , $ allowedTags );
48
144
$ this ->assertEquals ($ expected , $ actual );
49
145
}
50
146
@@ -56,7 +152,7 @@ public function testEscapeHtmlWithInvalidData($data, $expected, $allowedTags = [
56
152
{
57
153
$ this ->loggerMock ->expects ($ this ->once ())
58
154
->method ('critical ' );
59
- $ actual = $ this ->_escaper ->escapeHtml ($ data , $ allowedTags );
155
+ $ actual = $ this ->escaper ->escapeHtml ($ data , $ allowedTags );
60
156
$ this ->assertEquals ($ expected , $ actual );
61
157
}
62
158
@@ -160,8 +256,8 @@ public function testEscapeUrl()
160
256
{
161
257
$ data = 'http://example.com/search?term=this+%26+that&view=list ' ;
162
258
$ expected = 'http://example.com/search?term=this+%26+that&view=list ' ;
163
- $ this ->assertEquals ($ expected , $ this ->_escaper ->escapeUrl ($ data ));
164
- $ this ->assertEquals ($ expected , $ this ->_escaper ->escapeUrl ($ expected ));
259
+ $ this ->assertEquals ($ expected , $ this ->escaper ->escapeUrl ($ data ));
260
+ $ this ->assertEquals ($ expected , $ this ->escaper ->escapeUrl ($ expected ));
165
261
}
166
262
167
263
/**
@@ -171,8 +267,8 @@ public function testEscapeJsQuote()
171
267
{
172
268
$ data = ["Don't do that. " , 'lost_key ' => "Can't do that. " ];
173
269
$ expected = ["Don \\'t do that. " , "Can \\'t do that. " ];
174
- $ this ->assertEquals ($ expected , $ this ->_escaper ->escapeJsQuote ($ data ));
175
- $ this ->assertEquals ($ expected [0 ], $ this ->_escaper ->escapeJsQuote ($ data [0 ]));
270
+ $ this ->assertEquals ($ expected , $ this ->escaper ->escapeJsQuote ($ data ));
271
+ $ this ->assertEquals ($ expected [0 ], $ this ->escaper ->escapeJsQuote ($ data [0 ]));
176
272
}
177
273
178
274
/**
@@ -185,8 +281,8 @@ public function testEscapeQuote()
185
281
"Text with 'single' and "double" quotes " ,
186
282
"Text with \\'single \\' and \\"double \\" quotes " ,
187
283
];
188
- $ this ->assertEquals ($ expected [0 ], $ this ->_escaper ->escapeQuote ($ data ));
189
- $ this ->assertEquals ($ expected [1 ], $ this ->_escaper ->escapeQuote ($ data , true ));
284
+ $ this ->assertEquals ($ expected [0 ], $ this ->escaper ->escapeQuote ($ data ));
285
+ $ this ->assertEquals ($ expected [1 ], $ this ->escaper ->escapeQuote ($ data , true ));
190
286
}
191
287
192
288
/**
@@ -197,7 +293,7 @@ public function testEscapeQuote()
197
293
*/
198
294
public function testEscapeXssInUrl ($ input , $ expected )
199
295
{
200
- $ this ->assertEquals ($ expected , $ this ->_escaper ->escapeXssInUrl ($ input ));
296
+ $ this ->assertEquals ($ expected , $ this ->escaper ->escapeXssInUrl ($ input ));
201
297
}
202
298
203
299
/**
0 commit comments