ChatGPT's update to harden software and run db updates.

This commit is contained in:
2026-10-21 06:53:45 -04:00
parent 1e63076123
commit acc8cb70f5
171 changed files with 9325 additions and 404 deletions
+28 -10
View File
@@ -15,7 +15,7 @@ class Base {
const APPLICATION_NAME = "My Hunting Club Roster";
const APPLICATION_MNEMONIC = "HUNTINGCLUBROSTER";
const VERSION = "1.00";
const VERSION = "1.04";
const TIMEZONE = "America/New_York";
// =================
// Session Variables
@@ -176,7 +176,7 @@ class Base {
public function displayContent($content = "") {
$html = $this->applyXSL("", $this->getXSL("content"));
$html = $this->applyXSL("", $this->getXSL("content"), ["IS_SUPER"=>(new TenantAccess())->isSuper()?"1":"0","CAN_MANAGE_CLUBS" => (new TenantAccess())->managesAny()?"1":"0"]);
$html = str_replace("$$$-CONTENT-$$$", $content, $html);
echo $html;
@@ -245,11 +245,18 @@ class Base {
exit('Method not allowed.');
}
// Reject arrays and oversized values before passing input to string operations.
foreach (array_merge($_GET, $_POST) as $value) {
if (!is_string($value) || strlen($value) > 8192) {
http_response_code(400);
exit('Invalid request.');
// Ticket bodies need room for 8,000 four-byte Unicode characters. Keep
// a hard transport ceiling; field validators enforce the character limit.
$candidate=$_POST['action']??$_GET['Xaction']??$_GET['action']??'';
$ticketSubmission=is_string($candidate)&&strtolower(trim($candidate))==='roster.tickets'
&& in_array($_POST['step']??null,['openTicket','reply'],true);
foreach ([$_GET,$_POST] as $source=>$values) {
foreach($values as $field=>$value){
$byteLimit=$source===1&&$ticketSubmission&&$field==='message'?65536:8192;
if (!is_string($value) || strlen($value) > $byteLimit) {
http_response_code(400);
exit('Invalid request.');
}
}
}
$action = strtolower(trim($_POST['action'] ?? $_GET['Xaction'] ?? $_GET['action'] ?? ''));
@@ -296,6 +303,12 @@ class Base {
if ($method === 'POST') {
$this->requireCsrf();
}
$mfa=new MfaService();
if($mfa->gate($user,$action))return;
$sensitive=in_array($action,['users.changepassword','users.adduser','users.edituser','users.deleteuser','users.updateactivestatus','users.useractive','users.resetpassword'],true)
|| ($action==='roster.membersummary' && ($_POST['step']??'')==='member')
|| ($action==='roster.workspace' && (($_POST['step']??'')==='member' || (($_POST['step']??'')==='invite' && ($_POST['membership_role']??'')==='administrator')));
if($method==='POST' && $sensitive && (new TenantAccess())->managesAny())$mfa->requireRecent();
if ((bool) $user['user_change_password']) {
(new Users())->changePassword();
return;
@@ -312,7 +325,12 @@ class Base {
'getage' => [Base::class, 'getAge', false],
'users.changepassword' => [Users::class, 'changePassword', false],
'roster.workspace' => [Roster::class,'workspace',false],
'roster.membersummary' => [MemberSummary::class,'show',false],
'roster.createclub' => [Roster::class,'createClub','super'],
'roster.help' => [Roster::class,'help',false],
'roster.invitations' => [Roster::class,'invitations',false],
'roster.tickets' => [Roster::class,'tickets',false],
'rosterreports.catalog' => [RosterReports::class,'catalog',true],
'rosterreports.ledger' => [RosterReports::class,'ledger',true],
'rosterreports.csv' => [RosterReports::class,'csv',true],
'rosterreports.excel' => [RosterReports::class,'excel',true],
@@ -334,7 +352,7 @@ class Base {
];
foreach ($adminRoutes as $class => $methods) {
foreach ($methods as $entry) {
$routes[strtolower($class . '.' . $entry)] = [$class, $entry, true];
$routes[strtolower($class . '.' . $entry)] = [$class, $entry, $class==='Reports'?true:'super'];
}
}
if (!isset($routes[$action])) {
@@ -342,11 +360,11 @@ class Base {
exit('Page not found.');
}
[$class, $entry, $adminOnly] = $routes[$action];
if ($adminOnly && !in_array($user['user_role'], ['Administrator', 'System Administrator'], true)) {
if (($adminOnly==='super' && !(new TenantAccess())->isSuper()) || ($adminOnly===true && !(new TenantAccess())->managesAny())) {
http_response_code(403);
exit('You do not have permission to perform this action.');
}
if ($method !== 'POST' && !in_array($action, ['', './', 'displayhome', 'users.changepassword','roster.workspace','roster.help'], true)) {
if ($method !== 'POST' && !in_array($action, ['', './', 'displayhome', 'users.changepassword','roster.workspace','roster.membersummary','roster.createclub','roster.help','roster.invitations','roster.tickets','rosterreports.catalog'], true)) {
http_response_code(405);
exit('Use POST for this action.');
}