Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
6c6a988
Fix custom Favicon
johnnyq Oct 2, 2025
76c9933
Update imap and smtp providers to allow empty string if empty do not …
johnnyq Oct 2, 2025
956f184
Fix Microsoft SSO Login in Client Portal, fix ticket templates due to…
johnnyq Oct 3, 2025
6e8c133
Fix Regressions in Vendor Templates updated path from ../user/post to…
johnnyq Oct 3, 2025
5de2e7a
If imap Encryption is blank then use notls in the ticket mail parser
johnnyq Oct 3, 2025
32bfd29
Added Project Edit Function for Ticket
johnnyq Oct 3, 2025
fd93ee3
Allow HTML for signatures
johnnyq Oct 4, 2025
01f6615
rm test
Oct 6, 2025
d8803aa
prevent open redirects upon agent login
Oct 6, 2025
416a8d9
Fix to properly redirect to the setup page if config_enable_setup is …
johnnyq Oct 6, 2025
a4ed906
Update modal footer and header to user SERVER Document root with abso…
johnnyq Oct 6, 2025
4ef0755
Update Guest header and footer to use Server Document Root var
johnnyq Oct 6, 2025
3fcbe44
Fix Missing Missing Country code in Guest View Ticket
johnnyq Oct 7, 2025
16242be
Update Client Nav to use Absolute links and updated more of the inc_a…
johnnyq Oct 7, 2025
35a7506
Copy crons from /scripts to /cron, added custom directories for api/v…
johnnyq Oct 7, 2025
2ec4cdc
Ceated inc_all_guest.php and modulaized the guest header.php removed …
johnnyq Oct 8, 2025
27e1d6a
remove net terms in quote add jquery to guest header
johnnyq Oct 8, 2025
e3e7c2e
Add Signature in ticket reply POST dont add a signature if Internal
johnnyq Oct 8, 2025
1eb9d16
Updated Changelog
johnnyq Oct 8, 2025
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
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,14 @@ client/custom/*
!client/custom/readme.php
guest/custom/*
!guest/custom/readme.php
cron/custom/*
!cron/custom/readme.php
scripts/custom/*
!scripts/custom/readme.php
setup/custom/*
!setup/custom/readme.php
api/v1/custom/*
!api/v1/custom/readme.php
.zed


22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,28 @@

This file documents all notable changes made to ITFlow.

## [25.10.1]
- Deprecation Notice: `/scripts/cron_mail_queue.php` , `/scripts/cron_ticket_email_parser.php` , `/scripts/cron.php` `/scripts/cron_domain_refresher.php`, `/scripts/cron_certificate_refresher.php` are being phased out. Please transition to `/cron/mail_queue.php` , `/cron/ticket_email_parser.php`, `/cron/cron.php`, `/cron/domain_refresher.php`, `/cron/certificate_refresher.php` These older scripts will be removed in the November 25.11 release—update accordingly. 25.10.1 installs have the script already configured.

### Fixes
- Fix regression missing custom Favicon.
- Update SMTP and IMAP provider to allow for empty strings, empty means disabled.
- Fix Client portal Microsoft SSO Logins.
- Fix regression in Vendor Templates.
- Fix refression in some broken links from user to agent.
- Fix Project edit.
- Prevent open redirects upon agent login.
- Fix regression on switching to Webklex IMAP to allow for no SSL/TLS in IMAP.
- Fix Setup Redirect not behaving properly when setup hasnt been performed.
- Added Server Document Root Var to several includes, headers, footers files to allow includes from deeper directory strutures such as the new custom directories.

### Added / Changed
- Support for HTML Signatures.
- Add Edit Project Functionality in a ticket.
- Added more custom locations: /cron/custom/, /scripts/custom/, /api/v1/custom/, /setup/custom/.
- Copied `/scripts/cron.php` `/scripts/cron_domain_refresher.php`, `/scripts/cron_certificate_refresher.php` to `/cron/cron.php`, `/cron/domain_refresher.php`, `/cron/certificate_refresher.php`. See Above!
- Signatures is now handled in post ticket reply on Public Comments only.

## [25.10]

### Breaking Changes
Expand Down
12 changes: 9 additions & 3 deletions admin/database_updates.php
Original file line number Diff line number Diff line change
Expand Up @@ -4027,10 +4027,16 @@ function processFile($file_path, $file_name, $mysqli) {
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '2.3.5'");
}

// if (CURRENT_DATABASE_VERSION == '2.3.4') {
// // Insert queries here required to update to DB version 2.3.4
if (CURRENT_DATABASE_VERSION == '2.3.5') {
mysqli_query($mysqli, "ALTER TABLE `settings` CHANGE `config_smtp_provider` `config_smtp_provider` VARCHAR(200) DEFAULT NULL");
mysqli_query($mysqli, "ALTER TABLE `settings` CHANGE `config_imap_provider` `config_imap_provider` VARCHAR(200) DEFAULT NULL");
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '2.3.6'");
}

// if (CURRENT_DATABASE_VERSION == '2.3.5') {
// // Insert queries here required to update to DB version 2.3.5
// // Then, update the database to the next sequential version
// mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '2.3.5'");
// mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '2.3.6'");
// }

} else {
Expand Down
22 changes: 11 additions & 11 deletions admin/includes/inc_all_admin.php
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
<?php

require_once "../config.php";
require_once "../functions.php";
require_once "../includes/check_login.php";
require_once "../includes/page_title.php";
require_once $_SERVER['DOCUMENT_ROOT'] . '/config.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/functions.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/check_login.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/page_title.php';
if (!isset($session_is_admin) || !$session_is_admin) {
exit(WORDING_ROLECHECK_FAILED . "<br>Tell your admin: Your role does not have admin access.");
}
require_once "../includes/header.php";
require_once "../includes/top_nav.php";
require_once "includes/side_nav.php";
require_once "../includes/inc_wrapper.php";
require_once "../includes/inc_alert_feedback.php";
require_once "../includes/filter_header.php";
require_once "../includes/app_version.php";
require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/header.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/top_nav.php';
require_once 'includes/side_nav.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/inc_wrapper.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/inc_alert_feedback.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/filter_header.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/app_version.php';
2 changes: 1 addition & 1 deletion admin/includes/side_nav.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<!-- Main Sidebar Container -->
<aside class="main-sidebar sidebar-dark-<?php echo nullable_htmlentities($config_theme); ?> d-print-none">
<a class="brand-link pb-1 mt-1" href="../agent/<?php echo $config_start_page ?>">
<a class="brand-link pb-1 mt-1" href="/agent/<?php echo $config_start_page ?>">
<p class="h6">
<i class="nav-icon fas fa-arrow-left ml-3 mr-2"></i>
<span class="brand-text">
Expand Down
8 changes: 4 additions & 4 deletions admin/post/settings_mail.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

validateCSRFToken($_POST['csrf_token']);

$config_smtp_provider = sanitizeInput($_POST['config_smtp_provider'] ?? 'standard_smtp');
$config_smtp_provider = sanitizeInput($_POST['config_smtp_provider']);
$config_smtp_host = sanitizeInput($_POST['config_smtp_host']);
$config_smtp_port = intval($_POST['config_smtp_port'] ?? 0);
$config_smtp_encryption = sanitizeInput($_POST['config_smtp_encryption']);
Expand All @@ -22,7 +22,7 @@

mysqli_query($mysqli, "
UPDATE settings SET
config_smtp_provider = " . ($config_smtp_provider === 'none' ? "NULL" : "'$config_smtp_provider'") . ",
config_smtp_provider = '$config_smtp_provider',
config_smtp_host = '$config_smtp_host',
config_smtp_port = $config_smtp_port,
config_smtp_encryption = '$config_smtp_encryption',
Expand All @@ -48,7 +48,7 @@

validateCSRFToken($_POST['csrf_token']);

$config_imap_provider = sanitizeInput($_POST['config_imap_provider'] ?? 'standard_imap');
$config_imap_provider = sanitizeInput($_POST['config_imap_provider']);
$config_imap_host = sanitizeInput($_POST['config_imap_host']);
$config_imap_port = intval($_POST['config_imap_port'] ?? 0);
$config_imap_encryption = sanitizeInput($_POST['config_imap_encryption']);
Expand All @@ -64,7 +64,7 @@

mysqli_query($mysqli, "
UPDATE settings SET
config_imap_provider = " . ($config_imap_provider === 'none' ? "NULL" : "'$config_imap_provider'") . ",
config_imap_provider = '$config_imap_provider',
config_imap_host = '$config_imap_host',
config_imap_port = $config_imap_port,
config_imap_encryption = '$config_imap_encryption',
Expand Down
4 changes: 2 additions & 2 deletions admin/post/ticket_template.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
defined('FROM_POST_HANDLER') || die("Direct file access is not allowed");

// Import shared code from user-side tickets/tasks as we reuse functions
require_once '../user/post/ticket.php';
require_once '../user/post/task.php';
require_once '../agent/post/ticket.php';
require_once '../agent/post/task.php';

if (isset($_POST['add_ticket_template'])) {

Expand Down
2 changes: 1 addition & 1 deletion admin/post/vendor_template.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
defined('FROM_POST_HANDLER') || die("Direct file access is not allowed");

// Import shared code from user-side vendor management as we reuse functions
require_once '../user/post/vendor.php';
require_once '../agent/post/vendor.php';

if (isset($_POST['add_vendor_template'])) {

Expand Down
16 changes: 8 additions & 8 deletions admin/settings_mail.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@
<span class="input-group-text"><i class="fa fa-fw fa-cloud"></i></span>
</div>
<select class="form-control" name="config_smtp_provider" id="config_smtp_provider">
<option value="none" <?php if(($config_smtp_provider ?? '')==='none' || ($config_smtp_provider ?? '')==='') echo 'selected'; ?>>None (Disabled)</option>
<option value="standard_smtp" <?php if(($config_smtp_provider ?? 'standard_smtp')==='standard_smtp') echo 'selected'; ?>>Standard SMTP (Username/Password)</option>
<option value="google_oauth" <?php if(($config_smtp_provider ?? '')==='google_oauth') echo 'selected'; ?>>Google Workspace (OAuth)</option>
<option value="microsoft_oauth" <?php if(($config_smtp_provider ?? '')==='microsoft_oauth') echo 'selected'; ?>>Microsoft 365 (OAuth)</option>
<option value="" <?php if(empty($config_smtp_provider)) { echo 'selected'; } ?>>None (Disabled)</option>
<option value="standard_smtp" <?php if($config_smtp_provider === 'standard_smtp') { echo 'selected'; } ?>>Standard SMTP (Username/Password)</option>
<option value="google_oauth" <?php if($config_smtp_provider === 'google_oauth') { echo 'selected'; } ?>>Google Workspace (OAuth)</option>
<option value="microsoft_oauth" <?php if($config_smtp_provider === 'microsoft_oauth') { echo 'selected'; } ?>>Microsoft 365 (OAuth)</option>
</select>
</div>
<small class="text-secondary d-block mt-1" id="smtp_provider_hint">
Expand Down Expand Up @@ -116,10 +116,10 @@
<span class="input-group-text"><i class="fa fa-fw fa-cloud"></i></span>
</div>
<select class="form-control" name="config_imap_provider" id="config_imap_provider">
<option value="none" <?php if($config_imap_provider ==='') echo 'selected'; ?>>None (Disabled)</option>
<option value="standard_imap" <?php if(($config_imap_provider ?? 'standard_imap')==='standard_imap') echo 'selected'; ?>>Standard IMAP (Username/Password)</option>
<option value="google_oauth" <?php if(($config_imap_provider ?? '')==='google_oauth') echo 'selected'; ?>>Google Workspace (OAuth)</option>
<option value="microsoft_oauth" <?php if(($config_imap_provider ?? '')==='microsoft_oauth') echo 'selected'; ?>>Microsoft 365 (OAuth)</option>
<option value="" <?php if(empty($config_imap_provider)) { echo 'selected'; } ?>>None (Disabled)</option>
<option value="standard_imap" <?php if($config_imap_provider === 'standard_imap') { echo 'selected'; } ?>>Standard IMAP (Username/Password)</option>
<option value="google_oauth" <?php if($config_imap_provider === 'google_oauth') { echo 'selected'; } ?>>Google Workspace (OAuth)</option>
<option value="microsoft_oauth" <?php if($config_imap_provider === 'microsoft_oauth') { echo 'selected'; } ?>>Microsoft 365 (OAuth)</option>
</select>
</div>
<small class="text-secondary d-block mt-1" id="imap_provider_hint">
Expand Down
2 changes: 0 additions & 2 deletions admin/update.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,6 @@
<p class="text-center font-weight-bold">Ignore this warning at your own risk.</p>
</div>

<a class="btn btn-primary btn-lg my-4 confirm-link" href="post.php?no"><i class="fas fa-fw fa-4x fa-download mb-1"></i><h5>TEST</h5></a>

<a class="btn btn-primary btn-lg my-4 confirm-link" href="post.php?update"><i class="fas fa-fw fa-4x fa-download mb-1"></i><h5>Update App</h5></a>
<a class="btn btn-danger btn-lg confirm-link" href="post.php?update&force_update=1"><i class="fas fa-fw fa-4x fa-hammer mb-1"></i><h5>FORCE Update App</h5></a>

Expand Down
22 changes: 11 additions & 11 deletions agent/includes/inc_all.php
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
<?php
// Configuration & core
require_once "../config.php";
require_once "../functions.php";
require_once "../includes/check_login.php";
require_once $_SERVER['DOCUMENT_ROOT'] . '/config.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/functions.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/check_login.php';

// Page setup
require_once "../includes/page_title.php";
require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/page_title.php';

// Layout UI
require_once "../includes/header.php";
require_once "../includes/top_nav.php";
require_once "includes/get_side_nav_counts.php";
require_once "includes/side_nav.php";
require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/header.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/top_nav.php';
require_once 'includes/get_side_nav_counts.php';
require_once 'includes/side_nav.php';

// Wrapper & alerts
require_once "../includes/inc_wrapper.php";
require_once "../includes/inc_alert_feedback.php";
require_once "../includes/filter_header.php";
require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/inc_wrapper.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/inc_alert_feedback.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/filter_header.php';
24 changes: 12 additions & 12 deletions agent/includes/inc_all_client.php
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<?php

require_once "../config.php";
require_once "../functions.php";
require_once "../includes/check_login.php";
require_once "../includes/page_title.php";
require_once $_SERVER['DOCUMENT_ROOT'] . '/config.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/functions.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/check_login.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/page_title.php';

// Perms
enforceUserPermission('module_client');
Expand Down Expand Up @@ -35,7 +35,7 @@
);

if (mysqli_num_rows($sql) == 0) {
require_once "../includes/header.php";
require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/header.php';

echo "<center><h1 class='text-secondary mt-5'>Nothing to see here</h1></center>";
} else {
Expand Down Expand Up @@ -304,10 +304,10 @@
}
}

require_once "../includes/header.php";
require_once "../includes/top_nav.php";
require_once "includes/client_side_nav.php";
require_once "../includes/inc_wrapper.php";
require_once "../includes/inc_alert_feedback.php";
require_once "includes/inc_client_top_head.php";
require_once "../includes/filter_header.php";
require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/header.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/top_nav.php';
require_once 'includes/client_side_nav.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/inc_wrapper.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/inc_alert_feedback.php';
require_once 'includes/inc_client_top_head.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/filter_header.php';
20 changes: 10 additions & 10 deletions agent/includes/inc_client_overview_all.php
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
<?php

require_once "../config.php";
require_once "../functions.php";
require_once "../includes/check_login.php";
require_once "../includes/page_title.php";
require_once "../includes/header.php";
require_once "../includes/top_nav.php";
require_once "includes/client_overview_side_nav.php";
require_once "../includes/inc_wrapper.php";
require_once "../includes/inc_alert_feedback.php";
require_once "../includes/filter_header.php";
require_once $_SERVER['DOCUMENT_ROOT'] . '/config.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/functions.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/check_login.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/page_title.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/header.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/top_nav.php';
require_once 'includes/client_overview_side_nav.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/inc_wrapper.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/inc_alert_feedback.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/filter_header.php';
65 changes: 65 additions & 0 deletions agent/modals/ticket/ticket_edit_project.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php

require_once '../../../includes/modal_header.php';

$ticket_id = intval($_GET['id']);

$sql = mysqli_query($mysqli, "SELECT * FROM tickets LEFT JOIN clients ON client_id = ticket_client_id WHERE ticket_id = $ticket_id LIMIT 1");

$row = mysqli_fetch_array($sql);
$client_id = intval($row['ticket_client_id']);
$client_name = nullable_htmlentities($row['client_name']);
$ticket_prefix = nullable_htmlentities($row['ticket_prefix']);
$ticket_number = intval($row['ticket_number']);
$ticket_project_id = intval($row['ticket_project_id']);


// Select box arrays
$sql_projects = mysqli_query($mysqli, "SELECT project_id, project_name FROM projects WHERE (project_client_id = $client_id OR project_client_id = 0) AND project_completed_at IS NULL AND project_archived_at IS NULL ORDER BY project_name ASC");

// Generate the HTML form content using output buffering.
ob_start();
?>

<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fas fa-fw fa-project-diagram mr-2"></i>Project: <strong><?= "$ticket_prefix$ticket_number" ?></strong> - <?= $client_name ?></h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="ticket_id" value="<?php echo $ticket_id; ?>">
<div class="modal-body">

<div class="form-group">
<label>Project</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-project-diagram"></i></span>
</div>
<select class="form-control select2" name="project">
<option value="0">- None -</option>
<?php
while ($row = mysqli_fetch_array($sql_projects)) {
$project_id = intval($row['project_id']);
$project_name = nullable_htmlentities($row['project_name']); ?>
<option <?php if ($ticket_project_id == $project_id) { echo "selected"; } ?>
value="<?= $project_id ?>"><?= $project_name ?>
</option>

<?php } ?>
</select>
</div>
</div>

</div>

<div class="modal-footer">
<button type="submit" name="edit_ticket_project" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Save</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
</div>

</form>

<?php
require_once '../../../includes/modal_footer.php';
2 changes: 1 addition & 1 deletion agent/post.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
// Dynamically load admin-related module POST logic

// Load all module POST logic
// Loads everything in post/user/
// Loads everything in post
// Eventually, it would be nice to only specifically load what we need like we do for admins

foreach (glob("post/*.php") as $user_module) {
Expand Down
6 changes: 3 additions & 3 deletions agent/post/client.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@

$client_id = mysqli_insert_id($mysqli);

if (!file_exists("../uploads/clients/$client_id")) {
mkdir("../uploads/clients/$client_id");
file_put_contents("../uploads/clients/$client_id/index.php", "");
if (!file_exists($_SERVER['DOCUMENT_ROOT'] . "/uploads/clients/$client_id")) {
mkdir($_SERVER['DOCUMENT_ROOT'] . "/uploads/clients/$client_id");
file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/uploads/clients/$client_id/index.php", "");
}

// Create Referral if it doesn't exist
Expand Down
Loading