Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion PcAssignCashToTab.php
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@
echo '<input type="hidden" name="FormID" value="', $_SESSION['FormID'], '" />';
$SQL = "SELECT tabcode
FROM pctabs
WHERE assigner='" . $_SESSION['UserID'] . "'
WHERE FIND_IN_SET('" . $_SESSION['UserID'] . "', REPLACE(assigner, ' ', '')) > 0
ORDER BY tabcode";
$Result = DB_query($SQL);
echo '<fieldset>
Expand Down
3 changes: 2 additions & 1 deletion PcAuthorizeCash.php
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,8 @@ functionalexrate,
echo '<input type="hidden" name="FormID" value="', $_SESSION['FormID'], '" />';
$SQL = "SELECT tabcode
FROM pctabs
WHERE authorizer='" . $_SESSION['UserID'] . "'";
WHERE CONCAT(',', authorizer, ',') LIKE '%," . $_SESSION['UserID'] . ",%'
ORDER BY tabcode";
$Result = DB_query($SQL);
echo '<table class="selection">
<tr>
Expand Down
11 changes: 6 additions & 5 deletions PcAuthorizeExpenses.php
Original file line number Diff line number Diff line change
Expand Up @@ -344,15 +344,16 @@
/*The option to submit was not hit so display form */
echo '<form method="post" action="', htmlspecialchars($_SERVER['PHP_SELF'], ENT_QUOTES, 'UTF-8'), '">';
echo '<input type="hidden" name="FormID" value="', $_SESSION['FormID'], '" />';
echo '<fieldset>'; //Main table

$SQL = "SELECT tabcode
FROM pctabs
WHERE authorizerexpenses='" . $_SESSION['UserID'] . "'
WHERE authorizerexpenses LIKE '%" . $_SESSION['UserID'] . "%'

Copilot AI Apr 26, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

authorizerexpenses is now treated as a comma-separated list; using LIKE '%%' can match partial IDs and show tabs to the wrong users. Switch to delimiter-aware matching so only whole user IDs match.

Suggested change
WHERE authorizerexpenses LIKE '%" . $_SESSION['UserID'] . "%'
WHERE CONCAT(',', authorizerexpenses, ',') LIKE '%," . $_SESSION['UserID'] . ",%'

Copilot uses AI. Check for mistakes.
ORDER BY tabcode";
$Result = DB_query($SQL);
echo '<field>
<td>', __('Authorise expenses on petty cash tab'), ':</td>
<td><select required="required" name="SelectedTabs">';
echo '<fieldset>
<field>
<label>', __('Authorise expenses on petty cash tab'), '</label>
<select required="required" name="SelectedTabs">';
while ($MyRow = DB_fetch_array($Result)) {
if (isset($_POST['SelectTabs']) and $MyRow['tabcode'] == $_POST['SelectTabs']) {
echo '<option selected="selected" value="', $MyRow['tabcode'], '">', $MyRow['tabcode'], '</option>';
Expand Down
12 changes: 6 additions & 6 deletions PcReportExpense.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@
AND pcashdetails.codeexpense='".$SelectedExpense."'
AND pcashdetails.date >='" . $SQL_FromDate . "'
AND pcashdetails.date <= '" . $SQL_ToDate . "'
AND (pctabs.authorizer='" . $_SESSION['UserID'] .
"' OR pctabs.usercode ='" . $_SESSION['UserID'].
"' OR pctabs.assigner ='" . $_SESSION['UserID'] . "')
AND (pctabs.authorizer LIKE '%" . $_SESSION['UserID'] . "%'
OR pctabs.usercode = '" . $_SESSION['UserID'] . "'
OR pctabs.assigner LIKE '%" . $_SESSION['UserID'] . "%' )
Comment on lines +65 to +67

Copilot AI Apr 26, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This authorization predicate uses LIKE '%%' against a comma-separated list, which can match partial user IDs and leak data. Update the predicate to match whole IDs using delimiter-aware matching (or a normalized join table) rather than substring LIKE.

Suggested change
AND (pctabs.authorizer LIKE '%" . $_SESSION['UserID'] . "%'
OR pctabs.usercode = '" . $_SESSION['UserID'] . "'
OR pctabs.assigner LIKE '%" . $_SESSION['UserID'] . "%' )
AND (FIND_IN_SET('" . $_SESSION['UserID'] . "', REPLACE(pctabs.authorizer, ' ', '')) > 0
OR pctabs.usercode = '" . $_SESSION['UserID'] . "'
OR FIND_IN_SET('" . $_SESSION['UserID'] . "', REPLACE(pctabs.assigner, ' ', '')) > 0)

Copilot uses AI. Check for mistakes.
ORDER BY pcashdetails.date, pcashdetails.counterindex ASC";

$Result = DB_query($SQL,
Expand Down Expand Up @@ -218,9 +218,9 @@
$SQL = "SELECT DISTINCT(pctabexpenses.codeexpense)
FROM pctabs, pctabexpenses
WHERE pctabexpenses.typetabcode = pctabs.typetabcode
AND ( pctabs.authorizer='" . $_SESSION['UserID'] .
"' OR pctabs.usercode ='" . $_SESSION['UserID'].
"' OR pctabs.assigner ='" . $_SESSION['UserID'] . "' )
AND (CONCAT(',', pctabs.authorizer, ',') LIKE '%," . $_SESSION['UserID'] . ",%'
OR pctabs.usercode = '" . $_SESSION['UserID'] . "'
OR CONCAT(',', pctabs.assigner, ',') LIKE '%," . $_SESSION['UserID'] . ",%' )
ORDER BY pctabexpenses.codeexpense";

$Result = DB_query($SQL);
Expand Down
6 changes: 3 additions & 3 deletions PcReportTab.php
Original file line number Diff line number Diff line change
Expand Up @@ -341,9 +341,9 @@

$SQL = "SELECT tabcode
FROM pctabs
WHERE ( authorizer = '" . $_SESSION['UserID'] .
"' OR usercode = '" . $_SESSION['UserID'].
"' OR assigner = '" . $_SESSION['UserID'] . "' )
WHERE ( CONCAT(',', authorizer, ',') LIKE '%," . $_SESSION['UserID'] . ",%'
OR usercode = '" . $_SESSION['UserID'] . "'
OR CONCAT(',', assigner, ',') LIKE '%," . $_SESSION['UserID'] . ",%' )
ORDER BY tabcode";
$Result = DB_query($SQL);

Expand Down
78 changes: 59 additions & 19 deletions PcTabs.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
include(__DIR__ . '/includes/header.php');

echo '<p class="page_title_text">
<img src="', $RootPath, '/css/', $_SESSION['Theme'], '/images/money_add.png" title="', __('Payment Entry'), '" alt="" />', ' ', $Title, '
<img src="', $RootPath, '/css/', $_SESSION['Theme'], '/images/money_add.png" title="', $Title, '" alt="" />', ' ', $Title, '
</p>';

if (isset($_POST['SelectedTab'])) {
Expand Down Expand Up @@ -63,14 +63,41 @@
$InputError = 1;
prnMsg(__('You must select a tax group'), 'error');
}

if ($InputError == 0) {
$AuthorisersExpenses = '';
$i = 0;
foreach ($_POST['SelectAuthoriserExpenses'] as $Value) {
if ($i) $AuthorisersExpenses .= ',';
$AuthorisersExpenses .= $Value;
$i++;
}

$AuthorisersCash = '';
$i = 0;
foreach ($_POST['SelectAuthoriserCash'] as $Value) {
if ($i) $AuthorisersCash .= ',';
$AuthorisersCash .= $Value;
$i++;
}

$Assigners = '';
$i = 0;
foreach ($_POST['SelectAssigner'] as $Value) {
if ($i) $Assigners .= ',';
$Assigners .= $Value;
$i++;
Comment on lines +69 to +89

Copilot AI Apr 26, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These foreach loops assume SelectAuthoriserExpenses/SelectAuthoriserCash/SelectAssigner are always set and are arrays. If a later validation fails (e.g., TaxGroup) the page will re-render with these values as arrays, but if the keys are unset you'll get warnings; if they are not arrays you'll get runtime errors. Guard with isset()+is_array(), and consider using implode() to build the comma-separated values.

Suggested change
$i = 0;
foreach ($_POST['SelectAuthoriserExpenses'] as $Value) {
if ($i) $AuthorisersExpenses .= ',';
$AuthorisersExpenses .= $Value;
$i++;
}
$AuthorisersCash = '';
$i = 0;
foreach ($_POST['SelectAuthoriserCash'] as $Value) {
if ($i) $AuthorisersCash .= ',';
$AuthorisersCash .= $Value;
$i++;
}
$Assigners = '';
$i = 0;
foreach ($_POST['SelectAssigner'] as $Value) {
if ($i) $Assigners .= ',';
$Assigners .= $Value;
$i++;
if (isset($_POST['SelectAuthoriserExpenses']) and is_array($_POST['SelectAuthoriserExpenses'])) {
$AuthorisersExpenses = implode(',', $_POST['SelectAuthoriserExpenses']);
}
$AuthorisersCash = '';
if (isset($_POST['SelectAuthoriserCash']) and is_array($_POST['SelectAuthoriserCash'])) {
$AuthorisersCash = implode(',', $_POST['SelectAuthoriserCash']);
}
$Assigners = '';
if (isset($_POST['SelectAssigner']) and is_array($_POST['SelectAssigner'])) {
$Assigners = implode(',', $_POST['SelectAssigner']);

Copilot uses AI. Check for mistakes.
}
}

if (isset($SelectedTab) and $InputError != 1) {
$SQL = "UPDATE pctabs SET usercode = '" . $_POST['SelectUser'] . "',
typetabcode = '" . $_POST['SelectTabs'] . "',
currency = '" . $_POST['SelectCurrency'] . "',
tablimit = '" . filter_number_format($_POST['TabLimit']) . "',
assigner = '" . $_POST['SelectAssigner'] . "',
authorizer = '" . $_POST['SelectAuthoriserCash'] . "',
authorizerexpenses = '" . $_POST['SelectAuthoriserExpenses'] . "',
assigner = '" . $Assigners . "',
authorizer = '" . $AuthorisersCash . "',
authorizerexpenses = '" . $AuthorisersExpenses . "',
glaccountassignment = '" . $_POST['GLAccountCash'] . "',
glaccountpcash = '" . $_POST['GLAccountPcashTab'] . "',
taxgroupid='" . $_POST['TaxGroup'] . "'
Expand Down Expand Up @@ -104,9 +131,9 @@
'" . $_POST['SelectTabs'] . "',
'" . $_POST['SelectCurrency'] . "',
'" . filter_number_format($_POST['TabLimit']) . "',
'" . $_POST['SelectAssigner'] . "',
'" . $_POST['SelectAuthoriserCash'] . "',
'" . $_POST['SelectAuthoriserExpenses'] . "',
'" . $Assigners . "',
'" . $AuthorisersCash . "',
'" . $AuthorisersExpenses . "',
'" . $_POST['GLAccountCash'] . "',
'" . $_POST['GLAccountPcashTab'] . "',
'" . $_POST['TaxGroup'] . "'
Expand All @@ -126,6 +153,7 @@
unset($_POST['TabLimit']);
unset($_POST['SelectAssigner']);
unset($_POST['SelectAuthoriserCash']);
unset($_POST['SelectAuthoriserExpenses']);
unset($_POST['GLAccountCash']);
unset($_POST['GLAccountPcashTab']);
unset($_POST['TaxGroup']);
Expand Down Expand Up @@ -319,52 +347,64 @@
</field>';
echo '<field>
<label for="SelectAssigner">', __('Cash Assigner'), ':</label>
<select required="required" name="SelectAssigner">';
<td><select multiple="multiple" name="SelectAssigner[]">';

Copilot AI Apr 26, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The select markup introduces a inside a block and drops the required attribute. This results in invalid HTML (unmatched table cell tags) and allows submitting with no selection. Remove the wrapper and keep required="required" on these multiple selects (or enforce selection server-side).

Suggested change
<td><select multiple="multiple" name="SelectAssigner[]">';
<select multiple="multiple" name="SelectAssigner[]" required="required">';

Copilot uses AI. Check for mistakes.
$SQL = "SELECT userid,
realname
FROM www_users
ORDER BY userid";
$Result = DB_query($SQL);
while ($MyRow = DB_fetch_array($Result)) {
if (isset($_POST['SelectAssigner']) and $MyRow['userid'] == $_POST['SelectAssigner']) {
echo '<option selected="selected" value="', $MyRow['userid'], '">', $MyRow['userid'], ' - ', $MyRow['realname'], '</option>';
$Assigners = explode(',',$_POST['SelectAssigner']);
if (isset($_POST['SelectAssigner']) and in_array($MyRow['userid'],$Assigners)) {
echo '<option selected="selected" value="';
} else {
Comment on lines 356 to 360

Copilot AI Apr 26, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$Assigners is recalculated inside the option loop and explode() assumes $_POST['SelectAssigner'] is a string. After a submit, it will be an array (because of name="SelectAssigner[]"), which will cause a TypeError in PHP 8+. Compute selected IDs once before the loop and handle both the stored CSV string (edit mode) and the posted array (submit with errors).

Copilot uses AI. Check for mistakes.
echo '<option value="', $MyRow['userid'], '">', $MyRow['userid'], ' - ', $MyRow['realname'], '</option>';
echo '<option value="';
}
echo $MyRow['userid'] . '">' . $MyRow['userid'] . ' - ' . $MyRow['realname'] . '</option>';

} //end while loop get assigner
echo '</select>
</field>';
echo '<field>
<label for="SelectAuthoriserCash">', __('Authoriser - Cash'), ':</label>
<select required="required" name="SelectAuthoriserCash">';
<td><select multiple="multiple" name="SelectAuthoriserCash[]">';

$SQL = "SELECT userid,
realname
FROM www_users
ORDER BY userid";
$Result = DB_query($SQL);
while ($MyRow = DB_fetch_array($Result)) {
if (isset($_POST['SelectAuthoriserCash']) and $MyRow['userid'] == $_POST['SelectAuthoriserCash']) {
echo '<option selected="selected" value="', $MyRow['userid'], '">', $MyRow['userid'], ' - ', $MyRow['realname'], '</option>';
$Authorizer = explode(',',$_POST['SelectAuthoriserCash']);
if (isset($_POST['SelectAuthoriserCash']) and in_array($MyRow['userid'],$Authorizer)) {
echo '<option selected="selected" value="';
} else {
Comment on lines 377 to 381

Copilot AI Apr 26, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue as the assigner select: explode() assumes a string but $_POST['SelectAuthoriserCash'] will be an array after submit, leading to a TypeError and broken re-rendering on validation errors. Normalize the selected values before the loop (handle both CSV string from DB and array from POST).

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback

echo '<option value="', $MyRow['userid'], '">', $MyRow['userid'], ' - ', $MyRow['realname'], '</option>';
echo '<option value="';
}
echo $MyRow['userid'] . '">' . $MyRow['userid'] . ' - ' . $MyRow['realname'] . '</option>';

} //end while loop get authoriser

echo '</select>
</field>';
echo '<field>
<label for="SelectAuthoriserExpenses">', __('Authoriser - Expenses'), ':</label>
<select required="required" name="SelectAuthoriserExpenses">';
<td><select multiple="multiple" name="SelectAuthoriserExpenses[]">';

$SQL = "SELECT userid,
realname
FROM www_users
ORDER BY userid";
$Result = DB_query($SQL);
while ($MyRow = DB_fetch_array($Result)) {
if (isset($_POST['SelectAuthoriserExpenses']) and $MyRow['userid'] == $_POST['SelectAuthoriserExpenses']) {
echo '<option selected="selected" value="', $MyRow['userid'], '">', $MyRow['userid'], ' - ', $MyRow['realname'], '</option>';
$Authorizer = explode(',',$_POST['SelectAuthoriserExpenses']);
if (isset($_POST['SelectAuthoriserExpenses']) and in_array($MyRow['userid'],$Authorizer)) {
echo '<option selected="selected" value="';
} else {
Comment on lines 399 to 403

Copilot AI Apr 26, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue as the cash authoriser select: explode() will receive an array after submit (name="SelectAuthoriserExpenses[]"), causing a TypeError on re-render. Normalize selected values once outside the loop and handle both CSV string and array forms.

Copilot uses AI. Check for mistakes.
echo '<option value="', $MyRow['userid'], '">', $MyRow['userid'], ' - ', $MyRow['realname'], '</option>';
echo '<option value="';
}
echo $MyRow['userid'] . '">' . $MyRow['userid'] . ' - ' . $MyRow['realname'] . '</option>';

} //end while loop get authoriser
echo '</select>
</field>';
Expand Down