Changed to permlainks only
This commit is contained in:
parent
66c741200a
commit
c120f624df
6 changed files with 76 additions and 8 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -6,5 +6,5 @@ thumbs/
|
|||
*.log
|
||||
cache/
|
||||
push.json
|
||||
in-dir_renames.txt
|
||||
node_modules/
|
||||
bin/.personality_index
|
||||
|
|
|
|||
51
404.php
Normal file
51
404.php
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
date_default_timezone_set('Europe/Copenhagen');
|
||||
if (!function_exists('h')) {
|
||||
function h($s){ return htmlspecialchars((string)$s, ENT_QUOTES, "UTF-8"); }
|
||||
}
|
||||
$siteHeaderTitle = 'Multiple Voices Log';
|
||||
$brandUrl = '404.php';
|
||||
http_response_code(404);
|
||||
?>
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<title>404 — MVLog</title>
|
||||
<meta name="robots" content="noindex,nofollow">
|
||||
<link rel="stylesheet" href="style.css?v=20260531u">
|
||||
<style>
|
||||
.not-found-card{
|
||||
max-width:680px;
|
||||
margin:0 auto;
|
||||
background:rgba(27,30,34,.92);
|
||||
backdrop-filter:blur(2px);
|
||||
border-radius:.8rem;
|
||||
padding:1.25rem 1.25rem 1.4rem;
|
||||
box-shadow:0 2px 16px #0006;
|
||||
text-align:center
|
||||
}
|
||||
.not-found-card h2{
|
||||
font-size:1.8rem;
|
||||
margin:.1rem 0 .9rem
|
||||
}
|
||||
.not-found-card p{
|
||||
font-size:1.05rem;
|
||||
line-height:1.55;
|
||||
margin:.55rem 0
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<?php include __DIR__ . '/_header.php'; ?>
|
||||
<main>
|
||||
<section class="not-found-card" aria-labelledby="not-found-title">
|
||||
<h2 id="not-found-title">404 — Not found</h2>
|
||||
<p>The narrator claimed he knew where he was going.</p>
|
||||
<p>The narrator is unreliable.</p>
|
||||
</section>
|
||||
</main>
|
||||
<?php include __DIR__ . '/_footer.php'; ?>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
<?php
|
||||
// Shared header for public pages (index.php, contact.php, etc.)
|
||||
?><header class="site-header admin-header"><div class="brand-wrap"><a class="header-logo" href="index.php" aria-label="MVLog home"><img src="assets/img/moto_travel.png" alt=""></a><a class="brand" href="index.php"><h1><?=h($siteHeaderTitle)?></h1><p>journal of an<br>unreliable narrator.</p></a></div><div class="header-actions"><button id="push-toggle" class="push-toggle" type="button" hidden aria-label="Notifications" title="Notifications"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 22a2.7 2.7 0 0 0 2.6-2h-5.2A2.7 2.7 0 0 0 12 22Zm7-6V11a7 7 0 0 0-5-6.7V3a2 2 0 0 0-4 0v1.3A7 7 0 0 0 5 11v5l-2 2v1h18v-1l-2-2Z"/></svg></button><a class="rss-link" href="feed.php" aria-label="RSS feed" title="RSS feed"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M6.2 17.8a2 2 0 1 1-4 0 2 2 0 0 1 4 0ZM2.2 8.7v3.1a10 10 0 0 1 10 10h3.1A13.1 13.1 0 0 0 2.2 8.7Zm0-5.5v3.1a15.5 15.5 0 0 1 15.5 15.5h3.1A18.6 18.6 0 0 0 2.2 3.2Z"/></svg></a><a class="contact-link" href="contact.php" aria-label="Contact" title="Contact"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M22 6c0-1.1-.9-2-2-2H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6zm-2 0-8 5-8-5h16zm0 12H4V8l8 5 8-5v10z"/></svg></a></div></header>
|
||||
$brandUrl = $brandUrl ?? 'index.php';
|
||||
if ($brandUrl === '') $brandUrl = 'index.php';
|
||||
?><header class="site-header admin-header"><div class="brand-wrap"><a class="header-logo" href="<?=h($brandUrl)?>" aria-label="MVLog home"><img src="assets/img/moto_travel.png" alt=""></a><a class="brand" href="<?=h($brandUrl)?>"><h1><?=h($siteHeaderTitle)?></h1><p>journal of an<br>unreliable narrator.</p></a></div><div class="header-actions"><button id="push-toggle" class="push-toggle" type="button" hidden aria-label="Notifications" title="Notifications"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 22a2.7 2.7 0 0 0 2.6-2h-5.2A2.7 2.7 0 0 0 12 22Zm7-6V11a7 7 0 0 0-5-6.7V3a2 2 0 0 0-4 0v1.3A7 7 0 0 0 5 11v5l-2 2v1h18v-1l-2-2Z"/></svg></button><a class="rss-link" href="feed.php" aria-label="RSS feed" title="RSS feed"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M6.2 17.8a2 2 0 1 1-4 0 2 2 0 0 1 4 0ZM2.2 8.7v3.1a10 10 0 0 1 10 10h3.1A13.1 13.1 0 0 0 2.2 8.7Zm0-5.5v3.1a15.5 15.5 0 0 1 15.5 15.5h3.1A18.6 18.6 0 0 0 2.2 3.2Z"/></svg></a><a class="contact-link" href="contact.php" aria-label="Contact" title="Contact"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M22 6c0-1.1-.9-2-2-2H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6zm-2 0-8 5-8-5h16zm0 12H4V8l8 5 8-5v10z"/></svg></a></div></header>
|
||||
|
|
|
|||
23
index.php
23
index.php
|
|
@ -112,6 +112,12 @@ function article_og_image_url($articleId){
|
|||
return 'https://bubulescu.org/out-dir/' . rawurlencode($articleId . '_og.jpg');
|
||||
}
|
||||
|
||||
function render_404_page(){
|
||||
http_response_code(404);
|
||||
include __DIR__ . '/404.php';
|
||||
exit;
|
||||
}
|
||||
|
||||
function video_metadata($path){
|
||||
$base = pathinfo($path, PATHINFO_FILENAME);
|
||||
$meta = [
|
||||
|
|
@ -223,6 +229,9 @@ usort($videos, function($a, $b) use ($videoCache) {
|
|||
});
|
||||
|
||||
$articleId = trim((string)($_GET['id'] ?? ''));
|
||||
if ($articleId === '' || !preg_match('/^[0-9]{14}[a-f0-9]{16}$/', $articleId) || count(array_diff_key($_GET, ['id' => true])) > 0) {
|
||||
render_404_page();
|
||||
}
|
||||
|
||||
if ($articleId !== '') {
|
||||
$videos = array_values(array_filter($videos, function($v) use ($articleId, $config) {
|
||||
|
|
@ -289,6 +298,9 @@ $total = count($videos);
|
|||
$pages = max(1, (int)ceil($total / $per));
|
||||
$page = min($page, $pages);
|
||||
$slice = array_slice($videos, ($page - 1) * $per, $per);
|
||||
if (!$slice) {
|
||||
render_404_page();
|
||||
}
|
||||
|
||||
$activeFilterCount = ($keywordValue !== '') ? 1 : 0;
|
||||
$baseParams = ($rawKeyword !== '') ? ['q' => $rawKeyword] : [];
|
||||
|
|
@ -347,6 +359,7 @@ $headerTitles = [
|
|||
'My Vices Last',
|
||||
];
|
||||
$siteHeaderTitle = $headerTitles[array_rand($headerTitles)];
|
||||
$brandUrl = '?id=' . rawurlencode($articleId);
|
||||
?>
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
|
@ -430,12 +443,14 @@ $siteHeaderTitle = $headerTitles[array_rand($headerTitles)];
|
|||
</form>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($articleId === ''): ?>
|
||||
<p class="filter-summary">
|
||||
Showing <?=h((string)$total)?> article(s)
|
||||
<?php if($activeFilterCount > 0): ?> with <?=h((string)$activeFilterCount)?> active filter(s)<?php endif; ?>
|
||||
</p>
|
||||
|
||||
<?php if(!$slice): ?><p>No videos found for current filter.</p><?php endif; ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="video-list">
|
||||
<?php foreach($slice as $v):
|
||||
|
|
@ -453,8 +468,8 @@ $siteHeaderTitle = $headerTitles[array_rand($headerTitles)];
|
|||
<div class="video-row-head video-row-head-mobile">
|
||||
<h2 class="video-row-title"><?php if($permalinkUrl !== ''): ?><a href="<?=h($permalinkUrl)?>"><?=h($m['title'])?></a><?php else: ?><?=h($m['title'])?><?php endif; ?></h2>
|
||||
<p class="meta">
|
||||
<span><a href="<?=h($dateFilterUrl)?>"><?=h($m['date'])?></a></span>
|
||||
<?php if(!empty($m['location'])): ?><span><a href="<?=h($locFilterUrl)?>"><?=h($m['location'])?></a></span><?php endif; ?>
|
||||
<span><?=h($m['date'])?></span>
|
||||
<?php if(!empty($m['location'])): ?><span><?=h($m['location'])?></span><?php endif; ?>
|
||||
</p>
|
||||
<?php if(!empty($m['teaser'])): ?><p class="description-teaser description-teaser-mobile"><?=h((string)$m['teaser'])?></p><?php endif; ?>
|
||||
</div>
|
||||
|
|
@ -471,8 +486,8 @@ $siteHeaderTitle = $headerTitles[array_rand($headerTitles)];
|
|||
<div class="video-info">
|
||||
<h2 class="video-row-title video-row-title-desktop"><?php if($permalinkUrl !== ''): ?><a href="<?=h($permalinkUrl)?>"><?=h($m['title'])?></a><?php else: ?><?=h($m['title'])?><?php endif; ?></h2>
|
||||
<p class="meta meta-desktop">
|
||||
<span><a href="<?=h($dateFilterUrl)?>"><?=h($m['date'])?></a></span>
|
||||
<?php if(!empty($m['location'])): ?><span><a href="<?=h($locFilterUrl)?>"><?=h($m['location'])?></a></span><?php endif; ?>
|
||||
<span><?=h($m['date'])?></span>
|
||||
<?php if(!empty($m['location'])): ?><span><?=h($m['location'])?></span><?php endif; ?>
|
||||
</p>
|
||||
<?php if(!empty($m['teaser'])): ?><p class="description-teaser description-teaser-desktop"><?=h((string)$m['teaser'])?></p><?php endif; ?>
|
||||
<?php if(!empty($m['description'])): ?><p class="description"><?=nl2br(h($m['description']), false)?></p><?php endif; ?>
|
||||
|
|
|
|||
|
|
@ -18,6 +18,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||
function h($s){ return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); }
|
||||
?>
|
||||
<!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>MVLog Login</title><link rel="icon" type="image/png" href="assets/img/moto_travel.png"><link rel="stylesheet" href="style.css"></head><body>
|
||||
<header class="site-header"><div class="brand-wrap"><a class="header-logo" href="index.php" aria-label="MVLog home"><img src="assets/img/moto_travel.png" alt=""></a><a class="brand" href="index.php"><h1>MVLog <span class="admin-word">Admin</span></h1><p>Bubulescu.Org</p></a></div></header>
|
||||
<header class="site-header"><div class="brand-wrap"><a class="header-logo" href="login.php" aria-label="MVLog home"><img src="assets/img/moto_travel.png" alt=""></a><a class="brand" href="login.php"><h1>MVLog <span class="admin-word">Admin</span></h1><p>Bubulescu.Org</p></a></div></header>
|
||||
<main><section><h2>Log in</h2><?php if($err): ?><div class="err"><?=h($err)?></div><?php endif; ?><form method="post" autocomplete="on"><input type="hidden" name="next" value="<?=h($next)?>"><label>Username<input name="user" autocomplete="username" required autofocus></label><label>Password<input type="password" name="password" autocomplete="current-password" required></label><button type="submit">Log in</button></form></section></main>
|
||||
</body></html>
|
||||
|
|
|
|||
2
new.php
2
new.php
|
|
@ -1309,7 +1309,7 @@ $runningJobs = active_worker_jobs($config);
|
|||
<noscript><button type="submit">Apply</button></noscript>
|
||||
</form>
|
||||
<?php if($hasVideo): ?><time class="admin-time<?= $staleLabel ? ' admin-time-stale' : '' ?>" title="<?=h($staleLabel ?: 'Video created at')?>"><?=h(date('d.m.Y H:i', filemtime($displayVideoPath)))?></time><?php endif; ?>
|
||||
</div><div class="admin-actions"><?php if($running): ?><span class="button disabled" title="Rendering now" data-edit-action="1">Rendering</span><?php else: ?><a class="button" href="?id=<?=rawurlencode(read_article_id($d))?>&edit=<?=rawurlencode(basename($d))?>" data-edit-action="1" data-edit-href="?id=<?=rawurlencode(read_article_id($d))?>&edit=<?=rawurlencode(basename($d))?>">Edit</a><?php endif; ?></div></div><h2><?=h($meta['title'] ?: ($info['title'] ?? basename($d)))?></h2><p class="meta"><?php if($meta['date']): ?><span><?=h($meta['date'])?></span><?php endif; ?><?php if($meta['location']): ?><span><?=h($meta['location'])?></span><?php endif; ?><?php if(!$hasVideo): ?><span>No video</span><?php endif; ?><?php if($previewVideo): ?><span>Preview video</span><?php endif; ?></p><?php if(!empty($meta['teaser'])): ?><p class="description-teaser"><?=h((string)$meta['teaser'])?></p><?php endif; ?><?php if($meta['description']): ?><p class="description"><?=nl2br(h($meta['description']), false)?></p><?php endif; ?><?php if(!empty($meta['quote_da'])): ?><p class="description-quote">“<?=h(trim((string)$meta['quote_da'], "\"“”"))?>”</p><?php endif; ?><p class="details"><?=h(basename($d))?> · <?=h($info['file_count'] ?? count(list_files($d)))?> files</p></div></article><?php endforeach; ?></div><?=page_links('edit',$editPage,$editPages)?></section><?php endif; ?>
|
||||
</div><div class="admin-actions"><?php if($running): ?><span class="button disabled" title="Rendering now" data-edit-action="1">Rendering</span><?php else: ?><a class="button" href="?id=<?=rawurlencode(read_article_id($d))?>&edit=<?=rawurlencode(basename($d))?>" data-edit-action="1" data-edit-href="?id=<?=rawurlencode(read_article_id($d))?>&edit=<?=rawurlencode(basename($d))?>">Edit</a><?php endif; ?></div></div><?php $articleIdForLink = read_article_id($d); $titleText = h($meta['title'] ?: ($info['title'] ?? basename($d))); ?><h2><?php if(article_id_is_valid($articleIdForLink)): ?><a href="index.php?id=<?=rawurlencode($articleIdForLink)?>"><?= $titleText ?></a><?php else: ?><?= $titleText ?><?php endif; ?></h2><p class="meta"><?php if($meta['date']): ?><span><?=h($meta['date'])?></span><?php endif; ?><?php if($meta['location']): ?><span><?=h($meta['location'])?></span><?php endif; ?><?php if(!$hasVideo): ?><span>No video</span><?php endif; ?><?php if($previewVideo): ?><span>Preview video</span><?php endif; ?></p><?php if(!empty($meta['teaser'])): ?><p class="description-teaser"><?=h((string)$meta['teaser'])?></p><?php endif; ?><?php if($meta['description']): ?><p class="description"><?=nl2br(h($meta['description']), false)?></p><?php endif; ?><?php if(!empty($meta['quote_da'])): ?><p class="description-quote">“<?=h(trim((string)$meta['quote_da'], "\"“”"))?>”</p><?php endif; ?><p class="details"><?=h(basename($d))?> · <?=h($info['file_count'] ?? count(list_files($d)))?> files</p></div></article><?php endforeach; ?></div><?=page_links('edit',$editPage,$editPages)?></section><?php endif; ?>
|
||||
<?php if($tab==='edit' && $editDir && $editRunning): ?><section><h2>Edit input dir</h2><p><code>in-dir/<?=h(basename($editDir))?></code></p><div class="err">This input directory is <?=h($editStatus)?>. Editing is disabled until the job completes.</div></section><?php endif; ?>
|
||||
<?php if($tab==='edit' && $editDir && !$editRunning): ?><section><h2>Edit input dir</h2><p><code>in-dir/<?=h(basename($editDir))?></code></p><form method="post" enctype="multipart/form-data" id="edit-form"><input type="hidden" name="action" value="update"><input type="hidden" name="dir" value="<?=h(basename($editDir))?>"><input type="hidden" name="id" value="<?=h(ensure_article_id($editDir))?>"><label>Title<input name="title" value="<?=h($editData['title'])?>"></label><label>Teaser<input name="teaser" value="<?=h($editData['teaser'])?>" maxlength="240"></label><label>Danish quote<input name="quote_da" value="<?=h($editData['quote_da'])?>" maxlength="280"></label><label>Date<input name="date" value="<?=h($editData['date'])?>"></label><label>Place<input name="place" value="<?=h($editData['place'])?>"></label><label>Description<textarea name="description" maxlength="5000" data-counter="description-counter-edit"><?=h($editData['description'])?></textarea><small id="description-counter-edit" class="counter"></small></label><label>Add images / videos<input type="file" name="media[]" multiple accept="image/*,video/*"></label><label>Add audio<input type="file" name="audio[]" multiple accept="audio/*"></label><h3>Files and captions</h3><div class="file-list"><?php foreach($editFiles as $f): $ext=strtolower(pathinfo($f, PATHINFO_EXTENSION)); $fileUrl='in-dir/'.rawurlencode(basename($editDir)).'/'.rawurlencode($f); ?><div class="caption-row"><div class="preview"><?php if(in_array($ext,['jpg','jpeg','png','webp','gif'])): ?><img src="<?=h($fileUrl)?>" alt=""><?php elseif(in_array($ext,['mp4','mov','m4v','webm'])): ?><video src="<?=h($fileUrl)?>" controls preload="metadata"></video><a class="download-link" href="<?=h($fileUrl)?>" download>Download</a><?php else: ?><span><?=h(strtoupper($ext ?: 'FILE'))?></span><?php endif; ?></div><div class="caption-fields"><strong><?=h($f)?></strong><?php if(in_array($ext,['jpg','jpeg','png','webp','gif','mp4','mov','m4v','webm'])): ?><input type="hidden" name="caption_files[]" value="<?=h($f)?>"><textarea name="captions[]" placeholder="Optional caption for this file"><?=h($editData['captions'][$f] ?? '')?></textarea><?php if(in_array($ext,['mp4','mov','m4v','webm'])): ?><label class="checkbox-label"><input type="checkbox" name="use_audio_files[]" value="<?=h($f)?>" <?=!empty($editData['video_audio'][$f])?'checked':''?>> <span>Use video file audio</span></label><?php endif; ?><?php else: ?><small>No caption for audio files</small><?php endif; ?></div><div class="file-actions" style="display:flex;gap:.45rem;flex-wrap:wrap;align-self:start"><?php if(in_array($ext,['jpg','jpeg','png','webp','gif'])): ?><button type="button" class="set-thumb-btn" onclick="setThumb(<?=h(json_encode($f))?>)">Set as thumb</button><?php endif; ?><button type="button" onclick="deleteFile(<?=h(json_encode($f))?>)">Remove</button></div></div><?php endforeach; ?></div><button type="submit">Save changes</button></form><form method="post" id="delete-file-form" style="display:none"><input type="hidden" name="action" value="delete_file"><input type="hidden" name="dir" value="<?=h(basename($editDir))?>"><input type="hidden" name="id" value="<?=h(ensure_article_id($editDir))?>"><input type="hidden" name="file" id="delete-file-name" value=""></form><form method="post" onsubmit="return confirm(\'Delete this input directory\?\')" id="delete-dir-form""><input type="hidden" name="action" value="delete_dir"><input type="hidden" name="dir" value="<?=h(basename($editDir))?>"><input type="hidden" name="id" value="<?=h(ensure_article_id($editDir))?>"><label class="checkbox-label"><input type="checkbox" name="delete_output" value="1"> <span>Also delete generated video, if any</span></label><button class="danger" type="submit">Delete input dir</button></form></section><?php endif; ?>
|
||||
<?php if($tab==='new'): ?><section><h2>Add new movie input</h2><form method="post" enctype="multipart/form-data" id="new-form"><input type="hidden" name="action" value="create"><label>Title*<input name="title" required></label><label>Teaser<input name="teaser" maxlength="240"></label><label>Danish quote<input name="quote_da" maxlength="280"></label><label>Date<input name="date" placeholder="2026-05-25"></label><label>Place<input name="place"></label><label>Description<textarea name="description" maxlength="5000" data-counter="description-counter-new"></textarea><small id="description-counter-new" class="counter"></small></label><label>Images / videos*<input type="file" name="media[]" multiple required accept="image/*,video/*"></label><label>Audio (optional)<input type="file" name="audio[]" multiple accept="audio/*"></label><button type="submit">Create input-dir</button></form></section><?php endif; ?>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue