Notifications
Clear all
6 Forums 829 Topics 3,280 Posts 3 Online 3,047 Members

In Progress MergedEvent crashes on PHP 8 when agent name contains URL-encoded characters

2 Posts
2 Users
0 Reactions
16 Views
Posts: 6
Topic starter
(@cbd4-dk)
Member
Joined: 6 months ago

Environment:

  • osTicket-1.18.3-Awesome-104
  • PHP 8.3.6

When viewing a ticket containing merged child tickets, osTicket throws a fatal PHP error:

PHP Fatal error: Uncaught ValueError: Unknown format specifier "C"

The error originates from:

include/class.thread.php

class MergedEvent extends ThreadEvent {
function getDescription($mode=self::MODE_STAFF) {
return sprintf(
$this->template(
__('{somebody} merged this ticket with %s{data.id}%s{data.ticket}%s {timestamp}'),
$mode
),
'', ''
);
}
}

Stack trace points directly to the sprintf() call.

Root Cause:
The {somebody} placeholder is expanded before sprintf() is executed.

In our installation the merged event was created by an agent named:

Casper F. Sørensen

The generated HTML contains an avatar URL with URL-encoded characters:

name=Casper+F.+S%C3%B8rensen

After placeholder substitution, sprintf() receives a string containing:

%C3%B8

PHP 8 interprets "%C" as a format specifier and throws:

ValueError: Unknown format specifier "C"

This causes the entire ticket thread rendering to fail.

Example Debug Output:
Template result:

<img class="avatar" ... name=Casper+F.+S%C3%B8rensen" />Casper F. Sørensen
merged this ticket with 344
Ticket #S416

Expected Behavior:
Merged ticket events should render correctly regardless of agent names containing non-ASCII characters such as:

ø
æ
å
ü
é
etc.

Actual Behavior:
Ticket thread rendering fails with a fatal PHP error.

Suggested Fix:
Avoid using sprintf() after placeholder expansion.

One possible approach:

Build the link placeholders before template rendering.
Use str_replace() instead of sprintf().
Escape literal percent signs before passing strings to sprintf().

For example:

return str_replace(
array('LINK_START', 'LINK_MID', 'LINK_END'),
array('', ''),
$this->template(__($raw), $mode)
);

Impact:
Any merged ticket can become unreadable when the merge event was performed by an agent whose display name results in URL-encoded percent sequences being present in the rendered HTML.

This appears to be a PHP 8 compatibility issue rather than a localization or theme issue.


1 Reply
Posts: 1187
Admin
(@stevland)
Member
Joined: 10 years ago

Thanks for the detailed write-up, Carsten. You've done the investigative work here and your analysis is correct. The {somebody} placeholder is expanded by template() before sprintf() runs, so any URL-encoded characters in the resulting HTML (like %C3%B8 from "Sørensen") land in sprintf() as format specifiers. PHP 7 would silently ignore unknown ones; PHP 8 throws a ValueError. Your suggested fix is sound.

This is a bug in osTicket core (include/class.thread.php) rather than something osTicket Awesome modifies, so as a matter of policy its not something I can patch on our end (I don't patch upstream issues in osTicket Awesome as doing so would create too much chaos over time).

What I can do is take your report and open an issue on the osTicket GitHub tracker on your behalf. You've already written the hard part. I'd send you the link so you can follow it upstream.

Would you like me to do that? Or perhaps you would rather do it yourself and receive all of the glory. Let me know which you prefer.


Reply
Share: