PluginProbe
King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder / 51.1.83
King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder v51.1.83
51.1.86 51.1.84 51.1.85 51.1.83 51.1.82 51.1.81 51.1.79 51.1.78 51.1.77 51.1.76 51.1.74 51.1.75 51.1.65 51.1.64 51.1.63 trunk 51.1.14 51.1.2 51.1.35 51.1.36 51.1.37 51.1.38 51.1.39 51.1.44 51.1.45 All 40 releases
← All changes | includes/controls/Ajax_Select2/Ajax_Select2_API.php +61 -23 51.1.39 → 51.1.83 View file →
@@ -11,8 +11,18 @@
11 11 }
12 12
13 13 class Ajax_Select2_API
14 14 {
15 + private const ALLOWED_ACTIONS = [
16 + 'getElementorTemplates',
17 + 'getPostsByPostType',
18 + 'getPostTypeTaxonomies',
19 + 'getCustomMetaKeys',
20 + 'getUsers',
21 + 'getTaxonomies',
22 + 'getCustomMetaKeysProduct',
23 + ];
24 +
15 25 public function __construct()
16 26 {
17 27 $this->init();
18 28 }
@@ -25,17 +35,31 @@
25 35 '/(?P<action>\w+)/',
26 36 [
27 37 'methods' => 'GET',
28 38 'callback' => [$this, 'callback'],
29 - 'permission_callback' => '__return_true'
39 + 'permission_callback' => [$this, 'canAccess'],
30 40 ]
31 41 );
32 42 });
33 43 }
34 44
45 + public function canAccess($request): bool
46 + {
47 + $action = sanitize_key((string)($request['action'] ?? ''));
48 + $allowed_actions = array_map('sanitize_key', self::ALLOWED_ACTIONS);
49 +
50 + return current_user_can('edit_posts') && in_array($action, $allowed_actions, true);
51 + }
52 +
35 53 public function callback($request)
36 54 {
37 - return $this->{$request['action']}($request);
55 + $action = (string)($request['action'] ?? '');
56 +
57 + if (!in_array($action, self::ALLOWED_ACTIONS, true) || !is_callable([$this, $action])) {
58 + return new \WP_Error('king_addons_invalid_ajaxselect2_action', esc_html__('Invalid request.', 'king-addons'), ['status' => 400]);
59 + }
60 +
61 + return $this->{$action}($request);
38 62 }
39 63
40 64 public function getElementorTemplates($request): ?array
41 65 {
@@ -48,10 +72,20 @@
48 72 'meta_value' => ['page', 'section', 'container'],
49 73 'numberposts' => 10
50 74 ];
51 75
76 + // Load specific templates by IDs (for pre-populating selected values)
77 + if (isset($request['ids']) && !empty($request['ids'])) {
78 + $ids = array_filter(array_map('intval', explode(',', $request['ids'])));
79 + if (!empty($ids)) {
80 + $args['post__in'] = $ids;
81 + $args['numberposts'] = -1;
82 + unset($args['meta_key'], $args['meta_value']); // Allow any template type when loading by ID
83 + }
84 + }
85 +
52 86 if (isset($request['s'])) {
53 - $args['s'] = $request['s'];
87 + $args['s'] = sanitize_text_field((string)$request['s']);
54 88 }
55 89
56 90 $options = [];
57 91 $the_query = new WP_Query($args);
@@ -60,9 +94,9 @@
60 94 while ($the_query->have_posts()) {
61 95 $the_query->the_post();
62 96 $options[] = [
63 97 'id' => get_the_ID(),
64 - 'text' => html_entity_decode(get_the_title()),
98 + 'text' => wp_strip_all_tags(html_entity_decode(get_the_title())),
65 99 ];
66 100 }
67 101 }
68 102
@@ -74,9 +108,9 @@
74 108 public function getPostsByPostType($request): ?array
75 109 {
76 110 if (!current_user_can('edit_posts')) return null;
77 111
78 - $post_type = $request['query_slug'] ?? '';
112 + $post_type = sanitize_key((string)($request['query_slug'] ?? ''));
79 113
80 114 $args = [
81 115 'post_type' => $post_type,
82 116 'post_status' => $post_type === 'attachment' ? 'any' : 'publish',
@@ -83,13 +117,13 @@
83 117 'posts_per_page' => 15,
84 118 ];
85 119
86 120 if (isset($request['ids'])) {
87 - $args['post__in'] = explode(',', $request['ids']);
121 + $args['post__in'] = array_filter(array_map('intval', explode(',', (string)$request['ids'])));
88 122 }
89 123
90 124 if (isset($request['s'])) {
91 - $args['s'] = $request['s'];
125 + $args['s'] = sanitize_text_field((string)$request['s']);
92 126 }
93 127
94 128 $query = new WP_Query($args);
95 129 $options = [];
@@ -98,9 +132,9 @@
98 132 while ($query->have_posts()) {
99 133 $query->the_post();
100 134 $options[] = [
101 135 'id' => get_the_ID(),
102 - 'text' => html_entity_decode(get_the_title()),
136 + 'text' => wp_strip_all_tags(html_entity_decode(get_the_title())),
103 137 ];
104 138 }
105 139 }
106 140
@@ -111,9 +145,9 @@
111 145 public function getPostTypeTaxonomies($request): ?array
112 146 {
113 147 if (!current_user_can('edit_posts')) return null;
114 148
115 - $post_type = $request['query_slug'] ?? '';
149 + $post_type = sanitize_key((string)($request['query_slug'] ?? ''));
116 150
117 151 $taxonomies = get_object_taxonomies($post_type, 'objects');
118 152 $options = [];
119 153
@@ -119,14 +153,14 @@
119 153
120 154 if ($taxonomies) {
121 155 foreach ($taxonomies as $taxonomy) {
122 156
123 - if (isset($request['s']) && stripos($taxonomy->label, $request['s']) === false) {
157 + if (isset($request['s']) && stripos($taxonomy->label, sanitize_text_field((string)$request['s'])) === false) {
124 158 continue;
125 159 }
126 160
127 161 if (isset($request['ids'])) {
128 - $ids = explode(',', $request['ids'] ?: '99999999');
162 + $ids = array_map('sanitize_key', explode(',', (string)($request['ids'] ?: '99999999')));
129 163 if (!in_array($taxonomy->name, $ids)) {
130 164 continue;
131 165 }
132 166 }
@@ -132,9 +166,9 @@
132 166 }
133 167
134 168 $options[] = [
135 169 'id' => $taxonomy->name,
136 - 'text' => $taxonomy->label,
170 + 'text' => wp_strip_all_tags($taxonomy->label),
137 171 ];
138 172 }
139 173 }
140 174
@@ -167,12 +201,12 @@
167 201 )
168 202 );
169 203
170 204 $filtered = array_filter($mergedKeys, function ($key) use ($request) {
171 - return !isset($request['s']) || strpos($key, $request['s']) !== false;
205 + return !isset($request['s']) || strpos($key, sanitize_text_field((string)$request['s'])) !== false;
172 206 });
173 207
174 - $options = array_map(fn($k) => ['id' => $k, 'text' => $k], $filtered);
208 + $options = array_map(fn($k) => ['id' => $k, 'text' => wp_strip_all_tags($k)], $filtered);
175 209
176 210 return ['results' => $options];
177 211 }
178 212
@@ -189,15 +223,15 @@
189 223 $args['include'] = array_map('intval', explode(',', $request['ids']));
190 224 }
191 225
192 226 if (!empty($request['s'])) {
193 - $args['search'] = '*' . $request['s'] . '*';
227 + $args['search'] = '*' . sanitize_text_field((string)$request['s']) . '*';
194 228 }
195 229
196 230 $results = (new WP_User_Query($args))->get_results();
197 231
198 232 $options = array_map(
199 - fn($user) => ['id' => $user->ID, 'text' => $user->display_name],
233 + fn($user) => ['id' => $user->ID, 'text' => wp_strip_all_tags($user->display_name)],
200 234 $results ?: []
201 235 );
202 236
203 237 wp_reset_postdata();
@@ -208,9 +242,9 @@
208 242 public function getTaxonomies($request)
209 243 {
210 244 if (!current_user_can('edit_posts')) return null;
211 245
212 - $tax = $request['query_slug'] ?? '';
246 + $tax = sanitize_key((string)($request['query_slug'] ?? ''));
213 247 $args = [
214 248 'orderby' => 'name',
215 249 'order' => 'DESC',
216 250 'hide_empty' => true,
@@ -217,20 +251,24 @@
217 251 'number' => 10,
218 252 ];
219 253
220 254 if (isset($request['ids'])) {
221 - $args['include'] = explode(',', $request['ids'] ?: '99999999');
255 + $args['include'] = array_filter(array_map('intval', explode(',', (string)($request['ids'] ?: '99999999'))));
222 256 }
223 257
224 258 if (!empty($request['s'])) {
225 - $args['name__like'] = $request['s'];
259 + $args['name__like'] = sanitize_text_field((string)$request['s']);
226 260 }
227 261
228 262 $terms = get_terms($tax, $args);
263 + if (is_wp_error($terms)) {
264 + return ['results' => []];
265 + }
266 +
229 267 $options = array_map(function ($term) {
230 268 return [
231 269 'id' => $term->term_id,
232 - 'text' => $term->name,
270 + 'text' => wp_strip_all_tags($term->name),
233 271 ];
234 272 }, $terms);
235 273
236 274 wp_reset_postdata();
@@ -261,12 +299,12 @@
261 299 }
262 300
263 301 $merged_meta_keys = array_values(array_unique($merged_meta_keys));
264 302 foreach ($merged_meta_keys as $key) {
265 - if (empty($request['s']) || false !== strpos($key, $request['s'])) {
303 + if (empty($request['s']) || false !== strpos($key, sanitize_text_field((string)$request['s']))) {
266 304 $options[] = [
267 305 'id' => $key,
268 - 'text' => $key,
306 + 'text' => wp_strip_all_tags($key),
269 307 ];
270 308 }
271 309 }
272 310
@@ -299,9 +337,9 @@
299 337
300 338 foreach (array_keys($product_attributes) as $attribute_name) {
301 339 $options[] = [
302 340 'id' => $attribute_name,
303 - 'text' => $attribute_name,
341 + 'text' => wp_strip_all_tags($attribute_name),
304 342 ];
305 343 }
306 344
307 345 return [