Skip to content

Comments

feat:2.0 composer integration#1683

Open
fiammybe wants to merge 22 commits intoImpressCMS:developfrom
fiammybe:2.0-composer-integration
Open

feat:2.0 composer integration#1683
fiammybe wants to merge 22 commits intoImpressCMS:developfrom
fiammybe:2.0-composer-integration

Conversation

@fiammybe
Copy link
Member

@fiammybe fiammybe commented Feb 21, 2026

This introduces Composer-based autoloading for libraries. No new functionality, just the base framework to start extricating bundled PHP libraries from the core.

  • moved some libraries to composer already : htmlpurifier, simplepie and wideimage
  • during installation or update, the bundled vendor folder is moved below the trustpath for added security.

To test : execute a 'composer install' to get the necessary files in the vendor folder. This will have been done already in the release archive.

fiammybe and others added 22 commits January 4, 2025 19:34
…omposer, but that is not yet implemented for HTMLPurifier
Co-authored-by: Raimondas Rimkevičius <github@mekdrop.name>
…unused dev dependencies, and clean up scripts
@qodo-free-for-open-source-projects
Copy link
Contributor

Review Summary by Qodo

Composer integration with vendor directory security relocation

✨ Enhancement

Grey Divider

Walkthroughs

Description
• Implements Composer-based autoloading for ImpressCMS libraries, replacing bundled PHP libraries
  with Composer dependencies
• Moves HTMLPurifier, SimplePie, and WideImage libraries to Composer management, removing 300+
  bundled library files
• Adds moveVendorToTrust() functionality to securely relocate Composer vendor directory from web
  root to trust path during installation
• Integrates new vendor move installation wizard page with comprehensive error handling and user
  feedback
• Updates autoloader chain in icms.php and installation bootstrap to support both trust path and
  root path vendor locations
• Implements Composer-based module and theme discovery via InstalledVersions instead of filesystem
  scanning
• Adds composer.json with PSR-4/PSR-0 autoloading configuration for Icms\* and icms_*
  namespaces
• Standardizes codebase to PSR-12 formatting: array syntax [], double quotes, proper brace
  placement
• Updates SimplePie and HTMLPurifier references to use namespaced class constants from Composer
  packages
• Increments database version to 49 and system version to 2.1.0 beta
• Fixes minor bugs: undefined array index in theme blocks, array indentation inconsistencies
Diagram
flowchart LR
  A["Bundled Libraries<br/>htmlpurifier, simplepie,<br/>wideimage"] -->|"Migrate to Composer"| B["composer.json<br/>Dependencies"]
  B -->|"Install via Composer"| C["vendor/ Directory<br/>in Web Root"]
  C -->|"moveVendorToTrust()"| D["Trust Path<br/>vendor/"]
  E["Autoloader Chain"] -->|"Load from"| D
  F["Module/Theme Discovery"] -->|"Query via"| B
  G["Installation Wizard"] -->|"Execute"| C
  G -->|"Trigger"| D
Loading

Grey Divider

File Changes

1. htdocs/libraries/icms/core/Filesystem.php ✨ Enhancement +407/-116

Code formatting and vendor directory relocation functionality

• Reformatted code to follow PSR-12 coding standards (opening braces on new lines, proper spacing)
• Changed array syntax from array() to [] throughout the file
• Converted single quotes to double quotes for consistency
• Added new moveVendorToTrust() static method to safely move Composer vendor directory from web
 root to trust path
• Improved code readability with better line breaks and indentation in complex statements

htdocs/libraries/icms/core/Filesystem.php


2. htdocs/install/language/english/install.php 📝 Documentation +262/-73

Language constants for vendor move installation step

• Reformatted multi-line define() statements to improve readability
• Changed quote style from single to double quotes for consistency
• Added new language constants for vendor move installation step (MOVE_VENDOR, MOVE_VENDOR_TITLE,
 VENDOR_MOVE_* messages)
• Improved formatting of long strings and concatenations

htdocs/install/language/english/install.php


3. htdocs/modules/system/icms_version.php ⚙️ Configuration changes +309/-252

Version bump and code style standardization

• Updated module version from 2.0.2 to 2.1.0 beta
• Changed array syntax from array() to [] throughout
• Converted single quotes to double quotes for consistency
• Updated status from "Final" to "Beta" with new date and author notes
• Reformatted multi-line array definitions for better readability

htdocs/modules/system/icms_version.php


View more (120)
4. htdocs/modules/system/include/update.php ✨ Enhancement +202/-60

Database upgrade for vendor directory relocation

• Added new database version 49 upgrade step for moving vendor directory to trust path
• Implemented moveVendorToTrust() call with comprehensive error handling and user feedback
• Changed array syntax from array() to [] and quotes from single to double
• Improved code formatting with proper line breaks and indentation
• Added detailed comments explaining the vendor move operation and conflict resolution

htdocs/modules/system/include/update.php


5. htdocs/install/class/IcmsInstallWizard.php ✨ Enhancement +79/-57

Installation wizard integration for vendor move step

• Added movevendor page to the installation wizard page sequence
• Updated page names and titles arrays to include vendor move step
• Reformatted code to PSR-12 standards with opening braces on new lines
• Changed array syntax from array() to [] and quotes to double quotes
• Improved code readability with consistent spacing and indentation

htdocs/install/class/IcmsInstallWizard.php


6. htdocs/libraries/icms/core/HTMLFilter.php ✨ Enhancement +18/-11

HTMLPurifier Composer integration and autoloading

• Added use \HTMLPurifier; statement at the top for Composer autoloading
• Removed manual require_once statements for HTMLPurifier (now handled by Composer)
• Updated getCustomFilterList() to check both bundled and Composer vendor locations
• Improved code comments to document fallback behavior for backward compatibility

htdocs/libraries/icms/core/HTMLFilter.php


7. htdocs/libraries/icms/module/Handler.php ✨ Enhancement +30/-4

Composer-based module and theme discovery

• Added use \Composer\InstalledVersions; statement for Composer integration
• Renamed getAvailable() to getAvailableOld() and created new getAvailable() using Composer
 packages
• New implementation queries Composer for installed packages of type impresscms-theme and
 impresscms-module
• Added return type declarations (: array, : int) to several methods
• Improved code formatting with proper spacing

htdocs/libraries/icms/module/Handler.php


8. htdocs/install/modules/protector/trust_path/modules/protector/filters_byconfig/postcommon_post_htmlpurify4everyone.php ✨ Enhancement +1/-1

HTMLPurifier Composer use statement

• Added use \HTMLPurifier; statement for Composer autoloading support

htdocs/install/modules/protector/trust_path/modules/protector/filters_byconfig/postcommon_post_htmlpurify4everyone.php


9. htdocs/libraries/icms.php ✨ Enhancement +169/-99

Composer integration with PSR-12 code formatting

• Replaced custom icms_Autoloader with Composer's autoloader, supporting both trust path and root
 path locations
• Reformatted code to PSR-12 standards: adjusted brace placement, converted array syntax from
 array() to [], changed quotes from single to double
• Updated static property declarations from static public to public static for consistency
• Refactored method signatures with improved formatting and line breaks for readability
• Added fallback autoloader registration for trust-path vendor scenarios to correctly resolve
 icms_* and Icms\* classes

htdocs/libraries/icms.php


10. htdocs/libraries/icms/view/theme/Factory.php Formatting +117/-111

PSR-12 code style reformatting and array handling

• Reformatted entire file to PSR-12 standards with consistent indentation and brace placement
• Changed array syntax from array() to [] throughout
• Updated docblock formatting with consistent spacing
• Modified getThemesList() to return empty array fallback instead of potentially non-array value
• Added safety check in getAdminThemesList() for file existence before concatenation

htdocs/libraries/icms/view/theme/Factory.php


11. htdocs/install/install_tpl.php Formatting +56/-41

Quote standardization and template logic improvements

• Converted string quotes from single to double quotes throughout
• Reformatted conditional blocks and PHP embedded in HTML for better readability
• Simplified arithmetic expressions (removed unnecessary parentheses)
• Updated array access and string concatenation formatting
• Changed hardcoded page number 11 to use $wizard->lastpage variable for flexibility

htdocs/install/install_tpl.php


12. htdocs/include/common.php ✨ Enhancement +134/-32

Composer autoloader integration with trust path support

• Added comprehensive Composer autoloader loading with trust path priority and fallback logic
• Implemented prepended SPL autoloader to handle icms_* (PSR-0) and Icms\* (PSR-4) class
 resolution when vendor is in trust path
