Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion config.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?php
// Plugin version.
if ( ! defined( 'ATBDP_VERSION' ) ) {
define( 'ATBDP_VERSION', '8.9.2' );
define( 'ATBDP_VERSION', '8.9.3' );
}
// Plugin Folder Path.
if ( ! defined( 'ATBDP_DIR' ) ) {
Expand Down
2 changes: 1 addition & 1 deletion directorist-base.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* Plugin Name: Directorist - Business Directory Solution
* Plugin URI: https://wpwax.com
* Description: A comprehensive solution to create professional looking directory site of any kind. Like Yelp, Foursquare, etc.
* Version: 8.9.2
* Version: 8.9.3
* Requires PHP: 7.4
* Author: wpWax
* Author URI: https://wpwax.com
Expand Down
8 changes: 8 additions & 0 deletions includes/classes/class-extension.php
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,14 @@ public static function get_default_extensions() {
'active' => true,
'item_id' => 370908,
],
'directorist-divi-integration' => [
'name' => 'Directorist Divi Integration',
'description' => __( 'Turn your directory into native Divi 5 modules and visually customize listing archives, search, categories, locations, single listings, and author profile pages.', 'directorist' ),
'link' => 'https://directorist.com/product/directorist-divi-integration/',
'thumbnail' => 'https://directorist.com/wp-content/uploads/edd/2026/06/Directorist-Divi_620x400.jpg',
'active' => true,
'item_id' => 371246,
],
'directorist-listing-importer' => [
'name' => 'Directorist Listing Importer',
'description' => __( 'Import Google Maps and feeds into Directorist automatically, effortlessly.', 'directorist' ),
Expand Down
85 changes: 80 additions & 5 deletions includes/classes/class-submission-controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,13 @@ protected static function validate_file_field( $field, &$posted_data ) {
}
}

$value = self::get_safe_submitted_filename( $value );
if ( ! $value ) {
$field->add_error( __( 'Invalid file name.', 'directorist' ) );

return;
}

try {
$upload_dir = wp_get_upload_dir();
$temp_dir = trailingslashit( $upload_dir['basedir'] ) . trailingslashit( directorist_get_temp_upload_dir() . DIRECTORY_SEPARATOR . date( 'nj' ) );
Expand All @@ -119,6 +126,12 @@ protected static function validate_file_field( $field, &$posted_data ) {
return;
}

if ( ! self::is_path_inside_directory( $filepath, $temp_dir ) ) {
$field->add_error( __( 'Invalid file path.', 'directorist' ) );

return;
}

$file_type = $field->get_file_types();

if ( in_array( $file_type, array( '', 'all_types', 'all' ), true ) ) {
Expand Down Expand Up @@ -165,6 +178,37 @@ protected static function validate_file_field( $field, &$posted_data ) {
}
}

protected static function get_safe_submitted_filename( $filename ) {
if ( ! is_string( $filename ) ) {
return false;
}

$filename = trim( $filename );

if ( '' === $filename || wp_basename( $filename ) !== $filename || preg_match( '#[\\\\/]#', $filename ) ) {
return false;
}

$sanitized_filename = sanitize_file_name( $filename );

if ( '' === $sanitized_filename || $sanitized_filename !== $filename ) {
return false;
}

return $filename;
}

protected static function is_path_inside_directory( $path, $directory ) {
$real_path = realpath( $path );
$real_directory = realpath( $directory );

if ( false === $real_path || false === $real_directory ) {
return false;
}

return 0 === strpos( $real_path, trailingslashit( $real_directory ) );
}

protected static function get_file_value( $field, &$posted_data ) {
$value = $field->get_value( $posted_data );

Expand All @@ -184,6 +228,11 @@ protected static function get_file_value( $field, &$posted_data ) {
}
}

$value = self::get_safe_submitted_filename( $value );
if ( ! $value ) {
return;
}

try {
$upload_dir = wp_get_upload_dir();
$temp_dir = trailingslashit( $upload_dir['basedir'] ) . trailingslashit( directorist_get_temp_upload_dir() . DIRECTORY_SEPARATOR . date( 'nj' ) );
Expand All @@ -202,10 +251,18 @@ protected static function get_file_value( $field, &$posted_data ) {
return;
}

if ( ! self::is_path_inside_directory( $filepath, $temp_dir ) ) {
return;
}

if ( file_exists( $target_dir . $value ) ) {
$value = wp_unique_filename( $target_dir, $value );
}

if ( ! self::is_path_inside_directory( $target_dir, $upload_dir['basedir'] ) ) {
return;
}

rename( $filepath, $target_dir . $value );

return trailingslashit( $upload_dir['baseurl'] ) . trailingslashit( 'atbdp_temp' ) . $value;
Expand Down Expand Up @@ -584,10 +641,11 @@ public static function submit( $posted_data, $from = 'web' ) {

static::cache_selected_categories( $directory_id, $posted_data );

$error = new WP_Error();
$tax_data = array();
$meta_data = array();
$listing_data = array(
$error = new WP_Error();
$tax_data = array();
$meta_data = array();
$api_file_fields = array();
$listing_data = array(
'post_type' => ATBDP_POST_TYPE
);

Expand Down Expand Up @@ -667,14 +725,18 @@ public static function submit( $posted_data, $from = 'web' ) {

// Exception from the web version.
if ( self::$from === 'api' && $field->type === 'file' ) {
$meta_data[ '_' . $field->get_key() ] = self::get_file_value( $field, $posted_data );
$api_file_fields[] = $field;
}
}

if ( $error->has_errors() ) {
return $error;
}

foreach ( $api_file_fields as $field ) {
$meta_data[ '_' . $field->get_key() ] = self::get_file_value( $field, $posted_data );
}

// Terms & conditions and privacy policy have been merged in v8.
if ( ! empty( $posted_data['t_c_check'] ) || ! empty( $posted_data['privacy_policy'] ) ) {
$meta_data['_t_c_check'] = true;
Expand Down Expand Up @@ -860,16 +922,29 @@ public static function upload_images( $listing_id, $posted_data ) {
continue;
}

$image = self::get_safe_submitted_filename( $image );
if ( ! $image ) {
continue;
}

$filepath = $temp_dir . $image;

if ( is_dir( $filepath ) || ! file_exists( $filepath ) ) {
continue;
}

if ( ! self::is_path_inside_directory( $filepath, $temp_dir ) ) {
continue;
}

if ( file_exists( $target_dir . $image ) ) {
$image = wp_unique_filename( $target_dir, $image );
}

if ( ! self::is_path_inside_directory( $target_dir, $upload_dir['basedir'] ) ) {
continue;
}

rename( $filepath, $target_dir . $image );

$mime = wp_check_filetype( $image );
Expand Down
7 changes: 6 additions & 1 deletion readme.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Tags: business directory, listings, classifieds, directory plugin, directory
Requires at least: 4.6
Tested up to: 7.0
Requires PHP: 7.0
Stable tag: 8.9.2
Stable tag: 8.9.3
License: GPLv3
License URI: https://www.gnu.org/licenses/gpl-3.0.html

Expand Down Expand Up @@ -300,6 +300,11 @@ Directorist comes with an AI-powered directory builder. Use the Create with AI o

== Changelog ==

= 8.9.3 - Aug 9, 2026 =

**Security**
- Prevent path traversal in REST listing submission file and image upload handling.

= 8.9.2 - Jul 27, 2026 =

**Fixed**
Expand Down
Loading