From 4061516548b51c7cb74cdbdbd74b3bcc122787a5 Mon Sep 17 00:00:00 2001
From: Dennis Snell
456
789', - (string) $p - ); - } - - /** - * @ticket 56299 - * - * @covers next_tag - * @covers remove_attribute - * @covers __toString - */ - public function test_removing_attributes_works_even_in_malformed_html() { - $p = new WP_HTML_Tag_Processor( self::HTML_MALFORMED ); - $p->next_tag( 'span' ); - $p->remove_attribute( 'Notifications<' ); - $this->assertSame( - 'This <is> a <strong is="true">thing.
test',
- 'This <is> a <strong is="true">thing.
test',
- );
-
- $examples['HTML tag brackets in attribute values and data markup'] = array(
- 'This <is> a <strong is="true">thing.
test',
- 'This <is> a <strong is="true">thing.
test',
- );
-
- $examples['Single and double quotes in attribute value'] = array(
- 'test', - '
test', - ); - - $examples['Unquoted attribute values'] = array( - '
- *
- *
- *
- * @ticket 56299
- *
- * @dataProvider data_set_attribute_escapable_values
- * @covers set_attribute
- */
- public function test_set_attribute_prevents_xss( $value_to_set, $expected_result ) {
- $p = new WP_HTML_Tag_Processor( '' );
- $p->next_tag();
- $p->set_attribute( 'test', $value_to_set );
-
- /*
- * Testing the escaping is hard using tools that properly parse
- * HTML because they might interpret the escaped values. It's hard
- * with tools that don't understand HTML because they might get
- * confused by improperly-escaped values.
- *
- * For this test, since we control the input HTML we're going to
- * do what looks like the opposite of what we want to be doing with
- * this library but are only doing so because we have full control
- * over the content and because we want to look at the raw values.
- */
- $match = null;
- preg_match( '~^$~', $p->get_updated_html(), $match );
- list( , $actual_value ) = $match;
-
- $this->assertEquals( $actual_value, '"' . $expected_result . '"' );
- }
-
- /**
- * Data provider with HTML attribute values that might need escaping.
- */
- public function data_set_attribute_escapable_values() {
- return array(
- array( '"', '"' ),
- array( '"', '"' ),
- array( '&', '&' ),
- array( '&', '&' ),
- array( '€', '€' ),
- array( "'", ''' ),
- array( '<>', '<>' ),
- array( '"";', '"";' ),
- array(
- '" onclick="alert(\'1\');">',
- '" onclick="alert('1');"><span onclick=""></span><script>alert("1")</script>',
- ),
- );
- }
-
-}
From fecc1d2aa66c2fb2c6379fb47de5d7cd71f01f8c Mon Sep 17 00:00:00 2001
From: George Mamadashvili { __( 'Select or create a menu' ) }
- ) : ( -{ __( 'Select or create a menu' ) }
+ ) : ( +{ __( - 'To edit this navigation menu, convert it to single page links. This allows you to add, re-order, remove items, or edit their labels.' - ) } -
-- { __( - "Note: if you add new pages to your site, you'll need to add them to your navigation menu." + 'This menu is automatically kept in sync with pages on your site. You can manage the menu yourself by clicking customize below.' ) }
+ * $p = new WP_HTML_Tag_Processor( '' );
+ * $p->next_tag( [ 'tag_name' => 'div', 'tag_closers' => 'visit' ] );
+ * $p->is_tag_closer() === false;
+ *
+ * $p->next_tag( [ 'tag_name' => 'div', 'tag_closers' => 'visit' ] );
+ * $p->is_tag_closer() === true;
+ *
+ *
+ * @return bool
+ */
+ public function is_tag_closer() {
+ return $this->is_closing_tag;
+ }
+
/**
* Updates or creates a new attribute on the currently matched tag with the value passed.
*
@@ -1175,8 +1224,8 @@ public function get_tag() {
* @throws Exception When WP_DEBUG is true and the attribute name is invalid.
*/
public function set_attribute( $name, $value ) {
- if ( null === $this->tag_name_starts_at ) {
- return;
+ if ( $this->is_closing_tag || null === $this->tag_name_starts_at ) {
+ return false;
}
/*
@@ -1286,8 +1335,8 @@ public function set_attribute( $name, $value ) {
* @param string $name The attribute name to remove.
*/
public function remove_attribute( $name ) {
- if ( ! isset( $this->attributes[ $name ] ) ) {
- return;
+ if ( $this->is_closing_tag || ! isset( $this->attributes[ $name ] ) ) {
+ return false;
}
/*
@@ -1316,6 +1365,10 @@ public function remove_attribute( $name ) {
* @param string $class_name The class name to add.
*/
public function add_class( $class_name ) {
+ if ( $this->is_closing_tag ) {
+ return false;
+ }
+
if ( null !== $this->tag_name_starts_at ) {
$this->classname_updates[ $class_name ] = self::ADD_CLASS;
}
@@ -1329,6 +1382,10 @@ public function add_class( $class_name ) {
* @param string $class_name The class name to remove.
*/
public function remove_class( $class_name ) {
+ if ( $this->is_closing_tag ) {
+ return false;
+ }
+
if ( null !== $this->tag_name_starts_at ) {
$this->classname_updates[ $class_name ] = self::REMOVE_CLASS;
}
@@ -1392,7 +1449,9 @@ public function get_updated_html() {
// Parse the attributes in the updated markup.
$this->attributes = array();
- $this->parse_tag_opener_attributes();
+ while ( $this->parse_next_attribute() ) {
+ continue;
+ }
return $this->html;
}
@@ -1407,6 +1466,7 @@ public function get_updated_html() {
*
* @type string|null $tag_name Which tag to find, or `null` for "any tag."
* @type string|null $class_name Tag must contain this class name to match.
+ * @type string $tag_closers "visit" or "skip": whether to stop on tag closers, e.g.