diff --git a/lib/index b/lib/index index bce5ba7..8f908d7 160000 --- a/lib/index +++ b/lib/index @@ -1 +1 @@ -Subproject commit bce5ba77a268ecd6338d0e3520e41ff4c40cbeda +Subproject commit 8f908d7f688bd95fdedd868c5bf8d25a3b500b99 diff --git a/public/manage/changelog/change.php b/public/manage/changelog/change.php index 5c82419..faaee59 100644 --- a/public/manage/changelog/change.php +++ b/public/manage/changelog/change.php @@ -68,12 +68,16 @@ if($_SERVER['REQUEST_METHOD'] === 'POST' && CSRF::validateRequest()) { ); } - if(isset($change) && !empty($_POST['tags']) && is_array($_POST['tags']) && array_test($_POST['tags'], 'ctype_digit')) { + if(isset($change) && !empty($_POST['tags']) && is_array($_POST['tags'])) { $applyTags = []; - foreach($_POST['tags'] as $tagId) + foreach($_POST['tags'] as $tagId) { + if(!ctype_digit($tagId)) + die('Invalid item encountered in roles list.'); + try { $applyTags[] = ChangelogTag::byId((int)filter_var($tagId, FILTER_SANITIZE_NUMBER_INT)); } catch(ChangelogTagNotFoundException $ex) {} + } $change->setTags($applyTags); } diff --git a/public/manage/users/user.php b/public/manage/users/user.php index 7f7ab2d..5d41ebb 100644 --- a/public/manage/users/user.php +++ b/public/manage/users/user.php @@ -61,16 +61,21 @@ if(CSRF::validateRequest() && $canEdit) { } } - if(!empty($_POST['roles']) && is_array($_POST['roles']) && array_test($_POST['roles'], 'ctype_digit')) { + if(!empty($_POST['roles']) && is_array($_POST['roles'])) { + // Read user input array and throw intval on em + $applyRoles = []; + foreach($_POST['roles'] as $item) { + if(!ctype_digit($item)) + die('Invalid item encountered in roles list.'); + $applyRoles[] = (int)$item; + } + // Fetch existing roles $existingRoles = $userInfo->getRoles(); // Initialise set array with existing roles $setRoles = $existingRoles; - // Read user input array and throw intval on em - $applyRoles = array_apply($_POST['roles'], 'intval'); - // Storage array for roles to dump $removeRoles = []; diff --git a/public/manage/users/warnings.php b/public/manage/users/warnings.php index 215ccbf..ee88525 100644 --- a/public/manage/users/warnings.php +++ b/public/manage/users/warnings.php @@ -50,12 +50,18 @@ if(!empty($_POST['warning']) && is_array($_POST['warning'])) { if(!empty($customDuration)) { switch($warningDuration) { case -100: // YYYY-MM-DD - $splitDate = array_apply(explode('-', $customDuration, 3), function ($a) { - return (int)$a; - }); + $splitDate = explode('-', $customDuration, 3); + if(count($splitDate) !== 3) + die('Invalid date specified.'); - if(checkdate($splitDate[1], $splitDate[2], $splitDate[0])) - $warningDuration = mktime(0, 0, 0, $splitDate[1], $splitDate[2], $splitDate[0]) - time(); + $wYear = (int)$splitDate[0]; + $wMonth = (int)$splitDate[1]; + $wDay = (int)$splitDate[2]; + + if(checkdate($wMonth, $wDay, $wYear)) + $warningDuration = mktime(0, 0, 0, $wMonth, $wDay, $wYear) - time(); + else + die('Invalid date specified.'); break; case -200: // Raw seconds diff --git a/src/AuthToken.php b/src/AuthToken.php index 56cf571..f51f17f 100644 --- a/src/AuthToken.php +++ b/src/AuthToken.php @@ -173,17 +173,28 @@ class AuthToken { return $token; } + public static function cookieDomain(bool $compatible = true): string { + $url = parse_url($_SERVER['HTTP_HOST'], PHP_URL_HOST); + if(empty($url)) + $url = $_SERVER['HTTP_HOST']; + + if(!filter_var($url, FILTER_VALIDATE_IP) && $compatible) + $url = '.' . $url; + + return $url; + } + public function applyCookie(int $expires = 0): void { if($expires > 0) $this->cookieExpires = $expires; else $expires = $this->cookieExpires; - setcookie('msz_auth', $this->pack(), $expires, '/', msz_cookie_domain(), !empty($_SERVER['HTTPS']), true); + setcookie('msz_auth', $this->pack(), $expires, '/', self::cookieDomain(), !empty($_SERVER['HTTPS']), true); } public static function nukeCookie(): void { - setcookie('msz_auth', '', -9001, '/', msz_cookie_domain(), !empty($_SERVER['HTTPS']), true); + setcookie('msz_auth', '', -9001, '/', self::cookieDomain(), !empty($_SERVER['HTTPS']), true); setcookie('msz_auth', '', -9001, '/', '', !empty($_SERVER['HTTPS']), true); } diff --git a/src/Forum/perms.php b/src/Forum/perms.php index a574cc4..9d91a84 100644 --- a/src/Forum/perms.php +++ b/src/Forum/perms.php @@ -87,7 +87,11 @@ function forum_perms_get_user(?int $forum, int $user): array { $getPerms->bind('user_id_1', $user); $getPerms->bind('user_id_2', $user); - return $memo[$memoId] = array_bit_or($perms, $getPerms->fetch()); + $userPerms = $getPerms->fetch(); + foreach($perms as $key => $value) + $perms[$key] |= $userPerms[$key] ?? 0; + + return $memo[$memoId] = $perms; } function forum_perms_get_role(?int $forum, int $role): array { @@ -124,7 +128,11 @@ function forum_perms_get_role(?int $forum, int $role): array { $getPerms->bind('forum_id', $forum); $getPerms->bind('role_id', $role); - return $memo[$memoId] = array_bit_or($perms, $getPerms->fetch()); + $userPerms = $getPerms->fetch(); + foreach($perms as $key => $value) + $perms[$key] |= $userPerms[$key] ?? 0; + + return $memo[$memoId] = $perms; } function forum_perms_get_user_raw(?int $forum, int $user): array { diff --git a/src/Memoizer.php b/src/Memoizer.php index 40f7af5..fa0f419 100644 --- a/src/Memoizer.php +++ b/src/Memoizer.php @@ -2,6 +2,7 @@ namespace Misuzu; use InvalidArgumentException; +use Index\XArray; // get rid of this garbage as soon as possible @@ -16,7 +17,7 @@ class Memoizer { } if(is_callable($find)) { - $item = array_find($this->collection, $find) ?? $create(); + $item = XArray::first($this->collection, $find) ?? $create(); if(method_exists($item, 'getId')) $this->collection[$item->getId()] = $item; else diff --git a/src/News/NewsPost.php b/src/News/NewsPost.php index 01631b7..17907bc 100644 --- a/src/News/NewsPost.php +++ b/src/News/NewsPost.php @@ -128,7 +128,9 @@ class NewsPost implements JsonSerializable { return Parser::instance(Parser::MARKDOWN)->parseText($this->getText()); } public function getFirstParagraph(): string { - return first_paragraph($this->getText()); + $text = $this->getText(); + $index = mb_strpos($text, "\n"); + return $index === false ? $text : mb_substr($text, 0, $index); } public function getParsedFirstParagraph(): string { return Parser::instance(Parser::MARKDOWN)->parseText($this->getFirstParagraph()); diff --git a/src/TwigMisuzu.php b/src/TwigMisuzu.php index 9d739c3..af77cd2 100644 --- a/src/TwigMisuzu.php +++ b/src/TwigMisuzu.php @@ -23,7 +23,6 @@ final class TwigMisuzu extends AbstractExtension { new TwigFilter('byte_symbol', 'byte_symbol'), new TwigFilter('parse_text', fn(string $text, int $parser): string => Parser::instance($parser)->parseText($text)), new TwigFilter('perms_check', 'perms_check'), - new TwigFilter('clamp', 'clamp'), new TwigFilter('time_diff', [$this, 'timeDiff'], ['needs_environment' => true]), ]; } diff --git a/src/Users/User.php b/src/Users/User.php index 2947890..22cd277 100644 --- a/src/Users/User.php +++ b/src/Users/User.php @@ -4,6 +4,7 @@ namespace Misuzu\Users; use DateTime; use DateTimeZone; use JsonSerializable; +use Index\XString; use Index\Colour\Colour; use Misuzu\DB; use Misuzu\HasRankInterface; @@ -666,7 +667,7 @@ class User implements HasRankInterface, JsonSerializable { } public static function validatePassword(string $password): string { - if(unique_chars($password) < self::PASSWORD_UNIQUE) + if(XString::countUnique($password) < self::PASSWORD_UNIQUE) return 'weak'; return ''; diff --git a/src/Zalgo.php b/src/Zalgo.php index 784ba56..4a31680 100644 --- a/src/Zalgo.php +++ b/src/Zalgo.php @@ -55,9 +55,10 @@ final class Zalgo { public static function getString(array $array, int $length): string { $string = ''; + $rngMax = count($array) - 1; for($i = 0; $i < $length; $i++) - $string .= array_rand_value($array); + $string .= $array[mt_rand(0, $rngMax)]; return $string; } diff --git a/templates/forum/macros.twig b/templates/forum/macros.twig index 7444b04..da6345a 100644 --- a/templates/forum/macros.twig +++ b/templates/forum/macros.twig @@ -322,7 +322,8 @@ {% if topic.topic_pages|default(0) > 1 %}