• Converted string quotes from single to double quotes
• Reformatted conditional statements and array initializations to PSR-12 standards
• Added detailed comments explaining the autoloader strategy and trust path resolution

htdocs/include/common.php


13. htdocs/install/common.inc.php ✨ Enhancement +193/-15

Installer Composer autoloader with trust path detection

• Moved session_start() to beginning of file before autoloader loading to enable trust path
 detection via session
• Replaced icms_Autoloader::setup() with Composer autoloader loading logic
• Added sophisticated vendor directory location detection (trust path vs web root) with fallback
 mechanisms
• Implemented prepended SPL autoloader for icms_* and Icms\* classes when vendor is in trust
 path
• Added comprehensive error handling with human-readable messages when autoloader is not found
• Converted string quotes from single to double quotes

htdocs/install/common.inc.php


14. htdocs/install/page_movevendor.php ✨ Enhancement +239/-0

New installer page for vendor directory security move

• New file implementing vendor directory migration from web root to trust path during installation
• Provides GET preview showing current state and what will happen on POST submission
• Executes vendor move via icms_core_Filesystem::moveVendorToTrust() on POST with error handling
• Includes helper functions for state analysis, conflict detection, and HTML preview/result building
• Sets session flag VENDOR_MOVED to signal successful move to subsequent installer pages

htdocs/install/page_movevendor.php


15. htdocs/include/version.php Formatting +5/-5

Version constants quote standardization

• Converted all define() calls from single to double quotes for consistency
• Updated ICMS_SYSTEM_DBVERSION from 48 to 49 to reflect database schema changes

htdocs/include/version.php


16. htdocs/libraries/icms/module/Object.php ✨ Enhancement +3/-11

Module class registration delegated to Composer

• Removed manual class path registration logic from registerClassPath() method
• Added comment explaining that Composer autoloader now handles module class loading via classmap
• Simplified method to only check module status without performing registration

htdocs/libraries/icms/module/Object.php


17. htdocs/install/modules/protector/trust_path/modules/protector/filters_byconfig/postcommon_post_htmlpurify4guest.php ✨ Enhancement +3/-1

HTMLPurifier namespace import via Composer

• Added use \HTMLPurifier; namespace import at top of file
• Removed require_once statement for HTMLPurifier.auto.php (now loaded via Composer)
• Simplified code by relying on Composer autoloader instead of manual inclusion

htdocs/install/modules/protector/trust_path/modules/protector/filters_byconfig/postcommon_post_htmlpurify4guest.php


18. htdocs/admin.php ✨ Enhancement +1/-1

SimplePie constant namespace update

• Updated SimplePie constant reference from SIMPLEPIE_LOCATOR_NONE to
 \Simplepie\Simplepie::LOCATOR_NONE
• Changed to use namespaced class constant from Composer-managed SimplePie library

htdocs/admin.php


19. htdocs/modules/system/admin/modulesadmin/modulesadmin.php Formatting +2/-2

Array indentation formatting fixes

• Fixed array closing parenthesis indentation in xoops_module_install() function
• Fixed array closing parenthesis indentation in xoops_module_uninstall() function

htdocs/modules/system/admin/modulesadmin/modulesadmin.php


20. htdocs/libraries/icms/feeds/Simplerss.php ✨ Enhancement +1/-2

SimplePie namespace import via Composer

• Replaced include_once statements for SimplePie library files with use \SimplePie\SimplePie;
 namespace import
• Removed manual inclusion of autoloader and IDN conversion class (now handled by Composer)

htdocs/libraries/icms/feeds/Simplerss.php


21. htdocs/modules/system/blocks/system_blocks.php 🐞 Bug fix +1/-0

Theme block array initialization fix

• Added initialization of $block['theme_select'] as empty array before loop to prevent undefined
 index warnings

htdocs/modules/system/blocks/system_blocks.php


22. htdocs/composer.json ⚙️ Configuration changes +77/-0

Composer project configuration with library dependencies

• New file defining Composer project configuration for ImpressCMS
• Specifies PHP 7.4+ requirement and required extensions (gd, json, mbstring, mysqli, pcre, pdo,
 session, xml, zlib)
• Declares dependencies on HTMLPurifier, SimplePie, and WideImage libraries
• Configures PSR-4 and PSR-0 autoloading for Icms\* and icms_* classes from libraries directory
• Includes classmap entry for bare icms class
• Sets Composer configuration for optimized autoloader and vendor directory location

htdocs/composer.json


23. htdocs/libraries/WideImage/Canvas.php Additional files +0/-161

...

htdocs/libraries/WideImage/Canvas.php


24. htdocs/libraries/WideImage/Coordinate.php Additional files +0/-198

...

htdocs/libraries/WideImage/Coordinate.php


25. htdocs/libraries/WideImage/Exception/Exception.php Additional files +0/-32

...

htdocs/libraries/WideImage/Exception/Exception.php


26. htdocs/libraries/WideImage/Exception/GDFunctionResultException.php Additional files +0/-10

...

htdocs/libraries/WideImage/Exception/GDFunctionResultException.php


27. htdocs/libraries/WideImage/Exception/InvalidCanvasMethodException.php Additional files +0/-8

...

htdocs/libraries/WideImage/Exception/InvalidCanvasMethodException.php


28. htdocs/libraries/WideImage/Exception/InvalidCoordinateException.php Additional files +0/-8

...

htdocs/libraries/WideImage/Exception/InvalidCoordinateException.php


29. htdocs/libraries/WideImage/Exception/InvalidFontFileException.php Additional files +0/-8

...

htdocs/libraries/WideImage/Exception/InvalidFontFileException.php


30. htdocs/libraries/WideImage/Exception/InvalidImageDimensionException.php Additional files +0/-10

...

htdocs/libraries/WideImage/Exception/InvalidImageDimensionException.php


31. htdocs/libraries/WideImage/Exception/InvalidImageHandleException.php Additional files +0/-8

...

htdocs/libraries/WideImage/Exception/InvalidImageHandleException.php


32. htdocs/libraries/WideImage/Exception/InvalidImageSourceException.php Additional files +0/-8

...

htdocs/libraries/WideImage/Exception/InvalidImageSourceException.php


33. htdocs/libraries/WideImage/Exception/NoFontException.php Additional files +0/-8

...

htdocs/libraries/WideImage/Exception/NoFontException.php


34. htdocs/libraries/WideImage/Exception/UnknownErrorWhileMappingException.php Additional files +0/-10

...

htdocs/libraries/WideImage/Exception/UnknownErrorWhileMappingException.php


35. htdocs/libraries/WideImage/Exception/UnknownImageOperationException.php Additional files +0/-8

...

htdocs/libraries/WideImage/Exception/UnknownImageOperationException.php


36. htdocs/libraries/WideImage/Exception/UnsupportedFormatException.php Additional files +0/-10

...

htdocs/libraries/WideImage/Exception/UnsupportedFormatException.php


37. htdocs/libraries/WideImage/Font/GDF.php Additional files +0/-51

...

htdocs/libraries/WideImage/Font/GDF.php


38. htdocs/libraries/WideImage/Font/PS.php Additional files +0/-64

...

htdocs/libraries/WideImage/Font/PS.php


39. htdocs/libraries/WideImage/Font/TTF.php Additional files +0/-79

...

htdocs/libraries/WideImage/Font/TTF.php


40. htdocs/libraries/WideImage/Image.php Additional files +0/-979

...

htdocs/libraries/WideImage/Image.php


41. htdocs/libraries/WideImage/LICENSE Additional files +0/-16

...

htdocs/libraries/WideImage/LICENSE


42. htdocs/libraries/WideImage/Mapper/BMP.php Additional files +0/-53

...

htdocs/libraries/WideImage/Mapper/BMP.php


43. htdocs/libraries/WideImage/Mapper/GD.php Additional files +0/-46

...

htdocs/libraries/WideImage/Mapper/GD.php


44. htdocs/libraries/WideImage/Mapper/GD2.php Additional files +0/-42

...

htdocs/libraries/WideImage/Mapper/GD2.php


45. htdocs/libraries/WideImage/Mapper/GIF.php Additional files +0/-52

...

htdocs/libraries/WideImage/Mapper/GIF.php


46. htdocs/libraries/WideImage/Mapper/JPEG.php Additional files +0/-42

...

htdocs/libraries/WideImage/Mapper/JPEG.php


