151 lines
5.8 KiB
PHP
151 lines
5.8 KiB
PHP
<?php
|
|
define('CONF', parse_ini_file(__DIR__ . '/config.ini', true, INI_SCANNER_TYPED));
|
|
|
|
foreach (array_diff(scandir(CONF['common']['root_path'] . '/fn'), array('..', '.')) as $file)
|
|
require CONF['common']['root_path'] . '/fn/' . $file;
|
|
require 'pages.php';
|
|
|
|
define('DB_PATH', CONF['common']['root_path'] . '/db/niver.db');
|
|
|
|
const LF = "\n";
|
|
|
|
const PLACEHOLDER_DOMAIN = 'example'; // From RFC2606: Reserved Top Level DNS Names > 2. TLDs for Testing, & Documentation Examples
|
|
const PLACEHOLDER_IPV6 = '2001:db8::3'; // From RFC3849: IPv6 Address Prefix Reserved for Documentation
|
|
const PLACEHOLDER_IPV4 = '203.0.113.42'; // From RFC5737: IPv4 Address Blocks Reserved for Documentation
|
|
|
|
if ($_SERVER['REQUEST_URI'] === '/sftpgo-auth.php')
|
|
return;
|
|
|
|
$pageAddress = substr($_SERVER['REQUEST_URI'], strlen(CONF['common']['prefix']) + 1);
|
|
if (strpos($pageAddress, '?') !== false) {
|
|
parse_str(substr($pageAddress, strpos($pageAddress, '?') + 1), $_GET);
|
|
$pageAddress = substr($pageAddress, 0, strpos($pageAddress, '?'));
|
|
}
|
|
define('PAGE_URL', $pageAddress);
|
|
define('PAGE_ADDRESS', $pageAddress . ((substr($pageAddress, -1) === '/' OR $pageAddress === '') ? 'index' : ''));
|
|
define('PAGE_LINEAGE', explode('/', PAGE_ADDRESS));
|
|
define('SERVICE', dirname(PAGE_ADDRESS));
|
|
define('PAGE', basename(PAGE_ADDRESS, '.php'));
|
|
|
|
function getPageInformations($pages, $pageElements) {
|
|
if (!isset($pages['index']) OR $pageElements[0] === 'index')
|
|
return [
|
|
'titles_lineage' => [$pages[$pageElements[0]]['title'] ?? false],
|
|
'page_metadata' => $pages[$pageElements[0]] ?? NULL
|
|
];
|
|
$result = $pages['index']['title'];
|
|
if (!isset($pageElements[1]))
|
|
unset($pages['index']);
|
|
else
|
|
$pages = $pages[array_shift($pageElements)] ?? false;
|
|
$results = getPageInformations($pages, $pageElements);
|
|
$results['titles_lineage'][] = $result;
|
|
return $results;
|
|
}
|
|
$pageInformations = getPageInformations(PAGES, PAGE_LINEAGE);
|
|
define('TITLES_LINEAGE', array_reverse($pageInformations['titles_lineage']));
|
|
define('PAGE_METADATA', $pageInformations['page_metadata']);
|
|
|
|
if (!TITLES_LINEAGE[array_key_last(TITLES_LINEAGE)]) {
|
|
http_response_code(404);
|
|
exit('Page not found.');
|
|
}
|
|
|
|
const SESSION_COOKIE_NAME = 'niver-session-key';
|
|
if (
|
|
isset($_COOKIE[SESSION_COOKIE_NAME]) // Resume session
|
|
OR
|
|
(isset($_POST['username']) AND in_array(PAGE_URL, ['auth/login', 'auth/register'])) // Start new session
|
|
) {
|
|
session_start([
|
|
'name' => SESSION_COOKIE_NAME,
|
|
'sid_length' => 64,
|
|
'sid_bits_per_character' => 6,
|
|
'cookie_secure' => true,
|
|
'cookie_httponly' => true,
|
|
'cookie_samesite' => 'Strict',
|
|
'cookie_path' => CONF['common']['prefix'] . '/',
|
|
'cookie_lifetime' => 432000, // = 60*60*24*5 = 5 days
|
|
'gc_maxlifetime' => 10800,
|
|
'use_strict_mode' => true,
|
|
'use_cookies' => true,
|
|
'use_only_cookies' => true,
|
|
]);
|
|
}
|
|
|
|
?>
|
|
<!DOCTYPE html>
|
|
<html lang="fr"<?php if (!empty(SERVICE)) echo ' class="' . SERVICE . '"'; ?>>
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<title><?php
|
|
foreach(array_reverse(TITLES_LINEAGE) as $id => $title)
|
|
echo strip_tags($title) . (array_key_last(TITLES_LINEAGE) === $id ? '' : ' < ');
|
|
?></title>
|
|
<?php
|
|
foreach (glob('css/*.css') as $cssPath)
|
|
echo ' <link type="text/css" rel="stylesheet" media="screen" href="' . CONF['common']['prefix'] . '/' . $cssPath . '">' . LF;
|
|
?>
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
</head>
|
|
<body>
|
|
<header>
|
|
<p>
|
|
<?php if (isset($_SESSION['id'])) { ?>
|
|
<?= ($_SESSION['type'] === 'trusted') ? '<span title="Compte confiancé">👤 </span>' : '<span title="Compte de test">⏳ </span>' ?><strong><?= $_SESSION['display-username'] ?></strong> <a class="auth" href="<?= CONF['common']['prefix'] ?>/auth/logout">Se déconnecter</a>
|
|
<?php } else { ?>
|
|
<span aria-hidden="true">👻 </span><em>Anonyme</em> <a class="auth" href="<?= redirUrl('auth/login') ?>">Se connecter</a>
|
|
<?php } ?>
|
|
</p>
|
|
<nav>
|
|
<?php
|
|
foreach (TITLES_LINEAGE as $id => $title) {
|
|
$lastTitle = (TITLES_LINEAGE[array_key_last(TITLES_LINEAGE)] === $title);
|
|
echo '<ul><li>' . ($lastTitle ? '<h1>' : '') . '<a' . (($id === 0) ? ' class="niver"' : '') . ' href="' . CONF['common']['prefix'] . ($lastTitle ? '/' . PAGE_URL : '/' . implode('/', array_slice(PAGE_LINEAGE, 0, $id)) . (($lastTitle OR $id === 0) ? '' : '/')) . '">' . $title . '</a>' . ($lastTitle ? '</h1>' : '') . LF;
|
|
}
|
|
echo str_repeat('</li></ul>', count(TITLES_LINEAGE));
|
|
?>
|
|
|
|
</nav>
|
|
</header>
|
|
<main>
|
|
<?php
|
|
|
|
if (in_array(SERVICE, ['reg', 'ns', 'ht']) AND CONF[SERVICE]['enabled'] !== true)
|
|
output(403, 'Ce service est désactivé.');
|
|
|
|
// Protect against cross-site request forgery if a POST request is received
|
|
if ($_POST !== []) {
|
|
if (isset($_SERVER['HTTP_SEC_FETCH_SITE']) !== true)
|
|
output(403, 'The <code>Sec-Fetch-Site</code> HTTP header is required when submitting a POST request to prevent Cross-Site Request Forgery (<abbr>CSRF</abbr>).');
|
|
if ($_SERVER['HTTP_SEC_FETCH_SITE'] !== 'same-origin')
|
|
output(403, 'The <code>Sec-Fetch-Site</code> HTTP header must be <code>same-origin</code> when submitting a POST request to prevent Cross-Site Request Forgery (<abbr>CSRF</abbr>).');
|
|
}
|
|
|
|
if (isset($_SERVER['SERVER_NAME']) !== true)
|
|
output(500, 'Missing $_SERVER[\'SERVER_NAME\']');
|
|
if (in_array($_SERVER['SERVER_NAME'], CONF['common']['public_domains'], true) !== true)
|
|
output(500, 'The current server name is not allowed in configuration.');
|
|
define('SERVER_NAME', $_SERVER['SERVER_NAME']);
|
|
|
|
function displayFinalMessage() {
|
|
global $final_message;
|
|
echo $final_message ?? '';
|
|
$final_message = NULL;
|
|
}
|
|
|
|
function executePage() {
|
|
require 'pages/' . PAGE_ADDRESS . '.php';
|
|
|
|
displayFinalMessage();
|
|
?>
|
|
</main>
|
|
<footer>
|
|
<small><a rel="external" href="https://code.antopie.org/niver/niver" class="niver">Code source</a> sous <abbr title="Cooperative Nonviolent Public License No Attribution version 7 ou plus">CNPL-NAv7+</abbr>.</small>
|
|
</footer>
|
|
</body>
|
|
</html>
|
|
<?php
|
|
exit();
|
|
}
|
|
executePage();
|