Skip to content

Commit ff80a3d

Browse files
authored
Merge pull request #1186 from itflow-org/develop
v25.02.4 - Stable Minor Release
2 parents 9f2b9e3 + c7d00d7 commit ff80a3d

File tree

8 files changed

+107
-10
lines changed

8 files changed

+107
-10
lines changed

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,16 @@
22

33
This file documents all notable changes made to ITFlow.
44

5+
## [25.02.4]
6+
7+
### Fixed
8+
- Resolved issue preventing the addition or editing of licenses when no vendor was selected.
9+
- Fixed several undeclared variables in AJAX contact details.
10+
- Corrected the contact ticket count display.
11+
- Addressed an issue where clicking "More Details" in AJAX contact/asset details failed to include the `client_id` in the URL.
12+
- Fixed an issue with recurring invoices in the client URL: clicking "Inactive" or "Active" would unexpectedly navigate away from the client section.
13+
- Added new php function getFieldById() to return a record using just an id and sanitized as well.
14+
515
## [25.02.3]
616

717
### Fixed

ajax/ajax_asset_details.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -848,7 +848,7 @@ function updateAssetNotes(asset_id) {
848848
</div>
849849

850850
<div class="modal-footer bg-white">
851-
<a href="asset_details.php?<?php echo $client_url; ?>asset_id=<?php echo $asset_id; ?>" class="btn btn-primary text-bold"><span class="text-white"><i class="fas fa-info-circle mr-2"></i>More Details</span></a>
851+
<a href="asset_details.php?client_id=<?php echo $client_id; ?>&asset_id=<?php echo $asset_id; ?>" class="btn btn-primary text-bold"><span class="text-white"><i class="fas fa-info-circle mr-2"></i>More Details</span></a>
852852
<a href="#" class="btn btn-secondary"
853853
data-toggle="ajax-modal" data-ajax-url="ajax/ajax_asset_edit.php" data-ajax-id="<?php echo $asset_id; ?>">
854854
<span class="text-white"><i class="fas fa-edit mr-2"></i>Edit</span>

ajax/ajax_contact_details.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
LEFT JOIN locations ON location_id = contact_location_id
1010
LEFT JOIN users ON user_id = contact_user_id
1111
WHERE contact_id = $contact_id
12-
$client_query
12+
LIMIT 1
1313
");
1414

1515
$row = mysqli_fetch_array($sql);
@@ -114,7 +114,7 @@
114114
AND service_contacts.service_id = services.service_id
115115
ORDER BY service_name ASC"
116116
);
117-
$service_count = mysqli_num_rows($sql_linked_services);
117+
$services_count = mysqli_num_rows($sql_linked_services);
118118

119119
$linked_services = array();
120120

@@ -846,7 +846,7 @@ function updateContactNotes(contact_id) {
846846
</div>
847847

848848
<div class="modal-footer bg-white">
849-
<a href="contact_details.php?<?php echo $client_url; ?>contact_id=<?php echo $contact_id; ?>" class="btn btn-primary text-bold">
849+
<a href="contact_details.php?client_id=<?php echo $client_id; ?>&contact_id=<?php echo $contact_id; ?>" class="btn btn-primary text-bold">
850850
<span class="text-white"><i class="fas fa-info-circle mr-2"></i>More Details</span>
851851
</a>
852852
<a href="#" class="btn btn-secondary"

contacts.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -385,7 +385,7 @@ class="btn btn-<?php if($archived == 1){ echo "primary"; } else { echo "default"
385385
if ($ticket_count) {
386386
$ticket_count_display = "<span class='mr-2 badge badge-pill badge-secondary p-2' title='$ticket_count Tickets'><i class='fas fa-fw fa-life-ring mr-2'></i>$ticket_count</span>";
387387
} else {
388-
$software_count_display = '';
388+
$ticket_count_display = '';
389389
}
390390

391391
// Related Documents Query

functions.php

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1413,4 +1413,91 @@ function logAuth($status, $details) {
14131413
// Helper function for missing data fallback
14141414
function getFallback($data) {
14151415
return !empty($data) ? $data : '<span class="text-muted">N/A</span>';
1416+
}
1417+
1418+
/**
1419+
* Retrieves a specified field's value from a table based on the record's id.
1420+
* It validates the table and field names, automatically determines the primary key (or uses the first column as fallback),
1421+
* and returns the field value with an appropriate escaping method.
1422+
*
1423+
* @param string $table The name of the table.
1424+
* @param int $id The record's id.
1425+
* @param string $field The field (column) to retrieve.
1426+
* @param string $escape_method The escape method: 'sql' (default, auto-detects int), 'html', 'json', or 'int'.
1427+
*
1428+
* @return mixed The escaped field value, or null if not found or invalid input.
1429+
*/
1430+
function getFieldById($table, $id, $field, $escape_method = 'sql') {
1431+
global $mysqli; // Use the global MySQLi connection
1432+
1433+
// Validate table and field names to allow only letters, numbers, and underscores
1434+
if (!preg_match('/^[a-zA-Z0-9_]+$/', $table) || !preg_match('/^[a-zA-Z0-9_]+$/', $field)) {
1435+
return null; // Invalid table or field name
1436+
}
1437+
1438+
// Sanitize id as an integer
1439+
$id = (int)$id;
1440+
1441+
// Get the list of columns and their details from the table
1442+
$columns_result = mysqli_query($mysqli, "SHOW COLUMNS FROM `$table`");
1443+
if (!$columns_result || mysqli_num_rows($columns_result) == 0) {
1444+
return null; // Table not found or has no columns
1445+
}
1446+
1447+
// Build an associative array with column details
1448+
$columns = [];
1449+
while ($row = mysqli_fetch_assoc($columns_result)) {
1450+
$columns[$row['Field']] = [
1451+
'type' => $row['Type'],
1452+
'key' => $row['Key']
1453+
];
1454+
}
1455+
1456+
// Find the primary key field if available
1457+
$id_field = null;
1458+
foreach ($columns as $col => $details) {
1459+
if ($details['key'] === 'PRI') {
1460+
$id_field = $col;
1461+
break;
1462+
}
1463+
}
1464+
// Fallback: if no primary key is found, use the first column
1465+
if (!$id_field) {
1466+
reset($columns);
1467+
$id_field = key($columns);
1468+
}
1469+
1470+
// Ensure the requested field exists; if not, default to the id field
1471+
if (!array_key_exists($field, $columns)) {
1472+
$field = $id_field;
1473+
}
1474+
1475+
// Build and execute the query to fetch the specified field value
1476+
$query = "SELECT `$field` FROM `$table` WHERE `$id_field` = $id";
1477+
$sql = mysqli_query($mysqli, $query);
1478+
1479+
if ($sql && mysqli_num_rows($sql) > 0) {
1480+
$row = mysqli_fetch_assoc($sql);
1481+
$value = $row[$field];
1482+
1483+
// Apply the desired escaping method or auto-detect integer type if using SQL escaping
1484+
switch ($escape_method) {
1485+
case 'html':
1486+
return htmlspecialchars($value, ENT_QUOTES, 'UTF-8'); // Escape for HTML
1487+
case 'json':
1488+
return json_encode($value); // Escape for JSON
1489+
case 'int':
1490+
return (int)$value; // Explicitly cast value to integer
1491+
case 'sql':
1492+
default:
1493+
// Auto-detect if the field type is integer
1494+
if (stripos($columns[$field]['type'], 'int') !== false) {
1495+
return (int)$value;
1496+
} else {
1497+
return sanitizeInput($value); // Escape for SQL using a custom function
1498+
}
1499+
}
1500+
}
1501+
1502+
return null; // Return null if no record was found
14161503
}

includes/app_version.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@
55
* Update this file each time we merge develop into master. Format is YY.MM (add a .v if there is more than one release a month.
66
*/
77

8-
DEFINE("APP_VERSION", "25.02.3");
8+
DEFINE("APP_VERSION", "25.02.4");

post/user/software.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@
6666
$expire = "'" . $expire . "'";
6767
}
6868
$notes = sanitizeInput($_POST['notes']);
69-
$vendor = sanitizeInput($_POST['vendor'] ?? 0);
69+
$vendor = intval($_POST['vendor'] ?? 0);
7070

7171
mysqli_query($mysqli,"INSERT INTO software SET software_name = '$name', software_version = '$version', software_description = '$description', software_type = '$type', software_key = '$key', software_license_type = '$license_type', software_seats = $seats, software_purchase_reference = '$purchase_reference', software_purchase = $purchase, software_expire = $expire, software_notes = '$notes', software_vendor_id = $vendor, software_client_id = $client_id");
7272

@@ -127,7 +127,7 @@
127127
$expire = "'" . $expire . "'";
128128
}
129129
$notes = sanitizeInput($_POST['notes']);
130-
$vendor = sanitizeInput($_POST['vendor'] ?? 0);
130+
$vendor = intval($_POST['vendor'] ?? 0);
131131

132132
mysqli_query($mysqli,"UPDATE software SET software_name = '$name', software_version = '$version', software_description = '$description', software_type = '$type', software_key = '$key', software_license_type = '$license_type', software_seats = $seats, software_purchase_reference = '$purchase_reference', software_purchase = $purchase, software_expire = $expire, software_notes = '$notes', software_vendor_id = $vendor WHERE software_id = $software_id");
133133

recurring_invoices.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,8 @@
7070
<div class="col-sm-8">
7171
<div class="btn-toolbar float-right">
7272
<div class="btn-group mr-2">
73-
<a href="?status=active" class="btn btn-<?php if ($status_filter == "active"){ echo "primary"; } else { echo "default"; } ?>"><i class="fa fa-fw fa-check mr-2"></i>Active</a>
74-
<a href="?status=inactive" class="btn btn-<?php if ($status_filter == "inactive"){ echo "primary"; } else { echo "default"; } ?>"><i class="fa fa-fw fa-ban mr-2"></i>Inactive</a>
73+
<a href="?<?php echo $client_url; ?>status=active" class="btn btn-<?php if ($status_filter == "active"){ echo "primary"; } else { echo "default"; } ?>"><i class="fa fa-fw fa-check mr-2"></i>Active</a>
74+
<a href="?<?php echo $client_url; ?>status=inactive" class="btn btn-<?php if ($status_filter == "inactive"){ echo "primary"; } else { echo "default"; } ?>"><i class="fa fa-fw fa-ban mr-2"></i>Inactive</a>
7575
</div>
7676
</div>
7777
</div>

0 commit comments

Comments
 (0)