47. htdocs/libraries/WideImage/Mapper/PNG.php Additional files +0/-42

...

htdocs/libraries/WideImage/Mapper/PNG.php


48. htdocs/libraries/WideImage/Mapper/TGA.php Additional files +0/-50

...

htdocs/libraries/WideImage/Mapper/TGA.php


49. htdocs/libraries/WideImage/Mapper/WEBP.php Additional files +0/-43

...

htdocs/libraries/WideImage/Mapper/WEBP.php


50. htdocs/libraries/WideImage/MapperFactory.php Additional files +0/-136

...

htdocs/libraries/WideImage/MapperFactory.php


51. htdocs/libraries/WideImage/Operation/AddNoise.php Additional files +0/-167

...

htdocs/libraries/WideImage/Operation/AddNoise.php


52. htdocs/libraries/WideImage/Operation/ApplyConvolution.php Additional files +0/-54

...

htdocs/libraries/WideImage/Operation/ApplyConvolution.php


53. htdocs/libraries/WideImage/Operation/ApplyFilter.php Additional files +0/-72

...

htdocs/libraries/WideImage/Operation/ApplyFilter.php


54. htdocs/libraries/WideImage/Operation/ApplyMask.php Additional files +0/-105

...

htdocs/libraries/WideImage/Operation/ApplyMask.php


55. htdocs/libraries/WideImage/Operation/AsGrayscale.php Additional files +0/-55

...

htdocs/libraries/WideImage/Operation/AsGrayscale.php


56. htdocs/libraries/WideImage/Operation/AsNegative.php Additional files +0/-70

...

htdocs/libraries/WideImage/Operation/AsNegative.php


57. htdocs/libraries/WideImage/Operation/AutoCrop.php Additional files +0/-166

...

htdocs/libraries/WideImage/Operation/AutoCrop.php


58. htdocs/libraries/WideImage/Operation/CopyChannelsPalette.php Additional files +0/-98

...

htdocs/libraries/WideImage/Operation/CopyChannelsPalette.php


59. htdocs/libraries/WideImage/Operation/CopyChannelsTrueColor.php Additional files +0/-74

...

htdocs/libraries/WideImage/Operation/CopyChannelsTrueColor.php


60. htdocs/libraries/WideImage/Operation/CorrectGamma.php Additional files +0/-52

...

htdocs/libraries/WideImage/Operation/CorrectGamma.php


61. htdocs/libraries/WideImage/Operation/Crop.php Additional files +0/-96

...

htdocs/libraries/WideImage/Operation/Crop.php


62. htdocs/libraries/WideImage/Operation/Exception/InvalidFitMethodException.php Additional files +0/-10

...

htdocs/libraries/WideImage/Operation/Exception/InvalidFitMethodException.php


63. htdocs/libraries/WideImage/Operation/Exception/InvalidResizeDimensionException.php Additional files +0/-10

...

htdocs/libraries/WideImage/Operation/Exception/InvalidResizeDimensionException.php


64. htdocs/libraries/WideImage/Operation/Flip.php Additional files +0/-60

...

htdocs/libraries/WideImage/Operation/Flip.php


65. htdocs/libraries/WideImage/Operation/GetMask.php Additional files +0/-76

...

htdocs/libraries/WideImage/Operation/GetMask.php


66. htdocs/libraries/WideImage/Operation/Merge.php Additional files +0/-82

...

htdocs/libraries/WideImage/Operation/Merge.php


67. htdocs/libraries/WideImage/Operation/Mirror.php Additional files +0/-60

...

htdocs/libraries/WideImage/Operation/Mirror.php


68. htdocs/libraries/WideImage/Operation/Resize.php Additional files +0/-166

...

htdocs/libraries/WideImage/Operation/Resize.php


69. htdocs/libraries/WideImage/Operation/ResizeCanvas.php Additional files +0/-109

...

htdocs/libraries/WideImage/Operation/ResizeCanvas.php


70. htdocs/libraries/WideImage/Operation/Rotate.php Additional files +0/-71

...

htdocs/libraries/WideImage/Operation/Rotate.php


71. htdocs/libraries/WideImage/Operation/RoundCorners.php Additional files +0/-124

...

htdocs/libraries/WideImage/Operation/RoundCorners.php


72. htdocs/libraries/WideImage/Operation/Unsharp.php Additional files +0/-154

...

htdocs/libraries/WideImage/Operation/Unsharp.php


73. htdocs/libraries/WideImage/OperationFactory.php Additional files +0/-56

...

htdocs/libraries/WideImage/OperationFactory.php


74. htdocs/libraries/WideImage/PaletteImage.php Additional files +0/-150

...

htdocs/libraries/WideImage/PaletteImage.php


75. htdocs/libraries/WideImage/TrueColorImage.php Additional files +0/-293

...

htdocs/libraries/WideImage/TrueColorImage.php


76. htdocs/libraries/WideImage/VERSION Additional files +0/-2

...

htdocs/libraries/WideImage/VERSION


77. htdocs/libraries/WideImage/WideImage.php Additional files +0/-372

...

htdocs/libraries/WideImage/WideImage.php


78. htdocs/libraries/WideImage/gpl.txt Additional files +0/-339

...

htdocs/libraries/WideImage/gpl.txt


79. htdocs/libraries/WideImage/index.html Additional files +0/-1

...

htdocs/libraries/WideImage/index.html


80. htdocs/libraries/WideImage/lgpl.txt Additional files +0/-504

...

htdocs/libraries/WideImage/lgpl.txt


81. htdocs/libraries/WideImage/lib/Canvas.php Additional files +0/-167

...

htdocs/libraries/WideImage/lib/Canvas.php


82. htdocs/libraries/WideImage/lib/Coordinate.php Additional files +0/-208

...

htdocs/libraries/WideImage/lib/Coordinate.php


83. htdocs/libraries/WideImage/lib/Exception.php Additional files +0/-31

...

htdocs/libraries/WideImage/lib/Exception.php


84. htdocs/libraries/WideImage/lib/Font/GDF.php Additional files +0/-48

...

htdocs/libraries/WideImage/lib/Font/GDF.php


85. htdocs/libraries/WideImage/lib/Font/PS.php Additional files +0/-60

...

htdocs/libraries/WideImage/lib/Font/PS.php


86. htdocs/libraries/WideImage/lib/Font/TTF.php Additional files +0/-75

...

htdocs/libraries/WideImage/lib/Font/TTF.php


87. htdocs/libraries/WideImage/lib/Font/index.html Additional files +0/-1

...

htdocs/libraries/WideImage/lib/Font/index.html


88. htdocs/libraries/WideImage/lib/Image.php Additional files +0/-964

...

htdocs/libraries/WideImage/lib/Image.php


89. htdocs/libraries/WideImage/lib/Mapper/BMP.php Additional files +0/-51

...

htdocs/libraries/WideImage/lib/Mapper/BMP.php


90. htdocs/libraries/WideImage/lib/Mapper/GD.php Additional files +0/-44

...

htdocs/libraries/WideImage/lib/Mapper/GD.php


91. htdocs/libraries/WideImage/lib/Mapper/GD2.php Additional files +0/-41

...

htdocs/libraries/WideImage/lib/Mapper/GD2.php


92. htdocs/libraries/WideImage/lib/Mapper/GIF.php Additional files +0/-50

...

htdocs/libraries/WideImage/lib/Mapper/GIF.php


93. htdocs/libraries/WideImage/lib/Mapper/JPEG.php Additional files +0/-41

...

htdocs/libraries/WideImage/lib/Mapper/JPEG.php


94. htdocs/libraries/WideImage/lib/Mapper/PNG.php Additional files +0/-41

...

htdocs/libraries/WideImage/lib/Mapper/PNG.php


95. htdocs/libraries/WideImage/lib/Mapper/TGA.php Additional files +0/-48

...

htdocs/libraries/WideImage/lib/Mapper/TGA.php


96. htdocs/libraries/WideImage/lib/Mapper/index.html Additional files +0/-1

...

htdocs/libraries/WideImage/lib/Mapper/index.html


97. htdocs/libraries/WideImage/lib/MapperFactory.php Additional files +0/-126

...

htdocs/libraries/WideImage/lib/MapperFactory.php


98. htdocs/libraries/WideImage/lib/Operation/AddNoise.php Additional files +0/-153

...

htdocs/libraries/WideImage/lib/Operation/AddNoise.php


99. htdocs/libraries/WideImage/lib/Operation/ApplyConvolution.php Additional files +0/-48

...

