Skip to content

Commit b3d9e39

Browse files
committed
Merge branch '1.17.x' into develop
2 parents c466519 + 3ff35ad commit b3d9e39

File tree

150 files changed

+2687
-2098
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

150 files changed

+2687
-2098
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ setup/cli/modules/importer
77
.vagrant
88
._.DS_Store
99
Vagrantfile
10+
# VS Code workspace files
11+
*.code-workspace
1012

1113
# Staging directory used for packaging script
1214
stage

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,13 @@ easy to setup and use. The best part is, it's completely free.
2222
Requirements
2323
------------
2424
* HTTP server running Microsoft® IIS or Apache
25-
* PHP version 8.1 - 8.2 (8.2 recommended)
25+
* PHP version 8.2 - 8.4 (8.4 recommended)
2626
* mysqli extension for PHP
2727
* MySQL database version 5.5 (or greater)
2828

2929
### Recommendations
30-
* fileinfo, gd, gettext, imap, intl, json, mbstring, Zend OPcache, phar,
31-
xml, xml-dom, and zip extensions for PHP
30+
* ctype, fileinfo, gd, gettext, iconv, imap, intl, json, mbstring,
31+
Zend OPcache, phar, xml, xml-dom, and zip extensions for PHP
3232
* APCu module enabled and configured for PHP
3333

3434
Deployment

WHATSNEW.md

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,67 @@ osTicket v1.18
1616
* Database: Change Plugin Name to varchar(255) (aac546d0)
1717
* update: MAJOR_VERSION (3eac42e5)
1818

19+
osTicket v1.17.6
20+
================
21+
### Improvements
22+
* Fix PR #6283: DB column value of "local backend" is 'client' and not 'local' (7805cd94)
23+
* i18n: Tasks Department ID Missing (00bc6b1b)
24+
* issue: Checkbox Template Variable (09de9587)
25+
* Fixed mailfetch error message (cd4717a1)
26+
* issue: fix square characters being printed when printing tickets that's using languages like Thai (872a6492, 25844034)
27+
* issue: Position Styling.. Again (7f03a64b, b843fb15)
28+
* mysqli: Multi-Host Failure (0a8475fb)
29+
* issue: Task Last Respondent (5277c7ab)
30+
* i18n: Schedules getDays() (f2facda3)
31+
* issue: Referred Closed Tickets (a7b0711d)
32+
* php: Update Prerequisites (d331a44c)
33+
* i18n: Lang URL Param (fece6ff7)
34+
* mysql: Update Minimum Version (317ab967)
35+
* Fix ajax path for AddRemoteCollaborator (6df6cd98)
36+
* Fix staff mobile field class (f8455c82)
37+
* patches: Latest 05/28/2024 (2d65cb77, 36b4c94f, 854cf47c, d9fe3ada)
38+
* upgrade: Laminas-Mail (2.25.1) (c0a74162, 939a278c, f658268d)
39+
* hotfix: Fix getRawEmail() (c26d840c, 1eb71197)
40+
* issue: Linked Icon annotation (6c096cce)
41+
* fix(email): fix case sensitivity in "Action" header retrieval (07843598)
42+
* Upgrade mimeDecode.php from v1.48 to v1.5.6 2016-08-28 (cbd78ac8)
43+
* mailer: sendmail() Failure (14e2057b)
44+
* php: 8.3 Support (a3931f46, b38db372, fea5e1e0, 387a1c04, 136d372e)
45+
* issue: Ticket Relations (9426b2dd)
46+
* issue: Basic Search Selector (74b8bd0e)
47+
* mail: Reapply Memory Optimization (eaaa64d9, ab76ffe8)
48+
* php: iconv Recommendation (33ecc3a0)
49+
* Ignore VS Code Workspace Files (0da2e0e0)
50+
* issue: Email Remote Backend Name (b54dd584)
51+
* issue: Safari Response Content Disposition (64a5df68)
52+
* api: DueDate and Other Errors (14814ae2)
53+
* issue: Multiselect List Export (f3bf8553)
54+
* issue: Image Annotation (aeeb2850)
55+
* user: List Import (fec70c4a)
56+
* issue: Latest SQL Warnings (9bdfde5a)
57+
* fields: Variable Name Validation (0724d1ad)
58+
* issue: Transfer Empty Comments Var (ed87b257)
59+
* update: Composer symfony/process (59f25918)
60+
* issue: Client ACL Staff File Download (8255b2e7)
61+
* update: PHP Deprecations & Warnings (84c14ace)
62+
* issue: User Lookup Umlaut (504b0bfb)
63+
* issue: Department Field User Import (5c2b6a5d)
64+
* Fix force-https auto-enabling on settings page (3805bbfd)
65+
* queue: getTotal Incorrect Counts (4f137dc2)
66+
* issue: Referred Tickets Incorrect Queue Counts (b42cad6f)
67+
* php: 8.4 Support (a4c0f674, b4938b99, 5e5a9ff5, fb9a39ba)
68+
* issue: Canned Response Access (b930a68b)
69+
* issue: Excessive Fetching Errors (c546a167)
70+
* issue: Plain-text Base64 (216ded32)
71+
* i18n: Crowdin API v2 (0ec6670d)
72+
* issue: iFrame Logins (3a5da66b)
73+
* issue: mimeDecode .eml Attachments (7fc3d8c2)
74+
* patches: Latest 11/18/2024 (416b548b, 245e7554)
75+
* Revert part of 0784359 commit (ec76a203)
76+
77+
### Security
78+
* security: Latest Vulns 01/2025 (193f5fe0, ab6672fa)
79+
1980
osTicket v1.17.5
2081
================
2182
### Improvements

