diff --git a/src/Core/Addon/AddonHelper.php b/src/Core/Addon/AddonHelper.php index 03a21232e5..500bf66f1d 100644 --- a/src/Core/Addon/AddonHelper.php +++ b/src/Core/Addon/AddonHelper.php @@ -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; diff --git a/src/Core/Addon/AddonInfo.php b/src/Core/Addon/AddonInfo.php index 98e7fb3ed3..d0b46f11c6 100644 --- a/src/Core/Addon/AddonInfo.php +++ b/src/Core/Addon/AddonInfo.php @@ -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 */"); diff --git a/src/Core/Addon/AddonManagerHelper.php b/src/Core/Addon/AddonManagerHelper.php index 4b7ed1c4a0..f19b8604ff 100644 --- a/src/Core/Addon/AddonManagerHelper.php +++ b/src/Core/Addon/AddonManagerHelper.php @@ -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 index 0000000000..28079bb1e1 --- /dev/null +++ b/src/Core/Addon/Exception/InvalidAddonException.php @@ -0,0 +1,17 @@ +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 = []; diff --git a/src/Module/Admin/Addons/Index.php b/src/Module/Admin/Addons/Index.php index 6038373018..6cbd472c8c 100644 --- a/src/Module/Admin/Addons/Index.php +++ b/src/Module/Admin/Addons/Index.php @@ -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(), diff --git a/tests/Unit/Core/Addon/AddonInfoTest.php b/tests/Unit/Core/Addon/AddonInfoTest.php index 20eb654f3a..7a342bc059 100644 --- a/tests/Unit/Core/Addon/AddonInfoTest.php +++ b/tests/Unit/Core/Addon/AddonInfoTest.php @@ -30,8 +30,7 @@ class AddonInfoTest extends TestCase 'without-author' => [ 'test', << [ 'test', << [ 'test', <<assertEquals('Hello Addon', $info->getName()); } + public function testGetAddonInfoThrowsInvalidAddonException(): void + { + $root = vfsStream::setup(__FUNCTION__ . '_addons', 0777, [ + 'helloaddon' => [ + 'helloaddon.php' => <<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, + ], + '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',