|
25 | 25 | define( 'SSE_ALLOWED_EXTENSIONS', array( 'zip', 'sql' ) ); |
26 | 26 | } |
27 | 27 |
|
| 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 | + |
28 | 33 | /** |
29 | 34 | * WordPress Core Classes Documentation |
30 | 35 | * |
@@ -233,8 +238,8 @@ function sse_exporter_page_html() { |
233 | 238 | if ( empty( $upload_dir['basedir'] ) ) { |
234 | 239 | wp_die( esc_html__( 'Could not determine the WordPress upload directory.', 'simple-wp-site-exporter' ) ); |
235 | 240 | } |
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; |
238 | 243 | $display_path = str_replace( ABSPATH, '', $export_dir_path ); |
239 | 244 | ?> |
240 | 245 | <div class="wrap"> |
@@ -413,11 +418,21 @@ function sse_setup_export_directories() { |
413 | 418 | return new WP_Error( 'upload_dir_error', __( 'Could not determine the WordPress upload directory or URL.', 'simple-wp-site-exporter' ) ); |
414 | 419 | } |
415 | 420 |
|
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; |
418 | 423 | $export_url = trailingslashit( $upload_dir['baseurl'] ) . $export_dir_name; |
419 | 424 |
|
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 | + |
421 | 436 | sse_create_index_file( $export_dir ); |
422 | 437 |
|
423 | 438 | return array( |
@@ -963,7 +978,7 @@ function sse_bulk_cleanup_exports_handler() { |
963 | 978 | sse_log( 'Bulk export cleanup handler triggered', 'info' ); |
964 | 979 |
|
965 | 980 | $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; |
967 | 982 |
|
968 | 983 | if ( ! is_dir( $export_dir ) ) { |
969 | 984 | sse_log( 'Export directory does not exist, nothing to clean up', 'info' ); |
@@ -1477,7 +1492,7 @@ function sse_validate_filename_format( $filename ) { |
1477 | 1492 | function sse_validate_export_file_path( $filename ) { |
1478 | 1493 | // Get the full path to the file. |
1479 | 1494 | $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; |
1481 | 1496 | $file_path = trailingslashit( $export_dir ) . $filename; |
1482 | 1497 |
|
1483 | 1498 | // Validate the file path is within our export directory. |
@@ -1735,7 +1750,7 @@ function sse_validate_download_file_data( $file_data ) { |
1735 | 1750 | function sse_validate_download_file_access( $filepath ) { |
1736 | 1751 | // Security: Whitelist approach - only allow files in our controlled export directory. |
1737 | 1752 | $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; |
1739 | 1754 |
|
1740 | 1755 | // Security: Additional validation to prevent SSRF attacks. |
1741 | 1756 | // Ensure file extension is in our allowed list. |
@@ -1818,7 +1833,7 @@ function sse_validate_file_output_security( $filepath ) { |
1818 | 1833 |
|
1819 | 1834 | // Security: Ensure file is within our controlled directory before serving. |
1820 | 1835 | $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; |
1822 | 1837 | $real_export_dir = realpath( $export_dir ); |
1823 | 1838 | $real_file_path = realpath( $filepath ); |
1824 | 1839 |
|
|
0 commit comments