dragon_fire/www/router.php

231 lines
6.5 KiB
PHP

<?php
$data_time_start = microtime(true);
require_once 'vendor/autoload.php';
require_once 'post_adapter.php';
require_once 'fontawesome.php';
use Symfony\Component\Yaml\Yaml;
$SERVER_HOST = $_SERVER['HTTP_HOST'];
if(!preg_match('/^[\w\.]+$/', $SERVER_HOST)) {
die();
}
$SERVER_PREFIX = "https://" . $SERVER_HOST;
$SITE_CONFIG = Yaml::parseFile('secrets/' . $SERVER_HOST . '.config.yml');
$SITE_CONFIG['uri_prefix'] = $SERVER_PREFIX;
$SITE_CONFIG['HTTP_HOST'] = $SERVER_HOST;
$adapter = new PostHandler($SITE_CONFIG);
$loader = new \Twig\Loader\FilesystemLoader(['./templates', './user_content']);
$twig = new \Twig\Environment($loader,['debug' => true]);
$twig->addExtension(new Twig\Extra\Markdown\MarkdownExtension());
use Twig\Extra\Markdown\DefaultMarkdown;
use Twig\Extra\Markdown\MarkdownRuntime;
use Twig\RuntimeLoader\RuntimeLoaderInterface;
function deduce_user_agent() {
$real_agent=$_SERVER['HTTP_USER_AGENT'];
if(preg_match('/(Googlebot|\w*Google\w*)/', $real_agent, $match)) {
return "bot/google/" . $match[1];
}
elseif(preg_match('/(Mozilla|Chrome|Chromium)/', $real_agent, $match)) {
return "user/" . $match[1];
}
else {
return "unidentified";
}
}
function log_and_die($path, $die_code = 0, $referrer = null) {
global $data_time_start;
global $adapter;
$data_time_end = microtime(true);
if(!isset($referrer)) {
$referrer = 'magic';
if(isset($_SERVER['HTTP_REFERER'])) {
$referrer = parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST);
}
}
$adapter->log_post_access($path,
deduce_user_agent(),
$referrer,
$data_time_end - $data_time_start);
die($die_code);
}
$twig->addRuntimeLoader(new class implements RuntimeLoaderInterface {
public function load($class) {
if (MarkdownRuntime::class === $class) {
return new MarkdownRuntime(new DefaultMarkdown());
}
}
});
function render_twig($template, $args = []) {
global $twig;
global $FONT_AWESOME_ARRAY;
$args['fa'] = $FONT_AWESOME_ARRAY;
$post = $args['post'] ?? [];
$settings = $post['settings'] ?? [];
$meta = $post['post_metadata'] ?? [];
$args['banner'] ??= $settings['banners'] ?? [
["src"=> "/static/banner/0.png"],
["src" => "/static/banner/1.png"]
];
$args['og'] = array_merge([
"title" => $meta['title'] ?? "Dergennibble",
"url" => $_SERVER['REQUEST_URI'],
"description" => $meta['description']
?? $settings['description']
?? "The softest spot to find dragons on"
], $args['og'] ?? []);
if(($meta['type'] ?? '') == 'image') {
$args['og']['image'] ??= "https://lucidragons.de" . $post['post_file_dir'];
}
$args['og']['image'] ??= 'https://lucidragons.de' . $args['banner'][0]["src"];
$args['banner'] = json_encode($args['banner']);
echo $twig->render($template, $args);
}
function try_render_post($SURI) {
global $adapter;
$post = $adapter->get_post_by_path($SURI);
if(!$post['found']) {
echo render_twig('post_types/rrror.html',[
"error_code" => '404 Hoard not found!',
"error_description" => "Well, we searched
far and wide for `" . $SURI . "` but
somehow it must have gotten lost... Sorry!",
"post" => array_merge($post, [
"post_metadata" => ["title" => "404 ???"]
])
]);
log_and_die('/404', referrer: ($_SERVER['HTTP_REFERER'] ?? 'magic'));
}
switch($post['post_metadata']['type']) {
case 'directory':
if(preg_match('/^(.*[^\/])((?:#.*)?)$/', $SURI, $match)) {
header('Location: ' . $match[1] . '/' . $match[2]);
die();
}
echo render_twig('post_types/directory.html', [
"post" => $post,
"subposts" => $adapter->get_subposts_by_path($SURI)
]);
break;
case 'text/markdown':
echo render_twig('post_types/markdown.html', [
"post" => $post
]);
break;
case 'image':
echo render_twig('post_types/image.html', [
"post" => $post,
]);
break;
}
}
function generate_website($SURI) {
global $adapter;
global $FONT_AWESOME_ARRAY;
if(preg_match('/^\/api\/admin/', $SURI)) {
header('Content-Type: application/json');
$user_api_key = '';
if(isset($_GET['api_key'])) {
$user_api_key = $_GET['api_key'];
}
if(isset($_POST['api_key'])) {
$user_api_key = $_POST['api_key'];
}
if($user_api_key != file_get_contents('secrets/api_admin_key')) {
http_response_code(401);
echo json_encode([
"authorized" => false
]);
log_and_die('/api/401');
}
if($SURI = '/api/admin/upload') {
$adapter->handle_upload($_POST['post_path'], $_FILES['post_data']['tmp_name']);
echo json_encode(["ok" => true]);
}
} elseif(preg_match('/^\/api/', $SURI)) {
if($SURI == '/api/post_counters') {
header('Content-Type: application/json');
echo json_encode($adapter->get_post_access_counters());
} elseif($SURI == '/api/metrics') {
header('Content-Type: application/line');
echo $adapter->get_post_access_counters_line();
} elseif(preg_match('/^\/api\/posts(.*)$/', $SURI, $match)) {
header('Content-Type: application/json');
echo json_encode($adapter->get_post_by_path($match[1]));
} elseif(preg_match('/^\/api\/subposts(.*)$/', $SURI, $match)) {
header('Content-Type: application/json');
echo json_encode(get_subposts($match[1]));
} elseif($SURI == '/api/upload') {
echo $twig->render('upload.html');
}
} elseif(preg_match('/^\/feed(?:\/(rss|atom)(.*))?$/', $SURI, $match)) {
$feed = $adapter->get_laminas_feed($match[2] ?? '/', $match[1] ?? 'rss');
header('Content-Type: application/xml');
header('Cache-Control: max-age=1800');
header('Etag: W/"' . $SURI . '/' . strtotime($feed['feed_ts']) . '"');
echo $feed['feed'];
} elseif(!preg_match('/^\s*text\/html/', $_SERVER['HTTP_ACCEPT'])) {
header('Location: /raw' . $SURI);
exit(0);
} elseif(true) {
try_render_post($SURI);
}
}
$URL_PATH = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
generate_website($URL_PATH);
log_and_die($URL_PATH);
?>