ajout de la gestion des albums privés (partie 1)
This commit is contained in:
parent
87aa0271a5
commit
d25d6a4b36
12
admin.php
12
admin.php
@ -121,6 +121,18 @@ function showAdminInterface() {
|
|||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
<a href="arbre-prive.php" class="admin-menu-item">
|
||||||
|
<div class="menu-icon">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect>
|
||||||
|
<path d="M7 11V7a5 5 0 0 1 10 0v4"></path>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div class="menu-content">
|
||||||
|
<h2>Albums privés</h2>
|
||||||
|
<p>Gérez vos albums photos privés et sécurisés.</p>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
305
arbre-img-prive.php
Normal file
305
arbre-img-prive.php
Normal file
@ -0,0 +1,305 @@
|
|||||||
|
<?php
|
||||||
|
require_once 'fonctions.php';
|
||||||
|
|
||||||
|
// Vérifier l'authentification
|
||||||
|
session_start();
|
||||||
|
if (!isset($_SESSION['admin_id'])) {
|
||||||
|
header('Location: admin.php?action=login');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Récupérer le chemin courant
|
||||||
|
$currentPath = isset($_GET['path']) ? $_GET['path'] : './liste_albums_prives';
|
||||||
|
$currentPath = realpath($currentPath);
|
||||||
|
|
||||||
|
// Vérification de sécurité
|
||||||
|
if (!isSecurePrivatePath($currentPath)) {
|
||||||
|
header('Location: arbre-prive.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gérer l'upload des images
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
|
if (isset($_POST['action'])) {
|
||||||
|
switch ($_POST['action']) {
|
||||||
|
case 'upload':
|
||||||
|
$uploadedFiles = $_FILES['images'] ?? [];
|
||||||
|
$successCount = 0;
|
||||||
|
$errors = [];
|
||||||
|
|
||||||
|
// Gérer les uploads multiples
|
||||||
|
for ($i = 0; $i < count($uploadedFiles['name']); $i++) {
|
||||||
|
if ($uploadedFiles['error'][$i] === UPLOAD_ERR_OK) {
|
||||||
|
$tmpName = $uploadedFiles['tmp_name'][$i];
|
||||||
|
$fileName = sanitizeFilename($uploadedFiles['name'][$i]);
|
||||||
|
$extension = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
|
||||||
|
|
||||||
|
// Vérifier l'extension
|
||||||
|
if (in_array($extension, ALLOWED_EXTENSIONS)) {
|
||||||
|
$destination = $currentPath . '/' . $fileName;
|
||||||
|
|
||||||
|
// Vérifier si le fichier existe déjà
|
||||||
|
if (file_exists($destination)) {
|
||||||
|
$baseName = pathinfo($fileName, PATHINFO_FILENAME);
|
||||||
|
$counter = 1;
|
||||||
|
while (file_exists($destination)) {
|
||||||
|
$fileName = $baseName . '_' . $counter . '.' . $extension;
|
||||||
|
$destination = $currentPath . '/' . $fileName;
|
||||||
|
$counter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (move_uploaded_file($tmpName, $destination)) {
|
||||||
|
$successCount++;
|
||||||
|
} else {
|
||||||
|
$errors[] = "Erreur lors du déplacement de $fileName";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$errors[] = "Extension non autorisée pour $fileName";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($successCount > 0) {
|
||||||
|
$_SESSION['success_message'] = "$successCount image(s) téléversée(s) avec succès.";
|
||||||
|
}
|
||||||
|
if (!empty($errors)) {
|
||||||
|
$_SESSION['error_message'] = implode("\n", $errors);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'toggle_top':
|
||||||
|
$image = $_POST['image'] ?? '';
|
||||||
|
if ($image) {
|
||||||
|
$imagePath = $currentPath . '/' . basename($image);
|
||||||
|
if (isSecurePrivatePath($imagePath) && file_exists($imagePath)) {
|
||||||
|
$info = pathinfo($imagePath);
|
||||||
|
$isTop = strpos($info['filename'], '--top--') !== false;
|
||||||
|
|
||||||
|
if ($isTop) {
|
||||||
|
// Enlever le tag top
|
||||||
|
$newName = str_replace('--top--', '', $info['filename']) . '.' . $info['extension'];
|
||||||
|
} else {
|
||||||
|
// Ajouter le tag top
|
||||||
|
$newName = $info['filename'] . '--top--.' . $info['extension'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$newPath = $currentPath . '/' . $newName;
|
||||||
|
if (rename($imagePath, $newPath)) {
|
||||||
|
$_SESSION['success_message'] = $isTop ? "Image retirée des tops." : "Image mise en top.";
|
||||||
|
} else {
|
||||||
|
$_SESSION['error_message'] = "Erreur lors de la modification du statut top.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'delete':
|
||||||
|
$images = $_POST['images'] ?? [];
|
||||||
|
$deleteCount = 0;
|
||||||
|
|
||||||
|
foreach ($images as $image) {
|
||||||
|
$imagePath = $currentPath . '/' . basename($image);
|
||||||
|
if (isSecurePrivatePath($imagePath) && file_exists($imagePath)) {
|
||||||
|
if (unlink($imagePath)) {
|
||||||
|
$deleteCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($deleteCount > 0) {
|
||||||
|
$_SESSION['success_message'] = "$deleteCount image(s) supprimée(s).";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
header('Location: arbre-img-prive.php?path=' . urlencode($currentPath));
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Récupérer les images du dossier courant
|
||||||
|
$images = [];
|
||||||
|
$tempImages = [];
|
||||||
|
foreach (new DirectoryIterator($currentPath) as $file) {
|
||||||
|
if ($file->isDot()) continue;
|
||||||
|
if ($file->isFile()) {
|
||||||
|
$extension = strtolower($file->getExtension());
|
||||||
|
if (in_array($extension, ALLOWED_EXTENSIONS)) {
|
||||||
|
$tempImages[] = [
|
||||||
|
'name' => $file->getFilename(),
|
||||||
|
'time' => $file->getCTime()
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trier par date de création décroissante
|
||||||
|
usort($tempImages, function($a, $b) {
|
||||||
|
return $b['time'] - $a['time'];
|
||||||
|
});
|
||||||
|
|
||||||
|
// Extraire uniquement les noms de fichiers
|
||||||
|
$images = array_map(function($img) {
|
||||||
|
return $img['name'];
|
||||||
|
}, $tempImages);
|
||||||
|
|
||||||
|
$currentAlbumInfo = getAlbumInfo($currentPath);
|
||||||
|
?>
|
||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fr">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Gestion des images privées - ICO</title>
|
||||||
|
<link rel="icon" type="image/png" href="favicon.png">
|
||||||
|
<link rel="stylesheet" href="styles.css">
|
||||||
|
<link rel="stylesheet" href="styles-admin.css">
|
||||||
|
</head>
|
||||||
|
<body class="admin-page">
|
||||||
|
<div class="admin-header">
|
||||||
|
<h1>
|
||||||
|
Images de : <?php echo htmlspecialchars($currentAlbumInfo['title']); ?>
|
||||||
|
<span class="private-badge">Privé</span>
|
||||||
|
</h1>
|
||||||
|
<div class="admin-actions">
|
||||||
|
<button onclick="document.getElementById('imageUploadForm').click()" class="action-button action-button-success">
|
||||||
|
Ajouter des images
|
||||||
|
</button>
|
||||||
|
<button onclick="deleteSelected()" id="deleteSelectedBtn" class="action-button action-button-danger">
|
||||||
|
Supprimer la sélection
|
||||||
|
</button>
|
||||||
|
<a href="arbre-prive.php?path=<?php echo urlencode($currentPath); ?>" class="action-button action-button-secondary">
|
||||||
|
Retour
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="admin-content">
|
||||||
|
<?php if (isset($_SESSION['success_message'])): ?>
|
||||||
|
<div class="message success-message"><?php echo nl2br(htmlspecialchars($_SESSION['success_message'])); ?></div>
|
||||||
|
<?php unset($_SESSION['success_message']); ?>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<?php if (isset($_SESSION['error_message'])): ?>
|
||||||
|
<div class="message error-message"><?php echo nl2br(htmlspecialchars($_SESSION['error_message'])); ?></div>
|
||||||
|
<?php unset($_SESSION['error_message']); ?>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<div class="upload-zone" id="dropZone">
|
||||||
|
<p>Glissez-déposez vos images ici ou cliquez sur "Ajouter des images"</p>
|
||||||
|
<form method="post" enctype="multipart/form-data" id="uploadForm">
|
||||||
|
<input type="hidden" name="action" value="upload">
|
||||||
|
<input type="file" name="images[]" id="imageUploadForm" multiple accept=".jpg,.jpeg,.png,.gif">
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form method="post" id="imagesForm">
|
||||||
|
<input type="hidden" name="action" id="formAction" value="">
|
||||||
|
<div class="images-grid">
|
||||||
|
<?php foreach($images as $image):
|
||||||
|
$imagePath = str_replace('\\', '/', substr($currentPath, strpos($currentPath, '/liste_albums_prives/') + strlen('/liste_albums_prives/')));
|
||||||
|
$imageUrl = getBaseUrl() . '/liste_albums_prives/' . ($imagePath ? $imagePath . '/' : '') . $image;
|
||||||
|
?>
|
||||||
|
<div class="image-item">
|
||||||
|
<input type="checkbox" name="images[]" value="<?php echo htmlspecialchars($image); ?>"
|
||||||
|
class="image-checkbox" onchange="updateActionButtons()">
|
||||||
|
<div class="image-wrapper">
|
||||||
|
<img src="<?php echo htmlspecialchars($imageUrl); ?>"
|
||||||
|
alt="<?php echo htmlspecialchars($image); ?>" loading="lazy">
|
||||||
|
<div class="image-actions">
|
||||||
|
<?php
|
||||||
|
$isTop = strpos($image, '--top--') !== false;
|
||||||
|
?>
|
||||||
|
<button type="button" onclick="toggleTop('<?php echo htmlspecialchars($image); ?>')"
|
||||||
|
class="tree-button <?php echo $isTop ? 'tree-button-top' : ''; ?>"
|
||||||
|
title="<?php echo $isTop ? 'Retirer des tops' : 'Mettre en top'; ?>">
|
||||||
|
⭐
|
||||||
|
</button>
|
||||||
|
<button type="button" onclick="deleteImage('<?php echo htmlspecialchars($image); ?>')"
|
||||||
|
class="tree-button tree-button-danger">🗑️</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function updateActionButtons() {
|
||||||
|
const checkboxes = document.querySelectorAll('.image-checkbox:checked');
|
||||||
|
const count = checkboxes.length;
|
||||||
|
const deleteBtn = document.getElementById('deleteSelectedBtn');
|
||||||
|
|
||||||
|
if (count > 0) {
|
||||||
|
deleteBtn.style.display = 'inline-flex';
|
||||||
|
} else {
|
||||||
|
deleteBtn.style.display = 'none';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteImage(imageName) {
|
||||||
|
if (confirm('Êtes-vous sûr de vouloir supprimer cette image ?')) {
|
||||||
|
const form = document.getElementById('imagesForm');
|
||||||
|
form.innerHTML = `
|
||||||
|
<input type="hidden" name="action" value="delete">
|
||||||
|
<input type="hidden" name="images[]" value="${imageName}">
|
||||||
|
`;
|
||||||
|
form.submit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteSelected() {
|
||||||
|
const checkboxes = document.querySelectorAll('.image-checkbox:checked');
|
||||||
|
if (checkboxes.length > 0 && confirm('Êtes-vous sûr de vouloir supprimer les images sélectionnées ?')) {
|
||||||
|
document.getElementById('formAction').value = 'delete';
|
||||||
|
document.getElementById('imagesForm').submit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleTop(imageName) {
|
||||||
|
const form = document.createElement('form');
|
||||||
|
form.method = 'post';
|
||||||
|
form.innerHTML = `
|
||||||
|
<input type="hidden" name="action" value="toggle_top">
|
||||||
|
<input type="hidden" name="image" value="${imageName}">
|
||||||
|
`;
|
||||||
|
document.body.appendChild(form);
|
||||||
|
form.submit();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gestion du drag & drop
|
||||||
|
const dropZone = document.getElementById('dropZone');
|
||||||
|
const uploadForm = document.getElementById('uploadForm');
|
||||||
|
const imageUploadForm = document.getElementById('imageUploadForm');
|
||||||
|
|
||||||
|
dropZone.addEventListener('dragover', (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
dropZone.classList.add('drag-over');
|
||||||
|
});
|
||||||
|
|
||||||
|
dropZone.addEventListener('dragleave', () => {
|
||||||
|
dropZone.classList.remove('drag-over');
|
||||||
|
});
|
||||||
|
|
||||||
|
dropZone.addEventListener('drop', (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
dropZone.classList.remove('drag-over');
|
||||||
|
|
||||||
|
const files = e.dataTransfer.files;
|
||||||
|
if (files.length > 0) {
|
||||||
|
const dataTransfer = new DataTransfer();
|
||||||
|
for (let file of files) {
|
||||||
|
dataTransfer.items.add(file);
|
||||||
|
}
|
||||||
|
imageUploadForm.files = dataTransfer.files;
|
||||||
|
uploadForm.submit();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Initialisation : masquer les boutons au chargement
|
||||||
|
document.addEventListener('DOMContentLoaded', updateActionButtons);
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
327
arbre-prive.php
Normal file
327
arbre-prive.php
Normal file
@ -0,0 +1,327 @@
|
|||||||
|
<?php
|
||||||
|
require_once 'fonctions.php';
|
||||||
|
|
||||||
|
session_start();
|
||||||
|
if (!isset($_SESSION['admin_id'])) {
|
||||||
|
header('Location: admin.php?action=login');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
|
$action = $_POST['action'] ?? '';
|
||||||
|
$path = $_POST['path'] ?? '';
|
||||||
|
$newName = $_POST['new_name'] ?? '';
|
||||||
|
$description = $_POST['description'] ?? '';
|
||||||
|
$matureContent = isset($_POST['mature_content']) ? '18+' : '18-';
|
||||||
|
|
||||||
|
switch ($action) {
|
||||||
|
case 'create_folder':
|
||||||
|
if ($path && $newName) {
|
||||||
|
$newPath = $path . '/' . sanitizeFilename($newName);
|
||||||
|
if (!file_exists($newPath)) {
|
||||||
|
$moreInfoUrl = $_POST['more_info_url'] ?? '';
|
||||||
|
mkdir($newPath, 0755, true);
|
||||||
|
$infoContent = $newName . "\n" . $description . "\n" . $matureContent . "\n" . $moreInfoUrl;
|
||||||
|
file_put_contents($newPath . '/infos.txt', $infoContent);
|
||||||
|
$_SESSION['success_message'] = "Dossier privé créé avec succès.";
|
||||||
|
} else {
|
||||||
|
$_SESSION['error_message'] = "Ce dossier existe déjà.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'edit_folder':
|
||||||
|
if ($path && isSecurePrivatePath($path)) {
|
||||||
|
$moreInfoUrl = $_POST['more_info_url'] ?? '';
|
||||||
|
$infoContent = $newName . "\n" . $description . "\n" . $matureContent . "\n" . $moreInfoUrl;
|
||||||
|
$infoPath = $path . '/infos.txt';
|
||||||
|
if (file_put_contents($infoPath, $infoContent) !== false) {
|
||||||
|
$_SESSION['success_message'] = "Dossier modifié avec succès.";
|
||||||
|
} else {
|
||||||
|
$_SESSION['error_message'] = "Erreur lors de la modification du dossier.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'delete_folder':
|
||||||
|
if ($path && isSecurePrivatePath($path) && $path !== './liste_albums_prives') {
|
||||||
|
function rrmdir($dir) {
|
||||||
|
if (is_dir($dir)) {
|
||||||
|
$objects = scandir($dir);
|
||||||
|
foreach ($objects as $object) {
|
||||||
|
if ($object != "." && $object != "..") {
|
||||||
|
if (is_dir($dir . "/" . $object)) {
|
||||||
|
rrmdir($dir . "/" . $object);
|
||||||
|
} else {
|
||||||
|
unlink($dir . "/" . $object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rmdir($dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rrmdir($path);
|
||||||
|
$_SESSION['success_message'] = "Dossier privé supprimé avec succès.";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
header('Location: arbre-prive.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$currentPath = isset($_GET['path']) ? $_GET['path'] : './liste_albums_prives';
|
||||||
|
$currentPath = realpath($currentPath);
|
||||||
|
|
||||||
|
if (!isSecurePrivatePath($currentPath)) {
|
||||||
|
header('Location: arbre-prive.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Créer le dossier racine s'il n'existe pas
|
||||||
|
if (!file_exists('./liste_albums_prives')) {
|
||||||
|
mkdir('./liste_albums_prives', 0755, true);
|
||||||
|
// Créer le fichier infos.txt pour le dossier racine
|
||||||
|
$infoContent = "Albums privés\nVos albums photos privés\n18-\n";
|
||||||
|
file_put_contents('./liste_albums_prives/infos.txt', $infoContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
function generatePrivateTree($path, $currentPath) {
|
||||||
|
if (!is_dir($path)) return '';
|
||||||
|
|
||||||
|
$output = '<ul class="tree-list">';
|
||||||
|
|
||||||
|
// Si c'est le dossier racine, ajoutons-le à l'arborescence
|
||||||
|
if ($path === './liste_albums_prives') {
|
||||||
|
$info = getAlbumInfo($path);
|
||||||
|
$output .= '<li class="tree-item root-folder' . ($path === $currentPath ? ' active' : '') . '">';
|
||||||
|
$output .= '<div class="tree-item-content">';
|
||||||
|
$output .= '<span class="tree-link">';
|
||||||
|
$output .= '<span class="folder-icon">🔒</span> ' . htmlspecialchars($info['title']);
|
||||||
|
if ($info['mature_content']) {
|
||||||
|
$output .= ' <span class="mature-warning">🔞</span>';
|
||||||
|
}
|
||||||
|
$output .= '</span>';
|
||||||
|
$output .= '<div class="tree-actions">';
|
||||||
|
$output .= '<button onclick="editFolder(\'' . htmlspecialchars($path) . '\', \'' . rawurlencode($info['title']) . '\', \'' . rawurlencode($info['description']) . '\', ' . ($info['mature_content'] ? 'true' : 'false') . ', \'' . rawurlencode($info['more_info_url']) . '\', ' . (hasImages($path) ? 'true' : 'false') . ')" class="tree-button">✏️</button>';
|
||||||
|
$output .= '<button onclick="createSubfolder(\'' . htmlspecialchars($path) . '\')" class="tree-button">➕</button>';
|
||||||
|
$output .= '</div></div>';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parcourir tous les sous-dossiers
|
||||||
|
foreach (new DirectoryIterator($path) as $item) {
|
||||||
|
if ($item->isDot()) continue;
|
||||||
|
if ($item->isDir()) {
|
||||||
|
$fullPath = $item->getPathname();
|
||||||
|
$info = getAlbumInfo($fullPath);
|
||||||
|
$isCurrentPath = realpath($fullPath) === $currentPath;
|
||||||
|
$hasSubfolders = hasSubfolders($fullPath);
|
||||||
|
|
||||||
|
$output .= '<li class="tree-item' . ($isCurrentPath ? ' active' : '') . '">';
|
||||||
|
$output .= '<div class="tree-item-content">';
|
||||||
|
$output .= '<span class="tree-link">';
|
||||||
|
$output .= '<span class="folder-icon">🔒</span> ' . htmlspecialchars($info['title']);
|
||||||
|
if ($info['mature_content']) {
|
||||||
|
$output .= ' <span class="mature-warning">🔞</span>';
|
||||||
|
}
|
||||||
|
$output .= '</span>';
|
||||||
|
$output .= '<div class="tree-actions">';
|
||||||
|
if (!$hasSubfolders) {
|
||||||
|
$output .= '<a href="arbre-img-prive.php?path=' . urlencode($fullPath) . '&private=1" class="tree-button" style="text-decoration: none">🖼️</a>';
|
||||||
|
}
|
||||||
|
if (!$hasSubfolders) {
|
||||||
|
$output .= '<button onclick="editFolder(\'' . htmlspecialchars($fullPath) . '\', \''
|
||||||
|
. rawurlencode($info['title']) . '\', \''
|
||||||
|
. rawurlencode($info['description']) . '\', '
|
||||||
|
. ($info['mature_content'] ? 'true' : 'false') . ', \''
|
||||||
|
. rawurlencode($info['more_info_url']) . '\', '
|
||||||
|
. (hasImages($fullPath) ? 'true' : 'false')
|
||||||
|
. ')" class="tree-button">✏️</button>';
|
||||||
|
} else {
|
||||||
|
$output .= '<button onclick="editFolder(\'' . htmlspecialchars($fullPath) . '\', \''
|
||||||
|
. rawurlencode($info['title']) . '\', \''
|
||||||
|
. rawurlencode($info['description']) . '\', '
|
||||||
|
. ($info['mature_content'] ? 'true' : 'false') . ', \'\', false)" class="tree-button">✏️</button>';
|
||||||
|
}
|
||||||
|
if (!hasImages($fullPath)) {
|
||||||
|
$output .= '<button onclick="createSubfolder(\'' . htmlspecialchars($fullPath) . '\')" class="tree-button">➕</button>';
|
||||||
|
}
|
||||||
|
if ($fullPath !== './liste_albums_prives') {
|
||||||
|
$output .= '<button onclick="deleteFolder(\'' . htmlspecialchars($fullPath) . '\')" class="tree-button tree-button-danger">🗑️</button>';
|
||||||
|
}
|
||||||
|
$output .= '</div></div>';
|
||||||
|
|
||||||
|
$output .= generatePrivateTree($fullPath, $currentPath);
|
||||||
|
$output .= '</li>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$output .= '</ul>';
|
||||||
|
return $output;
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fr">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Albums privés - ICO</title>
|
||||||
|
<link rel="icon" type="image/png" href="favicon.png">
|
||||||
|
<link rel="stylesheet" href="styles.css">
|
||||||
|
<link rel="stylesheet" href="styles-admin.css">
|
||||||
|
</head>
|
||||||
|
<body class="admin-page">
|
||||||
|
<div class="admin-header">
|
||||||
|
<h1>Gestion des albums privés</h1>
|
||||||
|
<div class="admin-actions">
|
||||||
|
<button onclick="createSubfolder('./liste_albums_prives')" class="action-button">Nouveau dossier privé</button>
|
||||||
|
<a href="admin.php" class="action-button action-button-secondary">Retour</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="admin-content">
|
||||||
|
<?php if (isset($_SESSION['success_message'])): ?>
|
||||||
|
<div class="message success-message"><?php echo htmlspecialchars($_SESSION['success_message']); ?></div>
|
||||||
|
<?php unset($_SESSION['success_message']); ?>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<?php if (isset($_SESSION['error_message'])): ?>
|
||||||
|
<div class="message error-message"><?php echo htmlspecialchars($_SESSION['error_message']); ?></div>
|
||||||
|
<?php unset($_SESSION['error_message']); ?>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<div class="tree-container">
|
||||||
|
<?php echo generatePrivateTree('./liste_albums_prives', $currentPath); ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Modal de création de dossier -->
|
||||||
|
<div id="createFolderModal" class="modal">
|
||||||
|
<div class="modal-content">
|
||||||
|
<h2>Créer un nouveau dossier privé</h2>
|
||||||
|
<form method="post" action="arbre-prive.php">
|
||||||
|
<input type="hidden" name="action" value="create_folder">
|
||||||
|
<input type="hidden" name="path" id="parentPath">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="new_name">Nom du dossier :</label>
|
||||||
|
<input type="text" id="new_name" name="new_name" required>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="description">Description :</label>
|
||||||
|
<textarea id="description" name="description" rows="4" class="form-textarea"></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="toggle-label">
|
||||||
|
<input type="checkbox" name="mature_content" id="mature_content">
|
||||||
|
<span class="toggle-text">Contenu réservé aux plus de 18 ans</span>
|
||||||
|
<span class="toggle-warning">⚠️</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-group" id="create_more_info_url_field" style="display: none;">
|
||||||
|
<label for="more_info_url">Lien "En savoir plus" (optionnel) :</label>
|
||||||
|
<input type="url" id="more_info_url" name="more_info_url" placeholder="https://...">
|
||||||
|
</div>
|
||||||
|
<div class="form-actions">
|
||||||
|
<button type="button" onclick="closeModal()" class="action-button action-button-secondary">Annuler</button>
|
||||||
|
<button type="submit" class="action-button">Créer</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Modal d'édition de dossier -->
|
||||||
|
<div id="editFolderModal" class="modal">
|
||||||
|
<div class="modal-content">
|
||||||
|
<h2>Modifier le dossier privé</h2>
|
||||||
|
<form method="post" action="arbre-prive.php">
|
||||||
|
<input type="hidden" name="action" value="edit_folder">
|
||||||
|
<input type="hidden" name="path" id="editPath">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="edit_name">Nom du dossier :</label>
|
||||||
|
<input type="text" id="edit_name" name="new_name" required>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="edit_description">Description :</label>
|
||||||
|
<textarea id="edit_description" name="description" rows="4" class="form-textarea"></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="toggle-label">
|
||||||
|
<input type="checkbox" name="mature_content" id="edit_mature_content">
|
||||||
|
<span class="toggle-text">Contenu réservé aux plus de 18 ans</span>
|
||||||
|
<span class="toggle-warning">⚠️</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-group" id="edit_more_info_url_field">
|
||||||
|
<label for="edit_more_info_url">Lien "En savoir plus" (optionnel) :</label>
|
||||||
|
<input type="url" id="edit_more_info_url" name="more_info_url" placeholder="https://...">
|
||||||
|
</div>
|
||||||
|
<div class="form-actions">
|
||||||
|
<button type="button" onclick="closeModal()" class="action-button action-button-secondary">Annuler</button>
|
||||||
|
<button type="submit" class="action-button">Enregistrer</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Modal de confirmation de suppression -->
|
||||||
|
<div id="deleteFolderModal" class="modal">
|
||||||
|
<div class="modal-content">
|
||||||
|
<h2>Confirmer la suppression</h2>
|
||||||
|
<p>Êtes-vous sûr de vouloir supprimer ce dossier privé et tout son contenu ?</p>
|
||||||
|
<form method="post" action="arbre-prive.php">
|
||||||
|
<input type="hidden" name="action" value="delete_folder">
|
||||||
|
<input type="hidden" name="path" id="deletePath">
|
||||||
|
<div class="form-actions">
|
||||||
|
<button type="button" onclick="closeModal()" class="action-button action-button-secondary">Annuler</button>
|
||||||
|
<button type="submit" class="action-button action-button-danger">Supprimer</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function createSubfolder(path) {
|
||||||
|
document.getElementById('parentPath').value = path;
|
||||||
|
document.getElementById('create_more_info_url_field').style.display = 'none';
|
||||||
|
document.getElementById('createFolderModal').style.display = 'block';
|
||||||
|
}
|
||||||
|
|
||||||
|
function editFolder(path, title, description, matureContent = false, moreInfoUrl = '', hasImages = false) {
|
||||||
|
document.getElementById('editPath').value = path;
|
||||||
|
document.getElementById('edit_name').value = decodeURIComponent(title);
|
||||||
|
document.getElementById('edit_description').value = decodeURIComponent(description);
|
||||||
|
document.getElementById('edit_mature_content').checked = matureContent;
|
||||||
|
document.getElementById('edit_more_info_url').value = decodeURIComponent(moreInfoUrl);
|
||||||
|
|
||||||
|
const moreInfoUrlField = document.getElementById('edit_more_info_url_field');
|
||||||
|
const showUrlField = hasImages === true || hasImages === 'true';
|
||||||
|
|
||||||
|
if (moreInfoUrlField) {
|
||||||
|
moreInfoUrlField.style.display = showUrlField ? 'block' : 'none';
|
||||||
|
if (!showUrlField) {
|
||||||
|
document.getElementById('edit_more_info_url').value = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById('editFolderModal').style.display = 'block';
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteFolder(path) {
|
||||||
|
document.getElementById('deletePath').value = path;
|
||||||
|
document.getElementById('deleteFolderModal').style.display = 'block';
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeModal() {
|
||||||
|
document.getElementById('createFolderModal').style.display = 'none';
|
||||||
|
document.getElementById('editFolderModal').style.display = 'none';
|
||||||
|
document.getElementById('deleteFolderModal').style.display = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
window.onclick = function(event) {
|
||||||
|
if (event.target.classList.contains('modal')) {
|
||||||
|
closeModal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -12,6 +12,18 @@ function getBaseUrl() {
|
|||||||
return $protocol . $_SERVER['HTTP_HOST'] . '/' . PROJECT_ROOT_DIR;
|
return $protocol . $_SERVER['HTTP_HOST'] . '/' . PROJECT_ROOT_DIR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vérifie si le chemin est sécurisé (dans le dossier liste_albums_prives)
|
||||||
|
* @param string $path Chemin à vérifier
|
||||||
|
* @return bool True si le chemin est sécurisé
|
||||||
|
*/
|
||||||
|
function isSecurePrivatePath($path) {
|
||||||
|
$realPath = realpath($path);
|
||||||
|
$privateRootPath = realpath('./liste_albums_prives');
|
||||||
|
|
||||||
|
return $realPath && (strpos($realPath, $privateRootPath) === 0);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Récupère les informations d'un album depuis son fichier infos.txt
|
* Récupère les informations d'un album depuis son fichier infos.txt
|
||||||
* @param string $albumPath Chemin vers l'album
|
* @param string $albumPath Chemin vers l'album
|
||||||
|
@ -57,6 +57,25 @@ body {
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Badge pour les contenus privés */
|
||||||
|
.private-badge {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
background-color: #6c757d;
|
||||||
|
color: white;
|
||||||
|
padding: 0.25rem 0.75rem;
|
||||||
|
border-radius: 1rem;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
margin-left: 1rem;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.private-badge::before {
|
||||||
|
content: "🔒";
|
||||||
|
font-size: 1.1em;
|
||||||
|
}
|
||||||
|
|
||||||
/* Zone de contenu principale */
|
/* Zone de contenu principale */
|
||||||
.admin-content {
|
.admin-content {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user