11<?php
22/*
3- Plugin Name: Simple WP Site Exporter
4- Description: Exports the site files and database as a zip archive.
5- Version: 1.7.0
6- Author: EngineScript
7- License: GPL v3 or later
8- Text Domain: Simple-WP-Site-Exporter
3+ Plugin Name: Simple WP Site Exporter
4+ Description: Exports the site files and database as a zip archive.
5+ Version: 1.7.0
6+ Author: EngineScript
7+ License: GPL v3 or later
8+ Text Domain: Simple-WP-Site-Exporter
99*/
1010
1111// Prevent direct access. Note: Using return here instead of exit.
1212if ( ! defined ( 'ABSPATH ' ) ) {
13- return ; // Prevent direct access
13+ return ; // Prevent direct access.
1414}
1515
1616// Define plugin version.
4242 *
4343 * @return string Client IP address or 'unknown' if not available.
4444 */
45- function sse_get_client_ip () {
45+ function sse_get_client_ip ()
46+ {
4647 // WordPress-style IP detection with validation.
47- $ ip = 'unknown ' ;
48+ $ client_ip = 'unknown ' ;
4849
50+ // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated -- $_SERVER['REMOTE_ADDR'] is safe for IP logging when properly sanitized
4951 if ( isset ( $ _SERVER ['REMOTE_ADDR ' ] ) ) {
50- $ ip = sanitize_text_field ( wp_unslash ( $ _SERVER ['REMOTE_ADDR ' ] ) );
52+ $ client_ip = sanitize_text_field ( wp_unslash ( $ _SERVER ['REMOTE_ADDR ' ] ) );
5153 }
5254
5355 // Basic IP validation.
54- if ( filter_var ( $ ip , FILTER_VALIDATE_IP ) ) {
55- return $ ip ;
56+ if ( filter_var ( $ client_ip , FILTER_VALIDATE_IP ) ) {
57+ return $ client_ip ;
5658 }
5759
5860 return 'unknown ' ;
@@ -67,7 +69,8 @@ function sse_get_client_ip() {
6769 * @param string $level The log level.
6870 * @return void
6971 */
70- function sse_store_log_in_database ( $ message , $ level ) {
72+ function sse_store_log_in_database ( $ message , $ level )
73+ {
7174 // Store last 20 important messages in an option.
7275 $ logs = get_option ( 'sse_error_logs ' , [] );
7376 $ logs [] = [
@@ -85,7 +88,7 @@ function sse_store_log_in_database( $message, $level ) {
8588
8689 update_option ( 'sse_error_logs ' , $ logs );
8790
88- } //end sse_store_log_in_database()
91+ } //end sse_store_log_in_database() //end sse_store_log_in_database()
8992
9093
9194/**
@@ -94,7 +97,8 @@ function sse_store_log_in_database( $message, $level ) {
9497 * @param string $formatted_message The formatted log message.
9598 * @return void
9699 */
97- function sse_output_log_message ( $ formatted_message ) {
100+ function sse_output_log_message ( $ formatted_message )
101+ {
98102 // Use WordPress logging (wp_debug_log is available in WP 5.1+).
99103 if ( function_exists ( 'wp_debug_log ' ) ) {
100104 wp_debug_log ( $ formatted_message );
@@ -110,7 +114,8 @@ function sse_output_log_message( $formatted_message ) {
110114 * @param string $level The log level (error, warning, info).
111115 * @return void
112116 */
113- function sse_log ( $ message , $ level = 'info ' ) {
117+ function sse_log ( $ message , $ level = 'info ' )
118+ {
114119 // Check if WP_DEBUG is enabled.
115120 if ( ! defined ( 'WP_DEBUG ' ) || ! WP_DEBUG ) {
116121 return ;
@@ -141,10 +146,11 @@ function sse_log( $message, $level = 'info' ) {
141146
142147/**
143148 * Safely get the PHP execution time limit
144- *
149+ *
145150 * @return int Current PHP execution time limit in seconds
146151 */
147- function sse_get_execution_time_limit () {
152+ function sse_get_execution_time_limit ()
153+ {
148154 // Get the current execution time limit
149155 $ max_exec_time = ini_get ('max_execution_time ' );
150156
@@ -165,10 +171,12 @@ function sse_get_execution_time_limit() {
165171 }
166172
167173 return (int )$ max_exec_time ;
168- }
174+
175+ } //end sse_get_execution_time_limit()
169176
170177// --- Admin Menu ---
171- function sse_admin_menu () {
178+ function sse_admin_menu ()
179+ {
172180 add_management_page (
173181 esc_html__ ( 'Simple WP Site Exporter ' , 'Simple-WP-Site-Exporter ' ), // Escaped title
174182 esc_html__ ( 'Site Exporter ' , 'Simple-WP-Site-Exporter ' ), // Escaped menu title
@@ -180,7 +188,8 @@ function sse_admin_menu() {
180188add_action ( 'admin_menu ' , 'sse_admin_menu ' );
181189
182190// --- Exporter Page HTML ---
183- function sse_exporter_page_html () {
191+ function sse_exporter_page_html ()
192+ {
184193 if ( ! current_user_can ( 'manage_options ' ) ) {
185194 wp_die ( esc_html__ ( 'You do not have permission to view this page. ' , 'Simple-WP-Site-Exporter ' ), 403 );
186195 }
@@ -270,7 +279,8 @@ function sse_handle_export() {
270279 *
271280 * @return bool True if request is valid, false otherwise.
272281 */
273- function sse_validate_export_request () { // phpcs:ignore WordPress.Security.NonceVerification.Missing
282+ function sse_validate_export_request ()
283+ { // phpcs:ignore WordPress.Security.NonceVerification.Missing
274284 $ post_action = isset ( $ _POST ['action ' ] ) ? sanitize_key ( $ _POST ['action ' ] ) : '' ;
275285 if ( 'sse_export_site ' !== $ post_action ) {
276286 return false ;
@@ -295,7 +305,8 @@ function sse_validate_export_request() { // phpcs:ignore WordPress.Security.Nonc
295305 *
296306 * @return void
297307 */
298- function sse_prepare_execution_environment () {
308+ function sse_prepare_execution_environment ()
309+ {
299310 $ max_exec_time = sse_get_execution_time_limit ();
300311 $ target_exec_time = 1800 ; // 30 minutes in seconds.
301312
@@ -555,13 +566,13 @@ function sse_add_file_to_zip( $zip, $file_info, $file, $pathname, $relative_path
555566
556567 if ( $ file_info ->isFile () ) {
557568 // Use real path (getRealPath() must succeed for security)
558- if ( false !== $ file ) {
559- $ file_to_add = $ file ;
560- } else {
569+ if ( false === $ file ) {
561570 sse_log ( "Skipping file with unresolvable real path: " . $ pathname , 'warning ' );
562571 return true ; // Skip this file but continue processing
563572 }
564573
574+ $ file_to_add = $ file ;
575+
565576 if ( ! $ zip ->addFile ( $ file_to_add , $ relative_path ) ) {
566577 sse_log ( "Failed to add file to zip: " . $ relative_path . " (Source: " . $ file_to_add . ") " , 'error ' );
567578 }
@@ -893,10 +904,10 @@ function sse_validate_parent_directory_safety($parent_dir, $upload_dir) {
893904 }
894905
895906 // Ensure parent directory is within WordPress upload directory
896- $ normalized_parent_dir = wp_normalize_path ($ parent_dir );
897- $ normalized_upload_dir = wp_normalize_path ($ upload_dir );
907+ $ norm_parent_dir = wp_normalize_path ($ parent_dir );
908+ $ norm_upload_dir = wp_normalize_path ($ upload_dir );
898909
899- if (strpos ($ normalized_parent_dir , $ normalized_upload_dir ) !== 0 ) {
910+ if (strpos ($ norm_parent_dir , $ norm_upload_dir ) !== 0 ) {
900911 sse_log ('Parent directory not within WordPress upload directory: ' . $ parent_dir , 'security ' );
901912 return false ;
902913 }
@@ -913,24 +924,24 @@ function sse_validate_parent_directory_safety($parent_dir, $upload_dir) {
913924 */
914925function sse_resolve_parent_directory ($ parent_dir , $ upload_dir ) {
915926 // Normalize and validate upload directory first
916- $ normalized_upload_dir = wp_normalize_path ($ upload_dir );
917- $ real_upload_dir = realpath ($ normalized_upload_dir );
927+ $ norm_upload_dir = wp_normalize_path ($ upload_dir );
928+ $ real_upload_dir = realpath ($ norm_upload_dir );
918929 if ($ real_upload_dir === false ) {
919930 sse_log ('Upload directory cannot be resolved: ' . $ upload_dir , 'security ' );
920931 return false ;
921932 }
922933
923934 // Normalize parent directory and perform basic validation
924- $ normalized_parent_dir = wp_normalize_path ($ parent_dir );
935+ $ norm_parent_dir = wp_normalize_path ($ parent_dir );
925936
926937 // Validate that normalized parent dir starts with normalized upload dir (before realpath)
927- if (strpos ($ normalized_parent_dir , $ normalized_upload_dir ) !== 0 ) {
938+ if (strpos ($ norm_parent_dir , $ norm_upload_dir ) !== 0 ) {
928939 sse_log ('Parent directory not within normalized upload directory: ' . $ parent_dir , 'security ' );
929940 return false ;
930941 }
931942
932943 // Now safe to resolve real path after validation - filesystem checks removed to prevent SSRF
933- $ real_parent_dir = realpath ($ normalized_parent_dir );
944+ $ real_parent_dir = realpath ($ norm_parent_dir );
934945 if ($ real_parent_dir === false ) {
935946 sse_log ('Parent directory resolution failed: ' . $ parent_dir , 'security ' );
936947 return false ;
0 commit comments