Compare commits

...

5 Commits
1.1.0 ... main

10 changed files with 133 additions and 20 deletions

View File

@ -37,4 +37,10 @@ Options -Indexes
Header set X-Content-Type-Options "nosniff" Header set X-Content-Type-Options "nosniff"
Header set X-Frame-Options "SAMEORIGIN" Header set X-Frame-Options "SAMEORIGIN"
Header set X-XSS-Protection "1; mode=block" Header set X-XSS-Protection "1; mode=block"
</IfModule>
# Bloquer l'accès direct aux images privées
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^liste_albums_prives/.+\.(jpg|jpeg|png|gif)$ - [F]
</IfModule> </IfModule>

View File

@ -92,7 +92,14 @@ $config = getSiteConfig();
<div class="empty-album"></div> <div class="empty-album"></div>
<?php else: ?> <?php else: ?>
<?php foreach ($album['images'] as $index => $image): ?> <?php foreach ($album['images'] as $index => $image): ?>
<div class="album-image" style="background-image: url('<?php echo htmlspecialchars($image); ?>')"></div> <div class="album-image">
<div class="image-background <?php echo is_array($image) && $image['is_mature'] ? 'mature-preview' : ''; ?>"
style="background-image: url('<?php echo htmlspecialchars(is_array($image) ? $image['url'] : $image); ?>')">
</div>
<?php if (is_array($image) && $image['is_mature']): ?>
<div class="mature-preview-indicator">🔞</div>
<?php endif; ?>
</div>
<?php endforeach; ?> <?php endforeach; ?>
<?php for ($i = count($album['images']); $i < 4; $i++): ?> <?php for ($i = count($album['images']); $i < 4; $i++): ?>
<div class="empty-image"></div> <div class="empty-image"></div>

View File

@ -228,7 +228,10 @@ $config = getSiteConfig();
<div class="images-grid"> <div class="images-grid">
<?php foreach($images as $image): <?php foreach($images as $image):
$imagePath = str_replace('\\', '/', substr($currentPath, strpos($currentPath, '/liste_albums_prives/') + strlen('/liste_albums_prives/'))); $imagePath = str_replace('\\', '/', substr($currentPath, strpos($currentPath, '/liste_albums_prives/') + strlen('/liste_albums_prives/')));
$imageUrl = getBaseUrl() . '/liste_albums_prives/' . ($imagePath ? $imagePath . '/' : '') . $image; $imageUrl = getBaseUrl() . '/images.php?path=' . urlencode($currentPath . '/' . $image);
if (isset($_SESSION['admin_id'])) {
$imageUrl .= '&admin_session=' . session_id();
}
?> ?>
<div class="image-item"> <div class="image-item">
<input type="checkbox" name="images[]" value="<?php echo htmlspecialchars($image); ?>" <input type="checkbox" name="images[]" value="<?php echo htmlspecialchars($image); ?>"

View File

@ -133,7 +133,7 @@ $config = getSiteConfig();
<div class="filters"> <div class="filters">
<div class="filter-group"> <div class="filter-group">
<label for="status-filter">Statut :</label> <label for="status-filter">Statut&nbsp;:</label>
<select id="status-filter" class="form-select" onchange="updateFilters()"> <select id="status-filter" class="form-select" onchange="updateFilters()">
<option value="active" <?php echo $filter === 'active' ? 'selected' : ''; ?>>Clés actives</option> <option value="active" <?php echo $filter === 'active' ? 'selected' : ''; ?>>Clés actives</option>
<option value="expired" <?php echo $filter === 'expired' ? 'selected' : ''; ?>>Clés expirées</option> <option value="expired" <?php echo $filter === 'expired' ? 'selected' : ''; ?>>Clés expirées</option>
@ -142,7 +142,7 @@ $config = getSiteConfig();
</div> </div>
<div class="filter-group"> <div class="filter-group">
<label for="album-filter">Album :</label> <label for="album-filter">Album&nbsp;:</label>
<select id="album-filter" class="form-select" onchange="updateFilters()"> <select id="album-filter" class="form-select" onchange="updateFilters()">
<option value="">Tous les albums</option> <option value="">Tous les albums</option>
<?php foreach ($albums as $album): ?> <?php foreach ($albums as $album): ?>

View File

