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 | modules/alex-grid/module.php +26 -41 4.2.1 → 4.5.6 View file →
@@ -32,11 +32,17 @@
32 32 return $widgets;
33 33 }
34 34
35 35 public function callback_ajax_loadmore_posts() {
36 + // Verify the front-end nonce (sent by UltimatePostKitConfig.nonce) before
37 + // processing this public load-more request.
38 + if ( ! check_ajax_referer( 'upk-site', 'nonce', false ) ) {
39 + wp_send_json_error( array( 'message' => esc_html__( 'Security check failed.', 'ultimate-post-kit' ) ), 403 );
40 + }
36 41
42 +
37 43 // Security: Verify nonce
38 - if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( $_POST['nonce'], 'upk-site' ) ) {
44 + if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['nonce'] ) ), 'upk-site' ) ) {
39 45 wp_send_json_error( [ 'message' => esc_html__( 'Security verification failed', 'ultimate-post-kit' ) ], 403 );
40 46 wp_die();
41 47 }
42 48
@@ -45,50 +51,33 @@
45 51 if ( isset( $_POST['settings'] ) && is_array( $_POST['settings'] ) ) {
46 52 $settings = map_deep( wp_unslash( $_POST['settings'] ), 'sanitize_text_field' );
47 53 }
48 54
49 - $post_type = $settings['post_source'] ?? 'post';
50 -
51 - // Security: Enforce query limits to prevent DoS
52 - $per_page = isset( $_POST['per_page'] ) ? absint( $_POST['per_page'] ) : 6;
53 - $per_page = min( $per_page, 50 ); // Maximum 50 posts per request
54 - $offset = isset( $_POST['offset'] ) ? absint( $_POST['offset'] ) : 0;
55 - $offset = min( $offset, 1000 ); // Maximum offset of 1000
56 -
57 - // Security: Whitelist allowed post types
58 - $allowed_post_types = [ 'post', 'page' ];
59 - $allowed_post_types = apply_filters( 'upk_alex_grid_allowed_post_types', $allowed_post_types );
60 - $post_type = in_array( $post_type, $allowed_post_types, true ) ? $post_type : 'post';
61 -
62 - // Security: Whitelist orderby values
63 - $allowed_orderby = [ 'date', 'title', 'modified', 'rand', 'comment_count', 'menu_order' ];
64 - $posts_orderby = isset( $settings['posts_orderby'] ) && in_array( $settings['posts_orderby'], $allowed_orderby, true ) ? $settings['posts_orderby'] : 'date';
65 -
66 - // Security: Whitelist order values
67 - $posts_order = isset( $settings['posts_order'] ) && in_array( strtoupper( $settings['posts_order'] ), [ 'ASC', 'DESC' ], true ) ? strtoupper( $settings['posts_order'] ) : 'DESC';
68 -
69 - $settings = array_merge(
55 + // NOTE: the request-derived values below are NOT the ones the query is built from.
56 + // query_args() is declared without parameters and re-reads $_POST['settings']
57 + // itself, so anything merged into $settings here is discarded. The query is
58 + // constrained inside query_args(): post_status is pinned to 'publish', per_page
59 + // is clamped to 1..100, and post_type is restricted to publicly visible post
60 + // types by ultimate_post_kit_sanitize_public_post_type(). The defaults are kept
61 + // only so the render loop below has the keys it expects.
62 + $settings = array_merge(
70 63 [
71 - 'posts_source' => $post_type,
72 - 'posts_orderby' => $posts_orderby,
73 - 'posts_order' => $posts_order,
64 + 'posts_source' => 'post',
65 + 'posts_orderby' => 'date',
66 + 'posts_order' => 'DESC',
74 67 'posts_ignore_sticky_posts' => 'no',
75 68 'posts_only_with_featured_image' => 'no',
76 69 'posts_select_date' => '',
77 70 'posts_exclude_by' => [],
78 71 'posts_include_by' => [],
79 - 'posts_per_page' => $per_page,
80 - 'posts_offset' => $offset,
81 72 ],
82 73 $settings
83 74 );
84 -
75 +
76 + // Fill display flags the request may have omitted (see trait) before the render loop reads them.
77 + $settings = array_merge( $this->loadmore_display_defaults(), $settings );
78 +
85 79 $ajaxposts = $this->query_args( $settings );
86 -
87 - // Security: Override post_status to ensure only published posts are shown
88 - if ( ! current_user_can( 'edit_posts' ) ) {
89 - $ajaxposts->query_vars['post_status'] = 'publish';
90 - }
91 80
92 81 ob_start();
93 82 $found_posts = false;
94 83
@@ -100,9 +89,9 @@
100 89 $title = get_the_title();
101 90 $post_link = esc_url(get_permalink());
102 91 $image_src = wp_get_attachment_image_url(get_post_thumbnail_id(), 'large');
103 92 $image_src = $image_src ? esc_url($image_src) : esc_url(\Elementor\Utils::get_placeholder_image_src());
104 - $category = wp_kses_post(upk_get_category($post_type));
93 + $category = wp_kses_post(upk_get_category($settings['posts_source'] ?? 'post'));
105 94 $author_url = esc_url(get_author_posts_url(get_the_author_meta('ID')));
106 95 $author_name = esc_html(get_the_author());
107 96 $title_tag = Utils::get_valid_html_tag($settings['title_tags'] );
108 97
@@ -107,13 +96,9 @@
107 96 $title_tag = Utils::get_valid_html_tag($settings['title_tags'] );
108 97
109 98 $meta_separator = isset( $settings['meta_separator'] ) ? $settings['meta_separator'] : '|';
110 99
111 - $onclick = '';
112 - if (!empty($settings['global_link']) && $settings['global_link'] === 'yes') {
113 - $onclick = ' onclick="window.open(\'' . $post_link . '\', \'_self\')"';
114 - }
115 -
100 +
116 101 $date = '';
117 102 if (!empty($settings['human_diff_time']) && $settings['human_diff_time'] === 'yes') {
118 103 $date = ultimate_post_kit_post_time_diff(($settings['human_diff_time_short'] === 'yes') ? 'short' : '');
119 104 } else {
@@ -158,9 +143,9 @@
158 143 <?php endif; ?>
159 144
160 145 <div class="upk-flex upk-flex-middle upk-date-reading-wrap">
161 146 <?php if ( $settings['show_date'] === 'yes' ) : ?>
162 - <div class="upk-date"><?php echo $date; ?></div>
147 + <div class="upk-date"><?php echo esc_html( $date ); ?></div>
163 148 <?php if ( $settings['show_time'] === 'yes' ) : ?>
164 149 <div class="upk-post-time" data-separator="<?php echo esc_attr( $meta_separator ); ?>">
165 150 <i class="upk-icon-clock" aria-hidden="true"></i><?php echo esc_html( get_the_time() ); ?>
166 151 </div>
@@ -168,9 +153,9 @@
168 153 <?php endif; ?>
169 154
170 155 <?php if ( function_exists( '_is_upk_pro_activated' ) && _is_upk_pro_activated() && $settings['show_reading_time'] === 'yes' ) : ?>
171 156 <div class="upk-reading-time" data-separator="<?php echo esc_attr( $meta_separator ); ?>">
172 - <?php echo ultimate_post_kit_reading_time( get_the_content(), $settings['avg_reading_speed'], $settings['hide_seconds'] ?? 'no', $settings['hide_minutes'] ?? 'no' ); ?>
157 + <?php echo wp_kses_post( ultimate_post_kit_reading_time( get_the_content(), $settings['avg_reading_speed'], $settings['hide_seconds'] ?? 'no', $settings['hide_minutes'] ?? 'no' ) ); ?>
173 158 </div>
174 159 <?php endif; ?>
175 160 </div>
176 161 </div>