@@ -356,7 +356,7 @@ function sse_create_index_file( $export_dir ) {
356356 if ( ! $ wp_filesystem ) {
357357 require_once ABSPATH . 'wp-admin/includes/file.php ' ; // phpcs:ignore WordPressVIPMinimum.Files.IncludingFile.UsingVariable -- WordPress core filesystem API
358358 if ( ! WP_Filesystem () ) {
359- sse_log ('Failed to initialize WordPress filesystem API ' , 'error ' );
359+ sse_log ( 'Failed to initialize WordPress filesystem API ' , 'error ' );
360360 return ;
361361 }
362362 }
@@ -795,7 +795,7 @@ function sse_safely_delete_file( $filepath ) {
795795
796796/**
797797 * Validates a file path for directory traversal attempts.
798- *
798+ *
799799 * @param string $normalized_file_path The normalized file path to check.
800800 * @return bool True if path is safe, false if contains traversal patterns.
801801 */
@@ -912,19 +912,19 @@ function sse_construct_final_file_path( $parent_dir, $filename, $upload_real_pat
912912function sse_get_upload_directory_info () {
913913 $ upload_dir = wp_upload_dir ();
914914 if ( ! isset ( $ upload_dir ['basedir ' ] ) || empty ( $ upload_dir ['basedir ' ] ) ) {
915- sse_log ('Could not determine WordPress upload directory for validation ' , 'error ' );
915+ sse_log ( 'Could not determine WordPress upload directory for validation ' , 'error ' );
916916 return false ;
917917 }
918-
918+
919919 $ wp_upload_dir = realpath ( $ upload_dir ['basedir ' ] );
920- if ( $ wp_upload_dir === false ) {
921- sse_log ('Could not resolve WordPress upload directory real path ' , 'error ' );
920+ if ( false === $ wp_upload_dir ) {
921+ sse_log ( 'Could not resolve WordPress upload directory real path ' , 'error ' );
922922 return false ;
923923 }
924924
925925 return array (
926- 'basedir ' => $ upload_dir ['basedir ' ],
927- 'realpath ' => $ wp_upload_dir
926+ 'basedir ' => $ upload_dir ['basedir ' ],
927+ 'realpath ' => $ wp_upload_dir,
928928 );
929929}
930930
@@ -936,18 +936,18 @@ function sse_get_upload_directory_info() {
936936 * @return bool True if safe, false otherwise.
937937 */
938938function sse_validate_parent_directory_safety ( $ parent_dir , $ upload_dir ) {
939- // Pre-validate that parent directory path looks safe
940- if (strpos ($ parent_dir , '.. ' ) !== false || strpos ($ parent_dir , 'wp-config ' ) !== false ) {
941- sse_log ('Rejected unsafe parent directory path: ' . $ parent_dir , 'security ' );
939+ // Pre-validate that parent directory path looks safe.
940+ if ( strpos ( $ parent_dir , '.. ' ) !== false || strpos ( $ parent_dir , 'wp-config ' ) !== false ) {
941+ sse_log ( 'Rejected unsafe parent directory path: ' . $ parent_dir , 'security ' );
942942 return false ;
943943 }
944-
945- // Ensure parent directory is within WordPress upload directory
946- $ norm_parent_dir = wp_normalize_path ($ parent_dir );
947- $ norm_upload_dir = wp_normalize_path ($ upload_dir );
948-
949- if (strpos ($ norm_parent_dir , $ norm_upload_dir ) !== 0 ) {
950- sse_log ('Parent directory not within WordPress upload directory: ' . $ parent_dir , 'security ' );
944+
945+ // Ensure parent directory is within WordPress upload directory.
946+ $ norm_parent_dir = wp_normalize_path ( $ parent_dir );
947+ $ norm_upload_dir = wp_normalize_path ( $ upload_dir );
948+
949+ if ( strpos ( $ norm_parent_dir , $ norm_upload_dir ) !== 0 ) {
950+ sse_log ( 'Parent directory not within WordPress upload directory: ' . $ parent_dir , 'security ' );
951951 return false ;
952952 }
953953
@@ -962,33 +962,33 @@ function sse_validate_parent_directory_safety( $parent_dir, $upload_dir ) {
962962 * @return string|false Real parent directory path or false on failure.
963963 */
964964function sse_resolve_parent_directory ( $ parent_dir , $ upload_dir ) {
965- // Normalize and validate upload directory first
966- $ norm_upload_dir = wp_normalize_path ($ upload_dir );
965+ // Normalize and validate upload directory first.
966+ $ norm_upload_dir = wp_normalize_path ( $ upload_dir );
967967 $ real_upload_dir = realpath ( $ norm_upload_dir );
968- if ($ real_upload_dir === false ) {
969- sse_log ('Upload directory cannot be resolved: ' . $ upload_dir , 'security ' );
968+ if ( false === $ real_upload_dir ) {
969+ sse_log ( 'Upload directory cannot be resolved: ' . $ upload_dir , 'security ' );
970970 return false ;
971971 }
972-
973- // Normalize parent directory and perform basic validation
974- $ norm_parent_dir = wp_normalize_path ($ parent_dir );
975-
976- // Validate that normalized parent dir starts with normalized upload dir (before realpath)
977- if (strpos ($ norm_parent_dir , $ norm_upload_dir ) !== 0 ) {
978- sse_log ('Parent directory not within normalized upload directory: ' . $ parent_dir , 'security ' );
972+
973+ // Normalize parent directory and perform basic validation.
974+ $ norm_parent_dir = wp_normalize_path ( $ parent_dir );
975+
976+ // Validate that normalized parent dir starts with normalized upload dir (before realpath).
977+ if ( strpos ( $ norm_parent_dir , $ norm_upload_dir ) !== 0 ) {
978+ sse_log ( 'Parent directory not within normalized upload directory: ' . $ parent_dir , 'security ' );
979979 return false ;
980980 }
981-
982- // Now safe to resolve real path after validation - filesystem checks removed to prevent SSRF
981+
982+ // Now safe to resolve real path after validation - filesystem checks removed to prevent SSRF.
983983 $ real_parent_dir = realpath ( $ norm_parent_dir );
984- if ($ real_parent_dir === false ) {
985- sse_log ('Parent directory resolution failed: ' . $ parent_dir , 'security ' );
984+ if ( false === $ real_parent_dir ) {
985+ sse_log ( 'Parent directory resolution failed: ' . $ parent_dir , 'security ' );
986986 return false ;
987987 }
988-
989- // Final validation: ensure resolved path is still within upload directory
990- if (strpos ($ real_parent_dir , $ real_upload_dir ) !== 0 ) {
991- sse_log ('Parent directory real path validation failed ' , 'security ' );
988+
989+ // Final validation: ensure resolved path is still within upload directory.
990+ if ( strpos ( $ real_parent_dir , $ real_upload_dir ) !== 0 ) {
991+ sse_log ( 'Parent directory real path validation failed ' , 'security ' );
992992 return false ;
993993 }
994994
@@ -1002,9 +1002,9 @@ function sse_resolve_parent_directory( $parent_dir, $upload_dir ) {
10021002 * @return string|false Sanitized filename or false on failure.
10031003 */
10041004function sse_sanitize_filename ( $ filename ) {
1005- $ filename = sanitize_file_name ($ filename );
1006- if (strpos ($ filename , '.. ' ) !== false || strpos ($ filename , '/ ' ) !== false || strpos ($ filename , '\\' ) !== false ) {
1007- sse_log ('Filename contains invalid characters: ' . $ filename , 'security ' );
1005+ $ filename = sanitize_file_name ( $ filename );
1006+ if ( strpos ( $ filename , '.. ' ) !== false || strpos ( $ filename , '/ ' ) !== false || strpos ( $ filename , '\\' ) !== false ) {
1007+ sse_log ( 'Filename contains invalid characters: ' . $ filename , 'security ' );
10081008 return false ;
10091009 }
10101010
@@ -1019,16 +1019,16 @@ function sse_sanitize_filename( $filename ) {
10191019 * @return bool True if the file is within the base directory, false otherwise.
10201020 */
10211021function sse_check_path_within_base ( $ real_file_path , $ real_base_dir ) {
1022- // Ensure both paths are available for comparison
1023- if ($ real_file_path === false ) {
1022+ // Ensure both paths are available for comparison.
1023+ if ( false === $ real_file_path ) {
10241024 return false ;
10251025 }
1026-
1027- // Ensure the file path starts with the base directory (with trailing slash)
1028- $ real_base_dir = rtrim ($ real_base_dir , '/ ' ) . '/ ' ;
1029- $ real_file_path = rtrim ($ real_file_path , '/ ' ) . '/ ' ;
1030-
1031- $ is_within_base = strpos ($ real_file_path , $ real_base_dir ) === 0 ;
1026+
1027+ // Ensure the file path starts with the base directory (with trailing slash).
1028+ $ real_base_dir = rtrim ( $ real_base_dir , '/ ' ) . '/ ' ;
1029+ $ real_file_path = rtrim ( $ real_file_path , '/ ' ) . '/ ' ;
1030+
1031+ $ is_within_base = strpos ( $ real_file_path , $ real_base_dir ) === 0 ;
10321032
10331033 if ( ! $ is_within_base ) {
10341034 sse_log ('Path validation failed - path outside base directory. File: ' . $ real_file_path . ', Base: ' . $ real_base_dir , 'warning ' );
@@ -1054,18 +1054,18 @@ function sse_validate_filepath($file_path, $base_dir) {
10541054 return false ;
10551055 }
10561056
1057- // Resolve real paths to prevent directory traversal
1058- $ real_file_path = sse_resolve_file_path ($ normalized_file_path );
1059- $ real_base_dir = realpath ( $ normalized_base_dir );
1060-
1061- // Base directory must be resolvable for security
1062- if ($ real_base_dir === false ) {
1063- sse_log ('Could not resolve base directory: ' . $ normalized_base_dir , 'security ' );
1057+ // Resolve real paths to prevent directory traversal.
1058+ $ real_file_path = sse_resolve_file_path ( $ normalized_file_path );
1059+ $ real_base_dir = realpath ( $ normalized_base_dir );
1060+
1061+ // Base directory must be resolvable for security.
1062+ if ( false === $ real_base_dir ) {
1063+ sse_log ( 'Could not resolve base directory: ' . $ normalized_base_dir , 'security ' );
10641064 return false ;
10651065 }
1066-
1067- // Validate path is within base directory
1068- return sse_check_path_within_base ($ real_file_path , $ real_base_dir );
1066+
1067+ // Validate path is within base directory.
1068+ return sse_check_path_within_base ( $ real_file_path , $ real_base_dir );
10691069}
10701070
10711071/**
@@ -1144,19 +1144,19 @@ function sse_validate_basic_export_file($filename) {
11441144 * @param string $filename The filename to validate.
11451145 * @return true|WP_Error True on success, WP_Error on failure.
11461146 */
1147- function sse_validate_filename_format ($ filename ) {
1148- if (empty ($ filename) ) {
1149- return new WP_Error ('invalid_request ' , esc_html__ ('No file specified. ' , 'simple-wp-site-exporter ' ) );
1147+ function sse_validate_filename_format ( $ filename ) {
1148+ if ( empty ( $ filename ) ) {
1149+ return new WP_Error ( 'invalid_request ' , esc_html__ ( 'No file specified. ' , 'simple-wp-site-exporter ' ) );
11501150 }
1151-
1152- // Prevent path traversal attacks
1153- if (strpos ($ filename , '/ ' ) !== false || strpos ($ filename , '\\' ) !== false ) {
1154- return new WP_Error ('invalid_filename ' , esc_html__ ('Invalid filename. ' , 'simple-wp-site-exporter ' ) );
1151+
1152+ // Prevent path traversal attacks.
1153+ if ( strpos ( $ filename , '/ ' ) !== false || strpos ( $ filename , '\\' ) !== false ) {
1154+ return new WP_Error ( 'invalid_filename ' , esc_html__ ( 'Invalid filename. ' , 'simple-wp-site-exporter ' ) );
11551155 }
1156-
1157- // Validate that it's our export file format
1156+
1157+ // Validate that it's our export file format.
11581158 if ( ! preg_match ( '/^site_export_sse_[a-f0-9]{7}_[a-zA-Z0-9_-]+_\d{4}-\d{2}-\d{2}_\d{2}-\d{2}-\d{2}\.zip$/ ' , $ filename ) ) {
1159- return new WP_Error ('invalid_format ' , esc_html__ ('Invalid export file format. ' , 'simple-wp-site-exporter ' ) );
1159+ return new WP_Error ( 'invalid_format ' , esc_html__ ( 'Invalid export file format. ' , 'simple-wp-site-exporter ' ) );
11601160 }
11611161
11621162 return true ;
@@ -1191,21 +1191,21 @@ function sse_validate_export_file_path($filename) {
11911191 * @param string $file_path The file path to check.
11921192 * @return true|WP_Error True on success, WP_Error on failure.
11931193 */
1194- function sse_validate_file_existence ($ file_path ) {
1194+ function sse_validate_file_existence ( $ file_path ) {
11951195 global $ wp_filesystem ;
1196-
1197- // Initialize the WordPress filesystem
1198- if (empty ($ wp_filesystem) ) {
1196+
1197+ // Initialize the WordPress filesystem.
1198+ if ( empty ( $ wp_filesystem ) ) {
11991199 require_once ABSPATH . 'wp-admin/includes/file.php ' ;
12001200 if ( ! WP_Filesystem () ) {
1201- sse_log ('Failed to initialize WordPress filesystem API ' , 'error ' );
1202- return new WP_Error ('filesystem_init_failed ' , esc_html__ ('Failed to initialize WordPress filesystem API. ' , 'simple-wp-site-exporter ' ) );
1201+ sse_log ( 'Failed to initialize WordPress filesystem API ' , 'error ' );
1202+ return new WP_Error ( 'filesystem_init_failed ' , esc_html__ ( 'Failed to initialize WordPress filesystem API. ' , 'simple-wp-site-exporter ' ) );
12031203 }
12041204 }
1205-
1206- // Check if file exists using WP Filesystem
1205+
1206+ // Check if file exists using WP Filesystem.
12071207 if ( ! $ wp_filesystem ->exists ( $ file_path ) ) {
1208- return new WP_Error ('file_not_found ' , esc_html__ ('Export file not found. ' , 'simple-wp-site-exporter ' ) );
1208+ return new WP_Error ( 'file_not_found ' , esc_html__ ( 'Export file not found. ' , 'simple-wp-site-exporter ' ) );
12091209 }
12101210
12111211 return true ;
@@ -1329,14 +1329,17 @@ function () {
13291329 wp_safe_redirect ( admin_url ( 'tools.php?page=simple-wp-site-exporter ' ) );
13301330 exit ; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- WordPress standard: exit required after wp_safe_redirect.
13311331 }
1332-
1333- add_action ( 'admin_notices ' , function () {
1334- ?>
1335- <div class="notice notice-error is-dismissible">
1336- <p><?php esc_html_e ( 'Failed to delete export file. ' , 'simple-wp-site-exporter ' ); ?> </p>
1337- </div>
1338- <?php
1339- });
1332+
1333+ add_action (
1334+ 'admin_notices ' ,
1335+ function () {
1336+ ?>
1337+ <div class="notice notice-error is-dismissible">
1338+ <p><?php esc_html_e ( 'Failed to delete export file. ' , 'simple-wp-site-exporter ' ); ?> </p>
1339+ </div>
1340+ <?php
1341+ }
1342+ );
13401343 sse_log ( 'Failed manual deletion of export file: ' . $ validation ['filepath ' ], 'error ' );
13411344
13421345 // Redirect back to the export page to prevent resubmission.
0 commit comments