htdocs/libraries/WideImage/lib/Operation/ApplyConvolution.php


100. htdocs/libraries/WideImage/lib/Operation/ApplyFilter.php Additional files +0/-67

...

htdocs/libraries/WideImage/lib/Operation/ApplyFilter.php


101. htdocs/libraries/WideImage/lib/Operation/ApplyMask.php Additional files +0/-105

...

htdocs/libraries/WideImage/lib/Operation/ApplyMask.php


102. htdocs/libraries/WideImage/lib/Operation/AsGrayscale.php Additional files +0/-49

...

htdocs/libraries/WideImage/lib/Operation/AsGrayscale.php


103. htdocs/libraries/WideImage/lib/Operation/AsNegative.php Additional files +0/-63

...

htdocs/libraries/WideImage/lib/Operation/AsNegative.php


104. htdocs/libraries/WideImage/lib/Operation/AutoCrop.php Additional files +0/-162

...

htdocs/libraries/WideImage/lib/Operation/AutoCrop.php


105. htdocs/libraries/WideImage/lib/Operation/CopyChannelsPalette.php Additional files +0/-90

...

htdocs/libraries/WideImage/lib/Operation/CopyChannelsPalette.php


106. htdocs/libraries/WideImage/lib/Operation/CopyChannelsTrueColor.php Additional files +0/-67

...

htdocs/libraries/WideImage/lib/Operation/CopyChannelsTrueColor.php


107. htdocs/libraries/WideImage/lib/Operation/CorrectGamma.php Additional files +0/-48

...

htdocs/libraries/WideImage/lib/Operation/CorrectGamma.php


108. htdocs/libraries/WideImage/lib/Operation/Crop.php Additional files +0/-86

...

htdocs/libraries/WideImage/lib/Operation/Crop.php


109. htdocs/libraries/WideImage/lib/Operation/Flip.php Additional files +0/-54

...

htdocs/libraries/WideImage/lib/Operation/Flip.php


110. htdocs/libraries/WideImage/lib/Operation/GetMask.php Additional files +0/-67

...

htdocs/libraries/WideImage/lib/Operation/GetMask.php


111. htdocs/libraries/WideImage/lib/Operation/Merge.php Additional files +0/-78

...

htdocs/libraries/WideImage/lib/Operation/Merge.php


112. htdocs/libraries/WideImage/lib/Operation/Mirror.php Additional files +0/-55

...

htdocs/libraries/WideImage/lib/Operation/Mirror.php


113. htdocs/libraries/WideImage/lib/Operation/Resize.php Additional files +0/-157

...

htdocs/libraries/WideImage/lib/Operation/Resize.php


114. htdocs/libraries/WideImage/lib/Operation/ResizeCanvas.php Additional files +0/-107

...

htdocs/libraries/WideImage/lib/Operation/ResizeCanvas.php


115. htdocs/libraries/WideImage/lib/Operation/Rotate.php Additional files +0/-64

...

htdocs/libraries/WideImage/lib/Operation/Rotate.php


116. htdocs/libraries/WideImage/lib/Operation/RoundCorners.php Additional files +0/-114

...

htdocs/libraries/WideImage/lib/Operation/RoundCorners.php


117. htdocs/libraries/WideImage/lib/Operation/Unsharp.php Additional files +0/-135

...

htdocs/libraries/WideImage/lib/Operation/Unsharp.php


118. htdocs/libraries/WideImage/lib/Operation/index.html Additional files +0/-1

...

htdocs/libraries/WideImage/lib/Operation/index.html


119. htdocs/libraries/WideImage/lib/OperationFactory.php Additional files +0/-57

...

htdocs/libraries/WideImage/lib/OperationFactory.php


120. htdocs/libraries/WideImage/lib/PaletteImage.php Additional files +0/-136

...

htdocs/libraries/WideImage/lib/PaletteImage.php


121. htdocs/libraries/WideImage/lib/README Additional files +0/-21

...

htdocs/libraries/WideImage/lib/README


122. htdocs/libraries/WideImage/lib/TrueColorImage.php Additional files +0/-218

...

htdocs/libraries/WideImage/lib/TrueColorImage.php


123. Additional files not shown Additional files +0/-0

...

Additional files not shown


Grey Divider

Qodo Logo

@qodo-free-for-open-source-projects
Copy link
Contributor

Code Review by Qodo

🐞 Bugs (4) 📘 Rule violations (8) 📎 Requirement gaps (0)

Grey Divider


Action required

1. $_icms_autoload not verified 📘 Rule violation ⛯ Reliability
Description
require_once $_icms_autoload is executed without verifying that the selected autoload path exists,
which can trigger a fatal error when neither trust-path nor web-root vendor/autoload.php is
present. This violates the requirement to handle dependency-loading failure points gracefully with
actionable context.
Code

htdocs/include/common.php[R49-56]

+$_icms_autoload_from_trustpath = false;
+if (file_exists(ICMS_TRUST_PATH . "/vendor/autoload.php")) {
+	$_icms_autoload = ICMS_TRUST_PATH . "/vendor/autoload.php";
+	$_icms_autoload_from_trustpath = true;
+} else {
+	$_icms_autoload = ICMS_ROOT_PATH . "/vendor/autoload.php";
+}
+require_once $_icms_autoload;
Evidence
PR Compliance ID 3 requires robust handling of failure points; the added code selects a fallback
path but never checks that the fallback exists before require_once, so missing files become an
unhandled fatal error.

Rule 3: Generic: Robust Error Handling and Edge Case Management
htdocs/include/common.php[49-56]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`htdocs/include/common.php` loads Composer autoloading via `require_once $_icms_autoload` without verifying the resolved path exists, which can cause an unhandled fatal error when `vendor/autoload.php` is missing.

## Issue Context
This is core bootstrap code; failures here should be handled with clear, actionable context rather than an opaque fatal include error.

## Fix Focus Areas
- htdocs/include/common.php[49-56]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. common.php uses == 📘 Rule violation ✓ Correctness
Description
Several modified conditionals use loose comparisons (==) instead of strict comparisons (===),
which can cause unexpected behavior due to PHP type juggling. This violates the strict-comparison
requirement for condition checks.
Code

htdocs/include/common.php[R137-205]

+if (
+	empty($_SERVER["SERVER_NAME"]) ||
+	substr(PHP_SAPI, 0, 3) == "cli" ||
+	$GLOBALS["icmsConfigMultilang"]
+) {
+	$icmsConfig["gzip_compression"] = 0;
}

