Fix: /admin/content is nu boom-editor + image-grootte knop + custom syntax
- /admin/content is nu de boom-editor (plugin-file-tree structuur),
consistent met plugin- en thema-editors. Oude tabelweergave verhuisd
naar /admin/content-list, bereikbaar via 'Boom weergave'/'Lijst
weergave' knoppen. /admin/content-files redirect naar /admin/content.
- Image-grootte knop in markdown editor-toolbar: selecteer ,
klik knop, breedte/hoogte dialog, {:width=... height=...} syntax
toevoegen/vervangen. Bestaande waarden worden in prompts getoond.
- Custom-grootte syntax {:width=...} nu ook correct herschreven naar
/-media/ endpoint (was alleen gewone  herschreven).
- Handleidingen bijgewerkt (content-beheer.md NL+EN: boom/lijst
weergave uitleg + image-grootte + images in content sectie)
- Release notes v2.6.2 bijgewerkt
- Pentest 30/30, WCAG 25/25
This commit is contained in:
+56
-51
@@ -270,12 +270,17 @@ switch ($route) {
|
||||
break;
|
||||
|
||||
case 'content':
|
||||
handleContentFiles($auth, $appConfig, $twig, $user, $csrf, $siteConfig);
|
||||
break;
|
||||
|
||||
case 'content-list':
|
||||
handleContent($auth, $appConfig, $twig, $user, $csrf, $siteConfig);
|
||||
break;
|
||||
|
||||
case 'content-files':
|
||||
handleContentFiles($auth, $appConfig, $twig, $user, $csrf, $siteConfig);
|
||||
break;
|
||||
// Backward compat: redirect to the unified content editor
|
||||
header('Location: /admin/content');
|
||||
exit;
|
||||
|
||||
case 'content-file-upload':
|
||||
handleContentFileUpload($auth, $appConfig, $user);
|
||||
@@ -1015,18 +1020,18 @@ function handleContentFiles($auth, $config, $twig, $user, $csrf, $siteConfig): v
|
||||
function handleContentFileUpload($auth, $config, $user): void
|
||||
{
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
header('Location: /admin/content-files');
|
||||
header('Location: /admin/content');
|
||||
exit;
|
||||
}
|
||||
if (!$auth->verifyCsrf($_POST['csrf_token'] ?? '')) {
|
||||
header('Location: /admin/content-files');
|
||||
header('Location: /admin/content');
|
||||
exit;
|
||||
}
|
||||
|
||||
$contentDir = $config['content_dir'];
|
||||
$realContentDir = realpath($contentDir);
|
||||
if (!$realContentDir || !is_dir($realContentDir)) {
|
||||
header('Location: /admin/content-files');
|
||||
header('Location: /admin/content');
|
||||
exit;
|
||||
}
|
||||
|
||||
@@ -1040,13 +1045,13 @@ function handleContentFileUpload($auth, $config, $user): void
|
||||
$realTarget = realpath($targetDir);
|
||||
if ($realTarget === false) {
|
||||
if (!@mkdir($targetDir, 0755, true)) {
|
||||
header('Location: /admin/content-files');
|
||||
header('Location: /admin/content');
|
||||
exit;
|
||||
}
|
||||
$realTarget = realpath($targetDir);
|
||||
}
|
||||
if (!$realTarget || strpos($realTarget, $realContentDir) !== 0 || !is_dir($realTarget)) {
|
||||
header('Location: /admin/content-files');
|
||||
header('Location: /admin/content');
|
||||
exit;
|
||||
}
|
||||
|
||||
@@ -1090,7 +1095,7 @@ function handleContentFileUpload($auth, $config, $user): void
|
||||
$type = $type === 'success' ? 'success' : 'danger';
|
||||
}
|
||||
|
||||
$redir = '/admin/content-files';
|
||||
$redir = '/admin/content';
|
||||
if (!empty($msg)) {
|
||||
$redir .= '?msg=' . urlencode(implode(' ', $msg)) . '&msgtype=' . urlencode($type);
|
||||
}
|
||||
@@ -1105,18 +1110,18 @@ function handleContentFileUpload($auth, $config, $user): void
|
||||
function handleContentFileDelete($auth, $config, $user): void
|
||||
{
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
header('Location: /admin/content-files');
|
||||
header('Location: /admin/content');
|
||||
exit;
|
||||
}
|
||||
if (!$auth->verifyCsrf($_POST['csrf_token'] ?? '')) {
|
||||
header('Location: /admin/content-files');
|
||||
header('Location: /admin/content');
|
||||
exit;
|
||||
}
|
||||
|
||||
$contentDir = $config['content_dir'];
|
||||
$realContentDir = realpath($contentDir);
|
||||
if (!$realContentDir || !is_dir($realContentDir)) {
|
||||
header('Location: /admin/content-files');
|
||||
header('Location: /admin/content');
|
||||
exit;
|
||||
}
|
||||
|
||||
@@ -1124,20 +1129,20 @@ function handleContentFileDelete($auth, $config, $user): void
|
||||
$relFile = ltrim($relFile, '/');
|
||||
foreach (explode('/', $relFile) as $seg) {
|
||||
if ($seg === '..' || $seg === '.') {
|
||||
header('Location: /admin/content-files');
|
||||
header('Location: /admin/content');
|
||||
exit;
|
||||
}
|
||||
}
|
||||
$base = basename($relFile);
|
||||
if ($base === '' || $base[0] === '.') {
|
||||
header('Location: /admin/content-files');
|
||||
header('Location: /admin/content');
|
||||
exit;
|
||||
}
|
||||
|
||||
$fullPath = $realContentDir . '/' . $relFile;
|
||||
$realPath = realpath($fullPath);
|
||||
if ($realPath === false || strpos($realPath, $realContentDir) !== 0 || !is_file($realPath)) {
|
||||
header('Location: /admin/content-files');
|
||||
header('Location: /admin/content');
|
||||
exit;
|
||||
}
|
||||
|
||||
@@ -1152,7 +1157,7 @@ function handleContentFileDelete($auth, $config, $user): void
|
||||
$type = 'danger';
|
||||
}
|
||||
|
||||
header('Location: /admin/content-files?msg=' . urlencode($msg) . '&msgtype=' . urlencode($type));
|
||||
header('Location: /admin/content?msg=' . urlencode($msg) . '&msgtype=' . urlencode($type));
|
||||
exit;
|
||||
}
|
||||
|
||||
@@ -1165,7 +1170,7 @@ function handleContentFileMove($auth, $config, $twig, $user, $csrf): void
|
||||
$contentDir = $config['content_dir'];
|
||||
$realContentDir = realpath($contentDir);
|
||||
if (!$realContentDir || !is_dir($realContentDir)) {
|
||||
header('Location: /admin/content-files');
|
||||
header('Location: /admin/content');
|
||||
exit;
|
||||
}
|
||||
|
||||
@@ -1173,20 +1178,20 @@ function handleContentFileMove($auth, $config, $twig, $user, $csrf): void
|
||||
$relFile = ltrim($relFile, '/');
|
||||
foreach (explode('/', $relFile) as $seg) {
|
||||
if ($seg === '..' || $seg === '.') {
|
||||
header('Location: /admin/content-files');
|
||||
header('Location: /admin/content');
|
||||
exit;
|
||||
}
|
||||
}
|
||||
$base = basename($relFile);
|
||||
if ($base === '' || $base[0] === '.') {
|
||||
header('Location: /admin/content-files');
|
||||
header('Location: /admin/content');
|
||||
exit;
|
||||
}
|
||||
|
||||
$fullPath = $realContentDir . '/' . $relFile;
|
||||
$realPath = realpath($fullPath);
|
||||
if ($realPath === false || strpos($realPath, $realContentDir) !== 0 || !is_file($realPath)) {
|
||||
header('Location: /admin/content-files');
|
||||
header('Location: /admin/content');
|
||||
exit;
|
||||
}
|
||||
|
||||
@@ -1241,7 +1246,7 @@ function handleContentFileMove($auth, $config, $twig, $user, $csrf): void
|
||||
} elseif (rename($realPath, $newPath)) {
|
||||
adminLog($config, 'info', $user['username'] . ' verplaatste content/' . $relFile . ' naar content/' . ($dest ? $dest . '/' : '') . basename($relFile));
|
||||
$newRel = $dest === '' ? basename($relFile) : $dest . '/' . basename($relFile);
|
||||
header('Location: /admin/content-files?file=' . urlencode($newRel) . '&msg=' . urlencode('Bestand verplaatst.') . '&msgtype=success');
|
||||
header('Location: /admin/content?file=' . urlencode($newRel) . '&msg=' . urlencode('Bestand verplaatst.') . '&msgtype=success');
|
||||
exit;
|
||||
} else {
|
||||
$err = error_get_last();
|
||||
@@ -1275,18 +1280,18 @@ function handleContentFileMove($auth, $config, $twig, $user, $csrf): void
|
||||
function handleContentDirCreateIn($auth, $config, $user): void
|
||||
{
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
header('Location: /admin/content-files');
|
||||
header('Location: /admin/content');
|
||||
exit;
|
||||
}
|
||||
if (!$auth->verifyCsrf($_POST['csrf_token'] ?? '')) {
|
||||
header('Location: /admin/content-files');
|
||||
header('Location: /admin/content');
|
||||
exit;
|
||||
}
|
||||
|
||||
$contentDir = $config['content_dir'];
|
||||
$realContentDir = realpath($contentDir);
|
||||
if (!$realContentDir || !is_dir($realContentDir)) {
|
||||
header('Location: /admin/content-files');
|
||||
header('Location: /admin/content');
|
||||
exit;
|
||||
}
|
||||
|
||||
@@ -1298,19 +1303,19 @@ function handleContentDirCreateIn($auth, $config, $user): void
|
||||
$dirname = trim($_POST['dirname'] ?? '');
|
||||
$dirname = preg_replace('/[^a-zA-Z0-9._-]/', '-', $dirname);
|
||||
if ($dirname === '' || $dirname === '.' || $dirname === '..') {
|
||||
header('Location: /admin/content-files?msg=' . urlencode('Ongeldige mapnaam.') . '&msgtype=danger');
|
||||
header('Location: /admin/content?msg=' . urlencode('Ongeldige mapnaam.') . '&msgtype=danger');
|
||||
exit;
|
||||
}
|
||||
$newPath = $realContentDir . '/' . ($inDir ? $inDir . '/' : '') . $dirname;
|
||||
if (file_exists($newPath)) {
|
||||
header('Location: /admin/content-files?msg=' . urlencode('Map bestaat al.') . '&msgtype=danger');
|
||||
header('Location: /admin/content?msg=' . urlencode('Map bestaat al.') . '&msgtype=danger');
|
||||
exit;
|
||||
}
|
||||
if (@mkdir($newPath, 0755, true)) {
|
||||
adminLog($config, 'info', $user['username'] . ' creëerde content map ' . ($inDir ? $inDir . '/' : '') . $dirname);
|
||||
header('Location: /admin/content-files?msg=' . urlencode('Map aangemaakt.') . '&msgtype=success');
|
||||
header('Location: /admin/content?msg=' . urlencode('Map aangemaakt.') . '&msgtype=success');
|
||||
} else {
|
||||
header('Location: /admin/content-files?msg=' . urlencode('Map aanmaken mislukt.') . '&msgtype=danger');
|
||||
header('Location: /admin/content?msg=' . urlencode('Map aanmaken mislukt.') . '&msgtype=danger');
|
||||
}
|
||||
exit;
|
||||
}
|
||||
@@ -1324,7 +1329,7 @@ function handleContentDirRenameIn($auth, $config, $twig, $user, $csrf): void
|
||||
$contentDir = $config['content_dir'];
|
||||
$realContentDir = realpath($contentDir);
|
||||
if (!$realContentDir || !is_dir($realContentDir)) {
|
||||
header('Location: /admin/content-files');
|
||||
header('Location: /admin/content');
|
||||
exit;
|
||||
}
|
||||
|
||||
@@ -1366,7 +1371,7 @@ function handleContentDirRenameIn($auth, $config, $twig, $user, $csrf): void
|
||||
$messageType = 'danger';
|
||||
} elseif (rename($realDir, $newPath)) {
|
||||
adminLog($config, 'info', $user['username'] . ' hernoemde content map ' . $dirRel . ' naar ' . $newName);
|
||||
header('Location: /admin/content-files?msg=' . urlencode('Map hernoemd.') . '&msgtype=success');
|
||||
header('Location: /admin/content?msg=' . urlencode('Map hernoemd.') . '&msgtype=success');
|
||||
exit;
|
||||
} else {
|
||||
$message = 'Hernoemen mislukt.';
|
||||
@@ -1378,7 +1383,7 @@ function handleContentDirRenameIn($auth, $config, $twig, $user, $csrf): void
|
||||
}
|
||||
|
||||
if ($dirRel === '') {
|
||||
header('Location: /admin/content-files?msg=' . urlencode('Map niet gevonden.') . '&msgtype=danger');
|
||||
header('Location: /admin/content?msg=' . urlencode('Map niet gevonden.') . '&msgtype=danger');
|
||||
exit;
|
||||
}
|
||||
|
||||
@@ -1403,18 +1408,18 @@ function handleContentDirRenameIn($auth, $config, $twig, $user, $csrf): void
|
||||
function handleContentDirDeleteIn($auth, $config, $user): void
|
||||
{
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
header('Location: /admin/content-files');
|
||||
header('Location: /admin/content');
|
||||
exit;
|
||||
}
|
||||
if (!$auth->verifyCsrf($_POST['csrf_token'] ?? '')) {
|
||||
header('Location: /admin/content-files');
|
||||
header('Location: /admin/content');
|
||||
exit;
|
||||
}
|
||||
|
||||
$contentDir = $config['content_dir'];
|
||||
$realContentDir = realpath($contentDir);
|
||||
if (!$realContentDir || !is_dir($realContentDir)) {
|
||||
header('Location: /admin/content-files');
|
||||
header('Location: /admin/content');
|
||||
exit;
|
||||
}
|
||||
|
||||
@@ -1422,19 +1427,19 @@ function handleContentDirDeleteIn($auth, $config, $user): void
|
||||
$dirRel = ltrim($dirRel, '/');
|
||||
foreach (explode('/', $dirRel) as $seg) {
|
||||
if ($seg === '..' || $seg === '.') {
|
||||
header('Location: /admin/content-files?msg=' . urlencode('Ongeldige map.') . '&msgtype=danger');
|
||||
header('Location: /admin/content?msg=' . urlencode('Ongeldige map.') . '&msgtype=danger');
|
||||
exit;
|
||||
}
|
||||
}
|
||||
if ($dirRel === '') {
|
||||
header('Location: /admin/content-files?msg=' . urlencode('Ongeldige map.') . '&msgtype=danger');
|
||||
header('Location: /admin/content?msg=' . urlencode('Ongeldige map.') . '&msgtype=danger');
|
||||
exit;
|
||||
}
|
||||
|
||||
$fullPath = $realContentDir . '/' . $dirRel;
|
||||
$realDir = realpath($fullPath);
|
||||
if (!$realDir || !is_dir($realDir) || strpos($realDir, $realContentDir) !== 0) {
|
||||
header('Location: /admin/content-files?msg=' . urlencode('Map niet gevonden.') . '&msgtype=danger');
|
||||
header('Location: /admin/content?msg=' . urlencode('Map niet gevonden.') . '&msgtype=danger');
|
||||
exit;
|
||||
}
|
||||
|
||||
@@ -1445,14 +1450,14 @@ function handleContentDirDeleteIn($auth, $config, $user): void
|
||||
if ($e[0] !== '.') { $isEmpty = false; break; }
|
||||
}
|
||||
if (!$isEmpty) {
|
||||
header('Location: /admin/content-files?msg=' . urlencode('Map moet leeg zijn.') . '&msgtype=danger');
|
||||
header('Location: /admin/content?msg=' . urlencode('Map moet leeg zijn.') . '&msgtype=danger');
|
||||
exit;
|
||||
}
|
||||
if (@rmdir($realDir)) {
|
||||
adminLog($config, 'info', $user['username'] . ' verwijderde content map ' . $dirRel);
|
||||
header('Location: /admin/content-files?msg=' . urlencode('Map verwijderd.') . '&msgtype=success');
|
||||
header('Location: /admin/content?msg=' . urlencode('Map verwijderd.') . '&msgtype=success');
|
||||
} else {
|
||||
header('Location: /admin/content-files?msg=' . urlencode('Map verwijderen mislukt.') . '&msgtype=danger');
|
||||
header('Location: /admin/content?msg=' . urlencode('Map verwijderen mislukt.') . '&msgtype=danger');
|
||||
}
|
||||
exit;
|
||||
}
|
||||
@@ -1470,7 +1475,7 @@ function handleContentEdit($auth, $config, $twig, $user, $csrf, $siteConfig): vo
|
||||
$realPath = realpath($filePath);
|
||||
$realContentDir = realpath($contentDir);
|
||||
if (!$realPath || !$realContentDir || strpos($realPath, $realContentDir) !== 0) {
|
||||
header('Location: /admin/content');
|
||||
header('Location: /admin/content-list');
|
||||
exit;
|
||||
}
|
||||
|
||||
@@ -1690,13 +1695,13 @@ function handleContentNew($auth, $config, $twig, $user, $csrf, $siteConfig): voi
|
||||
function handleContentDelete($auth, $config): void
|
||||
{
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
header('Location: /admin/content');
|
||||
header('Location: /admin/content-list');
|
||||
exit;
|
||||
}
|
||||
|
||||
$user = $auth->getCurrentUser();
|
||||
if (!$auth->verifyCsrf($_POST['csrf_token'] ?? '')) {
|
||||
header('Location: /admin/content');
|
||||
header('Location: /admin/content-list');
|
||||
exit;
|
||||
}
|
||||
|
||||
@@ -1710,20 +1715,20 @@ function handleContentDelete($auth, $config): void
|
||||
adminLog($config, 'info', $user['username'] . ' verwijderde ' . $file);
|
||||
}
|
||||
|
||||
header('Location: /admin/content?dir=' . urlencode(dirname($file)));
|
||||
header('Location: /admin/content-list?dir=' . urlencode(dirname($file)));
|
||||
exit;
|
||||
}
|
||||
|
||||
function handleContentDirCreate($auth, $config): void
|
||||
{
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
header('Location: /admin/content');
|
||||
header('Location: /admin/content-list');
|
||||
exit;
|
||||
}
|
||||
|
||||
$user = $auth->getCurrentUser();
|
||||
if (!$auth->verifyCsrf($_POST['csrf_token'] ?? '')) {
|
||||
header('Location: /admin/content');
|
||||
header('Location: /admin/content-list');
|
||||
exit;
|
||||
}
|
||||
|
||||
@@ -1741,7 +1746,7 @@ function handleContentDirCreate($auth, $config): void
|
||||
}
|
||||
}
|
||||
|
||||
header('Location: /admin/content?dir=' . urlencode($subdir));
|
||||
header('Location: /admin/content-list?dir=' . urlencode($subdir));
|
||||
exit;
|
||||
}
|
||||
|
||||
@@ -1768,7 +1773,7 @@ function handleContentDirRename($auth, $config, $twig, $user, $csrf): void
|
||||
if (!file_exists($newPath) && $newPath !== $fullPath) {
|
||||
rename($fullPath, $newPath);
|
||||
adminLog($config, 'info', $user['username'] . ' hernoemde map ' . basename($dir) . ' naar ' . $newName);
|
||||
header('Location: /admin/content?dir=' . urlencode(dirname($dir) . '/' . $newName));
|
||||
header('Location: /admin/content-list?dir=' . urlencode(dirname($dir) . '/' . $newName));
|
||||
exit;
|
||||
} else {
|
||||
$message = 'Map bestaat al of ongeldige naam.';
|
||||
@@ -1797,13 +1802,13 @@ function handleContentDirRename($auth, $config, $twig, $user, $csrf): void
|
||||
function handleContentDirDelete($auth, $config): void
|
||||
{
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
header('Location: /admin/content');
|
||||
header('Location: /admin/content-list');
|
||||
exit;
|
||||
}
|
||||
|
||||
$user = $auth->getCurrentUser();
|
||||
if (!$auth->verifyCsrf($_POST['csrf_token'] ?? '')) {
|
||||
header('Location: /admin/content');
|
||||
header('Location: /admin/content-list');
|
||||
exit;
|
||||
}
|
||||
|
||||
@@ -1821,7 +1826,7 @@ function handleContentDirDelete($auth, $config): void
|
||||
}
|
||||
}
|
||||
|
||||
header('Location: /admin/content?dir=' . urlencode(dirname($dir)));
|
||||
header('Location: /admin/content-list?dir=' . urlencode(dirname($dir)));
|
||||
exit;
|
||||
}
|
||||
|
||||
@@ -1867,7 +1872,7 @@ function handleContentMove($auth, $config, $twig, $user, $csrf): void
|
||||
if (!file_exists($newPath)) {
|
||||
rename($fullPath, $newPath);
|
||||
adminLog($config, 'info', $user['username'] . ' verplaatste ' . $item . ' naar ' . $dest);
|
||||
header('Location: /admin/content?dir=' . urlencode($dest));
|
||||
header('Location: /admin/content-list?dir=' . urlencode($dest));
|
||||
exit;
|
||||
} else {
|
||||
$message = 'Bestand of map bestaat al op de bestemming.';
|
||||
|
||||
Reference in New Issue
Block a user