From 312faf1706e4eafcb4a07d26ad252b713e4ca238 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Mon, 25 Nov 2019 17:48:51 -0800 Subject: [PATCH 1/5] Include extension_type in generated tag specs --- bin/amphtml-update.py | 4 ---- includes/sanitizers/class-amp-allowed-tags-generated.php | 1 + .../sanitizers/class-amp-tag-and-attribute-sanitizer.php | 9 ++++++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/bin/amphtml-update.py b/bin/amphtml-update.py index 469d744696e..acfb718ca85 100644 --- a/bin/amphtml-update.py +++ b/bin/amphtml-update.py @@ -593,10 +593,6 @@ def GetTagRules(tag_spec): versions.remove( 'latest' ) extension_spec['version'] = sorted( versions, key=lambda version: map(int, version.split('.') ) ) - # Unused since amp_filter_script_loader_tag() and \AMP_Tag_And_Attribute_Sanitizer::get_rule_spec_list_to_validate() just hard-codes the check for amp-mustache. - if 'extension_type' in extension_spec: - del extension_spec['extension_type'] - if 'deprecated_version' in extension_spec: del extension_spec['deprecated_version'] diff --git a/includes/sanitizers/class-amp-allowed-tags-generated.php b/includes/sanitizers/class-amp-allowed-tags-generated.php index 65d3e7d65be..974e46c1825 100644 --- a/includes/sanitizers/class-amp-allowed-tags-generated.php +++ b/includes/sanitizers/class-amp-allowed-tags-generated.php @@ -13602,6 +13602,7 @@ class AMP_Allowed_Tags_Generated { ), 'tag_spec' => array( 'extension_spec' => array( + 'extension_type' => 2, 'name' => 'amp-mustache', 'requires_usage' => true, 'version' => array( diff --git a/includes/sanitizers/class-amp-tag-and-attribute-sanitizer.php b/includes/sanitizers/class-amp-tag-and-attribute-sanitizer.php index b635d83e4aa..e81c72e0e01 100644 --- a/includes/sanitizers/class-amp-tag-and-attribute-sanitizer.php +++ b/includes/sanitizers/class-amp-tag-and-attribute-sanitizer.php @@ -380,8 +380,11 @@ private function get_rule_spec_list_to_validate( DOMElement $node, $rule_spec ) if ( isset( $rule_spec[ AMP_Rule_Spec::TAG_SPEC ]['extension_spec'] ) ) { $extension_spec = $rule_spec[ AMP_Rule_Spec::TAG_SPEC ]['extension_spec']; - // This could also be derived from the extension_type in the extension_spec. - $custom_attr = 'amp-mustache' === $extension_spec['name'] ? 'custom-template' : 'custom-element'; + if ( isset( $rule_spec[ AMP_Rule_Spec::TAG_SPEC ]['extension_spec']['extension_type'] ) && 2 === $rule_spec[ AMP_Rule_Spec::TAG_SPEC ]['extension_spec']['extension_type'] ) { + $custom_attr = 'custom-template'; + } else { + $custom_attr = 'custom-element'; + } $rule_spec[ AMP_Rule_Spec::ATTR_SPEC_LIST ][ $custom_attr ] = [ AMP_Rule_Spec::VALUE => $extension_spec['name'], @@ -1056,7 +1059,7 @@ private function get_spec_name( DOMElement $element, $tag_spec ) { } elseif ( isset( $tag_spec['extension_spec']['name'] ) ) { return sprintf( 'script[%s=%s]', - 'amp-mustache' === $tag_spec['extension_spec']['name'] ? 'custom-template' : 'custom-element', + isset( $tag_spec['extension_spec']['extension_type'] ) && 2 === $tag_spec['extension_spec']['extension_type'] ? 'custom-template' : 'custom-element', strtolower( $tag_spec['extension_spec']['name'] ) ); } else { From 0347568e769b5f1781c4d86672544fd3ab276b81 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Mon, 25 Nov 2019 19:06:00 -0800 Subject: [PATCH 2/5] Add obtaining a tag spec by name --- bin/amphtml-update.py | 25 +++- .../class-amp-allowed-tags-generated.php | 132 +++++++++++++++++- .../sanitizers/class-amp-style-sanitizer.php | 24 +--- tests/php/test-amp-style-sanitizer.php | 9 ++ 4 files changed, 167 insertions(+), 23 deletions(-) diff --git a/bin/amphtml-update.py b/bin/amphtml-update.py index acfb718ca85..743a829f311 100644 --- a/bin/amphtml-update.py +++ b/bin/amphtml-update.py @@ -101,6 +101,7 @@ def GeneratePHP(out_dir): expected_spec_names = ( 'style amp-custom', 'style[amp-keyframes]', + 'link rel=stylesheet for fonts', ) for expected_spec_name in expected_spec_names: if expected_spec_name not in seen_spec_names: @@ -250,12 +251,26 @@ def GenerateFooterPHP(out): * Get the rules for a single tag so that the entire data structure needn't be passed around. * * @since 0.7 - * @param string $node_name Tag name. + * + * @param string $node_name Tag name. + * @param string|null $spec_name Spec name. * @return array|null Allowed tag, or null if the tag does not exist. */ - public static function get_allowed_tag( $node_name ) { + public static function get_allowed_tag( $node_name, $spec_name = null ) { if ( isset( self::$allowed_tags[ $node_name ] ) ) { - return self::$allowed_tags[ $node_name ]; + $rule_specs = self::$allowed_tags[ $node_name ]; + if ( empty( $spec_name ) ) { + return $rule_specs; + } + foreach ( $rule_specs as $rule_spec ) { + if ( + ( ! isset( $rule_spec['tag_spec']['spec_name'] ) && $node_name === $spec_name ) + || + ( isset( $rule_spec['tag_spec']['spec_name'] ) && $rule_spec['tag_spec']['spec_name'] === $spec_name ) + ) { + return $rule_spec; + } + } } return null; } @@ -502,6 +517,10 @@ def GetTagSpec(tag_spec, attr_lists): raise Exception( 'Already seen spec_name: %s' % spec_name ) seen_spec_names.add( spec_name ) + # Add the spec_name to the tag spec if it isn't the same as the tag name. + if spec_name != tag_spec.tag_name.lower(): + tag_spec_dict['tag_spec']['spec_name'] = spec_name + return tag_spec_dict diff --git a/includes/sanitizers/class-amp-allowed-tags-generated.php b/includes/sanitizers/class-amp-allowed-tags-generated.php index 974e46c1825..511c474aaaa 100644 --- a/includes/sanitizers/class-amp-allowed-tags-generated.php +++ b/includes/sanitizers/class-amp-allowed-tags-generated.php @@ -11554,6 +11554,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-3d-gltf]', ), ), array( @@ -11579,6 +11580,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-3q-player]', ), ), array( @@ -11608,6 +11610,7 @@ class AMP_Allowed_Tags_Generated { 'requires_extension' => array( 'amp-access', ), + 'spec_name' => 'script [custom-element=amp-access-laterpay]', ), ), array( @@ -11636,6 +11639,7 @@ class AMP_Allowed_Tags_Generated { 'requires_extension' => array( 'amp-access', ), + 'spec_name' => 'script [custom-element=amp-access-poool]', ), ), array( @@ -11664,6 +11668,7 @@ class AMP_Allowed_Tags_Generated { 'requires_extension' => array( 'amp-access', ), + 'spec_name' => 'script [custom-element=amp-access-scroll]', ), ), array( @@ -11689,6 +11694,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-access]', ), ), array( @@ -11746,6 +11752,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-accordion]', ), ), array( @@ -11771,6 +11778,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-action-macro]', ), ), array( @@ -11848,6 +11856,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-addthis]', ), ), array( @@ -11873,6 +11882,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-analytics]', ), ), array( @@ -11924,6 +11934,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-anim]', ), ), array( @@ -11949,6 +11960,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-animation]', ), ), array( @@ -11999,6 +12011,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-apester-media]', ), ), array( @@ -12024,6 +12037,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-app-banner]', ), ), array( @@ -12049,6 +12063,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-audio]', ), ), array( @@ -12074,6 +12089,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-auto-ads]', ), ), array( @@ -12099,6 +12115,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-autocomplete]', ), ), array( @@ -12149,6 +12166,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-base-carousel]', ), ), array( @@ -12174,6 +12192,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-beopinion]', ), ), array( @@ -12199,6 +12218,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-bind]', ), ), array( @@ -12252,6 +12272,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-bodymovin-animation]', ), ), array( @@ -12277,6 +12298,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-brid-player]', ), ), array( @@ -12302,6 +12324,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-brightcove]', ), ), array( @@ -12327,6 +12350,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-byside-content]', ), ), array( @@ -12352,6 +12376,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-call-tracking]', ), ), array( @@ -12378,6 +12403,7 @@ class AMP_Allowed_Tags_Generated { '0.2', ), ), + 'spec_name' => 'script [custom-element=amp-carousel]', ), ), array( @@ -12403,6 +12429,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-connatix-player]', ), ), array( @@ -12428,6 +12455,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-consent]', ), ), array( @@ -12479,6 +12507,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-dailymotion]', ), ), array( @@ -12504,6 +12533,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-date-countdown]', ), ), array( @@ -12529,6 +12559,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-date-display]', ), ), array( @@ -12554,6 +12585,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-date-picker]', ), ), array( @@ -12579,6 +12611,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-delight-player]', ), ), array( @@ -12604,6 +12637,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-dynamic-css-classes]', ), ), array( @@ -12629,6 +12663,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-embedly-card]', ), ), array( @@ -12655,6 +12690,7 @@ class AMP_Allowed_Tags_Generated { '1.0', ), ), + 'spec_name' => 'script [custom-element=amp-experiment]', ), ), array( @@ -12705,6 +12741,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-facebook-comments]', ), ), array( @@ -12730,6 +12767,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-facebook-like]', ), ), array( @@ -12755,6 +12793,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-facebook-page]', ), ), array( @@ -12780,6 +12819,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-facebook]', ), ), array( @@ -12805,6 +12845,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-fit-text]', ), ), array( @@ -12830,6 +12871,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-font]', ), ), array( @@ -12855,6 +12897,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-form]', ), ), array( @@ -12880,6 +12923,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-fx-collection]', ), ), array( @@ -12905,6 +12949,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-fx-flying-carpet]', ), ), array( @@ -12930,6 +12975,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-geo]', ), ), array( @@ -12981,6 +13027,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-gfycat]', ), ), array( @@ -13006,6 +13053,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-gist]', ), ), array( @@ -13031,6 +13079,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-google-document-embed]', ), ), array( @@ -13056,6 +13105,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-hulu]', ), ), array( @@ -13081,6 +13131,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-iframe]', ), ), array( @@ -13106,6 +13157,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-ima-video]', ), ), array( @@ -13131,6 +13183,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-image-lightbox]', ), ), array( @@ -13156,6 +13209,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-image-slider]', ), ), array( @@ -13181,6 +13235,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-imgur]', ), ), array( @@ -13206,6 +13261,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-inputmask]', ), ), array( @@ -13231,6 +13287,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-instagram]', ), ), array( @@ -13256,6 +13313,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-install-serviceworker]', ), ), array( @@ -13281,6 +13339,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-izlesene]', ), ), array( @@ -13306,6 +13365,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-jwplayer]', ), ), array( @@ -13331,6 +13391,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-kaltura-player]', ), ), array( @@ -13356,6 +13417,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-lightbox-gallery]', ), ), array( @@ -13381,6 +13443,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-lightbox]', ), ), array( @@ -13406,6 +13469,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-link-rewriter]', ), ), array( @@ -13456,6 +13520,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-list]', ), ), array( @@ -13482,6 +13547,7 @@ class AMP_Allowed_Tags_Generated { ), ), 'mandatory_parent' => 'head', + 'spec_name' => 'script [custom-element=amp-live-list]', 'unique_warning' => true, ), ), @@ -13508,6 +13574,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-mathml]', ), ), array( @@ -13533,6 +13600,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-megaphone]', ), ), array( @@ -13558,6 +13626,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-minute-media-player]', ), ), array( @@ -13583,6 +13652,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-mowplayer]', ), ), array( @@ -13610,6 +13680,7 @@ class AMP_Allowed_Tags_Generated { '0.2', ), ), + 'spec_name' => 'script [custom-template=amp-mustache]', ), ), array( @@ -13673,6 +13744,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-next-page]', ), ), array( @@ -13717,6 +13789,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-nexxtv-player]', ), ), array( @@ -13742,6 +13815,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-o2-player]', ), ), array( @@ -13767,6 +13841,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-ooyala-player]', ), ), array( @@ -13792,6 +13867,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-orientation-observer]', ), ), array( @@ -13817,6 +13893,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-pan-zoom]', ), ), array( @@ -13842,6 +13919,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-pinterest]', ), ), array( @@ -13867,6 +13945,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-playbuzz]', ), ), array( @@ -13892,6 +13971,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-position-observer]', ), ), array( @@ -13917,6 +13997,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-powr-player]', ), ), array( @@ -13942,6 +14023,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-reach-player]', ), ), array( @@ -13967,6 +14049,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-recaptcha-input]', ), ), array( @@ -13992,6 +14075,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-reddit]', ), ), array( @@ -14017,6 +14101,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-riddle-quiz]', ), ), array( @@ -14042,6 +14127,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-script]', ), ), array( @@ -14104,6 +14190,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-selector]', ), ), array( @@ -14129,6 +14216,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-sidebar]', ), ), array( @@ -14154,6 +14242,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-skimlinks]', ), ), array( @@ -14179,6 +14268,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-smartlinks]', ), ), array( @@ -14204,6 +14294,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-social-share]', ), ), array( @@ -14229,6 +14320,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-soundcloud]', ), ), array( @@ -14254,6 +14346,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-springboard-player]', ), ), array( @@ -14280,6 +14373,7 @@ class AMP_Allowed_Tags_Generated { '1.0', ), ), + 'spec_name' => 'script [custom-element=amp-sticky-ad]', ), ), array( @@ -14305,6 +14399,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-story-auto-ads]', ), ), array( @@ -14356,6 +14451,7 @@ class AMP_Allowed_Tags_Generated { '1.0', ), ), + 'spec_name' => 'script [custom-element=amp-story]', ), ), array( @@ -14452,6 +14548,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-subscriptions]', ), ), array( @@ -14512,6 +14609,7 @@ class AMP_Allowed_Tags_Generated { 'requires_extension' => array( 'amp-subscriptions', ), + 'spec_name' => 'script [custom-element=amp-subscriptions-google]', ), ), array( @@ -14537,6 +14635,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-timeago]', ), ), array( @@ -14562,6 +14661,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-truncate-text]', ), ), array( @@ -14587,6 +14687,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-twitter]', ), ), array( @@ -14612,6 +14713,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-user-location]', ), ), array( @@ -14663,6 +14765,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-user-notification]', ), ), array( @@ -14714,6 +14817,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-video-iframe]', ), ), array( @@ -14765,6 +14869,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-vimeo]', ), ), array( @@ -14790,6 +14895,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-vine]', ), ), array( @@ -14815,6 +14921,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-viqeo-player]', ), ), array( @@ -14840,6 +14947,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-vk]', ), ), array( @@ -14865,6 +14973,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-web-push]', ), ), array( @@ -14890,6 +14999,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-wistia-player]', ), ), array( @@ -14915,6 +15025,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-yotpo]', 'spec_url' => 'https://amp.dev/documentation/components/amp-yotpo', ), ), @@ -14941,6 +15052,7 @@ class AMP_Allowed_Tags_Generated { '0.1', ), ), + 'spec_name' => 'script [custom-element=amp-youtube]', ), ), ), @@ -17625,12 +17737,26 @@ public static function get_extension_specs() { * Get the rules for a single tag so that the entire data structure needn't be passed around. * * @since 0.7 - * @param string $node_name Tag name. + * + * @param string $node_name Tag name. + * @param string|null $spec_name Spec name. * @return array|null Allowed tag, or null if the tag does not exist. */ - public static function get_allowed_tag( $node_name ) { + public static function get_allowed_tag( $node_name, $spec_name = null ) { if ( isset( self::$allowed_tags[ $node_name ] ) ) { - return self::$allowed_tags[ $node_name ]; + $rule_specs = self::$allowed_tags[ $node_name ]; + if ( empty( $spec_name ) ) { + return $rule_specs; + } + foreach ( $rule_specs as $rule_spec ) { + if ( + ( ! isset( $rule_spec['tag_spec']['spec_name'] ) && $node_name === $spec_name ) + || + ( isset( $rule_spec['tag_spec']['spec_name'] ) && $rule_spec['tag_spec']['spec_name'] === $spec_name ) + ) { + return $rule_spec; + } + } } return null; } diff --git a/includes/sanitizers/class-amp-style-sanitizer.php b/includes/sanitizers/class-amp-style-sanitizer.php index 9bcc886e3f3..5a05037c2f8 100644 --- a/includes/sanitizers/class-amp-style-sanitizer.php +++ b/includes/sanitizers/class-amp-style-sanitizer.php @@ -388,24 +388,14 @@ public static function has_required_php_css_parser() { public function __construct( $dom, array $args = [] ) { parent::__construct( $dom, $args ); - foreach ( AMP_Allowed_Tags_Generated::get_allowed_tag( 'style' ) as $spec_rule ) { - if ( ! isset( $spec_rule[ AMP_Rule_Spec::TAG_SPEC ]['spec_name'] ) ) { - continue; - } - if ( self::STYLE_AMP_KEYFRAMES_SPEC_NAME === $spec_rule[ AMP_Rule_Spec::TAG_SPEC ]['spec_name'] ) { - $this->style_keyframes_cdata_spec = $spec_rule[ AMP_Rule_Spec::CDATA ]; - } elseif ( self::STYLE_AMP_CUSTOM_SPEC_NAME === $spec_rule[ AMP_Rule_Spec::TAG_SPEC ]['spec_name'] ) { - $this->style_custom_cdata_spec = $spec_rule[ AMP_Rule_Spec::CDATA ]; - } - } + $style_custom_rule_spec = AMP_Allowed_Tags_Generated::get_allowed_tag( 'style', self::STYLE_AMP_CUSTOM_SPEC_NAME ); + $this->style_custom_cdata_spec = $style_custom_rule_spec[ AMP_Rule_Spec::CDATA ]; - $spec_name = 'link rel=stylesheet for fonts'; // phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedStylesheet - foreach ( AMP_Allowed_Tags_Generated::get_allowed_tag( 'link' ) as $spec_rule ) { - if ( isset( $spec_rule[ AMP_Rule_Spec::TAG_SPEC ]['spec_name'] ) && $spec_name === $spec_rule[ AMP_Rule_Spec::TAG_SPEC ]['spec_name'] ) { - $this->allowed_font_src_regex = '@^(' . $spec_rule[ AMP_Rule_Spec::ATTR_SPEC_LIST ]['href']['value_regex'] . ')$@'; - break; - } - } + $style_keyframes_rule_spec = AMP_Allowed_Tags_Generated::get_allowed_tag( 'style', self::STYLE_AMP_KEYFRAMES_SPEC_NAME ); + $this->style_keyframes_cdata_spec = $style_keyframes_rule_spec[ AMP_Rule_Spec::CDATA ]; + + $font_stylesheet_tag_spec = AMP_Allowed_Tags_Generated::get_allowed_tag( 'link', 'link rel=stylesheet for fonts' ); // phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedStylesheet + $this->allowed_font_src_regex = '@^(' . $font_stylesheet_tag_spec[ AMP_Rule_Spec::ATTR_SPEC_LIST ]['href']['value_regex'] . ')$@'; $guessurl = site_url(); if ( ! $guessurl ) { diff --git a/tests/php/test-amp-style-sanitizer.php b/tests/php/test-amp-style-sanitizer.php index b22274e443d..99d3543b8f0 100644 --- a/tests/php/test-amp-style-sanitizer.php +++ b/tests/php/test-amp-style-sanitizer.php @@ -38,6 +38,15 @@ public function tearDown() { $wp_scripts = null; } + /** + * Ensure the specs required by the constructor are present. + */ + public function test_constructor_dependencies() { + $this->assertInternalType( 'array', AMP_Allowed_Tags_Generated::get_allowed_tag( 'style', AMP_Style_Sanitizer::STYLE_AMP_CUSTOM_SPEC_NAME )[ AMP_Rule_Spec::CDATA ] ); + $this->assertInternalType( 'array', AMP_Allowed_Tags_Generated::get_allowed_tag( 'style', AMP_Style_Sanitizer::STYLE_AMP_KEYFRAMES_SPEC_NAME )[ AMP_Rule_Spec::CDATA ] ); + $this->assertInternalType( 'string', AMP_Allowed_Tags_Generated::get_allowed_tag( 'link', 'link rel=stylesheet for fonts' )[ AMP_Rule_Spec::ATTR_SPEC_LIST ]['href']['value_regex'] ); // phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedStylesheet + } + /** * Get data for tests. * From 5b0dedba85cf0578104c90af3cb7bc9a09c1fcb9 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Mon, 25 Nov 2019 21:20:45 -0800 Subject: [PATCH 3/5] Separate extension specs from tag specs --- bin/amphtml-update.py | 76 +- .../class-amp-allowed-tags-generated.php | 8074 ++++++----------- .../class-amp-tag-and-attribute-sanitizer.php | 100 +- 3 files changed, 2976 insertions(+), 5274 deletions(-) diff --git a/bin/amphtml-update.py b/bin/amphtml-update.py index 743a829f311..c4b05058537 100644 --- a/bin/amphtml-update.py +++ b/bin/amphtml-update.py @@ -96,7 +96,7 @@ def GeneratePHP(out_dir): """ logging.info('entering ...') - allowed_tags, attr_lists, descendant_lists, reference_points, versions = ParseRules(out_dir) + allowed_tags, extension_specs, attr_lists, descendant_lists, reference_points, versions = ParseRules(out_dir) expected_spec_names = ( 'style amp-custom', @@ -116,6 +116,7 @@ def GeneratePHP(out_dir): GenerateLayoutAttributesPHP(out, attr_lists) GenerateGlobalAttributesPHP(out, attr_lists) GenerateReferencePointsPHP(out, reference_points) + GenerateExtensionSpecsPHP(out, extension_specs) GenerateFooterPHP(out) # join out array into a single string and remove unneeded whitespace @@ -207,6 +208,15 @@ def GenerateReferencePointsPHP(out, reference_points): out.append('') logging.info('... done') +def GenerateExtensionSpecsPHP(out, extension_specs): + logging.info('entering ...') + + # Output the reference points. + out.append('') + out.append('\tprivate static $extension_specs = %s;' % Phpize( extension_specs, 1 ).lstrip() ) + out.append('') + logging.info('... done') + def GenerateFooterPHP(out): logging.info('entering ...') @@ -227,22 +237,27 @@ def GenerateFooterPHP(out): * * @since 1.5 * @internal + * * @return array Extension specs, keyed by extension name. */ public static function get_extension_specs() { - static $extension_specs = []; - - if ( ! empty( $extension_specs ) ) { - return $extension_specs; - } + return self::$extension_specs; + } - foreach ( self::get_allowed_tag( 'script' ) as $script_spec ) { - if ( isset( $script_spec[ AMP_Rule_Spec::TAG_SPEC ]['extension_spec'] ) ) { - $extension_specs[ $script_spec[ AMP_Rule_Spec::TAG_SPEC ]['extension_spec']['name'] ] = $script_spec[ AMP_Rule_Spec::TAG_SPEC ]['extension_spec']; - } + /** + * Get extension specs. + * + * @since 1.5 + * @internal + * + * @param string $name Extension name. + * @return array Extension specs, keyed by extension name. + */ + public static function get_extension_spec( $name ) { + if ( isset( self::$extension_specs[ $name ] ) ) { + return self::$extension_specs[ $name ]; } - - return $extension_specs; + return null; } /** @@ -252,23 +267,23 @@ def GenerateFooterPHP(out): * * @since 0.7 * - * @param string $node_name Tag name. + * @param string $tag_name Tag name. * @param string|null $spec_name Spec name. - * @return array|null Allowed tag, or null if the tag does not exist. + * @return array[]|array|null Allowed tags, allowed tag spec, or null if the tag does not exist. */ - public static function get_allowed_tag( $node_name, $spec_name = null ) { - if ( isset( self::$allowed_tags[ $node_name ] ) ) { - $rule_specs = self::$allowed_tags[ $node_name ]; + public static function get_allowed_tag( $tag_name, $spec_name = null ) { + if ( isset( self::$allowed_tags[ $tag_name ] ) ) { + $rule_specs = self::$allowed_tags[ $tag_name ]; if ( empty( $spec_name ) ) { return $rule_specs; } foreach ( $rule_specs as $rule_spec ) { if ( - ( ! isset( $rule_spec['tag_spec']['spec_name'] ) && $node_name === $spec_name ) + ( ! isset( $rule_spec['tag_spec']['spec_name'] ) && $tag_name === $spec_name ) || ( isset( $rule_spec['tag_spec']['spec_name'] ) && $rule_spec['tag_spec']['spec_name'] === $spec_name ) ) { - return $rule_spec; + return array_merge( compact( 'tag_name' ), $rule_spec ); } } } @@ -354,6 +369,7 @@ def ParseRules(out_dir): validator_pb2 = imp.load_source('validator_pb2', os.path.join( out_dir, 'validator_pb2.py' )) allowed_tags = {} + extension_specs = {} attr_lists = {} descendant_lists = {} reference_points = {} @@ -413,12 +429,16 @@ def ParseRules(out_dir): tag_list = [] else: tag_list = allowed_tags[UnicodeEscape(tag_spec.tag_name).lower()] - # AddTag(allowed_tags, tag_spec, attr_lists) gotten_tag_spec = GetTagSpec(tag_spec, attr_lists) if gotten_tag_spec is not None: - tag_list.append(gotten_tag_spec) - allowed_tags[UnicodeEscape(tag_spec.tag_name).lower()] = tag_list + if 'extension_spec' in gotten_tag_spec['tag_spec']: + extension_name = gotten_tag_spec['tag_spec']['extension_spec']['name'] + del gotten_tag_spec['tag_spec']['extension_spec']['name'] + extension_specs[ extension_name ] = gotten_tag_spec['tag_spec']['extension_spec'] + else: + tag_list.append(gotten_tag_spec) + allowed_tags[UnicodeEscape(tag_spec.tag_name).lower()] = tag_list elif 'descendant_tag_list' == field_desc.name: for list in field_val: descendant_lists[list.name] = [] @@ -431,7 +451,7 @@ def ParseRules(out_dir): descendant_lists[list.name].append( val.lower() ) logging.info('... done') - return allowed_tags, attr_lists, descendant_lists, reference_points, versions + return allowed_tags, extension_specs, attr_lists, descendant_lists, reference_points, versions def GetTagSpec(tag_spec, attr_lists): @@ -504,23 +524,17 @@ def GetTagSpec(tag_spec, attr_lists): if 'spec_name' not in tag_spec_dict['tag_spec']: if 'extension_spec' in tag_spec_dict['tag_spec']: - # CUSTOM_ELEMENT=1 (default), CUSTOM_TEMPLATE=2 - extension_type = tag_spec_dict['tag_spec']['extension_spec'].get('extension_type', 1) - spec_name = 'script [%s=%s]' % ( 'custom-element' if 1 == extension_type else 'custom-template', tag_spec_dict['tag_spec']['extension_spec']['name'].lower() ) + extension_name = tag_spec_dict['tag_spec']['extension_spec']['name'].lower() + spec_name = 'script %s' % extension_name else: spec_name = tag_spec.tag_name.lower() else: spec_name = tag_spec_dict['tag_spec']['spec_name'] - if '$reference_point' != spec_name: if spec_name in seen_spec_names: raise Exception( 'Already seen spec_name: %s' % spec_name ) seen_spec_names.add( spec_name ) - # Add the spec_name to the tag spec if it isn't the same as the tag name. - if spec_name != tag_spec.tag_name.lower(): - tag_spec_dict['tag_spec']['spec_name'] = spec_name - return tag_spec_dict diff --git a/includes/sanitizers/class-amp-allowed-tags-generated.php b/includes/sanitizers/class-amp-allowed-tags-generated.php index 511c474aaaa..ba6851ec569 100644 --- a/includes/sanitizers/class-amp-allowed-tags-generated.php +++ b/includes/sanitizers/class-amp-allowed-tags-generated.php @@ -11533,181 +11533,171 @@ class AMP_Allowed_Tags_Generated { ), array( 'attr_spec_list' => array( - 'async' => array( + 'id' => array( + 'dispatch_key' => 2, 'mandatory' => true, 'value' => array( - '', + 'amp-access', ), ), 'nonce' => array(), 'type' => array( + 'mandatory' => true, 'value_casei' => array( - 'text/javascript', + 'application/json', ), ), ), + 'cdata' => array( + 'blacklisted_cdata_regex' => array( + 'error_message' => 'html comments', + 'regex' => '