Skip to content

FreePBX 17 / PHP 8.2 compatibility patches#4

Open
carlswart wants to merge 2 commits into
asternic:masterfrom
carlswart:fpbx17-compat
Open

FreePBX 17 / PHP 8.2 compatibility patches#4
carlswart wants to merge 2 commits into
asternic:masterfrom
carlswart:fpbx17-compat

Conversation

@carlswart

Copy link
Copy Markdown

This PR applies 8 patches to make Asternic CDR Reports v1.6.6 compatible with FreePBX 17 (PHP 8.2, Whoops error handler, PJSIP channels, and the new CDR recording pipeline).

Background

FreePBX 17 ships with PHP 8.x and the Whoops error handler, which converts E_WARNING into exceptions. The upstream v1.6.6 code was written for PHP 5/7 where missing array keys silently returned null. This causes hard crashes on multiple
features.

Additionally, FreePBX 17's CDR backend does not populate recordingfile for outgoing calls, breaking the play/download icons that the module relies on.

Patches included

| Patch │ Commit │What it fixes │
| ----- | --- | --- |
│ PATCH-001 │ 6b54b0b │ $_REQUEST['type'] / $_REQUEST['display'] undefined in getrecords AJAX handler │
│ PATCH-002 │ a09b4b6 │ Missing recording icons for outgoing calls — adds CEL session + disk glob() fallback │
│ PATCH-003 │ 6978961 │ PDF Footer() crash on null $lang array │
│ PATCH-004 │ 4f4cbfd │ PDF Combined report column mismatch (12 data columns vs 11 headers) │
│ PATCH-005 │ 75840ed │ Replace deprecated each() with foreach() in bundled FPDF │
│ PATCH-006 │ e1e8507 │ Distribution heatmap color index overflow ($colorete has only 7 elements) │
│ PATCH-007 │ d779b70 │ Escape unfiltered $_SERVER['REQUEST_URI'] and $_REQUEST output in HTML/JS │
│ PATCH-008 │ 98d0882 │ Remove dead Adobe Flash swf_bar_old() function (no callers, no SWF assets) │

Testing performed

All functionality was tested on a live FreePBX 17.0.28 installation:

  • Module loading / Module Admin
  • Outgoing / Incoming / Combined report charts
  • Drill-down detail table
  • Recording icons (incoming & outgoing)
  • Call recording playback (Howler.js)
  • Call recording download
  • PDF export (all report types)
  • CSV export
  • Distribution hourly heatmap

Backward compatibility

These changes are backward-compatible with PHP 7 / FreePBX 14-16:

  • Null coalescing (??) works on PHP 7.0+
  • htmlspecialchars() with explicit encoding is safe on all PHP versions
  • foreach() replacing each() is valid on all PHP versions
  • The removed swf_bar_old() had zero callers

Documentation

The README has been updated with a FreePBX 17 Compatibility section explaining the fixes and installation methods.


Thank you for maintaining this module. Let me know if you would like any changes before merging.

- Fix PHP 8 undefined array keys in getrecords AJAX handler
- Add CEL + disk fallback for missing recordingfile on outgoing calls
- Fix PDF Footer() crash on null locale array
- Fix Combined report PDF column mismatch
- Replace deprecated each() with foreach() in FPDF
- Cap color index in Distribution heatmap
- Escape unfiltered superglobals in HTML/JS output
- Remove dead Adobe Flash swf_bar_old() function

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request introduces compatibility patches for FreePBX 17 and PHP 8.2, addressing issues such as deprecated functions, PDF export crashes, missing recording files, and unescaped superglobals. The review feedback highlights several critical issues: removing the $total_bill > 0 check introduces a division-by-zero risk, $ftype and $fdisplay require sanitization to prevent XSS/JS injection, the $numcolor cap needs to be applied to the 1-day report block as well, and a ternary expression in the PDF footer can be simplified using the null coalescing operator.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread page.asternic_cdr.php Outdated
Comment on lines +1016 to +1017
$percentage_bill = $val * 100 / $total_bill;
$percentage_bill = number_format($percentage_bill,2);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

