dossier privé
protégé par id+mdp
This commit is contained in:
parent
ba9661eef5
commit
4fbf15f5b4
96
privé/auth.php
Normal file
96
privé/auth.php
Normal file
@ -0,0 +1,96 @@
|
||||
<?php
|
||||
// auth.php
|
||||
session_start();
|
||||
|
||||
class Auth {
|
||||
private $config;
|
||||
|
||||
public function __construct() {
|
||||
$this->config = require 'config.php';
|
||||
}
|
||||
|
||||
public function isAuthenticated() {
|
||||
if (!isset($_SESSION['auth_time']) || !isset($_SESSION['username'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Vérifier si la session n'a pas expiré
|
||||
$elapsed = time() - $_SESSION['auth_time'];
|
||||
if ($elapsed > $this->config['session_duration']) {
|
||||
$this->logout();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function login($username, $password) {
|
||||
if (!isset($this->config['users'][$username])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($this->config['users'][$username]['password'] === $password) {
|
||||
$_SESSION['auth_time'] = time();
|
||||
$_SESSION['username'] = $username;
|
||||
$_SESSION['user_description'] = $this->config['users'][$username]['description'];
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function logout() {
|
||||
session_destroy();
|
||||
}
|
||||
|
||||
public function getCurrentUser() {
|
||||
if ($this->isAuthenticated()) {
|
||||
return [
|
||||
'username' => $_SESSION['username'],
|
||||
'description' => $_SESSION['user_description']
|
||||
];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Point d'entrée API pour l'authentification
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
header('Content-Type: application/json');
|
||||
|
||||
$auth = new Auth();
|
||||
$data = json_decode(file_get_contents('php://input'), true);
|
||||
|
||||
if (isset($data['action'])) {
|
||||
switch ($data['action']) {
|
||||
case 'login':
|
||||
if (isset($data['username']) && isset($data['password'])) {
|
||||
$success = $auth->login($data['username'], $data['password']);
|
||||
if ($success) {
|
||||
$user = $auth->getCurrentUser();
|
||||
echo json_encode(['success' => true, 'user' => $user]);
|
||||
} else {
|
||||
echo json_encode(['success' => false, 'error' => 'Identifiants incorrects']);
|
||||
}
|
||||
} else {
|
||||
echo json_encode(['success' => false, 'error' => 'Identifiants manquants']);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'logout':
|
||||
$auth->logout();
|
||||
echo json_encode(['success' => true]);
|
||||
break;
|
||||
|
||||
case 'check':
|
||||
$isAuthenticated = $auth->isAuthenticated();
|
||||
$user = $isAuthenticated ? $auth->getCurrentUser() : null;
|
||||
echo json_encode([
|
||||
'authenticated' => $isAuthenticated,
|
||||
'user' => $user
|
||||
]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
exit;
|
||||
}
|
||||
?>
|
21
privé/config.php
Normal file
21
privé/config.php
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
// config.php
|
||||
return [
|
||||
'users' => [
|
||||
'admin' => [
|
||||
'password' => 'votre_mot_de_passe_admin', // À changer !
|
||||
'description' => 'Administrateur'
|
||||
],
|
||||
'user1' => [
|
||||
'password' => 'votre_mot_de_passe_user1', // À changer !
|
||||
'description' => 'Utilisateur 1'
|
||||
],
|
||||
'invite' => [
|
||||
'password' => 'votre_mot_de_passe_invite', // À changer !
|
||||
'description' => 'Invité'
|
||||
]
|
||||
],
|
||||
'session_duration' => 3600, // Durée de la session en secondes (1 heure)
|
||||
// Vous pouvez ajouter autant d'utilisateurs que nécessaire
|
||||
];
|
||||
?>
|
40
privé/get-file.php
Normal file
40
privé/get-file.php
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
// get-file.php
|
||||
require_once 'auth.php';
|
||||
|
||||
$auth = new Auth();
|
||||
|
||||
// Vérifier l'authentification
|
||||
if (!$auth->isAuthenticated()) {
|
||||
http_response_code(401);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Vérifier si un fichier est spécifié
|
||||
if (!isset($_GET['file'])) {
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
$filename = $_GET['file'];
|
||||
$filepath = './' . $filename;
|
||||
|
||||
// Vérifier que le fichier existe et est dans le dossier courant
|
||||
if (!file_exists($filepath) || !is_file($filepath) || dirname(realpath($filepath)) !== realpath('.')) {
|
||||
http_response_code(404);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Fichiers système à ne pas servir
|
||||
$forbidden_files = ['index.html', 'list-files.php', 'auth.php', 'config.php', 'get-file.php'];
|
||||
if (in_array($filename, $forbidden_files)) {
|
||||
http_response_code(403);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Servir le fichier
|
||||
$mime_type = mime_content_type($filepath);
|
||||
header('Content-Type: ' . $mime_type);
|
||||
header('Content-Disposition: inline; filename="' . basename($filepath) . '"');
|
||||
readfile($filepath);
|
||||
?>
|
778
privé/index.html
Normal file
778
privé/index.html
Normal file
@ -0,0 +1,778 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr" data-theme="dark">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Esenjin | Explorateur de fichiers</title>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/js/all.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.min.js"></script>
|
||||
<style>
|
||||
/* Variables de thème */
|
||||
:root[data-theme="dark"] {
|
||||
--primary-color: #64B5F6;
|
||||
--hover-color: #42A5F5;
|
||||
--bg-color: #1a1a1a;
|
||||
--container-bg: #2d2d2d;
|
||||
--text-color: #e0e0e0;
|
||||
--border-color: #404040;
|
||||
--meta-color: #909090;
|
||||
--input-bg: #3d3d3d;
|
||||
}
|
||||
|
||||
:root[data-theme="light"] {
|
||||
--primary-color: #4a90e2;
|
||||
--hover-color: #357abd;
|
||||
--bg-color: #f5f6fa;
|
||||
--container-bg: white;
|
||||
--text-color: #333;
|
||||
--border-color: #eee;
|
||||
--meta-color: #666;
|
||||
--input-bg: white;
|
||||
}
|
||||
|
||||
/* Global styles */
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||
margin: 0;
|
||||
padding: 20px;
|
||||
background: var(--bg-color);
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
.theme-toggle {
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
padding: 10px;
|
||||
border-radius: 5px;
|
||||
background: var(--input-bg);
|
||||
border: 1px solid var(--border-color);
|
||||
color: var(--text-color);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
background: var(--container-bg);
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 2px 10px rgba(0,0,0,0.2);
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: var(--primary-color);
|
||||
margin-bottom: 30px;
|
||||
padding-bottom: 10px;
|
||||
border-bottom: 2px solid var(--border-color);
|
||||
}
|
||||
|
||||
.file-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
|
||||
gap: 20px;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.file-item {
|
||||
background: var(--container-bg);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 8px;
|
||||
padding: 15px;
|
||||
transition: all 0.3s ease;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
color: var(--text-color);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.file-item:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.2);
|
||||
border-color: var(--primary-color);
|
||||
}
|
||||
|
||||
.file-icon {
|
||||
font-size: 2em;
|
||||
margin-bottom: 10px;
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
.file-name {
|
||||
word-break: break-word;
|
||||
margin-top: 8px;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.file-meta {
|
||||
font-size: 0.8em;
|
||||
color: var(--meta-color);
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.search-bar {
|
||||
width: 100%;
|
||||
max-width: 500px;
|
||||
margin: 0 auto 20px;
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
flex: 1;
|
||||
padding: 10px 15px;
|
||||
border: 2px solid var(--border-color);
|
||||
border-radius: 5px;
|
||||
font-size: 1em;
|
||||
background: var(--input-bg);
|
||||
color: var(--text-color);
|
||||
transition: border-color 0.3s ease;
|
||||
}
|
||||
|
||||
.search-input:focus {
|
||||
outline: none;
|
||||
border-color: var(--primary-color);
|
||||
}
|
||||
|
||||
.sort-select {
|
||||
padding: 10px;
|
||||
border: 2px solid var(--border-color);
|
||||
border-radius: 5px;
|
||||
background: var(--input-bg);
|
||||
color: var(--text-color);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.sort-select:focus {
|
||||
outline: none;
|
||||
border-color: var(--primary-color);
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.file-grid {
|
||||
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
|
||||
}
|
||||
}
|
||||
|
||||
/* Modal */
|
||||
.modal {
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, 0.9);
|
||||
z-index: 1000;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
position: relative;
|
||||
margin: auto;
|
||||
padding: 20px;
|
||||
width: 90%;
|
||||
max-width: 1200px;
|
||||
min-height: 200px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
.modal-close {
|
||||
position: absolute;
|
||||
right: 25px;
|
||||
top: 25px;
|
||||
color: var(--text-color);
|
||||
font-size: 24px;
|
||||
cursor: pointer;
|
||||
z-index: 1001;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.preview-container {
|
||||
width: 100%;
|
||||
height: 80vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.preview-container img {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.preview-container video,
|
||||
.preview-container audio {
|
||||
width: 100%;
|
||||
max-width: 800px;
|
||||
}
|
||||
|
||||
.preview-container iframe {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.loading {
|
||||
color: var(--text-color);
|
||||
text-align: center;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.modal-content {
|
||||
width: 95%;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.preview-container {
|
||||
height: 60vh;
|
||||
}
|
||||
}
|
||||
|
||||
/* formulaire de conexion */
|
||||
.login-container {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: var(--bg-color);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 2000;
|
||||
}
|
||||
|
||||
.login-form {
|
||||
background: var(--container-bg);
|
||||
padding: 30px;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 2px 10px rgba(0,0,0,0.2);
|
||||
width: 100%;
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
.login-form h2 {
|
||||
color: var(--primary-color);
|
||||
margin-bottom: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.login-form input[type="password"] {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
margin-bottom: 15px;
|
||||
border: 2px solid var(--border-color);
|
||||
border-radius: 5px;
|
||||
background: var(--input-bg);
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
.login-form button {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
background: var(--primary-color);
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
transition: background 0.3s;
|
||||
}
|
||||
|
||||
.login-form button:hover {
|
||||
background: var(--hover-color);
|
||||
}
|
||||
|
||||
.login-error {
|
||||
color: #ff4444;
|
||||
margin-bottom: 15px;
|
||||
text-align: center;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.user-controls {
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
right: 80px;
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.logout-button {
|
||||
padding: 10px;
|
||||
background: var(--input-bg);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 5px;
|
||||
color: var(--text-color);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.login-form input[type="text"],
|
||||
.login-form input[type="password"] {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
margin-bottom: 15px;
|
||||
border: 2px solid var(--border-color);
|
||||
border-radius: 5px;
|
||||
background: var(--input-bg);
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
.user-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
.user-avatar {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
background: var(--primary-color);
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.user-name {
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.user-description {
|
||||
color: var(--meta-color);
|
||||
font-size: 0.8em;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="loginContainer" class="login-container">
|
||||
<form id="loginForm" class="login-form">
|
||||
<h2>Connexion</h2>
|
||||
<div id="loginError" class="login-error">Identifiants incorrects</div>
|
||||
<input type="text" id="username" placeholder="Identifiant" required>
|
||||
<input type="password" id="password" placeholder="Mot de passe" required>
|
||||
<button type="submit">Se connecter</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="user-controls">
|
||||
<div class="user-info">
|
||||
<div class="user-avatar" id="userAvatar"></div>
|
||||
<div>
|
||||
<div class="user-name" id="userName"></div>
|
||||
<div class="user-description" id="userDescription"></div>
|
||||
</div>
|
||||
</div>
|
||||
<button id="logoutButton" class="logout-button">
|
||||
<i class="fas fa-sign-out-alt"></i> Déconnexion
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<button class="theme-toggle" id="themeToggle">
|
||||
<i class="fas fa-moon"></i>
|
||||
</button>
|
||||
|
||||
<div class="container">
|
||||
<h1>De bric et de broc ...</h1>
|
||||
|
||||
<div class="search-bar">
|
||||
<input type="text" class="search-input" placeholder="Rechercher des fichiers..." id="searchInput">
|
||||
<select class="sort-select" id="sortSelect">
|
||||
<option value="name">Nom</option>
|
||||
<option value="date">Date</option>
|
||||
<option value="size">Taille</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="file-grid" id="fileGrid">
|
||||
<!-- Les fichiers seront ajoutés ici dynamiquement -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="previewModal" class="modal">
|
||||
<span class="modal-close" id="modalClose">×</span>
|
||||
<div class="modal-content">
|
||||
<div id="previewContainer" class="preview-container">
|
||||
<div class="loading">Chargement ...</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Gestion de l'authentification
|
||||
const loginContainer = document.getElementById('loginContainer');
|
||||
const loginForm = document.getElementById('loginForm');
|
||||
const loginError = document.getElementById('loginError');
|
||||
const logoutButton = document.getElementById('logoutButton');
|
||||
|
||||
async function checkAuth() {
|
||||
try {
|
||||
const response = await fetch('auth.php', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ action: 'check' })
|
||||
});
|
||||
const data = await response.json();
|
||||
return data.authenticated;
|
||||
} catch (error) {
|
||||
console.error('Erreur de vérification d\'authentification:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async function login(username, password) {
|
||||
try {
|
||||
const response = await fetch('auth.php', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
action: 'login',
|
||||
username,
|
||||
password
|
||||
})
|
||||
});
|
||||
const data = await response.json();
|
||||
if (data.success && data.user) {
|
||||
updateUserInfo(data.user);
|
||||
}
|
||||
return data.success;
|
||||
} catch (error) {
|
||||
console.error('Erreur de connexion:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function updateUserInfo(user) {
|
||||
const avatar = document.getElementById('userAvatar');
|
||||
const name = document.getElementById('userName');
|
||||
const description = document.getElementById('userDescription');
|
||||
|
||||
avatar.textContent = user.username.charAt(0).toUpperCase();
|
||||
name.textContent = user.username;
|
||||
description.textContent = user.description;
|
||||
}
|
||||
|
||||
loginForm.addEventListener('submit', async (e) => {
|
||||
e.preventDefault();
|
||||
const username = document.getElementById('username').value;
|
||||
const password = document.getElementById('password').value;
|
||||
const success = await login(username, password);
|
||||
|
||||
if (success) {
|
||||
hideLoginForm();
|
||||
initializeFiles();
|
||||
} else {
|
||||
loginError.style.display = 'block';
|
||||
}
|
||||
|
||||
document.getElementById('username').value = '';
|
||||
document.getElementById('password').value = '';
|
||||
});
|
||||
|
||||
async function checkAuth() {
|
||||
try {
|
||||
const response = await fetch('auth.php', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ action: 'check' })
|
||||
});
|
||||
const data = await response.json();
|
||||
if (data.authenticated && data.user) {
|
||||
updateUserInfo(data.user);
|
||||
}
|
||||
return data.authenticated;
|
||||
} catch (error) {
|
||||
console.error('Erreur de vérification d\'authentification:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async function logout() {
|
||||
try {
|
||||
await fetch('auth.php', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ action: 'logout' })
|
||||
});
|
||||
showLoginForm();
|
||||
} catch (error) {
|
||||
console.error('Erreur de déconnexion:', error);
|
||||
}
|
||||
}
|
||||
|
||||
function showLoginForm() {
|
||||
loginContainer.style.display = 'flex';
|
||||
loginError.style.display = 'none';
|
||||
}
|
||||
|
||||
function hideLoginForm() {
|
||||
loginContainer.style.display = 'none';
|
||||
}
|
||||
|
||||
loginForm.addEventListener('submit', async (e) => {
|
||||
e.preventDefault();
|
||||
const password = document.getElementById('password').value;
|
||||
const success = await login(password);
|
||||
|
||||
if (success) {
|
||||
hideLoginForm();
|
||||
initializeFiles();
|
||||
} else {
|
||||
loginError.style.display = 'block';
|
||||
}
|
||||
|
||||
document.getElementById('password').value = '';
|
||||
});
|
||||
|
||||
logoutButton.addEventListener('click', logout);
|
||||
|
||||
// Vérifier l'authentification au chargement
|
||||
async function initialize() {
|
||||
const isAuthenticated = await checkAuth();
|
||||
if (isAuthenticated) {
|
||||
hideLoginForm();
|
||||
await initializeFiles();
|
||||
} else {
|
||||
showLoginForm();
|
||||
}
|
||||
}
|
||||
|
||||
// Toggle thème
|
||||
const themeToggle = document.getElementById('themeToggle');
|
||||
const html = document.documentElement;
|
||||
|
||||
themeToggle.addEventListener('click', () => {
|
||||
const currentTheme = html.getAttribute('data-theme');
|
||||
const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
|
||||
html.setAttribute('data-theme', newTheme);
|
||||
themeToggle.innerHTML = newTheme === 'dark' ? '<i class="fas fa-moon"></i>' : '<i class="fas fa-sun"></i>';
|
||||
});
|
||||
|
||||
// Fonction pour déterminer l'icône
|
||||
function getFileIcon(filename) {
|
||||
const ext = filename.split('.').pop().toLowerCase();
|
||||
const iconMap = {
|
||||
pdf: 'file-pdf',
|
||||
doc: 'file-word',
|
||||
docx: 'file-word',
|
||||
xls: 'file-excel',
|
||||
xlsx: 'file-excel',
|
||||
jpg: 'file-image',
|
||||
jpeg: 'file-image',
|
||||
png: 'file-image',
|
||||
gif: 'file-image',
|
||||
mp3: 'file-audio',
|
||||
wav: 'file-audio',
|
||||
mp4: 'file-video',
|
||||
zip: 'file-archive',
|
||||
rar: 'file-archive'
|
||||
};
|
||||
|
||||
return iconMap[ext] || 'file';
|
||||
}
|
||||
|
||||
// Fonction pour formater la taille
|
||||
function formatFileSize(bytes) {
|
||||
if (bytes === 0) return '0 Bytes';
|
||||
const k = 1024;
|
||||
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
||||
}
|
||||
|
||||
function createFileElement(file) {
|
||||
const fileItem = document.createElement('a');
|
||||
fileItem.className = 'file-item';
|
||||
fileItem.href = '#';
|
||||
|
||||
const icon = getFileIcon(file.name);
|
||||
|
||||
fileItem.innerHTML = `
|
||||
<i class="fa-solid fa-${icon} file-icon"></i>
|
||||
<div class="file-name">${file.name}</div>
|
||||
<div class="file-meta">${formatFileSize(file.size)}</div>
|
||||
<div class="file-meta">${file.date}</div>
|
||||
`;
|
||||
|
||||
// Gestion du clic pour la prévisualisation
|
||||
fileItem.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
previewFile(file);
|
||||
});
|
||||
|
||||
return fileItem;
|
||||
}
|
||||
|
||||
// Gestion de la prévisualisation
|
||||
const modal = document.getElementById('previewModal');
|
||||
const modalClose = document.getElementById('modalClose');
|
||||
const previewContainer = document.getElementById('previewContainer');
|
||||
|
||||
modalClose.addEventListener('click', () => {
|
||||
modal.style.display = 'none';
|
||||
previewContainer.innerHTML = '<div class="loading">Chargement...</div>';
|
||||
});
|
||||
|
||||
window.addEventListener('click', (e) => {
|
||||
if (e.target === modal) {
|
||||
modal.style.display = 'none';
|
||||
previewContainer.innerHTML = '<div class="loading">Chargement...</div>';
|
||||
}
|
||||
});
|
||||
|
||||
function getFileType(filename) {
|
||||
const ext = filename.split('.').pop().toLowerCase();
|
||||
const imageTypes = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
|
||||
const videoTypes = ['mp4', 'webm', 'ogg'];
|
||||
const audioTypes = ['mp3', 'wav', 'ogg'];
|
||||
const documentTypes = ['pdf'];
|
||||
|
||||
if (imageTypes.includes(ext)) return 'image';
|
||||
if (videoTypes.includes(ext)) return 'video';
|
||||
if (audioTypes.includes(ext)) return 'audio';
|
||||
if (documentTypes.includes(ext)) return 'pdf';
|
||||
return 'other';
|
||||
}
|
||||
|
||||
async function previewFile(file) {
|
||||
modal.style.display = 'block';
|
||||
const fileType = getFileType(file.name);
|
||||
const fileUrl = file.path;
|
||||
|
||||
switch (fileType) {
|
||||
case 'image':
|
||||
previewContainer.innerHTML = `
|
||||
<img src="${fileUrl}" alt="${file.name}" />
|
||||
`;
|
||||
break;
|
||||
|
||||
case 'video':
|
||||
previewContainer.innerHTML = `
|
||||
<video controls>
|
||||
<source src="${fileUrl}" type="video/${file.name.split('.').pop()}">
|
||||
Votre navigateur ne supporte pas la lecture vidéo.
|
||||
</video>
|
||||
`;
|
||||
break;
|
||||
|
||||
case 'audio':
|
||||
previewContainer.innerHTML = `
|
||||
<audio controls>
|
||||
<source src="${fileUrl}" type="audio/${file.name.split('.').pop()}">
|
||||
Votre navigateur ne supporte pas la lecture audio.
|
||||
</audio>
|
||||
`;
|
||||
break;
|
||||
|
||||
case 'pdf':
|
||||
// Utilisation de PDF.js pour les PDF
|
||||
previewContainer.innerHTML = `
|
||||
<iframe src="${fileUrl}" type="application/pdf"></iframe>
|
||||
`;
|
||||
break;
|
||||
|
||||
default:
|
||||
previewContainer.innerHTML = `
|
||||
<div class="loading">
|
||||
Ce type de fichier ne peut pas être prévisualisé.<br>
|
||||
<a href="${fileUrl}" target="_blank" style="color: var(--primary-color);">
|
||||
Télécharger le fichier
|
||||
</a>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
// Charger les fichiers depuis l'API
|
||||
async function loadFiles() {
|
||||
try {
|
||||
const response = await fetch('list-files.php');
|
||||
const files = await response.json();
|
||||
return files;
|
||||
} catch (error) {
|
||||
console.error('Erreur lors du chargement des fichiers:', error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
// Initialisation
|
||||
let allFiles = [];
|
||||
|
||||
async function initializeFiles() {
|
||||
allFiles = await loadFiles();
|
||||
displayFiles(allFiles);
|
||||
}
|
||||
|
||||
function displayFiles(files) {
|
||||
const fileGrid = document.getElementById('fileGrid');
|
||||
fileGrid.innerHTML = '';
|
||||
files.forEach(file => {
|
||||
fileGrid.appendChild(createFileElement(file));
|
||||
});
|
||||
}
|
||||
|
||||
// Recherche
|
||||
const searchInput = document.getElementById('searchInput');
|
||||
searchInput.addEventListener('input', (e) => {
|
||||
const searchTerm = e.target.value.toLowerCase();
|
||||
const filteredFiles = allFiles.filter(file =>
|
||||
file.name.toLowerCase().includes(searchTerm)
|
||||
);
|
||||
displayFiles(filteredFiles);
|
||||
});
|
||||
|
||||
// Tri
|
||||
const sortSelect = document.getElementById('sortSelect');
|
||||
sortSelect.addEventListener('change', (e) => {
|
||||
const sortBy = e.target.value;
|
||||
const sortedFiles = [...allFiles].sort((a, b) => {
|
||||
switch(sortBy) {
|
||||
case 'name':
|
||||
return a.name.localeCompare(b.name);
|
||||
case 'date':
|
||||
return new Date(b.date) - new Date(a.date);
|
||||
case 'size':
|
||||
return b.size - a.size;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
displayFiles(sortedFiles);
|
||||
});
|
||||
|
||||
// Modifier la fonction loadFiles pour gérer les erreurs d'authentification
|
||||
async function loadFiles() {
|
||||
try {
|
||||
const response = await fetch('list-files.php');
|
||||
if (response.status === 401) {
|
||||
showLoginForm();
|
||||
return [];
|
||||
}
|
||||
const files = await response.json();
|
||||
return files;
|
||||
} catch (error) {
|
||||
console.error('Erreur lors du chargement des fichiers:', error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
// Lancer l'initialisation
|
||||
initialize();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
48
privé/list-files.php
Normal file
48
privé/list-files.php
Normal file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
// list-files.php
|
||||
require_once 'auth.php';
|
||||
|
||||
$auth = new Auth();
|
||||
|
||||
// Vérifier l'authentification
|
||||
if (!$auth->isAuthenticated()) {
|
||||
http_response_code(401);
|
||||
echo json_encode(['error' => 'Non authentifié']);
|
||||
exit;
|
||||
}
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
function scanDirectory($dir = '.') {
|
||||
$files = [];
|
||||
$scan = scandir($dir);
|
||||
|
||||
foreach ($scan as $file) {
|
||||
// Ignore les fichiers cachés, système et les fichiers de configuration
|
||||
if ($file[0] === '.' || in_array($file, ['index.html', 'list-files.php', 'auth.php', 'config.php'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$path = $dir . '/' . $file;
|
||||
|
||||
if (is_file($path)) {
|
||||
$files[] = [
|
||||
'name' => $file,
|
||||
'size' => filesize($path),
|
||||
'date' => date('Y-m-d', filemtime($path)),
|
||||
'path' => 'get-file.php?file=' . rawurlencode($file)
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $files;
|
||||
}
|
||||
|
||||
try {
|
||||
$files = scanDirectory('.');
|
||||
echo json_encode($files);
|
||||
} catch (Exception $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode(['error' => $e->getMessage()]);
|
||||
}
|
||||
?>
|
Loading…
x
Reference in New Issue
Block a user