Skip to content

fix: harden Apps page against errors from corrupt caches and malformed data - #128

Open
Squidly271 wants to merge 5 commits into
betafrom
fix/php-error-hardening
Open

fix: harden Apps page against errors from corrupt caches and malformed data#128
Squidly271 wants to merge 5 commits into
betafrom
fix/php-error-hardening

Conversation

@Squidly271

@Squidly271 Squidly271 commented Jul 15, 2026

Copy link
Copy Markdown
Collaborator

Summary

Defensive hardening across the Apps backend so corrupt cache files, malformed application-feed/template data, and unusual settings values degrade gracefully instead of throwing PHP errors (warnings or fatals) under PHP 8.

Changes

  • Pinned apps — cache reads cast to (array) (pinApp, areAppsPinned, my_display_apps), and findPinnedTemplate now honors the Hide Deprecated setting alongside the existing blacklist/incompatible skips.
  • Template info cache$GLOBALS['templates'] is coerced to an array at all four assignment sites, so a corrupt templates cache can't reach count()/foreach as a scalar.
  • Docker infogetAllInfo() always returns an array; $info lookups in the card/sidebar action builders are guarded (?? and $ind !== false) so a stale-vs-live mismatch can't misread or warn.
  • Translationtr() coerces non-string input to a safe string so it can't fatal inside dynamix _()'s trim().
  • XML generationArray2XML::createXML resets its static DomDocument state even when conversion throws (fixing a state leak into the next call), and makeXML() catches conversion exceptions instead of propagating a 500.
  • Guarded a couple of never-populated template fields (TemplateURL, Version) that were read without ??.

Notes

  • No functional/behaviour change on the happy path — every guard only changes what happens when data is missing, corrupt, or the wrong type.
  • .plg version, CHANGES block, and ca.md5 intentionally left untouched; a user-facing Fixed: bullet is added to plugins/CHANGES.md.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Improved Apps page stability by hardening against malformed cache/feed/template settings and unusual values.
    • Reduced rare page errors and related log noise (including corrupted pinned/published data).
    • Pinned apps now respect the Hide Deprecated setting, with more resilient pinned-data handling.
    • Safer app and language-pack action rendering when template metadata is missing.
    • Added guards for XML generation/conversion failures to prevent unhandled exceptions.
    • Deferred the plugin self-update flow to avoid interfering with the initial Action Centre visibility request.

Eli Bosley (elibosley) and others added 2 commits July 14, 2026 14:30
ci(release): establish beta promotion gate
…d data

Add defensive guards across the Apps backend so corrupt cache files, malformed application-feed/template data, and unusual settings values degrade gracefully instead of throwing PHP errors:

- Pinned apps: cast cache reads to array, guard the menu-state and toggle paths, and honor the Hide Deprecated setting.
- Template info cache ($GLOBALS['templates']) and Docker info (getAllInfo): always return arrays, with guarded $info lookups.
- Translation wrapper tr(): coerce non-string input so it can't fatal in dynamix _().
- XML generation: reset Array2XML static state on failure and catch conversion errors in makeXML.
- Guard a couple of never-populated template fields (TemplateURL, Version).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 27d1282b-f2ab-46ef-875c-5bf02a76aa97

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The Apps page now normalizes corrupted data, catches XML-generation failures, handles missing template metadata, and filters deprecated pinned apps when configured. The unreleased changelog documents these fixes.

Changes

Apps page resilience and pinned-app filtering

Layer / File(s) Summary
Normalize template data and XML state
source/.../include/helpers.php, source/.../include/xml_libs.php
Cache and helper inputs are normalized, translation/version handling is guarded, and XML failures reset state and return false.
Harden pinned-app loading and filtering
source/.../include/exec.php, source/.../include/pinned_apps_helpers.php, source/.../skins/Narrow/skin.php
Pinned data is cast to arrays, and deprecated templates are skipped when Hide Deprecated is enabled.
Guard template and language actions
source/.../skins/Narrow/skin_helpers.php
Docker and language actions safely handle absent URLs, template paths, running states, and template URLs.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

Poem

A bunny hops through cache and feed,
Safe little arrays now lead.
Deprecated pins hide from view,
Missing fields cause less ado.
XML resets, errors flee—
Apps page blooms reliably!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title uses the required conventional commit prefix and accurately describes the PR’s hardening/fix scope.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/php-error-hardening
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch fix/php-error-hardening

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

github-actions Bot added a commit that referenced this pull request Jul 15, 2026

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@source/community.applications/usr/local/emhttp/plugins/community.applications/include/helpers.php`:
- Around line 1181-1186: Update callers of makeXML, especially the usages in
exec.php, to explicitly detect a false return value before writing XML to disk.
Handle the failure gracefully by skipping the write or returning an appropriate
error, while preserving normal writes for valid XML results.
- Around line 2052-2055: Replace scalar-to-array casts for JSON cache values
with explicit array validation so invalid data produces an empty array. In
helpers.php lines 2052-2055, update the containers return path; also update the
readJsonFile calls in helpers.php lines 66 and 83, exec.php lines 1971 and 1988,
and skins/Narrow/skin.php line 1165 to use an is_array check with an empty-array
fallback.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 448ef3fd-e7c6-4aa6-97c3-b6792768c803

📥 Commits

Reviewing files that changed from the base of the PR and between 8c69240 and d6841ca.

📒 Files selected for processing (7)
  • plugins/CHANGES.md
  • source/community.applications/usr/local/emhttp/plugins/community.applications/include/exec.php
  • source/community.applications/usr/local/emhttp/plugins/community.applications/include/helpers.php
  • source/community.applications/usr/local/emhttp/plugins/community.applications/include/pinned_apps_helpers.php
  • source/community.applications/usr/local/emhttp/plugins/community.applications/include/xml_libs.php
  • source/community.applications/usr/local/emhttp/plugins/community.applications/skins/Narrow/skin.php
  • source/community.applications/usr/local/emhttp/plugins/community.applications/skins/Narrow/skin_helpers.php

@Squidly271
Squidly271 changed the base branch from master to beta July 20, 2026 03:17
Squidly271 added a commit that referenced this pull request Jul 20, 2026
- Use is_array(...) ? ... : [] instead of (array) casts so a corrupt cache
  that decodes to a scalar yields an empty array, not a one-element array
  wrapping the junk value (getGlobals, getFullGlobals, getAllInfo, pinApp,
  areAppsPinned, my_display_apps).
- Guard makeXML callers (createXML, convert_docker): on a false return, send
  an error response instead of writing an empty XML file to disk.
- Declare makeXML @return string|false to match the failure path (PHPStan).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Squidly271 and others added 2 commits July 20, 2026 00:48
- Use is_array(...) ? ... : [] instead of (array) casts so a corrupt cache
  that decodes to a scalar yields an empty array, not a one-element array
  wrapping the junk value (getGlobals, getFullGlobals, getAllInfo, pinApp,
  areAppsPinned, my_display_apps).
- Guard makeXML callers (createXML, convert_docker): on a false return, send
  an error response instead of writing an empty XML file to disk.
- Declare makeXML @return string|false to match the failure path (PHPStan).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Move caPluginUpdateCheck out of page init into the setupActionCentre callback
(guarded to run once). Kicking a CA plugin update check during init could leave
enableActionCentre blocking on an update that the same page load just started.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@Squidly271
Squidly271 force-pushed the fix/php-error-hardening branch from 1df109d to 4ccdd1f Compare July 20, 2026 04:50

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🧹 Nitpick comments (1)
source/community.applications/usr/local/emhttp/plugins/community.applications/include/helpers.php (1)

1158-1159: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Broaden the makeXML() failure contract.

makeXML() catches any Throwable, but the PHPDoc says false is returned only for invalid XML names. Document this as a general XML-conversion failure, or narrow the catch to the specific expected exception.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@source/community.applications/usr/local/emhttp/plugins/community.applications/include/helpers.php`
around lines 1158 - 1159, Update the makeXML() PHPDoc return description to
state that false may be returned for any XML-conversion failure, matching its
catch of any Throwable; do not limit the documented failure to invalid XML tag
or attribute names.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@source/community.applications/usr/local/emhttp/plugins/community.applications/include/helpers.php`:
- Around line 2053-2057: Normalize the result of the cache read immediately
after loading CA_PATHS['info'], before the refresh decision checks such as
!$containers or empty($containers). In the surrounding Docker cache refresh
function, convert any non-array value to [] at that point so corrupt scalar data
triggers the existing refresh path; then remove the redundant final is_array
guard while preserving the typed array return.

---

Nitpick comments:
In
`@source/community.applications/usr/local/emhttp/plugins/community.applications/include/helpers.php`:
- Around line 1158-1159: Update the makeXML() PHPDoc return description to state
that false may be returned for any XML-conversion failure, matching its catch of
any Throwable; do not limit the documented failure to invalid XML tag or
attribute names.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: bda91ddf-d6b0-40d4-bbd5-66631fdfc254

📥 Commits

Reviewing files that changed from the base of the PR and between d6841ca and 4ccdd1f.

📒 Files selected for processing (4)
  • source/community.applications/usr/local/emhttp/plugins/community.applications/Apps.page
  • source/community.applications/usr/local/emhttp/plugins/community.applications/include/exec.php
  • source/community.applications/usr/local/emhttp/plugins/community.applications/include/helpers.php
  • source/community.applications/usr/local/emhttp/plugins/community.applications/skins/Narrow/skin.php
🚧 Files skipped from review as they are similar to previous changes (1)
  • source/community.applications/usr/local/emhttp/plugins/community.applications/include/exec.php

Addresses CodeRabbit: the is_array guard was only at getAllInfo's return, so a
truthy scalar from a corrupt cache made both !$containers and empty() false,
skipping the refresh and returning [] indefinitely. Normalize non-arrays to []
right after the read so the existing refresh path rebuilds from Docker.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.

2 participants