-if ($icmsConfig['gzip_compression'] == 1 && extension_loaded('zlib') && !ini_get('zlib.output_compression')) {
-	ini_set('zlib.output_compression', TRUE);
-	if (ini_get('zlib.output_compression_level') < 0) {
-		ini_set('zlib.output_compression_level', 6);
+if (
+	$icmsConfig["gzip_compression"] == 1 &&
+	extension_loaded("zlib") &&
+	!ini_get("zlib.output_compression")
+) {
+	ini_set("zlib.output_compression", true);
+	if (ini_get("zlib.output_compression_level") < 0) {
+		ini_set("zlib.output_compression_level", 6);
	}
	if (!zlib_get_coding_type()) {
-		ini_set('zlib.output_compression', FALSE);
-		ob_start('ob_gzhandler');
+		ini_set("zlib.output_compression", false);
+		ob_start("ob_gzhandler");
	}
}

/*
 * This address the strict compliance for PHP 5.3/5.4, but the rest of our timezone handling
 * can be improved beyond this. ~skenow
 */
-date_default_timezone_set(timezone_name_from_abbr("", $icmsConfig['default_TZ'] * 3600, 0));
+date_default_timezone_set(
+	timezone_name_from_abbr("", $icmsConfig["default_TZ"] * 3600, 0),
+);

// -- Include site-wide lang file
-icms_loadLanguageFile('core', 'global');
-icms_loadLanguageFile('core', 'core');
-icms_loadLanguageFile('system', 'common');
-@define('_GLOBAL_LEFT', @_ADM_USE_RTL == 1 ? 'right' : 'left');
-@define('_GLOBAL_RIGHT', @_ADM_USE_RTL == 1 ? 'left' : 'right');
+icms_loadLanguageFile("core", "global");
+icms_loadLanguageFile("core", "core");
+icms_loadLanguageFile("system", "common");
+@define("_GLOBAL_LEFT", @_ADM_USE_RTL == 1 ? "right" : "left");
+@define("_GLOBAL_RIGHT", @_ADM_USE_RTL == 1 ? "left" : "right");

// -- Include page-specific lang file
-if (isset($xoopsOption['pagetype']) && FALSE === strpos($xoopsOption['pagetype'], '.')) {
-	icms_loadLanguageFile('core', $xoopsOption['pagetype']);
+if (
+	isset($xoopsOption["pagetype"]) &&
+	false === strpos($xoopsOption["pagetype"], ".")
+) {
+	icms_loadLanguageFile("core", $xoopsOption["pagetype"]);
}

defined("XOOPS_USE_MULTIBYTES") or define("XOOPS_USE_MULTIBYTES", 0);

-if (!empty($_POST['xoops_theme_select']) && in_array($_POST['xoops_theme_select'], $icmsConfig['theme_set_allowed'])) {
-	$icmsConfig['theme_set'] = $_POST['xoops_theme_select'];
-	$_SESSION['xoopsUserTheme'] = $_POST['xoops_theme_select'];
-} elseif (!empty($_POST['theme_select']) && in_array($_POST['theme_select'], $icmsConfig['theme_set_allowed'])) {
-	$icmsConfig['theme_set'] = $_POST['theme_select'];
-	$_SESSION['xoopsUserTheme'] = $_POST['theme_select'];
-} elseif (!empty($_SESSION['xoopsUserTheme']) && in_array($_SESSION['xoopsUserTheme'], $icmsConfig['theme_set_allowed'])) {
-	$icmsConfig['theme_set'] = $_SESSION['xoopsUserTheme'];
+if (
+	!empty($_POST["xoops_theme_select"]) &&
+	in_array($_POST["xoops_theme_select"], $icmsConfig["theme_set_allowed"])
+) {
+	$icmsConfig["theme_set"] = $_POST["xoops_theme_select"];
+	$_SESSION["xoopsUserTheme"] = $_POST["xoops_theme_select"];
+} elseif (
+	!empty($_POST["theme_select"]) &&
+	in_array($_POST["theme_select"], $icmsConfig["theme_set_allowed"])
+) {
+	$icmsConfig["theme_set"] = $_POST["theme_select"];
+	$_SESSION["xoopsUserTheme"] = $_POST["theme_select"];
+} elseif (
+	!empty($_SESSION["xoopsUserTheme"]) &&
+	in_array($_SESSION["xoopsUserTheme"], $icmsConfig["theme_set_allowed"])
+) {
+	$icmsConfig["theme_set"] = $_SESSION["xoopsUserTheme"];
}

-if ($icmsConfig['closesite'] == 1) {
-	include ICMS_INCLUDE_PATH . '/site-closed.php';
+if ($icmsConfig["closesite"] == 1) {
+	include ICMS_INCLUDE_PATH . "/site-closed.php";
Evidence
PR Compliance ID 7 requires strict comparisons; the changed code introduces/retains == checks in
multiple conditionals (CLI detection, gzip flag, RTL direction constants, and closesite flag).

htdocs/include/common.php[137-205]
Best Practice: Learned patterns

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`htdocs/include/common.php` uses loose comparisons (`==`) in modified conditionals, which violates the strict-comparison requirement.

## Issue Context
These conditions affect core boot behavior (gzip, CLI detection, RTL constants, site-closed), so type juggling can cause hard-to-debug misbehavior.

## Fix Focus Areas
- htdocs/include/common.php[137-205]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. multi_login key unguarded 📘 Rule violation ⛯ Reliability
Description
$icmsConfigPersona["multi_login"] and $_SERVER["REMOTE_ADDR"] are accessed without
isset()/fallbacks, which can trigger notices or errors in edge cases (e.g., missing config or
CLI/non-HTTP contexts). This violates the requirement to check array indices before access and
provide fallbacks.
Code

htdocs/include/common.php[R210-219]

+if ($icmsConfigPersona["multi_login"]) {
	if (is_object(icms::$user)) {
-		$online_handler = icms::handler('icms_core_Online');
-		$online_handler->write(icms::$user->getVar('uid'), icms::$user->getVar('uname'), time(), 0, $_SERVER['REMOTE_ADDR']);
+		$online_handler = icms::handler("icms_core_Online");
+		$online_handler->write(
+			icms::$user->getVar("uid"),
+			icms::$user->getVar("uname"),
+			time(),
+			0,
+			$_SERVER["REMOTE_ADDR"],
+		);
Evidence
PR Compliance ID 9 requires guards before accessing array keys; the modified code reads
$icmsConfigPersona["multi_login"] and $_SERVER["REMOTE_ADDR"] directly with no existence checks
or default handling.

htdocs/include/common.php[210-219]
Best Practice: Learned patterns

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The code reads `$icmsConfigPersona[&quot;multi_login&quot;]` and `$_SERVER[&quot;REMOTE_ADDR&quot;]` without checking they exist, which can cause notices or failures.

## Issue Context
This runs during core bootstrap and should be resilient across environments (HTTP vs CLI) and configuration states.

## Fix Focus Areas
- htdocs/include/common.php[210-219]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View more (6)
4. copyRecursive() uses == 📘 Rule violation ✓ Correctness
Description
icms_core_Filesystem::copyRecursive() uses loose equality (==) when comparing directory entries
("."/".."), which violates the strict-comparison requirement and risks type juggling edge cases.
This should be strict (===).
Code

htdocs/libraries/icms/core/Filesystem.php[R166-170]

+		while (false !== ($entry = $dir->read())) {
			// Skip pointers
-			if ($entry == '.' || $entry == '..') {continue;}
+			if ($entry == "." || $entry == "..") {
+				continue;
+			}
Evidence
PR Compliance ID 7 requires strict comparisons; the modified loop compares $entry with
"."/".." using == rather than ===.

htdocs/libraries/icms/core/Filesystem.php[166-170]
Best Practice: Learned patterns

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`copyRecursive()` uses `==` to compare directory entries, violating the strict-comparison requirement.

## Issue Context
Filesystem routines are sensitive to edge cases; strict comparisons avoid PHP type juggling surprises.

## Fix Focus Areas
- htdocs/libraries/icms/core/Filesystem.php[166-170]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. $_POST[mod] unchecked 📘 Rule violation ⛯ Reliability
Description
The installer template reads $_POST["mod"] directly without checking it exists, and uses a loose
comparison (!= 1), which can trigger notices and type-juggling behavior. This violates the
requirement to check array indices before access and to use strict comparisons.
Code

htdocs/install/install_tpl.php[R162-165]

+								onclick="location.href='<?php echo $wizard->pageURI("+1"); ?>'" class="next">
							<?php } ?>
-							<?php if ($_POST['mod'] != 1) { ?>
+							<?php if ($_POST["mod"] != 1) { ?>
								<img src="img/right-arr.png" alt="<?php echo BUTTON_NEXT; ?>" width="16"/>
Evidence
PR Compliance ID 9 requires isset()/fallback before reading array keys like $_POST["mod"], and
PR Compliance ID 7 requires strict comparisons; the modified template uses $_POST["mod"] != 1 with
no guard.

htdocs/install/install_tpl.php[162-165]
Best Practice: Learned patterns
Best Practice: Learned patterns

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The installer template reads `$_POST[&quot;mod&quot;]` without an existence check and compares loosely.

## Issue Context
Installer pages should not emit notices/warnings due to missing POST fields.

## Fix Focus Areas
- htdocs/install/install_tpl.php[162-165]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


6. baseLocation() unguarded $_SERVER 📘 Rule violation ⛯ Reliability
Description
baseLocation() reads $_SERVER["HTTP_HOST"] and $_SERVER["PHP_SELF"] without checking they
exist, which can trigger notices in nonstandard environments or proxied/test contexts. This violates
the requirement to check array indices before access and provide fallbacks.
Code

htdocs/install/class/IcmsInstallWizard.php[R188-194]

+		$proto =
+			isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] === "on"
+				? "https"
+				: "http";
+		$host = htmlentities($_SERVER["HTTP_HOST"]);
+		$server_php_self = htmlentities($_SERVER["PHP_SELF"]);
+		$base = substr($server_php_self, 0, strrpos($server_php_self, "/"));
Evidence
PR Compliance ID 9 requires guarding array index access; the modified code directly accesses
$_SERVER["HTTP_HOST"] and $_SERVER["PHP_SELF"] without isset()/fallback handling.

htdocs/install/class/IcmsInstallWizard.php[188-194]
Best Practice: Learned patterns

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`baseLocation()` accesses `$_SERVER` keys without checking they exist.

## Issue Context
While typically present in web requests, these keys can be missing in edge cases; the installer should not emit notices.

## Fix Focus Areas
- htdocs/install/class/IcmsInstallWizard.php[188-194]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


7. Bad SimplePie namespace 🐞 Bug ✓ Correctness
Description
Admin RSS now calls \Simplepie\Simplepie::LOCATOR_NONE (wrong casing/namespace), which will trigger
a class-not-found fatal when that page renders.
Code

htdocs/admin.php[90]

+	$feed->set_autodiscovery_level(\Simplepie\Simplepie::LOCATOR_NONE);
Evidence
admin.php uses a non-existent namespace casing, while the wrapper feed class imports and extends the
correct Composer SimplePie class (\SimplePie\SimplePie).

htdocs/admin.php[86-92]
htdocs/libraries/icms/feeds/Simplerss.php[19-22]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`htdocs/admin.php` references `\Simplepie\Simplepie::LOCATOR_NONE` which does not match the actual Composer SimplePie class namespace. This will fail at runtime.

### Issue Context
SimplePie is now provided via Composer and used as `\SimplePie\SimplePie`.

### Fix Focus Areas
- htdocs/admin.php[90-90]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


8. getAvailable() API break 🐞 Bug ✓ Correctness
Description
icms_module_Handler::getAvailable() now returns Composer package metadata arrays, but
installer/modulesadmin treat it as a list of module dirnames; this can produce warnings and break
module install/admin flows when such packages are present.
Code

htdocs/libraries/icms/module/Handler.php[R405-419]

+	static public function getAvailable(): array
+	{
+		$package_types = ['impresscms-theme', 'impresscms-module'];
+
+		$dirtyList = $cleanList = array();
+		foreach($package_types as $package_type) {
+			$dirtyList = \Composer\InstalledVersions::getInstalledPackagesByType($package_type);
+			foreach ($dirtyList as $item) {
+
+				$cleanList[$item]['Name'] = $item;
+				$cleanList[$item]['Version'] = InstalledVersions::getVersion($item);
+				$cleanList[$item]['PrettyVersion'] = InstalledVersions::getPrettyVersion($item);
+			}
+		}
+		return $cleanList;
Evidence
The new getAvailable() returns arrays keyed by package name with nested fields, but call sites
iterate expecting string values (used in path building and array_diff). That is a breaking contract
change.

htdocs/libraries/icms/module/Handler.php[405-419]
htdocs/install/page_modulesinstall.php[93-99]
htdocs/modules/system/admin/modulesadmin/modulesadmin.php[97-103]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`icms_module_Handler::getAvailable()` changed its return type/shape, but existing consumers still assume the legacy string list of module directory names.

### Issue Context
Installer and modules admin build filesystem paths and compute diffs using the returned values.

### Fix Focus Areas
- htdocs/libraries/icms/module/Handler.php[388-420]
- htdocs/install/page_modulesinstall.php[93-99]
- htdocs/modules/system/admin/modulesadmin/modulesadmin.php[97-103]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


9. Vendor move can corrupt 🐞 Bug ⛯ Reliability
Description
moveVendorToTrust() can delete the source vendor even if some files fail to copy, because
copyRecursive() ignores copy() failures and returns true after the loop; this can leave an
incomplete vendor tree and break the site.
Code

htdocs/libraries/icms/core/Filesystem.php[R697-734]

+		// ── Copy source → destination ─────────────────────────────────────────
+		@set_time_limit(300);
+
+		if (!self::copyRecursive($src, $dest)) {
+			// Copy failed – clean up any partial destination.
+			if (is_dir($dest)) {
+				self::deleteRecursive($dest, true);
+			}
+			return $base + [
+				"status" => "error_copy",
+				"message" => sprintf(
+					"Failed to copy the vendor directory from the web root (%s) to the " .
+						"trust path (%s). Please check that the trust path is writable and " .
+						"that there is sufficient disk space, then retry. " .
+						"Alternatively, copy the vendor directory manually via FTP/SFTP.",
+					$src,
+					$dest,
+				),
+			];
+		}
+
+		// Verify the copy completed by checking that autoload.php arrived.
+		if (!file_exists($dest . "/autoload.php")) {
+			self::deleteRecursive($dest, true);
+			return $base + [
+				"status" => "error_copy",
+				"message" => sprintf(
+					"The vendor copy to the trust path (%s) appears incomplete " .
+						"(autoload.php is missing). The partial copy has been removed. " .
+						"Please retry or copy the vendor directory manually via FTP/SFTP.",
+					$dest,
+				),
+			];
+		}

+		// ── Delete the original from the web root ─────────────────────────────
+		self::deleteRecursive($src, true);
+
Evidence
copyRecursive() does not check the return value of copy() calls for directory contents and always
returns true, so moveVendorToTrust() may proceed to delete the source after a partial copy (it only
verifies autoload.php presence).

htdocs/libraries/icms/core/Filesystem.php[152-181]
htdocs/libraries/icms/core/Filesystem.php[697-734]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The vendor move uses `copyRecursive()` which does not detect per-file copy failures, yet `moveVendorToTrust()` deletes the source after only checking for `autoload.php`.

### Issue Context
A partial copy (permissions/disk full) could still include `autoload.php`, causing the original vendor to be deleted and leaving the system in a broken state.

### Fix Focus Areas
- htdocs/libraries/icms/core/Filesystem.php[152-181]
- htdocs/libraries/icms/core/Filesystem.php[697-734]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

10. writeFile() echoes generic error 📘 Rule violation ⛯ Reliability
Description
icms_core_Filesystem::writeFile() uses a loose comparison for fwrite(...) == false and emits a
generic echo "failed write file" without actionable context (e.g., filename), making failures
harder to diagnose. This violates robust error handling and strict-comparison requirements.
Code

htdocs/libraries/icms/core/Filesystem.php[R509-519]

+		if ($extension == "") {
+			$extension = "php";
+		}
+		if (DIRECTORY_SEPARATOR !== "/") {
+			$location = str_replace(DIRECTORY_SEPARATOR, "/", $location);
+		}
+		$file = $location . "/" . $filename . "." . $extension;
		if ($fp = fopen($file, "wt")) {
-			if (fwrite($fp, $contents) == FALSE) {
-				echo 'failed write file';
-				return FALSE;
+			if (fwrite($fp, $contents) == false) {
+				echo "failed write file";
+				return false;
Evidence
PR Compliance ID 7 requires strict comparisons (use === false for fwrite failures), and PR
Compliance ID 3 requires meaningful, contextual error handling; the modified code uses == false
and prints a non-actionable error message.

Rule 3: Generic: Robust Error Handling and Edge Case Management
htdocs/libraries/icms/core/Filesystem.php[509-519]
Best Practice: Learned patterns

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`writeFile()` uses loose comparison for `fwrite` failure and outputs a generic error string without context.

## Issue Context
Callers need actionable context (which file/operation failed) and strict comparisons reduce type-juggling surprises.

## Fix Focus Areas
- htdocs/libraries/icms/core/Filesystem.php[509-519]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


11. Installer reveals autoload paths 📘 Rule violation ⛨ Security
Description
When the Composer autoloader is missing, the installer prints the full filesystem paths it checked,
which can disclose sensitive server directory structure to the user. This violates the secure error
handling requirement to avoid exposing internal system details in user-facing output.
Code

htdocs/install/common.inc.php[R125-145]

+// ── Step 4: nothing found – emit a human-readable error ──────────────────────
+if ($_icms_vendor_autoload === null) {
+	$__locations = [__DIR__ . "/../vendor/autoload.php"];
+	if (!empty($_icms_trust_path)) {
+		array_unshift(
+			$__locations,
+			rtrim(str_replace("\\", "/", $_icms_trust_path), "/") .
+				"/vendor/autoload.php",
+		);
+	}
+	header("Content-Type: text/plain; charset=utf-8");
+	echo "ImpressCMS Installer – Autoloader not found\n\n";
+	echo "The Composer autoloader (vendor/autoload.php) could not be found ";
+	echo "in any of the expected locations:\n";
+	foreach ($__locations as $__loc) {
+		echo "  • " . $__loc . "\n";
+	}
+	echo "\nIf you moved the vendor directory manually, make sure it exists ";
+	echo "at one of the paths listed above.\n";
+	unset($__locations);
+	exit(1);
Evidence
PR Compliance ID 4 prohibits exposing internal system details to end users; the added error output
enumerates absolute locations of vendor/autoload.php, disclosing filesystem layout.

Rule 4: Generic: Secure Error Handling
htdocs/install/common.inc.php[125-145]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The installer prints absolute filesystem paths in a user-facing error when the Composer autoloader cannot be found.

## Issue Context
Absolute paths reveal internal server structure and should not be shown to users; detailed diagnostics should go to secure logs.

## Fix Focus Areas
- htdocs/install/common.inc.php[125-145]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


12. Wrong purifier filter path 🐞 Bug ✓ Correctness
Description
HTMLFilter custom filter discovery falls back to ICMS_ROOT_PATH/vendor/... but vendor is moved to
ICMS_TRUST_PATH, so custom filters won’t be found post-install/update.
Code

htdocs/libraries/icms/core/HTMLFilter.php[R99-106]

	private static function getCustomFilterList() {
+		// Check bundled location first for backward compatibility
		$dirPath = ICMS_LIBRARIES_PATH . '/htmlpurifier/standalone/HTMLPurifier/Filter/';
+
+		// Fall back to Composer location if bundled doesn't exist
+		if (!is_dir($dirPath)) {
+			$dirPath = ICMS_ROOT_PATH . '/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Filter/';
+		}
Evidence
common.php explicitly prefers loading Composer’s autoloader from ICMS_TRUST_PATH/vendor after
install/update, but HTMLFilter’s fallback hardcodes ICMS_ROOT_PATH/vendor for htmlpurifier filters,
making it inconsistent with the new vendor location.

htdocs/include/common.php[46-56]
htdocs/libraries/icms/core/HTMLFilter.php[99-106]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
Custom HTMLPurifier filter discovery assumes the Composer vendor directory is under the web root, but the PR moves vendor into the trust path.

### Issue Context
The application prefers loading Composer from `ICMS_TRUST_PATH/vendor` after install/update.

### Fix Focus Areas
- htdocs/libraries/icms/core/HTMLFilter.php[99-106]
- htdocs/include/common.php[46-56]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

Comment on lines +49 to +56
$_icms_autoload_from_trustpath = false;
if (file_exists(ICMS_TRUST_PATH . "/vendor/autoload.php")) {
$_icms_autoload = ICMS_TRUST_PATH . "/vendor/autoload.php";
$_icms_autoload_from_trustpath = true;
} else {
$_icms_autoload = ICMS_ROOT_PATH . "/vendor/autoload.php";
}
require_once $_icms_autoload;

Choose a reason for hiding this comment

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

Action required

1. $_icms_autoload not verified 📘 Rule violation ⛯ Reliability

require_once $_icms_autoload is executed without verifying that the selected autoload path exists,
which can trigger a fatal error when neither trust-path nor web-root vendor/autoload.php is
present. This violates the requirement to handle dependency-loading failure points gracefully with
actionable context.
Agent Prompt
## Issue description
`htdocs/include/common.php` loads Composer autoloading via `require_once $_icms_autoload` without verifying the resolved path exists, which can cause an unhandled fatal error when `vendor/autoload.php` is missing.

## Issue Context
This is core bootstrap code; failures here should be handled with clear, actionable context rather than an opaque fatal include error.

## Fix Focus Areas
- htdocs/include/common.php[49-56]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +137 to +205
if (
empty($_SERVER["SERVER_NAME"]) ||
substr(PHP_SAPI, 0, 3) == "cli" ||
$GLOBALS["icmsConfigMultilang"]
) {
$icmsConfig["gzip_compression"] = 0;
}

if ($icmsConfig['gzip_compression'] == 1 && extension_loaded('zlib') && !ini_get('zlib.output_compression')) {
ini_set('zlib.output_compression', TRUE);
if (ini_get('zlib.output_compression_level') < 0) {
ini_set('zlib.output_compression_level', 6);
if (
$icmsConfig["gzip_compression"] == 1 &&
extension_loaded("zlib") &&
!ini_get("zlib.output_compression")
) {
ini_set("zlib.output_compression", true);
if (ini_get("zlib.output_compression_level") < 0) {
ini_set("zlib.output_compression_level", 6);
}
if (!zlib_get_coding_type()) {
ini_set('zlib.output_compression', FALSE);
ob_start('ob_gzhandler');
ini_set("zlib.output_compression", false);
ob_start("ob_gzhandler");
}
}

/*
* This address the strict compliance for PHP 5.3/5.4, but the rest of our timezone handling
* can be improved beyond this. ~skenow
*/
date_default_timezone_set(timezone_name_from_abbr("", $icmsConfig['default_TZ'] * 3600, 0));
date_default_timezone_set(
timezone_name_from_abbr("", $icmsConfig["default_TZ"] * 3600, 0),
);

// -- Include site-wide lang file
icms_loadLanguageFile('core', 'global');
icms_loadLanguageFile('core', 'core');
icms_loadLanguageFile('system', 'common');
@define('_GLOBAL_LEFT', @_ADM_USE_RTL == 1 ? 'right' : 'left');
@define('_GLOBAL_RIGHT', @_ADM_USE_RTL == 1 ? 'left' : 'right');
icms_loadLanguageFile("core", "global");
icms_loadLanguageFile("core", "core");
icms_loadLanguageFile("system", "common");
@define("_GLOBAL_LEFT", @_ADM_USE_RTL == 1 ? "right" : "left");
@define("_GLOBAL_RIGHT", @_ADM_USE_RTL == 1 ? "left" : "right");

// -- Include page-specific lang file
if (isset($xoopsOption['pagetype']) && FALSE === strpos($xoopsOption['pagetype'], '.')) {
icms_loadLanguageFile('core', $xoopsOption['pagetype']);
if (
isset($xoopsOption["pagetype"]) &&
false === strpos($xoopsOption["pagetype"], ".")
) {
icms_loadLanguageFile("core", $xoopsOption["pagetype"]);
}

defined("XOOPS_USE_MULTIBYTES") or define("XOOPS_USE_MULTIBYTES", 0);

if (!empty($_POST['xoops_theme_select']) && in_array($_POST['xoops_theme_select'], $icmsConfig['theme_set_allowed'])) {
$icmsConfig['theme_set'] = $_POST['xoops_theme_select'];
$_SESSION['xoopsUserTheme'] = $_POST['xoops_theme_select'];
} elseif (!empty($_POST['theme_select']) && in_array($_POST['theme_select'], $icmsConfig['theme_set_allowed'])) {
$icmsConfig['theme_set'] = $_POST['theme_select'];
$_SESSION['xoopsUserTheme'] = $_POST['theme_select'];
} elseif (!empty($_SESSION['xoopsUserTheme']) && in_array($_SESSION['xoopsUserTheme'], $icmsConfig['theme_set_allowed'])) {
$icmsConfig['theme_set'] = $_SESSION['xoopsUserTheme'];
if (
!empty($_POST["xoops_theme_select"]) &&
in_array($_POST["xoops_theme_select"], $icmsConfig["theme_set_allowed"])
) {
$icmsConfig["theme_set"] = $_POST["xoops_theme_select"];
$_SESSION["xoopsUserTheme"] = $_POST["xoops_theme_select"];
} elseif (
!empty($_POST["theme_select"]) &&
in_array($_POST["theme_select"], $icmsConfig["theme_set_allowed"])
) {
$icmsConfig["theme_set"] = $_POST["theme_select"];
$_SESSION["xoopsUserTheme"] = $_POST["theme_select"];
} elseif (
!empty($_SESSION["xoopsUserTheme"]) &&
in_array($_SESSION["xoopsUserTheme"], $icmsConfig["theme_set_allowed"])
) {
$icmsConfig["theme_set"] = $_SESSION["xoopsUserTheme"];
}

if ($icmsConfig['closesite'] == 1) {
include ICMS_INCLUDE_PATH . '/site-closed.php';
if ($icmsConfig["closesite"] == 1) {
include ICMS_INCLUDE_PATH . "/site-closed.php";

Choose a reason for hiding this comment

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

Action required

2. common.php uses == 📘 Rule violation ✓ Correctness

Several modified conditionals use loose comparisons (==) instead of strict comparisons (===),
which can cause unexpected behavior due to PHP type juggling. This violates the strict-comparison
requirement for condition checks.
Agent Prompt
## Issue description
`htdocs/include/common.php` uses loose comparisons (`==`) in modified conditionals, which violates the strict-comparison requirement.

## Issue Context
These conditions affect core boot behavior (gzip, CLI detection, RTL constants, site-closed), so type juggling can cause hard-to-debug misbehavior.

## Fix Focus Areas
- htdocs/include/common.php[137-205]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +210 to +219
if ($icmsConfigPersona["multi_login"]) {
if (is_object(icms::$user)) {
$online_handler = icms::handler('icms_core_Online');
$online_handler->write(icms::$user->getVar('uid'), icms::$user->getVar('uname'), time(), 0, $_SERVER['REMOTE_ADDR']);
$online_handler = icms::handler("icms_core_Online");
$online_handler->write(
icms::$user->getVar("uid"),
icms::$user->getVar("uname"),
time(),
0,
$_SERVER["REMOTE_ADDR"],
);

Choose a reason for hiding this comment

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

Action required

3. multi_login key unguarded 📘 Rule violation ⛯ Reliability

$icmsConfigPersona["multi_login"] and $_SERVER["REMOTE_ADDR"] are accessed without
isset()/fallbacks, which can trigger notices or errors in edge cases (e.g., missing config or
CLI/non-HTTP contexts). This violates the requirement to check array indices before access and
provide fallbacks.
Agent Prompt
## Issue description
The code reads `$icmsConfigPersona["multi_login"]` and `$_SERVER["REMOTE_ADDR"]` without checking they exist, which can cause notices or failures.

## Issue Context
This runs during core bootstrap and should be resilient across environments (HTTP vs CLI) and configuration states.

## Fix Focus Areas
- htdocs/include/common.php[210-219]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +166 to +170
while (false !== ($entry = $dir->read())) {
// Skip pointers
if ($entry == '.' || $entry == '..') {continue;}
if ($entry == "." || $entry == "..") {
continue;
}

Choose a reason for hiding this comment

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

Action required

4. copyrecursive() uses == 📘 Rule violation ✓ Correctness

icms_core_Filesystem::copyRecursive() uses loose equality (==) when comparing directory entries
("."/".."), which violates the strict-comparison requirement and risks type juggling edge cases.
This should be strict (===).
Agent Prompt
## Issue description
`copyRecursive()` uses `==` to compare directory entries, violating the strict-comparison requirement.

## Issue Context
Filesystem routines are sensitive to edge cases; strict comparisons avoid PHP type juggling surprises.

## Fix Focus Areas
- htdocs/libraries/icms/core/Filesystem.php[166-170]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +162 to 165
onclick="location.href='<?php echo $wizard->pageURI("+1"); ?>'" class="next">
<?php } ?>
<?php if ($_POST['mod'] != 1) { ?>
<?php if ($_POST["mod"] != 1) { ?>
<img src="img/right-arr.png" alt="<?php echo BUTTON_NEXT; ?>" width="16"/>

Choose a reason for hiding this comment

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

Action required

5. $_post[mod] unchecked 📘 Rule violation ⛯ Reliability

The installer template reads $_POST["mod"] directly without checking it exists, and uses a loose
comparison (!= 1), which can trigger notices and type-juggling behavior. This violates the
requirement to check array indices before access and to use strict comparisons.
Agent Prompt
## Issue description
The installer template reads `$_POST["mod"]` without an existence check and compares loosely.

## Issue Context
Installer pages should not emit notices/warnings due to missing POST fields.

## Fix Focus Areas
- htdocs/install/install_tpl.php[162-165]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +188 to +194
$proto =
isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] === "on"
? "https"
: "http";
$host = htmlentities($_SERVER["HTTP_HOST"]);
$server_php_self = htmlentities($_SERVER["PHP_SELF"]);
$base = substr($server_php_self, 0, strrpos($server_php_self, "/"));

Choose a reason for hiding this comment

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

Action required

6. baselocation() unguarded $_server 📘 Rule violation ⛯ Reliability

baseLocation() reads $_SERVER["HTTP_HOST"] and $_SERVER["PHP_SELF"] without checking they
exist, which can trigger notices in nonstandard environments or proxied/test contexts. This violates
the requirement to check array indices before access and provide fallbacks.
Agent Prompt
## Issue description
`baseLocation()` accesses `$_SERVER` keys without checking they exist.

## Issue Context
While typically present in web requests, these keys can be missing in edge cases; the installer should not emit notices.

## Fix Focus Areas
- htdocs/install/class/IcmsInstallWizard.php[188-194]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

$feed->set_feed_url($rssurl);
$feed->set_cache_duration(3600);
$feed->set_autodiscovery_level(SIMPLEPIE_LOCATOR_NONE);
$feed->set_autodiscovery_level(\Simplepie\Simplepie::LOCATOR_NONE);

Choose a reason for hiding this comment

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

Action required

7. Bad simplepie namespace 🐞 Bug ✓ Correctness

Admin RSS now calls \Simplepie\Simplepie::LOCATOR_NONE (wrong casing/namespace), which will trigger
a class-not-found fatal when that page renders.
Agent Prompt
### Issue description
`htdocs/admin.php` references `\Simplepie\Simplepie::LOCATOR_NONE` which does not match the actual Composer SimplePie class namespace. This will fail at runtime.

### Issue Context
SimplePie is now provided via Composer and used as `\SimplePie\SimplePie`.

### Fix Focus Areas
- htdocs/admin.php[90-90]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +405 to +419
static public function getAvailable(): array
{
$package_types = ['impresscms-theme', 'impresscms-module'];

$dirtyList = $cleanList = array();
foreach($package_types as $package_type) {
$dirtyList = \Composer\InstalledVersions::getInstalledPackagesByType($package_type);
foreach ($dirtyList as $item) {

$cleanList[$item]['Name'] = $item;
$cleanList[$item]['Version'] = InstalledVersions::getVersion($item);
$cleanList[$item]['PrettyVersion'] = InstalledVersions::getPrettyVersion($item);
}
}
return $cleanList;

Choose a reason for hiding this comment

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

Action required

8. Getavailable() api break 🐞 Bug ✓ Correctness

icms_module_Handler::getAvailable() now returns Composer package metadata arrays, but
installer/modulesadmin treat it as a list of module dirnames; this can produce warnings and break
module install/admin flows when such packages are present.
Agent Prompt
### Issue description
`icms_module_Handler::getAvailable()` changed its return type/shape, but existing consumers still assume the legacy string list of module directory names.

### Issue Context
Installer and modules admin build filesystem paths and compute diffs using the returned values.

### Fix Focus Areas
- htdocs/libraries/icms/module/Handler.php[388-420]
- htdocs/install/page_modulesinstall.php[93-99]
- htdocs/modules/system/admin/modulesadmin/modulesadmin.php[97-103]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +697 to +734
// ── Copy source → destination ─────────────────────────────────────────
@set_time_limit(300);

if (!self::copyRecursive($src, $dest)) {
// Copy failed – clean up any partial destination.
if (is_dir($dest)) {
self::deleteRecursive($dest, true);
}
return $base + [
"status" => "error_copy",
"message" => sprintf(
"Failed to copy the vendor directory from the web root (%s) to the " .
"trust path (%s). Please check that the trust path is writable and " .
"that there is sufficient disk space, then retry. " .
"Alternatively, copy the vendor directory manually via FTP/SFTP.",
$src,
$dest,
),
];
}

// Verify the copy completed by checking that autoload.php arrived.
if (!file_exists($dest . "/autoload.php")) {
self::deleteRecursive($dest, true);
return $base + [
"status" => "error_copy",
"message" => sprintf(
"The vendor copy to the trust path (%s) appears incomplete " .
"(autoload.php is missing). The partial copy has been removed. " .
"Please retry or copy the vendor directory manually via FTP/SFTP.",
$dest,
),
];
}

// ── Delete the original from the web root ─────────────────────────────
self::deleteRecursive($src, true);

Choose a reason for hiding this comment

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

Action required

9. Vendor move can corrupt 🐞 Bug ⛯ Reliability

moveVendorToTrust() can delete the source vendor even if some files fail to copy, because
copyRecursive() ignores copy() failures and returns true after the loop; this can leave an
incomplete vendor tree and break the site.
Agent Prompt
### Issue description
The vendor move uses `copyRecursive()` which does not detect per-file copy failures, yet `moveVendorToTrust()` deletes the source after only checking for `autoload.php`.

### Issue Context
A partial copy (permissions/disk full) could still include `autoload.php`, causing the original vendor to be deleted and leaving the system in a broken state.

### Fix Focus Areas
- htdocs/libraries/icms/core/Filesystem.php[152-181]
- htdocs/libraries/icms/core/Filesystem.php[697-734]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant