]> git.mxchange.org Git - friendica.git/commitdiff
Let AddonHelper::getAddonInfo() throw exception on invalid addons
authorArt4 <art4@wlabs.de>
Wed, 4 Jun 2025 09:26:38 +0000 (09:26 +0000)
committerArt4 <art4@wlabs.de>
Wed, 4 Jun 2025 09:26:38 +0000 (09:26 +0000)
src/Core/Addon/AddonHelper.php
src/Core/Addon/AddonInfo.php
src/Core/Addon/AddonManagerHelper.php
src/Core/Addon/Exception/InvalidAddonException.php [new file with mode: 0644]
src/Module/Admin/Addons/Details.php
src/Module/Admin/Addons/Index.php
tests/Unit/Core/Addon/AddonInfoTest.php
tests/Unit/Core/Addon/AddonManagerHelperTest.php

index 03a21232e5c1a95e02c021d4b3fa2b31c0535abd..500bf66f1dd9ca434785dedb5d77ddee4202497a 100644 (file)
@@ -61,6 +61,8 @@ interface AddonHelper
 
        /**
         * Get the comment block of an addon as value object.
+        *
+        * @throws \Friendica\Core\Addon\Exception\InvalidAddonException if there is an error with the addon file
         */
        public function getAddonInfo(string $addonId): AddonInfo;
 
index 98e7fb3ed372dfb3a772969d1aa120300f0ab7a8..d0b46f11c698e7f2955d23ee841376c601cc8bc7 100644 (file)
@@ -41,13 +41,7 @@ final class AddonInfo
                        'id' => $addonId,
                ];
 
