diff --git a/includes/sanitizers/class-amp-tag-and-attribute-sanitizer.php b/includes/sanitizers/class-amp-tag-and-attribute-sanitizer.php index abbb2fa5c12..16cd3a534be 100644 --- a/includes/sanitizers/class-amp-tag-and-attribute-sanitizer.php +++ b/includes/sanitizers/class-amp-tag-and-attribute-sanitizer.php @@ -53,6 +53,14 @@ class AMP_Tag_And_Attribute_Sanitizer extends AMP_Base_Sanitizer { */ protected $layout_allowed_attributes; + /** + * Mapping of alternative names back to their primary names. + * + * @since 0.7 + * @var array + */ + protected $rev_alternate_attr_name_lookup = array(); + /** * Stack. * @@ -91,16 +99,26 @@ public function __construct( $dom, $args = array() ) { 'amp_allowed_tags' => AMP_Allowed_Tags_Generated::get_allowed_tags(), 'amp_globally_allowed_attributes' => AMP_Allowed_Tags_Generated::get_allowed_attributes(), 'amp_layout_allowed_attributes' => AMP_Allowed_Tags_Generated::get_layout_attributes(), + 'amp_bind_placeholder_prefix' => AMP_DOM_Utils::get_amp_bind_placeholder_prefix(), ); parent::__construct( $dom, $args ); - /** - * Prepare whitelists - */ - $this->allowed_tags = $this->args['amp_allowed_tags']; - $this->globally_allowed_attributes = $this->args['amp_globally_allowed_attributes']; - $this->layout_allowed_attributes = $this->args['amp_layout_allowed_attributes']; + // Prepare whitelists. + $this->allowed_tags = $this->args['amp_allowed_tags']; + foreach ( AMP_Rule_Spec::$additional_allowed_tags as $tag_name => $tag_rule_spec ) { + $this->allowed_tags[ $tag_name ][] = $tag_rule_spec; + } + + foreach ( $this->allowed_tags as &$tag_specs ) { + foreach ( $tag_specs as &$tag_spec ) { + if ( isset( $tag_spec[ AMP_Rule_Spec::ATTR_SPEC_LIST ] ) ) { + $tag_spec[ AMP_Rule_Spec::ATTR_SPEC_LIST ] = $this->process_alternate_names( $tag_spec[ AMP_Rule_Spec::ATTR_SPEC_LIST ] ); + } + } + } + $this->globally_allowed_attributes = $this->process_alternate_names( $this->args['amp_globally_allowed_attributes'] ); + $this->layout_allowed_attributes = $this->process_alternate_names( $this->args['amp_layout_allowed_attributes'] ); } /** @@ -127,6 +145,34 @@ public function get_scripts() { return $scripts; } + /** + * Process alternative names in attribute spec list. + * + * @since 0.7 + * + * @param array $attr_spec_list Attribute spec list. + * @return array Modified attribute spec list. + */ + private function process_alternate_names( $attr_spec_list ) { + foreach ( $attr_spec_list as $attr_name => &$attr_spec ) { + if ( '[' === $attr_name[0] ) { + $placeholder_attr_name = $this->args['amp_bind_placeholder_prefix'] . trim( $attr_name, '[]' ); + if ( ! isset( $attr_spec[ AMP_Rule_Spec::ALTERNATIVE_NAMES ] ) ) { + $attr_spec[ AMP_Rule_Spec::ALTERNATIVE_NAMES ] = array(); + } + $attr_spec[ AMP_Rule_Spec::ALTERNATIVE_NAMES ][] = $placeholder_attr_name; + } + + // Save all alternative names in lookup to improve performance. + if ( isset( $attr_spec[ AMP_Rule_Spec::ALTERNATIVE_NAMES ] ) ) { + foreach ( $attr_spec[ AMP_Rule_Spec::ALTERNATIVE_NAMES ] as $alternative_name ) { + $this->rev_alternate_attr_name_lookup[ $alternative_name ] = $attr_name; + } + } + } + return $attr_spec_list; + } + /** * Sanitize the