<?php
// PHP File Explorer with Add/Delete/Move Functionality
// Security: Define the root directory to prevent directory traversal attacks
$rootDir = __DIR__; // Changed from __DIR__ . '/apps' to __DIR__ (current directory)
$currentDir = isset($_GET['dir']) ? $_GET['dir'] : '';
// Configure your domain - CHANGE THIS to your actual domain
$baseDomain= 'http://108.61.85.3'; // Change this to your domain
$webPath = ''; // Changed from '/apps' to '' (root web path)
// Sanitize the directory path
$currentDir = str_replace(['../', '..\\'], '', $currentDir);
$fullPath = realpath($rootDir . '/' . $currentDir);
// Security check: Ensure we're still within the root directory
if (!$fullPath || strpos($fullPath, realpath($rootDir)) !== 0) {
$fullPath = realpath($rootDir);
$currentDir = '';
}
$message = '';
$messageType = '';
// Handle form submissions (create, upload, delete, move)
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (isset($_POST['action'])) {
switch ($_POST['action']) {
case 'create_file':
$fileName = trim($_POST['file_name']);
if ($fileName && !preg_match('/[<>:"|?*]/', $fileName)) {
$newFilePath = $fullPath . '/' . $fileName;
if (!file_exists($newFilePath)) {
if (file_put_contents($newFilePath, '') !== false) {
setPermissions($newFilePath);
$message = "File '$fileName' created successfully with 777 permissions!";
$messageType = 'success';
} else {
$message = "Failed to create file '$fileName'.";
$messageType = 'error';
}
} else {
$message = "File '$fileName' already exists.";
$messageType = 'error';
}
} else {
$message = "Invalid file name.";
$messageType = 'error';
}
break;
case 'create_folder':
$folderName = trim($_POST['folder_name']);
if ($folderName && !preg_match('/[<>:"|?*]/', $folderName)) {
$newFolderPath = $fullPath . '/' . $folderName;
if (!file_exists($newFolderPath)) {
umask(0000); // Ensure proper permissions for new directories
if (mkdir($newFolderPath, 0777)) {
setPermissions($newFolderPath);
$message = "Folder '$folderName' created successfully with 777 permissions!";
$messageType = 'success';
} else {
$message = "Failed to create folder '$folderName'.";
$messageType = 'error';
}
} else {
$message = "Folder '$folderName' already exists.";
$messageType = 'error';
}
} else {
$message = "Invalid folder name.";
$messageType = 'error';
}
break;
case 'upload_file':
if (isset($_FILES['file']) && $_FILES['file']['error'] === UPLOAD_ERR_OK) {
$fileName = basename($_FILES['file']['name']);
$targetPath = $fullPath . '/' . $fileName;
if (move_uploaded_file($_FILES['file']['tmp_name'], $targetPath)) {
setPermissions($targetPath);
$message = "File '$fileName' uploaded successfully with 777 permissions!";
$messageType = 'success';
} else {
$message = "Failed to upload file '$fileName'.";
$messageType = 'error';
}
} else {
$message = "No file selected or upload error.";
$messageType = 'error';
}
break;
case 'delete_items':
if (isset($_POST['selected_items']) && is_array($_POST['selected_items'])) {
$deletedCount = 0;
foreach ($_POST['selected_items'] as $item) {
$itemPath = $fullPath . '/' . basename($item);
if (file_exists($itemPath)) {
if (is_dir($itemPath)) {
if (rmdir_recursive($itemPath)) {
$deletedCount++;
}
} else {
if (unlink($itemPath)) {
$deletedCount++;
}
}
}
}
if ($deletedCount > 0) {
$message = "$deletedCount item(s) deleted successfully!";
$messageType = 'success';
} else {
$message = "No items were deleted.";
$messageType = 'error';
}
} else {
$message = "No items selected for deletion.";
$messageType = 'error';
}
break;
case 'move_items':
if (isset($_POST['selected_items']) && is_array($_POST['selected_items']) && isset($_POST['destination_folder'])) {
$destinationDir = trim($_POST['destination_folder']);
// Handle moving to parent directory
if ($destinationDir === '..') {
if ($currentDir) {
$pathParts = explode('/', $currentDir);
array_pop($pathParts);
$destinationDir = implode('/', $pathParts);
} else {
$destinationDir = '';
}
}
// Sanitize destination path
$destinationDir = str_replace(['../', '..\\'], '', $destinationDir);
$destinationFullPath = realpath($rootDir . '/' . $destinationDir);
// Security check for destination
if ($destinationFullPath && strpos($destinationFullPath, realpath($rootDir)) === 0 && is_dir($destinationFullPath)) {
$movedCount = 0;
$errors = [];
foreach ($_POST['selected_items'] as $item) {
$itemName = basename($item);
$sourcePath = $fullPath . '/' . $itemName;
$destinationPath = $destinationFullPath . '/' . $itemName;
if (file_exists($sourcePath)) {
// Check if destination already exists
if (file_exists($destinationPath)) {
$errors[] = "Item '$itemName' already exists in destination folder.";
continue;
}
// Attempt to move the item
if (rename($sourcePath, $destinationPath)) {
setPermissions($destinationPath);
$movedCount++;
} else {
$errors[] = "Failed to move '$itemName'.";
}
} else {
$errors[] = "Item '$itemName' not found.";
}
}
if ($movedCount > 0) {
$message = "$movedCount item(s) moved successfully!";
if (!empty($errors)) {
$message .= " Errors: " . implode(', ', $errors);
}
$messageType = 'success';
} else {
$message = "No items were moved. " . implode(', ', $errors);
$messageType = 'error';
}
} else {
$message = "Invalid destination folder.";
$messageType = 'error';
}
} else {
$message = "No items selected for moving or no destination specified.";
$messageType = 'error';
}
break;
case 'change_permissions':
if (isset($_POST['selected_items']) && is_array($_POST['selected_items']) && isset($_POST['new_permissions'])) {
$newPermissions = trim($_POST['new_permissions']);
// Validate octal permission format
if (preg_match('/^[0-7]{3,4}$/', $newPermissions)) {
$octalPermissions = octdec($newPermissions);
$changedCount = 0;
$errors = [];
foreach ($_POST['selected_items'] as $item) {
$itemName = basename($item);
$itemPath = $fullPath . '/' . $itemName;
if (file_exists($itemPath)) {
if (chmod($itemPath, $octalPermissions)) {
$changedCount++;
} else {
$errors[] = "Failed to change permissions for '$itemName'.";
}
} else {
$errors[] = "Item '$itemName' not found.";
}
}
if ($changedCount > 0) {
$message = "$changedCount item(s) permissions changed to $newPermissions successfully!";
if (!empty($errors)) {
$message .= " Errors: " . implode(', ', $errors);
}
$messageType = 'success';
} else {
$message = "No permissions were changed. " . implode(', ', $errors);
$messageType = 'error';
}
} else {
$message = "Invalid permission format. Use 3 or 4 digit octal format (e.g., 755, 644).";
$messageType = 'error';
}
} else {
$message = "No items selected or no permissions specified.";
$messageType = 'error';
}
break;
}
}
}
// Recursive directory removal function
function rmdir_recursive($dir) {
if (!is_dir($dir)) return false;
$files = array_diff(scandir($dir), ['.', '..']);
foreach ($files as $file) {
$filePath = $dir . '/' . $file;
if (is_dir($filePath)) {
rmdir_recursive($filePath);
} else {
unlink($filePath);
}
}
return rmdir($dir);
}
// Helper function to ensure proper permissions
function setPermissions($path) {
if (file_exists($path)) {
chmod($path, 0777);
// Also try to set umask to ensure new files get proper permissions
umask(0000);
return true;
}
return false;
}
// Helper function to get file permissions in octal format
function getFilePermissions($path) {
if (file_exists($path)) {
return substr(sprintf('%o', fileperms($path)), -4);
}
return '0000';
}
// Get directory contents
$items = [];
if (is_dir($fullPath)) {
$files = scandir($fullPath);
foreach ($files as $file) {
if ($file !== '.' && $file !== '..') {
$filePath = $fullPath . '/' . $file;
$relativePath = $currentDir ? $currentDir . '/' . $file : $file;
$items[] = [
'name' => $file,
'path' => $relativePath,
'is_dir' => is_dir($filePath),
'size' => is_file($filePath) ? filesize($filePath) : 0,
'modified' => filemtime($filePath),
'permissions' => getFilePermissions($filePath)
];
}
}
}
// Sort items: directories first, then files, alphabetically
usort($items, function($a, $b) {
if ($a['is_dir'] !== $b['is_dir']) {
return $b['is_dir'] - $a['is_dir'];
}
return strcasecmp($a['name'], $b['name']);
});
// Get available folders for move operation
function getAvailableFolders($rootDir, $currentDir, $excludeItems = []) {
$folders = [];
// Add parent directory option if not in root
if ($currentDir) {
$folders[] = ['name' => '.. (Parent Directory)', 'path' => '..', 'display' => 'š .. (Parent Directory)'];
}
// Add root directory if not already there
if ($currentDir) {
$folders[] = ['name' => 'root', 'path' => '', 'display' => 'š root'];
}
// Get all subdirectories recursively
$getAllFolders = function($dir, $prefix = '') use (&$getAllFolders, $rootDir, $excludeItems) {
$result = [];
$fullDir = $rootDir . '/' . $dir;
if (is_dir($fullDir)) {
$files = scandir($fullDir);
foreach ($files as $file) {
if ($file !== '.' && $file !== '..' && is_dir($fullDir . '/' . $file)) {
$relativePath = $dir ? $dir . '/' . $file : $file;
// Skip if this folder is in the exclude list
if (!in_array($file, $excludeItems)) {
$displayName = $prefix . 'š ' . $file;
$result[] = ['name' => $file, 'path' => $relativePath, 'display' => $displayName];
// Recursively get subfolders
$subFolders = $getAllFolders($relativePath, $prefix . ' ');
$result = array_merge($result, $subFolders);
}
}
}
}
return $result;
};
// Get all folders except current directory
$allFolders = $getAllFolders('');
// Filter out current directory
foreach ($allFolders as $folder) {
if ($folder['path'] !== $currentDir) {
$folders[] = $folder;
}
}
return $folders;
}
// Helper function to format file sizes
function formatBytes($size, $precision = 2) {
$units = ['B', 'KB', 'MB', 'GB', 'TB'];
for ($i = 0; $size > 1024 && $i < count($units) - 1; $i++) {
$size /= 1024;
}
return round($size, $precision) . ' ' . $units[$i];
}
// Helper function to get breadcrumb navigation
function getBreadcrumbs($currentDir) {
$breadcrumbs = [['name' => 'root', 'path' => '']]; // Changed from 'apps' to 'root'
if ($currentDir) {
$parts = explode('/', $currentDir);
$path = '';
foreach ($parts as $part) {
$path .= ($path ? '/' : '') . $part;
$breadcrumbs[] = ['name' => $part, 'path' => $path];
}
}
return $breadcrumbs;
}
// Helper function to check if file is viewable
function isViewableFile($filename) {
$ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
$editableExts = ['txt', 'php', 'html', 'css', 'js', 'json', 'xml', 'md', 'py', 'java', 'cpp', 'c', 'h', 'sql', 'yml', 'yaml'];
$imageExts = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg'];
return in_array($ext, $editableExts) || in_array($ext, $imageExts);
}
// Helper function to check if file can be opened in browser
function isWebAccessible($filename) {
$ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
$webExts = ['html', 'htm', 'php', 'css', 'js', 'json', 'xml', 'txt', 'svg', 'jpg', 'jpeg', 'png', 'gif', 'pdf'];
return in_array($ext, $webExts);
}
// Helper function to generate web URL for file
function getWebUrl($currentDir, $filename, $baseDomain, $webPath) {
$path = $currentDir ? $currentDir . '/' . $filename : $filename;
return $baseDomain . $webPath . '/' . $path;
}
$availableFolders = getAvailableFolders($rootDir, $currentDir);
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PHP File Explorer</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background-color: #f5f5f5;
color: #333;
line-height: 1.6;
}
.container {
max-width: 1400px;
margin: 0 auto;
padding: 20px;
}
.navigation {
background: white;
padding: 15px 20px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
margin-bottom: 20px;
}
.breadcrumb {
display: flex;
align-items: center;
gap: 8px;
flex-wrap: wrap;
}
.breadcrumb a {
color: #3498db;
text-decoration: none;
padding: 4px 8px;
border-radius: 4px;
transition: background-color 0.2s;
}
.breadcrumb a:hover {
background-color: #ecf0f1;
}
.breadcrumb span {
color: #7f8c8d;
}
.message {
padding: 12px 20px;
border-radius: 6px;
margin-bottom: 20px;
}
.message.success {
background-color: #d4edda;
color: #155724;
border: 1px solid #c3e6cb;
}
.message.error {
background-color: #f8d7da;
color: #721c24;
border: 1px solid #f5c6cb;
}
.main-content {
display: block;
}
.file-browser {
background: white;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
margin-bottom: 20px;
}
.toolbar {
padding: 20px;
border-top: 1px solid #ecf0f1;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
gap: 12px;
}
.toolbar-section {
display: flex;
flex-direction: column;
gap: 8px;
}
.toolbar-section h3 {
color: #2c3e50;
font-size: 14px;
margin-bottom: 5px;
}
.form-group {
display: flex;
gap: 8px;
align-items: center;
}
.form-group input[type="text"],
.form-group input[type="file"],
.form-group select {
flex: 1;
padding: 6px 10px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 13px;
}
.btn {
padding: 6px 12px;
border: none;
border-radius: 4px;
font-size: 13px;
cursor: pointer;
transition: background-color 0.2s;
text-decoration: none;
display: inline-block;
text-align: center;
}
.btn-primary {
background-color: #3498db;
color: white;
}
.btn-primary:hover {
background-color: #2980b9;
}
.btn-success {
background-color: #27ae60;
color: white;
}
.btn-success:hover {
background-color: #229954;
}
.btn-danger {
background-color: #e74c3c;
color: white;
}
.btn-danger:hover {
background-color: #c0392b;
}
.btn:disabled {
background-color: #bdc3c7;
cursor: not-allowed;
}
.file-list {
max-height: 500px;
overflow-y: auto;
}
.file-item {
display: flex;
align-items: center;
padding: 8px 20px;
border-bottom: 1px solid #ecf0f1;
transition: background-color 0.2s;
}
.file-item:hover {
background-color: #f8f9fa;
}
.file-item:last-child {
border-bottom: none;
}
.file-checkbox {
margin-right: 8px;
}
.file-icon {
width: 20px;
height: 20px;
margin-right: 8px;
display: flex;
align-items: center;
justify-content: center;
font-size: 16px;
}
.file-name {
flex: 1;
min-width: 0;
}
.file-name a {
color: #2c3e50;
text-decoration: none;
font-weight: 500;
}
.file-name a:hover {
color: #3498db;
}
.file-actions {
margin-left: 8px;
}
.file-actions a {
color: #7f8c8d;
text-decoration: none;
font-size: 12px;
padding: 2px 6px;
border-radius: 3px;
margin-left: 4px;
}
.file-actions a:hover {
background-color: #ecf0f1;
}
.file-info {
display: flex;
gap: 15px;
color: #7f8c8d;
font-size: 12px;
margin-left: auto;
}
.file-permissions {
min-width: 40px;
text-align: center;
font-family: 'Courier New', monospace;
background-color: #ecf0f1;
padding: 2px 6px;
border-radius: 3px;
}
.file-size {
min-width: 60px;
text-align: right;
}
.empty-folder {
padding: 40px 20px;
text-align: center;
color: #7f8c8d;
font-style: italic;
}
.select-all {
padding: 10px 20px;
background: #f8f9fa;
border-bottom: 1px solid #ecf0f1;
}
.footer {
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
text-align: center;
}
.footer h1 {
color: #2c3e50;
margin: 0;
}
.move-section {
display: flex;
flex-direction: column;
gap: 8px;
}
.move-form {
display: flex;
flex-direction: column;
gap: 8px;
}
@media (max-width: 1024px) {
.toolbar {
grid-template-columns: 1fr;
}
}
</style>
</head>
<body>
<div class="container">
<!-- Navigation at the top -->
<div class="navigation">
<nav class="breadcrumb">
<?php
$breadcrumbs = getBreadcrumbs($currentDir);
foreach ($breadcrumbs as $index => $crumb):
?>
<?php if ($index > 0): ?>
<span>/</span>
<?php endif; ?>
<?php if ($index === count($breadcrumbs) - 1): ?>
<span><?= htmlspecialchars($crumb['name']) ?></span>
<?php else: ?>
<a href="?dir=<?= urlencode($crumb['path']) ?>">
<?= htmlspecialchars($crumb['name']) ?>
</a>
<?php endif; ?>
<?php endforeach; ?>
</nav>
</div>
<?php if ($message): ?>
<div class="message <?= $messageType ?>">
<?= htmlspecialchars($message) ?>
</div>
<?php endif; ?>
<!-- File Explorer -->
<div class="main-content">
<div class="file-browser">
<div class="file-list">
<?php if (empty($items)): ?>
<div class="empty-folder">
This folder is empty
</div>
<?php else: ?>
<div class="select-all">
<label>
<input type="checkbox" id="selectAll"> Select All
</label>
</div>
<?php foreach ($items as $item): ?>
<div class="file-item">
<input type="checkbox" class="file-checkbox" name="selected_items[]"
value="<?= htmlspecialchars($item['name']) ?>" form="deleteForm">
<div class="file-icon">
<?= $item['is_dir'] ? 'š' : 'š' ?>
</div>
<div class="file-name">
<?php if ($item['is_dir']): ?>
<a href="?dir=<?= urlencode($item['path']) ?>">
<?= htmlspecialchars($item['name']) ?>
</a>
<?php else: ?>
<span><?= htmlspecialchars($item['name']) ?></span>
<?php endif; ?>
</div>
<?php if (!$item['is_dir']): ?>
<div class="file-actions">
<?php if (isViewableFile($item['name'])): ?>
<a href="editor.php?dir=<?= urlencode($currentDir) ?>&view=<?= urlencode($item['name']) ?>">Edit</a>
<?php endif; ?>
<?php if (isWebAccessible($item['name'])): ?>
<a href="<?= getWebUrl($currentDir, $item['name'], $baseDomain, $webPath) ?>" target="_blank">Open</a>
<?php endif; ?>
</div>
<?php endif; ?>
<div class="file-info">
<div class="file-permissions" title="File permissions">
<?= htmlspecialchars($item['permissions']) ?>
</div>
<div class="file-size">
<?= $item['is_dir'] ? '-' : formatBytes($item['size']) ?>
</div>
</div>
</div>
<?php endforeach; ?>
<?php endif; ?>
</div>
<div class="toolbar">
<div class="toolbar-section">
<h3>š Change Permissions</h3>
<form method="post" id="permissionsForm" class="form-group">
<input type="hidden" name="action" value="change_permissions">
<input type="text" name="new_permissions" placeholder="755"
pattern="[0-7]{3,4}" maxlength="4" title="Enter 3 or 4 digit octal permissions (e.g., 755, 644)">
<button type="submit" class="btn btn-primary" id="permissionsBtn" disabled
onclick="return confirmPermissions()">
Change
</button>
</form>
</div>
<div class="toolbar-section">
<h3>š Create File</h3>
<form method="post" class="form-group">
<input type="hidden" name="action" value="create_file">
<input type="text" name="file_name" placeholder="filename.ext" required>
<button type="submit" class="btn btn-primary">Create</button>
</form>
</div>
<div class="toolbar-section">
<h3>š Create Folder</h3>
<form method="post" class="form-group">
<input type="hidden" name="action" value="create_folder">
<input type="text" name="folder_name" placeholder="Folder name" required>
<button type="submit" class="btn btn-primary">Create</button>
</form>
</div>
<div class="toolbar-section">
<h3>š Upload File</h3>
<form method="post" enctype="multipart/form-data" class="form-group">
<input type="hidden" name="action" value="upload_file">
<input type="file" name="file" required>
<button type="submit" class="btn btn-primary">Upload</button>
</form>
</div>
<div class="toolbar-section move-section">
<h3>š¦ Move Selected</h3>
<form method="post" id="moveForm" class="move-form">
<input type="hidden" name="action" value="move_items">
<select name="destination_folder" id="destinationFolder" required>
<option value="">Select destination folder...</option>
<?php foreach ($availableFolders as $folder): ?>
<option value="<?= htmlspecialchars($folder['path']) ?>">
<?= htmlspecialchars($folder['display']) ?>
</option>
<?php endforeach; ?>
</select>
<button type="submit" class="btn btn-success" id="moveBtn" disabled
onclick="return confirmMove()">
Move
</button>
</form>
</div>
<div class="toolbar-section">
<h3>šļø Delete Selected</h3>
<form method="post" id="deleteForm" class="form-group">
<input type="hidden" name="action" value="delete_items">
<button type="submit" class="btn btn-danger" id="deleteBtn" disabled
onclick="return confirmDelete()">
Delete
</button>
</form>
</div>
</div>
</div>
</div>
<!-- Title at the bottom -->
<div class="footer">
<h1>š File Explorer</h1>
</div>
</div>
<script>
// Handle select all functionality
const selectAllCheckbox = document.getElementById('selectAll');
const fileCheckboxes = document.querySelectorAll('.file-checkbox');
const deleteBtn = document.getElementById('deleteBtn');
const moveBtn = document.getElementById('moveBtn');
const permissionsBtn = document.getElementById('permissionsBtn');
const destinationFolder = document.getElementById('destinationFolder');
const permissionsInput = document.querySelector('input[name="new_permissions"]');
function updateButtons() {
const checkedBoxes = document.querySelectorAll('.file-checkbox:checked');
const hasSelection = checkedBoxes.length > 0;
const hasDestination = destinationFolder.value !== '';
const hasPermissions = permissionsInput.value !== '' && /^[0-7]{3,4}$/.test(permissionsInput.value);
deleteBtn.disabled = !hasSelection;
moveBtn.disabled = !hasSelection || !hasDestination;
permissionsBtn.disabled = !hasSelection || !hasPermissions;
}
if (selectAllCheckbox) {
selectAllCheckbox.addEventListener('change', function() {
fileCheckboxes.forEach(checkbox => {
checkbox.checked = this.checked;
});
updateButtons();
});
}
fileCheckboxes.forEach(checkbox => {
checkbox.addEventListener('change', function() {
const allChecked = Array.from(fileCheckboxes).every(cb => cb.checked);
const noneChecked = Array.from(fileCheckboxes).every(cb => !cb.checked);
if (selectAllCheckbox) {
selectAllCheckbox.checked = allChecked;
selectAllCheckbox.indeterminate = !allChecked && !noneChecked;
}
updateButtons();
});
});
// Update buttons when destination or permissions change
destinationFolder.addEventListener('change', function() {
updateButtons();
});
permissionsInput.addEventListener('input', function() {
updateButtons();
});
function confirmPermissions() {
const checkedBoxes = document.querySelectorAll('.file-checkbox:checked');
const permissionsValue = permissionsInput.value;
if (checkedBoxes.length === 0) {
alert('No items selected for permission change.');
return false;
}
if (!permissionsValue || !/^[0-7]{3,4}$/.test(permissionsValue)) {
alert('Please enter valid octal permissions (e.g., 755, 644).');
return false;
}
const itemNames = Array.from(checkedBoxes).map(cb => cb.value);
const itemList = itemNames.join('\n⢠');
return confirm(`Are you sure you want to change permissions to ${permissionsValue} for the following ${itemNames.length} item(s):\n\n⢠${itemList}`);
}
// Smart confirmation functions
function confirmDelete() {
const checkedBoxes = document.querySelectorAll('.file-checkbox:checked');
if (checkedBoxes.length === 0) {
alert('No items selected for deletion.');
return false;
}
const itemNames = Array.from(checkedBoxes).map(cb => cb.value);
const itemList = itemNames.join('\n⢠');
return confirm(`Are you sure you want to delete the following ${itemNames.length} item(s)?\n\n⢠${itemList}\n\nThis action cannot be undone.`);
}
function confirmMove() {
const checkedBoxes = document.querySelectorAll('.file-checkbox:checked');
const destinationSelect = document.getElementById('destinationFolder');
if (checkedBoxes.length === 0) {
alert('No items selected for moving.');
return false;
}
if (destinationSelect.value === '') {
alert('Please select a destination folder.');
return false;
}
const itemNames = Array.from(checkedBoxes).map(cb => cb.value);
const itemList = itemNames.join('\n⢠');
const destinationText = destinationSelect.options[destinationSelect.selectedIndex].text;
return confirm(`Are you sure you want to move the following ${itemNames.length} item(s):\n\n⢠${itemList}\n\nTo: ${destinationText}`);
}
// Add selected items to forms when submitting
document.getElementById('moveForm').addEventListener('submit', function() {
const checkedBoxes = document.querySelectorAll('.file-checkbox:checked');
checkedBoxes.forEach(checkbox => {
const hiddenInput = document.createElement('input');
hiddenInput.type = 'hidden';
hiddenInput.name = 'selected_items[]';
hiddenInput.value = checkbox.value;
this.appendChild(hiddenInput);
});
});
document.getElementById('permissionsForm').addEventListener('submit', function() {
const checkedBoxes = document.querySelectorAll('.file-checkbox:checked');
checkedBoxes.forEach(checkbox => {
const hiddenInput = document.createElement('input');
hiddenInput.type = 'hidden';
hiddenInput.name = 'selected_items[]';
hiddenInput.value = checkbox.value;
this.appendChild(hiddenInput);
});
});
// Initial state
updateButtons();
</script>
</body>
</html>