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']; ?> Krypton File Manager

Upload Files

Files

Filename Size Permissions Last Modified Actions
..
- - - -
isDirectory): ?> name); ?> name); ?>
size; ?> permissions; ?> lastModified; ?>
isDirectory): ?> isEditable): ?>