PluginProbe
Elementor Website Builder – more than just a page builder / 4.3.0-beta3
Elementor Website Builder – more than just a page builder v4.3.0-beta3
4.3.0-beta3 4.3.0-beta2 4.3.0-beta1 4.2.4 4.2.3 4.2.2 4.2.1 4.2.0 4.1.5 4.2.0-beta2 4.2.0-dev2 4.2.0-beta1 4.1.4 4.1.3 4.1.2 4.1.1 4.1.0 4.1.0-beta3 4.1.0-dev3 4.0.9 4.1.0-beta2 4.1.0-dev2 4.0.8 4.1.0-beta1 4.1.0-dev1 All 452 releases
← All changes | includes/utils.php +106 -7 4.1.0-dev14.3.0-beta3 View file →
@@ -46,8 +46,29 @@
46 46 'section',
47 47 'span',
48 48 ];
49 49
50 + /**
51 + * Tags that must never be usable as an HTML wrapper tag, regardless of what
52 + * `elementor/allowed_html_wrapper_tags` filters return. These are the classic
53 + * script-execution / markup-injection vectors (XSS), so they're enforced as a
54 + * hard denylist rather than left to filter authors to avoid re-adding them.
55 + */
56 + const FORBIDDEN_HTML_WRAPPER_TAGS = [
57 + 'script',
58 + 'iframe',
59 + 'object',
60 + 'embed',
61 + 'style',
62 + 'link',
63 + 'meta',
64 + 'base',
65 + 'noscript',
66 + 'template',
67 + 'svg',
68 + 'math',
69 + ];
70 +
50 71 const EXTENDED_ALLOWED_HTML_TAGS = [
51 72 'iframe' => [
52 73 'iframe' => [
53 74 'allow' => true,
@@ -637,8 +658,12 @@
637 658 public static function has_pro() {
638 659 return defined( 'ELEMENTOR_PRO_VERSION' );
639 660 }
640 661
662 + public static function is_license_active(): bool {
663 + return class_exists( '\ElementorPro\License\API' ) && \ElementorPro\License\API::is_license_active();
664 + }
665 +
641 666 public static function is_pro_installed_and_not_active(): bool {
642 667 if ( ! function_exists( 'get_plugins' ) ) {
643 668 require_once ABSPATH . 'wp-admin/includes/plugin.php';
644 669 }
@@ -729,13 +754,19 @@
729 754 if ( $id === $element['id'] ) {
730 755 return $element;
731 756 }
732 757
733 - if ( ! empty( $element['elements'] ) ) {
734 - $element = self::find_element_recursive( $element['elements'], $id );
758 + $inner_elements = apply_filters(
759 + 'elementor/utils/find_element_recursive/inner_elements',
760 + $element['elements'] ?? [],
761 + $element
762 + );
735 763
736 - if ( $element ) {
737 - return $element;
764 + if ( ! empty( $inner_elements ) ) {
765 + $found = self::find_element_recursive( $inner_elements, $id );
766 +
767 + if ( $found ) {
768 + return $found;
738 769 }
739 770 }
740 771 }
741 772
@@ -765,8 +796,45 @@
765 796 }
766 797 }
767 798
768 799 /**
800 + * @var string[]|null
801 + */
802 + private static $resolved_allowed_html_wrapper_tags;
803 +
804 + /**
805 + * Get allowed HTML wrapper tags.
806 + *
807 + * @since 4.4.0
808 + *
809 + * @return string[]
810 + */
811 + public static function get_allowed_html_wrapper_tags(): array {
812 + if ( null !== self::$resolved_allowed_html_wrapper_tags ) {
813 + return self::$resolved_allowed_html_wrapper_tags;
814 + }
815 +
816 + /**
817 + * Allowed HTML wrapper tags.
818 + *
819 + * Filters the list of allowed HTML tag names used by `validate_html_tag()`.
820 + *
821 + * Note: tags in `Utils::FORBIDDEN_HTML_WRAPPER_TAGS` (e.g. `script`, `iframe`,
822 + * `object`) are always stripped after this filter runs and cannot be re-added,
823 + * to prevent XSS via a wrapper tag that executes script or embeds external content.
824 + *
825 + * @since 4.4.0
826 + *
827 + * @param string[] $tags A list of lowercase HTML tag name strings.
828 + */
829 + $tags = apply_filters( 'elementor/allowed_html_wrapper_tags', self::ALLOWED_HTML_WRAPPER_TAGS );
830 +
831 + self::$resolved_allowed_html_wrapper_tags = self::normalize_allowed_html_wrapper_tags( $tags );
832 +
833 + return self::$resolved_allowed_html_wrapper_tags;
834 + }
835 +
836 + /**
769 837 * Validate an HTML tag against a safe allowed list.
770 838 *
771 839 * @param string $tag
772 840 *
@@ -772,12 +840,37 @@
772 840 *
773 841 * @return string
774 842 */
775 843 public static function validate_html_tag( $tag ) {
776 - return $tag && in_array( strtolower( $tag ), self::ALLOWED_HTML_WRAPPER_TAGS ) ? $tag : 'div';
844 + return $tag && in_array( strtolower( $tag ), self::get_allowed_html_wrapper_tags(), true ) ? $tag : 'div';
777 845 }
778 846
779 847 /**
848 + * @param array $tags
849 + *
850 + * @return string[]
851 + */
852 + private static function normalize_allowed_html_wrapper_tags( array $tags ): array {
853 + $normalized_tags = [];
854 +
855 + foreach ( $tags as $tag ) {
856 + if ( ! is_string( $tag ) ) {
857 + continue;
858 + }
859 +
860 + $tag = strtolower( $tag );
861 +
862 + if ( in_array( $tag, self::FORBIDDEN_HTML_WRAPPER_TAGS, true ) ) {
863 + continue;
864 + }
865 +
866 + $normalized_tags[] = $tag;
867 + }
868 +
869 + return array_values( array_unique( $normalized_tags ) );
870 + }
871 +
872 + /**
780 873 * Safe print a validated HTML tag.
781 874 *
782 875 * @param string $tag
783 876 */
@@ -829,8 +922,14 @@
829 922
830 923 echo wp_kses( $text, $allowed_html );
831 924 }
832 925
926 + public static function kses_post_deep( $data ) {
927 + return map_deep( $data, function ( $value ) {
928 + return is_string( $value ) ? wp_kses_post( $value ) : $value;
929 + } );
930 + }
931 +
833 932 public static function is_elementor_path( $path ) {
834 933 $path = wp_normalize_path( $path );
835 934
836 935 /**
@@ -922,10 +1021,10 @@
922 1021 return $cache;
923 1022 }
924 1023
925 1024 public static function is_sale_time(): bool {
926 - $sale_start_time = gmmktime( 12, 0, 0, 11, 25, 2025 );
927 - $sale_end_time = gmmktime( 3, 59, 0, 12, 3, 2025 );
1025 + $sale_start_time = gmmktime( 10, 0, 0, 6, 15, 2026 );
1026 + $sale_end_time = gmmktime( 3, 59, 0, 6, 17, 2026 );
928 1027
929 1028 $now_time = gmdate( 'U' );
930 1029
931 1030 return $now_time >= $sale_start_time && $now_time <= $sale_end_time;