Skip to content

Commit 47f864d

Browse files
authored
Updates
1 parent 074be0d commit 47f864d

3 files changed

Lines changed: 28 additions & 9 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
- **Scheduled Deletion**: Resolved issue where export files were not being automatically deleted due to WordPress cron scheduling failures
2727
- **Fallback System**: Removed unnecessary fallback methods as requested, streamlining the system to use only WordPress cron
2828
- **Error Logging**: Improved error visibility by adding direct `error_log()` output for cron debugging when WordPress debug settings are disabled
29+
- **Export Directory Consistency**: Centralized export directory naming via `SSE_EXPORT_DIR_NAME` constant to eliminate mismatched cleanup paths and ensure all subsystems reference the same location
30+
- **Filesystem Validation**: Added explicit directory creation and writability checks with helpful error messaging when the exports folder can't be prepared
2931

3032
## 1.9.0 - August 23, 2025
3133

readme.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
9999
* **Verification System**: Added post-scheduling verification to confirm events are properly added to WordPress cron schedule
100100
* **WordPress Coding Standards**: Fixed all inline comments punctuation, corrected Yoda conditions, aligned array formatting, standardized variable assignments, and removed debug code
101101
* **Bug Fixes**: Resolved issue where export files were not being automatically deleted due to WordPress cron scheduling failures
102+
* **Export Directory Consistency**: Centralized export directory naming with a shared constant so every cleanup routine targets the correct path
103+
* **Filesystem Validation**: Added explicit directory creation and writability checks that surface actionable errors when the exports folder cannot be prepared
102104
* **Code Quality**: Enhanced overall code readability and maintainability through standardized formatting and compliance improvements
103105

104106
= 1.8.5 =

simple-wp-site-exporter.php

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@
2525
define( 'SSE_ALLOWED_EXTENSIONS', array( 'zip', 'sql' ) );
2626
}
2727

28+
// Define export directory name used across the plugin.
29+
if ( ! defined( 'SSE_EXPORT_DIR_NAME' ) ) {
30+
define( 'SSE_EXPORT_DIR_NAME', 'simple-wp-site-exporter-exports' );
31+
}
32+
2833
/**
2934
* WordPress Core Classes Documentation
3035
*
@@ -233,8 +238,8 @@ function sse_exporter_page_html() {
233238
if ( empty( $upload_dir['basedir'] ) ) {
234239
wp_die( esc_html__( 'Could not determine the WordPress upload directory.', 'simple-wp-site-exporter' ) );
235240
}
236-
$export_dir_name = 'simple-wp-site-exporter-exports';
237-
$export_dir_path = trailingslashit( $upload_dir['basedir'] ) . $export_dir_name;
241+
$export_dir_name = SSE_EXPORT_DIR_NAME;
242+
$export_dir_path = trailingslashit( $upload_dir['basedir'] ) . SSE_EXPORT_DIR_NAME;
238243
$display_path = str_replace( ABSPATH, '', $export_dir_path );
239244
?>
240245
<div class="wrap">
@@ -413,11 +418,21 @@ function sse_setup_export_directories() {
413418
return new WP_Error( 'upload_dir_error', __( 'Could not determine the WordPress upload directory or URL.', 'simple-wp-site-exporter' ) );
414419
}
415420

416-
$export_dir_name = 'simple-wp-site-exporter-exports';
417-
$export_dir = trailingslashit( $upload_dir['basedir'] ) . $export_dir_name;
421+
$export_dir_name = SSE_EXPORT_DIR_NAME;
422+
$export_dir = trailingslashit( $upload_dir['basedir'] ) . SSE_EXPORT_DIR_NAME;
418423
$export_url = trailingslashit( $upload_dir['baseurl'] ) . $export_dir_name;
419424

420-
wp_mkdir_p( $export_dir );
425+
if ( ! wp_mkdir_p( $export_dir ) && ! is_dir( $export_dir ) ) {
426+
sse_log( 'Failed to create export directory at path: ' . $export_dir, 'error' );
427+
return new WP_Error( 'export_dir_creation_failed', __( 'Could not create the export directory. Please verify filesystem permissions.', 'simple-wp-site-exporter' ) );
428+
}
429+
430+
$is_writable = function_exists( 'wp_is_writable' ) ? wp_is_writable( $export_dir ) : is_writable( $export_dir ); // phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.file_ops_is_writable
431+
if ( ! $is_writable ) {
432+
sse_log( 'Export directory is not writable: ' . $export_dir, 'error' );
433+
return new WP_Error( 'export_dir_not_writable', __( 'The export directory is not writable. Please adjust filesystem permissions.', 'simple-wp-site-exporter' ) );
434+
}
435+
421436
sse_create_index_file( $export_dir );
422437

423438
return array(
@@ -963,7 +978,7 @@ function sse_bulk_cleanup_exports_handler() {
963978
sse_log( 'Bulk export cleanup handler triggered', 'info' );
964979

965980
$upload_dir = wp_upload_dir();
966-
$export_dir = $upload_dir['basedir'] . '/simple-wp-site-exports';
981+
$export_dir = trailingslashit( $upload_dir['basedir'] ) . SSE_EXPORT_DIR_NAME;
967982

968983
if ( ! is_dir( $export_dir ) ) {
969984
sse_log( 'Export directory does not exist, nothing to clean up', 'info' );
@@ -1477,7 +1492,7 @@ function sse_validate_filename_format( $filename ) {
14771492
function sse_validate_export_file_path( $filename ) {
14781493
// Get the full path to the file.
14791494
$upload_dir = wp_upload_dir();
1480-
$export_dir = trailingslashit( $upload_dir['basedir'] ) . 'simple-wp-site-exporter-exports';
1495+
$export_dir = trailingslashit( $upload_dir['basedir'] ) . SSE_EXPORT_DIR_NAME;
14811496
$file_path = trailingslashit( $export_dir ) . $filename;
14821497

14831498
// Validate the file path is within our export directory.
@@ -1735,7 +1750,7 @@ function sse_validate_download_file_data( $file_data ) {
17351750
function sse_validate_download_file_access( $filepath ) {
17361751
// Security: Whitelist approach - only allow files in our controlled export directory.
17371752
$upload_dir = wp_upload_dir();
1738-
$export_dir = trailingslashit( $upload_dir['basedir'] ) . 'simple-wp-site-exporter-exports';
1753+
$export_dir = trailingslashit( $upload_dir['basedir'] ) . SSE_EXPORT_DIR_NAME;
17391754

17401755
// Security: Additional validation to prevent SSRF attacks.
17411756
// Ensure file extension is in our allowed list.
@@ -1818,7 +1833,7 @@ function sse_validate_file_output_security( $filepath ) {
18181833

18191834
// Security: Ensure file is within our controlled directory before serving.
18201835
$upload_dir = wp_upload_dir();
1821-
$export_dir = trailingslashit( $upload_dir['basedir'] ) . 'simple-wp-site-exporter-exports';
1836+
$export_dir = trailingslashit( $upload_dir['basedir'] ) . SSE_EXPORT_DIR_NAME;
18221837
$real_export_dir = realpath( $export_dir );
18231838
$real_file_path = realpath( $filepath );
18241839

0 commit comments

Comments
 (0)