Compare commits
6 Commits
Author | SHA1 | Date | |
---|---|---|---|
ae8476d404 | |||
acb80e4668 | |||
fd431a332a | |||
fd1ac715db | |||
3cacb4645f | |||
0018ac8554 |
@ -1,8 +1,4 @@
|
|||||||
# Cyla
|
# Cyla
|
||||||
Site d'hébergement de fichiers simple, réduit au strict nécessaire.
|
Site d'hébergement de fichiers simple, réduit au strict nécessaire.
|
||||||
|
|
||||||
|
|
||||||
Le projet se base sur la première version de [QuadFile](https://github.com/QuadPiece/QuadFile).
|
|
||||||
|
|
||||||
|
|
||||||
![image](https://concepts.esenjin.xyz/cyla/fichiers/6787d3fe886e4_1736954878.png)
|
![image](https://concepts.esenjin.xyz/cyla/fichiers/6787d3fe886e4_1736954878.png)
|
89
admin.php
89
admin.php
@ -289,56 +289,57 @@ $files = $fileData['files'];
|
|||||||
<div class="file-list">
|
<div class="file-list">
|
||||||
<?php foreach ($files as $file): ?>
|
<?php foreach ($files as $file): ?>
|
||||||
<div class="file-item">
|
<div class="file-item">
|
||||||
<div class="file-preview">
|
<div class="file-preview">
|
||||||
<?php if ($file['preview_type'] === 'image'): ?>
|
<?php if ($file['preview_type'] === 'image'): ?>
|
||||||
<img src="fichiers/<?php echo Cyla::escape($file['name']); ?>"
|
<img src="<?php echo $file['path'] . Cyla::escape($file['name']); ?>"
|
||||||
alt="<?php echo Cyla::escape($file['name']); ?>">
|
alt="<?php echo Cyla::escape($file['name']); ?>">
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
<div class="preview-placeholder">
|
<div class="preview-placeholder">
|
||||||
<?php echo strtoupper($file['extension']); ?>
|
<?php echo strtoupper($file['extension']); ?>
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="file-info">
|
|
||||||
<p class="file-name"><?php echo Cyla::escape($file['name']); ?></p>
|
|
||||||
<p class="file-meta">
|
|
||||||
<?php echo Cyla::escape(round($file['size'] / 1024, 2)); ?> Ko
|
|
||||||
· <?php echo date('d/m/Y H:i', $file['uploaded']); ?>
|
|
||||||
</p>
|
|
||||||
<div class="file-actions">
|
|
||||||
<a href="share.php?file=<?php echo urlencode($file['name']); ?>"
|
|
||||||
class="btn btn-secondary"
|
|
||||||
target="_blank">Voir</a>
|
|
||||||
<button class="btn"
|
|
||||||
onclick="copyShareLink('<?php echo SITE_URL; ?>share.php?file=<?php echo urlencode($file['name']); ?>')">
|
|
||||||
Copier le lien
|
|
||||||
</button>
|
|
||||||
<button class="btn btn-danger"
|
|
||||||
onclick="confirmDelete('<?php echo Cyla::escape($file['name']); ?>')">
|
|
||||||
×
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
<!-- Formulaire caché pour la suppression -->
|
|
||||||
<form id="deleteForm-<?php echo Cyla::escape($file['name']); ?>"
|
|
||||||
action="admin.php"
|
|
||||||
method="POST"
|
|
||||||
style="display: none;">
|
|
||||||
<input type="hidden" name="action" value="delete_file">
|
|
||||||
<input type="hidden" name="filename" value="<?php echo Cyla::escape($file['name']); ?>">
|
|
||||||
<input type="hidden" name="csrf_token" value="<?php echo Cyla::generateCSRFToken(); ?>">
|
|
||||||
</form>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="file-info">
|
||||||
|
<p class="file-name"><?php echo Cyla::escape($file['name']); ?></p>
|
||||||
|
<p class="file-meta">
|
||||||
|
<?php echo Cyla::escape(round($file['size'] / 1024, 2)); ?> Ko
|
||||||
|
· <?php echo date('d/m/Y H:i', $file['uploaded']); ?>
|
||||||
|
· <?php echo $file['path']; ?>
|
||||||
|
</p>
|
||||||
|
<div class="file-actions">
|
||||||
|
<a href="share.php?file=<?php echo urlencode($file['name']); ?>&path=<?php echo urlencode($file['path']); ?>"
|
||||||
|
class="btn btn-secondary"
|
||||||
|
target="_blank">Voir</a>
|
||||||
|
<button class="btn"
|
||||||
|
onclick="copyShareLink('<?php echo SITE_URL; ?>share.php?file=<?php echo urlencode($file['name']); ?>&path=<?php echo urlencode($file['path']); ?>')">
|
||||||
|
Copier le lien
|
||||||
|
</button>
|
||||||
|
<button class="btn btn-danger"
|
||||||
|
onclick="confirmDelete('<?php echo Cyla::escape($file['name']); ?>', '<?php echo Cyla::escape($file['path']); ?>')">
|
||||||
|
×
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Formulaire caché pour la suppression -->
|
||||||
|
<form id="deleteForm-<?php echo Cyla::escape($file['name']); ?>"
|
||||||
|
action="admin.php"
|
||||||
|
method="POST"
|
||||||
|
style="display: none;">
|
||||||
|
<input type="hidden" name="action" value="delete_file">
|
||||||
|
<input type="hidden" name="filename" value="<?php echo Cyla::escape($file['name']); ?>">
|
||||||
|
<input type="hidden" name="path" value="<?php echo Cyla::escape($file['path']); ?>">
|
||||||
|
<input type="hidden" name="csrf_token" value="<?php echo Cyla::generateCSRFToken(); ?>">
|
||||||
|
</form>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
|
||||||
<?php if ($fileData['totalPages'] > 1): ?>
|
<?php if ($fileData['totalPages'] > 1): ?>
|
||||||
<div class="pagination">
|
<div class="pagination">
|
||||||
<?php if ($fileData['currentPage'] > 1): ?>
|
<?php if ($fileData['currentPage'] > 1): ?>
|
||||||
<a href="?page=<?php echo $fileData['currentPage'] - 1; ?>"
|
<a href="?page=<?php echo $fileData['currentPage'] - 1; ?>"
|
||||||
class="pagination-link">« Précédent</a>
|
class="pagination-link">«</a>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
@ -365,7 +366,7 @@ $files = $fileData['files'];
|
|||||||
|
|
||||||
if ($fileData['currentPage'] < $fileData['totalPages']): ?>
|
if ($fileData['currentPage'] < $fileData['totalPages']): ?>
|
||||||
<a href="?page=<?php echo $fileData['currentPage'] + 1; ?>"
|
<a href="?page=<?php echo $fileData['currentPage'] + 1; ?>"
|
||||||
class="pagination-link">Suivant »</a>
|
class="pagination-link">»</a>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
@ -7,10 +7,14 @@ if (!defined('CYLA_CORE')) {
|
|||||||
|
|
||||||
// Site configuration
|
// Site configuration
|
||||||
define('SITE_NAME', 'Cyla');
|
define('SITE_NAME', 'Cyla');
|
||||||
define('SITE_VERSION', '3.0.1');
|
define('SITE_VERSION', '3.0.2');
|
||||||
define('SITE_URL', 'https://concepts.esenjin.xyz/cyla/');
|
define('SITE_URL', 'https://concepts.esenjin.xyz/cyla/');
|
||||||
|
|
||||||
// Files configuration
|
// Files configuration
|
||||||
|
define('LEGACY_UPLOAD_DIRS', [
|
||||||
|
__DIR__ . '/v1/img/fichiers/',
|
||||||
|
__DIR__ . '/v2/file/'
|
||||||
|
]);
|
||||||
define('UPLOAD_DIR', __DIR__ . '/fichiers/');
|
define('UPLOAD_DIR', __DIR__ . '/fichiers/');
|
||||||
define('MAX_FILE_SIZE', 100 * 1024 * 1024); // 100 Mo en octets
|
define('MAX_FILE_SIZE', 100 * 1024 * 1024); // 100 Mo en octets
|
||||||
define('ALLOWED_EXTENSIONS', [
|
define('ALLOWED_EXTENSIONS', [
|
||||||
|
69
core.php
69
core.php
@ -138,7 +138,17 @@ class Cyla {
|
|||||||
*/
|
*/
|
||||||
public static function listFiles($page = 1, $perPage = 20) {
|
public static function listFiles($page = 1, $perPage = 20) {
|
||||||
$files = [];
|
$files = [];
|
||||||
$allFiles = glob(UPLOAD_DIR . '*');
|
$allFiles = [];
|
||||||
|
|
||||||
|
// Ajouter les fichiers du dossier principal
|
||||||
|
$allFiles = array_merge($allFiles, glob(UPLOAD_DIR . '*'));
|
||||||
|
|
||||||
|
// Ajouter les fichiers des dossiers hérités
|
||||||
|
foreach (LEGACY_UPLOAD_DIRS as $dir) {
|
||||||
|
if (is_dir($dir)) {
|
||||||
|
$allFiles = array_merge($allFiles, glob($dir . '*'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Trier les fichiers par date de modification (plus récent en premier)
|
// Trier les fichiers par date de modification (plus récent en premier)
|
||||||
usort($allFiles, function($a, $b) {
|
usort($allFiles, function($a, $b) {
|
||||||
@ -148,7 +158,7 @@ class Cyla {
|
|||||||
// Calculer la pagination
|
// Calculer la pagination
|
||||||
$total = count($allFiles);
|
$total = count($allFiles);
|
||||||
$totalPages = ceil($total / $perPage);
|
$totalPages = ceil($total / $perPage);
|
||||||
$page = max(1, min($page, $totalPages)); // Garantir que la page est dans les limites
|
$page = max(1, min($page, $totalPages));
|
||||||
$offset = ($page - 1) * $perPage;
|
$offset = ($page - 1) * $perPage;
|
||||||
|
|
||||||
// Récupérer uniquement les fichiers de la page courante
|
// Récupérer uniquement les fichiers de la page courante
|
||||||
@ -156,12 +166,24 @@ class Cyla {
|
|||||||
|
|
||||||
foreach ($pageFiles as $file) {
|
foreach ($pageFiles as $file) {
|
||||||
$info = pathinfo($file);
|
$info = pathinfo($file);
|
||||||
|
$relativePath = '';
|
||||||
|
|
||||||
|
// Déterminer le chemin relatif selon le dossier
|
||||||
|
if (strpos($file, UPLOAD_DIR) === 0) {
|
||||||
|
$relativePath = 'fichiers/';
|
||||||
|
} elseif (strpos($file, __DIR__ . '/v1/img/fichiers/') === 0) {
|
||||||
|
$relativePath = 'v1/img/fichiers/';
|
||||||
|
} elseif (strpos($file, __DIR__ . '/v2/file/') === 0) {
|
||||||
|
$relativePath = 'v2/file/';
|
||||||
|
}
|
||||||
|
|
||||||
$files[] = [
|
$files[] = [
|
||||||
'name' => basename($file),
|
'name' => basename($file),
|
||||||
'size' => filesize($file),
|
'size' => filesize($file),
|
||||||
'extension' => strtolower($info['extension']),
|
'extension' => strtolower($info['extension'] ?? ''),
|
||||||
'uploaded' => filemtime($file),
|
'uploaded' => filemtime($file),
|
||||||
'preview_type' => getPreviewType($info['extension'])
|
'preview_type' => getPreviewType($info['extension'] ?? ''),
|
||||||
|
'path' => $relativePath // Ajout du chemin relatif
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -173,23 +195,50 @@ class Cyla {
|
|||||||
'perPage' => $perPage
|
'perPage' => $perPage
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Supprime un fichier
|
* Supprime un fichier
|
||||||
* @param string $filename Nom du fichier à supprimer
|
* @param string $filename Nom du fichier à supprimer
|
||||||
|
* @param string $path Chemin relatif du fichier
|
||||||
* @return array ['success' => bool, 'error' => string|null]
|
* @return array ['success' => bool, 'error' => string|null]
|
||||||
*/
|
*/
|
||||||
public static function deleteFile($filename) {
|
public static function deleteFile($filename, $path = 'fichiers/') {
|
||||||
$filepath = UPLOAD_DIR . $filename;
|
// Déterminer le chemin complet selon le dossier
|
||||||
|
$basePath = '';
|
||||||
|
switch ($path) {
|
||||||
|
case 'v1/img/fichiers/':
|
||||||
|
$basePath = __DIR__ . '/v1/img/fichiers/';
|
||||||
|
break;
|
||||||
|
case 'v2/file/':
|
||||||
|
$basePath = __DIR__ . '/v2/file/';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$basePath = UPLOAD_DIR;
|
||||||
|
}
|
||||||
|
|
||||||
// Vérifier que le fichier existe et est dans le dossier d'upload
|
$filepath = $basePath . $filename;
|
||||||
|
|
||||||
|
// Vérifier que le fichier existe et est dans le bon dossier
|
||||||
if (!file_exists($filepath) || !is_file($filepath)) {
|
if (!file_exists($filepath) || !is_file($filepath)) {
|
||||||
return ['success' => false, 'error' => 'Fichier introuvable'];
|
return ['success' => false, 'error' => 'Fichier introuvable'];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Vérifier que le fichier est bien dans le dossier d'upload
|
// Vérifier que le fichier est bien dans un des dossiers autorisés
|
||||||
$realpath = realpath($filepath);
|
$realpath = realpath($filepath);
|
||||||
$uploadDir = realpath(UPLOAD_DIR);
|
$allowed = false;
|
||||||
if (strpos($realpath, $uploadDir) !== 0) {
|
|
||||||
|
if (strpos($realpath, realpath(UPLOAD_DIR)) === 0) {
|
||||||
|
$allowed = true;
|
||||||
|
} else {
|
||||||
|
foreach (LEGACY_UPLOAD_DIRS as $dir) {
|
||||||
|
if (strpos($realpath, realpath($dir)) === 0) {
|
||||||
|
$allowed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$allowed) {
|
||||||
return ['success' => false, 'error' => 'Chemin de fichier non autorisé'];
|
return ['success' => false, 'error' => 'Chemin de fichier non autorisé'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
135
css/style.css
135
css/style.css
@ -450,10 +450,11 @@ footer {
|
|||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: var(--spacing-sm);
|
gap: var(--spacing-xs);
|
||||||
margin-top: var(--spacing-lg);
|
margin: var(--spacing-lg) auto;
|
||||||
padding-top: var(--spacing-md);
|
padding-top: var(--spacing-md);
|
||||||
border-top: 1px solid var(--color-border);
|
border-top: 1px solid var(--color-border);
|
||||||
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pagination-link {
|
.pagination-link {
|
||||||
@ -462,13 +463,15 @@ footer {
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
min-width: 2rem;
|
min-width: 2rem;
|
||||||
height: 2rem;
|
height: 2rem;
|
||||||
padding: 0 var(--spacing-sm);
|
padding: 0 0.5rem;
|
||||||
color: var(--color-text);
|
color: var(--color-text);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
background-color: var(--color-bg);
|
background-color: var(--color-bg);
|
||||||
border: 1px solid var(--color-border);
|
border: 1px solid var(--color-border);
|
||||||
border-radius: var(--border-radius);
|
border-radius: var(--border-radius);
|
||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease;
|
||||||
|
white-space: nowrap;
|
||||||
|
font-size: 0.9rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pagination-link:hover {
|
.pagination-link:hover {
|
||||||
@ -483,7 +486,8 @@ footer {
|
|||||||
|
|
||||||
.pagination-ellipsis {
|
.pagination-ellipsis {
|
||||||
color: var(--color-text-muted);
|
color: var(--color-text-muted);
|
||||||
padding: 0 var(--spacing-xs);
|
padding: 0 0.25rem;
|
||||||
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Bouton de suppression */
|
/* Bouton de suppression */
|
||||||
@ -553,6 +557,14 @@ footer {
|
|||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.pagination {
|
.pagination {
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
gap: var(--spacing-xs);
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination-link {
|
||||||
|
min-width: 2.25rem;
|
||||||
|
height: 2.25rem;
|
||||||
|
padding: 0 var(--spacing-sm);
|
||||||
|
font-size: 0.9rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.file-actions {
|
.file-actions {
|
||||||
@ -591,3 +603,118 @@ footer {
|
|||||||
from { opacity: 1; }
|
from { opacity: 1; }
|
||||||
to { opacity: 0; }
|
to { opacity: 0; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.share-container {
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.share-container h1 {
|
||||||
|
color: var(--color-primary);
|
||||||
|
margin-bottom: var(--spacing-sm);
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-meta {
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
margin-bottom: var(--spacing-lg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-container {
|
||||||
|
background-color: var(--color-bg);
|
||||||
|
border: 1px solid var(--color-border);
|
||||||
|
border-radius: var(--border-radius);
|
||||||
|
margin-bottom: var(--spacing-lg);
|
||||||
|
min-height: 200px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-content {
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 600px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-preview {
|
||||||
|
width: 100%;
|
||||||
|
max-height: 600px;
|
||||||
|
overflow: auto;
|
||||||
|
padding: var(--spacing-md);
|
||||||
|
background-color: var(--color-bg);
|
||||||
|
color: var(--color-text);
|
||||||
|
font-family: monospace;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-preview {
|
||||||
|
text-align: center;
|
||||||
|
padding: var(--spacing-lg);
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.extension-badge {
|
||||||
|
background-color: var(--color-bg-alt);
|
||||||
|
color: var(--color-primary);
|
||||||
|
padding: var(--spacing-md) var(--spacing-lg);
|
||||||
|
border-radius: var(--border-radius);
|
||||||
|
font-size: 2rem;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: var(--spacing-md);
|
||||||
|
}
|
||||||
|
|
||||||
|
.share-actions {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: var(--spacing-md);
|
||||||
|
}
|
||||||
|
|
||||||
|
.share-link {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: var(--spacing-xs);
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-group {
|
||||||
|
display: flex;
|
||||||
|
gap: var(--spacing-sm);
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-group input {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Styles responsifs */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.input-group {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-group .btn {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Animation de notification */
|
||||||
|
.notification {
|
||||||
|
position: fixed;
|
||||||
|
bottom: var(--spacing-lg);
|
||||||
|
right: var(--spacing-lg);
|
||||||
|
background-color: var(--color-success);
|
||||||
|
color: white;
|
||||||
|
padding: var(--spacing-md) var(--spacing-lg);
|
||||||
|
border-radius: var(--border-radius);
|
||||||
|
animation: slideIn 0.3s ease-out, fadeOut 0.3s ease-in 2.7s forwards;
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes slideIn {
|
||||||
|
from { transform: translateY(100%); opacity: 0; }
|
||||||
|
to { transform: translateY(0); opacity: 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fadeOut {
|
||||||
|
from { opacity: 1; }
|
||||||
|
to { opacity: 0; }
|
||||||
|
}
|
186
share.php
186
share.php
@ -10,25 +10,60 @@ if (!isset($_GET['file'])) {
|
|||||||
$error = 'Aucun fichier spécifié';
|
$error = 'Aucun fichier spécifié';
|
||||||
} else {
|
} else {
|
||||||
$filename = $_GET['file'];
|
$filename = $_GET['file'];
|
||||||
$filepath = UPLOAD_DIR . $filename;
|
$path = $_GET['path'] ?? 'fichiers/';
|
||||||
|
|
||||||
// Vérifier si le fichier existe
|
// Déterminer le chemin complet selon le dossier
|
||||||
if (!file_exists($filepath)) {
|
$basePath = '';
|
||||||
|
switch ($path) {
|
||||||
|
case 'v1/img/fichiers/':
|
||||||
|
$basePath = __DIR__ . '/v1/img/fichiers/';
|
||||||
|
break;
|
||||||
|
case 'v2/file/':
|
||||||
|
$basePath = __DIR__ . '/v2/file/';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$basePath = UPLOAD_DIR;
|
||||||
|
$path = 'fichiers/'; // Assurer que le path par défaut est correct
|
||||||
|
}
|
||||||
|
|
||||||
|
$filepath = $basePath . $filename;
|
||||||
|
|
||||||
|
// Vérifier que le fichier existe et est un fichier régulier
|
||||||
|
if (!file_exists($filepath) || !is_file($filepath)) {
|
||||||
$error = 'Fichier introuvable';
|
$error = 'Fichier introuvable';
|
||||||
} else {
|
} else {
|
||||||
// Récupérer les informations du fichier
|
// Vérifier que le chemin est sécurisé
|
||||||
$file_info = [
|
$realpath = realpath($filepath);
|
||||||
'name' => $filename,
|
$allowed = false;
|
||||||
'size' => filesize($filepath),
|
|
||||||
'extension' => strtolower(pathinfo($filename, PATHINFO_EXTENSION)),
|
if (strpos($realpath, realpath(UPLOAD_DIR)) === 0) {
|
||||||
'preview_type' => getPreviewType(pathinfo($filename, PATHINFO_EXTENSION))
|
$allowed = true;
|
||||||
];
|
} else {
|
||||||
|
foreach (LEGACY_UPLOAD_DIRS as $dir) {
|
||||||
|
if (strpos($realpath, realpath($dir)) === 0) {
|
||||||
|
$allowed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$allowed) {
|
||||||
|
$error = 'Accès non autorisé';
|
||||||
|
} else {
|
||||||
|
// Récupérer les informations du fichier
|
||||||
|
$file_info = [
|
||||||
|
'name' => $filename,
|
||||||
|
'size' => filesize($filepath),
|
||||||
|
'extension' => strtolower(pathinfo($filename, PATHINFO_EXTENSION)),
|
||||||
|
'preview_type' => getPreviewType(pathinfo($filename, PATHINFO_EXTENSION))
|
||||||
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Construction de l'URL absolue du fichier
|
// Construction des URLs
|
||||||
$file_url = SITE_URL . 'fichiers/' . ($file_info ? rawurlencode($file_info['name']) : '');
|
$file_url = SITE_URL . $path . ($file_info ? rawurlencode($file_info['name']) : '');
|
||||||
$share_url = SITE_URL . 'share.php?file=' . ($file_info ? rawurlencode($file_info['name']) : '');
|
$share_url = SITE_URL . 'share.php?file=' . ($file_info ? rawurlencode($file_info['name']) : '') . '&path=' . urlencode($path);
|
||||||
|
|
||||||
// Contenu de la page
|
// Contenu de la page
|
||||||
$pageTitle = $file_info ? $file_info['name'] : 'Fichier introuvable';
|
$pageTitle = $file_info ? $file_info['name'] : 'Fichier introuvable';
|
||||||
@ -71,8 +106,13 @@ ob_start(); ?>
|
|||||||
</audio>
|
</audio>
|
||||||
<?php elseif ($file_info['preview_type'] === 'text'): ?>
|
<?php elseif ($file_info['preview_type'] === 'text'): ?>
|
||||||
<pre class="text-preview"><?php
|
<pre class="text-preview"><?php
|
||||||
|
// Lire et afficher le contenu du fichier texte de manière sécurisée
|
||||||
$content = file_get_contents($filepath);
|
$content = file_get_contents($filepath);
|
||||||
echo Cyla::escape($content);
|
if ($content !== false) {
|
||||||
|
echo Cyla::escape($content);
|
||||||
|
} else {
|
||||||
|
echo "Erreur lors de la lecture du fichier";
|
||||||
|
}
|
||||||
?></pre>
|
?></pre>
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
<div class="no-preview">
|
<div class="no-preview">
|
||||||
@ -142,124 +182,6 @@ ob_start(); ?>
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
|
||||||
/* Styles spécifiques à la page de partage */
|
|
||||||
.share-container {
|
|
||||||
max-width: 800px;
|
|
||||||
margin: 0 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.share-container h1 {
|
|
||||||
color: var(--color-primary);
|
|
||||||
margin-bottom: var(--spacing-sm);
|
|
||||||
word-break: break-all;
|
|
||||||
}
|
|
||||||
|
|
||||||
.file-meta {
|
|
||||||
color: var(--color-text-muted);
|
|
||||||
margin-bottom: var(--spacing-lg);
|
|
||||||
}
|
|
||||||
|
|
||||||
.preview-container {
|
|
||||||
background-color: var(--color-bg);
|
|
||||||
border: 1px solid var(--color-border);
|
|
||||||
border-radius: var(--border-radius);
|
|
||||||
margin-bottom: var(--spacing-lg);
|
|
||||||
min-height: 200px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preview-content {
|
|
||||||
max-width: 100%;
|
|
||||||
max-height: 600px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-preview {
|
|
||||||
width: 100%;
|
|
||||||
max-height: 600px;
|
|
||||||
overflow: auto;
|
|
||||||
padding: var(--spacing-md);
|
|
||||||
background-color: var(--color-bg);
|
|
||||||
color: var(--color-text);
|
|
||||||
font-family: monospace;
|
|
||||||
white-space: pre-wrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.no-preview {
|
|
||||||
text-align: center;
|
|
||||||
padding: var(--spacing-lg);
|
|
||||||
color: var(--color-text-muted);
|
|
||||||
}
|
|
||||||
|
|
||||||
.extension-badge {
|
|
||||||
background-color: var(--color-bg-alt);
|
|
||||||
color: var(--color-primary);
|
|
||||||
padding: var(--spacing-md) var(--spacing-lg);
|
|
||||||
border-radius: var(--border-radius);
|
|
||||||
font-size: 2rem;
|
|
||||||
font-weight: bold;
|
|
||||||
margin-bottom: var(--spacing-md);
|
|
||||||
}
|
|
||||||
|
|
||||||
.share-actions {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: var(--spacing-md);
|
|
||||||
}
|
|
||||||
|
|
||||||
.share-link {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: var(--spacing-xs);
|
|
||||||
}
|
|
||||||
|
|
||||||
.input-group {
|
|
||||||
display: flex;
|
|
||||||
gap: var(--spacing-sm);
|
|
||||||
}
|
|
||||||
|
|
||||||
.input-group input {
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Styles responsifs */
|
|
||||||
@media (max-width: 768px) {
|
|
||||||
.input-group {
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.input-group .btn {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Animation de notification */
|
|
||||||
.notification {
|
|
||||||
position: fixed;
|
|
||||||
bottom: var(--spacing-lg);
|
|
||||||
right: var(--spacing-lg);
|
|
||||||
background-color: var(--color-success);
|
|
||||||
color: white;
|
|
||||||
padding: var(--spacing-md) var(--spacing-lg);
|
|
||||||
border-radius: var(--border-radius);
|
|
||||||
animation: slideIn 0.3s ease-out, fadeOut 0.3s ease-in 2.7s forwards;
|
|
||||||
z-index: 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes slideIn {
|
|
||||||
from { transform: translateY(100%); opacity: 0; }
|
|
||||||
to { transform: translateY(0); opacity: 1; }
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes fadeOut {
|
|
||||||
from { opacity: 1; }
|
|
||||||
to { opacity: 0; }
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// Fonction pour gérer la copie
|
// Fonction pour gérer la copie
|
||||||
async function handleCopy(elementId, message) {
|
async function handleCopy(elementId, message) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user