Stricter checking on GET variables.

This commit is contained in:
flash 2019-03-18 23:02:30 +01:00
parent d7e2f811ed
commit 9f472d2693
16 changed files with 96 additions and 74 deletions

View file

@ -3,7 +3,9 @@
require_once '../misuzu.php'; require_once '../misuzu.php';
switch ($_GET['m'] ?? '') { $mode = !empty($_GET['m']) && is_string($_GET['m']) ? $_GET['m'] : '';
switch ($mode) {
case 'logout': case 'logout':
echo tpl_render('auth.logout'); echo tpl_render('auth.logout');
break; break;

View file

@ -6,7 +6,7 @@ if (user_session_active()) {
return; return;
} }
if (isset($_GET['resolve_user']) && is_string($_GET['resolve_user'])) { if (!empty($_GET['resolve_user']) && is_string($_GET['resolve_user'])) {
header('Content-Type: text/plain; charset=utf-8'); header('Content-Type: text/plain; charset=utf-8');
echo user_id_from_username($_GET['resolve_user']); echo user_id_from_username($_GET['resolve_user']);
return; return;

View file

@ -1,10 +1,10 @@
<?php <?php
require_once '../misuzu.php'; require_once '../misuzu.php';
$changelogChange = (int)($_GET['c'] ?? 0); $changelogChange = !empty($_GET['c']) && is_string($_GET['c']) ? (int)$_GET['c'] : 0;
$changelogDate = $_GET['d'] ?? ''; $changelogDate = !empty($_GET['d']) && is_string($_GET['d']) ? (string)$_GET['d'] : '';
$changelogUser = (int)($_GET['u'] ?? 0); $changelogUser = !empty($_GET['u']) && is_string($_GET['u']) ? (int)$_GET['u'] : 0;
$changelogTags = $_GET['t'] ?? ''; $changelogTags = !empty($_GET['t']) && is_string($_GET['t']) ? (string)$_GET['t'] : '';
tpl_var('comments_perms', $commentPerms = comments_get_perms(user_session_current('user_id', 0))); tpl_var('comments_perms', $commentPerms = comments_get_perms(user_session_current('user_id', 0)));

View file

@ -37,7 +37,11 @@ if (user_warning_check_expiration($currentUserId, MSZ_WARN_SILENCE) > 0) {
header(csrf_http_header('comments')); header(csrf_http_header('comments'));
$commentPerms = comments_get_perms($currentUserId); $commentPerms = comments_get_perms($currentUserId);
switch ($_GET['m'] ?? null) { $commentId = !empty($_GET['c']) && is_string($_GET['c']) ? (int)$_GET['c'] : 0;
$commentMode = !empty($_GET['m']) && is_string($_GET['m']) ? (string)$_GET['m'] : '';
$commentVote = !empty($_GET['v']) && is_string($_GET['v']) ? (int)$_GET['v'] : MSZ_COMMENTS_VOTE_INDIFFERENT;
switch ($commentMode) {
case 'pin': case 'pin':
case 'unpin': case 'unpin':
if (!$commentPerms['can_pin']) { if (!$commentPerms['can_pin']) {
@ -45,8 +49,7 @@ switch ($_GET['m'] ?? null) {
break; break;
} }
$comment = (int)($_GET['c'] ?? 0); $commentInfo = comments_post_get($commentId, false);
$commentInfo = comments_post_get($comment, false);
if (!$commentInfo || $commentInfo['comment_deleted'] !== null) { if (!$commentInfo || $commentInfo['comment_deleted'] !== null) {
echo render_info_or_json($isXHR, "This comment doesn't exist!", 400); echo render_info_or_json($isXHR, "This comment doesn't exist!", 400);
@ -58,7 +61,7 @@ switch ($_GET['m'] ?? null) {
break; break;
} }
$isPinning = $_GET['m'] === 'pin'; $isPinning = $commentMode === 'pin';
if ($isPinning && !empty($commentInfo['comment_pinned'])) { if ($isPinning && !empty($commentInfo['comment_pinned'])) {
echo render_info_or_json($isXHR, 'This comment is already pinned.', 400); echo render_info_or_json($isXHR, 'This comment is already pinned.', 400);
@ -87,15 +90,12 @@ switch ($_GET['m'] ?? null) {
break; break;
} }
$vote = (int)($_GET['v'] ?? MSZ_COMMENTS_VOTE_INDIFFERENT); if (!comments_vote_type_valid($commentVote)) {
if (!comments_vote_type_valid($vote)) {
echo render_info_or_json($isXHR, 'Invalid vote action.', 400); echo render_info_or_json($isXHR, 'Invalid vote action.', 400);
break; break;
} }
$comment = (int)($_GET['c'] ?? 0); $commentInfo = comments_post_get($commentId, false);
$commentInfo = comments_post_get($comment, false);
if (!$commentInfo || $commentInfo['comment_deleted'] !== null) { if (!$commentInfo || $commentInfo['comment_deleted'] !== null) {
echo render_info_or_json($isXHR, "This comment doesn't exist!", 400); echo render_info_or_json($isXHR, "This comment doesn't exist!", 400);
@ -103,17 +103,17 @@ switch ($_GET['m'] ?? null) {
} }
$voteResult = comments_vote_add( $voteResult = comments_vote_add(
$comment, $commentInfo['comment_id'],
user_session_current('user_id', 0), user_session_current('user_id', 0),
$vote $commentVote
); );
if (!$isXHR) { if (!$isXHR) {
header('Location: ' . $redirect . '#comment-' . $comment); header('Location: ' . $redirect . '#comment-' . $commentInfo['comment_id']);
break; break;
} }
echo json_encode(comments_votes_get($comment)); echo json_encode(comments_votes_get($commentInfo['comment_id']));
break; break;
case 'delete': case 'delete':
@ -122,8 +122,7 @@ switch ($_GET['m'] ?? null) {
break; break;
} }
$comment = (int)($_GET['c'] ?? 0); $commentInfo = comments_post_get($commentId, false);
$commentInfo = comments_post_get($comment, false);
if (!$commentInfo) { if (!$commentInfo) {
echo render_info_or_json($isXHR, "This comment doesn't exist.", 400); echo render_info_or_json($isXHR, "This comment doesn't exist.", 400);
@ -147,19 +146,19 @@ switch ($_GET['m'] ?? null) {
break; break;
} }
if (!comments_post_delete($comment)) { if (!comments_post_delete($commentInfo['comment_id'])) {
echo render_info_or_json($isXHR, 'Failed to delete comment.', 500); echo render_info_or_json($isXHR, 'Failed to delete comment.', 500);
break; break;
} }
if ($isModAction) { if ($isModAction) {
audit_log(MSZ_AUDIT_COMMENT_ENTRY_DELETE_MOD, $currentUserId, [ audit_log(MSZ_AUDIT_COMMENT_ENTRY_DELETE_MOD, $currentUserId, [
$comment, $commentInfo['comment_id'],
(int)($commentInfo['user_id'] ?? 0), (int)($commentInfo['user_id'] ?? 0),
$commentInfo['username'] ?? '(Deleted User)', $commentInfo['username'] ?? '(Deleted User)',
]); ]);
} else { } else {
audit_log(MSZ_AUDIT_COMMENT_ENTRY_DELETE, $currentUserId, [$comment]); audit_log(MSZ_AUDIT_COMMENT_ENTRY_DELETE, $currentUserId, [$commentInfo['comment_id']]);
} }
if ($redirect) { if ($redirect) {
@ -168,7 +167,7 @@ switch ($_GET['m'] ?? null) {
} }
echo json_encode([ echo json_encode([
'id' => $comment, 'id' => $commentInfo['comment_id'],
]); ]);
break; break;
@ -178,8 +177,7 @@ switch ($_GET['m'] ?? null) {
break; break;
} }
$comment = (int)($_GET['c'] ?? 0); $commentInfo = comments_post_get($commentId, false);
$commentInfo = comments_post_get($comment, false);
if (!$commentInfo) { if (!$commentInfo) {
echo render_info_or_json($isXHR, "This comment doesn't exist.", 400); echo render_info_or_json($isXHR, "This comment doesn't exist.", 400);
@ -191,24 +189,24 @@ switch ($_GET['m'] ?? null) {
break; break;
} }
if (!comments_post_delete($comment, false)) { if (!comments_post_delete($commentInfo['comment_id'], false)) {
echo render_info_or_json($isXHR, 'Failed to restore comment.', 500); echo render_info_or_json($isXHR, 'Failed to restore comment.', 500);
break; break;
} }
audit_log(MSZ_AUDIT_COMMENT_ENTRY_RESTORE, $currentUserId, [ audit_log(MSZ_AUDIT_COMMENT_ENTRY_RESTORE, $currentUserId, [
$comment, $commentInfo['comment_id'],
(int)($commentInfo['user_id'] ?? 0), (int)($commentInfo['user_id'] ?? 0),
$commentInfo['username'] ?? '(Deleted User)', $commentInfo['username'] ?? '(Deleted User)',
]); ]);
if ($redirect) { if ($redirect) {
header('Location: ' . $redirect . '#comment-' . $comment); header('Location: ' . $redirect . '#comment-' . $commentInfo['comment_id']);
break; break;
} }
echo json_encode([ echo json_encode([
'id' => $comment, 'id' => $commentInfo['comment_id'],
]); ]);
break; break;
@ -223,7 +221,7 @@ switch ($_GET['m'] ?? null) {
break; break;
} }
$categoryId = (int)($_POST['comment']['category'] ?? 0); $categoryId = !empty($_POST['comment']['category']) && is_string($_POST['comment']['category']) ? (int)$_POST['comment']['category'] : 0;
$category = comments_category_info($categoryId); $category = comments_category_info($categoryId);
if (!$category) { if (!$category) {
@ -236,10 +234,10 @@ switch ($_GET['m'] ?? null) {
break; break;
} }
$commentText = $_POST['comment']['text'] ?? ''; $commentText = !empty($_POST['comment']['text']) && is_string($_POST['comment']['text']) ? $_POST['comment']['text'] : '';
$commentLock = !empty($_POST['comment']['lock']) && $commentPerms['can_lock']; $commentLock = !empty($_POST['comment']['lock']) && $commentPerms['can_lock'];
$commentPin = !empty($_POST['comment']['pin']) && $commentPerms['can_pin']; $commentPin = !empty($_POST['comment']['pin']) && $commentPerms['can_pin'];
$commentReply = (int)($_POST['comment']['reply'] ?? 0); $commentReply = !empty($_POST['comment']['reply']) && is_string($_POST['comment']['reply']) ? (int)$_POST['comment']['reply'] : 0;
if ($commentLock) { if ($commentLock) {
comments_category_lock($categoryId, is_null($category['category_locked'])); comments_category_lock($categoryId, is_null($category['category_locked']));

View file

@ -1,7 +1,7 @@
<?php <?php
require_once '../../misuzu.php'; require_once '../../misuzu.php';
$forumId = !empty($_GET['f']) && !is_array($_GET['f']) ? (int)$_GET['f'] : 0; $forumId = !empty($_GET['f']) && is_string($_GET['f']) ? (int)$_GET['f'] : 0;
$forumId = max($forumId, 0); $forumId = max($forumId, 0);
if ($forumId === 0) { if ($forumId === 0) {

View file

@ -1,9 +1,11 @@
<?php <?php
require_once '../../misuzu.php'; require_once '../../misuzu.php';
switch ($_GET['m'] ?? '') { $indexMode = !empty($_GET['m']) && is_string($_GET['m']) ? (string)$_GET['m'] : '';
$forumId = !empty($_GET['f']) && is_string($_GET['f']) ? (int)$_GET['f'] : 0;
switch ($indexMode) {
case 'mark': case 'mark':
$forumId = (int)($_GET['f'] ?? null);
$markEntireForum = $forumId === 0; $markEntireForum = $forumId === 0;
if (user_session_active() && csrf_verify('forum_mark', $_GET['c'] ?? '')) { if (user_session_active() && csrf_verify('forum_mark', $_GET['c'] ?? '')) {

View file

@ -1,8 +1,9 @@
<?php <?php
require_once '../../misuzu.php'; require_once '../../misuzu.php';
$postId = (int)($_GET['p'] ?? 0); $postId = !empty($_GET['p']) && is_string($_GET['p']) ? (int)$_GET['p'] : 0;
$postMode = (string)($_GET['m'] ?? ''); $postMode = !empty($_GET['m']) && is_string($_GET['m']) ? (string)$_GET['m'] : '';
$submissionConfirmed = !empty($_GET['confirm']) && is_string($_GET['confirm']) && $_GET['confirm'] === '1';
// basing whether or not this is an xhr request on whether a referrer header is present // basing whether or not this is an xhr request on whether a referrer header is present
// this page is never directy accessed, under normal circumstances // this page is never directy accessed, under normal circumstances
@ -115,7 +116,7 @@ switch ($postMode) {
} }
if (!$isXHR) { if (!$isXHR) {
if ($postRequestVerified && isset($_GET['confirm']) && $_GET['confirm'] !== '1') { if ($postRequestVerified && !$submissionConfirmed) {
header("Location: " . url('forum-post', [ header("Location: " . url('forum-post', [
'post' => $postInfo['post_id'], 'post' => $postInfo['post_id'],
'post_fragment' => 'p' . $postInfo['post_id'], 'post_fragment' => 'p' . $postInfo['post_id'],
@ -165,7 +166,7 @@ switch ($postMode) {
} }
if (!$isXHR) { if (!$isXHR) {
if ($postRequestVerified && isset($_GET['confirm']) && $_GET['confirm'] !== '1') { if ($postRequestVerified && !$submissionConfirmed) {
header("Location: " . url('forum-post', [ header("Location: " . url('forum-post', [
'post' => $postInfo['post_id'], 'post' => $postInfo['post_id'],
'post_fragment' => 'p' . $postInfo['post_id'], 'post_fragment' => 'p' . $postInfo['post_id'],
@ -207,7 +208,7 @@ switch ($postMode) {
} }
if (!$isXHR) { if (!$isXHR) {
if ($postRequestVerified && isset($_GET['confirm']) && $_GET['confirm'] !== '1') { if ($postRequestVerified && !$submissionConfirmed) {
header("Location: " . url('forum-post', [ header("Location: " . url('forum-post', [
'post' => $postInfo['post_id'], 'post' => $postInfo['post_id'],
'post_fragment' => 'p' . $postInfo['post_id'], 'post_fragment' => 'p' . $postInfo['post_id'],

View file

@ -16,15 +16,15 @@ $forumPostingModes = [
]; ];
if (!empty($_POST)) { if (!empty($_POST)) {
$mode = $_POST['post']['mode'] ?? 'create'; $mode = !empty($_POST['post']['mode']) && is_string($_POST['post']['mode']) ? $_POST['post']['mode'] : 'create';
$postId = max(0, (int)($_POST['post']['id'] ?? 0)); $postId = !empty($_POST['post']['id']) && is_string($_POST['post']['id']) ? (int)$_POST['post']['id'] : 0;
$topicId = max(0, (int)($_POST['post']['topic'] ?? 0)); $topicId = !empty($_POST['post']['topic']) && is_string($_POST['post']['topic']) ? (int)$_POST['post']['topic'] : 0;
$forumId = max(0, (int)($_POST['post']['forum'] ?? 0)); $forumId = !empty($_POST['post']['forum']) && is_string($_POST['post']['forum']) ? (int)$_POST['post']['forum'] : 0;
} else { } else {
$mode = $_GET['m'] ?? 'create'; $mode = !empty($_GET['m']) && is_string($_GET['m']) ? $_GET['m'] : 'create';
$postId = max(0, (int)($_GET['p'] ?? 0)); $postId = !empty($_GET['p']) && is_string($_GET['p']) ? (int)$_GET['p'] : 0;
$topicId = max(0, (int)($_GET['t'] ?? 0)); $topicId = !empty($_GET['t']) && is_string($_GET['t']) ? (int)$_GET['t'] : 0;
$forumId = max(0, (int)($_GET['f'] ?? 0)); $forumId = !empty($_GET['f']) && is_string($_GET['f']) ? (int)$_GET['f'] : 0;
} }
if (!in_array($mode, $forumPostingModes, true)) { if (!in_array($mode, $forumPostingModes, true)) {

View file

@ -1,8 +1,10 @@
<?php <?php
require_once '../../misuzu.php'; require_once '../../misuzu.php';
$postId = (int)($_GET['p'] ?? 0); $postId = !empty($_GET['p']) && is_string($_GET['p']) ? (int)$_GET['p'] : 0;
$topicId = (int)($_GET['t'] ?? 0); $topicId = !empty($_GET['t']) && is_string($_GET['t']) ? (int)$_GET['t'] : 0;
$moderationMode = !empty($_GET['m']) && is_string($_GET['m']) ? (string)$_GET['m'] : '';
$submissionConfirmed = !empty($_GET['confirm']) && is_string($_GET['confirm']) && $_GET['confirm'] === '1';
$topicUserId = user_session_current('user_id', 0); $topicUserId = user_session_current('user_id', 0);
@ -53,7 +55,6 @@ $canDelete = !$topicIsDeleted && (
) )
); );
$moderationMode = (string)($_GET['m'] ?? '');
$validModerationModes = [ $validModerationModes = [
'delete', 'restore', 'nuke', 'delete', 'restore', 'nuke',
'bump', 'lock', 'unlock', 'bump', 'lock', 'unlock',
@ -91,7 +92,7 @@ if (in_array($moderationMode, $validModerationModes, true)) {
return; return;
} }
switch ($_GET['m'] ?? '') { switch ($moderationMode) {
case 'delete': case 'delete':
$canDeleteCode = forum_topic_can_delete($topic, $topicUserId); $canDeleteCode = forum_topic_can_delete($topic, $topicUserId);
$canDeleteMsg = ''; $canDeleteMsg = '';
@ -150,7 +151,7 @@ if (in_array($moderationMode, $validModerationModes, true)) {
} }
if (!$isXHR) { if (!$isXHR) {
if (isset($_GET['confirm']) && $_GET['confirm'] !== '1') { if (!$submissionConfirmed) {
header("Location: " . url( header("Location: " . url(
'forum-topic', 'forum-topic',
['topic' => $topic['topic_id']] ['topic' => $topic['topic_id']]
@ -202,7 +203,7 @@ if (in_array($moderationMode, $validModerationModes, true)) {
} }
if (!$isXHR) { if (!$isXHR) {
if (isset($_GET['confirm']) && $_GET['confirm'] !== '1') { if (!$submissionConfirmed) {
header("Location: " . url('forum-topic', [ header("Location: " . url('forum-topic', [
'topic' => $topic['topic_id'], 'topic' => $topic['topic_id'],
])); ]));
@ -245,7 +246,7 @@ if (in_array($moderationMode, $validModerationModes, true)) {
} }
if (!$isXHR) { if (!$isXHR) {
if (isset($_GET['confirm']) && $_GET['confirm'] !== '1') { if (!$submissionConfirmed) {
header('Location: ' . url('forum-topic', [ header('Location: ' . url('forum-topic', [
'topic' => $topic['topic_id'], 'topic' => $topic['topic_id'],
])); ]));

View file

@ -1,9 +1,9 @@
<?php <?php
require_once '../misuzu.php'; require_once '../misuzu.php';
$roleId = (int)($_GET['r'] ?? MSZ_ROLE_MAIN); $roleId = !empty($_GET['r']) && is_string($_GET['r']) ? (int)$_GET['r'] : MSZ_ROLE_MAIN;
$orderBy = mb_strtolower($_GET['ss'] ?? ''); $orderBy = !empty($_GET['ss']) && is_string($_GET['ss']) ? mb_strtolower($_GET['ss']) : '';
$orderDir = mb_strtolower($_GET['sd'] ?? ''); $orderDir = !empty($_GET['sd']) && is_string($_GET['sd']) ? mb_strtolower($_GET['sd']) : '';
$orderDirs = [ $orderDirs = [
'asc' => 'Ascending', 'asc' => 'Ascending',

View file

@ -1,10 +1,18 @@
<?php <?php
require_once '../misuzu.php'; require_once '../misuzu.php';
$categoryId = isset($_GET['c']) ? (int)$_GET['c'] : null; if (!empty($_GET['n']) && is_string($_GET['n'])) {
$postId = isset($_GET['p']) ? (int)$_GET['p'] : (isset($_GET['n']) ? (int)$_GET['n'] : null); header('Location: ' . url('news-post', [
'post' => (int)$_GET['n'],
]));
http_response_code(301);
return;
}
if ($postId !== null) { $categoryId = !empty($_GET['c']) && is_string($_GET['c']) ? (int)$_GET['c'] : 0;
$postId = !empty($_GET['p']) && is_string($_GET['p']) ? (int)$_GET['p'] : 0;
if ($postId > 0) {
$post = news_post_get($postId); $post = news_post_get($postId);
if (!$post) { if (!$post) {
@ -35,7 +43,7 @@ if ($postId !== null) {
return; return;
} }
if ($categoryId !== null) { if ($categoryId > 0) {
$category = news_category_get($categoryId, true); $category = news_category_get($categoryId, true);
if (empty($category)) { if (empty($category)) {

View file

@ -1,7 +1,11 @@
<?php <?php
require_once '../misuzu.php'; require_once '../misuzu.php';
$userId = user_find_for_profile($_GET['u'] ?? 0); $userId = !empty($_GET['u']) && is_string($_GET['u']) ? (int)$_GET['u'] : 0;
$profileMode = !empty($_GET['m']) && is_string($_GET['m']) ? (string)$_GET['m'] : '';
$isEditing = !empty($_GET['edit']) && is_string($_GET['edit']) ? (bool)$_GET['edit'] : !empty($_POST) && is_array($_POST);
$userId = user_find_for_profile($userId);
if ($userId < 1) { if ($userId < 1) {
http_response_code(404); http_response_code(404);
@ -9,8 +13,6 @@ if ($userId < 1) {
return; return;
} }
$mode = (string)($_GET['m'] ?? null);
$isEditing = !empty($_GET['edit']) || !empty($_POST);
$notices = []; $notices = [];
$currentUserId = user_session_current('user_id', 0); $currentUserId = user_session_current('user_id', 0);
@ -269,7 +271,7 @@ if (is_file($backgroundPath)) {
} }
} }
switch ($mode) { switch ($profileMode) {
default: default:
echo render_error(404); echo render_error(404);
return; return;
@ -379,7 +381,7 @@ switch ($mode) {
if (!empty($template)) { if (!empty($template)) {
echo tpl_render($template, [ echo tpl_render($template, [
'profile' => $profile, 'profile' => $profile,
'profile_mode' => $mode, 'profile_mode' => $profileMode,
'profile_notices' => $notices, 'profile_notices' => $notices,
'profile_can_edit' => $canEdit, 'profile_can_edit' => $canEdit,
'profile_is_editing' => $isEditing, 'profile_is_editing' => $isEditing,

View file

@ -32,8 +32,8 @@ if (user_warning_check_expiration($userId, MSZ_WARN_BAN) > 0) {
return; return;
} }
$subjectId = (int)($_GET['u'] ?? 0); $subjectId = !empty($_GET['u']) && is_string($_GET['u']) ? (int)$_GET['u'] : 0;
$relationType = (int)($_GET['m'] ?? -1); $relationType = !empty($_GET['m']) && is_string($_GET['m']) ? (int)$_GET['m'] : -1;
if (!user_relation_is_valid_type($relationType)) { if (!user_relation_is_valid_type($relationType)) {
echo render_info_or_json($isXHR, 'Invalid relation type.', 400); echo render_info_or_json($isXHR, 'Invalid relation type.', 400);

View file

@ -1,10 +1,10 @@
<?php <?php
$userAssetsMode = (string)($_GET['m'] ?? null); $userAssetsMode = !empty($_GET['m']) && is_string($_GET['m']) ? (string)$_GET['m'] : '';
$misuzuBypassLockdown = $userAssetsMode === 'avatar'; $misuzuBypassLockdown = $userAssetsMode === 'avatar';
require_once '../misuzu.php'; require_once '../misuzu.php';
$userId = (int)($_GET['u'] ?? 0); $userId = !empty($_GET['u']) && is_string($_GET['u']) ? (int)$_GET['m'] : 0;
$userExists = user_exists($userId); $userExists = user_exists($userId);
$canViewImages = !$userExists $canViewImages = !$userExists

View file

@ -107,7 +107,11 @@ function csrf_token(string $realm): string
function csrf_verify(string $realm, $token): bool function csrf_verify(string $realm, $token): bool
{ {
$token = (string)(is_array($token) && !empty($token[$realm]) ? $token[$realm] : $token); $token = is_array($token) && !empty($token[$realm]) ? $token[$realm] : $token;
if (!is_string($token)) {
return false;
}
return csrf_token_verify( return csrf_token_verify(
$realm, $realm,

View file

@ -43,5 +43,9 @@ function pagination_offset(array &$pagination, ?int $page): int
function pagination_param(string $name = 'p', int $default = 1, ?array $source = null): int function pagination_param(string $name = 'p', int $default = 1, ?array $source = null): int
{ {
if (!isset(($source ?? $_GET)[$name]) || !is_string(($source ?? $_GET)[$name])) {
return $default;
}
return (int)(($source ?? $_GET)[$name] ?? $default); return (int)(($source ?? $_GET)[$name] ?? $default);
} }