security = tigerstyle_life9()->get_security(); $this->init_hooks(); } /** * Initialize WordPress hooks */ private function init_hooks() { // REST API add_action('rest_api_init', [$this, 'register_rest_routes']); // AJAX handlers add_action('wp_ajax_tigerstyle_life9_start_backup', [$this, 'ajax_start_backup']); add_action('wp_ajax_tigerstyle_life9_get_backup_status', [$this, 'ajax_get_backup_status']); add_action('wp_ajax_tigerstyle_life9_cancel_backup', [$this, 'ajax_cancel_backup']); add_action('wp_ajax_tigerstyle_life9_download_backup', [$this, 'ajax_download_backup']); add_action('wp_ajax_tigerstyle_life9_delete_backup', [$this, 'ajax_delete_backup']); add_action('wp_ajax_tigerstyle_life9_restore_backup', [$this, 'ajax_restore_backup']); add_action('wp_ajax_tigerstyle_life9_browse_files', [$this, 'ajax_browse_files']); add_action('wp_ajax_tigerstyle_life9_preview_file', [$this, 'ajax_preview_file']); add_action('wp_ajax_tigerstyle_life9_save_settings', [$this, 'ajax_save_settings']); add_action('wp_ajax_tigerstyle_life9_get_dashboard_stats', [$this, 'ajax_get_dashboard_stats']); add_action('wp_ajax_tigerstyle_life9_get_system_status', [$this, 'ajax_get_system_status']); // Rate limiting add_action('wp_ajax_tigerstyle_life9_rate_limit_check', [$this, 'check_rate_limits']); } /** * Register REST API routes */ public function register_rest_routes() { $this->rest_endpoints = new TigerStyle_Life9_REST_Endpoints(); $this->rest_endpoints->register_routes(); } /** * Check user permissions for API access * * @param string $capability Required capability * @return bool */ private function check_permissions($capability = 'manage_options') { return current_user_can($capability); } /** * Validate and sanitize AJAX request * * @param string $action Action name for nonce verification * @return array Sanitized request data */ private function validate_ajax_request($action) { // Check permissions if (!$this->check_permissions()) { wp_send_json_error(['message' => __('Insufficient permissions', 'tigerstyle-life9')]); } // Verify nonce if (!$this->security->verify_nonce($_POST['nonce'] ?? '', $action)) { wp_send_json_error(['message' => __('Security check failed', 'tigerstyle-life9')]); } // Sanitize request data $sanitizer = new TigerStyle_Life9_Sanitizer(); return $sanitizer->sanitize_array($_POST); } /** * AJAX: Start backup process */ public function ajax_start_backup() { $request = $this->validate_ajax_request('start_backup'); try { // Validate backup configuration $backup_config = $request['backup_config'] ?? []; if (is_string($backup_config)) { $backup_config = json_decode($backup_config, true); } $sanitizer = new TigerStyle_Life9_Sanitizer(); $validator = new TigerStyle_Life9_Validator(); $clean_config = $sanitizer->sanitize_backup_config($backup_config); if (!$validator->validate_backup_config($clean_config)) { $errors = $validator->get_errors(); wp_send_json_error([ 'message' => __('Invalid backup configuration', 'tigerstyle-life9'), 'errors' => $errors ]); } // Start backup process $backup_engine = new TigerStyle_Life9_Backup_Engine(); $backup_id = $backup_engine->start_backup($clean_config); if ($backup_id) { wp_send_json_success([ 'backup_id' => $backup_id, 'message' => __('Backup started successfully', 'tigerstyle-life9'), 'status_url' => rest_url('tigerstyle-life9/v1/backups/' . $backup_id . '/status') ]); } else { wp_send_json_error(['message' => __('Failed to start backup', 'tigerstyle-life9')]); } } catch (Exception $e) { error_log('TigerStyle Life9: Backup start error - ' . $e->getMessage()); wp_send_json_error(['message' => __('An error occurred while starting backup', 'tigerstyle-life9')]); } } /** * AJAX: Get backup status */ public function ajax_get_backup_status() { $request = $this->validate_ajax_request('get_backup_status'); $backup_id = intval($request['backup_id'] ?? 0); if (!$backup_id) { wp_send_json_error(['message' => __('Invalid backup ID', 'tigerstyle-life9')]); } try { global $wpdb; $backup = $wpdb->get_row($wpdb->prepare( "SELECT * FROM {$wpdb->prefix}tigerstyle_life9_backups WHERE id = %d", $backup_id )); if (!$backup) { wp_send_json_error(['message' => __('Backup not found', 'tigerstyle-life9')]); } // Get recent log entries $logs = $wpdb->get_results($wpdb->prepare( "SELECT * FROM {$wpdb->prefix}tigerstyle_life9_logs WHERE backup_id = %d ORDER BY created_at DESC LIMIT 10", $backup_id )); $response = [ 'id' => $backup->id, 'status' => $backup->status, 'created_at' => $backup->created_at, 'completed_at' => $backup->completed_at, 'file_size' => $backup->file_size, 'progress' => $this->calculate_backup_progress($backup), 'logs' => array_map(function($log) { return [ 'level' => $log->level, 'message' => $log->message, 'created_at' => $log->created_at ]; }, $logs) ]; wp_send_json_success($response); } catch (Exception $e) { error_log('TigerStyle Life9: Status check error - ' . $e->getMessage()); wp_send_json_error(['message' => __('Failed to get backup status', 'tigerstyle-life9')]); } } /** * AJAX: Cancel backup process */ public function ajax_cancel_backup() { $request = $this->validate_ajax_request('cancel_backup'); $backup_id = intval($request['backup_id'] ?? 0); if (!$backup_id) { wp_send_json_error(['message' => __('Invalid backup ID', 'tigerstyle-life9')]); } try { $backup_engine = new TigerStyle_Life9_Backup_Engine(); $success = $backup_engine->cancel_backup($backup_id); if ($success) { wp_send_json_success(['message' => __('Backup cancelled', 'tigerstyle-life9')]); } else { wp_send_json_error(['message' => __('Failed to cancel backup', 'tigerstyle-life9')]); } } catch (Exception $e) { error_log('TigerStyle Life9: Cancel backup error - ' . $e->getMessage()); wp_send_json_error(['message' => __('An error occurred while cancelling backup', 'tigerstyle-life9')]); } } /** * AJAX: Download backup file */ public function ajax_download_backup() { $request = $this->validate_ajax_request('download_backup'); $backup_id = intval($request['backup_id'] ?? 0); if (!$backup_id) { wp_send_json_error(['message' => __('Invalid backup ID', 'tigerstyle-life9')]); } try { global $wpdb; $backup = $wpdb->get_row($wpdb->prepare( "SELECT * FROM {$wpdb->prefix}tigerstyle_life9_backups WHERE id = %d AND status = 'completed'", $backup_id )); if (!$backup || !$backup->file_path) { wp_send_json_error(['message' => __('Backup file not found', 'tigerstyle-life9')]); } // Validate file path if (!$this->security->validate_path($backup->file_path)) { wp_send_json_error(['message' => __('Invalid file path', 'tigerstyle-life9')]); } if (!file_exists($backup->file_path)) { wp_send_json_error(['message' => __('Backup file does not exist', 'tigerstyle-life9')]); } // Generate secure download token $token = $this->security->generate_token(); set_transient('tigerstyle_life9_download_' . $token, $backup_id, 300); // 5 minutes $download_url = add_query_arg([ 'tigerstyle_life9_download' => $token, 'backup_id' => $backup_id ], admin_url('admin.php')); wp_send_json_success(['download_url' => $download_url]); } catch (Exception $e) { error_log('TigerStyle Life9: Download error - ' . $e->getMessage()); wp_send_json_error(['message' => __('Failed to generate download link', 'tigerstyle-life9')]); } } /** * AJAX: Delete backup */ public function ajax_delete_backup() { $request = $this->validate_ajax_request('delete_backup'); $backup_id = intval($request['backup_id'] ?? 0); if (!$backup_id) { wp_send_json_error(['message' => __('Invalid backup ID', 'tigerstyle-life9')]); } try { global $wpdb; $backup = $wpdb->get_row($wpdb->prepare( "SELECT * FROM {$wpdb->prefix}tigerstyle_life9_backups WHERE id = %d", $backup_id )); if (!$backup) { wp_send_json_error(['message' => __('Backup not found', 'tigerstyle-life9')]); } // Delete file if exists if ($backup->file_path && file_exists($backup->file_path)) { $encryption = new TigerStyle_Life9_Encryption(); $encryption->secure_delete($backup->file_path); } // Delete from database $wpdb->delete( $wpdb->prefix . 'tigerstyle_life9_backups', ['id' => $backup_id], ['%d'] ); // Log the deletion $this->security->log_security_event('backup_deleted', [ 'backup_id' => $backup_id, 'backup_name' => $backup->name ]); wp_send_json_success(['message' => __('Backup deleted successfully', 'tigerstyle-life9')]); } catch (Exception $e) { error_log('TigerStyle Life9: Delete backup error - ' . $e->getMessage()); wp_send_json_error(['message' => __('Failed to delete backup', 'tigerstyle-life9')]); } } /** * AJAX: Browse files */ public function ajax_browse_files() { $request = $this->validate_ajax_request('browse_files'); $path = $request['path'] ?? ABSPATH; $show_hidden = (bool) ($request['show_hidden'] ?? false); // Validate path if (!$this->security->validate_path($path, ABSPATH)) { wp_send_json_error(['message' => __('Invalid path', 'tigerstyle-life9')]); } try { $scanner = new TigerStyle_Life9_File_Scanner(); $files = $scanner->scan_directory($path, [ 'show_hidden' => $show_hidden, 'max_depth' => 1 ]); wp_send_json_success([ 'files' => $files, 'current_path' => $path ]); } catch (Exception $e) { error_log('TigerStyle Life9: File browse error - ' . $e->getMessage()); wp_send_json_error(['message' => __('Failed to browse files', 'tigerstyle-life9')]); } } /** * AJAX: Preview file */ public function ajax_preview_file() { $request = $this->validate_ajax_request('preview_file'); $file_path = $request['path'] ?? ''; // Validate file path if (!$this->security->validate_path($file_path, ABSPATH)) { wp_send_json_error(['message' => __('Invalid file path', 'tigerstyle-life9')]); } if (!file_exists($file_path) || !is_readable($file_path)) { wp_send_json_error(['message' => __('File not found or not readable', 'tigerstyle-life9')]); } try { $file_size = filesize($file_path); $max_preview_size = 1024 * 1024; // 1MB if ($file_size > $max_preview_size) { wp_send_json_error(['message' => __('File too large for preview', 'tigerstyle-life9')]); } $content = file_get_contents($file_path); // Basic security check for content if (strpos($content, ' $content]); } catch (Exception $e) { error_log('TigerStyle Life9: File preview error - ' . $e->getMessage()); wp_send_json_error(['message' => __('Failed to preview file', 'tigerstyle-life9')]); } } /** * AJAX: Save settings */ public function ajax_save_settings() { $request = $this->validate_ajax_request('save_settings'); $settings = $request['settings'] ?? []; if (is_string($settings)) { $settings = json_decode($settings, true); } if (!is_array($settings)) { wp_send_json_error(['message' => __('Invalid settings format', 'tigerstyle-life9')]); } try { $sanitizer = new TigerStyle_Life9_Sanitizer(); $validator = new TigerStyle_Life9_Validator(); // Define allowed settings with their types $allowed_settings = [ 'backup_retention_days' => 'int', 'max_backup_size_mb' => 'int', 'enable_compression' => 'bool', 'compression_method' => 'string', 'backup_database' => 'bool', 'backup_files' => 'bool', 'exclude_patterns' => 'array', 'storage_locations' => 'array', 'api_rate_limit' => 'int', 'enable_logging' => 'bool', 'log_level' => 'string' ]; $updated_settings = []; foreach ($allowed_settings as $setting_name => $type) { if (isset($settings[$setting_name])) { $value = $sanitizer->sanitize_sql_param($settings[$setting_name], $type); // Additional validation switch ($setting_name) { case 'backup_retention_days': if ($value < 1 || $value > 365) { wp_send_json_error(['message' => __('Retention days must be between 1 and 365', 'tigerstyle-life9')]); } break; case 'max_backup_size_mb': if ($value < 1 || $value > 10000) { wp_send_json_error(['message' => __('Max backup size must be between 1MB and 10GB', 'tigerstyle-life9')]); } break; case 'compression_method': $valid_methods = ['zip', 'tar', 'gzip', 'none']; if (!in_array($value, $valid_methods)) { wp_send_json_error(['message' => __('Invalid compression method', 'tigerstyle-life9')]); } break; } update_option('tigerstyle_life9_' . $setting_name, $value); $updated_settings[$setting_name] = $value; } } wp_send_json_success([ 'message' => __('Settings saved successfully', 'tigerstyle-life9'), 'updated_settings' => $updated_settings ]); } catch (Exception $e) { error_log('TigerStyle Life9: Save settings error - ' . $e->getMessage()); wp_send_json_error(['message' => __('Failed to save settings', 'tigerstyle-life9')]); } } /** * AJAX: Get dashboard statistics */ public function ajax_get_dashboard_stats() { $this->validate_ajax_request('get_dashboard_stats'); try { global $wpdb; $stats = [ 'total_backups' => 0, 'total_size' => 0, 'successful_backups' => 0, 'failed_backups' => 0, 'last_backup' => null ]; // Get backup counts and stats $backup_stats = $wpdb->get_row( "SELECT COUNT(*) as total_backups, SUM(CASE WHEN status = 'completed' THEN 1 ELSE 0 END) as successful_backups, SUM(CASE WHEN status = 'failed' THEN 1 ELSE 0 END) as failed_backups, SUM(CASE WHEN status = 'completed' THEN file_size ELSE 0 END) as total_size, MAX(CASE WHEN status = 'completed' THEN created_at ELSE NULL END) as last_backup FROM {$wpdb->prefix}tigerstyle_life9_backups" ); if ($backup_stats) { $stats = [ 'total_backups' => intval($backup_stats->total_backups), 'total_size' => intval($backup_stats->total_size), 'successful_backups' => intval($backup_stats->successful_backups), 'failed_backups' => intval($backup_stats->failed_backups), 'last_backup' => $backup_stats->last_backup ]; } wp_send_json_success($stats); } catch (Exception $e) { error_log('TigerStyle Life9: Dashboard stats error - ' . $e->getMessage()); wp_send_json_error(['message' => __('Failed to load dashboard stats', 'tigerstyle-life9')]); } } /** * AJAX: Get system status */ public function ajax_get_system_status() { $this->validate_ajax_request('get_system_status'); try { $upload_dir = wp_upload_dir(); $backup_dir = $upload_dir['basedir'] . '/tigerstyle-life9'; $status = [ 'php_version' => PHP_VERSION, 'php_version_ok' => version_compare(PHP_VERSION, '8.0', '>='), 'wp_version' => get_bloginfo('version'), 'wp_version_ok' => version_compare(get_bloginfo('version'), '6.0', '>='), 'available_space' => disk_free_space($backup_dir), 'disk_space_ok' => disk_free_space($backup_dir) > (1024 * 1024 * 1024), // 1GB 'permissions_ok' => is_writable($backup_dir), 'extensions' => [ 'openssl' => extension_loaded('openssl'), 'zip' => extension_loaded('zip'), 'curl' => extension_loaded('curl'), 'json' => extension_loaded('json') ] ]; wp_send_json_success($status); } catch (Exception $e) { error_log('TigerStyle Life9: System status error - ' . $e->getMessage()); wp_send_json_error(['message' => __('Failed to get system status', 'tigerstyle-life9')]); } } /** * Calculate backup progress percentage * * @param object $backup Backup database record * @return int Progress percentage (0-100) */ private function calculate_backup_progress($backup) { switch ($backup->status) { case 'completed': return 100; case 'failed': case 'cancelled': return 0; case 'running': // This would be determined by the backup engine // For now, return a placeholder return 50; default: return 0; } } /** * Check rate limits for API requests */ public function check_rate_limits() { $action = $_POST['action'] ?? ''; $limit = intval(get_option('tigerstyle_life9_api_rate_limit', 100)); if (!$this->security->check_rate_limit($action, $limit)) { wp_send_json_error(['message' => __('Rate limit exceeded', 'tigerstyle-life9')]); } wp_send_json_success(['message' => 'Rate limit OK']); } }