Download index.php from Urban-Guy/Drive: direct link, hf CLI and curl.
- Browser
- Download file 66.1 kB
-
https://huggingface.co/spaces/Urban-Guy/Drive/resolve/main/index.php
- Command line
-
hf download hf://spaces/Urban-Guy/Drive/index.php
-
curl -L -o index.php https://huggingface.co/spaces/Urban-Guy/Drive/resolve/main/index.php
66.1 kB
| session_start(); | |
| function getGoogleDriveIcon($fileName, $mimeType) { | |
| $extension = strtolower(pathinfo($fileName, PATHINFO_EXTENSION)); | |
| // FOLDERS - Google Drive green | |
| if ($mimeType === 'folder') { | |
| return [ | |
| 'icon' => 'folder', | |
| 'color' => '#5F6368', // Google's folder gray | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'folder-item' | |
| ]; | |
| } | |
| // IMAGES - Show thumbnail | |
| if (strpos($mimeType, 'image/') === 0) { | |
| return [ | |
| 'icon' => 'image', | |
| 'color' => '#EA4335', // Google red | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'image-file', | |
| 'showThumbnail' => true | |
| ]; | |
| } | |
| // VIDEOS - Show thumbnail with play icon | |
| if (strpos($mimeType, 'video/') === 0) { | |
| return [ | |
| 'icon' => 'play_circle_filled', | |
| 'color' => '#EA4335', // Google red | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'video-file', | |
| 'showThumbnail' => true | |
| ]; | |
| } | |
| // AUDIO FILES | |
| if (strpos($mimeType, 'audio/') === 0) { | |
| return [ | |
| 'icon' => 'audiotrack', | |
| 'color' => '#EA4335', // Google red | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'audio-file' | |
| ]; | |
| } | |
| // PDF FILES - Google red | |
| if ($mimeType === 'application/pdf' || $extension === 'pdf') { | |
| return [ | |
| 'icon' => 'picture_as_pdf', | |
| 'color' => '#EA4335', // Google red | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'pdf-file' | |
| ]; | |
| } | |
| // MICROSOFT WORD / GOOGLE DOCS - Google blue | |
| if (in_array($extension, ['doc', 'docx']) || strpos($mimeType, 'word') !== false) { | |
| return [ | |
| 'icon' => 'description', | |
| 'color' => '#4285F4', // Google Docs blue | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'word-file' | |
| ]; | |
| } | |
| // MICROSOFT EXCEL / GOOGLE SHEETS - Google green | |
| if (in_array($extension, ['xls', 'xlsx']) || strpos($mimeType, 'excel') !== false || strpos($mimeType, 'spreadsheet') !== false) { | |
| return [ | |
| 'icon' => 'grid_on', | |
| 'color' => '#0F9D58', // Google Sheets green | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'excel-file' | |
| ]; | |
| } | |
| // MICROSOFT POWERPOINT / GOOGLE SLIDES - Google yellow | |
| if (in_array($extension, ['ppt', 'pptx']) || strpos($mimeType, 'powerpoint') !== false || strpos($mimeType, 'presentation') !== false) { | |
| return [ | |
| 'icon' => 'slideshow', | |
| 'color' => '#FBBC04', // Google Slides yellow | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'powerpoint-file' | |
| ]; | |
| } | |
| // ARCHIVE FILES (ZIP, RAR, etc.) | |
| if (in_array($extension, ['zip', 'rar', '7z', 'tar', 'gz', 'bz2'])) { | |
| return [ | |
| 'icon' => 'folder_zip', | |
| 'color' => '#F4B400', // Yellow | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'archive-file' | |
| ]; | |
| } | |
| // CODE FILES | |
| if (in_array($extension, ['html', 'css', 'js', 'php', 'py', 'java', 'cpp', 'c', 'json', 'xml', 'sql', 'sh', 'bat', 'ts', 'jsx', 'tsx'])) { | |
| return [ | |
| 'icon' => 'code', | |
| 'color' => '#5F6368', // Gray | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'code-file' | |
| ]; | |
| } | |
| // TEXT FILES | |
| if (strpos($mimeType, 'text/') === 0 || in_array($extension, ['txt', 'md', 'log'])) { | |
| return [ | |
| 'icon' => 'description', | |
| 'color' => '#5F6368', // Gray | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'text-file' | |
| ]; | |
| } | |
| // EXECUTABLE FILES (.exe, .msi, .app) ⭐ FIXES YOUR BROKEN ICON ISSUE | |
| if (in_array($extension, ['exe', 'msi', 'app', 'deb', 'rpm', 'apk'])) { | |
| return [ | |
| 'icon' => 'insert_drive_file', | |
| 'color' => '#80868B', // Light gray (like Google Drive) | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'executable-file' | |
| ]; | |
| } | |
| // BINARY FILES (.bin, .dll, .dat) ⭐ FIXES YOUR BROKEN ICON ISSUE | |
| if (in_array($extension, ['bin', 'dat', 'dll', 'sys', 'so', 'o'])) { | |
| return [ | |
| 'icon' => 'insert_drive_file', | |
| 'color' => '#80868B', // Light gray (like Google Drive) | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'binary-file' | |
| ]; | |
| } | |
| // DISK IMAGES (ISO, IMG, etc.) | |
| if (in_array($extension, ['iso', 'img', 'dmg', 'vhd'])) { | |
| return [ | |
| 'icon' => 'album', | |
| 'color' => '#9334E6', // Purple | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'disk-file' | |
| ]; | |
| } | |
| // DEFAULT - Generic file (like Google Drive) | |
| return [ | |
| 'icon' => 'insert_drive_file', | |
| 'color' => '#80868B', // Light gray | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'default-file' | |
| ]; | |
| } | |
| /** | |
| * Get Google Drive-style icon and color for file types | |
| * Returns exact Google colors and appropriate Material Icons | |
| */ | |
| function getGoogleDriveIcon($fileName, $mimeType) { | |
| $extension = strtolower(pathinfo($fileName, PATHINFO_EXTENSION)); | |
| // FOLDERS | |
| if ($mimeType === 'folder') { | |
| return [ | |
| 'icon' => 'folder', | |
| 'color' => '#5F6368', | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'folder-item' | |
| ]; | |
| } | |
| // IMAGES - Show thumbnail | |
| if (strpos($mimeType, 'image/') === 0) { | |
| return [ | |
| 'icon' => 'image', | |
| 'color' => '#EA4335', | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'image-file', | |
| 'showThumbnail' => true | |
| ]; | |
| } | |
| // VIDEOS | |
| if (strpos($mimeType, 'video/') === 0) { | |
| return [ | |
| 'icon' => 'play_circle_filled', | |
| 'color' => '#EA4335', | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'video-file', | |
| 'showThumbnail' => true | |
| ]; | |
| } | |
| // AUDIO FILES | |
| if (strpos($mimeType, 'audio/') === 0) { | |
| return [ | |
| 'icon' => 'audiotrack', | |
| 'color' => '#EA4335', | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'audio-file' | |
| ]; | |
| } | |
| // PDF FILES | |
| if ($mimeType === 'application/pdf' || $extension === 'pdf') { | |
| return [ | |
| 'icon' => 'picture_as_pdf', | |
| 'color' => '#EA4335', | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'pdf-file' | |
| ]; | |
| } | |
| // WORD DOCS | |
| if (in_array($extension, ['doc', 'docx']) || strpos($mimeType, 'word') !== false) { | |
| return [ | |
| 'icon' => 'description', | |
| 'color' => '#4285F4', | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'word-file' | |
| ]; | |
| } | |
| // EXCEL/SHEETS | |
| if (in_array($extension, ['xls', 'xlsx']) || strpos($mimeType, 'excel') !== false || strpos($mimeType, 'spreadsheet') !== false) { | |
| return [ | |
| 'icon' => 'grid_on', | |
| 'color' => '#0F9D58', | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'excel-file' | |
| ]; | |
| } | |
| // POWERPOINT/SLIDES | |
| if (in_array($extension, ['ppt', 'pptx']) || strpos($mimeType, 'powerpoint') !== false || strpos($mimeType, 'presentation') !== false) { | |
| return [ | |
| 'icon' => 'slideshow', | |
| 'color' => '#FBBC04', | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'powerpoint-file' | |
| ]; | |
| } | |
| // ARCHIVES | |
| if (in_array($extension, ['zip', 'rar', '7z', 'tar', 'gz', 'bz2'])) { | |
| return [ | |
| 'icon' => 'folder_zip', | |
| 'color' => '#F4B400', | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'archive-file' | |
| ]; | |
| } | |
| // CODE FILES | |
| if (in_array($extension, ['html', 'css', 'js', 'php', 'py', 'java', 'cpp', 'c', 'json', 'xml', 'sql', 'sh', 'bat'])) { | |
| return [ | |
| 'icon' => 'code', | |
| 'color' => '#5F6368', | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'code-file' | |
| ]; | |
| } | |
| // TEXT FILES | |
| if (strpos($mimeType, 'text/') === 0 || in_array($extension, ['txt', 'md', 'log'])) { | |
| return [ | |
| 'icon' => 'description', | |
| 'color' => '#5F6368', | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'text-file' | |
| ]; | |
| } | |
| // EXECUTABLE FILES (.exe, .msi, .app) ⭐ FIXES YOUR ISSUE | |
| if (in_array($extension, ['exe', 'msi', 'app', 'deb', 'rpm', 'apk'])) { | |
| return [ | |
| 'icon' => 'insert_drive_file', | |
| 'color' => '#80868B', | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'executable-file' | |
| ]; | |
| } | |
| // BINARY FILES (.bin, .dll, .dat) ⭐ FIXES YOUR ISSUE | |
| if (in_array($extension, ['bin', 'dat', 'dll', 'sys', 'so', 'o'])) { | |
| return [ | |
| 'icon' => 'insert_drive_file', | |
| 'color' => '#80868B', | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'binary-file' | |
| ]; | |
| } | |
| // DISK IMAGES | |
| if (in_array($extension, ['iso', 'img', 'dmg', 'vhd'])) { | |
| return [ | |
| 'icon' => 'album', | |
| 'color' => '#9334E6', | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'disk-file' | |
| ]; | |
| } | |
| // DEFAULT | |
| return [ | |
| 'icon' => 'insert_drive_file', | |
| 'color' => '#80868B', | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'default-file' | |
| ]; | |
| } | |
| <!-- Then in your file rendering section, replace the current preview code with this: --> | |
| foreach ($displayFiles as $file): | |
| <div class="file-item <?php echo $file['type'] === 'folder' ? 'folder-item' : ''; ?> <?php | |
| $iconData = getFileIconClass($file['name'], $file['type']); | |
| echo $iconData['class']; | |
| ?>" | |
| data-file-id="<?php echo htmlspecialchars($file['id']); ?>" | |
| data-file-name="<?php echo htmlspecialchars($file['name']); ?>" | |
| data-file-path="<?php echo htmlspecialchars($file['path']); ?>" | |
| data-file-type="<?php echo htmlspecialchars($file['type']); ?>" | |
| data-starred="<?php echo $file['starred'] ? 'true' : 'false'; ?>" | |
| onclick="selectFile(event, '<?php echo htmlspecialchars($file['id']); ?>')" | |
| ondblclick="<?php | |
| if ($file['type'] === 'folder') { | |
| echo "window.location.href='index.php?view=my-drive&folder=" . htmlspecialchars($file['id']) . "'"; | |
| } else { | |
| echo "openFile('" . htmlspecialchars($file['path']) . "', '" . htmlspecialchars($file['name']) . "', '" . htmlspecialchars($file['type']) . "', '" . htmlspecialchars($file['id']) . "')"; | |
| } | |
| " | |
| draggable="true"> | |
| <div class="file-preview"> | |
| <?php if ($file['type'] === 'folder'): ?> | |
| <!-- Folder icon --> | |
| <span class="material-icons folder-icon">folder</span> | |
| <?php elseif (strpos($file['type'], 'image/') === 0): ?> | |
| <!-- Image preview --> | |
| <img src=" echo htmlspecialchars($file['path']); " alt=" echo htmlspecialchars($file['name']); "> | |
| <?php else: ?> | |
| <!-- File icon for non-image files --> | |
| <?php | |
| $iconData = getFileIconClass($file['name'], $file['type']); | |
| ?> | |
| <div class="file-icon-preview echo $iconData['class']; "> | |
| <span class="material-icons"><?php echo $iconData['icon']; ?></span> | |
| </div> | |
| <?php endif; ?> | |
| <!-- Star badge --> | |
| <?php if ($file['starred']): ?> | |
| <span class="star-badge material-icons">star</span> | |
| <?php endif; ?> | |
| <!-- Shared indicator --> | |
| <?php if (isset($file['shared']) && $file['shared']['enabled']): ?> | |
| <span class="shared-indicator">SHARED</span> | |
| <?php endif; ?> | |
| <!-- Star button on hover --> | |
| <button class="star-button" onclick="toggleStar('<?php echo htmlspecialchars($file['id']); ?>', event)"> | |
| <span class="material-icons"><?php echo $file['starred'] ? 'star' : 'star_border'; ?></span> | |
| </button> | |
| </div> | |
| <div class="file-info"> | |
| <div class="file-name"><?php echo htmlspecialchars($file['name']); ?></div> | |
| <div class="file-details"> | |
| <?php if ($file['type'] !== 'folder'): ?> | |
| <?php echo formatFileSize($file['size']); ?> • | |
| <?php endif; ?> | |
| <?php echo date('M d, Y', $file['modified']); ?> | |
| </div> | |
| </div> | |
| </div> | |
| <?php | |
| session_start(); | |
| // ===== ADD THIS ENTIRE FUNCTION HERE ===== ↓↓↓ | |
| /** | |
| * Get Google Drive-style icon and color for file types | |
| * Returns exact Google colors and appropriate Material Icons | |
| */ | |
| function getGoogleDriveIcon($fileName, $mimeType) { | |
| $extension = strtolower(pathinfo($fileName, PATHINFO_EXTENSION)); | |
| // FOLDERS - Google Drive green | |
| if ($mimeType === 'folder') { | |
| return [ | |
| 'icon' => 'folder', | |
| 'color' => '#5F6368', // Google's folder gray | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'folder-item' | |
| ]; | |
| } | |
| // IMAGES - Show thumbnail | |
| if (strpos($mimeType, 'image/') === 0) { | |
| return [ | |
| 'icon' => 'image', | |
| 'color' => '#EA4335', // Google red | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'image-file', | |
| 'showThumbnail' => true | |
| ]; | |
| } | |
| // VIDEOS - Show thumbnail with play icon | |
| if (strpos($mimeType, 'video/') === 0) { | |
| return [ | |
| 'icon' => 'play_circle_filled', | |
| 'color' => '#EA4335', // Google red | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'video-file', | |
| 'showThumbnail' => true | |
| ]; | |
| } | |
| // AUDIO FILES | |
| if (strpos($mimeType, 'audio/') === 0) { | |
| return [ | |
| 'icon' => 'audiotrack', | |
| 'color' => '#EA4335', // Google red | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'audio-file' | |
| ]; | |
| } | |
| // PDF FILES - Google red | |
| if ($mimeType === 'application/pdf' || $extension === 'pdf') { | |
| return [ | |
| 'icon' => 'picture_as_pdf', | |
| 'color' => '#EA4335', // Google red | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'pdf-file' | |
| ]; | |
| } | |
| // MICROSOFT WORD / GOOGLE DOCS - Google blue | |
| if (in_array($extension, ['doc', 'docx']) || strpos($mimeType, 'word') !== false) { | |
| return [ | |
| 'icon' => 'description', | |
| 'color' => '#4285F4', // Google Docs blue | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'word-file' | |
| ]; | |
| } | |
| // MICROSOFT EXCEL / GOOGLE SHEETS - Google green | |
| if (in_array($extension, ['xls', 'xlsx']) || strpos($mimeType, 'excel') !== false || strpos($mimeType, 'spreadsheet') !== false) { | |
| return [ | |
| 'icon' => 'grid_on', | |
| 'color' => '#0F9D58', // Google Sheets green | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'excel-file' | |
| ]; | |
| } | |
| // MICROSOFT POWERPOINT / GOOGLE SLIDES - Google yellow | |
| if (in_array($extension, ['ppt', 'pptx']) || strpos($mimeType, 'powerpoint') !== false || strpos($mimeType, 'presentation') !== false) { | |
| return [ | |
| 'icon' => 'slideshow', | |
| 'color' => '#FBBC04', // Google Slides yellow | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'powerpoint-file' | |
| ]; | |
| } | |
| // ARCHIVE FILES (ZIP, RAR, etc.) | |
| if (in_array($extension, ['zip', 'rar', '7z', 'tar', 'gz', 'bz2'])) { | |
| return [ | |
| 'icon' => 'folder_zip', | |
| 'color' => '#F4B400', // Yellow | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'archive-file' | |
| ]; | |
| } | |
| // CODE FILES | |
| if (in_array($extension, ['html', 'css', 'js', 'php', 'py', 'java', 'cpp', 'c', 'json', 'xml', 'sql', 'sh', 'bat', 'ts', 'jsx', 'tsx'])) { | |
| return [ | |
| 'icon' => 'code', | |
| 'color' => '#5F6368', // Gray | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'code-file' | |
| ]; | |
| } | |
| // TEXT FILES | |
| if (strpos($mimeType, 'text/') === 0 || in_array($extension, ['txt', 'md', 'log'])) { | |
| return [ | |
| 'icon' => 'description', | |
| 'color' => '#5F6368', // Gray | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'text-file' | |
| ]; | |
| } | |
| // EXECUTABLE FILES (.exe, .msi, .app) ⭐ FIXES YOUR BROKEN ICON ISSUE | |
| if (in_array($extension, ['exe', 'msi', 'app', 'deb', 'rpm', 'apk'])) { | |
| return [ | |
| 'icon' => 'insert_drive_file', | |
| 'color' => '#80868B', // Light gray (like Google Drive) | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'executable-file' | |
| ]; | |
| } | |
| // BINARY FILES (.bin, .dll, .dat) ⭐ FIXES YOUR BROKEN ICON ISSUE | |
| if (in_array($extension, ['bin', 'dat', 'dll', 'sys', 'so', 'o'])) { | |
| return [ | |
| 'icon' => 'insert_drive_file', | |
| 'color' => '#80868B', // Light gray (like Google Drive) | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'binary-file' | |
| ]; | |
| } | |
| // DISK IMAGES (ISO, IMG, etc.) | |
| if (in_array($extension, ['iso', 'img', 'dmg', 'vhd'])) { | |
| return [ | |
| 'icon' => 'album', | |
| 'color' => '#9334E6', // Purple | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'disk-file' | |
| ]; | |
| } | |
| // DEFAULT - Generic file (like Google Drive) | |
| return [ | |
| 'icon' => 'insert_drive_file', | |
| 'color' => '#80868B', // Light gray | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'default-file' | |
| ]; | |
| } | |
| // ===== END OF FUNCTION ===== ↑↑↑ | |
| // Check if this is a shared link | |
| if (isset($_GET['share']) && !empty($_GET['share'])) { | |
| // ... rest of your code continues | |
| // Check if this is a shared link | |
| if (isset($_GET['share']) && !empty($_GET['share'])) { | |
| $shareId = $_GET['share']; | |
| $metadataFile = 'data/files.json'; | |
| if (file_exists($metadataFile)) { | |
| $metadata = json_decode(file_get_contents($metadataFile), true); | |
| if ($metadata && isset($metadata['files'])) { | |
| foreach ($metadata['files'] as $file) { | |
| if ($file['id'] === $shareId) { | |
| // ALL FILES ARE PUBLIC - No checks! | |
| $fileName = $file['name']; | |
| $filePath = $file['path']; | |
| $mimeType = $file['type']; | |
| $fileSize = $file['size']; | |
| $modifiedTime = $file['modified']; | |
| if (file_exists($filePath)) { | |
| if (file_exists('view_shared.php')) { | |
| include 'view_shared.php'; | |
| exit; | |
| } | |
| } | |
| die('File not found'); | |
| } | |
| } | |
| } | |
| } | |
| die('File not found in database'); | |
| } | |
| // Create necessary directories | |
| $dirs = ['uploads', 'data', 'trash']; | |
| foreach ($dirs as $dir) { | |
| if (!is_dir($dir)) { | |
| mkdir($dir, 0755, true); | |
| } | |
| } | |
| // Initialize metadata file | |
| $metadataFile = 'data/files.json'; | |
| if (!file_exists($metadataFile)) { | |
| file_put_contents($metadataFile, json_encode(['files' => []], JSON_PRETTY_PRINT)); | |
| } | |
| // Load metadata | |
| function loadMetadata() { | |
| global $metadataFile; | |
| $data = file_get_contents($metadataFile); | |
| return json_decode($data, true); | |
| } | |
| // Save metadata | |
| function saveMetadata($metadata) { | |
| global $metadataFile; | |
| file_put_contents($metadataFile, json_encode($metadata, JSON_PRETTY_PRINT)); | |
| } | |
| // Delete directory recursively | |
| function deleteDirectory($dir) { | |
| if (!is_dir($dir)) return; | |
| $files = array_diff(scandir($dir), ['.', '..']); | |
| foreach ($files as $file) { | |
| $path = $dir . '/' . $file; | |
| is_dir($path) ? deleteDirectory($path) : unlink($path); | |
| } | |
| rmdir($dir); | |
| } | |
| // Calculate storage usage | |
| function calculateStorageUsage($directory = 'uploads') { | |
| $totalSize = 0; | |
| if (is_dir($directory)) { | |
| $files = new RecursiveIteratorIterator( | |
| new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS), | |
| RecursiveIteratorIterator::CHILD_FIRST | |
| ); | |
| foreach ($files as $file) { | |
| if ($file->isFile()) { | |
| $totalSize += $file->getSize(); | |
| } | |
| } | |
| } | |
| return $totalSize; | |
| } | |
| // Format bytes to human readable | |
| function formatBytes($bytes, $precision = 2) { | |
| if ($bytes >= 1073741824) { | |
| return number_format($bytes / 1073741824, $precision) . ' GB'; | |
| } elseif ($bytes >= 1048576) { | |
| return number_format($bytes / 1048576, $precision) . ' MB'; | |
| } elseif ($bytes >= 1024) { | |
| return number_format($bytes / 1024, $precision) . ' KB'; | |
| } else { | |
| return $bytes . ' bytes'; | |
| } | |
| } | |
| // Storage quota (50 GB in bytes) - FIXED TYPO | |
| $storageQuota = 50 * 1024 * 1024 * 1024; | |
| $storageUsed = calculateStorageUsage(); | |
| $storagePercentage = ($storageUsed / $storageQuota) * 100; | |
| // Determine storage color | |
| if ($storagePercentage >= 95) { | |
| $storageColor = '#ea4335'; | |
| } elseif ($storagePercentage >= 80) { | |
| $storageColor = '#f9ab00'; | |
| } else { | |
| $storageColor = '#1a73e8'; | |
| } | |
| // Get current view and folder | |
| $view = isset($_GET['view']) ? $_GET['view'] : 'my-drive'; | |
| $currentFolder = isset($_GET['folder']) ? $_GET['folder'] : 'root'; | |
| // Handle file upload via AJAX | |
| if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['files'])) { | |
| $uploadedFiles = $_FILES['files']; | |
| $totalFiles = count($uploadedFiles['name']); | |
| $metadata = loadMetadata(); | |
| $results = []; | |
| $targetFolder = isset($_POST['targetFolder']) ? $_POST['targetFolder'] : 'root'; | |
| // Determine upload path | |
| $uploadPath = 'uploads/'; | |
| if ($targetFolder !== 'root') { | |
| foreach ($metadata['files'] as $file) { | |
| if ($file['id'] === $targetFolder && $file['type'] === 'folder') { | |
| $uploadPath = $file['path'] . '/'; | |
| break; | |
| } | |
| } | |
| } | |
| for ($i = 0; $i < $totalFiles; $i++) { | |
| if ($uploadedFiles['error'][$i] === UPLOAD_ERR_OK) { | |
| $fileName = basename($uploadedFiles['name'][$i]); | |
| $tempFile = $uploadedFiles['tmp_name'][$i]; | |
| $targetFile = $uploadPath . $fileName; | |
| $counter = 1; | |
| $originalName = pathinfo($fileName, PATHINFO_FILENAME); | |
| $extension = pathinfo($fileName, PATHINFO_EXTENSION); | |
| while (file_exists($targetFile)) { | |
| $fileName = $originalName . '_' . $counter . '.' . $extension; | |
| $targetFile = $uploadPath . $fileName; | |
| $counter++; | |
| } | |
| if (move_uploaded_file($tempFile, $targetFile)) { | |
| $fileId = uniqid(); | |
| $newFile = [ | |
| 'id' => $fileId, | |
| 'name' => $fileName, | |
| 'path' => $targetFile, | |
| 'type' => getFileMimeType($targetFile), | |
| 'size' => filesize($targetFile), | |
| 'created' => time(), | |
| 'modified' => time(), | |
| 'accessed' => time(), | |
| 'starred' => false, | |
| 'trashed' => false, | |
| 'trashedDate' => null, | |
| 'parentFolder' => $targetFolder | |
| ]; | |
| $metadata['files'][] = $newFile; | |
| $results[] = ['success' => true, 'file' => $newFile]; | |
| } else { | |
| $results[] = ['success' => false, 'error' => 'Failed to upload ' . $fileName]; | |
| } | |
| } | |
| } | |
| saveMetadata($metadata); | |
| if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && | |
| strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest') { | |
| header('Content-Type: application/json'); | |
| echo json_encode([ | |
| 'success' => true, | |
| 'files' => $results, | |
| 'storageUsed' => calculateStorageUsage(), | |
| 'storageQuota' => $storageQuota | |
| ]); | |
| exit; | |
| } | |
| header('Location: index.php?view=' . $view . '&folder=' . $currentFolder); | |
| exit; | |
| } | |
| // Auto-delete files older than 30 days in trash | |
| $metadata = loadMetadata(); | |
| $thirtyDaysAgo = time() - (30 * 24 * 60 * 60); | |
| foreach ($metadata['files'] as $key => $file) { | |
| if (isset($file['trashed']) && $file['trashed'] && | |
| isset($file['trashedDate']) && $file['trashedDate'] && | |
| $file['trashedDate'] < $thirtyDaysAgo) { | |
| if ($file['type'] === 'folder') { | |
| if (is_dir($file['path'])) { | |
| deleteDirectory($file['path']); | |
| } | |
| } else { | |
| if (file_exists($file['path'])) { | |
| unlink($file['path']); | |
| } | |
| } | |
| unset($metadata['files'][$key]); | |
| } | |
| } | |
| $metadata['files'] = array_values($metadata['files']); | |
| saveMetadata($metadata); | |
| // Get files based on view | |
| function getFiles($view, $currentFolder) { | |
| $metadata = loadMetadata(); | |
| $files = $metadata['files']; | |
| switch ($view) { | |
| case 'my-drive': | |
| return array_filter($files, function($f) use ($currentFolder) { | |
| return !$f['trashed'] && $f['parentFolder'] === $currentFolder; | |
| }); | |
| case 'recent': | |
| $recentFiles = array_filter($files, function($f) { return !$f['trashed']; }); | |
| usort($recentFiles, function($a, $b) { return $b['accessed'] - $a['accessed']; }); | |
| return array_slice($recentFiles, 0, 20); | |
| case 'starred': | |
| return array_filter($files, function($f) { return $f['starred'] && !$f['trashed']; }); | |
| case 'trash': | |
| return array_filter($files, function($f) { return $f['trashed']; }); | |
| default: | |
| return array_filter($files, function($f) use ($currentFolder) { | |
| return !$f['trashed'] && $f['parentFolder'] === $currentFolder; | |
| }); | |
| } | |
| } | |
| $files = getFiles($view, $currentFolder); | |
| // Get folder breadcrumbs | |
| function getBreadcrumbs($folderId) { | |
| if ($folderId === 'root') return []; | |
| $metadata = loadMetadata(); | |
| $breadcrumbs = []; | |
| $currentId = $folderId; | |
| while ($currentId !== 'root') { | |
| foreach ($metadata['files'] as $file) { | |
| if ($file['id'] === $currentId) { | |
| array_unshift($breadcrumbs, $file); | |
| $currentId = isset($file['parentFolder']) ? $file['parentFolder'] : 'root'; | |
| break; | |
| } | |
| } | |
| if (!isset($file) || $file['id'] !== $currentId) break; | |
| } | |
| return $breadcrumbs; | |
| } | |
| $breadcrumbs = getBreadcrumbs($currentFolder); | |
| function formatFileSize($bytes) { | |
| 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'; | |
| } else { | |
| return $bytes . ' bytes'; | |
| } | |
| } | |
| function getFileMimeType($filePath) { | |
| // Try to get MIME type using multiple methods | |
| $mimeType = false; | |
| // Method 1: Use mime_content_type (most accurate) | |
| if (function_exists('mime_content_type')) { | |
| $mimeType = mime_content_type($filePath); | |
| } | |
| // Method 2: Use finfo (fallback) | |
| if (!$mimeType && function_exists('finfo_open')) { | |
| $finfo = finfo_open(FILEINFO_MIME_TYPE); | |
| $mimeType = finfo_file($finfo, $filePath); | |
| finfo_close($finfo); | |
| } | |
| // Method 3: Detect by extension (for .exe, .bin, etc.) | |
| if ($mimeType === 'application/octet-stream' || !$mimeType) { | |
| $extension = strtolower(pathinfo($filePath, PATHINFO_EXTENSION)); | |
| $extensionMap = [ | |
| // Executables | |
| 'exe' => 'application/x-msdownload', | |
| 'bin' => 'application/x-binary', | |
| 'dll' => 'application/x-msdownload', | |
| 'app' => 'application/x-executable', | |
| 'apk' => 'application/vnd.android.package-archive', | |
| 'dmg' => 'application/x-apple-diskimage', | |
| 'msi' => 'application/x-msdownload', | |
| // Archives | |
| 'zip' => 'application/zip', | |
| 'rar' => 'application/x-rar-compressed', | |
| '7z' => 'application/x-7z-compressed', | |
| 'tar' => 'application/x-tar', | |
| 'gz' => 'application/gzip', | |
| 'iso' => 'application/x-iso9660-image', | |
| // Documents | |
| 'doc' => 'application/msword', | |
| 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', | |
| 'xls' => 'application/vnd.ms-excel', | |
| 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', | |
| 'ppt' => 'application/vnd.ms-powerpoint', | |
| 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation', | |
| // Code files | |
| 'js' => 'application/javascript', | |
| 'json' => 'application/json', | |
| 'py' => 'text/x-python', | |
| 'java' => 'text/x-java', | |
| 'cpp' => 'text/x-c++', | |
| 'c' => 'text/x-c', | |
| 'php' => 'text/x-php', | |
| 'html' => 'text/html', | |
| 'css' => 'text/css', | |
| // Images | |
| 'jpg' => 'image/jpeg', | |
| 'jpeg' => 'image/jpeg', | |
| 'png' => 'image/png', | |
| 'gif' => 'image/gif', | |
| 'bmp' => 'image/bmp', | |
| 'svg' => 'image/svg+xml', | |
| 'webp' => 'image/webp', | |
| // Videos | |
| 'mp4' => 'video/mp4', | |
| 'avi' => 'video/x-msvideo', | |
| 'mov' => 'video/quicktime', | |
| 'wmv' => 'video/x-ms-wmv', | |
| 'mkv' => 'video/x-matroska', | |
| // Audio | |
| 'mp3' => 'audio/mpeg', | |
| 'wav' => 'audio/wav', | |
| 'ogg' => 'audio/ogg', | |
| 'flac' => 'audio/flac' | |
| ]; | |
| if (isset($extensionMap[$extension])) { | |
| $mimeType = $extensionMap[$extension]; | |
| } | |
| } | |
| // Default fallback | |
| return $mimeType ?: 'application/octet-stream'; | |
| } | |
| function getFileIcon($mimeType) { | |
| // Image files | |
| if (strpos($mimeType, 'image/') === 0) { | |
| return 'https://ssl.gstatic.com/docs/doclist/images/mediatype/icon_1_image_x16.png'; | |
| } | |
| // Video files | |
| if (strpos($mimeType, 'video/') === 0) { | |
| return 'https://ssl.gstatic.com/docs/doclist/images/mediatype/icon_1_video_x16.png'; | |
| } | |
| // Audio files | |
| if (strpos($mimeType, 'audio/') === 0) { | |
| return 'https://ssl.gstatic.com/docs/doclist/images/mediatype/icon_1_audio_x16.png'; | |
| } | |
| // PDF files | |
| if ($mimeType === 'application/pdf') { | |
| return 'https://ssl.gstatic.com/docs/doclist/images/mediatype/icon_1_pdf_x16.png'; | |
| } | |
| // Text files | |
| if (strpos($mimeType, 'text/') === 0) { | |
| return 'https://ssl.gstatic.com/docs/doclist/images/mediatype/icon_1_text_x16.png'; | |
| } | |
| // Document files (Word, Excel, PowerPoint, etc.) | |
| if (in_array($mimeType, [ | |
| 'application/msword', | |
| 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', | |
| 'application/vnd.oasis.opendocument.text' | |
| ])) { | |
| return 'https://ssl.gstatic.com/docs/doclist/images/mediatype/icon_1_document_x16.png'; | |
| } | |
| // Spreadsheet files | |
| if (in_array($mimeType, [ | |
| 'application/vnd.ms-excel', | |
| 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', | |
| 'application/vnd.oasis.opendocument.spreadsheet' | |
| ])) { | |
| return 'https://ssl.gstatic.com/docs/doclist/images/mediatype/icon_1_spreadsheet_x16.png'; | |
| } | |
| // Presentation files | |
| if (in_array($mimeType, [ | |
| 'application/vnd.ms-powerpoint', | |
| 'application/vnd.openxmlformats-officedocument.presentationml.presentation', | |
| 'application/vnd.oasis.opendocument.presentation' | |
| ])) { | |
| return 'https://ssl.gstatic.com/docs/doclist/images/mediatype/icon_1_presentation_x16.png'; | |
| } | |
| // Archive files (ZIP, RAR, 7Z, TAR, etc.) | |
| if (in_array($mimeType, [ | |
| 'application/zip', | |
| 'application/x-zip-compressed', | |
| 'application/x-rar-compressed', | |
| 'application/x-7z-compressed', | |
| 'application/x-tar', | |
| 'application/gzip', | |
| 'application/x-compressed' | |
| ])) { | |
| return 'https://ssl.gstatic.com/docs/doclist/images/mediatype/icon_1_archive_x16.png'; | |
| } | |
| // Code files | |
| if (in_array($mimeType, [ | |
| 'application/javascript', | |
| 'application/json', | |
| 'application/xml', | |
| 'text/javascript', | |
| 'text/x-python', | |
| 'text/x-java', | |
| 'text/x-c', | |
| 'text/x-c++', | |
| 'text/x-php', | |
| 'text/html', | |
| 'text/css' | |
| ])) { | |
| return 'https://ssl.gstatic.com/docs/doclist/images/mediatype/icon_1_code_x16.png'; | |
| } | |
| // Executable files (.exe, .bin, .app, .dmg, .apk, etc.) | |
| if (in_array($mimeType, [ | |
| 'application/x-msdownload', | |
| 'application/x-executable', | |
| 'application/x-binary', | |
| 'application/octet-stream', | |
| 'application/x-msdos-program', | |
| 'application/x-dosexec', | |
| 'application/vnd.microsoft.portable-executable' | |
| ])) { | |
| return 'https://ssl.gstatic.com/docs/doclist/images/mediatype/icon_1_executable_x16.png'; | |
| } | |
| // APK (Android Package) | |
| if ($mimeType === 'application/vnd.android.package-archive') { | |
| return 'https://ssl.gstatic.com/docs/doclist/images/mediatype/icon_1_executable_x16.png'; | |
| } | |
| // DMG (Mac Disk Image) | |
| if ($mimeType === 'application/x-apple-diskimage') { | |
| return 'https://ssl.gstatic.com/docs/doclist/images/mediatype/icon_1_executable_x16.png'; | |
| } | |
| // ISO (Disk Image) | |
| if ($mimeType === 'application/x-iso9660-image') { | |
| return 'https://ssl.gstatic.com/docs/doclist/images/mediatype/icon_1_archive_x16.png'; | |
| } | |
| // Default for unknown types | |
| return 'https://ssl.gstatic.com/docs/doclist/images/mediatype/icon_1_generic_x16.png'; | |
| } | |
| function getGoogleDriveIcon($fileName, $mimeType) { | |
| $extension = strtolower(pathinfo($fileName, PATHINFO_EXTENSION)); | |
| // FOLDERS | |
| if ($mimeType === 'folder') { | |
| return [ | |
| 'icon' => 'folder', | |
| 'color' => '#5F6368', | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'folder-item' | |
| ]; | |
| } | |
| // IMAGES - Show thumbnail | |
| if (strpos($mimeType, 'image/') === 0) { | |
| return [ | |
| 'icon' => 'image', | |
| 'color' => '#EA4335', | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'image-file', | |
| 'showThumbnail' => true | |
| ]; | |
| } | |
| // VIDEOS | |
| if (strpos($mimeType, 'video/') === 0) { | |
| return [ | |
| 'icon' => 'play_circle_filled', | |
| 'color' => '#EA4335', | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'video-file', | |
| 'showThumbnail' => true | |
| ]; | |
| } | |
| // AUDIO FILES | |
| if (strpos($mimeType, 'audio/') === 0) { | |
| return [ | |
| 'icon' => 'audiotrack', | |
| 'color' => '#EA4335', | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'audio-file' | |
| ]; | |
| } | |
| // PDF FILES | |
| if ($mimeType === 'application/pdf' || $extension === 'pdf') { | |
| return [ | |
| 'icon' => 'picture_as_pdf', | |
| 'color' => '#EA4335', | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'pdf-file' | |
| ]; | |
| } | |
| // WORD DOCS | |
| if (in_array($extension, ['doc', 'docx']) || strpos($mimeType, 'word') !== false) { | |
| return [ | |
| 'icon' => 'description', | |
| 'color' => '#4285F4', | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'word-file' | |
| ]; | |
| } | |
| // EXCEL/SHEETS | |
| if (in_array($extension, ['xls', 'xlsx']) || strpos($mimeType, 'excel') !== false || strpos($mimeType, 'spreadsheet') !== false) { | |
| return [ | |
| 'icon' => 'grid_on', | |
| 'color' => '#0F9D58', | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'excel-file' | |
| ]; | |
| } | |
| // POWERPOINT/SLIDES | |
| if (in_array($extension, ['ppt', 'pptx']) || strpos($mimeType, 'powerpoint') !== false || strpos($mimeType, 'presentation') !== false) { | |
| return [ | |
| 'icon' => 'slideshow', | |
| 'color' => '#FBBC04', | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'powerpoint-file' | |
| ]; | |
| } | |
| // ARCHIVES | |
| if (in_array($extension, ['zip', 'rar', '7z', 'tar', 'gz', 'bz2'])) { | |
| return [ | |
| 'icon' => 'folder_zip', | |
| 'color' => '#F4B400', | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'archive-file' | |
| ]; | |
| } | |
| // CODE FILES | |
| if (in_array($extension, ['html', 'css', 'js', 'php', 'py', 'java', 'cpp', 'c', 'json', 'xml', 'sql', 'sh', 'bat'])) { | |
| return [ | |
| 'icon' => 'code', | |
| 'color' => '#5F6368', | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'code-file' | |
| ]; | |
| } | |
| // TEXT FILES | |
| if (strpos($mimeType, 'text/') === 0 || in_array($extension, ['txt', 'md', 'log'])) { | |
| return [ | |
| 'icon' => 'description', | |
| 'color' => '#5F6368', | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'text-file' | |
| ]; | |
| } | |
| // EXECUTABLE FILES (.exe, .msi, .app) ⭐ FIXES YOUR ISSUE | |
| if (in_array($extension, ['exe', 'msi', 'app', 'deb', 'rpm', 'apk'])) { | |
| return [ | |
| 'icon' => 'insert_drive_file', | |
| 'color' => '#80868B', | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'executable-file' | |
| ]; | |
| } | |
| // BINARY FILES (.bin, .dll, .dat) ⭐ FIXES YOUR ISSUE | |
| if (in_array($extension, ['bin', 'dat', 'dll', 'sys', 'so', 'o'])) { | |
| return [ | |
| 'icon' => 'insert_drive_file', | |
| 'color' => '#80868B', | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'binary-file' | |
| ]; | |
| } | |
| // DISK IMAGES | |
| if (in_array($extension, ['iso', 'img', 'dmg', 'vhd'])) { | |
| return [ | |
| 'icon' => 'album', | |
| 'color' => '#9334E6', | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'disk-file' | |
| ]; | |
| } | |
| // DEFAULT | |
| return [ | |
| 'icon' => 'insert_drive_file', | |
| 'color' => '#80868B', | |
| 'bgColor' => '#ffffff', | |
| 'class' => 'default-file' | |
| ]; | |
| } | |
| function timeAgo($timestamp) { | |
| $diff = time() - $timestamp; | |
| if ($diff < 60) { | |
| return 'Just now'; | |
| } elseif ($diff < 3600) { | |
| $mins = floor($diff / 60); | |
| return $mins . ' minute' . ($mins > 1 ? 's' : '') . ' ago'; | |
| } elseif ($diff < 86400) { | |
| $hours = floor($diff / 3600); | |
| return $hours . ' hour' . ($hours > 1 ? 's' : '') . ' ago'; | |
| } elseif ($diff < 604800) { | |
| $days = floor($diff / 86400); | |
| return $days . ' day' . ($days > 1 ? 's' : '') . ' ago'; | |
| } else { | |
| return date('M j, Y', $timestamp); | |
| } | |
| } | |
| ?> | |
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>My Drive - Google Drive</title> | |
| <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap" rel="stylesheet"> | |
| <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"> | |
| <link rel="stylesheet" href="style.css"> | |
| </head> | |
| <body> | |
| <div class="header"> | |
| <div class="header-left"> | |
| <!-- MOBILE HAMBURGER MENU (NEW) --> | |
| <div class="hamburger-menu" onclick="toggleMobileSidebar()"> | |
| <span class="material-icons">menu</span> | |
| </div> | |
| <div class="header-logo" onclick="window.location.href='index.php'"> | |
| <!-- SVG LOGO --> | |
| <svg width="40" height="40" viewBox="0 0 40 40"> | |
| <path fill="#4285F4" d="M22.56 12.25c0-.78-.69-1.41-1.54-1.41H12.89c-.85 0-1.54.63-1.54 1.41s.69 1.41 1.54 1.41h8.13c.85 0 1.54-.63 1.54-1.41z"/> | |
| <path fill="#34A853" d="M26.28 16.25c0-.78-.69-1.41-1.54-1.41H12.89c-.85 0-1.54.63-1.54 1.41s.69 1.41 1.54 1.41h11.85c.85 0 1.54-.63 1.54-1.41z"/> | |
| <path fill="#FBBC04" d="M28.6 20.25c0-.78-.69-1.41-1.54-1.41H12.89c-.85 0-1.54.63-1.54 1.41s.69 1.41 1.54 1.41h14.17c.85 0 1.54-.63 1.54-1.41z"/> | |
| <path fill="#EA4335" d="M26.28 24.25c0-.78-.69-1.41-1.54-1.41H12.89c-.85 0-1.54.63-1.54 1.41s.69 1.41 1.54 1.41h11.85c.85 0 1.54-.63 1.54-1.41z"/> | |
| </svg> | |
| </div> | |
| <span class="header-title">Drive</span> | |
| </div> | |
| <div class="header-center"> | |
| <div class="search-box"> | |
| <span class="material-icons search-icon">search</span> | |
| <input type="text" class="search-input" id="searchInput" placeholder="Search in Drive"> | |
| </div> | |
| </div> | |
| <div class="header-right"> | |
| <!-- MOBILE SEARCH TOGGLE (NEW) --> | |
| <div class="header-icon search-toggle" onclick="toggleMobileSearch()"> | |
| <span class="material-icons">search</span> | |
| </div> | |
| <div class="header-icon"><span class="material-icons">help_outline</span></div> | |
| <div class="header-icon"><span class="material-icons">settings</span></div> | |
| <div class="header-icon"><span class="material-icons">apps</span></div> | |
| <div class="header-icon"><span class="material-icons">account_circle</span></div> | |
| </div> | |
| </div> | |
| <div class="sidebar"> | |
| <div class="new-button" id="newButton"> | |
| <span class="material-icons">add</span> | |
| <span>New</span> | |
| </div> | |
| <div class="new-dropdown" id="newDropdown"> | |
| <div class="dropdown-item" onclick="showFolderDialog()"> | |
| <span class="material-icons">create_new_folder</span> | |
| <span>New folder</span> | |
| </div> | |
| <div class="dropdown-item" onclick="triggerFileUpload()"> | |
| <span class="material-icons">upload_file</span> | |
| <span>File upload</span> | |
| </div> | |
| <div class="dropdown-item" onclick="triggerFolderUpload()"> | |
| <span class="material-icons">drive_folder_upload</span> | |
| <span>Folder upload</span> | |
| </div> | |
| <div class="dropdown-item" onclick="showWebFetchDialog()"> | |
| <span class="material-icons">cloud_download</span> | |
| <span>Web Fetch</span> | |
| </div> | |
| <div class="dropdown-divider"></div> | |
| <div class="dropdown-item disabled" title="Feature not available"> | |
| <span class="material-icons">description</span> | |
| <span>Google Docs</span> | |
| </div> | |
| <div class="dropdown-item disabled" title="Feature not available"> | |
| <span class="material-icons">grid_on</span> | |
| <span>Google Sheets</span> | |
| </div> | |
| <div class="dropdown-item disabled" title="Feature not available"> | |
| <span class="material-icons">slideshow</span> | |
| <span>Google Slides</span> | |
| </div> | |
| </div> | |
| <ul class="sidebar-menu"> | |
| <li class="sidebar-item <?php echo $view === 'my-drive' ? 'active' : ''; ?>" onclick="window.location.href='index.php?view=my-drive'"> | |
| <span class="material-icons">folder</span> | |
| <span>My Drive</span> | |
| </li> | |
| <li class="sidebar-item <?php echo $view === 'shared' ? 'active' : ''; ?>" onclick="window.location.href='shared.php'"> | |
| <span class="material-icons">people</span> | |
| <span>Shared with me</span> | |
| </li> | |
| <li class="sidebar-item <?php echo $view === 'recent' ? 'active' : ''; ?>" onclick="window.location.href='index.php?view=recent'"> | |
| <span class="material-icons">access_time</span> | |
| <span>Recent</span> | |
| </li> | |
| <li class="sidebar-item <?php echo $view === 'starred' ? 'active' : ''; ?>" onclick="window.location.href='index.php?view=starred'"> | |
| <span class="material-icons">star</span> | |
| <span>Starred</span> | |
| </li> | |
| <li class="sidebar-item <?php echo $view === 'trash' ? 'active' : ''; ?>" onclick="window.location.href='index.php?view=trash'"> | |
| <span class="material-icons">delete</span> | |
| <span>Trash</span> | |
| </li> | |
| </ul> | |
| <div class="storage-info" title="<?php echo number_format($storagePercentage, 1); ?>% used"> | |
| <div class="storage-text">Storage</div> | |
| <div class="storage-bar"> | |
| <div class="storage-used" style="width: <?php echo min($storagePercentage, 100); ?>%; background-color: <?php echo $storageColor; ?>;"></div> | |
| </div> | |
| <div class="storage-text"><?php echo formatBytes($storageUsed); ?> of <?php echo formatBytes($storageQuota); ?> used</div> | |
| </div> | |
| </div> | |
| <div class="sidebar-overlay" onclick="closeMobileSidebar()"></div> | |
| <div class="main-content" id="mainContent" data-current-folder="<?php echo htmlspecialchars($currentFolder); ?>"> | |
| <?php if (!empty($breadcrumbs) && $view === 'my-drive'): ?> | |
| <div class="breadcrumbs"> | |
| <span class="breadcrumb-item" onclick="window.location.href='index.php?view=my-drive&folder=root'"> | |
| <span class="material-icons">folder</span> My Drive | |
| </span> | |
| <?php foreach ($breadcrumbs as $crumb): ?> | |
| <span class="material-icons breadcrumb-arrow">chevron_right</span> | |
| <span class="breadcrumb-item" onclick="window.location.href='index.php?view=my-drive&folder=<?php echo htmlspecialchars($crumb['id']); ?>'"> | |
| <?php echo htmlspecialchars($crumb['name']); ?> | |
| </span> | |
| <?php endforeach; ?> | |
| </div> | |
| <?php endif; ?> | |
| <?php if ($view === 'shared'): ?> | |
| <div class="empty-state"> | |
| <span class="material-icons">people_outline</span> | |
| <h2>Nothing shared yet</h2> | |
| <p>Files and folders others share with you will show up here</p> | |
| </div> | |
| <?php elseif (empty($files)): ?> | |
| <div class="empty-state"> | |
| <?php if ($view === 'trash'): ?> | |
| <span class="material-icons">delete_outline</span> | |
| <h2>Trash is empty</h2> | |
| <p>Items you trash are deleted forever after 30 days</p> | |
| <?php elseif ($view === 'starred'): ?> | |
| <span class="material-icons">star_outline</span> | |
| <h2>No starred items</h2> | |
| <p>Add stars to files and folders to find them easily later</p> | |
| <?php elseif ($view === 'recent'): ?> | |
| <span class="material-icons">access_time</span> | |
| <h2>No recent files</h2> | |
| <p>Files you open or edit will show up here</p> | |
| <?php else: ?> | |
| <span class="material-icons">folder_open</span> | |
| <h2>Drop files here or use the "New" button</h2> | |
| <p>Drag files to upload or create a new folder</p> | |
| <?php endif; ?> | |
| </div> | |
| <?php else: ?> | |
| <div class="toolbar"> | |
| <div class="toolbar-left"> | |
| <span id="selectedCount" style="display: none; margin-right: 12px; color: #5f6368; font-size: 14px;">0 selected</span> | |
| <?php if ($view === 'trash'): ?> | |
| <button class="toolbar-button" onclick="restoreSelected()"> | |
| <span class="material-icons">restore_from_trash</span> | |
| Restore | |
| </button> | |
| <button class="toolbar-button" onclick="deleteForeverSelected()"> | |
| <span class="material-icons">delete_forever</span> | |
| Delete forever | |
| </button> | |
| <button class="toolbar-button" onclick="emptyTrash()"> | |
| <span class="material-icons">delete_sweep</span> | |
| Empty trash | |
| </button> | |
| <?php else: ?> | |
| <button class="toolbar-button" onclick="deleteSelectedFiles()" style="display: none;" id="deleteSelectedBtn"> | |
| <span class="material-icons">delete</span> | |
| Move to trash | |
| </button> | |
| <?php endif; ?> | |
| </div> | |
| <div class="toolbar-right"> | |
| <button class="toolbar-button" onclick="toggleView('list')" id="listViewBtn"> | |
| <span class="material-icons">view_list</span> | |
| </button> | |
| <button class="toolbar-button active" onclick="toggleView('grid')" id="gridViewBtn"> | |
| <span class="material-icons">view_module</span> | |
| </button> | |
| </div> | |
| </div> | |
| <div class="file-grid grid-view" id="fileGrid"> | |
| <?php foreach ($files as $file): ?> | |
| <?php $iconData = getGoogleDriveIcon($file['name'], $file['type']); ?> | |
| <div class="file-item <?php echo $iconData['class']; ?>" | |
| data-file-id="<?php echo htmlspecialchars($file['id']); ?>" | |
| data-file-name="<?php echo htmlspecialchars($file['name']); ?>" | |
| data-file-path="<?php echo htmlspecialchars($file['path']); ?>" | |
| data-file-type="<?php echo htmlspecialchars($file['type']); ?>" | |
| data-starred="<?php echo $file['starred'] ? 'true' : 'false'; ?>" | |
| onclick="selectFile(event, '<?php echo htmlspecialchars($file['id']); ?>')" | |
| ondblclick="<?php | |
| if ($file['type'] === 'folder') { | |
| echo "window.location.href='index.php?view=my-drive&folder=" . htmlspecialchars($file['id']) . "'"; | |
| } else { | |
| echo "openFile('" . htmlspecialchars($file['path']) . "', '" . htmlspecialchars($file['name']) . "', '" . htmlspecialchars($file['type']) . "', '" . htmlspecialchars($file['id']) . "')"; | |
| } | |
| " | |
| draggable="true"> | |
| <div class="file-preview" style="background-color: echo $iconData['bgColor']; ;"> | |
| <?php if ($file['type'] === 'folder'): ?> | |
| <!-- Folder Icon --> | |
| <span class="material-icons folder-icon" style="color: echo $iconData['color']; ;"> | |
| <?php echo $iconData['icon']; ?> | |
| </span> | |
| <?php elseif (isset($iconData['showThumbnail']) && $iconData['showThumbnail'] && strpos($file['type'], 'image/') === 0): ?> | |
| <!-- Image Thumbnail --> | |
| <img src=" echo htmlspecialchars($file['path']); " | |
| alt=" echo htmlspecialchars($file['name']); " | |
| style="width: 100%; height: 100%; object-fit: cover;"> | |
| <?php else: ?> | |
| <!-- File Icon (exe, bin, pdf, etc.) --> | |
| <div class="file-icon-preview"> | |
| <span class="material-icons" style="color: echo $iconData['color']; ; font-size: 64px;"> | |
| <?php echo $iconData['icon']; ?> | |
| </span> | |
| </div> | |
| <?php endif; ?> | |
| <!-- Star Badge --> | |
| <?php if ($file['starred']): ?> | |
| <span class="star-badge material-icons">star</span> | |
| <?php endif; ?> | |
| <!-- Shared Indicator --> | |
| <?php if (isset($file['shared']) && $file['shared']['enabled']): ?> | |
| <span class="shared-indicator">SHARED</span> | |
| <?php endif; ?> | |
| <!-- Star Button on Hover --> | |
| <button class="star-button" onclick="toggleStar('<?php echo htmlspecialchars($file['id']); ?>', event)"> | |
| <span class="material-icons"><?php echo $file['starred'] ? 'star' : 'star_border'; ?></span> | |
| </button> | |
| </div> | |
| <div class="file-info"> | |
| <div class="file-name"><?php echo htmlspecialchars($file['name']); ?></div> | |
| <div class="file-details"> | |
| <?php if ($file['type'] !== 'folder'): ?> | |
| <?php echo formatFileSize($file['size']); ?> • | |
| <?php endif; ?> | |
| <?php echo date('M d, Y', $file['modified']); ?> | |
| </div> | |
| </div> | |
| </div> | |
| <?php endforeach; ?> | |
| </div> | |
| <div class="file-info"> | |
| <div class="file-name"><?php echo htmlspecialchars($file['name']); ?></div> | |
| <div class="file-details"> | |
| <?php if ($file['type'] !== 'folder'): ?> | |
| <?php echo formatFileSize($file['size']); ?> • | |
| <?php endif; ?> | |
| <?php echo date('M d, Y', $file['modified']); ?> | |
| </div> | |
| </div> | |
| </div> | |
| <?php endforeach; ?> | |
| </div> | |
| <?php endif; ?> | |
| </div> | |
| <!-- Context Menu for Files --> | |
| <div class="context-menu" id="fileContextMenu"> | |
| <div class="context-menu-item" onclick="contextMenuAction('open')"> | |
| <span class="material-icons">open_in_new</span> | |
| <span>Open</span> | |
| </div> | |
| <div class="context-menu-item" onclick="contextMenuAction('preview')"> | |
| <span class="material-icons">visibility</span> | |
| <span>Preview</span> | |
| </div> | |
| <div class="context-menu-item" onclick="contextMenuAction('download')"> | |
| <span class="material-icons">download</span> | |
| <span>Download</span> | |
| </div> | |
| <div class="context-menu-divider"></div> | |
| <div class="context-menu-item" onclick="contextMenuAction('rename')"> | |
| <span class="material-icons">drive_file_rename_outline</span> | |
| <span>Rename</span> | |
| </div> | |
| <div class="context-menu-item" onclick="contextMenuAction('copy')"> | |
| <span class="material-icons">content_copy</span> | |
| <span>Make a copy</span> | |
| </div> | |
| <div class="context-menu-item" onclick="contextMenuAction('share')"> | |
| <span class="material-icons">person_add</span> | |
| <span>Share</span> | |
| </div> | |
| <div class="context-menu-divider"></div> | |
| <div class="context-menu-item" id="starMenuItem" onclick="contextMenuAction('star')"> | |
| <span class="material-icons">star</span> | |
| <span id="starMenuText">Add to starred</span> | |
| </div> | |
| <div class="context-menu-item" onclick="contextMenuAction('trash')"> | |
| <span class="material-icons">delete</span> | |
| <span>Move to trash</span> | |
| </div> | |
| </div> | |
| <!-- Context Menu for Empty Space --> | |
| <div class="context-menu" id="emptyContextMenu"> | |
| <div class="context-menu-item" onclick="emptyContextAction('upload')"> | |
| <span class="material-icons">upload_file</span> | |
| <span>Upload files</span> | |
| </div> | |
| <div class="context-menu-item" onclick="emptyContextAction('folder')"> | |
| <span class="material-icons">create_new_folder</span> | |
| <span>New folder</span> | |
| </div> | |
| <div class="context-menu-divider"></div> | |
| <div class="context-menu-item" onclick="emptyContextAction('refresh')"> | |
| <span class="material-icons">refresh</span> | |
| <span>Refresh</span> | |
| </div> | |
| </div> | |
| <!-- File Preview Modal --> | |
| <div class="modal" id="fileModal"> | |
| <div class="modal-content"> | |
| <div class="modal-header"> | |
| <div class="modal-title" id="modalTitle">File Preview</div> | |
| <button class="modal-close" onclick="closeModal()"> | |
| <span class="material-icons">close</span> | |
| </button> | |
| </div> | |
| <div class="modal-body" id="modalBody"></div> | |
| </div> | |
| </div> | |
| <!-- Share Dialog (Simplified) --> | |
| <div class="modal" id="shareModal"> | |
| <div class="modal-content" style="max-width: 500px;"> | |
| <div class="modal-header"> | |
| <div class="modal-title"> | |
| <span class="material-icons" style="vertical-align: middle; margin-right: 8px;">person_add</span> | |
| Share "<span id="shareFileName"></span>" | |
| </div> | |
| <button class="modal-close" onclick="closeShareDialog()"> | |
| <span class="material-icons">close</span> | |
| </button> | |
| </div> | |
| <div class="modal-body" style="padding: 24px;"> | |
| <!-- Simple share info --> | |
| <div style="margin-bottom: 20px;"> | |
| <div style="padding: 16px; background: #e8f4fd; border-radius: 8px; border-left: 4px solid #1a73e8;"> | |
| <div style="display: flex; align-items: center; gap: 8px; margin-bottom: 8px;"> | |
| <span class="material-icons" style="color: #1a73e8; font-size: 20px;">info</span> | |
| <span style="font-weight: 500; color: #1a73e8; font-size: 14px;">Public File</span> | |
| </div> | |
| <p style="margin: 0; color: #5f6368; font-size: 13px; line-height: 1.5;"> | |
| This file is publicly shareable. Anyone with the link can view and download it. | |
| </p> | |
| </div> | |
| </div> | |
| <!-- Link sharing box --> | |
| <div id="linkSharingBox" style="display: none; padding: 16px; background: #f1f3f4; border-radius: 8px;"> | |
| <div style="font-size: 13px; color: #5f6368; margin-bottom: 8px;"> | |
| <span class="material-icons" style="vertical-align: middle; font-size: 16px; color: #1a73e8;">info</span> | |
| Anyone with this link can view the file | |
| </div> | |
| <div style="display: flex; gap: 8px; align-items: center;"> | |
| <input type="text" | |
| id="shareLinkInput" | |
| class="folder-input" | |
| readonly | |
| style="flex: 1; background: #fff; font-size: 13px;"> | |
| <button class="button-secondary" onclick="copyShareLink()" style="padding: 8px 16px;"> | |
| <span class="material-icons" style="font-size: 18px;">content_copy</span> | |
| Copy | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="modal-footer" style="justify-content: space-between;"> | |
| <div style="font-size: 12px; color: #5f6368;"> | |
| <span class="material-icons" style="vertical-align: middle; font-size: 16px;">visibility</span> | |
| <span id="shareStatusText">Private</span> | |
| </div> | |
| <button class="button-primary" onclick="closeShareDialog()">Done</button> | |
| </div> | |
| </div> | |
| </div> | |
| <style> | |
| /* Highlight selected option */ | |
| input[type="radio"]:checked + div { | |
| color: #1a73e8; | |
| } | |
| label:has(input[type="radio"]:checked) { | |
| border-color: #1a73e8 !important; | |
| background: #e8f0fe; | |
| } | |
| .shared-indicator { | |
| position: absolute; | |
| top: 8px;<div class="context-menu-divider"></div> | |
| right: 32px; | |
| background: #1a73e8; | |
| color: white; | |
| padding: 2px 6px; | |
| border-radius: 4px; | |
| font-size: 10px; | |
| font-weight: 500; | |
| } | |
| </style> | |
| <!-- New Folder Dialog --> | |
| <div class="modal" id="folderModal"> | |
| <div class="modal-content folder-dialog"> | |
| <div class="modal-header"> | |
| <div class="modal-title">New folder</div> | |
| <button class="modal-close" onclick="closeFolderDialog()"> | |
| <span class="material-icons">close</span> | |
| </button> | |
| </div> | |
| <div class="modal-body"> | |
| <input type="text" id="folderNameInput" class="folder-input" placeholder="Untitled folder" autofocus> | |
| </div> | |
| <div class="modal-footer"> | |
| <button class="button-secondary" onclick="closeFolderDialog()">Cancel</button> | |
| <button class="button-primary" id="createFolderBtn" onclick="createFolder()" disabled>Create</button> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Web Fetch Dialog --> | |
| <div class="modal" id="webFetchModal"> | |
| <div class="modal-content folder-dialog"> | |
| <div class="modal-header"> | |
| <div class="modal-title"> | |
| <span class="material-icons" style="vertical-align: middle; margin-right: 8px;">cloud_download</span> | |
| Download from Web | |
| </div> | |
| <button class="modal-close" onclick="closeWebFetchDialog()"> | |
| <span class="material-icons">close</span> | |
| </button> | |
| </div> | |
| <div class="modal-body"> | |
| <div style="margin-bottom: 20px;"> | |
| <label style="display: block; margin-bottom: 8px; font-size: 14px; font-weight: 500; color: #202124;"> | |
| File URL <span style="color: #ea4335;">*</span> | |
| </label> | |
| <input type="url" | |
| id="webFetchUrlInput" | |
| class="folder-input" | |
| placeholder="https://example.com/file.pdf" | |
| style="margin-bottom: 4px;"> | |
| <span style="font-size: 12px; color: #5f6368;">Enter the direct URL to the file</span> | |
| </div> | |
| <div> | |
| <label style="display: block; margin-bottom: 8px; font-size: 14px; font-weight: 500; color: #202124;"> | |
| Custom filename (optional) | |
| </label> | |
| <input type="text" | |
| id="webFetchNameInput" | |
| class="folder-input" | |
| placeholder="my-document.pdf"> | |
| <span style="font-size: 12px; color: #5f6368;">Leave empty to use original filename</span> | |
| </div> | |
| <div id="webFetchProgress" style="display: none; margin-top: 16px; padding: 12px; background: #f1f3f4; border-radius: 4px;"> | |
| <div style="display: flex; align-items: center; gap: 12px;"> | |
| <div class="spinner" style="width: 20px; height: 20px; border: 2px solid #1a73e8; border-top-color: transparent; border-radius: 50%; animation: spin 0.8s linear infinite;"></div> | |
| <span style="font-size: 14px; color: #5f6368;">Downloading file...</span> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="modal-footer"> | |
| <button class="button-secondary" onclick="closeWebFetchDialog()">Cancel</button> | |
| <button class="button-primary" id="webFetchDownloadBtn" onclick="downloadFromWeb()">Download</button> | |
| </div> | |
| </div> | |
| </div> | |
| <style> | |
| @keyframes spin { | |
| to { transform: rotate(360deg); } | |
| } | |
| </style> | |
| <!-- Upload Progress Popup --> | |
| <div class="upload-progress" id="uploadProgress"> | |
| <div class="upload-header"> | |
| <div class="upload-title"> | |
| <span id="uploadStatusText">Uploading 0 files</span> | |
| </div> | |
| <div class="upload-actions"> | |
| <button class="icon-button" onclick="minimizeUploadProgress()"> | |
| <span class="material-icons">minimize</span> | |
| </button> | |
| <button class="icon-button" onclick="closeUploadProgress()"> | |
| <span class="material-icons">close</span> | |
| </button> | |
| </div> | |
| </div> | |
| <div class="upload-overall-progress"> | |
| <div class="progress-bar"> | |
| <div class="progress-fill" id="overallProgress" style="width: 0%"></div> | |
| </div> | |
| <div class="progress-text" id="overallProgressText">0%</div> | |
| </div> | |
| <div class="upload-file-list" id="uploadFileList"></div> | |
| </div> | |
| <!-- Drag & Drop Overlay --> | |
| <div class="drag-overlay" id="dragOverlay"> | |
| <div class="drag-content"> | |
| <span class="material-icons">cloud_upload</span> | |
| <h2>Drop files to upload</h2> | |
| </div> | |
| </div> | |
| <!-- Toast Notification --> | |
| <div class="toast" id="toast"></div> | |
| <!-- Upload Form (Hidden) --> | |
| <form id="uploadForm" style="display: none;"> | |
| <input type="file" id="fileInput" name="files[]" multiple> | |
| <input type="file" id="folderInput" name="files[]" multiple webkitdirectory directory> | |
| </form> | |
| <script> | |
| window.storageQuota = <?php echo $storageQuota; ?>; | |
| window.storageUsed = <?php echo $storageUsed; ?>; | |
| window.currentFolder = '<?php echo htmlspecialchars($currentFolder); ?>'; | |
| </script> | |
| <script src="script.js"></script> | |
| </body> | |
| </html> |