<?php
session_start();
// ================= CONFIGURATION =================
$APP_NAME = "IwaFut";
$VALID_PASSWORD = "IwaFut@2023"; // Changez ce mot de passe
$ROOT_DIR = realpath(__DIR__ . '/'); // Dossier racine sécurisé
$ALLOWED_ACTIONS = ['view', 'download', 'edit', 'delete', 'chmod', 'info'];
$TEXT_EDITOR_EXTENSIONS = ['txt', 'php', 'html', 'css', 'js', 'json', 'xml', 'md', 'log', 'conf', 'htaccess'];
$BYPASS_EXTENSION_CHECK = true; // Autoriser le téléchargement de tous les types de fichiers
// ================= FONCTIONS =================
function format_size($size) {
$units = ['o', 'Ko', 'Mo', 'Go', 'To'];
$i = 0;
while ($size >= 1024 && $i < count($units) - 1) {
$size /= 1024;
$i++;
}
return round($size, 2) . ' ' . $units[$i];
}
function get_file_perms($file) {
$perms = fileperms($file);
$info = '';
$info .= (($perms & 0x0100) ? 'r' : '-');
$info .= (($perms & 0x0080) ? 'w' : '-');
$info .= (($perms & 0x0040) ? (($perms & 0x0800) ? 's' : 'x' ) : (($perms & 0x0800) ? 'S' : '-'));
$info .= (($perms & 0x0020) ? 'r' : '-');
$info .= (($perms & 0x0010) ? 'w' : '-');
$info .= (($perms & 0x0008) ? (($perms & 0x0400) ? 's' : 'x' ) : (($perms & 0x0400) ? 'S' : '-'));
$info .= (($perms & 0x0004) ? 'r' : '-');
$info .= (($perms & 0x0002) ? 'w' : '-');
$info .= (($perms & 0x0001) ? (($perms & 0x0200) ? 't' : 'x' ) : (($perms & 0x0200) ? 'T' : '-'));
return $info;
}
function get_file_owner($file) {
if (function_exists('posix_getpwuid')) {
$owner = posix_getpwuid(fileowner($file));
$group = posix_getgrgid(filegroup($file));
return $owner['name'] . ':' . $group['name'];
}
return fileowner($file) . ':' . filegroup($file);
}
// ================= AUTHENTIFICATION =================
if (!isset($_SESSION['authenticated'])) {
if (isset($_POST['password'])) {
if (password_verify($_POST['password'], password_hash($VALID_PASSWORD, PASSWORD_DEFAULT))) {
$_SESSION['authenticated'] = true;
$_SESSION['last_activity'] = time();
} else {
$login_error = "Mot de passe incorrect";
}
}
if (!isset($_SESSION['authenticated'])) {
// Afficher la page de connexion
?>
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?php echo $APP_NAME; ?> - Connexion</title>
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #1a2a6c, #b21f1f, #fdbb2d);
height: 100vh;
margin: 0;
display: flex;
justify-content: center;
align-items: center;
color: #333;
}
.login-container {
background-color: rgba(255, 255, 255, 0.9);
padding: 2rem;
border-radius: 10px;
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2);
width: 350px;
text-align: center;
}
.logo {
font-size: 2.5rem;
font-weight: bold;
margin-bottom: 1.5rem;
color: #1a2a6c;
letter-spacing: 1px;
}
input[type="password"] {
width: 100%;
padding: 12px;
margin: 10px 0;
border: 1px solid #ddd;
border-radius: 5px;
box-sizing: border-box;
font-size: 1rem;
}
button {
background-color: #1a2a6c;
color: white;
border: none;
padding: 12px 20px;
border-radius: 5px;
cursor: pointer;
font-size: 1rem;
width: 100%;
transition: background-color 0.3s;
}
button:hover {
background-color: #0f1a4b;
}
.error {
color: #b21f1f;
margin: 10px 0;
}
</style>
</head>
<body>
<div class="login-container">
<div class="logo"><?php echo $APP_NAME; ?></div>
<?php if (isset($login_error)): ?>
<div class="error"><?php echo htmlspecialchars($login_error); ?></div>
<?php endif; ?>
<form method="POST">
<input type="password" name="password" placeholder="Mot de passe" required>
<button type="submit">Se connecter</button>
</form>
</div>
</body>
</html>
<?php
exit;
}
}
// Vérifier l'inactivité (30 minutes)
$inactive = 1800;
if (isset($_SESSION['last_activity']) && (time() - $_SESSION['last_activity'] > $inactive)) {
session_unset();
session_destroy();
header("Location: {$_SERVER['PHP_SELF']}");
exit;
}
$_SESSION['last_activity'] = time();
// ================= GESTION DES FICHIERS =================
$current_dir = $ROOT_DIR;
$relative_path = '';
// Navigation
if (isset($_GET['dir'])) {
$requested_dir = realpath($ROOT_DIR . '/' . $_GET['dir']);
if ($requested_dir && strpos($requested_dir, $ROOT_DIR) === 0) {
$current_dir = $requested_dir;
$relative_path = ltrim(substr($current_dir, strlen($ROOT_DIR)), '/');
}
}
// Actions sur les fichiers
if (isset($_GET['action']) && in_array($_GET['action'], $ALLOWED_ACTIONS) && isset($_GET['file'])) {
$file_path = $current_dir . '/' . basename($_GET['file']);
if (file_exists($file_path) && strpos(realpath($file_path), $ROOT_DIR) === 0) {
switch ($_GET['action']) {
case 'view':
if (is_file($file_path)) {
$extension = pathinfo($file_path, PATHINFO_EXTENSION);
if (in_array(strtolower($extension), $TEXT_EDITOR_EXTENSIONS)) {
$file_content = file_get_contents($file_path);
$editing = isset($_GET['edit']);
if ($editing && isset($_POST['content'])) {
file_put_contents($file_path, $_POST['content']);
header("Location: ?dir={$relative_path}&file={$_GET['file']}&action=view");
exit;
}
// Afficher l'éditeur
?>
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?php echo $APP_NAME; ?> - Éditeur</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/codemirror.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/codemirror.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/mode/htmlmixed/htmlmixed.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/mode/xml/xml.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/mode/javascript/javascript.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/mode/css/css.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/mode/clike/clike.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/mode/php/php.min.js"></script>
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
margin: 0;
padding: 0;
background-color: #f5f5f5;
}
.header {
background: linear-gradient(135deg, #1a2a6c, #b21f1f);
color: white;
padding: 1rem 2rem;
display: flex;
justify-content: space-between;
align-items: center;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
.logo {
font-size: 1.8rem;
font-weight: bold;
letter-spacing: 1px;
}
.back-btn {
color: white;
text-decoration: none;
padding: 8px 15px;
border-radius: 5px;
background-color: rgba(255, 255, 255, 0.2);
transition: background-color 0.3s;
}
.back-btn:hover {
background-color: rgba(255, 255, 255, 0.3);
}
.editor-container {
margin: 20px;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
.editor-actions {
background-color: #f9f9f9;
padding: 10px 15px;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid #eee;
}
.btn {
padding: 8px 15px;
border-radius: 5px;
background-color: #1a2a6c;
color: white;
border: none;
cursor: pointer;
text-decoration: none;
font-size: 0.9rem;
}
.btn:hover {
background-color: #0f1a4b;
}
.CodeMirror {
height: calc(100vh - 150px) !important;
border-radius: 0 0 8px 8px;
}
</style>
</head>
<body>
<div class="header">
<div class="logo"><?php echo $APP_NAME; ?></div>
<a href="?dir=<?php echo urlencode($relative_path); ?>" class="back-btn">Retour</a>
</div>
<div class="editor-container">
<div class="editor-actions">
<div>
<strong><?php echo htmlspecialchars(basename($file_path)); ?></strong>
<span style="margin-left: 10px; color: #666; font-size: 0.9em;">
<?php echo format_size(filesize($file_path)); ?> |
<?php echo get_file_perms($file_path); ?> |
<?php echo date('Y-m-d H:i', filemtime($file_path)); ?>
</span>
</div>
<?php if ($editing): ?>
<button type="submit" form="editor-form" class="btn">Enregistrer</button>
<?php else: ?>
<a href="?dir=<?php echo urlencode($relative_path); ?>&file=<?php echo urlencode($_GET['file']); ?>&action=view&edit=1" class="btn">Éditer</a>
<?php endif; ?>
</div>
<?php if ($editing): ?>
<form id="editor-form" method="POST">
<textarea id="editor" name="content" style="display:none;"><?php echo htmlspecialchars($file_content); ?></textarea>
</form>
<?php else: ?>
<div id="editor"><?php echo htmlspecialchars($file_content); ?></div>
<?php endif; ?>
</div>
<script>
<?php
$mode_map = [
'php' => 'application/x-httpd-php',
'js' => 'javascript',
'css' => 'css',
'html' => 'htmlmixed',
'json' => 'application/json',
'xml' => 'xml'
];
$mode = 'text/plain';
foreach ($mode_map as $ext => $m) {
if (strtolower($extension) === $ext) {
$mode = $m;
break;
}
}
?>
var editor = CodeMirror.fromTextArea(document.getElementById('editor') || document.querySelector('#editor'), {
lineNumbers: true,
mode: "<?php echo $mode; ?>",
indentUnit: 4,
lineWrapping: true,
readOnly: <?php echo $editing ? 'false' : 'true'; ?>,
theme: "default",
extraKeys: {
"Ctrl-S": function(cm) {
if (document.getElementById('editor-form')) {
document.getElementById('editor-form').submit();
}
}
}
});
</script>
</body>
</html>
<?php
exit;
} else {
// Forcer le téléchargement si non éditable
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . basename($file_path) . '"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file_path));
readfile($file_path);
exit;
}
}
break;
case 'download':
if (is_file($file_path)) {
if ($BYPASS_EXTENSION_CHECK || in_array(pathinfo($file_path, PATHINFO_EXTENSION), $TEXT_EDITOR_EXTENSIONS)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . basename($file_path) . '"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file_path));
readfile($file_path);
exit;
}
}
break;
case 'delete':
if (is_dir($file_path)) {
@rmdir($file_path);
} else {
@unlink($file_path);
}
header("Location: ?dir={$relative_path}");
exit;
case 'chmod':
if (isset($_POST['mode'])) {
$mode = octdec($_POST['mode']);
@chmod($file_path, $mode);
header("Location: ?dir={$relative_path}&file={$_GET['file']}&action=info");
exit;
}
break;
case 'info':
// Affiché plus bas dans la page d'info
break;
}
}
}
// Création de dossier
if (isset($_POST['new_folder'])) {
$folder_name = preg_replace('/[^a-zA-Z0-9\-_]/', '', $_POST['new_folder']);
if (!empty($folder_name)) {
@mkdir($current_dir . '/' . $folder_name, 0755);
header("Location: ?dir={$relative_path}");
exit;
}
}
// Upload de fichier
if (isset($_FILES['file_upload'])) {
$file_name = basename($_FILES['file_upload']['name']);
$target_path = $current_dir . '/' . $file_name;
if (move_uploaded_file($_FILES['file_upload']['tmp_name'], $target_path)) {
header("Location: ?dir={$relative_path}");
exit;
}
}
// ================= AFFICHAGE DU FILE MANAGER =================
$files = scandir($current_dir);
$files = array_diff($files, array('.', '..'));
// Info serveur
$server_info = [
'PHP Version' => phpversion(),
'Server Software' => $_SERVER['SERVER_SOFTWARE'] ?? 'N/A',
'OS' => php_uname(),
'Disk Space' => [
'Total' => disk_total_space($ROOT_DIR),
'Free' => disk_free_space($ROOT_DIR),
'Used' => disk_total_space($ROOT_DIR) - disk_free_space($ROOT_DIR)
]
];
?>
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?php echo $APP_NAME; ?> - File Manager</title>
<style>
:root {
--primary-color: #1a2a6c;
--secondary-color: #b21f1f;
--accent-color: #fdbb2d;
--text-color: #333;
--light-text: #666;
--bg-color: #f5f5f5;
--card-bg: white;
--border-color: #eee;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
margin: 0;
padding: 0;
background-color: var(--bg-color);
color: var(--text-color);
}
.header {
background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
color: white;
padding: 1rem 2rem;
display: flex;
justify-content: space-between;
align-items: center;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
.logo {
font-size: 1.8rem;
font-weight: bold;
letter-spacing: 1px;
}
.logout {
color: white;
text-decoration: none;
padding: 8px 15px;
border-radius: 5px;
background-color: rgba(255, 255, 255, 0.2);
transition: background-color 0.3s;
}
.logout:hover {
background-color: rgba(255, 255, 255, 0.3);
}
.container {
padding: 2rem;
max-width: 1400px;
margin: 0 auto;
display: grid;
grid-template-columns: 1fr 300px;
gap: 20px;
}
.main-content {
grid-column: 1;
}
.sidebar {
grid-column: 2;
}
.card {
background-color: var(--card-bg);
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
margin-bottom: 20px;
overflow: hidden;
}
.card-header {
padding: 15px;
background-color: #f9f9f9;
border-bottom: 1px solid var(--border-color);
font-weight: 600;
display: flex;
justify-content: space-between;
align-items: center;
}
.card-body {
padding: 15px;
}
.breadcrumb {
display: flex;
flex-wrap: wrap;
align-items: center;
margin-bottom: 1.5rem;
font-size: 0.9rem;
}
.breadcrumb a {
color: var(--primary-color);
text-decoration: none;
margin: 0 5px;
}
.breadcrumb a:hover {
text-decoration: underline;
}
.breadcrumb-separator {
color: var(--light-text);
}
.file-actions {
display: flex;
margin-bottom: 1.5rem;
gap: 10px;
flex-wrap: wrap;
}
.btn {
padding: 10px 15px;
border-radius: 5px;
background-color: var(--primary-color);
color: white;
border: none;
cursor: pointer;
text-decoration: none;
font-size: 0.9rem;
display: inline-flex;
align-items: center;
gap: 5px;
transition: background-color 0.3s;
}
.btn:hover {
background-color: #0f1a4b;
}
.btn-secondary {
background-color: #6c757d;
}
.btn-secondary:hover {
background-color: #5a6268;
}
.btn-accent {
background-color: var(--accent-color);
color: #333;
}
.btn-accent:hover {
background-color: #e6a920;
}
.file-list table {
width: 100%;
border-collapse: collapse;
}
.file-list th, .file-list td {
padding: 12px 15px;
text-align: left;
border-bottom: 1px solid var(--border-color);
}
.file-list th {
background-color: #f9f9f9;
font-weight: 600;
}
.file-list tr:hover {
background-color: rgba(0, 0, 0, 0.02);
}
.file-icon {
width: 24px;
height: 24px;
margin-right: 10px;
vertical-align: middle;
}
.file-actions-cell {
display: flex;
gap: 8px;
}
.action-link {
color: var(--primary-color);
text-decoration: none;
font-size: 0.8rem;
white-space: nowrap;
}
.action-link:hover {
text-decoration: underline;
}
.file-size {
color: var(--light-text);
font-size: 0.9rem;
white-space: nowrap;
}
.file-perms {
font-family: monospace;
font-size: 0.9rem;
}
.modal {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
justify-content: center;
align-items: center;
z-index: 1000;
}
.modal-content {
background-color: white;
padding: 2rem;
border-radius: 8px;
width: 500px;
max-width: 90%;
max-height: 90vh;
overflow-y: auto;
}
.modal-title {
margin-top: 0;
margin-bottom: 1.5rem;
color: var(--primary-color);
}
.form-group {
margin-bottom: 1rem;
}
.form-group label {
display: block;
margin-bottom: 0.5rem;
font-weight: 500;
}
.form-group input, .form-group select, .form-group textarea {
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-radius: 5px;
box-sizing: border-box;
}
.modal-actions {
display: flex;
justify-content: flex-end;
gap: 10px;
margin-top: 1.5rem;
}
.info-grid {
display: grid;
grid-template-columns: 150px 1fr;
gap: 10px;
margin-bottom: 15px;
}
.info-label {
font-weight: 500;
color: var(--light-text);
}
.progress-container {
width: 100%;
background-color: #e0e0e0;
border-radius: 5px;
height: 10px;
margin-top: 5px;
}
.progress-bar {
height: 100%;
border-radius: 5px;
background: linear-gradient(90deg, var(--primary-color), var(--secondary-color));
}
.chmod-selector {
display: flex;
gap: 15px;
margin-top: 15px;
}
.chmod-group {
display: flex;
flex-direction: column;
gap: 5px;
}
.chmod-label {
font-weight: 500;
margin-bottom: 5px;
}
.chmod-checkbox {
display: flex;
align-items: center;
gap: 5px;
}
@media (max-width: 768px) {
.container {
grid-template-columns: 1fr;
}
.sidebar {
grid-column: 1;
}
}
</style>
</head>
<body>
<div class="header">
<div class="logo"><?php echo $APP_NAME; ?></div>
<a href="?logout=1" class="logout">Déconnexion</a>
</div>
<div class="container">
<div class="main-content">
<div class="breadcrumb">
<a href="?">Accueil</a>
<?php
$path_parts = explode('/', $relative_path);
$current_path = '';
foreach ($path_parts as $part) {
if (!empty($part)) {
$current_path .= '/' . $part;
echo '<span class="breadcrumb-separator">/</span>';
echo '<a href="?dir=' . urlencode(ltrim($current_path, '/')) . '">' . htmlspecialchars($part) . '</a>';
}
}
?>
</div>
<div class="file-actions">
<button onclick="document.getElementById('upload-modal').style.display='flex'" class="btn">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
<path d="M.5 9.9a.5.5 0 0 1 .5.5v2.5a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-2.5a.5.5 0 0 1 1 0v2.5a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2v-2.5a.5.5 0 0 1 .5-.5z"/>
<path d="M7.646 1.146a.5.5 0 0 1 .708 0l3 3a.5.5 0 0 1-.708.708L8.5 2.707V11.5a.5.5 0 0 1-1 0V2.707L5.354 4.854a.5.5 0 1 1-.708-.708l3-3z"/>
</svg>
Upload
</button>
<button onclick="document.getElementById('folder-modal').style.display='flex'" class="btn">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
<path d="M.54 3.87.5 3a2 2 0 0 1 2-2h3.672a2 2 0 0 1 1.414.586l.828.828A2 2 0 0 0 9.828 3h3.982a2 2 0 0 1 1.992 2.181l-.637 7A2 2 0 0 1 13.174 14H2.826a2 2 0 0 1-1.991-1.819l-.637-7a1.99 1.99 0 0 1 .342-1.31zM2.19 4a1 1 0 0 0-.996 1.09l.637 7a1 1 0 0 0 .995.91h10.348a1 1 0 0 0 .995-.91l.637-7A1 1 0 0 0 13.81 4H2.19zm4.69-1.707A1 1 0 0 0 6.172 2H2.5a1 1 0 0 0-1 .981l.006.139C1.72 3.042 1.95 3 2.19 3h5.396l-.707-.707z"/>
</svg>
Nouveau dossier
</button>
<button onclick="document.getElementById('server-modal').style.display='flex'" class="btn btn-accent">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
<path d="M1.333 2.667C1.333 1.194 4.318 0 8 0s6.667 1.194 6.667 2.667V4c0 1.473-2.985 2.667-6.667 2.667S1.333 5.473 1.333 4V2.667z"/>
<path d="M1.333 6.334v3C1.333 10.805 4.318 12 8 12s6.667-1.194 6.667-2.667V6.334a6.51 6.51 0 0 1-1.458.79C11.81 7.684 9.967 8 8 8c-1.966 0-3.809-.317-5.208-.876a6.508 6.508 0 0 1-1.458-.79z"/>
<path d="M14.667 11.668a6.51 6.51 0 0 1-1.458.789c-1.4.56-3.242.876-5.21.876-1.966 0-3.809-.316-5.208-.876a6.51 6.51 0 0 1-1.458-.79v1.666C1.333 14.806 4.318 16 8 16s6.667-1.194 6.667-2.667v-1.665z"/>
</svg>
Info Serveur
</button>
</div>
<div class="card file-list">
<table>
<thead>
<tr>
<th>Nom</th>
<th>Taille</th>
<th>Permissions</th>
<th>Modifié</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php if (!empty($relative_path)): ?>
<tr>
<td>
<img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJsdWNpZGUgbHVjaWRlLWZvbGRlci11cCI+PHBhdGggZD0iTTIwIDIwYTIgMiAwIDAgMS0yIDJIMmEyIDIgMCAwIDEtMi0yVjVhMiAyIDAgMCAxIDItMmgzLjljLjcgMCAxLjMuMyAxLjcuOWwuOCAxLjJjLjQuNiAxIC45IDEuNy45SDhhMiAyIDAgMCAxIDIgMnYzIi8+PHBhdGggZD0ibTE0IDEzLTQtNCIvPjxwYXRoIGQ9Im0xNCAxMyA0LTQiLz48L3N2Zz4=" class="file-icon" alt="Dossier parent">
<a href="?dir=<?php echo urlencode(dirname($relative_path)); ?>">..</a>
</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<?php endif; ?>
<?php foreach ($files as $file): ?>
<?php
$file_path = $current_dir . '/' . $file;
$is_dir = is_dir($file_path);
$file_url = $is_dir
? '?dir=' . urlencode($relative_path . (empty($relative_path) ? '' : '/') . $file)
: '?action=download&file=' . urlencode($file) . '&dir=' . urlencode($relative_path);
$file_size = $is_dir ? '' : format_size(filesize($file_path));
$modified = date('Y-m-d H:i', filemtime($file_path));
$perms = get_file_perms($file_path);
$owner = get_file_owner($file_path);
?>
<tr>
<td>
<img src="data:image/svg+xml;base64,<?php echo $is_dir
? 'PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJsdWNpZGUgbHVjaWRlLWZvbGRlciI+PHBhdGggZD0iTTIwIDIwYTIgMiAwIDAgMS0yIDJIMmEyIDIgMCAwIDEtMi0yVjVhMiAyIDAgMCAxIDItMmgzLjljLjcgMCAxLjMuMyAxLjcuOWwuOCAxLjJjLjQuNiAxIC45IDEuNy45SDhhMiAyIDAgMCAxIDIgMnYzIi8+PC9zdmc+'
: 'PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJsdWNpZGUgbHVjaWRlLWZpbGUiPjxwYXRoIGQ9Ik0xNCAySDZhMiAyIDAgMCAwLTIgMnYxNmEyIDIgMCAwIDAgMiAyaDEyYTIgMiAwIDAgMCAyLTJWOThaIi8+PHBhdGggZD0iTTE0IDJ2Nmg2Ii8+PC9zdmc+'; ?>" class="file-icon" alt="<?php echo $is_dir ? 'Dossier' : 'Fichier'; ?>">
<a href="<?php echo htmlspecialchars($file_url); ?>"><?php echo htmlspecialchars($file); ?></a>
</td>
<td class="file-size"><?php echo $file_size; ?></td>
<td class="file-perms"><?php echo $perms; ?></td>
<td><?php echo $modified; ?></td>
<td class="file-actions-cell">
<a href="?action=view&file=<?php echo urlencode($file); ?>&dir=<?php echo urlencode($relative_path); ?>" class="action-link">Voir</a>
<a href="?action=download&file=<?php echo urlencode($file); ?>&dir=<?php echo urlencode($relative_path); ?>" class="action-link" <?php echo $is_dir ? 'style="visibility:hidden"' : ''; ?>>Télécharger</a>
<a href="?action=info&file=<?php echo urlencode($file); ?>&dir=<?php echo urlencode($relative_path); ?>" class="action-link">Info</a>
<a href="?action=delete&file=<?php echo urlencode($file); ?>&dir=<?php echo urlencode($relative_path); ?>" class="action-link" onclick="return confirm('Êtes-vous sûr de vouloir supprimer ce <?php echo $is_dir ? 'dossier' : 'fichier'; ?> ?')">Supprimer</a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
<div class="sidebar">
<?php if (isset($_GET['action']) && $_GET['action'] === 'info' && isset($_GET['file'])): ?>
<?php
$file_path = $current_dir . '/' . basename($_GET['file']);
if (file_exists($file_path) && strpos(realpath($file_path), $ROOT_DIR) === 0):
$is_dir = is_dir($file_path);
$file_info = [
'Nom' => basename($file_path),
'Chemin' => $file_path,
'Type' => $is_dir ? 'Dossier' : 'Fichier',
'Taille' => $is_dir ? '-' : format_size(filesize($file_path)),
'Permissions' => get_file_perms($file_path),
'Propriétaire' => get_file_owner($file_path),
'Dernière modification' => date('Y-m-d H:i:s', filemtime($file_path)),
'Dernier accès' => date('Y-m-d H:i:s', fileatime($file_path))
];
if (!$is_dir) {
$file_info['Extension'] = pathinfo($file_path, PATHINFO_EXTENSION) ?: 'Aucune';
$file_info['MIME Type'] = mime_content_type($file_path);
}
?>
<div class="card">
<div class="card-header">
<span>Informations</span>
<a href="?dir=<?php echo urlencode($relative_path); ?>" style="color: var(--primary-color); text-decoration: none;">×</a>
</div>
<div class="card-body">
<?php foreach ($file_info as $label => $value): ?>
<div class="info-grid">
<div class="info-label"><?php echo $label; ?></div>
<div><?php echo htmlspecialchars($value); ?></div>
</div>
<?php endforeach; ?>
<form method="POST" action="?action=chmod&file=<?php echo urlencode($_GET['file']); ?>&dir=<?php echo urlencode($relative_path); ?>">
<div class="info-label">Changer les permissions:</div>
<input type="text" name="mode" value="<?php echo substr(sprintf('%o', fileperms($file_path)), -4); ?>" pattern="[0-7]{3,4}" required>
<button type="submit" class="btn" style="margin-top: 10px;">Appliquer</button>
</form>
</div>
</div>
<?php endif; ?>
<?php endif; ?>
<div class="card">
<div class="card-header">Espace Disque</div>
<div class="card-body">
<div class="info-grid">
<div class="info-label">Total:</div>
<div><?php echo format_size($server_info['Disk Space']['Total']); ?></div>
</div>
<div class="info-grid">
<div class="info-label">Utilisé:</div>
<div><?php echo format_size($server_info['Disk Space']['Used']); ?></div>
</div>
<div class="info-grid">
<div class="info-label">Libre:</div>
<div><?php echo format_size($server_info['Disk Space']['Free']); ?></div>
</div>
<div class="progress-container">
<div class="progress-bar" style="width: <?php echo round(($server_info['Disk Space']['Used'] / $server_info['Disk Space']['Total']) * 100); ?>%"></div>
</div>
</div>
</div>
</div>
</div>
<!-- Modals -->
<div class="modal" id="upload-modal">
<div class="modal-content">
<h3 class="modal-title">Uploader un fichier</h3>
<form action="?dir=<?php echo urlencode($relative_path); ?>" method="POST" enctype="multipart/form-data">
<div class="form-group">
<input type="file" name="file_upload" required>
</div>
<div class="modal-actions">
<button type="button" class="btn btn-secondary" onclick="document.getElementById('upload-modal').style.display='none'">Annuler</button>
<button type="submit" class="btn">Uploader</button>
</div>
</form>
</div>
</div>
<div class="modal" id="folder-modal">
<div class="modal-content">
<h3 class="modal-title">Créer un nouveau dossier</h3>
<form action="?dir=<?php echo urlencode($relative_path); ?>" method="POST">
<div class="form-group">
<label for="new_folder">Nom du dossier</label>
<input type="text" id="new_folder" name="new_folder" required pattern="[a-zA-Z0-9\-_]+" title="Seulement lettres, chiffres, tirets et underscores">
</div>
<div class="modal-actions">
<button type="button" class="btn btn-secondary" onclick="document.getElementById('folder-modal').style.display='none'">Annuler</button>
<button type="submit" class="btn">Créer</button>
</div>
</form>
</div>
</div>
<div class="modal" id="server-modal">
<div class="modal-content">
<h3 class="modal-title">Informations du Serveur</h3>
<div class="card-body">
<?php foreach ($server_info as $label => $value): ?>
<?php if (is_array($value)): ?>
<div style="margin-bottom: 15px;">
<div style="font-weight: 500; margin-bottom: 5px;"><?php echo $label; ?></div>
<?php foreach ($value as $sub_label => $sub_value): ?>
<div style="display: flex; justify-content: space-between; margin-bottom: 3px;">
<span style="color: var(--light-text);"><?php echo $sub_label; ?></span>
<span><?php echo is_numeric($sub_value) ? format_size($sub_value) : htmlspecialchars($sub_value); ?></span>
</div>
<?php endforeach; ?>
</div>
<?php else: ?>
<div style="display: flex; justify-content: space-between; margin-bottom: 10px;">
<span style="font-weight: 500; color: var(--light-text);"><?php echo $label; ?></span>
<span><?php echo htmlspecialchars($value); ?></span>
</div>
<?php endif; ?>
<?php endforeach; ?>
</div>
<div class="modal-actions">
<button type="button" class="btn" onclick="document.getElementById('server-modal').style.display='none'">Fermer</button>
</div>
</div>
</div>
<script>
// Fermer les modales en cliquant à l'extérieur
window.onclick = function(event) {
if (event.target.className === 'modal') {
event.target.style.display = 'none';
}
}
// Gérer la déconnexion
if (window.location.search.includes('logout=1')) {
window.location.href = window.location.pathname;
}
</script>
</body>
</html>