forked from WordPress/wordpress-develop
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathwpHtmlDecoder.php
More file actions
171 lines (161 loc) · 5.59 KB
/
Copy pathwpHtmlDecoder.php
File metadata and controls
171 lines (161 loc) · 5.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
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
<?php
/**
* Unit tests covering WP_HTML_Decoder functionality.
*
* @package WordPress
* @subpackage HTML-API
*/
/**
* @group html-api
*
* @coversDefaultClass WP_HTML_Decoder
*/
class Tests_HtmlApi_WpHtmlDecoder extends WP_UnitTestCase {
/**
* Ensures proper decoding of edge cases.
*
* @ticket 61072
*
* @dataProvider data_edge_cases
*
* @param $raw_text_node Raw input text.
* @param $decoded_value The expected decoded text result.
*/
public function test_edge_cases( $raw_text_node, $decoded_value ) {
$this->assertSame(
$decoded_value,
WP_HTML_Decoder::decode_text_node( $raw_text_node ),
'Improperly decoded raw text node.'
);
}
public static function data_edge_cases() {
return array(
'Single ampersand' => array( '&', '&' ),
);
}
/**
* Ensures that character references followed by NULL bytes do not emit native PHP errors.
*
* @ticket 65372
*/
public function test_character_reference_with_null_byte_does_not_emit_native_errors() {
$errors = array();
set_error_handler(
static function ( int $errno, string $errstr ) use ( &$errors ) {
$errors[] = "{$errno}: {$errstr}";
return true;
}
);
try {
$decoded = WP_HTML_Decoder::decode_text_node( "&\x00b" );
} finally {
restore_error_handler();
}
// Use assertSame() instead of assertEmpty() so PHPUnit shows captured error messages on failure.
$this->assertSame( array(), $errors );
$this->assertSame( "&\x00b", $decoded, 'Should have decoded the text without changing it.' );
}
/**
* Ensures proper detection of attribute prefixes ignoring ASCII case.
*
* @ticket 61072
*
* @dataProvider data_case_variants_of_attribute_prefixes
*
* @param string $attribute_value Raw attribute value from HTML string.
* @param string $search_string Prefix contained in encoded attribute value.
*/
public function test_detects_ascii_case_insensitive_attribute_prefixes( $attribute_value, $search_string ) {
$this->assertTrue(
WP_HTML_Decoder::attribute_starts_with( $attribute_value, $search_string, 'ascii-case-insensitive' ),
"Should have found that '{$attribute_value}' starts with '{$search_string}'"
);
}
/**
* Data provider.
*
* @return Generator.
*/
public static function data_case_variants_of_attribute_prefixes() {
$with_javascript_prefix = array(
'javascript:',
'JAVASCRIPT:',
'javascript:',
'javascript:',
'javascript:',
'javascript:',
'javascript:alert(1)',
'JaVaScRiPt:alert(1)',
'javascript:alert(1);',
'javascript:alert(1);',
'javascript:alert(1);',
'javascript:alert(1);',
'javascript:alert(1);',
'javascript:alert(1);',
'javascript:alert(1);',
'javascript:alert(1);',
'javascript:alert(1);',
'javascript:alert('XSS')',
'javascript:javascript:alert(1);',
'javascript:javascript:alert(1);',
'javascript:javascript:alert(1);',
'javascript:javascript:alert(1);',
'javascript:javascript:alert(1);',
'javascript:alert(1)//?:',
'javascript:alert(1)',
'javascript:x=1;alert(1)',
);
foreach ( $with_javascript_prefix as $attribute_value ) {
yield $attribute_value => array( $attribute_value, 'javascript:' );
}
}
/**
* Ensures that `attribute_starts_with` respects the case sensitivity argument.
*
* @ticket 61072
*
* @dataProvider data_attributes_with_prefix_and_case_sensitive_match
*
* @param string $attribute_value Raw attribute value from HTML string.
* @param string $search_string Prefix contained or not contained in encoded attribute value.
* @param string $case_sensitivity Whether to search with ASCII case sensitivity;
* 'ascii-case-insensitive' or 'case-sensitive'.
* @param bool $is_match Whether the search string is a prefix for the attribute value,
* given the case sensitivity setting.
*/
public function test_attribute_starts_with_heeds_case_sensitivity( $attribute_value, $search_string, $case_sensitivity, $is_match ) {
if ( $is_match ) {
$this->assertTrue(
WP_HTML_Decoder::attribute_starts_with( $attribute_value, $search_string, $case_sensitivity ),
'Should have found attribute prefix with case-sensitive search.'
);
} else {
$this->assertFalse(
WP_HTML_Decoder::attribute_starts_with( $attribute_value, $search_string, $case_sensitivity ),
'Should not have matched attribute with prefix with ASCII-case-insensitive search.'
);
}
}
/**
* Data provider.
*
* @return array[].
*/
public static function data_attributes_with_prefix_and_case_sensitive_match() {
return array(
array( 'http://wordpress.org', 'http', 'case-sensitive', true ),
array( 'http://wordpress.org', 'http', 'ascii-case-insensitive', true ),
array( 'http://wordpress.org', 'HTTP', 'case-sensitive', false ),
array( 'http://wordpress.org', 'HTTP', 'ascii-case-insensitive', true ),
array( 'http://wordpress.org', 'Http', 'case-sensitive', false ),
array( 'http://wordpress.org', 'Http', 'ascii-case-insensitive', true ),
array( 'http://wordpress.org', 'https', 'case-sensitive', false ),
array( 'http://wordpress.org', 'https', 'ascii-case-insensitive', false ),
array( '', 'http', 'case-sensitive', false ),
array( 'jav', 'javascript:', 'case-sensitive', false ),
array( 'jav', 'javascript:', 'ascii-case-insensitive', false ),
array( '<⃒script', '<', 'case-sensitive', true ),
array( '>⃒script', '>', 'case-sensitive', true ),
);
}
}