diff --git a/CHANGELOG.md b/CHANGELOG.md index aafcb2d746b6..76e89d04e4ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +## [v4.6.3](https://github.com/codeigniter4/CodeIgniter4/tree/v4.6.3) (2025-08-02) +[Full Changelog](https://github.com/codeigniter4/CodeIgniter4/compare/v4.6.2...v4.6.3) + +### Fixed Bugs + +* fix: CID check in Email class by @michalsn in https://github.com/codeigniter4/CodeIgniter4/pull/9645 +* fix: SMTP connection resource validation in `Email` class destructor by @michalsn in https://github.com/codeigniter4/CodeIgniter4/pull/9648 + +### Refactoring + +* refactor: update preload script to exclude `util_bootstrap` by @ddevsr in https://github.com/codeigniter4/CodeIgniter4/pull/9649 +* refactor: phpdoc for `Config\Filters::$globals` by @michalsn in https://github.com/codeigniter4/CodeIgniter4/pull/9652 + ## [v4.6.2](https://github.com/codeigniter4/CodeIgniter4/tree/v4.6.2) (2025-07-26) [Full Changelog](https://github.com/codeigniter4/CodeIgniter4/compare/v4.6.1...v4.6.2) diff --git a/app/Config/Filters.php b/app/Config/Filters.php index eb46a1d7cee8..9c83ae94e55c 100644 --- a/app/Config/Filters.php +++ b/app/Config/Filters.php @@ -65,7 +65,10 @@ class Filters extends BaseFilters * List of filter aliases that are always * applied before and after every request. * - * @var array>>|array> + * @var array{ + * before: array|string}>|list, + * after: array|string}>|list + * } */ public array $globals = [ 'before' => [ diff --git a/phpdoc.dist.xml b/phpdoc.dist.xml index b2df39d10bca..0238aec5f019 100644 --- a/phpdoc.dist.xml +++ b/phpdoc.dist.xml @@ -10,7 +10,7 @@ api/build/ api/cache/ - + system diff --git a/preload.php b/preload.php index 86322d5e7137..9d16bb31554f 100644 --- a/preload.php +++ b/preload.php @@ -57,6 +57,7 @@ class preload '/system/Config/Routes.php', '/system/Language/', '/system/bootstrap.php', + '/system/util_bootstrap.php', '/system/rewrite.php', '/Views/', // Errors occur. diff --git a/system/CodeIgniter.php b/system/CodeIgniter.php index 3c81f64c04cd..c87ff78e8348 100644 --- a/system/CodeIgniter.php +++ b/system/CodeIgniter.php @@ -55,7 +55,7 @@ class CodeIgniter /** * The current version of CodeIgniter Framework */ - public const CI_VERSION = '4.6.2'; + public const CI_VERSION = '4.6.3'; /** * App startup time. diff --git a/system/Config/Filters.php b/system/Config/Filters.php index 7eddc721bff6..80662ede4bb3 100644 --- a/system/Config/Filters.php +++ b/system/Config/Filters.php @@ -78,7 +78,10 @@ class Filters extends BaseConfig * List of filter aliases that are always * applied before and after every request. * - * @var array>>|array> + * @var array{ + * before: array|string}>|list, + * after: array|string}>|list + * } */ public array $globals = [ 'before' => [ diff --git a/system/Debug/Toolbar/Collectors/Routes.php b/system/Debug/Toolbar/Collectors/Routes.php index 47c808e7ac40..f8005065c57e 100644 --- a/system/Debug/Toolbar/Collectors/Routes.php +++ b/system/Debug/Toolbar/Collectors/Routes.php @@ -51,7 +51,7 @@ class Routes extends BaseCollector * Returns the data of this collector to be formatted in the toolbar * * @return array{ - * matchedRoute: arraynewline . 'Content-Disposition: ' . $attachment['disposition'] . ';' . $this->newline . 'Content-Transfer-Encoding: base64' . $this->newline - . ($attachment['cid'] === '' ? '' : 'Content-ID: <' . $attachment['cid'] . '>' . $this->newline) + . (isset($attachment['cid']) && $attachment['cid'] !== '' ? 'Content-ID: <' . $attachment['cid'] . '>' . $this->newline : '') . $this->newline . $attachment['content'] . $this->newline; } @@ -1886,7 +1886,7 @@ protected function SMTPEnd() */ protected function SMTPConnect() { - if (is_resource($this->SMTPConnect)) { + if ($this->isSMTPConnected()) { return true; } @@ -1910,7 +1910,7 @@ protected function SMTPConnect() $this->SMTPTimeout, ); - if (! is_resource($this->SMTPConnect)) { + if (! $this->isSMTPConnected()) { $this->setErrorMessage(lang('Email.SMTPError', [$errno . ' ' . $errstr])); return false; @@ -2227,7 +2227,7 @@ protected function mimeTypes($ext = '') public function __destruct() { - if ($this->SMTPConnect !== null) { + if ($this->isSMTPConnected()) { try { $this->sendCommand('quit'); } catch (ErrorException $e) { @@ -2284,4 +2284,16 @@ protected function setArchiveValues(): array return $this->archive; } + + /** + * Checks if there is an active SMTP connection. + * + * @return bool True if SMTP connection is established and open, false otherwise + */ + protected function isSMTPConnected(): bool + { + return $this->SMTPConnect !== null + && $this->SMTPConnect !== false + && get_debug_type($this->SMTPConnect) !== 'resource (closed)'; + } } diff --git a/system/Router/RouteCollection.php b/system/Router/RouteCollection.php index 66c3ace6fe1a..7379d014cc09 100644 --- a/system/Router/RouteCollection.php +++ b/system/Router/RouteCollection.php @@ -1724,7 +1724,7 @@ public function resetRoutes() * @return array< * string, * array{ - * filter?: string|list, namespace?: string, hostname?: string, + * filter?: list|string, namespace?: string, hostname?: string, * subdomain?: string, offset?: int, priority?: int, as?: string, * redirect?: int * } diff --git a/system/Test/Mock/MockConnection.php b/system/Test/Mock/MockConnection.php index 2801a0674ad5..d14160595333 100644 --- a/system/Test/Mock/MockConnection.php +++ b/system/Test/Mock/MockConnection.php @@ -27,8 +27,8 @@ class MockConnection extends BaseConnection { /** * @var array{ - * connect?: object|resource|false|list, - * execute?: object|resource|false, + * connect?: false|list|object|resource, + * execute?: false|object|resource, * } */ protected $returnValues = []; diff --git a/tests/system/Email/EmailTest.php b/tests/system/Email/EmailTest.php index 8d865b58ddeb..ca42613505e4 100644 --- a/tests/system/Email/EmailTest.php +++ b/tests/system/Email/EmailTest.php @@ -21,6 +21,7 @@ use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Group; use ReflectionException; +use ReflectionMethod; /** * @internal @@ -220,6 +221,41 @@ public function testSetAttachmentCIDBufferString(): void ); } + /** + * @see https://github.com/codeigniter4/CodeIgniter4/issues/9644 + * + * @throws ReflectionException + */ + public function testAppendAttachmentsWithoutCID(): void + { + $email = $this->createMockEmail(); + + // Manually inject an attachment without 'cid' + $this->setPrivateProperty($email, 'attachments', [ + [ + 'multipart' => 'mixed', + 'content' => 'VGhpcyBpcyBhIHRlc3QgZmlsZSBjb250ZW50Lg==', // base64 for "This is a test file content." + 'filename' => '', + 'type' => 'application/pdf', + 'name' => ['testfile.pdf'], + 'disposition' => 'attachment', + ], + ]); + + $body = ''; + $boundary = 'test-boundary'; + + // Use ReflectionMethod to call protected method with pass-by-reference + $refMethod = new ReflectionMethod($email, 'appendAttachments'); + $refMethod->invokeArgs($email, [&$body, $boundary, 'mixed']); + + // Assertion: Should not include a Content-ID header + $this->assertStringContainsString('Content-Type: application/pdf; name="testfile.pdf"', $body); + $this->assertStringContainsString('Content-Disposition: attachment;', $body); + $this->assertStringNotContainsString('Content-ID:', $body); + $this->assertStringContainsString('--' . $boundary . '--', $body); + } + /** * @throws ReflectionException */ diff --git a/user_guide_src/source/changelogs/index.rst b/user_guide_src/source/changelogs/index.rst index bd881c8b59fe..248594e298c0 100644 --- a/user_guide_src/source/changelogs/index.rst +++ b/user_guide_src/source/changelogs/index.rst @@ -12,6 +12,7 @@ See all the changes. .. toctree:: :titlesonly: + v4.6.3 v4.6.2 v4.6.1 v4.6.0 diff --git a/user_guide_src/source/changelogs/v4.6.3.rst b/user_guide_src/source/changelogs/v4.6.3.rst new file mode 100644 index 000000000000..90d0f8f42b37 --- /dev/null +++ b/user_guide_src/source/changelogs/v4.6.3.rst @@ -0,0 +1,22 @@ +############# +Version 4.6.3 +############# + +Release Date: August 2, 2025 + +**4.6.3 release of CodeIgniter4** + +.. contents:: + :local: + :depth: 3 + +********** +Bugs Fixed +********** + +- **Email:** Fixed a bug with CID check when building email attachments. +- **Email:** Fixed a bug with SMTP connection resource validation in the class destructor. + +See the repo's +`CHANGELOG.md `_ +for a complete list of bugs fixed. diff --git a/user_guide_src/source/conf.py b/user_guide_src/source/conf.py index 77166f7e014d..cf180802770c 100644 --- a/user_guide_src/source/conf.py +++ b/user_guide_src/source/conf.py @@ -26,7 +26,7 @@ version = '4.6' # The full version, including alpha/beta/rc tags. -release = '4.6.2' +release = '4.6.3' # -- General configuration --------------------------------------------------- diff --git a/user_guide_src/source/installation/upgrade_463.rst b/user_guide_src/source/installation/upgrade_463.rst new file mode 100644 index 000000000000..cbadc5ee89b3 --- /dev/null +++ b/user_guide_src/source/installation/upgrade_463.rst @@ -0,0 +1,44 @@ +############################# +Upgrading from 4.6.2 to 4.6.3 +############################# + +Please refer to the upgrade instructions corresponding to your installation method. + +- :ref:`Composer Installation App Starter Upgrading ` +- :ref:`Composer Installation Adding CodeIgniter4 to an Existing Project Upgrading ` +- :ref:`Manual Installation Upgrading ` + +.. contents:: + :local: + :depth: 2 + +************* +Project Files +************* + +Some files in the **project space** (root, app, public, writable) received updates. Due to +these files being outside of the **system** scope they will not be changed without your intervention. + +.. note:: There are some third-party CodeIgniter modules available to assist + with merging changes to the project space: + `Explore on Packagist `_. + +Content Changes +=============== + +The following files received significant changes (including deprecations or visual adjustments) +and it is recommended that you merge the updated versions with your application: + +Config +------ + +- app/Config/Filters.php + +All Changes +=========== + +This is a list of all files in the **project space** that received changes; +many will be simple comments or formatting that have no effect on the runtime: + +- app/Config/Filters.php +- preload.php diff --git a/user_guide_src/source/installation/upgrading.rst b/user_guide_src/source/installation/upgrading.rst index 0b9f2dd806d0..c03b6d0b8c7f 100644 --- a/user_guide_src/source/installation/upgrading.rst +++ b/user_guide_src/source/installation/upgrading.rst @@ -16,6 +16,7 @@ See also :doc:`./backward_compatibility_notes`. backward_compatibility_notes + upgrade_463 upgrade_462 upgrade_461 upgrade_460