Add type in functions signatures
This commit is contained in:
parent
7f7bcadb58
commit
973a129079
11 changed files with 59 additions and 59 deletions
30
fn/auth.php
30
fn/auth.php
|
@ -14,47 +14,47 @@ const OPTIONS_PASSWORD = [
|
|||
'threads' => 64,
|
||||
];
|
||||
|
||||
function checkUsernameFormat($username) {
|
||||
function checkUsernameFormat(string $username): void {
|
||||
if (preg_match('/' . USERNAME_REGEX . '/Du', $username) !== 1)
|
||||
output(403, 'Username malformed.');
|
||||
}
|
||||
|
||||
function checkPasswordFormat($password) {
|
||||
function checkPasswordFormat(string $password): void {
|
||||
if (preg_match('/' . PASSWORD_REGEX . '/Du', $password) !== 1)
|
||||
output(403, 'Password malformed.');
|
||||
}
|
||||
|
||||
function hashUsername($username) {
|
||||
function hashUsername(string $username): string {
|
||||
return base64_encode(sodium_crypto_pwhash(32, $username, hex2bin(query('select', 'params', ['name' => 'username_salt'], 'value')[0]), 2**10, 2**14, SODIUM_CRYPTO_PWHASH_ALG_ARGON2ID13));
|
||||
}
|
||||
|
||||
function hashPassword($password) {
|
||||
function hashPassword(string $password): string {
|
||||
return password_hash($password, ALGO_PASSWORD, OPTIONS_PASSWORD);
|
||||
}
|
||||
|
||||
function usernameExists($username) {
|
||||
function usernameExists(string $username): bool {
|
||||
return isset(query('select', 'users', ['username' => $username], 'id')[0]);
|
||||
}
|
||||
|
||||
function checkPassword($id, $password) {
|
||||
function checkPassword(string $id, string $password): bool {
|
||||
return password_verify($password, query('select', 'users', ['id' => $id], 'password')[0]);
|
||||
}
|
||||
|
||||
function outdatedPasswordHash($id) {
|
||||
function outdatedPasswordHash(string $id): bool {
|
||||
return password_needs_rehash(query('select', 'users', ['id' => $id], 'password')[0], ALGO_PASSWORD, OPTIONS_PASSWORD);
|
||||
}
|
||||
|
||||
function changePassword($id, $password) {
|
||||
function changePassword(string $id, string $password): void {
|
||||
DB->prepare('UPDATE users SET password = :password WHERE id = :id')
|
||||
->execute([':password' => hashPassword($password), ':id' => $id]);
|
||||
}
|
||||
|
||||
function stopSession() {
|
||||
function stopSession(): void {
|
||||
if (session_status() === PHP_SESSION_ACTIVE)
|
||||
session_destroy();
|
||||
}
|
||||
|
||||
function logout() {
|
||||
function logout(): never {
|
||||
stopSession();
|
||||
|
||||
header('Clear-Site-Data: "*"');
|
||||
|
@ -62,7 +62,7 @@ function logout() {
|
|||
redir();
|
||||
}
|
||||
|
||||
function setupDisplayUsername($display_username) {
|
||||
function setupDisplayUsername(string $display_username): void {
|
||||
$nonce = random_bytes(24);
|
||||
$key = sodium_crypto_aead_xchacha20poly1305_ietf_keygen();
|
||||
$cyphertext = sodium_crypto_aead_xchacha20poly1305_ietf_encrypt(
|
||||
|
@ -87,7 +87,7 @@ function setupDisplayUsername($display_username) {
|
|||
$_SESSION['display-username-cyphertext'] = $cyphertext;
|
||||
}
|
||||
|
||||
function authDeleteUser($user_id) {
|
||||
function authDeleteUser(string $user_id): void {
|
||||
$user_services = explode(',', query('select', 'users', ['id' => $user_id], 'services')[0]);
|
||||
|
||||
foreach (SERVICES_USER as $service)
|
||||
|
@ -138,7 +138,7 @@ function authDeleteUser($user_id) {
|
|||
query('delete', 'users', ['id' => $user_id]);
|
||||
}
|
||||
|
||||
function rateLimit() {
|
||||
function rateLimit(): void {
|
||||
if (PAGE_METADATA['tokens_account_cost'] ?? 0 > 0)
|
||||
rateLimitAccount(PAGE_METADATA['tokens_account_cost']);
|
||||
|
||||
|
@ -147,7 +147,7 @@ function rateLimit() {
|
|||
}
|
||||
|
||||
const MAX_ACCOUNT_TOKENS = 86400;
|
||||
function rateLimitAccount($requestedTokens) {
|
||||
function rateLimitAccount(int $requestedTokens): int {
|
||||
// Get
|
||||
$userData = query('select', 'users', ['id' => $_SESSION['id']]);
|
||||
$tokens = $userData[0]['bucket_tokens'];
|
||||
|
@ -174,7 +174,7 @@ function rateLimitAccount($requestedTokens) {
|
|||
return $tokens;
|
||||
}
|
||||
|
||||
function rateLimitInstance($requestedTokens) {
|
||||
function rateLimitInstance(int $requestedTokens): void {
|
||||
// Get
|
||||
$tokens = query('select', 'params', ['name' => 'instance_bucket_tokens'], 'value')[0];
|
||||
$bucketLastUpdate = query('select', 'params', ['name' => 'instance_bucket_last_update'], 'value')[0];
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
function output($code, $msg = '', $logs = [''], $data = []) {
|
||||
function output(int $code, string $msg = '', array $logs = [''], array $data = []): never {
|
||||
http_response_code($code);
|
||||
$shortCode = intval($code / 100);
|
||||
if ($shortCode === 5)
|
||||
|
@ -21,7 +21,7 @@ function exescape(array $args, array &$output = NULL, int &$result_code = NULL):
|
|||
return $result_code;
|
||||
}
|
||||
|
||||
function insert($table, $values) {
|
||||
function insert(string $table, array $values): void {
|
||||
$query = 'INSERT INTO "' . $table . '"(';
|
||||
|
||||
foreach ($values as $key => $val) {
|
||||
|
@ -44,7 +44,7 @@ function insert($table, $values) {
|
|||
->execute($values);
|
||||
}
|
||||
|
||||
function query($action, $table, $conditions = [], $column = NULL) {
|
||||
function query(string $action, string $table, array $conditions = [], string $column = NULL): array {
|
||||
|
||||
$query = match ($action) {
|
||||
'select' => 'SELECT *',
|
||||
|
@ -66,7 +66,7 @@ function query($action, $table, $conditions = [], $column = NULL) {
|
|||
return array_column($stmt->fetchAll(PDO::FETCH_ASSOC), $column);
|
||||
}
|
||||
|
||||
function displayIndex() { ?>
|
||||
function displayIndex(): void { ?>
|
||||
<nav>
|
||||
<dl>
|
||||
<?php foreach (PAGES[SERVICE] as $pageId => $page) {
|
||||
|
@ -82,11 +82,11 @@ function displayIndex() { ?>
|
|||
<?php
|
||||
}
|
||||
|
||||
function redirUrl($pageId) {
|
||||
function redirUrl(string $pageId): string {
|
||||
return CONF['common']['prefix'] . '/' . $pageId . '?redir=' . PAGE_URL;
|
||||
}
|
||||
|
||||
function redir($redir_to = NULL) {
|
||||
function redir(string $redir_to = NULL): never {
|
||||
$redir_to ??= $_GET['redir'] ?? NULL;
|
||||
|
||||
if ($redir_to === NULL) {
|
||||
|
@ -100,7 +100,7 @@ function redir($redir_to = NULL) {
|
|||
}
|
||||
|
||||
// PHP rmdir() only works on empty directories
|
||||
function removeDirectory($dir) {
|
||||
function removeDirectory(string $dir): void {
|
||||
$dirObj = new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS);
|
||||
$files = new RecursiveIteratorIterator($dirObj, RecursiveIteratorIterator::CHILD_FIRST);
|
||||
foreach ($files as $file)
|
||||
|
@ -109,7 +109,7 @@ function removeDirectory($dir) {
|
|||
output(500, 'Unable to remove directory.');
|
||||
}
|
||||
|
||||
function equalArrays($a, $b) {
|
||||
function equalArrays(array $a, array $b): bool {
|
||||
return array_diff($a, $b) === [] AND array_diff($b, $a) === [];
|
||||
}
|
||||
|
||||
|
@ -126,12 +126,12 @@ if (time() - query('select', 'params', ['name' => 'secret_key_last_change'], 'va
|
|||
->execute([':last_change' => time()]);
|
||||
}
|
||||
define('SECRET_KEY', hex2bin(query('select', 'params', ['name' => 'secret_key'], 'value')[0]));
|
||||
function getAuthToken() {
|
||||
function getAuthToken(): string {
|
||||
$salt = bin2hex(random_bytes(4));
|
||||
$hash = hash_hmac('sha256', $salt . ($_SESSION['id'] ?? ''), SECRET_KEY);
|
||||
return $salt . '-' . substr($hash, 0, 32);
|
||||
}
|
||||
function checkAuthToken($salt, $hash) {
|
||||
function checkAuthToken(string $salt, string $hash): void {
|
||||
$correctProof = substr(hash_hmac('sha256', $salt . $_SESSION['id'], SECRET_KEY), 0, 32);
|
||||
if (hash_equals($correctProof, $hash) !== true)
|
||||
output(403, _('Wrong proof.'));
|
||||
|
|
14
fn/dns.php
14
fn/dns.php
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
function parseZoneFile($zone_content, $types, $filter_domain = false) {
|
||||
function parseZoneFile(string $zone_content, array $types, bool|string $filter_domain = false): array {
|
||||
$parsed_zone_content = [];
|
||||
foreach (explode(LF, $zone_content) as $zone_line) {
|
||||
if ($zone_line === '' OR str_starts_with($zone_line, ';'))
|
||||
|
@ -46,7 +46,7 @@ function knotcConfExec(array $cmds): void {
|
|||
}
|
||||
}
|
||||
|
||||
function knotcZoneExec(string $zone, array $cmd, string $action = NULL) {
|
||||
function knotcZoneExec(string $zone, array $cmd, string $action = NULL): void {
|
||||
$action = checkAction($action ?? $_POST['action']);
|
||||
|
||||
knotc(['zone-begin', $zone], $output['begin'], $code['begin']);
|
||||
|
@ -66,7 +66,7 @@ function knotcZoneExec(string $zone, array $cmd, string $action = NULL) {
|
|||
}
|
||||
}
|
||||
|
||||
function checkIpFormat($ip) {
|
||||
function checkIpFormat(string $ip): string {
|
||||
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4))
|
||||
return 'A';
|
||||
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6))
|
||||
|
@ -74,24 +74,24 @@ function checkIpFormat($ip) {
|
|||
output(403, _('IP address malformed.'));
|
||||
}
|
||||
|
||||
function checkAbsoluteDomainFormat($domain) { // If the domain must end with a dot
|
||||
function checkAbsoluteDomainFormat(string $domain): void { // If the domain must end with a dot
|
||||
if (!filter_var($domain, FILTER_VALIDATE_DOMAIN) OR preg_match('/^(?=^.{1,254}$)([a-z0-9_-]{1,63}\.){2,127}$/D', $domain) !== 1)
|
||||
output(403, _('Domain malformed.'));
|
||||
}
|
||||
|
||||
function formatEndWithDot($str) {
|
||||
function formatEndWithDot(string $str): string {
|
||||
if (!str_ends_with($str, '.'))
|
||||
$str .= '.';
|
||||
return $str;
|
||||
}
|
||||
|
||||
function formatAbsoluteDomain($domain) {
|
||||
function formatAbsoluteDomain(string $domain): string {
|
||||
$domain = formatEndWithDot(strtolower($domain));
|
||||
checkAbsoluteDomainFormat($domain);
|
||||
return $domain;
|
||||
}
|
||||
|
||||
function checkAction($action) {
|
||||
function checkAction(string $action): string {
|
||||
return match ($action) {
|
||||
'add' => '',
|
||||
'delete' => 'un',
|
||||
|
|
16
fn/ht.php
16
fn/ht.php
|
@ -3,7 +3,7 @@
|
|||
const SUBPATH_REGEX = '^[a-z0-9-]{4,63}$';
|
||||
const ED25519_PUBKEY_REGEX = '^[a-zA-Z0-9/+]{68}$';
|
||||
|
||||
function htSetupUserFs($id) {
|
||||
function htSetupUserFs(string $id): void {
|
||||
// Setup SFTP directory
|
||||
if (mkdir(CONF['ht']['ht_path'] . '/fs/' . $id, 0000) !== true)
|
||||
output(500, 'Can\'t create user directory.');
|
||||
|
@ -42,19 +42,19 @@ function htSetupUserFs($id) {
|
|||
output(500, 'Can\'t create Tor keys directory.');
|
||||
}
|
||||
|
||||
function checkDomainFormat($domain) {
|
||||
function checkDomainFormat(string $domain): void {
|
||||
// If the domain must end without a dot
|
||||
if (!filter_var($domain, FILTER_VALIDATE_DOMAIN) OR !preg_match('/^(?=^.{1,254}$)([a-z0-9_-]{1,63}\.){1,126}[a-z0-9]{1,63}$/D', $domain))
|
||||
output(403, _('Domain malformed.'));
|
||||
}
|
||||
|
||||
function formatDomain($domain) {
|
||||
function formatDomain(string $domain): string {
|
||||
$domain = rtrim(strtolower($domain), '.');
|
||||
checkDomainFormat($domain);
|
||||
return $domain;
|
||||
}
|
||||
|
||||
function listFsDirs($username) {
|
||||
function listFsDirs(string $username): array {
|
||||
if ($username === '')
|
||||
return [];
|
||||
$absoluteDirs = glob(CONF['ht']['ht_path'] . '/fs/' . $username . '/*/', GLOB_ONLYDIR);
|
||||
|
@ -65,7 +65,7 @@ function listFsDirs($username) {
|
|||
return $dirs;
|
||||
}
|
||||
|
||||
function addSite($username, $siteDir, $address, $type) {
|
||||
function addSite(string $username, string $siteDir, string $address, string $type): void {
|
||||
insert('sites', [
|
||||
'username' => $username,
|
||||
'site_dir' => $siteDir,
|
||||
|
@ -75,7 +75,7 @@ function addSite($username, $siteDir, $address, $type) {
|
|||
]);
|
||||
}
|
||||
|
||||
function dirsStatuses($type) {
|
||||
function dirsStatuses(string $type): array {
|
||||
if (isset($_SESSION['id']) !== true)
|
||||
return [];
|
||||
$dbDirs = query('select', 'sites', [
|
||||
|
@ -88,7 +88,7 @@ function dirsStatuses($type) {
|
|||
return $dirs;
|
||||
}
|
||||
|
||||
function htRelativeSymlink($target, $name) {
|
||||
function htRelativeSymlink(string $target, string $name): void {
|
||||
chdir(pathinfo($name)['dirname']);
|
||||
$symlink = symlink($target, pathinfo($name)['basename']);
|
||||
chdir(ROOT_PATH);
|
||||
|
@ -96,7 +96,7 @@ function htRelativeSymlink($target, $name) {
|
|||
output(500, 'Unable to create symlink.');
|
||||
}
|
||||
|
||||
function htDeleteSite($address, $type, $user_id) {
|
||||
function htDeleteSite(string $address, string $type, string $user_id): void {
|
||||
|
||||
if ($type === 'onion') {
|
||||
$dir = query('select', 'sites', [
|
||||
|
|
|
@ -17,7 +17,7 @@ const ALLOWED_TYPES = ['AAAA', 'A', 'TXT', 'SRV', 'MX', 'SVCB', 'HTTPS', 'NS', '
|
|||
|
||||
const ZONE_MAX_CHARACTERS = 10000;
|
||||
|
||||
function nsParseCommonRequirements() {
|
||||
function nsParseCommonRequirements(): array {
|
||||
nsCheckZonePossession($_POST['zone']);
|
||||
|
||||
if (($_POST['subdomain'] === '') OR ($_POST['subdomain'] === '@'))
|
||||
|
@ -35,20 +35,20 @@ function nsParseCommonRequirements() {
|
|||
return $values;
|
||||
}
|
||||
|
||||
function nsListUserZones() {
|
||||
function nsListUserZones(): array {
|
||||
if (isset($_SESSION['id']))
|
||||
return query('select', 'zones', ['username' => $_SESSION['id']], 'zone');
|
||||
return [];
|
||||
}
|
||||
|
||||
function nsCheckZonePossession($zone) {
|
||||
function nsCheckZonePossession(string $zone): void {
|
||||
checkAbsoluteDomainFormat($zone);
|
||||
|
||||
if (!in_array($zone, nsListUserZones(), true))
|
||||
output(403, 'You don\'t own this zone on the name server.');
|
||||
}
|
||||
|
||||
function nsDeleteZone($zone, $user_id) {
|
||||
function nsDeleteZone(string $zone, string $user_id): void {
|
||||
// Remove from Knot configuration
|
||||
knotcConfExec([['conf-unset', 'zone[' . $zone . ']']]);
|
||||
|
||||
|
|
|
@ -2,18 +2,18 @@
|
|||
|
||||
const SUBDOMAIN_REGEX = '^(?!\-)(?!..\-\-)[a-z0-9-]{4,63}(?<!\-)$';
|
||||
|
||||
function regListUserDomains() {
|
||||
function regListUserDomains(): array {
|
||||
if (isset($_SESSION['id']))
|
||||
return query('select', 'registry', ['username' => $_SESSION['id']], 'domain');
|
||||
return [];
|
||||
}
|
||||
|
||||
function regCheckDomainPossession($domain) {
|
||||
function regCheckDomainPossession(string $domain): void {
|
||||
if (in_array($domain, regListUserDomains(), true) !== true)
|
||||
output(403, 'You don\'t own this domain on the registry.');
|
||||
}
|
||||
|
||||
function regDeleteDomain($domain, $user_id) {
|
||||
function regDeleteDomain(string $domain, string $user_id): void {
|
||||
// Delete domain from registry file
|
||||
$path = CONF['reg']['suffixes_path'] . '/' . regParseDomain($domain)['suffix'] . 'zone';
|
||||
$content = file_get_contents($path);
|
||||
|
@ -46,7 +46,7 @@ function regDeleteDomain($domain, $user_id) {
|
|||
}
|
||||
}
|
||||
|
||||
function regParseDomain($domain) {
|
||||
function regParseDomain(string $domain): array {
|
||||
$parts = explode('.', $domain, 2);
|
||||
$subdomain = $parts[0];
|
||||
$suffix = $parts[1];
|
||||
|
|
2
init.php
2
init.php
|
@ -5,7 +5,7 @@ set_error_handler(function ($level, $message, $file = '', $line = 0) {
|
|||
throw new ErrorException($message, 0, $level, $file, $line);
|
||||
});
|
||||
set_exception_handler(function ($e) {
|
||||
error_log($e);
|
||||
error_log($e->getMessage());
|
||||
http_response_code(500);
|
||||
echo '<h1>Error</h1>An error occured.';
|
||||
});
|
||||
|
|
|
@ -18,7 +18,7 @@ if (preg_match('/^;; Flags: qr rd ra ad;/Dm', implode("\n", $output)) !== 1)
|
|||
|
||||
define('COOKIE_FILE', sys_get_temp_dir() . '/cookie-' . bin2hex(random_bytes(16)) . '.txt');
|
||||
|
||||
function curlTest($address, $post = [], $tor = false) {
|
||||
function curlTest(string $address, array $post = [], bool $tor = false): string {
|
||||
$req = curl_init();
|
||||
curl_setopt($req, CURLOPT_RETURNTRANSFER, true);
|
||||
|
||||
|
@ -85,7 +85,7 @@ curlTest('/auth/username', [
|
|||
|
||||
echo 'Created account with username "' . $username . '" and password "' . $password . '".' . LF;
|
||||
|
||||
function testReg() {
|
||||
function testReg(): string {
|
||||
$subdomain = bin2hex(random_bytes(16));
|
||||
|
||||
curlTest('/reg/register', [
|
||||
|
@ -119,7 +119,7 @@ function testReg() {
|
|||
return $domain;
|
||||
}
|
||||
|
||||
function testNs($domain) {
|
||||
function testNs(string $domain): void {
|
||||
foreach (CONF['ns']['servers'] as $ns)
|
||||
curlTest('/reg/ns', [
|
||||
'action' => 'add',
|
||||
|
@ -178,7 +178,7 @@ function testNs($domain) {
|
|||
exit('Error: /ns/edit: AAAA record not set' . LF);
|
||||
}
|
||||
|
||||
function testHt($username, $password) {
|
||||
function testHt(string $username, string $password): void {
|
||||
define('TEST_CONTENT', 'test-' . bin2hex(random_bytes(16)));
|
||||
|
||||
file_put_contents(sys_get_temp_dir() . '/index.html', TEST_CONTENT);
|
||||
|
|
|
@ -53,7 +53,7 @@ if ($blocked OR $registration_data !== [])
|
|||
if ($_POST['action'] !== 'register')
|
||||
message($message . ' ✔️ ' . _('This domain is open to registration!'));
|
||||
|
||||
function message($message) {
|
||||
function message(string $message): never {
|
||||
output(200, data: [
|
||||
'message' => '<p>' . $message . '</p>',
|
||||
'domain' => htmlspecialchars($_POST['subdomain']),
|
||||
|
|
|
@ -11,7 +11,7 @@ define('PAGE_ADDRESS', $pageAddress . ((substr($pageAddress, -1) === '/' OR $pag
|
|||
define('PAGE_LINEAGE', explode('/', PAGE_ADDRESS));
|
||||
define('SERVICE', dirname(PAGE_ADDRESS));
|
||||
|
||||
function getPageInformations($pages, $pageElements) {
|
||||
function getPageInformations(array $pages, array $pageElements): array {
|
||||
if (!isset($pages['index']) OR $pageElements[0] === 'index')
|
||||
return [
|
||||
'titles_lineage' => [$pages[$pageElements[0]]['title'] ?? false],
|
||||
|
@ -44,7 +44,7 @@ if (in_array($_SERVER['SERVER_NAME'], CONF['common']['public_domains'], true) !=
|
|||
define('SERVER_NAME', $_SERVER['SERVER_NAME']);
|
||||
|
||||
const SESSION_COOKIE_NAME = 'servnest-session-key';
|
||||
function startSession() {
|
||||
function startSession(): void {
|
||||
session_start([
|
||||
'name' => SESSION_COOKIE_NAME,
|
||||
'sid_length' => 64,
|
||||
|
@ -94,7 +94,7 @@ if (isset($_SESSION['id'])) {
|
|||
}
|
||||
}
|
||||
|
||||
function displayFinalMessage($data) {
|
||||
function displayFinalMessage(?array $data): void {
|
||||
if (isset($data['final_message'])) {
|
||||
echo $data['final_message'];
|
||||
unset($data['final_message']);
|
||||
|
@ -118,7 +118,7 @@ if ($_POST !== []) {
|
|||
require ROOT_PATH . '/pg-act/' . PAGE_ADDRESS . '.php';
|
||||
}
|
||||
|
||||
function displayPage($data) {
|
||||
function displayPage(?array $data): never {
|
||||
require ROOT_PATH . '/view.php';
|
||||
exit();
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ const DEBUG = false;
|
|||
|
||||
require 'init.php';
|
||||
|
||||
function deny($reason) {
|
||||
function deny(string $reason): never {
|
||||
!DEBUG or file_put_contents(ROOT_PATH . '/db/debug.txt', ob_get_contents() . $reason . LF);
|
||||
http_response_code(403);
|
||||
exit();
|
||||
|
|
Loading…
Reference in a new issue