critical

Removing the $total_bill > 0 check introduces a critical division by zero risk. If there are only missed calls or if the total billable time is zero, $total_bill will be 0, causing a fatal DivisionByZeroError or a warning that is converted to an exception by the Whoops error handler in FreePBX 17. Please restore the check or use a safe ternary operator.

                $percentage_bill = $total_bill > 0 ? number_format($val * 100 / $total_bill, 2) : '0.00';

Comment thread functions.inc.php
Comment on lines +203 to +204
$ftype = $_REQUEST['type'] ?? 'tool';
$fdisplay = $_REQUEST['display'] ?? 'asternic_cdr';

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

security-high high

The variables $ftype and $fdisplay are retrieved directly from $_REQUEST and later outputted unescaped inside a JavaScript onclick attribute (line 288). This creates a Cross-Site Scripting (XSS) and JavaScript injection vulnerability. Since these variables are expected to be simple alphanumeric identifiers (e.g., 'tool', 'asternic_cdr'), they should be sanitized to only allow alphanumeric characters, underscores, and hyphens.

    $ftype = preg_replace('/[^a-zA-Z0-9_-]/', '', $_REQUEST['type'] ?? 'tool');
    $fdisplay = preg_replace('/[^a-zA-Z0-9_-]/', '', $_REQUEST['display'] ?? 'asternic_cdr');

Comment thread page.asternic_cdr.php
if(!isset($num[$chann][$date][$hour])) { $num[$chann][$date][$hour]=0;}
$numcolor = intval(($dur[$chann][$date][$hour]/60)/10);
if((intval($dur[$chann][$date][$hour]/60))==0) { $numcolor=6; }
if($numcolor > 6) { $numcolor = 6; }

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

While you successfully capped $numcolor at 6 to prevent undefined offset errors in the multi-day report block, the same bug is still present in the 1-day report block (around line 490). If a 1-day report has more than 60 minutes of calls in a single hour, $numcolor will exceed 6 and cause an 'Undefined array key' Whoops exception. Please ensure you also apply this cap to the 1-day report block.

Comment thread functions.inc.php Outdated
$this->SetFont('Arial','I',8);
//Print centered page number
$this->Cell(0,10,$lang["$language"]['page'].' '.$this->PageNo(),0,0,'C');
$pageText = (isset($lang[$language]['page']) ? $lang[$language]['page'] : 'Page') . ' ' . $this->PageNo();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

This ternary expression can be simplified and made more idiomatic using the PHP null coalescing operator (??). This improves readability and is fully compatible with PHP 7.0+.

        $pageText = ($lang[$language]['page'] ?? 'Page') . ' ' . $this->PageNo();

- Restore >0 guard in Combined report (division-by-zero risk)
- Sanitize  /  with htmlspecialchars() before JS interpolation
- Apply  cap to 1-day distribution report block as well
- Simplify PDF footer ternary: use ?? for nested key with isset() guard on parent
@carlswart

Copy link
Copy Markdown
Author

Thanks for the thorough review. I've pushed commit 0f25413 to address all four points:

  1. Division-by-zero in Combined report — Restored the $total_bill>0 guard before calculating $percentage_bill in the Combined report loop (page.asternic_cdr.php:1017).

  2. XSS in $ftype / $fdisplay — Added htmlspecialchars(..., ENT_QUOTES, 'UTF-8') on both variables before they are interpolated into the JavaScript onclick handler (functions.inc.php:288).

  3. $numcolor cap missing in 1-day block — Added if($numcolor > 6) { $numcolor = 6; } to the single-day distribution heatmap loop (page.asternic_cdr.php:492). The existing cap on the multi-day block was correct; this brings the
    1-day block into parity.

  4. PDF footer ternary simplification — Restructured to isset($lang[$language]) ? ($lang[$language]['page'] ?? 'Page') : 'Page'. This uses ?? for the nested key while keeping isset() on the parent array element, which is safe
    when $lang itself is null (the FreePBX 17 execution context).

Let me know if anything else needs adjustment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant