get_body_node(); $this->strip_attributes_recursive( $body ); } /** * Passes through the DOM and removes stuff that shouldn't be there. * * @param DOMNode $node The DOM node to strip attributes from. * * @return void */ private function strip_attributes_recursive( $node ) { if ( $node->nodeType !== XML_ELEMENT_NODE ) { return; } if ( $node->hasAttributes() ) { $node_name = $node->nodeName; $length = $node->attributes->length; for ( $i = --$length; $i >= 0; $i-- ) { $attribute = $node->attributes->item( $i ); switch ( $node_name ) { case 'a': $this->sanitize_a_attribute( $node, $attribute ); break; case 'pre': $this->sanitize_pre_attribute( $node, $attribute ); break; case 'table': $this->sanitize_table_attribute( $node, $attribute ); break; case 'td': case 'th': $this->sanitize_cell_attribute( $node, $attribute ); break; } } } foreach ( $node->childNodes as $child_node ) { $this->strip_attributes_recursive( $child_node ); } } /** * Passes through the DOM and strips forbidden tags. * * @param DOMNode $node The DOM node to strip the forbidden tags from. * @param array $tag_names The forbidden tag names. * * @return void */ private function strip_tags( $node, $tag_names ) { foreach ( $tag_names as $tag_name ) { $elements = $node->getElementsByTagName( $tag_name ); $length = $elements->length; if ( 0 === $length ) { continue; } for ( $i = --$length; $i >= 0; $i-- ) { $element = $elements->item( $i ); $parent_node = $element->parentNode; $parent_node->removeChild( $element ); if ( 'body' !== $parent_node->nodeName && AMP_DOM_Utils::is_node_empty( $parent_node ) ) { $parent_node->parentNode->removeChild( $parent_node ); } } } } /** * Sanitizes anchor attributes. * * @param DOMNode $node The DOM node to sanitize the passed attribute from. * @param DOMNode $attribute The attribute to sanitize. * * @return void */ private function sanitize_a_attribute( $node, $attribute ) { $attribute_name = strtolower( $attribute->name ); if ( 'rel' === $attribute_name && 'nofollow' !== $attribute->value ) { $node->removeAttribute( $attribute_name ); } } /** * Sanitizes pre tag attributes. * * @param DOMNode $node The DOM node to sanitize the passed attribute from. * @param DOMNode $attribute The attribute to sanitize. * * @return void */ private function sanitize_pre_attribute( $node, $attribute ) { $attribute_name = strtolower( $attribute->name ); if ( 'line' === $attribute_name ) { $node->removeAttribute( $attribute_name ); } } /** * Sanitizes td / th tag attributes. * * @param DOMNode $node The DOM node to sanitize the passed attribute from. * @param DOMNode $attribute The attribute to sanitize. * * @return void */ private function sanitize_cell_attribute( $node, $attribute ) { $attribute_name = strtolower( $attribute->name ); if ( in_array( $attribute_name, array( 'width', 'height' ), true ) ) { $node->removeAttribute( $attribute_name ); } } /** * Sanitize table tag attributes. * * @param DOMNode $node The DOM node to sanitize the passed attribute from. * @param DOMNode $attribute The attribute to sanitize. * * @return void */ private function sanitize_table_attribute( $node, $attribute ) { $attribute_name = strtolower( $attribute->name ); if ( in_array( $attribute_name, array( 'border', 'cellspacing', 'cellpadding', 'summary' ), true ) ) { $node->removeAttribute( $attribute_name ); } } }