HEX
Server: LiteSpeed
System: Linux php-prod-1.spaceapp.ru 5.15.0-157-generic #167-Ubuntu SMP Wed Sep 17 21:35:53 UTC 2025 x86_64
User: xnsbb3110 (1041)
PHP: 8.1.33
Disabled: NONE
Upload Files
File: //usr/local/CyberCP/public/static/filemanager/filemanager.js
// Modern File Manager JavaScript
angular.module('fileManagerApp', ['angularFileUpload'])
    .config(['$interpolateProvider', function($interpolateProvider) {
        // Change Angular delimiters to avoid conflict with Django
        $interpolateProvider.startSymbol('[[');
        $interpolateProvider.endSymbol(']]');
    }])
    .filter('fileTypeFilter', function() {
        return function(files, type) {
            if (!type || type === 'all') return files;
            
            const typeMap = {
                'images': ['jpg', 'jpeg', 'png', 'gif', 'svg', 'webp', 'bmp', 'ico'],
                'documents': ['pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'rtf', 'odt'],
                'code': ['js', 'ts', 'py', 'php', 'html', 'css', 'json', 'xml', 'yml', 'yaml', 'md', 'sql', 'sh'],
                'archives': ['zip', 'rar', '7z', 'tar', 'gz', 'bz2', 'xz']
            };
            
            return files.filter(file => {
                if (file.type === 'folder') return true;
                const ext = file.name.toLowerCase().split('.').pop();
                return typeMap[type] && typeMap[type].includes(ext);
            });
        };
    })
    .controller('fileManagerCtrl', ['$scope', '$http', '$timeout', 'FileUploader', function($scope, $http, $timeout, FileUploader) {
        
        // Initialize scope variables
        $scope.viewMode = 'grid';
        $scope.files = [];
        $scope.filteredFiles = [];
        $scope.selectedFiles = [];
        $scope.breadcrumbs = [];
        $scope.currentPath = '/home';
        $scope.loading = false;
        $scope.searchQuery = '';
        $scope.filter = { type: 'all' };
        $scope.sortField = 'name';
        $scope.sortReverse = false;
        $scope.sidebarCollapsed = false;
        $scope.showPreview = false;
        $scope.previewFile = null;
        $scope.showContextMenu = false;
        $scope.contextFile = null;
        $scope.contextMenuX = 0;
        $scope.contextMenuY = 0;
        $scope.isDragging = false;
        $scope.clipboard = null;
        $scope.showUpload = false;  // Make sure this is false
        $scope.uploadQueue = [];
        $scope.uploadDragging = false;
        
        // Storage info (mock data - replace with real API)
        $scope.storageUsed = 45.2;
        $scope.storageTotal = 100;
        $scope.storagePercent = Math.round(($scope.storageUsed / $scope.storageTotal) * 100);
        
        // Get domain name
        $scope.domainName = document.getElementById('domainNameInitial')?.textContent || 'example.com';
        
        // Initialize file uploader
        const uploader = $scope.uploader = new FileUploader({
            url: '/filemanager/upload',
            headers: {
                'X-CSRFToken': getCookie('csrftoken')
            }
        });
        
        // File uploader filters
        uploader.filters.push({
            name: 'customFilter',
            fn: function(item) {
                return this.queue.length < 10;
            }
        });
        
        // File uploader callbacks
        uploader.onWhenAddingFileFailed = function(item, filter, options) {
            console.info('onWhenAddingFileFailed', item, filter, options);
        };
        
        uploader.onAfterAddingFile = function(fileItem) {
            console.info('onAfterAddingFile', fileItem);
            $scope.uploadQueue.push({
                name: fileItem.file.name,
                size: fileItem.file.size,
                progress: 0,
                status: 'pending'
            });
        };
        
        uploader.onAfterAddingAll = function(addedFileItems) {
            console.info('onAfterAddingAll', addedFileItems);
        };
        
        uploader.onBeforeUploadItem = function(item) {
            console.info('onBeforeUploadItem', item);
            item.formData.push({ path: $scope.currentPath });
        };
        
        uploader.onProgressItem = function(fileItem, progress) {
            console.info('onProgressItem', fileItem, progress);
            const queueItem = $scope.uploadQueue.find(f => f.name === fileItem.file.name);
            if (queueItem) {
                queueItem.progress = progress;
                queueItem.status = 'uploading';
            }
        };
        
        uploader.onProgressAll = function(progress) {
            console.info('onProgressAll', progress);
        };
        
        uploader.onSuccessItem = function(fileItem, response, status, headers) {
            console.info('onSuccessItem', fileItem, response, status, headers);
            const queueItem = $scope.uploadQueue.find(f => f.name === fileItem.file.name);
            if (queueItem) {
                queueItem.progress = 100;
                queueItem.status = 'success';
            }
            $scope.refreshFiles();
        };
        
        uploader.onErrorItem = function(fileItem, response, status, headers) {
            console.info('onErrorItem', fileItem, response, status, headers);
            const queueItem = $scope.uploadQueue.find(f => f.name === fileItem.file.name);
            if (queueItem) {
                queueItem.status = 'error';
            }
        };
        
        uploader.onCancelItem = function(fileItem, response, status, headers) {
            console.info('onCancelItem', fileItem, response, status, headers);
        };
        
        uploader.onCompleteItem = function(fileItem, response, status, headers) {
            console.info('onCompleteItem', fileItem, response, status, headers);
        };
        
        uploader.onCompleteAll = function() {
            console.info('onCompleteAll');
            $timeout(function() {
                $scope.uploadQueue = [];
                $scope.showUpload = false;
            }, 2000);
        };
        
        // Initialize
        $scope.init = function() {
            $scope.loadFiles();
            $scope.setupEventListeners();
            $scope.updateBreadcrumbs();
        };
        
        // Load files from server
        $scope.loadFiles = function() {
            $scope.loading = true;
            
            // Mock data - replace with real API call
            $timeout(function() {
                $scope.files = [
                    { name: 'Documents', type: 'folder', size: 0, modified: new Date(), permissions: 'drwxr-xr-x', itemCount: 24 },
                    { name: 'Images', type: 'folder', size: 0, modified: new Date(), permissions: 'drwxr-xr-x', itemCount: 156 },
                    { name: 'Videos', type: 'folder', size: 0, modified: new Date(), permissions: 'drwxr-xr-x', itemCount: 12 },
                    { name: 'index.html', type: 'file', size: 24567, modified: new Date(), permissions: '-rw-r--r--' },
                    { name: 'style.css', type: 'file', size: 12890, modified: new Date(), permissions: '-rw-r--r--' },
                    { name: 'script.js', type: 'file', size: 45678, modified: new Date(), permissions: '-rw-r--r--' },
                    { name: 'logo.png', type: 'file', size: 89012, modified: new Date(), permissions: '-rw-r--r--', thumbnail: '/static/images/not-available-preview.png' },
                    { name: 'data.json', type: 'file', size: 3456, modified: new Date(), permissions: '-rw-r--r--' },
                    { name: 'backup.zip', type: 'file', size: 567890, modified: new Date(), permissions: '-rw-r--r--' }
                ];
                
                $scope.files.forEach(file => {
                    file.selected = false;
                    file.starred = false;
                });
                
                $scope.loading = false;
            }, 800);
        };
        
        // Refresh files
        $scope.refreshFiles = function() {
            $scope.loadFiles();
        };
        
        // Update breadcrumbs
        $scope.updateBreadcrumbs = function() {
            const parts = $scope.currentPath.split('/').filter(p => p);
            $scope.breadcrumbs = [{ name: 'Home', path: '/home' }];
            
            let path = '';
            parts.forEach(part => {
                if (part !== 'home') {
                    path += '/' + part;
                    $scope.breadcrumbs.push({ name: part, path: '/home' + path });
                }
            });
        };
        
        // Set view mode
        $scope.setViewMode = function(mode) {
            $scope.viewMode = mode;
        };
        
        // Set filter
        $scope.setFilter = function(type) {
            $scope.filter.type = type;
        };
        
        // Toggle sidebar
        $scope.toggleSidebar = function() {
            $scope.sidebarCollapsed = !$scope.sidebarCollapsed;
        };
        
        // Navigate to path
        $scope.navigateTo = function(path) {
            $scope.currentPath = path;
            $scope.updateBreadcrumbs();
            $scope.loadFiles();
        };
        
        // Select file
        $scope.selectFile = function(file, event) {
            if (event.ctrlKey || event.metaKey) {
                // Multi-select with Ctrl/Cmd
                file.selected = !file.selected;
            } else if (event.shiftKey && $scope.selectedFiles.length > 0) {
                // Range select with Shift
                const lastSelected = $scope.selectedFiles[$scope.selectedFiles.length - 1];
                const startIndex = $scope.files.indexOf(lastSelected);
                const endIndex = $scope.files.indexOf(file);
                const start = Math.min(startIndex, endIndex);
                const end = Math.max(startIndex, endIndex);
                
                for (let i = start; i <= end; i++) {
                    $scope.files[i].selected = true;
                }
            } else {
                // Single select
                $scope.files.forEach(f => f.selected = false);
                file.selected = true;
            }
            
            $scope.updateSelectedFiles();
            
            // Show preview for single selection
            if ($scope.selectedFiles.length === 1) {
                $scope.showPreview = true;
                $scope.previewFile = file;
            } else {
                $scope.showPreview = false;
                $scope.previewFile = null;
            }
        };
        
        // Update selected files array
        $scope.updateSelectedFiles = function() {
            $scope.selectedFiles = $scope.files.filter(f => f.selected);
        };
        
        // Open file
        $scope.openFile = function(file) {
            if (file.type === 'folder') {
                $scope.navigateTo($scope.currentPath + '/' + file.name);
            } else {
                // Open file based on type
                const ext = file.name.toLowerCase().split('.').pop();
                const codeExts = ['js', 'ts', 'py', 'php', 'html', 'css', 'json', 'xml', 'yml', 'yaml', 'md', 'sql', 'sh'];
                
                if (codeExts.includes(ext)) {
                    // Open in code editor
                    $scope.editFile(file);
                } else {
                    // Download file
                    $scope.downloadFile(file);
                }
            }
        };
        
        // Toggle star
        $scope.toggleStar = function(file, event) {
            if (event) {
                event.stopPropagation();
            }
            file.starred = !file.starred;
            
            // Save starred state (implement API call)
            console.log('Starred:', file.name, file.starred);
        };
        
        // Sort by field
        $scope.sortBy = function(field) {
            if ($scope.sortField === field) {
                $scope.sortReverse = !$scope.sortReverse;
            } else {
                $scope.sortField = field;
                $scope.sortReverse = false;
            }
        };
        
        // Select all
        $scope.selectAll = function() {
            $scope.files.forEach(f => f.selected = true);
            $scope.updateSelectedFiles();
        };
        
        // Unselect all
        $scope.unSelectAll = function() {
            $scope.files.forEach(f => f.selected = false);
            $scope.updateSelectedFiles();
            $scope.showPreview = false;
            $scope.previewFile = null;
        };
        
        // Clear selection
        $scope.clearSelection = function() {
            $scope.unSelectAll();
        };
        
        // Toggle select all
        $scope.toggleSelectAll = function() {
            if ($scope.selectAll) {
                $scope.selectAll();
            } else {
                $scope.unSelectAll();
            }
        };
        
        // Search files
        $scope.searchFiles = function() {
            // Search is handled by Angular filter
        };
        
        // Format file size
        $scope.formatFileSize = function(bytes) {
            if (!bytes) return '0 B';
            const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
            const i = Math.floor(Math.log(bytes) / Math.log(1024));
            return Math.round(bytes / Math.pow(1024, i) * 100) / 100 + ' ' + sizes[i];
        };
        
        // Format date
        $scope.formatDate = function(date) {
            if (!date) return '';
            const d = new Date(date);
            const now = new Date();
            const diff = now - d;
            
            if (diff < 86400000) { // Less than 24 hours
                if (diff < 3600000) { // Less than 1 hour
                    const mins = Math.floor(diff / 60000);
                    return mins + ' min ago';
                }
                const hours = Math.floor(diff / 3600000);
                return hours + ' hour' + (hours > 1 ? 's' : '') + ' ago';
            }
            
            return d.toLocaleDateString();
        };
        
        // Get file icon
        $scope.getFileIcon = function(file) {
            if (file.type === 'folder') {
                return 'fa-folder';
            }
            
            const ext = file.name.toLowerCase().split('.').pop();
            const iconMap = {
                // Images
                'jpg': 'fa-image', 'jpeg': 'fa-image', 'png': 'fa-image', 'gif': 'fa-image',
                'svg': 'fa-image', 'webp': 'fa-image', 'bmp': 'fa-image', 'ico': 'fa-image',
                // Documents
                'pdf': 'fa-file-pdf', 'doc': 'fa-file-word', 'docx': 'fa-file-word',
                'xls': 'fa-file-excel', 'xlsx': 'fa-file-excel', 'ppt': 'fa-file-powerpoint',
                'pptx': 'fa-file-powerpoint', 'txt': 'fa-file-alt', 'rtf': 'fa-file-alt',
                // Code
                'js': 'fa-file-code', 'ts': 'fa-file-code', 'py': 'fa-file-code',
                'php': 'fa-file-code', 'html': 'fa-file-code', 'css': 'fa-file-code',
                'json': 'fa-file-code', 'xml': 'fa-file-code', 'sql': 'fa-file-code',
                // Archives
                'zip': 'fa-file-archive', 'rar': 'fa-file-archive', '7z': 'fa-file-archive',
                'tar': 'fa-file-archive', 'gz': 'fa-file-archive', 'bz2': 'fa-file-archive',
                // Media
                'mp3': 'fa-file-audio', 'wav': 'fa-file-audio', 'flac': 'fa-file-audio',
                'mp4': 'fa-file-video', 'avi': 'fa-file-video', 'mkv': 'fa-file-video'
            };
            
            return iconMap[ext] || 'fa-file';
        };
        
        // Show context menu
        $scope.showContextMenu = function(file, event) {
            event.preventDefault();
            event.stopPropagation();
            
            $scope.contextFile = file;
            $scope.contextMenuX = event.pageX;
            $scope.contextMenuY = event.pageY;
            $scope.showContextMenu = true;
            
            // Adjust position if menu goes off screen
            $timeout(function() {
                const menu = document.querySelector('.fm-context-menu');
                if (menu) {
                    const rect = menu.getBoundingClientRect();
                    if (rect.right > window.innerWidth) {
                        $scope.contextMenuX = event.pageX - rect.width;
                    }
                    if (rect.bottom > window.innerHeight) {
                        $scope.contextMenuY = event.pageY - rect.height;
                    }
                }
            });
        };
        
        // Hide context menu
        $scope.hideContextMenu = function() {
            $scope.showContextMenu = false;
            $scope.contextFile = null;
        };
        
        // Download file
        $scope.downloadFile = function(file, event) {
            if (event) {
                event.stopPropagation();
            }
            
            // Implement download logic
            console.log('Download:', file.name);
            window.location.href = '/filemanager/download?path=' + encodeURIComponent($scope.currentPath + '/' + file.name);
        };
        
        // Download selected
        $scope.downloadSelected = function() {
            if ($scope.selectedFiles.length === 1) {
                $scope.downloadFile($scope.selectedFiles[0]);
            } else {
                // Create zip and download
                console.log('Download multiple:', $scope.selectedFiles);
            }
        };
        
        // Share file
        $scope.shareFile = function(file, event) {
            if (event) {
                event.stopPropagation();
            }
            
            // Implement share logic
            console.log('Share:', file.name);
            alert('Share functionality coming soon!');
        };
        
        // Share selected
        $scope.shareSelected = function() {
            console.log('Share selected:', $scope.selectedFiles);
            alert('Share functionality coming soon!');
        };
        
        // Delete file
        $scope.deleteFile = function(file, event) {
            if (event) {
                event.stopPropagation();
            }
            
            if (confirm('Are you sure you want to delete "' + file.name + '"?')) {
                // Implement delete logic
                console.log('Delete:', file.name);
                $scope.refreshFiles();
            }
        };
        
        // Delete selected
        $scope.deleteSelected = function() {
            if (confirm('Are you sure you want to delete ' + $scope.selectedFiles.length + ' items?')) {
                console.log('Delete selected:', $scope.selectedFiles);
                $scope.refreshFiles();
            }
        };
        
        // Move selected
        $scope.moveSelected = function() {
            console.log('Move selected:', $scope.selectedFiles);
            // Show move dialog
        };
        
        // Copy selected
        $scope.copySelected = function() {
            $scope.clipboard = {
                action: 'copy',
                files: [...$scope.selectedFiles]
            };
            console.log('Copy selected:', $scope.selectedFiles);
        };
        
        // Cut file
        $scope.cutFile = function(file) {
            $scope.clipboard = {
                action: 'cut',
                files: [file]
            };
            $scope.hideContextMenu();
        };
        
        // Copy file
        $scope.copyFile = function(file) {
            $scope.clipboard = {
                action: 'copy',
                files: [file]
            };
            $scope.hideContextMenu();
        };
        
        // Paste file
        $scope.pasteFile = function() {
            if ($scope.clipboard) {
                console.log('Paste:', $scope.clipboard);
                // Implement paste logic
                $scope.refreshFiles();
            }
            $scope.hideContextMenu();
        };
        
        // Rename file
        $scope.renameFile = function(file) {
            const newName = prompt('Enter new name:', file.name);
            if (newName && newName !== file.name) {
                console.log('Rename:', file.name, 'to', newName);
                // Implement rename logic
                $scope.refreshFiles();
            }
            $scope.hideContextMenu();
        };
        
        // Edit file
        $scope.editFile = function(file) {
            console.log('Edit:', file.name);
            // Open editor modal
            window.location.href = '/filemanager/edit?path=' + encodeURIComponent($scope.currentPath + '/' + file.name);
        };
        
        // Show properties
        $scope.showProperties = function(file) {
            console.log('Properties:', file);
            alert('File: ' + file.name + '\nSize: ' + $scope.formatFileSize(file.size) + '\nModified: ' + $scope.formatDate(file.modified) + '\nPermissions: ' + file.permissions);
            $scope.hideContextMenu();
        };
        
        // Close preview
        $scope.closePreview = function() {
            $scope.showPreview = false;
            $scope.previewFile = null;
        };
        
        // Show upload modal
        $scope.showUploadModal = function() {
            $scope.showUpload = true;
            $scope.uploadQueue = [];
        };
        
        // Close upload modal
        $scope.closeUploadModal = function() {
            $scope.showUpload = false;
            if (uploader.queue.length > 0) {
                uploader.clearQueue();
            }
        };
        
        // Create new folder
        $scope.createNewFolder = function() {
            const folderName = prompt('Enter folder name:');
            if (folderName) {
                console.log('Create folder:', folderName);
                // Implement create folder logic
                $scope.refreshFiles();
            }
        };
        
        // Remove from upload queue
        $scope.removeFromQueue = function(file) {
            const index = $scope.uploadQueue.indexOf(file);
            if (index > -1) {
                $scope.uploadQueue.splice(index, 1);
            }
        };
        
        // Start upload
        $scope.startUpload = function() {
            uploader.uploadAll();
        };
        
        // Setup event listeners
        $scope.setupEventListeners = function() {
            // Hide context menu on click
            document.addEventListener('click', function() {
                $scope.$apply(function() {
                    $scope.hideContextMenu();
                });
            });
            
            // Keyboard shortcuts
            document.addEventListener('keydown', function(e) {
                $scope.$apply(function() {
                    // Ctrl/Cmd + A - Select all
                    if ((e.ctrlKey || e.metaKey) && e.key === 'a') {
                        e.preventDefault();
                        $scope.selectAll();
                    }
                    
                    // Delete - Delete selected
                    if (e.key === 'Delete' && $scope.selectedFiles.length > 0) {
                        e.preventDefault();
                        $scope.deleteSelected();
                    }
                    
                    // F2 - Rename
                    if (e.key === 'F2' && $scope.selectedFiles.length === 1) {
                        e.preventDefault();
                        $scope.renameFile($scope.selectedFiles[0]);
                    }
                    
                    // Ctrl/Cmd + C - Copy
                    if ((e.ctrlKey || e.metaKey) && e.key === 'c' && $scope.selectedFiles.length > 0) {
                        e.preventDefault();
                        $scope.copySelected();
                    }
                    
                    // Ctrl/Cmd + X - Cut
                    if ((e.ctrlKey || e.metaKey) && e.key === 'x' && $scope.selectedFiles.length > 0) {
                        e.preventDefault();
                        $scope.clipboard = {
                            action: 'cut',
                            files: [...$scope.selectedFiles]
                        };
                    }
                    
                    // Ctrl/Cmd + V - Paste
                    if ((e.ctrlKey || e.metaKey) && e.key === 'v' && $scope.clipboard) {
                        e.preventDefault();
                        $scope.pasteFile();
                    }
                    
                    // Escape - Clear selection
                    if (e.key === 'Escape') {
                        $scope.clearSelection();
                        $scope.hideContextMenu();
                    }
                });
            });
            
            // Drag and drop
            const filesContainer = document.querySelector('.fm-files-container');
            if (filesContainer) {
                filesContainer.addEventListener('dragover', function(e) {
                    e.preventDefault();
                    $scope.$apply(function() {
                        $scope.isDragging = true;
                    });
                });
                
                filesContainer.addEventListener('dragleave', function(e) {
                    if (e.target === filesContainer) {
                        $scope.$apply(function() {
                            $scope.isDragging = false;
                        });
                    }
                });
                
                filesContainer.addEventListener('drop', function(e) {
                    e.preventDefault();
                    $scope.$apply(function() {
                        $scope.isDragging = false;
                        // Handle dropped files
                        const files = e.dataTransfer.files;
                        if (files.length > 0) {
                            $scope.showUploadModal();
                            // Add files to uploader
                            for (let i = 0; i < files.length; i++) {
                                uploader.addToQueue(files[i]);
                            }
                        }
                    });
                });
            }
            
            // Upload modal drag and drop
            const uploadZone = document.querySelector('.fm-upload-zone');
            if (uploadZone) {
                uploadZone.addEventListener('dragover', function(e) {
                    e.preventDefault();
                    $scope.$apply(function() {
                        $scope.uploadDragging = true;
                    });
                });
                
                uploadZone.addEventListener('dragleave', function(e) {
                    $scope.$apply(function() {
                        $scope.uploadDragging = false;
                    });
                });
                
                uploadZone.addEventListener('drop', function(e) {
                    e.preventDefault();
                    $scope.$apply(function() {
                        $scope.uploadDragging = false;
                        // Handle dropped files
                        const files = e.dataTransfer.files;
                        for (let i = 0; i < files.length; i++) {
                            uploader.addToQueue(files[i]);
                        }
                    });
                });
            }
        };
        
        // Initialize on load
        $scope.init();
    }])
    .directive('ngRightClick', ['$parse', function($parse) {
        return function(scope, element, attrs) {
            const fn = $parse(attrs.ngRightClick);
            element.bind('contextmenu', function(event) {
                scope.$apply(function() {
                    event.preventDefault();
                    fn(scope, {$event: event});
                });
            });
        };
    }]);

// Helper function to get CSRF token
function getCookie(name) {
    let cookieValue = null;
    if (document.cookie && document.cookie !== '') {
        const cookies = document.cookie.split(';');
        for (let i = 0; i < cookies.length; i++) {
            const cookie = cookies[i].trim();
            if (cookie.substring(0, name.length + 1) === (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}