bootstrap.php

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@ static function init() {
2222

2323
#Error reporting...Good idea to ENABLE error reporting to a file. i.e display_errors should be set to false
2424
$error_reporting = E_ALL & ~E_NOTICE & ~E_WARNING;
25-
if (defined('E_STRICT')) # 5.4.0
26-
$error_reporting &= ~E_STRICT;
2725
if (defined('E_DEPRECATED')) # 5.3.0
2826
$error_reporting &= ~(E_DEPRECATED | E_USER_DEPRECATED);
2927
error_reporting($error_reporting); //Respect whatever is set in php.ini (sysadmin knows better??)
@@ -214,15 +212,16 @@ static function connect() {
214212
$hosts = explode(',', DBHOST);
215213
foreach ($hosts as $host) {
216214
$ferror = null;
217-
if (!db_connect($host, DBUSER, DBPASS, $options)) {
218-
$ferror = sprintf('Unable to connect to the database — %s',
219-
db_connect_error());
220-
}elseif(!db_select_database(DBNAME)) {
221-
$ferror = sprintf('Unknown or invalid database: %s',
222-
DBNAME);
223-
}
224-
// break if no error
225-
if (!$ferror) break;
215+
try {
216+
if (!db_connect($host, DBUSER, DBPASS, $options))
217+
$ferror = sprintf('Unable to connect to the database — %s', db_connect_error());
218+
elseif (!db_select_database(DBNAME))
219+
$ferror = sprintf('Unknown or invalid database: %s', DBNAME);
220+
} catch (mysqli_sql_exception $e) {
221+
$ferror = sprintf('Database error — %s', $e->getMessage());
222+
}
223+
// break if no error
224+
if (!$ferror) break;
226225
}
227226

228227
if ($ferror) //Fatal error
@@ -341,7 +340,7 @@ function mb_str_wc($str) {
341340
static function croak($message) {
342341
$msg = $message."\n\n".THISPAGE;
343342
osTicket\Mail\Mailer::sendmail(ADMIN_EMAIL, 'osTicket Fatal Error', $msg,
344-
sprintf('"osTicket Alerts"<%s>', ADMIN_EMAIL));
343+
sprintf('"osTicket Alerts" <%s>', ADMIN_EMAIL));
345344
//Display generic error to the user
346345
Http::response(500, "<b>Fatal Error:</b> Contact system administrator.");
347346
}

include/ajax.content.php

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@
2020
class ContentAjaxAPI extends AjaxController {
2121

2222
function syslog($id) {
23+
global $thisstaff;
24+
25+
// Ensure there is a Staff and that they are an Administrator
26+
if (!$thisstaff || !$thisstaff->isAdmin())
27+
Http::response(403, 'Access Denied');
2328

2429
if($id && ($log=Log::lookup($id))) {
2530
$content=sprintf('<div
@@ -142,8 +147,8 @@ function getSignature($type, $id=null) {
142147
function manageContent($id, $lang=false) {
143148
global $thisstaff, $cfg;
144149

145-
if (!$thisstaff)
146-
Http::response(403, 'Login Required');
150+
if (!$thisstaff || !$thisstaff->isAdmin())
151+
Http::response(403, 'Access Denied');
147152

148153
$content = Page::lookup($id, $lang);
149154

@@ -168,8 +173,8 @@ function manageContent($id, $lang=false) {
168173
function manageNamedContent($type, $lang=false) {
169174
global $thisstaff, $cfg;
170175

171-
if (!$thisstaff)
172-
Http::response(403, 'Login Required');
176+
if (!$thisstaff || !$thisstaff->isAdmin())
177+
Http::response(403, 'Access Denied');
173178

174179
$langs = $cfg->getSecondaryLanguages();
175180

@@ -182,8 +187,8 @@ function manageNamedContent($type, $lang=false) {
182187
function updateContent($id) {
183188
global $thisstaff;
184189

185-
if (!$thisstaff)
186-
Http::response(403, 'Login Required');
190+
if (!$thisstaff || !$thisstaff->isAdmin())
191+
Http::response(403, 'Access Denied');
187192
elseif (!($content = Page::lookup($id)))
188193
Http::response(404, 'No such content');
189194

include/ajax.draft.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@ function uploadInlineImageEarlyClient($namespace) {
242242

243243
$draft = Draft::create(array(
244244
'namespace' => $namespace,
245+
'body' => ''
245246
));
246247
if (!$draft->save())
247248
Http::response(500, 'Unable to create draft');
@@ -312,7 +313,8 @@ function uploadInlineImageEarly($namespace) {
312313
Http::response(403, "Login required for image upload");
313314

314315
$draft = Draft::create(array(
315-
'namespace' => $namespace
316+
'namespace' => $namespace,
317+
'body' => ''
316318
));
317319
if (!$draft->save())
318320
Http::response(500, 'Unable to create draft');

include/ajax.users.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,7 @@ function addRemoteUser($bk, $id) {
323323
elseif (!$bk || !$id)
324324
Http::response(422, 'Backend and user id required');
325325
elseif (!($backend = AuthenticationBackend::getSearchDirectoryBackend($bk))
326-
|| !($user_info = $backend->lookup($id)))
326+
|| !($user_info = $backend->lookup(html_entity_decode($id))))
327327
Http::response(404, 'User not found');
328328

329329
$form = UserForm::getUserForm()->getForm($user_info);

include/api.tickets.php

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,22 @@ function getRequestStructure($format, $data=null) {
4343
foreach ($form->getFields() as $field)
4444
$supported[] = $field->get('name');
4545

46-
if(!strcasecmp($format, 'email')) {
47-
$supported = array_merge($supported, array('header', 'mid',
48-
'emailId', 'to-email-id', 'ticketId', 'reply-to', 'reply-to-name',
49-
'in-reply-to', 'references', 'thread-type', 'system_emails',
50-
'mailflags' => array('bounce', 'auto-reply', 'spam', 'viral'),
51-
'recipients' => array('*' => array('name', 'email', 'source'))
52-
));
53-
54-
$supported['attachments']['*'][] = 'cid';
46+
switch ($format) {
47+
case 'email':
48+
$supported = array_merge($supported, [
49+
'header', 'mid', 'emailId', 'to-email-id', 'ticketId', 'reply-to',
50+
'reply-to-name', 'in-reply-to', 'references', 'thread-type', 'system_emails',
51+
'mailflags' => ['bounce', 'auto-reply', 'spam', 'viral'],
52+
'recipients' => ['*' => ['name', 'email', 'source']]
53+
]);
54+
$supported['attachments']['*'][] = 'cid';
55+
break;
56+
case 'json':
57+
case 'xml':
58+
$supported = array_merge($supported, [
59+
'duedate', 'slaId', 'staffId'
60+
]);
61+
break;
5562
}
5663

5764
return $supported;

include/class.api.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -387,8 +387,8 @@ function parse($stream) {
387387
function fixup($current) {
388388
global $cfg;
389389

390-
if($current['ticket'])
391-
$current = $current['ticket'];
390+
if (isset($current['ticket']))
391+
$current = $current['ticket'];
392392

393393
if (!is_array($current))
394394
return $current;

include/class.attachment.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ function save($file, $inline=true) {
192192
function getInlines($lang=false) { return $this->_getList(false, true, $lang); }
193193
function getSeparates($lang=false) { return $this->_getList(true, false, $lang); }
194194
function getAll($lang=false) { return $this->_getList(true, true, $lang); }
195-
function count($lang=false) { return count($this->getSeparates($lang)); }
195+
function count($lang=false): int { return count($this->getSeparates($lang)); }
196196

197197
function _getList($separates=false, $inlines=false, $lang=false) {
198198
$base = $this;

include/class.canned.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,12 @@ function update($vars,&$errors) {
311311

312312
return true;
313313
}
314+
315+
function staffCanAccess($staff) {
316+
if (!$staff instanceof Staff)
317+
return false;
318+
return (!$this->dept || (($role = $staff->getRole($this->dept)) && $role->hasPerm(Canned::PERM_MANAGE)));
319+
}
314320
}
315321
RolePermission::register( /* @trans */ 'Knowledgebase', Canned::getPermissions());
316322

include/class.config.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,9 @@ static function cleanPwResets() {
195195
))->delete();
196196
}
197197

198-
static function getConfigsByNamespace(?string $namespace=null, $key, $value=false) {
198+
199+
static function getConfigsByNamespace(?string $namespace, $key, $value=false) {
200+
199201
$filter = array();
200202

201203
$filter['key'] = $key;

include/class.dynamic_forms.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -914,7 +914,7 @@ function isValid() {
914914
/* `variable` is used for automation. Internally it's called `name` */
915915
), "name");
916916
}
917-
if ($this->get('name') && !preg_match('/^(?!\d)([[:alnum:]]|_|-)+$/u', $this->get('name')))
917+
if ($this->get('name') && !preg_match('/^(?!\d)([[:alnum:]]|_)+$/u', $this->get('name')))
918918
$this->addError(__(
919919
'Invalid character in variable name. Please use letters and numbers only.'
920920
), 'name');
@@ -1355,7 +1355,7 @@ function saveAnswers($isEditable=null, $refetch=false) {
13551355
//use getChanges if getClean returns an empty array
13561356
$fieldClean = $field->getClean() ?: $field->getChanges();
13571357
if (is_array($fieldClean) && $fieldClean[0])
1358-
$fieldClean = json_decode($fieldClean[0], true);
1358+
$fieldClean = is_string($fieldClean[0]) ? json_decode($fieldClean[0], true) : $fieldClean[0];
13591359
} else
13601360
$fieldClean = $field->getClean();
13611361

@@ -1593,7 +1593,7 @@ function parse($value) {
15931593
$selection = array();
15941594

15951595
if ($value && !is_array($value))
1596-
$value = array($value);
1596+
$value = JsonDataParser::parse($value) ?: array($value);
15971597

15981598
if ($value && is_array($value)) {
15991599
foreach ($value as $k=>$v) {
@@ -1633,6 +1633,7 @@ function to_php($value, $id=false) {
16331633
$values = array();
16341634
$choices = $this->getChoices();
16351635
foreach (explode(',', $value) as $V) {
1636+
$V = trim($V);
16361637
if (isset($choices[$V]))
16371638
$values[$V] = $choices[$V];
16381639
}

include/class.email.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1357,7 +1357,7 @@ protected function setInfo($vars, &$errors) {
13571357
// matching.
13581358
if ($vars['smtp_active'] == 1
13591359
&& ($vars['smtp_auth_bk'] === 'mailbox')
1360-
&& (strpos($vars['auth_bk'], 'oauth2') === 0)
1360+
&& (strpos($vars['mailbox_auth_bk'], 'oauth2') === 0)
13611361
&& !$this->checkStrictMatching())
13621362
$_errors['smtp_auth_bk'] = sprintf('%s and %s', __('Resource Owner'), __('Email Mismatch'));
13631363

include/class.export.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ static function departmentMembers($dept, $agents, $filename='', $how='csv') {
322322
exit;
323323
}
324324

325-
static function audits($type, ?string $filename=null, ?string $tableInfo=null, ?string $object=null, ?string $how='csv', ?bool $show_viewed=true, ?array $data=array(), CsvExporter $exporter) {
325+
static function audits($type, ?string $filename, ?string $tableInfo, ?string $object, ?string $how='csv', ?bool $show_viewed=true, ?array $data=array(), CsvExporter $exporter) {
326326
$headings = array('Description', 'Timestamp', 'IP');
327327
switch ($type) {
328328
case 'audit':
@@ -620,7 +620,7 @@ function escape($data) {
620620
}
621621

622622
function write($data) {
623-
fputcsv($this->fp, $this->escape($data), $this->getDelimiter());
623+
fputcsv($this->fp, $this->escape($data), $this->getDelimiter(), "\"", "");
624624
}
625625

626626
}
@@ -725,15 +725,15 @@ function dump($tmp=false) {
725725
$delimiter = $this->getDelimiter();
726726
// Output a UTF-8 BOM (byte order mark)
727727
fputs($this->output, chr(0xEF) . chr(0xBB) . chr(0xBF));
728-
fputcsv($this->output, $this->getHeaders(), $delimiter);
728+
fputcsv($this->output, $this->getHeaders(), $delimiter, "\"", "");
729729
while ($row=$this->next())
730730
fputcsv($this->output, array_map(
731731
function($v){
732732
if (preg_match('/^[=\-+@].*/', $v))
733733
return "'".$v;
734734
return $v;
735735
}, $row),
736-
$delimiter);
736+
$delimiter, "\"", "");
737737

738738
if (!$tmp)
739739
fclose($this->output);

include/class.filter_action.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ function getImpl() {
8989
return $this->_impl;
9090
}
9191

92-
static function setFilterFlags(?object $actions=null, $flag, $bool) {
92+
static function setFilterFlags(?object $actions, $flag, $bool) {
9393
$flag = constant($flag);
9494
if ($actions)
9595
foreach ($actions as $action)

0 commit comments

Comments
 (0)