- Timestamp:
- 08/08/2024 07:23:53 AM (15 months ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-includes/html-api/class-wp-html-tag-processor.php
r58866 r58867 513 513 514 514 /** 515 * Indicates whether the parser is inside foreign content, 516 * e.g. inside an SVG or MathML element. 517 * 518 * One of 'html', 'svg', or 'math'. 519 * 520 * Several parsing rules change based on whether the parser 521 * is inside foreign content, including whether CDATA sections 522 * are allowed and whether a self-closing flag indicates that 523 * an element has no content. 524 * 525 * @since 6.7.0 526 * 527 * @var string 528 */ 529 private $parsing_namespace = 'html'; 530 531 /** 515 532 * What kind of syntax token became an HTML comment. 516 533 * … … 779 796 public function __construct( $html ) { 780 797 $this->html = $html; 798 } 799 800 /** 801 * Switches parsing mode into a new namespace, such as when 802 * encountering an SVG tag and entering foreign content. 803 * 804 * @since 6.7.0 805 * 806 * @param string $new_namespace One of 'html', 'svg', or 'math' indicating into what 807 * namespace the next tokens will be processed. 808 * @return bool Whether the namespace was valid and changed. 809 */ 810 public function change_parsing_namespace( string $new_namespace ): bool { 811 if ( ! in_array( $new_namespace, array( 'html', 'math', 'svg' ), true ) ) { 812 return false; 813 } 814 815 $this->parsing_namespace = $new_namespace; 816 return true; 781 817 } 782 818 … … 844 880 * 845 881 * @since 6.5.0 882 * @since 6.7.0 Recognizes CDATA sections within foreign content. 846 883 * 847 884 * @return bool Whether a token was parsed. … … 957 994 if ( 958 995 $this->is_closing_tag || 996 'html' !== $this->parsing_namespace || 959 997 1 !== strspn( $this->html, 'iIlLnNpPsStTxX', $this->tag_name_starts_at, 1 ) 960 998 ) { … … 997 1035 998 1036 // Find the closing tag if necessary. 999 $found_closer = false;1000 1037 switch ( $tag_name ) { 1001 1038 case 'SCRIPT': … … 1757 1794 $this->text_length = $closer_at - $this->text_starts_at; 1758 1795 $this->bytes_already_parsed = $closer_at + 1; 1796 return true; 1797 } 1798 1799 if ( 1800 'html' !== $this->parsing_namespace && 1801 strlen( $html ) > $at + 8 && 1802 '[' === $html[ $at + 2 ] && 1803 'C' === $html[ $at + 3 ] && 1804 'D' === $html[ $at + 4 ] && 1805 'A' === $html[ $at + 5 ] && 1806 'T' === $html[ $at + 6 ] && 1807 'A' === $html[ $at + 7 ] && 1808 '[' === $html[ $at + 8 ] 1809 ) { 1810 $closer_at = strpos( $html, ']]>', $at + 9 ); 1811 if ( false === $closer_at ) { 1812 $this->parser_state = self::STATE_INCOMPLETE_INPUT; 1813 1814 return false; 1815 } 1816 1817 $this->parser_state = self::STATE_CDATA_NODE; 1818 $this->text_starts_at = $at + 9; 1819 $this->text_length = $closer_at - $this->text_starts_at; 1820 $this->token_length = $closer_at + 3 - $this->token_starts_at; 1821 $this->bytes_already_parsed = $closer_at + 3; 1759 1822 return true; 1760 1823 } … … 2655 2718 2656 2719 /** 2720 * Returns the namespace of the matched token. 2721 * 2722 * @since 6.7.0 2723 * 2724 * @return string One of 'html', 'math', or 'svg'. 2725 */ 2726 public function get_namespace(): string { 2727 return $this->parsing_namespace; 2728 } 2729 2730 /** 2657 2731 * Returns the uppercase name of the matched tag. 2658 2732 * … … 2689 2763 2690 2764 return null; 2765 } 2766 2767 /** 2768 * Returns the adjusted tag name for a given token, taking into 2769 * account the current parsing context, whether HTML, SVG, or MathML. 2770 * 2771 * @since 6.7.0 2772 * 2773 * @return string|null Name of current tag name. 2774 */ 2775 public function get_qualified_tag_name(): ?string { 2776 $tag_name = $this->get_tag(); 2777 if ( null === $tag_name ) { 2778 return null; 2779 } 2780 2781 if ( 'html' === $this->get_namespace() ) { 2782 return $tag_name; 2783 } 2784 2785 $lower_tag_name = strtolower( $tag_name ); 2786 if ( 'math' === $this->get_namespace() ) { 2787 return $lower_tag_name; 2788 } 2789 2790 if ( 'svg' === $this->get_namespace() ) { 2791 switch ( $lower_tag_name ) { 2792 case 'altglyph': 2793 return 'altGlyph'; 2794 2795 case 'altglyphdef': 2796 return 'altGlyphDef'; 2797 2798 case 'altglyphitem': 2799 return 'altGlyphItem'; 2800 2801 case 'animatecolor': 2802 return 'animateColor'; 2803 2804 case 'animatemotion': 2805 return 'animateMotion'; 2806 2807 case 'animatetransform': 2808 return 'animateTransform'; 2809 2810 case 'clippath': 2811 return 'clipPath'; 2812 2813 case 'feblend': 2814 return 'feBlend'; 2815 2816 case 'fecolormatrix': 2817 return 'feColorMatrix'; 2818 2819 case 'fecomponenttransfer': 2820 return 'feComponentTransfer'; 2821 2822 case 'fecomposite': 2823 return 'feComposite'; 2824 2825 case 'feconvolvematrix': 2826 return 'feConvolveMatrix'; 2827 2828 case 'fediffuselighting': 2829 return 'feDiffuseLighting'; 2830 2831 case 'fedisplacementmap': 2832 return 'feDisplacementMap'; 2833 2834 case 'fedistantlight': 2835 return 'feDistantLight'; 2836 2837 case 'fedropshadow': 2838 return 'feDropShadow'; 2839 2840 case 'feflood': 2841 return 'feFlood'; 2842 2843 case 'fefunca': 2844 return 'feFuncA'; 2845 2846 case 'fefuncb': 2847 return 'feFuncB'; 2848 2849 case 'fefuncg': 2850 return 'feFuncG'; 2851 2852 case 'fefuncr': 2853 return 'feFuncR'; 2854 2855 case 'fegaussianblur': 2856 return 'feGaussianBlur'; 2857 2858 case 'feimage': 2859 return 'feImage'; 2860 2861 case 'femerge': 2862 return 'feMerge'; 2863 2864 case 'femergenode': 2865 return 'feMergeNode'; 2866 2867 case 'femorphology': 2868 return 'feMorphology'; 2869 2870 case 'feoffset': 2871 return 'feOffset'; 2872 2873 case 'fepointlight': 2874 return 'fePointLight'; 2875 2876 case 'fespecularlighting': 2877 return 'feSpecularLighting'; 2878 2879 case 'fespotlight': 2880 return 'feSpotLight'; 2881 2882 case 'fetile': 2883 return 'feTile'; 2884 2885 case 'feturbulence': 2886 return 'feTurbulence'; 2887 2888 case 'foreignobject': 2889 return 'foreignObject'; 2890 2891 case 'glyphref': 2892 return 'glyphRef'; 2893 2894 case 'lineargradient': 2895 return 'linearGradient'; 2896 2897 case 'radialgradient': 2898 return 'radialGradient'; 2899 2900 case 'textpath': 2901 return 'textPath'; 2902 2903 default: 2904 return $lower_tag_name; 2905 } 2906 } 2907 } 2908 2909 /** 2910 * Returns the adjusted attribute name for a given attribute, taking into 2911 * account the current parsing context, whether HTML, SVG, or MathML. 2912 * 2913 * @since 6.7.0 2914 * 2915 * @param string $attribute_name Which attribute to adjust. 2916 * 2917 * @return string|null 2918 */ 2919 public function get_qualified_attribute_name( $attribute_name ): ?string { 2920 if ( self::STATE_MATCHED_TAG !== $this->parser_state ) { 2921 return null; 2922 } 2923 2924 $namespace = $this->get_namespace(); 2925 $lower_name = strtolower( $attribute_name ); 2926 2927 if ( 'math' === $namespace && 'definitionurl' === $lower_name ) { 2928 return 'definitionURL'; 2929 } 2930 2931 if ( 'svg' === $this->get_namespace() ) { 2932 switch ( $lower_name ) { 2933 case 'attributename': 2934 return 'attributeName'; 2935 2936 case 'attributetype': 2937 return 'attributeType'; 2938 2939 case 'basefrequency': 2940 return 'baseFrequency'; 2941 2942 case 'baseprofile': 2943 return 'baseProfile'; 2944 2945 case 'calcmode': 2946 return 'calcMode'; 2947 2948 case 'clippathunits': 2949 return 'clipPathUnits'; 2950 2951 case 'diffuseconstant': 2952 return 'diffuseConstant'; 2953 2954 case 'edgemode': 2955 return 'edgeMode'; 2956 2957 case 'filterunits': 2958 return 'filterUnits'; 2959 2960 case 'glyphref': 2961 return 'glyphRef'; 2962 2963 case 'gradienttransform': 2964 return 'gradientTransform'; 2965 2966 case 'gradientunits': 2967 return 'gradientUnits'; 2968 2969 case 'kernelmatrix': 2970 return 'kernelMatrix'; 2971 2972 case 'kernelunitlength': 2973 return 'kernelUnitLength'; 2974 2975 case 'keypoints': 2976 return 'keyPoints'; 2977 2978 case 'keysplines': 2979 return 'keySplines'; 2980 2981 case 'keytimes': 2982 return 'keyTimes'; 2983 2984 case 'lengthadjust': 2985 return 'lengthAdjust'; 2986 2987 case 'limitingconeangle': 2988 return 'limitingConeAngle'; 2989 2990 case 'markerheight': 2991 return 'markerHeight'; 2992 2993 case 'markerunits': 2994 return 'markerUnits'; 2995 2996 case 'markerwidth': 2997 return 'markerWidth'; 2998 2999 case 'maskcontentunits': 3000 return 'maskContentUnits'; 3001 3002 case 'maskunits': 3003 return 'maskUnits'; 3004 3005 case 'numoctaves': 3006 return 'numOctaves'; 3007 3008 case 'pathlength': 3009 return 'pathLength'; 3010 3011 case 'patterncontentunits': 3012 return 'patternContentUnits'; 3013 3014 case 'patterntransform': 3015 return 'patternTransform'; 3016 3017 case 'patternunits': 3018 return 'patternUnits'; 3019 3020 case 'pointsatx': 3021 return 'pointsAtX'; 3022 3023 case 'pointsaty': 3024 return 'pointsAtY'; 3025 3026 case 'pointsatz': 3027 return 'pointsAtZ'; 3028 3029 case 'preservealpha': 3030 return 'preserveAlpha'; 3031 3032 case 'preserveaspectratio': 3033 return 'preserveAspectRatio'; 3034 3035 case 'primitiveunits': 3036 return 'primitiveUnits'; 3037 3038 case 'refx': 3039 return 'refX'; 3040 3041 case 'refy': 3042 return 'refY'; 3043 3044 case 'repeatcount': 3045 return 'repeatCount'; 3046 3047 case 'repeatdur': 3048 return 'repeatDur'; 3049 3050 case 'requiredextensions': 3051 return 'requiredExtensions'; 3052 3053 case 'requiredfeatures': 3054 return 'requiredFeatures'; 3055 3056 case 'specularconstant': 3057 return 'specularConstant'; 3058 3059 case 'specularexponent': 3060 return 'specularExponent'; 3061 3062 case 'spreadmethod': 3063 return 'spreadMethod'; 3064 3065 case 'startoffset': 3066 return 'startOffset'; 3067 3068 case 'stddeviation': 3069 return 'stdDeviation'; 3070 3071 case 'stitchtiles': 3072 return 'stitchTiles'; 3073 3074 case 'surfacescale': 3075 return 'surfaceScale'; 3076 3077 case 'systemlanguage': 3078 return 'systemLanguage'; 3079 3080 case 'tablevalues': 3081 return 'tableValues'; 3082 3083 case 'targetx': 3084 return 'targetX'; 3085 3086 case 'targety': 3087 return 'targetY'; 3088 3089 case 'textlength': 3090 return 'textLength'; 3091 3092 case 'viewbox': 3093 return 'viewBox'; 3094 3095 case 'viewtarget': 3096 return 'viewTarget'; 3097 3098 case 'xchannelselector': 3099 return 'xChannelSelector'; 3100 3101 case 'ychannelselector': 3102 return 'yChannelSelector'; 3103 3104 case 'zoomandpan': 3105 return 'zoomAndPan'; 3106 } 3107 } 3108 3109 if ( 'html' !== $namespace ) { 3110 switch ( $lower_name ) { 3111 case 'xlink:actuate': 3112 return 'xlink actuate'; 3113 3114 case 'xlink:arcrole': 3115 return 'xlink arcrole'; 3116 3117 case 'xlink:href': 3118 return 'xlink href'; 3119 3120 case 'xlink:role': 3121 return 'xlink role'; 3122 3123 case 'xlink:show': 3124 return 'xlink show'; 3125 3126 case 'xlink:title': 3127 return 'xlink title'; 3128 3129 case 'xlink:type': 3130 return 'xlink type'; 3131 3132 case 'xml:lang': 3133 return 'xml lang'; 3134 3135 case 'xml:space': 3136 return 'xml space'; 3137 3138 case 'xmlns': 3139 return 'xmlns'; 3140 3141 case 'xmlns:xlink': 3142 return 'xmlns xlink'; 3143 } 3144 } 3145 3146 return $attribute_name; 2691 3147 } 2692 3148 … … 2964 3420 * for security reasons (to avoid joining together strings that were safe 2965 3421 * when separated, but not when joined). 3422 * 3423 * @todo Inside HTML integration points and MathML integration points, the 3424 * text is processed according to the insertion mode, not according 3425 * to the foreign content rules. This should strip the NULL bytes. 2966 3426 */ 2967 return '#text' === $tag_name3427 return ( '#text' === $tag_name && 'html' === $this->get_namespace() ) 2968 3428 ? str_replace( "\x00", '', $decoded ) 2969 3429 : str_replace( "\x00", "\u{FFFD}", $decoded );
Note: See TracChangeset
for help on using the changeset viewer.