@ -139,15 +139,22 @@ function getImagesRecursively($albumPath, $limit = 4) {
if ($file->isFile()) { if ($file->isFile()) {
$extension = strtolower($file->getExtension()); $extension = strtolower($file->getExtension());
if (in_array($extension, ALLOWED_EXTENSIONS)) { if (in_array($extension, ALLOWED_EXTENSIONS)) {
// Récupérer les infos du dossier parent de l'image
$parentDir = dirname($file->getPathname());
$parentInfo = getAlbumInfo($parentDir);
$relativePath = str_replace('\\', '/', substr($file->getPathname(), strlen(realpath('./')))); $relativePath = str_replace('\\', '/', substr($file->getPathname(), strlen(realpath('./'))));
$images[] = $baseUrl . '/' . ltrim($relativePath, '/'); $images[] = [
'url' => $baseUrl . '/' . ltrim($relativePath, '/'),
'is_mature' => $parentInfo['mature_content']
];
} }
} }
} }
usort($images, function($a, $b) { usort($images, function($a, $b) {
$pathA = realpath('.') . str_replace(getBaseUrl(), '', $a); $pathA = realpath('.') . str_replace(getBaseUrl(), '', $a['url']);
$pathB = realpath('.') . str_replace(getBaseUrl(), '', $b); $pathB = realpath('.') . str_replace(getBaseUrl(), '', $b['url']);
return filectime($pathB) - filectime($pathA); return filectime($pathB) - filectime($pathA);
}); });

View File

