aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorReno Reckling <e-github@wthack.de>2024-03-06 14:24:00 +0100
committerDaniel Kesselberg <mail@danielkesselberg.de>2024-09-20 17:00:06 +0200
commitef7e857881b72b607f36a41c9f178c12db068b7a (patch)
treef697f622ce17ecaee56e69c70072c8f23f720566
parentbc5222726b7f6f04308231ff55b8e89ade582d37 (diff)
downloadnextcloud-server-ef7e857881b72b607f36a41c9f178c12db068b7a.tar.gz
nextcloud-server-ef7e857881b72b607f36a41c9f178c12db068b7a.zip
feat: make search path for BinaryFinder customizable.
This feature is important for nextcloud running on distributions like NixOS, where all the standard search paths do not exist. Also added tests. This fixes issue #43922 Co-authored-by: Daniel <mail@danielkesselberg.de> Signed-off-by: Reno Reckling <e-github@wthack.de>
-rw-r--r--config/config.sample.php16
-rw-r--r--lib/private/BinaryFinder.php28
-rw-r--r--tests/lib/BinaryFinderTest.php84
3 files changed, 118 insertions, 10 deletions
diff --git a/config/config.sample.php b/config/config.sample.php
index c1961f7d250..21a77a8cbf6 100644
--- a/config/config.sample.php
+++ b/config/config.sample.php
@@ -2533,4 +2533,20 @@ $CONFIG = [
* Defaults to ``true``
*/
'enable_non-accessible_features' => true,
+
+/**
+ * Directories where nextcloud looks for binaries.
+ * This is used to find external binaries like libreoffice, sendmail, ffmpeg and more.
+ *
+ * Defaults to ``['/usr/local/sbin','/usr/local/bin','/usr/sbin','/usr/bin','/sbin','/bin','/opt/bin']``
+ */
+'binary_search_paths' => [
+ '/usr/local/sbin',
+ '/usr/local/bin',
+ '/usr/sbin',
+ '/usr/bin',
+ '/sbin',
+ '/bin',
+ '/opt/bin',
+],
];
diff --git a/lib/private/BinaryFinder.php b/lib/private/BinaryFinder.php
index f7ac7a5195c..3dad245ff0d 100644
--- a/lib/private/BinaryFinder.php
+++ b/lib/private/BinaryFinder.php
@@ -11,15 +11,28 @@ namespace OC;
use OCP\IBinaryFinder;
use OCP\ICache;
use OCP\ICacheFactory;
+use OCP\IConfig;
use Symfony\Component\Process\ExecutableFinder;
/**
* Service that find the binary path for a program
*/
class BinaryFinder implements IBinaryFinder {
+ public const DEFAULT_BINARY_SEARCH_PATHS = [
+ '/usr/local/sbin',
+ '/usr/local/bin',
+ '/usr/sbin',
+ '/usr/bin',
+ '/sbin',
+ '/bin',
+ '/opt/bin',
+ ];
private ICache $cache;
- public function __construct(ICacheFactory $cacheFactory) {
+ public function __construct(
+ ICacheFactory $cacheFactory,
+ private IConfig $config,
+ ) {
$this->cache = $cacheFactory->createLocal('findBinaryPath');
}
@@ -37,15 +50,10 @@ class BinaryFinder implements IBinaryFinder {
if (\OCP\Util::isFunctionEnabled('exec')) {
$exeSniffer = new ExecutableFinder();
// Returns null if nothing is found
- $result = $exeSniffer->find($program, null, [
- '/usr/local/sbin',
- '/usr/local/bin',
- '/usr/sbin',
- '/usr/bin',
- '/sbin',
- '/bin',
- '/opt/bin',
- ]);
+ $result = $exeSniffer->find(
+ $program,
+ null,
+ $this->config->getSystemValue('binary_search_paths', self::DEFAULT_BINARY_SEARCH_PATHS));
if ($result === null) {
$result = false;
}
diff --git a/tests/lib/BinaryFinderTest.php b/tests/lib/BinaryFinderTest.php
new file mode 100644
index 00000000000..42306e49eac
--- /dev/null
+++ b/tests/lib/BinaryFinderTest.php
@@ -0,0 +1,84 @@
+<?php
+
+declare(strict_types = 1);
+/**
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace Test;
+
+use OC\BinaryFinder;
+use OC\Memcache\ArrayCache;
+use OCP\ICache;
+use OCP\ICacheFactory;
+use OCP\IConfig;
+
+class BinaryFinderTest extends TestCase {
+ private ICache $cache;
+ private ICacheFactory $cacheFactory;
+ private $oldEnv;
+
+ protected function setUp(): void {
+ $this->oldEnv = getenv('PATH');
+ // BinaryFinder always includes the "PATH" environment variable into the search path,
+ // which we want to avoid in this test because they are not usually found in webserver
+ // deployments.
+ putenv('PATH=""');
+ $this->cacheFactory = $this->createMock(ICacheFactory::class);
+ $this->cache = new ArrayCache();
+ $this->cacheFactory->method('createLocal')->with('findBinaryPath')->willReturn($this->cache);
+ }
+
+ protected function tearDown(): void {
+ putenv('PATH=' . $this->oldEnv);
+ }
+
+ public function testDefaultFindsCat() {
+ $config = $this->createMock(IConfig::class);
+ $config
+ ->method('getSystemValue')
+ ->with('binary_search_paths', $this->anything())
+ ->will($this->returnCallback(function ($key, $default) {
+ return $default;
+ }));
+ $finder = new BinaryFinder($this->cacheFactory, $config);
+ $this->assertEquals($finder->findBinaryPath('cat'), '/usr/bin/cat');
+ $this->assertEquals($this->cache->get('cat'), '/usr/bin/cat');
+ }
+
+ public function testDefaultDoesNotFindCata() {
+ $config = $this->createMock(IConfig::class);
+ $config
+ ->method('getSystemValue')
+ ->with('binary_search_paths', $this->anything())
+ ->will($this->returnCallback(function ($key, $default) {
+ return $default;
+ }));
+ $finder = new BinaryFinder($this->cacheFactory, $config);
+ $this->assertFalse($finder->findBinaryPath('cata'));
+ $this->assertFalse($this->cache->get('cata'));
+ }
+
+ public function testCustomPathFindsCat() {
+ $config = $this->createMock(IConfig::class);
+ $config
+ ->method('getSystemValue')
+ ->with('binary_search_paths', $this->anything())
+ ->willReturn(['/usr/bin']);
+ $finder = new BinaryFinder($this->cacheFactory, $config);
+ $this->assertEquals($finder->findBinaryPath('cat'), '/usr/bin/cat');
+ $this->assertEquals($this->cache->get('cat'), '/usr/bin/cat');
+ }
+
+ public function testWrongCustomPathDoesNotFindCat() {
+ $config = $this->createMock(IConfig::class);
+ $config
+ ->method('getSystemValue')
+ ->with('binary_search_paths')
+ ->willReturn(['/wrong']);
+ $finder = new BinaryFinder($this->cacheFactory, $config);
+ $this->assertFalse($finder->findBinaryPath('cat'));
+ $this->assertFalse($this->cache->get('cat'));
+ }
+}