PluginProbe
King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder / 51.1.87
King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder v51.1.87
51.1.87 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 All 41 releases
← All changes | includes/helpers/Grid/Grid_Ajax_Security.php +278 -1 51.1.76 → 51.1.87 View file →
@@ -29,9 +29,9 @@
29 29 * @return array<int, string> Allowed effect slugs.
30 30 */
31 31 public static function get_allowed_image_effects(): array
32 32 {
33 - return ['none', 'pro-zi', 'pro-zo', 'grayscale-in', 'pro-go', 'blur-in', 'pro-bo', 'slide'];
33 + return ['none', 'pro-zi', 'pro-zo', 'zoom-in', 'zoom-out', 'grayscale-in', 'grayscale-out', 'pro-go', 'blur-in', 'blur-out', 'pro-bo', 'slide'];
34 34 }
35 35
36 36 /**
37 37 * Returns allowed image effect direction values.
@@ -141,6 +141,283 @@
141 141 */
142 142 public static function sanitize_yes_no_switcher($value): string
143 143 {
144 144 return 'yes' === $value ? 'yes' : '';
145 + }
146 +
147 + /**
148 + * Returns allowed HTML tags for grid titles.
149 + *
150 + * @return array<int, string> Allowed tag names.
151 + */
152 + public static function get_allowed_html_tags(): array
153 + {
154 + return ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'div', 'span', 'p'];
155 + }
156 +
157 + /**
158 + * Sanitizes an HTML tag name against the grid allowlist.
159 + *
160 + * @param mixed $value Raw tag name.
161 + * @return string Allowed tag name.
162 + */
163 + public static function sanitize_html_tag($value): string
164 + {
165 + $value = strtolower(sanitize_key((string) $value));
166 +
167 + return in_array($value, self::get_allowed_html_tags(), true) ? $value : 'h2';
168 + }
169 +
170 + /**
171 + * Sanitizes a CSS class token.
172 + *
173 + * @param mixed $value Raw class token.
174 + * @return string Safe class token.
175 + */
176 + public static function sanitize_class_token($value): string
177 + {
178 + return sanitize_html_class((string) $value);
179 + }
180 +
181 + /**
182 + * Sanitizes a query source / post type slug.
183 + *
184 + * @param mixed $value Raw query source.
185 + * @return string Allowed query source.
186 + */
187 + public static function sanitize_query_source($value): string
188 + {
189 + $value = sanitize_key((string) $value);
190 + $allowed = array_merge(
191 + ['post', 'page', 'product', 'attachment', 'current', 'related', 'manual', 'dynamic'],
192 + array_keys(get_post_types(['public' => true], 'names'))
193 + );
194 +
195 + return in_array($value, $allowed, true) ? $value : 'post';
196 + }
197 +
198 + /**
199 + * Returns sanitized grid settings from the current AJAX request.
200 + *
201 + * @return array<string, mixed> Sanitized settings array.
202 + */
203 + public static function get_posted_grid_settings(): array
204 + {
205 + $settings = isset($_POST['grid_settings']) ? wp_unslash($_POST['grid_settings']) : [];
206 +
207 + if (!is_array($settings)) {
208 + return [];
209 + }
210 +
211 + return self::sanitize_grid_settings($settings);
212 + }
213 +
214 + /**
215 + * Sanitizes grid settings that may be reflected into HTML.
216 + *
217 + * @param array<string, mixed> $settings Raw grid settings.
218 + * @return array<string, mixed> Sanitized grid settings.
219 + */
220 + public static function sanitize_grid_settings(array $settings): array
221 + {
222 + $class_keys = [
223 + 'overlay_animation',
224 + 'overlay_animation_size',
225 + 'overlay_animation_timing',
226 + 'image_effects',
227 + 'image_effects_size',
228 + 'image_effects_direction',
229 + 'image_effects_animation_timing',
230 + 'title_pointer',
231 + 'title_pointer_animation',
232 + 'tax1_pointer',
233 + 'tax1_pointer_animation',
234 + 'tax2_pointer',
235 + 'tax2_pointer_animation',
236 + 'read_more_animation',
237 + 'layout_select',
238 + 'pagination_type',
239 + 'element_separator_style',
240 + 'element_tax_style',
241 + 'element_custom_field_style',
242 + 'overlay_post_link',
243 + ];
244 +
245 + foreach ($class_keys as $key) {
246 + if (isset($settings[$key]) && is_scalar($settings[$key])) {
247 + $settings[$key] = self::sanitize_class_token($settings[$key]);
248 + }
249 + }
250 +
251 + if (isset($settings['overlay_animation'])) {
252 + $settings['overlay_animation'] = self::sanitize_animation($settings['overlay_animation']);
253 + }
254 + if (isset($settings['overlay_animation_size'])) {
255 + $settings['overlay_animation_size'] = self::sanitize_animation_size($settings['overlay_animation_size']);
256 + }
257 + if (isset($settings['overlay_animation_timing'])) {
258 + $settings['overlay_animation_timing'] = self::sanitize_animation_timing($settings['overlay_animation_timing']);
259 + }
260 + if (isset($settings['overlay_animation_tr'])) {
261 + $settings['overlay_animation_tr'] = self::sanitize_yes_no_switcher($settings['overlay_animation_tr']);
262 + }
263 + if (isset($settings['image_effects'])) {
264 + $settings['image_effects'] = self::sanitize_image_effect($settings['image_effects']);
265 + }
266 + if (isset($settings['image_effects_size'])) {
267 + $settings['image_effects_size'] = self::sanitize_image_effect_size($settings['image_effects_size']);
268 + }
269 + if (isset($settings['image_effects_direction'])) {
270 + $settings['image_effects_direction'] = self::sanitize_image_effect_direction($settings['image_effects_direction']);
271 + }
272 + if (isset($settings['image_effects_animation_timing'])) {
273 + $settings['image_effects_animation_timing'] = self::sanitize_animation_timing($settings['image_effects_animation_timing']);
274 + }
275 + if (isset($settings['element_title_tag'])) {
276 + $settings['element_title_tag'] = self::sanitize_html_tag($settings['element_title_tag']);
277 + }
278 + if (isset($settings['query_source'])) {
279 + $settings['query_source'] = self::sanitize_query_source($settings['query_source']);
280 + }
281 + if (isset($settings['query_tax_selection'])) {
282 + $settings['query_tax_selection'] = sanitize_key((string) $settings['query_tax_selection']);
283 + }
284 + if (isset($settings['order_posts'])) {
285 + $settings['order_posts'] = sanitize_key((string) $settings['order_posts']);
286 + }
287 + if (isset($settings['order_direction'])) {
288 + $settings['order_direction'] = in_array(strtoupper((string) $settings['order_direction']), ['ASC', 'DESC'], true)
289 + ? strtoupper((string) $settings['order_direction'])
290 + : 'DESC';
291 + }
292 + if (isset($settings['query_randomize'])) {
293 + $settings['query_randomize'] = sanitize_key((string) $settings['query_randomize']);
294 + }
295 + foreach (['query_offset', 'query_posts_per_page', 'query_slides_to_show'] as $int_key) {
296 + if (isset($settings[$int_key])) {
297 + $settings[$int_key] = absint($settings[$int_key]);
298 + }
299 + }
300 + if (isset($settings['query_author']) && is_array($settings['query_author'])) {
301 + $settings['query_author'] = array_map('absint', $settings['query_author']);
302 + }
303 + foreach ($settings as $key => $value) {
304 + if (!is_string($key) || !is_array($value)) {
305 + continue;
306 + }
307 + if (0 === strpos($key, 'query_taxonomy_') || 0 === strpos($key, 'query_exclude_')) {
308 + $settings[$key] = array_map('absint', $value);
309 + }
310 + }
311 + if (isset($settings['tax1_custom_color_switcher'])) {
312 + $settings['tax1_custom_color_switcher'] = self::sanitize_yes_no_switcher($settings['tax1_custom_color_switcher']);
313 + }
314 + if (isset($settings['tax1_custom_color_field_text'])) {
315 + $settings['tax1_custom_color_field_text'] = sanitize_key((string) $settings['tax1_custom_color_field_text']);
316 + }
317 + if (isset($settings['tax1_custom_color_field_bg'])) {
318 + $settings['tax1_custom_color_field_bg'] = sanitize_key((string) $settings['tax1_custom_color_field_bg']);
319 + }
320 + if (isset($settings['open_links_in_new_tab'])) {
321 + $settings['open_links_in_new_tab'] = self::sanitize_yes_no_switcher($settings['open_links_in_new_tab']);
322 + }
323 + if (isset($settings['secondary_img_on_hover'])) {
324 + $settings['secondary_img_on_hover'] = self::sanitize_yes_no_switcher($settings['secondary_img_on_hover']);
325 + }
326 + if (isset($settings['grid_lazy_loading'])) {
327 + $settings['grid_lazy_loading'] = self::sanitize_yes_no_switcher($settings['grid_lazy_loading']);
328 + }
329 +
330 + if (!empty($settings['overlay_image']) && is_array($settings['overlay_image'])) {
331 + $settings['overlay_image']['url'] = esc_url_raw($settings['overlay_image']['url'] ?? '');
332 + $settings['overlay_image']['alt'] = sanitize_text_field($settings['overlay_image']['alt'] ?? '');
333 + }
334 +
335 + if (!empty($settings['grid_elements']) && is_array($settings['grid_elements'])) {
336 + foreach ($settings['grid_elements'] as $index => $element) {
337 + if (!is_array($element)) {
338 + unset($settings['grid_elements'][$index]);
339 + continue;
340 + }
341 + $settings['grid_elements'][$index] = self::sanitize_grid_element($element);
342 + }
343 + }
344 +
345 + return $settings;
346 + }
347 +
348 + /**
349 + * Sanitizes one grid element repeater row.
350 + *
351 + * @param array<string, mixed> $element Raw element settings.
352 + * @return array<string, mixed> Sanitized element settings.
353 + */
354 + public static function sanitize_grid_element(array $element): array
355 + {
356 + foreach (['element_select', '_id', 'element_display', 'element_align_hr', 'element_align_vr', 'element_location'] as $key) {
357 + if (isset($element[$key]) && is_scalar($element[$key])) {
358 + $element[$key] = self::sanitize_class_token($element[$key]);
359 + }
360 + }
361 +
362 + if (isset($element['element_title_tag'])) {
363 + $element['element_title_tag'] = self::sanitize_html_tag($element['element_title_tag']);
364 + }
365 + if (isset($element['element_animation'])) {
366 + $element['element_animation'] = self::sanitize_animation($element['element_animation']);
367 + }
368 + if (isset($element['element_animation_size'])) {
369 + $element['element_animation_size'] = self::sanitize_animation_size($element['element_animation_size']);
370 + }
371 + if (isset($element['element_animation_timing'])) {
372 + $element['element_animation_timing'] = self::sanitize_animation_timing($element['element_animation_timing']);
373 + }
374 + if (isset($element['element_animation_tr'])) {
375 + $element['element_animation_tr'] = self::sanitize_yes_no_switcher($element['element_animation_tr']);
376 + }
377 + if (isset($element['element_separator_style'])) {
378 + $element['element_separator_style'] = self::sanitize_class_token($element['element_separator_style']);
379 + }
380 + if (isset($element['element_tax_style'])) {
381 + $element['element_tax_style'] = self::sanitize_class_token($element['element_tax_style']);
382 + }
383 + if (isset($element['element_read_more_text'])) {
384 + $element['element_read_more_text'] = sanitize_text_field((string) $element['element_read_more_text']);
385 + }
386 + if (isset($element['element_extra_text'])) {
387 + $element['element_extra_text'] = sanitize_text_field((string) $element['element_extra_text']);
388 + }
389 + if (isset($element['element_tax_sep'])) {
390 + $element['element_tax_sep'] = sanitize_text_field((string) $element['element_tax_sep']);
391 + }
392 +
393 + return $element;
394 + }
395 +
396 + /**
397 + * Sanitizes a CSS color value used in generated style tags.
398 + *
399 + * @param mixed $value Raw color value.
400 + * @return string Safe color string or an empty string.
401 + */
402 + public static function sanitize_css_color($value): string
403 + {
404 + $value = trim((string) $value);
405 + if ('' === $value) {
406 + return '';
407 + }
408 +
409 + if (preg_match('/^#([A-Fa-f0-9]{3}|[A-Fa-f0-9]{6}|[A-Fa-f0-9]{8})$/', $value)) {
410 + return $value;
411 + }
412 +
413 + if (preg_match('/^(rgb|rgba|hsl|hsla)\(\s*[0-9.%,\s\/]+\s*\)$/i', $value)) {
414 + return $value;
415 + }
416 +
417 + if (preg_match('/^[a-zA-Z]+$/', $value)) {
418 + return sanitize_key($value);
419 + }
420 +
421 + return '';
145 422 }
146 423 }