@ -34,7 +34,7 @@ if (empty($shareKey)) {
if (in_array($extension, ALLOWED_EXTENSIONS)) { if (in_array($extension, ALLOWED_EXTENSIONS)) {
// Obtenir le chemin relatif depuis la racine du projet // Obtenir le chemin relatif depuis la racine du projet
$relativePath = str_replace('\\', '/', substr($file->getPathname(), strlen(realpath('./')))); $relativePath = str_replace('\\', '/', substr($file->getPathname(), strlen(realpath('./'))));
$url = $baseUrl . '/' . ltrim($relativePath, '/'); $url = $baseUrl . '/images.php?path=' . urlencode($file->getPathname()) . '&key=' . urlencode($shareKey);
// Vérifier que le fichier existe et est accessible // Vérifier que le fichier existe et est accessible
if (file_exists($file->getPathname())) { if (file_exists($file->getPathname())) {
$images[] = $url; $images[] = $url;
@ -148,7 +148,7 @@ $config = getSiteConfig();
} }
?> ?>
<div class="gallery-item <?php echo $isTop ? 'gallery-item-top' : ''; ?> <?php echo $spanClass; ?>"> <div class="gallery-item <?php echo $isTop ? 'gallery-item-top' : ''; ?> <?php echo $spanClass; ?>">
<a href="partage.php?image=<?php echo urlencode($image); ?>" target="_blank"> <a href="partage.php?image=<?php echo urlencode($image); ?>&key=<?php echo urlencode($shareKey); ?>" target="_blank">
<img src="<?php echo htmlspecialchars($image); ?>" <img src="<?php echo htmlspecialchars($image); ?>"
alt="Image de la galerie" alt="Image de la galerie"
loading="lazy"> loading="lazy">

34
images.php Normal file
View File

@ -0,0 +1,34 @@
<?php
// images.php
require_once 'fonctions.php';
session_start();
$path = $_GET['path'] ?? '';
$key = $_GET['key'] ?? '';
$adminSession = $_GET['admin_session'] ?? '';
// Vérifier que le chemin est valide et dans un album privé
if (!isSecurePrivatePath($path) || !file_exists($path)) {
header("HTTP/1.0 404 Not Found");
exit;
}
// Vérifier l'authentification (admin ou clé de partage valide)
if ($adminSession) {
session_id($adminSession);
session_start();
if (!isset($_SESSION['admin_id'])) {
header("HTTP/1.0 403 Forbidden");
exit;
}
} else {
if (!$key || !validateShareKey($key)) {
header("HTTP/1.0 403 Forbidden");
exit;
}
}
// Servir l'image avec le bon Content-Type
$mime = mime_content_type($path);
header("Content-Type: $mime");
readfile($path);

View File

@ -3,12 +3,36 @@ require_once 'fonctions.php';
// Vérifier que nous avons une URL d'image // Vérifier que nous avons une URL d'image
$imageUrl = isset($_GET['image']) ? $_GET['image'] : null; $imageUrl = isset($_GET['image']) ? $_GET['image'] : null;
$imagePath = realpath('.') . str_replace(getBaseUrl(), '', $imageUrl);
if (!$imageUrl || !file_exists($imagePath)) { if (!$imageUrl) {
header('Location: index.php'); header('Location: index.php');
exit; exit;
} }
// Si c'est une image privée
if (strpos($imageUrl, 'images.php') !== false) {
// On récupère les paramètres de l'URL de l'image
parse_str(parse_url($imageUrl, PHP_URL_QUERY), $params);
$path = $params['path'] ?? '';
$key = $params['key'] ?? '';
if (strpos($path, 'liste_albums_prives') !== false) {
$isPrivateImage = true;
if (!isset($_SESSION['admin_id'])) {
if (!$key || !validateShareKey($key)) {
header('Location: index.php');
exit;
}
} elseif (isset($_SESSION['admin_id'])) {
// Pour les admins, on remplace la clé par la session admin
$imageUrl = preg_replace('/&key=[^&]*/', '', $imageUrl) . '&admin_session=' . session_id();
}
}
}
// Récupérer le nom du fichier pour le téléchargement
$filename = basename(parse_url($imageUrl, PHP_URL_PATH));
// Si pas d'image, redirection // Si pas d'image, redirection
if (!$imageUrl) { if (!$imageUrl) {
header('Location: index.php'); header('Location: index.php');
@ -30,7 +54,7 @@ $config = getSiteConfig();
<link rel="stylesheet" href="styles.css"> <link rel="stylesheet" href="styles.css">
</head> </head>
<body class="share-page"> <body class="share-page">
<button onclick="var referrer = document.referrer; if (referrer.includes('galeries.php')) { window.close(); } else { window.location.href='index.php'; }" class="back-button">Retour</button> <button onclick="var referrer = document.referrer; if (referrer.includes('galeries.php') || referrer.includes('galeries-privees.php')) { window.close(); } else { window.location.href='index.php'; }" class="back-button">Retour</button>
<div class="share-container"> <div class="share-container">
<div class="share-image"> <div class="share-image">
@ -47,6 +71,7 @@ $config = getSiteConfig();
Partager Partager
</button> </button>
<?php if (!$isPrivateImage): ?>
<button class="action-button" onclick="embedImage()"> <button class="action-button" onclick="embedImage()">
<svg xmlns="http://www.w3.org/2000/svg" class="icon" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2"> <svg xmlns="http://www.w3.org/2000/svg" class="icon" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2">
<polyline points="16 18 22 12 16 6"></polyline> <polyline points="16 18 22 12 16 6"></polyline>
@ -54,6 +79,7 @@ $config = getSiteConfig();
</svg> </svg>
Intégrer Intégrer
</button> </button>
<?php endif; ?>
<a href="<?php echo htmlspecialchars($imageUrl); ?>" <a href="<?php echo htmlspecialchars($imageUrl); ?>"
download="<?php echo htmlspecialchars($filename); ?>" download="<?php echo htmlspecialchars($filename); ?>"

View File

@ -186,9 +186,12 @@ body {
} }
/* Styles pour le contenu mature dans les albums */ /* Styles pour le contenu mature dans les albums */
.album-card-mature {
position: relative;
}
.album-card-mature .album-images { .album-card-mature .album-images {
filter: blur(10px); filter: blur(10px);
transition: filter 0.3s ease;
} }
.album-card-mature::before { .album-card-mature::before {
@ -203,8 +206,12 @@ body {
border-radius: 0.5rem; border-radius: 0.5rem;
z-index: 2; z-index: 2;
white-space: nowrap; white-space: nowrap;
opacity: 1; transition: transform 0.3s ease, background-color 0.3s ease;
transition: opacity 0.3s ease; }
.album-card-mature:hover::before {
transform: translate(-50%, -50%) scale(1.1);
background-color: rgba(220, 53, 69, 1);
} }
.album-card-mature::after { .album-card-mature::after {
@ -216,12 +223,34 @@ body {
z-index: 2; z-index: 2;
} }
.album-card-mature:hover .album-images { .image-background {
filter: blur(0); position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
} }
.album-card-mature:hover::before { .image-background.mature-preview {
opacity: 0; filter: blur(10px);
}
.mature-preview-indicator {
position: absolute;
top: 5px;
right: 5px;
width: 24px;
height: 24px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
z-index: 10;
font-size: 14px;
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.8);
} }
.album-card { .album-card {
@ -257,6 +286,7 @@ body {
} }
.album-image { .album-image {
position: relative;
width: 100%; width: 100%;
height: 100%; height: 100%;
background-size: cover; background-size: cover;

View File

@ -1 +1 @@
1.1.0 1.1.2