cool new CSRF protection system
This commit is contained in:
parent
5097cb812a
commit
c21d1b65ac
25 changed files with 276 additions and 124 deletions
|
@ -67,6 +67,26 @@ body {
|
||||||
&--legacy {
|
&--legacy {
|
||||||
--background-color: #fbeeff;
|
--background-color: #fbeeff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&--bg-blend {
|
||||||
|
background-blend-mode: multiply;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*&--bg-slide {
|
||||||
|
}*/
|
||||||
|
|
||||||
|
&--bg-cover {
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--bg-stretch {
|
||||||
|
background-size: 100% 100%;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--bg-tile {
|
||||||
|
background-repeat: repeat;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Input elements
|
// Input elements
|
||||||
|
|
|
@ -30,6 +30,7 @@ require_once 'src/audit_log.php';
|
||||||
require_once 'src/changelog.php';
|
require_once 'src/changelog.php';
|
||||||
require_once 'src/colour.php';
|
require_once 'src/colour.php';
|
||||||
require_once 'src/comments.php';
|
require_once 'src/comments.php';
|
||||||
|
require_once 'src/csrf.php';
|
||||||
require_once 'src/general.php';
|
require_once 'src/general.php';
|
||||||
require_once 'src/git.php';
|
require_once 'src/git.php';
|
||||||
require_once 'src/manage.php';
|
require_once 'src/manage.php';
|
||||||
|
@ -261,10 +262,11 @@ MIG;
|
||||||
tpl_add_function('vsprintf', true);
|
tpl_add_function('vsprintf', true);
|
||||||
tpl_add_function('perms_check', true);
|
tpl_add_function('perms_check', true);
|
||||||
tpl_add_function('bg_settings', true, 'user_background_settings_strings');
|
tpl_add_function('bg_settings', true, 'user_background_settings_strings');
|
||||||
|
tpl_add_function('csrf', true, 'csrf_html');
|
||||||
|
|
||||||
tpl_add_function('git_commit_hash');
|
tpl_add_function('git_commit_hash');
|
||||||
tpl_add_function('git_branch');
|
tpl_add_function('git_branch');
|
||||||
tpl_add_function('csrf_token', false, 'tmp_csrf_token');
|
tpl_add_function('csrf_token');
|
||||||
tpl_add_function('startup_time', false, function (float $time = MSZ_STARTUP) {
|
tpl_add_function('startup_time', false, function (float $time = MSZ_STARTUP) {
|
||||||
return microtime(true) - $time;
|
return microtime(true) - $time;
|
||||||
});
|
});
|
||||||
|
@ -301,6 +303,8 @@ MIG;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
csrf_init('soapsoapsoap', empty($userDisplayInfo) ? ip_remote_address() : $_COOKIE['msz_sid']);
|
||||||
|
|
||||||
$privateInfo = $app->getPrivateInfo();
|
$privateInfo = $app->getPrivateInfo();
|
||||||
|
|
||||||
if (!$misuzuBypassLockdown && $privateInfo['enabled'] && !$app->hasActiveSession()) {
|
if (!$misuzuBypassLockdown && $privateInfo['enabled'] && !$app->hasActiveSession()) {
|
||||||
|
|
|
@ -44,7 +44,7 @@ switch ($authMode) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($_GET['s']) && tmp_csrf_verify($_GET['s'])) {
|
if (csrf_verify('logout', $_GET['s'] ?? '')) {
|
||||||
set_cookie_m('uid', '', -3600);
|
set_cookie_m('uid', '', -3600);
|
||||||
set_cookie_m('sid', '', -3600);
|
set_cookie_m('sid', '', -3600);
|
||||||
user_session_delete($app->getSessionId());
|
user_session_delete($app->getSessionId());
|
||||||
|
@ -159,6 +159,11 @@ switch ($authMode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
while ($isSubmission) {
|
while ($isSubmission) {
|
||||||
|
if (!csrf_verify('passforgot', $_POST['csrf'] ?? '')) {
|
||||||
|
tpl_var('auth_forgot_error', 'Possible request forgery detected, refresh and try again.');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (empty($authEmail)) {
|
if (empty($authEmail)) {
|
||||||
tpl_var('auth_forgot_error', 'Please enter an e-mail address.');
|
tpl_var('auth_forgot_error', 'Please enter an e-mail address.');
|
||||||
break;
|
break;
|
||||||
|
@ -257,6 +262,11 @@ MSG;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!csrf_verify('login', $_POST['csrf'] ?? '')) {
|
||||||
|
$authLoginError = 'Possible request forgery detected, refresh and try again.';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
$getUser = Database::prepare('
|
$getUser = Database::prepare('
|
||||||
SELECT `user_id`, `password`
|
SELECT `user_id`, `password`
|
||||||
FROM `msz_users`
|
FROM `msz_users`
|
||||||
|
@ -340,6 +350,11 @@ MSG;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!csrf_verify('register', $_POST['csrf'] ?? '')) {
|
||||||
|
$authRegistrationError = 'Possible request forgery detected, refresh and try again.';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
$checkSpamBot = mb_strtolower($_POST['auth']['meow'] ?? '');
|
$checkSpamBot = mb_strtolower($_POST['auth']['meow'] ?? '');
|
||||||
$spamBotValid = [
|
$spamBotValid = [
|
||||||
'19', '21', 'nineteen', 'nine-teen', 'nine teen', 'twentyone', 'twenty-one', 'twenty one',
|
'19', '21', 'nineteen', 'nine-teen', 'nine teen', 'twentyone', 'twenty-one', 'twenty one',
|
||||||
|
|
|
@ -15,7 +15,7 @@ if ($isXHR) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!tmp_csrf_verify($_REQUEST['csrf'] ?? '')) {
|
if (!csrf_verify('comments', $_REQUEST['csrf'] ?? '')) {
|
||||||
echo render_info_or_json($isXHR, "Couldn't verify this request, please refresh the page and try again.", 403);
|
echo render_info_or_json($isXHR, "Couldn't verify this request, please refresh the page and try again.", 403);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,7 +83,7 @@ if (!forum_may_have_topics($forum['forum_type'])) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($postRequest) {
|
if ($postRequest) {
|
||||||
if (!tmp_csrf_verify($_POST['csrf'] ?? '')) {
|
if (!csrf_verify('settings', $_POST['csrf'] ?? '')) {
|
||||||
echo 'Could not verify request.';
|
echo 'Could not verify request.';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,7 +73,7 @@ switch ($_GET['v'] ?? null) {
|
||||||
|
|
||||||
$changeId = (int)($_GET['c'] ?? 0);
|
$changeId = (int)($_GET['c'] ?? 0);
|
||||||
|
|
||||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && tmp_csrf_verify($_POST['csrf'] ?? '')) {
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && csrf_verify('changelog_add', $_POST['csrf'] ?? '')) {
|
||||||
if (!empty($_POST['change']) && is_array($_POST['change'])) {
|
if (!empty($_POST['change']) && is_array($_POST['change'])) {
|
||||||
if ($changeId > 0) {
|
if ($changeId > 0) {
|
||||||
$postChange = Database::prepare('
|
$postChange = Database::prepare('
|
||||||
|
@ -260,7 +260,7 @@ switch ($_GET['v'] ?? null) {
|
||||||
|
|
||||||
$tagId = (int)($_GET['t'] ?? 0);
|
$tagId = (int)($_GET['t'] ?? 0);
|
||||||
|
|
||||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && tmp_csrf_verify($_POST['csrf'] ?? '')) {
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && csrf_verify('changelog_tag', $_POST['csrf'] ?? '')) {
|
||||||
if (!empty($_POST['tag']) && is_array($_POST['tag'])) {
|
if (!empty($_POST['tag']) && is_array($_POST['tag'])) {
|
||||||
if ($tagId > 0) {
|
if ($tagId > 0) {
|
||||||
$updateTag = Database::prepare('
|
$updateTag = Database::prepare('
|
||||||
|
@ -325,7 +325,7 @@ switch ($_GET['v'] ?? null) {
|
||||||
|
|
||||||
$actionId = (int)($_GET['a'] ?? 0);
|
$actionId = (int)($_GET['a'] ?? 0);
|
||||||
|
|
||||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && tmp_csrf_verify($_POST['csrf'] ?? '')) {
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && csrf_verify('changelog_action', $_POST['csrf'] ?? '')) {
|
||||||
if (!empty($_POST['action']) && is_array($_POST['action'])) {
|
if (!empty($_POST['action']) && is_array($_POST['action'])) {
|
||||||
if ($actionId > 0) {
|
if ($actionId > 0) {
|
||||||
$updateAction = Database::prepare('
|
$updateAction = Database::prepare('
|
||||||
|
|
|
@ -113,7 +113,7 @@ switch ($_GET['v'] ?? null) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($isPostRequest) {
|
if ($isPostRequest) {
|
||||||
if (!tmp_csrf_verify($_POST['csrf'] ?? '')) {
|
if (!csrf_verify('users_edit', $_POST['csrf'] ?? '')) {
|
||||||
echo 'csrf err';
|
echo 'csrf err';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -303,7 +303,7 @@ switch ($_GET['v'] ?? null) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($isPostRequest) {
|
if ($isPostRequest) {
|
||||||
if (!tmp_csrf_verify($_POST['csrf'] ?? '')) {
|
if (!csrf_verify('users_role', $_POST['csrf'] ?? '')) {
|
||||||
echo 'csrf err';
|
echo 'csrf err';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,7 @@ $avatarProps = $app->getAvatarProps();
|
||||||
$backgroundProps = $app->getBackgroundProps();
|
$backgroundProps = $app->getBackgroundProps();
|
||||||
|
|
||||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
if (!tmp_csrf_verify($_POST['csrf'] ?? '')) {
|
if (!csrf_verify('settings', $_POST['csrf'] ?? '')) {
|
||||||
$settingsErrors[] = MSZ_TMP_USER_ERROR_STRINGS['csrf'];
|
$settingsErrors[] = MSZ_TMP_USER_ERROR_STRINGS['csrf'];
|
||||||
} else {
|
} else {
|
||||||
if (!empty($_POST['profile']) && is_array($_POST['profile'])) {
|
if (!empty($_POST['profile']) && is_array($_POST['profile'])) {
|
||||||
|
@ -156,6 +156,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
switch ($_POST['background']['mode'] ?? '') {
|
switch ($_POST['background']['mode'] ?? '') {
|
||||||
case 'delete':
|
case 'delete':
|
||||||
user_background_delete($settingsUserId);
|
user_background_delete($settingsUserId);
|
||||||
|
user_background_set_settings($settingsUserId, MSZ_USER_BACKGROUND_ATTACHMENT_NONE);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'upload':
|
case 'upload':
|
||||||
|
@ -164,40 +165,55 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty($_FILES['background'])
|
if (empty($_POST['background'])
|
||||||
|| !is_array($_FILES['background'])
|
|| !is_array($_POST['background'])) {
|
||||||
|| empty($_FILES['background']['name']['file'])) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($_FILES['background']['error']['file'] !== UPLOAD_ERR_OK) {
|
if (!empty($_FILES['background']['name']['file'])) {
|
||||||
$settingsErrors[] = sprintf(
|
if ($_FILES['background']['error']['file'] !== UPLOAD_ERR_OK) {
|
||||||
MSZ_TMP_USER_ERROR_STRINGS['avatar']['upload'][$_FILES['background']['error']['file']]
|
$settingsErrors[] = sprintf(
|
||||||
?? MSZ_TMP_USER_ERROR_STRINGS['avatar']['upload']['_'],
|
MSZ_TMP_USER_ERROR_STRINGS['avatar']['upload'][$_FILES['background']['error']['file']]
|
||||||
$_FILES['background']['error']['file'],
|
?? MSZ_TMP_USER_ERROR_STRINGS['avatar']['upload']['_'],
|
||||||
byte_symbol($backgroundProps['max_size'], true),
|
$_FILES['background']['error']['file'],
|
||||||
$backgroundProps['max_width'],
|
byte_symbol($backgroundProps['max_size'], true),
|
||||||
$backgroundProps['max_height']
|
$backgroundProps['max_width'],
|
||||||
|
$backgroundProps['max_height']
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$setBackground = user_background_set_from_path(
|
||||||
|
$settingsUserId,
|
||||||
|
$_FILES['background']['tmp_name']['file'],
|
||||||
|
$backgroundProps
|
||||||
);
|
);
|
||||||
break;
|
|
||||||
|
if ($setBackground !== MSZ_USER_BACKGROUND_NO_ERRORS) {
|
||||||
|
$settingsErrors[] = sprintf(
|
||||||
|
MSZ_TMP_USER_ERROR_STRINGS['avatar']['set'][$setBackground]
|
||||||
|
?? MSZ_TMP_USER_ERROR_STRINGS['avatar']['set']['_'],
|
||||||
|
$setBackground,
|
||||||
|
byte_symbol($backgroundProps['max_size'], true),
|
||||||
|
$backgroundProps['max_width'],
|
||||||
|
$backgroundProps['max_height']
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$setBackground = user_background_set_from_path(
|
$backgroundSettings = in_array($_POST['background']['attach'] ?? '', MSZ_USER_BACKGROUND_ATTACHMENTS_NAMES)
|
||||||
$settingsUserId,
|
? array_flip(MSZ_USER_BACKGROUND_ATTACHMENTS_NAMES)[$_POST['background']['attach']]
|
||||||
$_FILES['background']['tmp_name']['file'],
|
: MSZ_USER_BACKGROUND_ATTACHMENTS[0];
|
||||||
$backgroundProps
|
|
||||||
);
|
|
||||||
|
|
||||||
if ($setBackground !== MSZ_USER_BACKGROUND_NO_ERRORS) {
|
if (!empty($_POST['background']['attr']['blend'])) {
|
||||||
$settingsErrors[] = sprintf(
|
$backgroundSettings |= MSZ_USER_BACKGROUND_ATTRIBUTE_BLEND;
|
||||||
MSZ_TMP_USER_ERROR_STRINGS['avatar']['set'][$setBackground]
|
|
||||||
?? MSZ_TMP_USER_ERROR_STRINGS['avatar']['set']['_'],
|
|
||||||
$setBackground,
|
|
||||||
byte_symbol($backgroundProps['max_size'], true),
|
|
||||||
$backgroundProps['max_width'],
|
|
||||||
$backgroundProps['max_height']
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!empty($_POST['background']['attr']['slide'])) {
|
||||||
|
$backgroundSettings |= MSZ_USER_BACKGROUND_ATTRIBUTE_SLIDE;
|
||||||
|
}
|
||||||
|
|
||||||
|
user_background_set_settings($settingsUserId, $backgroundSettings);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -220,7 +236,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
} elseif ((int)$session['user_id'] !== $settingsUserId) {
|
} elseif ((int)$session['user_id'] !== $settingsUserId) {
|
||||||
$settingsErrors[] = 'You may only end your own sessions.';
|
$settingsErrors[] = 'You may only end your own sessions.';
|
||||||
} elseif ((int)$session['session_id'] === $app->getSessionId()) {
|
} elseif ((int)$session['session_id'] === $app->getSessionId()) {
|
||||||
header('Location: /auth.php?m=logout&s=' . tmp_csrf_token());
|
header('Location: /auth.php?m=logout&s=' . csrf_token('logout'));
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
user_session_delete($session['session_id']);
|
user_session_delete($session['session_id']);
|
||||||
|
@ -334,11 +350,17 @@ switch ($settingsMode) {
|
||||||
|
|
||||||
$getAccountInfo = Database::prepare(sprintf(
|
$getAccountInfo = Database::prepare(sprintf(
|
||||||
'
|
'
|
||||||
SELECT %s, `email`, `user_about_content`, `user_about_parser`
|
SELECT
|
||||||
|
%1$s, `email`, `user_about_content`, `user_about_parser`,
|
||||||
|
`user_background_settings` & 0x0F as `user_background_attachment`,
|
||||||
|
(`user_background_settings` & %2$d) > 0 as `user_background_attr_blend`,
|
||||||
|
(`user_background_settings` & %3$d) > 0 as `user_background_attr_slide`
|
||||||
FROM `msz_users`
|
FROM `msz_users`
|
||||||
WHERE `user_id` = :user_id
|
WHERE `user_id` = :user_id
|
||||||
',
|
',
|
||||||
pdo_prepare_array($profileFields, true, '`user_%s`')
|
pdo_prepare_array($profileFields, true, '`user_%s`'),
|
||||||
|
MSZ_USER_BACKGROUND_ATTRIBUTE_BLEND,
|
||||||
|
MSZ_USER_BACKGROUND_ATTRIBUTE_SLIDE
|
||||||
));
|
));
|
||||||
$getAccountInfo->bindValue('user_id', $settingsUserId);
|
$getAccountInfo->bindValue('user_id', $settingsUserId);
|
||||||
$accountInfo = $getAccountInfo->execute() ? $getAccountInfo->fetch(PDO::FETCH_ASSOC) : [];
|
$accountInfo = $getAccountInfo->execute() ? $getAccountInfo->fetch(PDO::FETCH_ASSOC) : [];
|
||||||
|
@ -354,6 +376,7 @@ switch ($settingsMode) {
|
||||||
'settings_profile_fields' => $profileFields,
|
'settings_profile_fields' => $profileFields,
|
||||||
'settings_disable_account_options' => $disableAccountOptions,
|
'settings_disable_account_options' => $disableAccountOptions,
|
||||||
'account_info' => $accountInfo,
|
'account_info' => $accountInfo,
|
||||||
|
'background_attachments' => MSZ_USER_BACKGROUND_ATTACHMENTS_NAMES,
|
||||||
]);
|
]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
114
src/csrf.php
Normal file
114
src/csrf.php
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
<?php
|
||||||
|
define('MSZ_CSRF_TOLERANCE', 15 * 60); // DO NOT EXCEED 16-BIT INTEGER SIZES, SHIT _WILL_ BREAK
|
||||||
|
define('MSZ_CSRF_HTML', '<input type="hidden" name="%1$s" value="%2$s">');
|
||||||
|
define('MSZ_CSRF_SECRET_STORE', '_msz_csrf_secret');
|
||||||
|
define('MSZ_CSRF_IDENTITY_STORE', '_msz_csrf_identity');
|
||||||
|
define('MSZ_CSRF_TOKEN_STORE', '_msz_csrf_tokens');
|
||||||
|
define('MSZ_CSRF_HASH_ALGO', 'sha256');
|
||||||
|
define('MSZ_CSRF_TOKEN_LENGTH', 76); // 8 + 4 + 64
|
||||||
|
|
||||||
|
// the following two functions DO NOT depend on csrf_init().
|
||||||
|
// $realm = Some kinda identifier for whatever's trying to do a validation.
|
||||||
|
// $identity = When the user is logged in I recommend just using their ID, otherwise IP will be fine.
|
||||||
|
function csrf_token_create(
|
||||||
|
string $realm,
|
||||||
|
string $identity,
|
||||||
|
string $secretKey,
|
||||||
|
?int $timestamp = null,
|
||||||
|
int $tolerance = MSZ_CSRF_TOLERANCE
|
||||||
|
): string {
|
||||||
|
$timestamp = $timestamp ?? time();
|
||||||
|
$token = bin2hex(pack('Vv', $timestamp, $tolerance));
|
||||||
|
|
||||||
|
return $token . csrf_token_hash(
|
||||||
|
MSZ_CSRF_HASH_ALGO,
|
||||||
|
$realm,
|
||||||
|
$identity,
|
||||||
|
$secretKey,
|
||||||
|
$timestamp,
|
||||||
|
$tolerance
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function csrf_token_hash(
|
||||||
|
string $algo,
|
||||||
|
string $realm,
|
||||||
|
string $identity,
|
||||||
|
string $secretKey,
|
||||||
|
int $timestamp,
|
||||||
|
int $tolerance
|
||||||
|
): string {
|
||||||
|
return hash_hmac(
|
||||||
|
$algo,
|
||||||
|
implode(',', [$realm, $identity, $timestamp, $tolerance]),
|
||||||
|
$secretKey
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function csrf_token_verify(
|
||||||
|
string $realm,
|
||||||
|
string $token,
|
||||||
|
string $identity,
|
||||||
|
string $secretKey
|
||||||
|
): bool {
|
||||||
|
if (empty($token) || strlen($token) !== MSZ_CSRF_TOKEN_LENGTH) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
[$timestamp, $tolerance] = [0, 0];
|
||||||
|
extract(unpack('Vtimestamp/vtolerance', hex2bin(substr($token, 0, 12))));
|
||||||
|
|
||||||
|
if (time() > $timestamp + $tolerance) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove timestamp + tolerance from token
|
||||||
|
$token = substr($token, 12);
|
||||||
|
|
||||||
|
$compare = csrf_token_hash(
|
||||||
|
MSZ_CSRF_HASH_ALGO,
|
||||||
|
$realm,
|
||||||
|
$identity,
|
||||||
|
$secretKey,
|
||||||
|
$timestamp,
|
||||||
|
$tolerance
|
||||||
|
);
|
||||||
|
|
||||||
|
return hash_equals($compare, $token);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets some defaults
|
||||||
|
function csrf_init(string $secretKey, string $identity): void
|
||||||
|
{
|
||||||
|
$GLOBALS[MSZ_CSRF_SECRET_STORE] = $secretKey;
|
||||||
|
$GLOBALS[MSZ_CSRF_IDENTITY_STORE] = $identity;
|
||||||
|
$GLOBALS[MSZ_CSRF_TOKEN_STORE] = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
function csrf_token(string $realm): string
|
||||||
|
{
|
||||||
|
if (array_key_exists($realm, $GLOBALS[MSZ_CSRF_TOKEN_STORE])) {
|
||||||
|
return $GLOBALS[MSZ_CSRF_TOKEN_STORE][$realm];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $GLOBALS[MSZ_CSRF_TOKEN_STORE][$realm] = csrf_token_create(
|
||||||
|
$realm,
|
||||||
|
$GLOBALS[MSZ_CSRF_IDENTITY_STORE],
|
||||||
|
$GLOBALS[MSZ_CSRF_SECRET_STORE]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function csrf_verify(string $realm, string $token): bool
|
||||||
|
{
|
||||||
|
return csrf_token_verify(
|
||||||
|
$realm,
|
||||||
|
$token,
|
||||||
|
$GLOBALS[MSZ_CSRF_IDENTITY_STORE],
|
||||||
|
$GLOBALS[MSZ_CSRF_SECRET_STORE]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function csrf_html(string $realm, string $name = 'csrf'): string
|
||||||
|
{
|
||||||
|
return sprintf(MSZ_CSRF_HTML, $name, csrf_token($realm));
|
||||||
|
}
|
|
@ -5,7 +5,7 @@
|
||||||
method="post" action="/comments.php?m=create"
|
method="post" action="/comments.php?m=create"
|
||||||
id="comment-{{ reply_mode ? 'reply-' ~ reply_to.comment_id : 'create-' ~ category.category_id }}">
|
id="comment-{{ reply_mode ? 'reply-' ~ reply_to.comment_id : 'create-' ~ category.category_id }}">
|
||||||
<input type="hidden" name="comment[category]" value="{{ category.category_id }}">
|
<input type="hidden" name="comment[category]" value="{{ category.category_id }}">
|
||||||
<input type="hidden" name="csrf" value="{{ csrf_token() }}">
|
{{ 'comments'|csrf|raw }}
|
||||||
|
|
||||||
{% if reply_mode %}
|
{% if reply_mode %}
|
||||||
<input type="hidden" name="comment[reply]" value="{{ reply_to.comment_id }}">
|
<input type="hidden" name="comment[reply]" value="{{ reply_to.comment_id }}">
|
||||||
|
@ -86,14 +86,14 @@
|
||||||
<div class="comment__actions">
|
<div class="comment__actions">
|
||||||
{% if perms.can_vote %}
|
{% if perms.can_vote %}
|
||||||
<a class="comment__action comment__action--link comment__action--like{% if comment.comment_user_vote == 'Like' %} comment__action--voted{% endif %}"
|
<a class="comment__action comment__action--link comment__action--like{% if comment.comment_user_vote == 'Like' %} comment__action--voted{% endif %}"
|
||||||
href="/comments.php?m=vote&c={{ comment.comment_id }}&v={{ comment.comment_user_vote == 'Like' ? '0' : '1' }}&csrf={{ csrf_token() }}">
|
href="/comments.php?m=vote&c={{ comment.comment_id }}&v={{ comment.comment_user_vote == 'Like' ? '0' : '1' }}&csrf={{ csrf_token('comments') }}">
|
||||||
Like
|
Like
|
||||||
{% if comment.comment_likes > 0 %}
|
{% if comment.comment_likes > 0 %}
|
||||||
({{ comment.comment_likes|number_format }})
|
({{ comment.comment_likes|number_format }})
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</a>
|
</a>
|
||||||
<a class="comment__action comment__action--link comment__action--dislike{% if comment.comment_user_vote == 'Dislike' %} comment__action--voted{% endif %}"
|
<a class="comment__action comment__action--link comment__action--dislike{% if comment.comment_user_vote == 'Dislike' %} comment__action--voted{% endif %}"
|
||||||
href="/comments.php?m=vote&c={{ comment.comment_id }}&v={{ comment.comment_user_vote == 'Dislike' ? '0' : '-1' }}&csrf={{ csrf_token() }}">
|
href="/comments.php?m=vote&c={{ comment.comment_id }}&v={{ comment.comment_user_vote == 'Dislike' ? '0' : '-1' }}&csrf={{ csrf_token('comments') }}">
|
||||||
Dislike
|
Dislike
|
||||||
{% if comment.comment_dislikes > 0 %}
|
{% if comment.comment_dislikes > 0 %}
|
||||||
({{ comment.comment_dislikes|number_format }})
|
({{ comment.comment_dislikes|number_format }})
|
||||||
|
@ -431,7 +431,7 @@
|
||||||
|
|
||||||
var replyCsrf = document.createElement('input');
|
var replyCsrf = document.createElement('input');
|
||||||
replyCsrf.name = 'csrf';
|
replyCsrf.name = 'csrf';
|
||||||
replyCsrf.value = '{{ csrf_token() }}';
|
replyCsrf.value = '{{ csrf_token("comments") }}';
|
||||||
replyCsrf.type = 'hidden';
|
replyCsrf.type = 'hidden';
|
||||||
commentReplyInput.appendChild(replyCsrf);
|
commentReplyInput.appendChild(replyCsrf);
|
||||||
|
|
||||||
|
@ -571,7 +571,7 @@
|
||||||
|
|
||||||
commentVoteLock = false;
|
commentVoteLock = false;
|
||||||
};
|
};
|
||||||
xhr.open('GET', '/comments.php?m=vote&c={0}&v={1}&csrf={{ csrf_token() }}'.replace('{0}', id).replace('{1}', vote));
|
xhr.open('GET', '/comments.php?m=vote&c={0}&v={1}&csrf={{ csrf_token("comments") }}'.replace('{0}', id).replace('{1}', vote));
|
||||||
xhr.setRequestHeader('X-Misuzu-XHR', 'comments');
|
xhr.setRequestHeader('X-Misuzu-XHR', 'comments');
|
||||||
xhr.send();
|
xhr.send();
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,7 +82,7 @@
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<li class="header__user__action">
|
<li class="header__user__action">
|
||||||
<a class="header__user__link" href="/auth.php?m=logout&s={{ csrf_token() }}">Log out</a>
|
<a class="header__user__link" href="/auth.php?m=logout&s={{ csrf_token('logout') }}">Log out</a>
|
||||||
</li>
|
</li>
|
||||||
{% else %}
|
{% else %}
|
||||||
<li class="header__user__action">
|
<li class="header__user__action">
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
{% if not prevent_registration %}
|
{% if not prevent_registration %}
|
||||||
<form class="container container--new auth" method="post" action="">
|
<form class="container container--new auth" method="post" action="">
|
||||||
<input type="hidden" name="auth[mode]" value="register">
|
<input type="hidden" name="auth[mode]" value="register">
|
||||||
|
{{ 'register'|csrf|raw }}
|
||||||
|
|
||||||
<div class="container__title">Register</div>
|
<div class="container__title">Register</div>
|
||||||
|
|
||||||
{% if auth_register_error is defined %}
|
{% if auth_register_error is defined %}
|
||||||
|
@ -44,6 +46,8 @@
|
||||||
{% if not prevent_password_reset %}
|
{% if not prevent_password_reset %}
|
||||||
<form class="container container--new auth" method="post" action="">
|
<form class="container container--new auth" method="post" action="">
|
||||||
<input type="hidden" name="auth[mode]" value="forgot">
|
<input type="hidden" name="auth[mode]" value="forgot">
|
||||||
|
{{ 'passforgot'|csrf|raw }}
|
||||||
|
|
||||||
<div class="container__title">Forgot password</div>
|
<div class="container__title">Forgot password</div>
|
||||||
|
|
||||||
{% if auth_forgot_error is defined %}
|
{% if auth_forgot_error is defined %}
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<div class="auth__form">
|
<div class="auth__form">
|
||||||
<p class="auth__paragraph">We couldn't verify that you were actually the person attempting to log out.</p>
|
<p class="auth__paragraph">We couldn't verify that you were actually the person attempting to log out.</p>
|
||||||
<p class="auth__paragraph">Press the button below to verify the logout request, otherwise click back in your browser or close this tab.</p>
|
<p class="auth__paragraph">Press the button below to verify the logout request, otherwise click back in your browser or close this tab.</p>
|
||||||
<a href="?m=logout&s={{ csrf_token() }}" class="input__button input__button--new">Logout</a>
|
<a href="?m=logout&s={{ csrf_token('logout') }}" class="input__button input__button--new">Logout</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
<form class="container container--new auth" method="post" action="/auth.php">
|
<form class="container container--new auth" method="post" action="/auth.php">
|
||||||
<input type="hidden" name="auth[mode]" value="login">
|
<input type="hidden" name="auth[mode]" value="login">
|
||||||
|
{{ 'login'|csrf|raw }}
|
||||||
|
|
||||||
<div class="auth__header">
|
<div class="auth__header">
|
||||||
<div class="avatar avatar--new auth__avatar" id="login-avatar"
|
<div class="avatar avatar--new auth__avatar" id="login-avatar"
|
||||||
|
|
|
@ -315,6 +315,7 @@
|
||||||
|
|
||||||
<div class="forum__posting__content">
|
<div class="forum__posting__content">
|
||||||
<input type="hidden" name="post[{{ is_reply ? 'topic' : 'forum' }}]" value="{{ target_id }}">
|
<input type="hidden" name="post[{{ is_reply ? 'topic' : 'forum' }}]" value="{{ target_id }}">
|
||||||
|
{{ 'forum_post'|csrf|raw }}
|
||||||
|
|
||||||
{#<div class="forum__posting__errors">
|
{#<div class="forum__posting__errors">
|
||||||
<p class="forum__posting__error">Error: Your post contained too much text, shorten it a bit or split it out in two posts.</p>
|
<p class="forum__posting__error">Error: Your post contained too much text, shorten it a bit or split it out in two posts.</p>
|
||||||
|
@ -331,7 +332,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="forum__posting__buttons">
|
<div class="forum__posting__buttons">
|
||||||
<button class="input__button" name="csrf" value="{{ csrf_token() }}">Submit</button>
|
<button class="input__button">Submit</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
{% block manage_content %}
|
{% block manage_content %}
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<form action="?v=action{{ edit_action is defined ? '&a=' ~ edit_action.action_id : '' }}" method="post">
|
<form action="?v=action{{ edit_action is defined ? '&a=' ~ edit_action.action_id : '' }}" method="post">
|
||||||
|
{{ 'changelog_action'|csrf|raw }}
|
||||||
|
|
||||||
<h1 class="container__title">
|
<h1 class="container__title">
|
||||||
{% if edit_action is defined %}
|
{% if edit_action is defined %}
|
||||||
Editing <span style="{{ edit_action.action_colour|html_colour }};color:var(--user-colour)">{{ edit_action.action_name }}</span> ({{ edit_action.action_id }})
|
Editing <span style="{{ edit_action.action_colour|html_colour }};color:var(--user-colour)">{{ edit_action.action_name }}</span> ({{ edit_action.action_id }})
|
||||||
|
@ -56,7 +58,7 @@
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<button class="input__button" name="csrf" value="{{ csrf_token() }}">Save</button>
|
<button class="input__button">Save</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
{% block manage_content %}
|
{% block manage_content %}
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<form action="?v=change{{ edit_change is defined ? '&c=' ~ edit_change.change_id : '' }}" method="post">
|
<form action="?v=change{{ edit_change is defined ? '&c=' ~ edit_change.change_id : '' }}" method="post">
|
||||||
|
{{ 'changelog_add'|csrf|raw }}
|
||||||
|
|
||||||
<h1 class="container__title">
|
<h1 class="container__title">
|
||||||
{% if edit_change is defined %}
|
{% if edit_change is defined %}
|
||||||
Editing #{{ edit_change.change_id }}
|
Editing #{{ edit_change.change_id }}
|
||||||
|
@ -57,7 +59,7 @@
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<button class="input__button" name="csrf" value="{{ csrf_token() }}">Save</button>
|
<button class="input__button">Save</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
@ -82,7 +84,7 @@
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<button class="input__button" name="csrf" value="{{ csrf_token() }}">Remove</button>
|
<button class="input__button" name="csrf" value="{{ csrf_token('changelog_add') }}">Remove</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -103,7 +105,7 @@
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<button class="input__button" name="csrf" value="{{ csrf_token() }}">Add</button>
|
<button class="input__button" name="csrf" value="{{ csrf_token('changelog_add') }}">Add</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
{% block manage_content %}
|
{% block manage_content %}
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<form action="?v=tag{{ edit_tag is defined ? '&t=' ~ edit_tag.tag_id : '' }}" method="post">
|
<form action="?v=tag{{ edit_tag is defined ? '&t=' ~ edit_tag.tag_id : '' }}" method="post">
|
||||||
|
{{ 'changelog_tag'|csrf|raw }}
|
||||||
|
|
||||||
<h1 class="container__title">
|
<h1 class="container__title">
|
||||||
{% if edit_tag is defined %}
|
{% if edit_tag is defined %}
|
||||||
Editing {{ edit_tag.tag_name }} ({{ edit_tag.tag_id }})
|
Editing {{ edit_tag.tag_name }} ({{ edit_tag.tag_id }})
|
||||||
|
@ -42,56 +44,8 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<button class="input__button" name="csrf" value="{{ csrf_token() }}">Save</button>
|
<button class="input__button">Save</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
{% if edit_change is defined %}
|
|
||||||
<h1 class="container__title">
|
|
||||||
Tags
|
|
||||||
</h1>
|
|
||||||
|
|
||||||
{% if edit_change_assigned_tags|length > 0 %}
|
|
||||||
<form class="container" method="post" action="" style="display:inline-block">
|
|
||||||
<label class="form__label">
|
|
||||||
<div class="form__label__text">Assigned Tags</div>
|
|
||||||
<div class="form__label__input">
|
|
||||||
<select name="remove_tag" class="input input--select">
|
|
||||||
{% for tag in edit_change_assigned_tags %}
|
|
||||||
<option value="{{ tag.tag_id }}">
|
|
||||||
{{ tag.tag_name }}
|
|
||||||
</option>
|
|
||||||
{% endfor %}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<button class="input__button" name="csrf" value="{{ csrf_token() }}">Remove</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if edit_change_available_tags|length > 0 %}
|
|
||||||
<form class="container" method="post" action="" style="display:inline-block">
|
|
||||||
<label class="form__label">
|
|
||||||
<div class="form__label__text">Available Tags</div>
|
|
||||||
<div class="form__label__input">
|
|
||||||
<select name="add_tag" class="input input--select">
|
|
||||||
{% for tag in edit_change_available_tags %}
|
|
||||||
<option value="{{ tag.tag_id }}">
|
|
||||||
{{ tag.tag_name }}
|
|
||||||
</option>
|
|
||||||
{% endfor %}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<button class="input__button" name="csrf" value="{{ csrf_token() }}">Add</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
{% endif %}
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
{% block manage_content %}
|
{% block manage_content %}
|
||||||
<form action="?v=role{{ edit_role is defined ? '&r=' ~ edit_role.role_id : '' }}" method="post">
|
<form action="?v=role{{ edit_role is defined ? '&r=' ~ edit_role.role_id : '' }}" method="post">
|
||||||
|
{{ 'users_role'|csrf|raw }}
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<h1 class="container__title">
|
<h1 class="container__title">
|
||||||
{% if edit_role is defined %}
|
{% if edit_role is defined %}
|
||||||
|
@ -93,6 +95,6 @@
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<button class="input__button" name="csrf" value="{{ csrf_token() }}">{{ edit_role is defined ? 'Update role' : 'Create role' }}</button>
|
<button class="input__button">{{ edit_role is defined ? 'Update role' : 'Create role' }}</button>
|
||||||
</form>
|
</form>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
{% block manage_content %}
|
{% block manage_content %}
|
||||||
{% if can_manage_users %}
|
{% if can_manage_users %}
|
||||||
<form method="post" enctype="multipart/form-data" action="">
|
<form method="post" enctype="multipart/form-data" action="">
|
||||||
|
{{ 'users_edit'|csrf|raw }}
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="container__title">
|
<div class="container__title">
|
||||||
Viewing <span style="{{ view_user.colour|html_colour }}">{{ view_user.username }}</span> ({{ view_user.user_id }})
|
Viewing <span style="{{ view_user.colour|html_colour }}">{{ view_user.username }}</span> ({{ view_user.user_id }})
|
||||||
|
@ -145,7 +147,7 @@
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<button class="input__button" name="csrf" value="{{ csrf_token() }}">Update</button>
|
<button class="input__button">Update</button>
|
||||||
</form>
|
</form>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
@ -154,7 +156,7 @@
|
||||||
<form method="post" action="" class="container">
|
<form method="post" action="" class="container">
|
||||||
<div class="container__title">Manage Roles</div>
|
<div class="container__title">Manage Roles</div>
|
||||||
<div class="container__content">
|
<div class="container__content">
|
||||||
<input type="hidden" name="csrf" value="{{ csrf_token() }}">
|
{{ 'users_edit'|csrf|raw }}
|
||||||
|
|
||||||
<label class="form__label">
|
<label class="form__label">
|
||||||
<div class="form__label__text">Has Roles</div>
|
<div class="form__label__text">Has Roles</div>
|
||||||
|
@ -192,7 +194,7 @@
|
||||||
</div>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<button class="input__button" name="csrf" value="{{ csrf_token() }}">Add</button>
|
<button class="input__button" name="csrf" value="{{ csrf_token('users_edit') }}">Add</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
</style>
|
</style>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</head>
|
</head>
|
||||||
<body class="main">
|
<body class="main{% if current_user.user_background_settings is defined %} {{ current_user.user_background_settings|bg_settings('main--bg-%s')|join(' ') }}{% endif %}">
|
||||||
{% include '_layout/header.twig' %}
|
{% include '_layout/header.twig' %}
|
||||||
|
|
||||||
<div class="main__wrapper">
|
<div class="main__wrapper">
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
<div class="container container--translucent">
|
<div class="container container--translucent">
|
||||||
<div class="container__title">Account</div>
|
<div class="container__title">Account</div>
|
||||||
<form action="" method="post" class="settings__account">
|
<form action="" method="post" class="settings__account">
|
||||||
<input type="hidden" name="csrf" value="{{ csrf_token() }}">
|
{{ 'settings'|csrf|raw }}
|
||||||
|
|
||||||
<div class="settings__account__row">
|
<div class="settings__account__row">
|
||||||
{% if settings_perms.edit_profile %}
|
{% if settings_perms.edit_profile %}
|
||||||
|
@ -136,7 +136,7 @@
|
||||||
<div class="container__title">Avatar</div>
|
<div class="container__title">Avatar</div>
|
||||||
<form action="" method="post" class="settings__images" enctype="multipart/form-data">
|
<form action="" method="post" class="settings__images" enctype="multipart/form-data">
|
||||||
<input type="hidden" name="MAX_FILE_SIZE" value="{{ background.max_size }}">
|
<input type="hidden" name="MAX_FILE_SIZE" value="{{ background.max_size }}">
|
||||||
<input type="hidden" name="csrf" value="{{ csrf_token() }}">
|
{{ 'settings'|csrf|raw }}
|
||||||
|
|
||||||
<div class="settings__images__sections">
|
<div class="settings__images__sections">
|
||||||
<div class="settings__images__requirements">
|
<div class="settings__images__requirements">
|
||||||
|
@ -207,7 +207,7 @@
|
||||||
<div class="container__title">Background</div>
|
<div class="container__title">Background</div>
|
||||||
<form action="" method="post" class="settings__images" enctype="multipart/form-data">
|
<form action="" method="post" class="settings__images" enctype="multipart/form-data">
|
||||||
<input type="hidden" name="MAX_FILE_SIZE" value="{{ background.max_size }}">
|
<input type="hidden" name="MAX_FILE_SIZE" value="{{ background.max_size }}">
|
||||||
<input type="hidden" name="csrf" value="{{ csrf_token() }}">
|
{{ 'settings'|csrf|raw }}
|
||||||
|
|
||||||
<div class="settings__images__sections">
|
<div class="settings__images__sections">
|
||||||
<div class="settings__images__requirements">
|
<div class="settings__images__requirements">
|
||||||
|
@ -218,6 +218,24 @@
|
||||||
<li class="settings__images__requirement">May not be larger than <strong>{{ background.max_width }}x{{ background.max_height }}</strong>.</li>
|
<li class="settings__images__requirement">May not be larger than <strong>{{ background.max_width }}x{{ background.max_height }}</strong>.</li>
|
||||||
<li class="settings__images__requirement">Animated gif images are <strong>not</strong> allowed.</li>
|
<li class="settings__images__requirement">Animated gif images are <strong>not</strong> allowed.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<select name="background[attach]" class="input__select">
|
||||||
|
{% for key, value in background_attachments %}
|
||||||
|
<option value="{{ value }}"{% if account_info.user_background_attachment == key %} selected{% endif %}>
|
||||||
|
{{ value|capitalize }}
|
||||||
|
</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" name="background[attr][blend]"{% if account_info.user_background_attr_blend %} checked{% endif %}>
|
||||||
|
Blend
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" name="background[attr][slide]"{% if account_info.user_background_attr_slide %} checked{% endif %}>
|
||||||
|
Slide
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -275,7 +293,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<form method="post" action="" enctype="multipart/form-data" class="settings__about">
|
<form method="post" action="" enctype="multipart/form-data" class="settings__about">
|
||||||
<input type="hidden" name="csrf" value="{{ csrf_token() }}">
|
{{ 'settings'|csrf|raw }}
|
||||||
|
|
||||||
<textarea name="about[text]" class="input__textarea settings__about__text" id="about-textarea">{{ account_info.user_about_content|escape }}</textarea>
|
<textarea name="about[text]" class="input__textarea settings__about__text" id="about-textarea">{{ account_info.user_about_content|escape }}</textarea>
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,8 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<form class="settings__sessions__actions" method="post" action="?m=sessions">
|
<form class="settings__sessions__actions" method="post" action="?m=sessions">
|
||||||
<input type="hidden" name="csrf" value="{{ csrf_token() }}">
|
{{ 'settings'|csrf|raw }}
|
||||||
|
|
||||||
<button class="input__button" name="session_action" value="kill-all">
|
<button class="input__button" name="session_action" value="kill-all">
|
||||||
Kill all active sessions
|
Kill all active sessions
|
||||||
</button>
|
</button>
|
||||||
|
@ -65,8 +66,9 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<form class="settings__sessions__column settings__sessions__column--options" method="post" action="?m=sessions">
|
<form class="settings__sessions__column settings__sessions__column--options" method="post" action="?m=sessions">
|
||||||
<input type="hidden" name="csrf" value="{{ csrf_token() }}">
|
|
||||||
<input type="hidden" name="session" value="{{ session.session_id }}">
|
<input type="hidden" name="session" value="{{ session.session_id }}">
|
||||||
|
{{ 'settings'|csrf|raw }}
|
||||||
|
|
||||||
<button class="input__button settings__sessions__button">
|
<button class="input__button settings__sessions__button">
|
||||||
{{ session.session_id == active_session_id ? 'Logout' : 'Kill' }}
|
{{ session.session_id == active_session_id ? 'Logout' : 'Kill' }}
|
||||||
</button>
|
</button>
|
||||||
|
|
|
@ -42,8 +42,8 @@
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% if is_editing %}
|
{% if is_editing %}
|
||||||
<form class="profile" method="post" action="/settings.php" enctype="multipart/form-data">
|
<form class="profile" method="post" action="/settings.php" enctype="multipart/form-data">
|
||||||
<input type="hidden" name="csrf" value="{{ csrf_token() }}">
|
|
||||||
<input type="hidden" name="user" value="{{ profile.user_id }}">
|
<input type="hidden" name="user" value="{{ profile.user_id }}">
|
||||||
|
{{ 'settings'|csrf|raw }}
|
||||||
|
|
||||||
{% if perms.edit_avatar %}
|
{% if perms.edit_avatar %}
|
||||||
<input class="settings__avatar__input"
|
<input class="settings__avatar__input"
|
||||||
|
|
12
utility.php
12
utility.php
|
@ -133,18 +133,6 @@ function get_country_name(string $code): string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// this is temporary, don't scream at me for using md5
|
|
||||||
// BIG TODO: make these functions not dependent on sessions so they can be used outside of those.
|
|
||||||
function tmp_csrf_verify(string $token): bool
|
|
||||||
{
|
|
||||||
return hash_equals(tmp_csrf_token(), $token);
|
|
||||||
}
|
|
||||||
|
|
||||||
function tmp_csrf_token(): string
|
|
||||||
{
|
|
||||||
return md5($_COOKIE['msz_sid'] ?? 'this is very insecure lmao');
|
|
||||||
}
|
|
||||||
|
|
||||||
function crop_image_centred_path(string $filename, int $target_width, int $target_height): \Imagick
|
function crop_image_centred_path(string $filename, int $target_width, int $target_height): \Imagick
|
||||||
{
|
{
|
||||||
return crop_image_centred(new \Imagick($filename), $target_width, $target_height);
|
return crop_image_centred(new \Imagick($filename), $target_width, $target_height);
|
||||||
|
|
Loading…
Add table
Reference in a new issue