-               $result = preg_match("|/\*.*\*/|msU", $raw, $m);
-
-               if ($result === false || $result === 0 || !is_array($m) || count($m) < 1) {
-                       return self::fromArray($data);
-               }
-
-               $ll = explode("\n", $m[0]);
+               $ll = explode("\n", $raw);
 
                foreach ($ll as $l) {
                        $l = trim($l, "\t\n\r */");
index 4b7ed1c4a024be5a2702e870eb8ab31b95b0a5a0..f19b8604ffb5e32037f17a13e76931b1a3cd02c8 100644 (file)
@@ -9,6 +9,7 @@ declare(strict_types=1);
 
 namespace Friendica\Core\Addon;
 
+use Friendica\Core\Addon\Exception\InvalidAddonException;
 use Friendica\Core\Cache\Capability\ICanCache;
 use Friendica\Core\Config\Capability\IManageConfigValues;
 use Friendica\Database\Database;
@@ -98,7 +99,14 @@ final class AddonManagerHelper implements AddonHelper
                $addons = [];
 
                foreach ($files as $addonId) {
-                       $addonInfo = $this->getAddonInfo($addonId);
+                       try {
+                               $addonInfo = $this->getAddonInfo($addonId);
+                       } catch (InvalidAddonException $th) {
+                               $this->logger->error('Invalid addon found: ' . $addonId, ['exception' => $th]);
+
+                               // skip invalid addons
+                               continue;
+                       }
 
                        if (
                                $this->config->get('system', 'show_unsupported_addons')
@@ -227,6 +235,8 @@ final class AddonManagerHelper implements AddonHelper
 
        /**
         * Get the comment block of an addon as value object.
+        *
+        * @throws \Friendica\Core\Addon\Exception\InvalidAddonException if there is an error with the addon file
         */
        public function getAddonInfo(string $addonId): AddonInfo
        {
@@ -235,17 +245,31 @@ final class AddonManagerHelper implements AddonHelper
                        'name' => $addonId,
                ];
 
-               if (!is_file($this->getAddonPath() . "/$addonId/$addonId.php")) {
+               $addonFile = $this->getAddonPath() . "/$addonId/$addonId.php";
+
+               if (!is_file($addonFile)) {
                        return AddonInfo::fromArray($default);
                }
 
                $this->profiler->startRecording('file');
 
-               $raw = file_get_contents($this->getAddonPath() . "/$addonId/$addonId.php");
+               $raw = file_get_contents($addonFile);
 
                $this->profiler->stopRecording();
 
-               return AddonInfo::fromString($addonId, $raw);
+               if ($raw === false) {
+                       throw new InvalidAddonException('Could not read addon file: ' . $addonFile);
+               }
+
+               $result = preg_match("|/\*.*\*/|msU", $raw, $matches);
+
+               var_dump($addonFile, $result, $matches);
+
+               if ($result === false || $result === 0 || !is_array($matches) || count($matches) < 1) {
+                       throw new InvalidAddonException('Could not find valid comment block in addon file: ' . $addonFile);
+               }
+
+               return AddonInfo::fromString($addonId, $matches[0]);
        }
 
        /**
diff --git a/src/Core/Addon/Exception/InvalidAddonException.php b/src/Core/Addon/Exception/InvalidAddonException.php
new file mode 100644 (file)
index 0000000..28079bb
--- /dev/null
@@ -0,0 +1,17 @@
+<?php
+
+// Copyright (C) 2010-2024, the Friendica project
+// SPDX-FileCopyrightText: 2010-2024 the Friendica project
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+declare(strict_types=1);
+
+namespace Friendica\Core\Addon\Exception;
+
+/**
+ * Exception in case an addon is invalid
+ */
+final class InvalidAddonException extends \RuntimeException
+{
+}
index 9080eb861f029111739ff4e50d4369d644ee10ca..6066cfba61cb3236c66ffbe6184056fb93ad0441 100644 (file)
@@ -8,6 +8,8 @@
 namespace Friendica\Module\Admin\Addons;
 
 use Friendica\Content\Text\Markdown;
+use Friendica\Core\Addon\AddonInfo;
+use Friendica\Core\Addon\Exception\InvalidAddonException;
 use Friendica\Core\Renderer;
 use Friendica\DI;
 use Friendica\Model\Contact;
@@ -45,6 +47,7 @@ class Details extends BaseAdmin
                $addonHelper = DI::addonHelper();
 
                $addon = Strings::sanitizeFilePathItem($this->parameters['addon']);
+
                if (!is_file("addon/$addon/$addon.php")) {
                        DI::sysmsg()->addNotice(DI::l10n()->t('Addon not found.'));
                        $addonHelper->uninstallAddon($addon);
@@ -91,7 +94,14 @@ class Details extends BaseAdmin
                        $func($admin_form);
                }
 
-               $addonInfo = $addonHelper->getAddonInfo($addon);
+               try {
+                       $addonInfo = $addonHelper->getAddonInfo($addon);
+               } catch (InvalidAddonException $th) {
+                       $this->logger->error('Invalid addon found: ' . $addon, ['exception' => $th]);
+                       DI::sysmsg()->addNotice(DI::l10n()->t('Invalid Addon found.'));
+
+                       $addonInfo = AddonInfo::fromArray(['id' => $addon, 'name' => $addon]);
+               }
 
                $addonAuthors = [];
 
index 6038373018f20533d5fe81430f46c9a404c969e6..6cbd472c8c205e94fe334b79ad8aec37747fcb36 100644 (file)
@@ -7,6 +7,7 @@
 
 namespace Friendica\Module\Admin\Addons;
 
+use Friendica\Core\Addon\Exception\InvalidAddonException;
 use Friendica\Core\Renderer;
 use Friendica\DI;
 use Friendica\Module\BaseAdmin;
@@ -57,7 +58,12 @@ class Index extends BaseAdmin
                $addons = [];
 
                foreach ($addonHelper->getAvailableAddons() as $addonId) {
-                       $addonInfo = $addonHelper->getAddonInfo($addonId);
+                       try {
+                               $addonInfo = $addonHelper->getAddonInfo($addonId);
+                       } catch (InvalidAddonException $th) {
+                               $this->logger->error('Invalid addon found: ' . $addonId, ['exception' => $th]);
+                               continue;
+                       }
 
                        $info = [
                                'name'        => $addonInfo->getName(),
index 20eb654f3a5c52d459aa13b93a4869c19d665ea1..7a342bc059e4eaa23b30dc4448462caeac30516d 100644 (file)
@@ -30,8 +30,7 @@ class AddonInfoTest extends TestCase
                        'without-author' => [
                                'test',
                                <<<TEXT
-                               <?php
-                               /*
+                               /**
                                 * Name: Test Addon
                                 * Description: adds awesome features to friendica
                                 * Version: 100.4.50-beta.5
@@ -55,7 +54,6 @@ class AddonInfoTest extends TestCase
                        'without-maintainer' => [
                                'test',
                                <<<TEXT
-                               <?php
                                /*
                                 * Name: Test Addon
                                 * Description: adds awesome features to friendica
@@ -79,7 +77,6 @@ class AddonInfoTest extends TestCase
                        'complete' => [
                                'test',
                                <<<TEXT
-                               <?php
                                /*
                                 * Name: Test Addon
                                 * Description: adds awesome features to friendica
index e46199ceee5e3e60910c9b8d7906ebbf1a3fb4fa..882082ceb00982e6753924454a6ead7fb980193e 100644 (file)
@@ -12,6 +12,7 @@ namespace Friendica\Test\Unit\Core\Addon;
 use Exception;
 use Friendica\Core\Addon\AddonInfo;
 use Friendica\Core\Addon\AddonManagerHelper;
+use Friendica\Core\Addon\Exception\InvalidAddonException;
 use Friendica\Core\Cache\Capability\ICanCache;
 use Friendica\Core\Config\Capability\IManageConfigValues;
 use Friendica\Database\Database;
@@ -54,6 +55,32 @@ class AddonManagerHelperTest extends TestCase
                $this->assertEquals('Hello Addon', $info->getName());
        }
 
+       public function testGetAddonInfoThrowsInvalidAddonException(): void
+       {
+               $root = vfsStream::setup(__FUNCTION__ . '_addons', 0777, [
+                       'helloaddon' => [
+                               'helloaddon.php' => <<<PHP
+                                       <?php
+                                       // This is not a valid addon comment section
+                                       PHP,
+                       ]
+               ]);
+
+               $addonManagerHelper = new AddonManagerHelper(
+                       $root->url(),
+                       $this->createStub(Database::class),
+                       $this->createStub(IManageConfigValues::class),
+                       $this->createStub(ICanCache::class),
+                       $this->createStub(LoggerInterface::class),
+                       $this->createStub(Profiler::class)
+               );
+
+               $this->expectException(InvalidAddonException::class);
+               $this->expectExceptionMessage('Could not find valid comment block in addon file:');
+
+               $addonManagerHelper->getAddonInfo('helloaddon');
+       }
+
        public function testEnabledAddons(): void
        {
                $config = $this->createStub(IManageConfigValues::class);
@@ -140,7 +167,18 @@ class AddonManagerHelperTest extends TestCase
        {
                $root = vfsStream::setup(__FUNCTION__ . '_addons', 0777, [
                        'helloaddon' => [
-                               'helloaddon.php' => '<?php',
+                               'helloaddon.php' => <<<PHP
+                                       <?php
+                                       /**
+                                        * Name: Hello Addon
+                                        * Description: For testing purpose only
+                                        * Version: 1.0
+                                        * Author: Artur Weigandt <dont-mail-me@example.com>
+                                        */
+                                       PHP,
+                       ],
+                       'invalidaddon' => [
+                               'invalidaddon.php' => 'This addon should not be loaded, because it does not contain a valid comment section.',
                        ],
                        '.hidden' => [
                                '.hidden.php' => 'This folder should be ignored',