Parameterize registration.php; atomic player delete

- All staff paths (build, lock, edit, editgame, delete, add, search) and the
  render SELECTs now use db.php helpers with bound params. Removes SQL injection
  via playerid/missionid/callsign/newtype/newmap/buildmissions.
- Delete routes through new pqs_remove_player() (shared lock + transaction,
  resyncs numplayers from real occupancy instead of a raw numplayers-1).
- Drop a stray buggy line ($callsign from an undefined $line) and guard
  $_SERVER['SERVER_ADDR']. build now sets nummercs=0 (strict-mode safe).

Verified on the stack: build/edit/delete/editgame/lock/search all work; delete
resyncs numplayers; no errors.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Cyd
2026-07-01 14:04:04 -05:00
co-authored by Claude Opus 4.8
parent 5aa01db123
commit 530326b8e4
2 changed files with 91 additions and 169 deletions
+24
View File
@@ -96,6 +96,30 @@ function pqs_enqueue_player(string $callsign, string $mech, int $merc = 0): int
});
}
/**
* Atomically remove a player from the queue and resync their mission's
* numplayers from actual occupancy. Under the shared lock so it can't race a
* concurrent registration/commit.
*/
function pqs_remove_player(int $playerid): void
{
pqs_with_queue_lock(function () use ($playerid) {
$db = pqs_db();
$db->begin_transaction();
try {
$row = pqs_row("SELECT MissionID FROM pqs_queue WHERE ID = ?", 'i', [$playerid]);
pqs_exec("DELETE FROM pqs_queue WHERE ID = ?", 'i', [$playerid]);
if ($row !== null && $row['MissionID'] !== null) {
pqs_sync_numplayers((int) $row['MissionID']);
}
$db->commit();
} catch (Throwable $e) {
$db->rollback();
throw $e;
}
});
}
/**
* Atomically add a player to a SPECIFIC mission (staff "new" action). Does not
* pick a mission or enforce capacity — staff may intentionally overfill — but
+67 -169
View File
@@ -20,6 +20,8 @@ var auto_refreshqueue = setInterval(function() {
//var_dump($_POST);
//var_dump($_SESSION);
include_once("includes/config.php");
require_once("includes/db.php");
require_once("includes/queue.php");
date_default_timezone_set('America/Chicago');
$tdate = date('Ymd');
$ttime = date('Hi');
@@ -31,58 +33,36 @@ $merc = 0;
$callsign = "";
$nummissions = 0;
$mech = "";
$server = $_SERVER['SERVER_ADDR'];
$server = $_SERVER['SERVER_ADDR'] ?? '';
if (isset($_GET['build'])) {
$buildmissions = $_GET['buildmissions'];
while ($buildmissions > 0){
$link = mysqli_connect('localhost', 'pqs', 'pqs') or die('Could not connect: ' . mysqli_error($link));
mysqli_select_db($link, 'pqs') or die('Could not select database');
$sql = "INSERT INTO pqs_mission (MissionDate, MissionSize, numplayers, MissionTime) VALUES ($tdate, $missionsize, 0, $ttime)";
mysqli_query($link, $sql) or die('Query failed: ' . mysqli_error($link));
$buildmissions--;
$buildmissions = (int)($_GET['buildmissions'] ?? 0);
for ($b = 0; $b < $buildmissions; $b++) {
pqs_exec("INSERT INTO pqs_mission (MissionDate, MissionSize, numplayers, nummercs, MissionTime) VALUES (?, ?, 0, 0, ?)",
'iii', array((int)$tdate, (int)$missionsize, (int)$ttime));
}
}
if (isset($_GET['clearcurrent'])) {
$link = mysqli_connect('localhost', 'pqs', 'pqs') or die('Could not connect: ' . mysqli_error($link));
mysqli_select_db($link, 'pqs') or die('Could not select database');
$sql = "TRUNCATE TABLE pqs_currentmission";
mysqli_query($link, $sql) or die('Query failed: ' . mysqli_error($link));
mysqli_close($link);
pqs_db()->query("TRUNCATE TABLE pqs_currentmission");
}
if (isset($_GET['lock'])) {
$link = mysqli_connect('localhost', 'pqs', 'pqs') or die('Could not connect: ' . mysqli_error($link));
mysqli_select_db($link, 'pqs') or die('Could not select database');
if (isset($_GET['missionid'])) {
$missionid = $_GET['missionid'];
}else{
$sql = "SELECT MIN(MissionID) FROM pqs_queue";
$getid = mysqli_query($link, $sql) or die('Query failed: ' . mysqli_error($link));
$rs = mysqli_fetch_array($getid);
$missionid = $rs[0];
$missionid = (int)$_GET['missionid'];
} else {
$missionid = (int) pqs_val("SELECT MIN(MissionID) FROM pqs_queue");
}
if ($missionid > 0) {
pqs_exec("UPDATE pqs_mission SET locked=1 WHERE MissionID=?", 'i', array($missionid));
}
$sql = "UPDATE pqs_mission SET locked=1 WHERE MissionID=$missionid";
mysqli_query($link, $sql) or die('Query failed: ' . mysqli_error($link));
mysqli_close($link);
}
if (isset($_POST['edit'])) {
if (isset($_POST['playerid'])) $playerid = $_POST['playerid'];
if (isset($_POST['callsign'])) $callsign = str_replace("'", "''", $_POST['callsign']);
if (isset($_POST['mech'])) $mech = $_POST['mech'];
$link = mysqli_connect('localhost', 'pqs', 'pqs') or die('Could not connect: ' . mysqli_error($link));
mysqli_select_db($link, 'pqs') or die('Could not select database');
$sql = "UPDATE pqs_queue SET Callsign='$callsign', mech='$mech', Updated=1 WHERE id=$playerid";
mysqli_query($link, $sql) or die('Update player in Queue failed: ' . mysqli_error($link));
mysqli_close($link);
$playerid = (int)($_POST['playerid'] ?? 0);
$callsign = isset($_POST['callsign']) ? $_POST['callsign'] : '';
$mech = isset($_POST['mech']) ? $_POST['mech'] : '';
pqs_exec("UPDATE pqs_queue SET Callsign=?, mech=?, Updated=1 WHERE id=?", 'ssi', array($callsign, $mech, $playerid));
}
if (isset($_POST['add'])) {
@@ -107,41 +87,28 @@ if (isset($_POST['new'])) {
}
if (isset($_POST['editgame'])) {
$newtype = $_POST['newtype'];
$newmap = $_POST['newmap'];
$missionid = $_GET['missionid'];
$link = mysqli_connect('localhost', 'pqs', 'pqs') or die('Could not connect: ' . mysqli_error($link));
mysqli_select_db($link, 'pqs') or die('Could not select database');
$sql = "UPDATE pqs_mission SET GameType='$newtype', map='$newmap' WHERE MissionID=$missionid";
mysqli_query($link, $sql) or die('Update player in Queue failed: ' . mysqli_error($link));
mysqli_close($link);
$newtype = (int)($_POST['newtype'] ?? 0);
$newmap = (int)($_POST['newmap'] ?? 0);
$missionid = (int)($_GET['missionid'] ?? 0);
pqs_exec("UPDATE pqs_mission SET GameType=?, map=? WHERE MissionID=?", 'iii', array($newtype, $newmap, $missionid));
}
if (isset($_GET['action'])) {
$action = $_GET['action'];
if (isset($_GET['playerid'])) $playerid = $_GET['playerid'];
if (isset($_GET['missionid'])) $missionid = $_GET['missionid'];
if (isset($_GET['callsign'])) $callsign = $_GET['callsign'];
if (isset($_GET['mech'])) $mech = $_GET['mech'];
if (isset($_GET['oldmap'])) $oldmap = $_GET['oldmap'];
if (isset($_GET['oldtype'])) $oldtype = $_GET['oldtype'];
$callsign=str_replace("'", "&apos;", $line[0]);
$playerid = (int)($_GET['playerid'] ?? 0);
$missionid = (int)($_GET['missionid'] ?? 0);
$mech = $_GET['mech'] ?? '';
$oldmap = (int)($_GET['oldmap'] ?? 0);
$oldtype = (int)($_GET['oldtype'] ?? 0);
$callsign = "";
$nextmission = $missionid + 1;
switch ($action) {
case "edit":
$link = mysqli_connect('localhost', 'pqs', 'pqs') or die('Could not connect: ' . mysqli_error($link));
mysqli_select_db($link, 'pqs') or die('Could not select database');
$row = pqs_row("SELECT * FROM pqs_queue WHERE ID = ?", 'i', array($playerid));
$callsign = $row['CallSign'] ?? '';
$mech = $row['Mech'] ?? '';
$sql = "SELECT * FROM pqs_queue WHERE ID = $playerid";
$result = mysqli_query($link, $sql) or die('Select player from Queue failed: ' . mysqli_error($link));
$rs = mysqli_fetch_array($result);
$callsign = $rs[0];
$mech = $rs[1];
echo "<form action='registration.php";if (isset($_GET['missionid'])) {$missionid = $_GET['missionid'];echo"?missionid=$missionid";};echo"' method='post'>";
echo "<form action='registration.php";if (isset($_GET['missionid'])) {$missionid = (int)$_GET['missionid'];echo"?missionid=$missionid";};echo"' method='post'>";
echo "<table align='center'><tr><td align='center'>";
echo "<div id='editqueue' class='queuedivreg'>";
echo "<table border='0' align='center'><tr>";
@@ -151,14 +118,10 @@ if (isset($_GET['action'])) {
echo "<td width='40%' align='center'>";
echo "<select class='editqueue' name='mech'>";
$query = 'SELECT * FROM pqs_mechinfo ORDER BY mechname';
$result = mysqli_query($link, $query) or die('Query failed: ' . mysqli_error($link));
while ($line = mysqli_fetch_array($result)) {
if ($line[1] == $mech) {
echo "<option value='$line[1]' selected>$line[1]</option>";
} else {
echo "<option value='$line[1]'>$line[1]</option>";
}
foreach (pqs_rows('SELECT * FROM pqs_mechinfo ORDER BY mechname') as $m) {
$mn = $m['MechName'];
$sel = ($mn == $mech) ? ' selected' : '';
echo "<option value='$mn'$sel>$mn</option>";
}
echo "</td>";
@@ -167,39 +130,19 @@ if (isset($_GET['action'])) {
echo "<input type='hidden' name='edit' value='commit'>";
echo "</table></div>";
echo "</td></tr></table></form>";
mysqli_close($link);
break;
case "delete":
$link = mysqli_connect('localhost', 'pqs', 'pqs') or die('Could not connect: ' . mysqli_error($link));
mysqli_select_db($link, 'pqs') or die('Could not select database');
$sql = "SELECT COUNT(CallSign) FROM pqs_queue";
$result = mysqli_query($link, $sql) or die('Delete player from Queue failed: ' . mysqli_error($link));
$line = mysqli_fetch_array($result);
$queuecount = $line[0];
$sql = "DELETE FROM pqs_queue WHERE id = $playerid";
$result = mysqli_query($link, $sql) or die('Delete player from Queue failed: ' . mysqli_error($link));
$sql = "UPDATE pqs_mission SET numplayers = numplayers - 1 WHERE missionid = $missionid";
$result = mysqli_query($link, $sql) or die('Update mission after delete player failed: ' . mysqli_error($link));
mysqli_close($link);
pqs_remove_player($playerid);
break;
case "add":
$link = mysqli_connect('localhost', 'pqs', 'pqs') or die('Could not connect: ' . mysqli_error($link));
mysqli_select_db($link, 'pqs') or die('Could not select database');
$sql = "SELECT * FROM pqs_queue WHERE ID = $playerid";
$result = mysqli_query($link, $sql) or die('Delete player from Queue failed: ' . mysqli_error($link));
$rs = mysqli_fetch_array($result);
$callsign = str_replace("'", "&apos;", $rs[0]);
$mech = $rs[1];
$merc = $rs[4];
$missionid = $rs[3];
echo "<form action='registration.php";if (isset($_GET['missionid'])) {$missionid = $_GET['missionid'];echo"?missionid=$missionid";};echo"' method='post'>";
$row = pqs_row("SELECT * FROM pqs_queue WHERE ID = ?", 'i', array($playerid));
$callsign = str_replace("'", "&apos;", $row['CallSign'] ?? '');
$mech = $row['Mech'] ?? '';
$merc = $row['Merc'] ?? 0;
$missionid = (int)($row['MissionID'] ?? 0);
echo "<form action='registration.php";if (isset($_GET['missionid'])) {$missionid = (int)$_GET['missionid'];echo"?missionid=$missionid";};echo"' method='post'>";
echo "<table width='650' align='center'>";
echo "<tr><td align='center'>";
echo "<div id='editqueue' class='queuedivreg'>";
@@ -215,14 +158,10 @@ if (isset($_GET['action'])) {
echo "<input type='hidden' name='add' value='commit'>";
echo "</table></div>";
echo "</td></tr></table></form>";
mysqli_close($link);
break;
case "editgame":
$link = mysqli_connect('localhost', 'pqs', 'pqs') or die('Could not connect: ' . mysqli_error($link));
mysqli_select_db($link, 'pqs') or die('Could not select database');
echo "<form name='editgame' action='registration.php";if (isset($_GET['missionid'])) {$missionid = $_GET['missionid'];echo"?missionid=$missionid";};echo"' method='post'>";
echo "<form name='editgame' action='registration.php";if (isset($_GET['missionid'])) {$missionid = (int)$_GET['missionid'];echo"?missionid=$missionid";};echo"' method='post'>";
echo "<input type='hidden' name='editgame' value='editgame'>";
echo "<table align='center'><tr><td align='center'>";
echo "<div id='edittype' class='queuedivreg'>";
@@ -231,32 +170,18 @@ if (isset($_GET['action'])) {
echo "<td width='40%' align='center'>";
echo "<select class='edittype' name='newtype' onchange='changeIt(this.options[this.selectedIndex].value)'>";
$sql = "SELECT * FROM pqs_gametype";
$result = mysqli_query($link, $sql) or die('Select player from Queue failed: ' . mysqli_error($link));
while ($line = mysqli_fetch_array($result)) {
if ($line[0] == $oldtype) {
echo "<option value='$line[0]' selected>$line[1]</option>
";
} else {
echo "<option value='$line[0]'>$line[1]</option>
";
}
foreach (pqs_rows("SELECT * FROM pqs_gametype") as $t) {
$sel = ($t['TypeID'] == $oldtype) ? ' selected' : '';
echo "<option value='{$t['TypeID']}'$sel>{$t['TypeName']}</option>\n\t\t\t\t\t";
}
echo "</td>";
echo "<td width='30%' align='center'>";
echo "<select class='editmap' name='newmap'>";
$sql = "SELECT * FROM pqs_mapinfo";
$result = mysqli_query($link, $sql) or die('Select player from Queue failed: ' . mysqli_error($link));
while ($line = mysqli_fetch_array($result)) {
if ($line[0] == $oldmap) {
echo "<option value='$line[0]' selected>$line[1]</option>";
} else {
echo "<option value='$line[0]'>$line[1]</option>";
}
foreach (pqs_rows("SELECT * FROM pqs_mapinfo") as $mp) {
$sel = ($mp['MapID'] == $oldmap) ? ' selected' : '';
echo "<option value='{$mp['MapID']}'$sel>{$mp['MapName']}</option>";
}
echo "</td>";
@@ -264,9 +189,6 @@ if (isset($_GET['action'])) {
echo "<input type='hidden' name='missionid' value='$missionid'>";
echo "</table></div>";
echo "</td></tr></table></form>";
mysqli_close($link);
break;
}
}
@@ -283,13 +205,8 @@ echo "</td></tr>";
// add player form
if($missionid==0){
$link = mysqli_connect('localhost', 'pqs', 'pqs') or die('Could not connect: ' . mysqli_error($link));
mysqli_select_db($link, 'pqs') or die('Could not select database');
$query = 'SELECT min(MissionID) FROM pqs_queue';
$result = mysqli_query($link, $query) or die('Query failed: ' . mysqli_error($link));
$line = mysqli_fetch_array($result);
$missionid = $line[0];
}
$missionid = (int) pqs_val('SELECT MIN(MissionID) FROM pqs_queue');
}
echo "<form action='registration.php";if (isset($_GET['missionid'])) {$missionid = $_GET['missionid'];echo"?missionid=$missionid";};echo"' method='post'>";
echo "<table align='center'><tr><td align='center'>";
echo "<div id='addqueue' class='queuedivreg'>";
@@ -299,13 +216,8 @@ echo "<table border='0' align='center'>";
echo "<tr><td width='10%' align='center'><a class='queuedisplayhead' href='registration.php'><font size='2'>Back to Current</font></a></td><td width='10%' class='consoledisplayhead' align='left'>M: $missionid</td><td width='40%' class='consoledisplayhead' align='center'>CS: <input class='editqueue' type='text' name='callsign' size='16' maxlength='16' /><input type='hidden' name='missionid' value='$missionid'></td>";
echo "<td width='30%' align='center'>";
echo "<select class='addqueue' name='mech'>";
$link = mysqli_connect('localhost', 'pqs', 'pqs') or die('Could not connect: ' . mysqli_error($link));
mysqli_select_db($link, 'pqs') or die('Could not select database');
$query = 'SELECT * FROM pqs_mechinfo ORDER BY mechname';
$result = mysqli_query($link, $query) or die('Query failed: ' . mysqli_error($link));
while ($line = mysqli_fetch_array($result)) {
echo "<option value='$line[1]'>$line[1]</option>
";
foreach (pqs_rows('SELECT * FROM pqs_mechinfo ORDER BY mechname') as $m) {
echo "<option value='{$m['MechName']}'>{$m['MechName']}</option>\n\t\t";
}
echo "</td><td align='center' width='10'><input type='submit' name='new' class='button' id='action' value='new' /></td></tr></table>";
echo "</tr></table></form>";
@@ -336,46 +248,32 @@ echo "</table>";
// search results //
if(isset($_GET['search'])){
if (isset($_GET['callsign'])){
$cs = str_replace("'", "&;", $_GET['callsign']);
$cs = isset($_GET['callsign']) ? str_replace("'", "&;", $_GET['callsign']) : '';
if($cs == ''){$cs = 'unknown';}
}
echo "<center><div class='queuedivreg'><table align='center'>";
echo "<tr><td colspan='5' class='queuedisplayhead'><font size='6'>Mission(s) : $cs</font></td></tr>";
echo "<tr><td class='queuedisplayhead' width='20%'>CallSign</td><td class='queuedisplayhead' width='20%'>Mission</td><td class='queuedisplayhead' width='20%'>ETD</td><td class='queuedisplayhead' width='20%'>Mech</td><td class='queuedisplayhead' width='20%'>Edit/Delete</td></tr>";
// fetch data //
$link = mysqli_connect('localhost', 'pqs', 'pqs') or die('Could not connect: ' . mysqli_error($link));
mysqli_select_db($link, 'pqs') or die('Could not select database');
// get last commit time and mission id
$query = "SELECT max(MissionID), max(UNIX_TIMESTAMP(ctime)) FROM pqs_pastmissions";
$getlct = mysqli_query($link, $query) or die('Query failed: ' . mysqli_error($link));
$rs2 = mysqli_fetch_array($getlct);
$lastmission = $rs2[0];
if(is_null($lastmission)){$lastmission = 0;}
$lastCommitTime = $rs2[1];// utc -H*mm*sc
if(is_null($lastCommitTime)){$lastCommitTime = time();}//-(6*60*60);}
$rs2 = pqs_row("SELECT max(MissionID) AS m, max(UNIX_TIMESTAMP(ctime)) AS t FROM pqs_pastmissions");
$lastmission = (int)($rs2['m'] ?? 0);
$lastCommitTime = $rs2['t'] ?? null;
if(is_null($lastCommitTime)){$lastCommitTime = time();}
// get time per game //
$query = "SELECT timepergame, timetoreset FROM pqs_gameconfig";
$gettpg = mysqli_query($link, $query) or die('Query failed: ' . mysqli_error($link));
$rs1 = mysqli_fetch_array($gettpg);
$tpg = $rs1[0]+$rs1[1];
$cfg = pqs_row("SELECT timepergame, timetoreset FROM pqs_gameconfig");
$tpg = (int)$cfg['timepergame'] + (int)$cfg['timetoreset'];
$query = "SELECT * FROM pqs_queue WHERE CallSign LIKE '$cs' ORDER BY MissionID";
$result = mysqli_query($link, $query) or die('Query failed: ' . mysqli_error($link));
while ($line = mysqli_fetch_array($result)) {
$mtd = ($line[3] - $lastmission) * $tpg;
foreach (pqs_rows("SELECT * FROM pqs_queue WHERE CallSign LIKE ? ORDER BY MissionID", 's', array($cs)) as $line) {
$mtd = ($line['MissionID'] - $lastmission) * $tpg;
$d=strtotime("+$mtd Minutes",$lastCommitTime);
$etd = date("h:i", $d);
$c = $line['CallSign']; $mid = $line['MissionID']; $pid = $line['ID']; $mch = $line['Mech'];
echo "<tr><td class='queuedisplay'>$line[0]</td><td class='queuedisplay'>$line[3]</td><td class='queuedisplay'>$etd</td><td class='queuedisplay'>$line[1]</td><td class='queuedisplay'>";
echo "<a href='registration.php?action=edit&playerid=$line[2]&missionid=$line[3]' title='Edit $line[0]&apos;s information'><img src='images/edit.png' border='0' height='22'></a>&nbsp;&nbsp;";
echo "<a href='registration.php?action=delete&playerid=$line[2]&missionid=$line[3]' title='Delete $line[0] from queue'><img src='images/delete.png' border='0' height='22'></a>&nbsp;&nbsp;";
echo "<tr><td class='queuedisplay'>$c</td><td class='queuedisplay'>$mid</td><td class='queuedisplay'>$etd</td><td class='queuedisplay'>$mch</td><td class='queuedisplay'>";
echo "<a href='registration.php?action=edit&playerid=$pid&missionid=$mid' title='Edit $c&apos;s information'><img src='images/edit.png' border='0' height='22'></a>&nbsp;&nbsp;";
echo "<a href='registration.php?action=delete&playerid=$pid&missionid=$mid' title='Delete $c from queue'><img src='images/delete.png' border='0' height='22'></a>&nbsp;&nbsp;";
echo "</td></tr>";
}