<?php
/**
 * Gestor de Archivos PHP - Sistema Completo
 * Permite: Ver, Subir, Eliminar archivos desde la raíz del hosting
 */

// Configuración de seguridad (opcional - descomentar para activar)
// define('PASSWORD', 'tu_password_aqui'); // Cambia esto por tu contraseña

session_start();

// Verificar autenticación si está configurada
if (defined('PASSWORD') && !isset($_SESSION['authenticated'])) {
    if (isset($_POST['password'])) {
        if ($_POST['password'] === PASSWORD) {
            $_SESSION['authenticated'] = true;
        } else {
            $error = 'Contraseña incorrecta';
        }
    }
    if (!isset($_SESSION['authenticated'])) {
        ?>
        <!DOCTYPE html>
        <html lang="es">
        <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title>Acceso - Gestor de Archivos</title>
            <style>
                body { font-family: Arial, sans-serif; display: flex; justify-content: center; align-items: center; min-height: 100vh; background: #f5f5f5; }
                .login-box { background: white; padding: 30px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
                input[type="password"] { width: 100%; padding: 10px; margin: 10px 0; border: 1px solid #ddd; border-radius: 4px; }
                button { width: 100%; padding: 10px; background: #007bff; color: white; border: none; border-radius: 4px; cursor: pointer; }
                .error { color: red; margin-bottom: 10px; }
            </style>
        </head>
        <body>
            <div class="login-box">
                <h2>Acceso al Gestor de Archivos</h2>
                <?php if (isset($error)) echo '<div class="error">' . htmlspecialchars($error) . '</div>'; ?>
                <form method="POST">
                    <input type="password" name="password" placeholder="Contraseña" required>
                    <button type="submit">Acceder</button>
                </form>
            </div>
        </body>
        </html>
        <?php
        exit;
    }
}

// Procesar acciones
$currentDir = isset($_GET['dir']) ? $_GET['dir'] : '.';
$currentDir = realpath($currentDir) ?: '.';
$message = '';
$messageType = '';

// Función para descomprimir archivos ZIP
function extractZip($zipPath, $extractTo) {
    if (!class_exists('ZipArchive')) {
        return ['success' => false, 'message' => 'La extensión ZipArchive no está disponible en este servidor.'];
    }
    
    $zip = new ZipArchive;
    $result = $zip->open($zipPath);
    
    if ($result === TRUE) {
        // Crear directorio de extracción si no existe
        if (!is_dir($extractTo)) {
            mkdir($extractTo, 0755, true);
        }
        
        // Extraer todos los archivos
        $zip->extractTo($extractTo);
        $fileCount = $zip->numFiles;
        $zip->close();
        
        return ['success' => true, 'message' => "Archivo ZIP descomprimido correctamente. Se extrajeron $fileCount archivo(s)."];
    } else {
        return ['success' => false, 'message' => 'Error al abrir el archivo ZIP. Código: ' . $result];
    }
}

// Subir archivo
if (isset($_POST['upload']) && isset($_FILES['file'])) {
    $targetDir = $currentDir . '/';
    $targetFile = $targetDir . basename($_FILES['file']['name']);
    $fileExtension = strtolower(pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION));
    $autoExtract = isset($_POST['auto_extract']) && $_POST['auto_extract'] == '1';
    
    if (move_uploaded_file($_FILES['file']['tmp_name'], $targetFile)) {
        $message = 'Archivo subido correctamente: ' . htmlspecialchars($_FILES['file']['name']);
        $messageType = 'success';
        
        // Si es un ZIP y se marcó auto-extraer, descomprimir automáticamente
        if ($autoExtract && $fileExtension == 'zip') {
            $extractDir = $targetDir . pathinfo($_FILES['file']['name'], PATHINFO_FILENAME);
            $extractResult = extractZip($targetFile, $extractDir);
            
            if ($extractResult['success']) {
                $message .= ' ' . $extractResult['message'];
            } else {
                $message .= ' ' . $extractResult['message'];
                $messageType = 'error';
            }
        }
    } else {
        $message = 'Error al subir el archivo.';
        $messageType = 'error';
    }
}

// Función para comprimir un directorio en ZIP
function compressDirectory($sourceDir, $zipPath) {
    if (!class_exists('ZipArchive')) {
        return ['success' => false, 'message' => 'La extensión ZipArchive no está disponible en este servidor.'];
    }
    
    $zip = new ZipArchive;
    if ($zip->open($zipPath, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== TRUE) {
        return ['success' => false, 'message' => 'No se pudo crear el archivo ZIP.'];
    }
    
    $sourceDir = realpath($sourceDir);
    if (!$sourceDir) {
        $zip->close();
        return ['success' => false, 'message' => 'Directorio no válido.'];
    }
    
    $files = new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator($sourceDir, RecursiveDirectoryIterator::SKIP_DOTS),
        RecursiveIteratorIterator::LEAVES_ONLY
    );
    
    $fileCount = 0;
    foreach ($files as $file) {
        if (!$file->isDir()) {
            $filePath = $file->getRealPath();
            $relativePath = str_replace($sourceDir . DIRECTORY_SEPARATOR, '', $filePath);
            $relativePath = str_replace('\\', '/', $relativePath); // Normalizar separadores
            
            if ($zip->addFile($filePath, $relativePath)) {
                $fileCount++;
            }
        }
    }
    
    $zip->close();
    return ['success' => true, 'message' => "Directorio comprimido correctamente. Se incluyeron $fileCount archivo(s).", 'count' => $fileCount];
}

// Comprimir y descargar directorio
if (isset($_GET['compress'])) {
    $compressParam = $_GET['compress'];
    
    // Si el parámetro es "." o está vacío, comprimir el directorio actual
    if ($compressParam == '.' || empty($compressParam)) {
        $compressDir = $currentDir;
    } else {
        $compressDir = $currentDir . '/' . basename($compressParam);
    }
    
    $compressDir = realpath($compressDir);
    
    if ($compressDir && is_dir($compressDir) && strpos($compressDir, realpath('.')) === 0) {
        $dirName = basename($compressDir);
        if (empty($dirName) || $dirName == '.') {
            $dirName = 'raiz_' . date('Y-m-d_His');
        }
        $zipFileName = $dirName . '_' . date('Y-m-d_His') . '.zip';
        $zipPath = sys_get_temp_dir() . '/' . uniqid('zip_', true) . '_' . $dirName . '.zip';
        
        $compressResult = compressDirectory($compressDir, $zipPath);
        
        if ($compressResult['success'] && file_exists($zipPath)) {
            // Enviar el archivo ZIP para descarga
            header('Content-Type: application/zip');
            header('Content-Disposition: attachment; filename="' . $zipFileName . '"');
            header('Content-Length: ' . filesize($zipPath));
            header('Cache-Control: must-revalidate');
            header('Pragma: public');
            
            readfile($zipPath);
            @unlink($zipPath); // Eliminar archivo temporal
            exit;
        } else {
            $message = $compressResult['message'];
            $messageType = 'error';
            @unlink($zipPath); // Limpiar archivo temporal en caso de error
        }
    } else {
        $message = 'Directorio no válido.';
        $messageType = 'error';
    }
}

// Descomprimir archivo ZIP
if (isset($_GET['extract'])) {
    $zipFile = $currentDir . '/' . basename($_GET['extract']);
    $zipFile = realpath($zipFile);
    
    if ($zipFile && is_file($zipFile) && strtolower(pathinfo($zipFile, PATHINFO_EXTENSION)) == 'zip') {
        if (strpos($zipFile, realpath('.')) === 0) {
            $extractDir = dirname($zipFile) . '/' . pathinfo($zipFile, PATHINFO_FILENAME);
            $extractResult = extractZip($zipFile, $extractDir);
            
            if ($extractResult['success']) {
                $message = $extractResult['message'];
                $messageType = 'success';
            } else {
                $message = $extractResult['message'];
                $messageType = 'error';
            }
        }
    } else {
        $message = 'Archivo ZIP no válido.';
        $messageType = 'error';
    }
}

// Eliminar archivo/directorio
if (isset($_GET['delete'])) {
    $deletePath = $currentDir . '/' . basename($_GET['delete']);
    $deletePath = realpath($deletePath);
    
    if ($deletePath && strpos($deletePath, realpath('.')) === 0) {
        if (is_file($deletePath)) {
            if (unlink($deletePath)) {
                $message = 'Archivo eliminado correctamente.';
                $messageType = 'success';
            } else {
                $message = 'Error al eliminar el archivo.';
                $messageType = 'error';
            }
        } elseif (is_dir($deletePath)) {
            if (rmdir($deletePath)) {
                $message = 'Directorio eliminado correctamente.';
                $messageType = 'success';
            } else {
                $message = 'Error: El directorio no está vacío o no se puede eliminar.';
                $messageType = 'error';
            }
        }
    }
}

// Crear directorio
if (isset($_POST['create_dir'])) {
    $newDirName = basename($_POST['dir_name']);
    $newDirPath = $currentDir . '/' . $newDirName;
    
    if (!empty($newDirName) && !file_exists($newDirPath)) {
        if (mkdir($newDirPath, 0755, true)) {
            $message = 'Directorio creado correctamente.';
            $messageType = 'success';
        } else {
            $message = 'Error al crear el directorio.';
            $messageType = 'error';
        }
    } else {
        $message = 'El directorio ya existe o el nombre es inválido.';
        $messageType = 'error';
    }
}

// Obtener archivos y directorios
$files = [];
$dirs = [];

if (is_dir($currentDir)) {
    $items = scandir($currentDir);
    foreach ($items as $item) {
        if ($item != '.' && $item != '..') {
            $fullPath = $currentDir . '/' . $item;
            if (is_dir($fullPath)) {
                $dirs[] = $item;
            } else {
                $files[] = $item;
            }
        }
    }
    sort($dirs);
    sort($files);
}

// Calcular tamaño de archivo
function formatBytes($bytes, $precision = 2) {
    $units = array('B', 'KB', 'MB', 'GB', 'TB');
    $bytes = max($bytes, 0);
    $pow = floor(($bytes ? log($bytes) : 0) / log(1024));
    $pow = min($pow, count($units) - 1);
    $bytes /= pow(1024, $pow);
    return round($bytes, $precision) . ' ' . $units[$pow];
}

// Obtener ruta relativa para navegación
$pathParts = explode('/', trim(str_replace(realpath('.'), '', realpath($currentDir)), '/'));
$breadcrumbs = [['name' => 'Raíz', 'path' => '.']];
$currentPath = '';
foreach ($pathParts as $part) {
    if (!empty($part)) {
        $currentPath .= '/' . $part;
        $breadcrumbs[] = ['name' => $part, 'path' => '.' . $currentPath];
    }
}
?>
<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Gestor de Archivos</title>
    <style>
        * { margin: 0; padding: 0; box-sizing: border-box; }
        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
            background: #f5f7fa;
            color: #333;
            padding: 20px;
        }
        .container {
            max-width: 1200px;
            margin: 0 auto;
            background: white;
            border-radius: 8px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
            padding: 20px;
        }
        h1 {
            color: #2c3e50;
            margin-bottom: 20px;
            padding-bottom: 10px;
            border-bottom: 2px solid #3498db;
        }
        .breadcrumb {
            margin-bottom: 20px;
            padding: 10px;
            background: #ecf0f1;
            border-radius: 4px;
        }
        .breadcrumb a {
            color: #3498db;
            text-decoration: none;
            margin: 0 5px;
        }
        .breadcrumb a:hover { text-decoration: underline; }
        .breadcrumb span { color: #7f8c8d; }
        .message {
            padding: 12px;
            margin-bottom: 20px;
            border-radius: 4px;
            font-weight: 500;
        }
        .message.success {
            background: #d4edda;
            color: #155724;
            border: 1px solid #c3e6cb;
        }
        .message.error {
            background: #f8d7da;
            color: #721c24;
            border: 1px solid #f5c6cb;
        }
        .actions {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
            gap: 20px;
            margin-bottom: 30px;
        }
        .action-box {
            background: #f8f9fa;
            padding: 20px;
            border-radius: 6px;
            border: 1px solid #dee2e6;
        }
        .action-box h3 {
            margin-bottom: 15px;
            color: #495057;
            font-size: 18px;
        }
        input[type="file"], input[type="text"] {
            width: 100%;
            padding: 8px;
            margin-bottom: 10px;
            border: 1px solid #ced4da;
            border-radius: 4px;
            font-size: 14px;
        }
        button, .btn {
            padding: 10px 20px;
            background: #3498db;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-size: 14px;
            text-decoration: none;
            display: inline-block;
            transition: background 0.3s;
        }
        button:hover, .btn:hover { background: #2980b9; }
        .btn-danger {
            background: #e74c3c;
        }
        .btn-danger:hover { background: #c0392b; }
        .btn-success {
            background: #27ae60;
        }
        .btn-success:hover { background: #229954; }
        table {
            width: 100%;
            border-collapse: collapse;
            margin-top: 20px;
        }
        th, td {
            padding: 12px;
            text-align: left;
            border-bottom: 1px solid #dee2e6;
        }
        th {
            background: #3498db;
            color: white;
            font-weight: 600;
        }
        tr:hover { background: #f8f9fa; }
        .file-icon {
            margin-right: 8px;
            font-size: 18px;
        }
        .actions-cell {
            display: flex;
            gap: 5px;
        }
        .actions-cell a {
            padding: 5px 10px;
            font-size: 12px;
        }
        @media (max-width: 768px) {
            .actions {
                grid-template-columns: 1fr;
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>📁 Gestor de Archivos</h1>
        
        <?php if ($message): ?>
            <div class="message <?php echo $messageType; ?>">
                <?php echo htmlspecialchars($message); ?>
            </div>
        <?php endif; ?>
        
        <div class="breadcrumb">
            <?php foreach ($breadcrumbs as $index => $crumb): ?>
                <a href="?dir=<?php echo urlencode($crumb['path']); ?>">
                    <?php echo htmlspecialchars($crumb['name']); ?>
                </a>
                <?php if ($index < count($breadcrumbs) - 1): ?>
                    <span>/</span>
                <?php endif; ?>
            <?php endforeach; ?>
        </div>
        
        <div class="actions">
            <div class="action-box">
                <h3>📤 Subir Archivo</h3>
                <form method="POST" enctype="multipart/form-data">
                    <input type="hidden" name="dir" value="<?php echo htmlspecialchars($currentDir); ?>">
                    <input type="file" name="file" required>
                    <label style="display: flex; align-items: center; margin: 10px 0; cursor: pointer;">
                        <input type="checkbox" name="auto_extract" value="1" style="width: auto; margin-right: 8px;">
                        <span>Descomprimir automáticamente si es ZIP</span>
                    </label>
                    <button type="submit" name="upload">Subir Archivo</button>
                </form>
            </div>
            
            <div class="action-box">
                <h3>📂 Crear Directorio</h3>
                <form method="POST">
                    <input type="text" name="dir_name" placeholder="Nombre del directorio" required>
                    <button type="submit" name="create_dir">Crear Directorio</button>
                </form>
            </div>
            
            <div class="action-box">
                <h3>📦 Comprimir Directorio Actual</h3>
                <p style="margin-bottom: 15px; color: #6c757d; font-size: 14px;">
                    Comprime todo el contenido del directorio actual en un archivo ZIP
                </p>
                <a href="?dir=<?php echo urlencode($currentDir); ?>&compress=." 
                   class="btn btn-success" 
                   style="width: 100%; text-align: center;">
                    📦 Descargar ZIP
                </a>
            </div>
        </div>
        
        <table>
            <thead>
                <tr>
                    <th>Nombre</th>
                    <th>Tamaño</th>
                    <th>Fecha Modificación</th>
                    <th>Acciones</th>
                </tr>
            </thead>
            <tbody>
                <?php if ($currentDir != '.'): ?>
                    <tr>
                        <td>
                            <span class="file-icon">📁</span>
                            <a href="?dir=<?php echo urlencode(dirname($currentDir)); ?>">.. (Directorio padre)</a>
                        </td>
                        <td>-</td>
                        <td>-</td>
                        <td>-</td>
                    </tr>
                <?php endif; ?>
                
                <?php foreach ($dirs as $dir): ?>
                    <tr>
                        <td>
                            <span class="file-icon">📁</span>
                            <a href="?dir=<?php echo urlencode($currentDir . '/' . $dir); ?>">
                                <?php echo htmlspecialchars($dir); ?>
                            </a>
                        </td>
                        <td>-</td>
                        <td><?php echo date('Y-m-d H:i:s', filemtime($currentDir . '/' . $dir)); ?></td>
                        <td class="actions-cell">
                            <a href="?dir=<?php echo urlencode($currentDir . '/' . $dir); ?>" class="btn">Abrir</a>
                            <a href="?dir=<?php echo urlencode($currentDir); ?>&compress=<?php echo urlencode($dir); ?>" 
                               class="btn btn-success" 
                               title="Comprimir carpeta y descargar como ZIP">📦 Comprimir</a>
                            <a href="?dir=<?php echo urlencode($currentDir); ?>&delete=<?php echo urlencode($dir); ?>" 
                               class="btn btn-danger" 
                               onclick="return confirm('¿Estás seguro de eliminar este directorio?');">Eliminar</a>
                        </td>
                    </tr>
                <?php endforeach; ?>
                
                <?php foreach ($files as $file): ?>
                    <?php
                    $filePath = $currentDir . '/' . $file;
                    $fileSize = filesize($filePath);
                    $fileExtension = strtolower(pathinfo($file, PATHINFO_EXTENSION));
                    $icon = '📄';
                    if (in_array($fileExtension, ['jpg', 'jpeg', 'png', 'gif', 'webp'])) $icon = '🖼️';
                    elseif (in_array($fileExtension, ['pdf'])) $icon = '📕';
                    elseif (in_array($fileExtension, ['zip', 'rar', 'tar', 'gz'])) $icon = '📦';
                    elseif (in_array($fileExtension, ['php', 'js', 'html', 'css'])) $icon = '💻';
                    ?>
                    <tr>
                        <td>
                            <span class="file-icon"><?php echo $icon; ?></span>
                            <?php echo htmlspecialchars($file); ?>
                        </td>
                        <td><?php echo formatBytes($fileSize); ?></td>
                        <td><?php echo date('Y-m-d H:i:s', filemtime($filePath)); ?></td>
                        <td class="actions-cell">
                            <a href="<?php echo htmlspecialchars($currentDir . '/' . $file); ?>" 
                               target="_blank" 
                               class="btn">Ver</a>
                            <?php if ($fileExtension == 'zip'): ?>
                                <a href="?dir=<?php echo urlencode($currentDir); ?>&extract=<?php echo urlencode($file); ?>" 
                                   class="btn btn-success" 
                                   onclick="return confirm('¿Descomprimir este archivo ZIP en el directorio actual?');"
                                   title="Descomprimir ZIP">📦 Descomprimir</a>
                            <?php endif; ?>
                            <a href="?dir=<?php echo urlencode($currentDir); ?>&delete=<?php echo urlencode($file); ?>" 
                               class="btn btn-danger" 
                               onclick="return confirm('¿Estás seguro de eliminar este archivo?');">Eliminar</a>
                        </td>
                    </tr>
                <?php endforeach; ?>
                
                <?php if (empty($dirs) && empty($files)): ?>
                    <tr>
                        <td colspan="4" style="text-align: center; padding: 30px; color: #7f8c8d;">
                            Este directorio está vacío
                        </td>
                    </tr>
                <?php endif; ?>
            </tbody>
        </table>
    </div>
</body>
</html>

