PluginProbe
Ultimate Post Kit – Elementor Post Grid, Post Carousel, Post Slider & Blog Layout Widgets / 4.5.6
Ultimate Post Kit – Elementor Post Grid, Post Carousel, Post Slider & Blog Layout Widgets v4.5.6
4.5.6 4.5.5 4.5.4 4.2.1 4.2.2 4.2.3 4.5.0 4.5.2 4.5.3 4.2.0 4.1.18 4.1.17 4.1.16 4.1.15 4.1.14 4.1.13 4.1.12 4.1.11 4.1.10 4.1.9 4.1.8 4.0.9 4.1.0 4.1.1 4.1.2 All 148 releases
← All changes | includes/helper.php +83 -63 4.2.0 → 4.5.6 View file →
@@ -192,8 +192,9 @@
192 192
193 193 return $output;
194 194 }
195 195
196 +// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- established function name relied on across the plugin family / feedback SDK; renaming would break integration.
196 197 function upk_get_category( $post_type ) {
197 198 switch ( $post_type ) {
198 199 case 'campaign':
199 200 $taxonomy = 'campaign_category';
@@ -354,8 +355,9 @@
354 355
355 356 /**
356 357 * HexColor
357 358 */
359 +// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- established function name relied on across the plugin family / feedback SDK; renaming would break integration.
358 360 function strToHex( $string, $steps = -10 ) {
359 361
360 362 if ( empty( $string ) ) {
361 363 return false;
@@ -817,11 +819,11 @@
817 819 'h3' => 'H3',
818 820 'h4' => 'H4',
819 821 'h5' => 'H5',
820 822 'h6' => 'H6',
821 - 'div' => 'div',
822 - 'span' => 'span',
823 - 'p' => 'p',
823 + 'div' => 'Div',
824 + 'span' => 'Span',
825 + 'p' => 'P',
824 826 ];
825 827
826 828 return $title_tags;
827 829 }
@@ -901,8 +903,9 @@
901 903
902 904 return wpautop( $output );
903 905 }
904 906
907 +// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- established function name relied on across the plugin family / feedback SDK; renaming would break integration.
905 908 function get_user_role( $id ) {
906 909 $user = new WP_User( $id );
907 910 $role = array_shift( $user->roles );
908 911
@@ -930,8 +933,11 @@
930 933 */
931 934
932 935 if ( _is_upk_pro_activated() ) {
933 936 function ultimate_post_kit_reading_time( $content, $avg_reading_speed, $hide_seconds = 'no', $hide_minutes = 'no' ) {
937 + $avg_reading_speed = is_scalar( $avg_reading_speed ) ? (int) $avg_reading_speed : 0;
938 + $avg_reading_speed = $avg_reading_speed > 0 ? $avg_reading_speed : 200;
939 +
934 940 $total_word = str_word_count( wp_strip_all_tags( $content ) );
935 941 $reading_minute = floor( $total_word / $avg_reading_speed );
936 942 $reading_seconds = floor( $total_word % $avg_reading_speed / ( $avg_reading_speed / 60 ) );
937 943
@@ -982,8 +988,9 @@
982 988 /**
983 989 * License Validation
984 990 */
985 991 if ( ! function_exists( 'upk_license_validation' ) ) {
992 + // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- established function name relied on across the plugin family / feedback SDK; renaming would break integration.
986 993 function upk_license_validation() {
987 994
988 995 if ( function_exists( '_is_upk_pro_activated' ) && false === _is_upk_pro_activated() ) {
989 996 return false;
@@ -998,94 +1005,107 @@
998 1005 return false;
999 1006 }
1000 1007 }
1001 1008
1009 +
1002 1010 /**
1003 - * Inject custom CSS and JS into the header
1011 + * Restrict a request-supplied post type to the ones this site already exposes to
1012 + * anonymous visitors.
1013 + *
1014 + * The load-more handlers are registered on wp_ajax_nopriv_* and rebuild their WP_Query
1015 + * from $_POST, so the post type they query is attacker-controlled. Post types that are
1016 + * public but flagged exclude_from_search (Elementor's elementor_library, for example)
1017 + * are deliberately hidden from anonymous visitors elsewhere, so they must not be
1018 + * reachable here either.
1019 + *
1020 + * @param string|array $post_type Requested post type(s).
1021 + * @param string $fallback Post type to fall back to when nothing is allowed.
1022 + * @return string|array Sanitized post type(s).
1004 1023 */
1005 -if ( ! function_exists( 'upk_inject_header_custom_code' ) ) {
1006 - function upk_inject_header_custom_code() {
1007 - if ( upk_is_page_excluded() ) {
1008 - return;
1009 - }
1024 +if ( ! function_exists( 'ultimate_post_kit_sanitize_public_post_type' ) ) {
1025 + function ultimate_post_kit_sanitize_public_post_type( $post_type, $fallback = 'post' ) {
1010 1026
1011 - $custom_css = get_option( 'upk_custom_css', '' );
1012 - $custom_js = get_option( 'upk_custom_js', '' );
1027 + $is_allowed = static function ( $type ) {
1028 + $object = get_post_type_object( $type );
1013 1029
1014 - if ( ! empty( $custom_css ) ) {
1015 - echo "\n<!-- Ultimate Post Kit Custom Header CSS -->\n";
1016 - echo '<style type="text/css">' . "\n";
1017 - // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Custom CSS authored by an administrator (manage_options) in plugin settings; output verbatim by design.
1018 - echo $custom_css . "\n";
1019 - echo '</style>' . "\n";
1030 + return $object && is_post_type_viewable( $type ) && empty( $object->exclude_from_search );
1031 + };
1032 +
1033 + if ( is_array( $post_type ) ) {
1034 + $requested = array_filter( $post_type, 'is_scalar' );
1035 + $requested = array_values( array_filter( array_map( 'strval', $requested ), $is_allowed ) );
1036 +
1037 + return empty( $requested ) ? $fallback : $requested;
1020 1038 }
1021 1039
1022 - if ( ! empty( $custom_js ) ) {
1023 - echo "\n<!-- Ultimate Post Kit Custom Header JS -->\n";
1024 - echo '<script type="text/javascript">' . "\n";
1025 - // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Custom JS authored by an administrator (manage_options) in plugin settings; output verbatim by design.
1026 - echo $custom_js . "\n";
1027 - echo '</script>' . "\n";
1040 + if ( ! is_scalar( $post_type ) ) {
1041 + return $fallback;
1028 1042 }
1043 +
1044 + $post_type = (string) $post_type;
1045 +
1046 + return $is_allowed( $post_type ) ? $post_type : $fallback;
1029 1047 }
1030 1048 }
1031 1049
1032 1050 /**
1033 - * Inject custom CSS and JS into the footer
1051 + * Clamp a request-supplied excerpt word count.
1052 + *
1053 + * excerpt_length arrives from $_POST on the unauthenticated load-more handlers and is
1054 + * passed straight to wp_trim_words(), so an unbounded value returns effectively the
1055 + * whole post_content instead of a teaser.
1056 + *
1057 + * @param mixed $length Requested word count.
1058 + * @param int $default Value to use when the request supplies nothing usable.
1059 + * @return int Clamped word count.
1034 1060 */
1035 -if ( ! function_exists( 'upk_inject_footer_custom_code' ) ) {
1036 - function upk_inject_footer_custom_code() {
1037 - if ( upk_is_page_excluded() ) {
1038 - return;
1039 - }
1061 +if ( ! function_exists( 'ultimate_post_kit_clamp_excerpt_length' ) ) {
1062 + function ultimate_post_kit_clamp_excerpt_length( $length, $default = 20 ) {
1040 1063
1041 - $custom_css_2 = get_option( 'upk_custom_css_2', '' );
1042 - $custom_js_2 = get_option( 'upk_custom_js_2', '' );
1064 + $length = is_scalar( $length ) ? (int) $length : 0;
1043 1065
1044 - if ( ! empty( $custom_css_2 ) ) {
1045 - echo "\n<!-- Ultimate Post Kit Custom Footer CSS -->\n";
1046 - echo '<style type="text/css">' . "\n";
1047 - // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Custom CSS authored by an administrator (manage_options) in plugin settings; output verbatim by design.
1048 - echo $custom_css_2 . "\n";
1049 - echo '</style>' . "\n";
1066 + if ( $length < 1 ) {
1067 + $length = (int) $default;
1050 1068 }
1051 1069
1052 - if ( ! empty( $custom_js_2 ) ) {
1053 - echo "\n<!-- Ultimate Post Kit Custom Footer JS -->\n";
1054 - echo '<script type="text/javascript">' . "\n";
1055 - // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Custom JS authored by an administrator (manage_options) in plugin settings; output verbatim by design.
1056 - echo $custom_js_2 . "\n";
1057 - echo '</script>' . "\n";
1058 - }
1070 + return max( 1, min( 200, $length ) );
1059 1071 }
1060 1072 }
1061 1073
1062 1074 /**
1063 - * Check if current page should be excluded from custom code injection
1075 + * Make a request-supplied Elementor icon array safe to render.
1076 + *
1077 + * The load-more handlers run on wp_ajax_nopriv_* and rebuild their settings from $_POST.
1078 + * map_deep() preserves nested arrays, so an icon array reaches
1079 + * Elementor\Icons_Manager::render_icon() exactly as the caller shaped it. The 'svg'
1080 + * library branch resolves to Svg::get_inline_svg( $value['id'] ), which reads an
1081 + * attachment by id with no capability or post-status check, so an icon coming from a
1082 + * request must never be allowed to select it.
1083 + *
1084 + * @param mixed $icon Icon array as supplied by the request.
1085 + * @return array|false Safe icon array, or false when nothing renderable remains.
1064 1086 */
1065 -if ( ! function_exists( 'upk_is_page_excluded' ) ) {
1066 - function upk_is_page_excluded() {
1067 - $excluded_pages = get_option( 'upk_excluded_pages', array() );
1068 -
1069 - if ( empty( $excluded_pages ) || ! is_array( $excluded_pages ) ) {
1087 +if ( ! function_exists( 'ultimate_post_kit_sanitize_request_icon' ) ) {
1088 + function ultimate_post_kit_sanitize_request_icon( $icon ) {
1089 +
1090 + if ( ! is_array( $icon ) || empty( $icon['library'] ) || ! is_scalar( $icon['library'] ) ) {
1070 1091 return false;
1071 1092 }
1072 1093
1073 - $current_id = 0;
1074 -
1075 - if ( is_home() && ! is_front_page() ) {
1076 - $current_id = get_option( 'page_for_posts' );
1077 - } elseif ( is_front_page() ) {
1078 - $current_id = get_option( 'page_on_front' );
1079 - } elseif ( is_singular() ) {
1080 - $current_id = get_queried_object_id();
1081 - } elseif ( is_category() || is_tag() || is_tax() ) {
1094 + $library = (string) $icon['library'];
1095 +
1096 + // Uploaded-SVG icons are addressed by attachment id; never resolve one from a request.
1097 + if ( 'svg' === $library ) {
1082 1098 return false;
1083 - } elseif ( is_author() ) {
1099 + }
1100 +
1101 + // Font icons are rendered as a CSS class, so the value must stay a scalar.
1102 + if ( ! isset( $icon['value'] ) || ! is_scalar( $icon['value'] ) ) {
1084 1103 return false;
1085 - } elseif ( is_archive() ) {
1086 - return false;
1087 1104 }
1088 1105
1089 - return in_array( $current_id, $excluded_pages );
1106 + return [
1107 + 'library' => $library,
1108 + 'value' => (string) $icon['value'],
1109 + ];
1090 1110 }
1091 1111 }