diff --git a/apps/files_external/appinfo/info.xml b/apps/files_external/appinfo/info.xml
index 285d5eb2a435f..e29479892b7f7 100644
--- a/apps/files_external/appinfo/info.xml
+++ b/apps/files_external/appinfo/info.xml
@@ -53,6 +53,7 @@ External storage can be configured using the GUI or at the command line. This se
OCA\Files_External\Command\Verify
OCA\Files_External\Command\Notify
OCA\Files_External\Command\Scan
+ OCA\Files_External\Command\Dependencies
diff --git a/apps/files_external/composer/composer/autoload_classmap.php b/apps/files_external/composer/composer/autoload_classmap.php
index 0b168b1170e43..589b70a078b05 100644
--- a/apps/files_external/composer/composer/autoload_classmap.php
+++ b/apps/files_external/composer/composer/autoload_classmap.php
@@ -14,6 +14,7 @@
'OCA\\Files_External\\Command\\Config' => $baseDir . '/../lib/Command/Config.php',
'OCA\\Files_External\\Command\\Create' => $baseDir . '/../lib/Command/Create.php',
'OCA\\Files_External\\Command\\Delete' => $baseDir . '/../lib/Command/Delete.php',
+ 'OCA\\Files_External\\Command\\Dependencies' => $baseDir . '/../lib/Command/Dependencies.php',
'OCA\\Files_External\\Command\\Export' => $baseDir . '/../lib/Command/Export.php',
'OCA\\Files_External\\Command\\Import' => $baseDir . '/../lib/Command/Import.php',
'OCA\\Files_External\\Command\\ListCommand' => $baseDir . '/../lib/Command/ListCommand.php',
@@ -96,6 +97,7 @@
'OCA\\Files_External\\Lib\\Storage\\SMB' => $baseDir . '/../lib/Lib/Storage/SMB.php',
'OCA\\Files_External\\Lib\\Storage\\StreamWrapper' => $baseDir . '/../lib/Lib/Storage/StreamWrapper.php',
'OCA\\Files_External\\Lib\\Storage\\Swift' => $baseDir . '/../lib/Lib/Storage/Swift.php',
+ 'OCA\\Files_External\\Lib\\Storage\\SystemBridge' => $baseDir . '/../lib/Lib/Storage/SystemBridge.php',
'OCA\\Files_External\\Lib\\VisibilityTrait' => $baseDir . '/../lib/Lib/VisibilityTrait.php',
'OCA\\Files_External\\Listener\\GroupDeletedListener' => $baseDir . '/../lib/Listener/GroupDeletedListener.php',
'OCA\\Files_External\\Listener\\LoadAdditionalListener' => $baseDir . '/../lib/Listener/LoadAdditionalListener.php',
diff --git a/apps/files_external/composer/composer/autoload_static.php b/apps/files_external/composer/composer/autoload_static.php
index 29e95ae968a59..0399f47685c8a 100644
--- a/apps/files_external/composer/composer/autoload_static.php
+++ b/apps/files_external/composer/composer/autoload_static.php
@@ -29,6 +29,7 @@ class ComposerStaticInitFiles_External
'OCA\\Files_External\\Command\\Config' => __DIR__ . '/..' . '/../lib/Command/Config.php',
'OCA\\Files_External\\Command\\Create' => __DIR__ . '/..' . '/../lib/Command/Create.php',
'OCA\\Files_External\\Command\\Delete' => __DIR__ . '/..' . '/../lib/Command/Delete.php',
+ 'OCA\\Files_External\\Command\\Dependencies' => __DIR__ . '/..' . '/../lib/Command/Dependencies.php',
'OCA\\Files_External\\Command\\Export' => __DIR__ . '/..' . '/../lib/Command/Export.php',
'OCA\\Files_External\\Command\\Import' => __DIR__ . '/..' . '/../lib/Command/Import.php',
'OCA\\Files_External\\Command\\ListCommand' => __DIR__ . '/..' . '/../lib/Command/ListCommand.php',
@@ -111,6 +112,7 @@ class ComposerStaticInitFiles_External
'OCA\\Files_External\\Lib\\Storage\\SMB' => __DIR__ . '/..' . '/../lib/Lib/Storage/SMB.php',
'OCA\\Files_External\\Lib\\Storage\\StreamWrapper' => __DIR__ . '/..' . '/../lib/Lib/Storage/StreamWrapper.php',
'OCA\\Files_External\\Lib\\Storage\\Swift' => __DIR__ . '/..' . '/../lib/Lib/Storage/Swift.php',
+ 'OCA\\Files_External\\Lib\\Storage\\SystemBridge' => __DIR__ . '/..' . '/../lib/Lib/Storage/SystemBridge.php',
'OCA\\Files_External\\Lib\\VisibilityTrait' => __DIR__ . '/..' . '/../lib/Lib/VisibilityTrait.php',
'OCA\\Files_External\\Listener\\GroupDeletedListener' => __DIR__ . '/..' . '/../lib/Listener/GroupDeletedListener.php',
'OCA\\Files_External\\Listener\\LoadAdditionalListener' => __DIR__ . '/..' . '/../lib/Listener/LoadAdditionalListener.php',
diff --git a/apps/files_external/lib/Command/Dependencies.php b/apps/files_external/lib/Command/Dependencies.php
new file mode 100644
index 0000000000000..d2db8a8c9af08
--- /dev/null
+++ b/apps/files_external/lib/Command/Dependencies.php
@@ -0,0 +1,57 @@
+setName('files_external:dependencies')
+ ->setDescription('Show information about the backend dependencies');
+ parent::configure();
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output): int {
+ $storageBackends = $this->backendService->getBackends();
+
+ $anyMissing = false;
+
+ foreach ($storageBackends as $backend) {
+ if ($backend->getDeprecateTo() !== null) {
+ continue;
+ }
+ $missingDependencies = $backend->checkDependencies();
+ if ($missingDependencies) {
+ $anyMissing = true;
+ $output->writeln($backend->getText() . ':');
+ foreach ($missingDependencies as $missingDependency) {
+ if ($missingDependency->getMessage()) {
+ $output->writeln(" - {$missingDependency->getDependency()}: {$missingDependency->getMessage()}");
+ } else {
+ $output->writeln(" - {$missingDependency->getDependency()}");
+ }
+ }
+ }
+ }
+
+ if (!$anyMissing) {
+ $output->writeln('All dependencies are met');
+ }
+
+ return self::SUCCESS;
+ }
+}
diff --git a/apps/files_external/lib/Lib/Backend/SMB.php b/apps/files_external/lib/Lib/Backend/SMB.php
index 13da0417c1e49..4479ecdcaaa1c 100644
--- a/apps/files_external/lib/Lib/Backend/SMB.php
+++ b/apps/files_external/lib/Lib/Backend/SMB.php
@@ -11,19 +11,20 @@
use Icewind\SMB\BasicAuth;
use Icewind\SMB\KerberosApacheAuth;
use Icewind\SMB\KerberosAuth;
+use Icewind\SMB\Native\NativeServer;
+use Icewind\SMB\Wrapped\Server;
use OCA\Files_External\Lib\Auth\AuthMechanism;
use OCA\Files_External\Lib\Auth\Password\Password;
use OCA\Files_External\Lib\Auth\SMB\KerberosApacheAuth as KerberosApacheAuthMechanism;
use OCA\Files_External\Lib\DefinitionParameter;
use OCA\Files_External\Lib\InsufficientDataForMeaningfulAnswerException;
-use OCA\Files_External\Lib\LegacyDependencyCheckPolyfill;
+use OCA\Files_External\Lib\MissingDependency;
+use OCA\Files_External\Lib\Storage\SystemBridge;
use OCA\Files_External\Lib\StorageConfig;
use OCP\IL10N;
use OCP\IUser;
class SMB extends Backend {
- use LegacyDependencyCheckPolyfill;
-
public function __construct(IL10N $l, Password $legacyAuth) {
$this
->setIdentifier('smb')
@@ -123,4 +124,20 @@ public function manipulateStorageConfig(StorageConfig &$storage, ?IUser $user =
$storage->setBackendOption('auth', $smbAuth);
}
+
+ public function checkDependencies() {
+ $system = \OCP\Server::get(SystemBridge::class);
+ if (NativeServer::available($system)) {
+ return [];
+ } elseif (Server::available($system)) {
+ $missing = new MissingDependency('php-smbclient');
+ $missing->setOptional(true);
+ $missing->setMessage('The php-smbclient library provides improved compatibility and performance for SMB storages.');
+ return [$missing];
+ } else {
+ $missing = new MissingDependency('php-smbclient');
+ $missing->setMessage('Either the php-smbclient library (preferred) or the smbclient binary is required for SMB storages.');
+ return [$missing, new MissingDependency('smbclient')];
+ }
+ }
}
diff --git a/apps/files_external/lib/Lib/MissingDependency.php b/apps/files_external/lib/Lib/MissingDependency.php
index 987bd226675a1..e6d3250264472 100644
--- a/apps/files_external/lib/Lib/MissingDependency.php
+++ b/apps/files_external/lib/Lib/MissingDependency.php
@@ -11,18 +11,16 @@
* External storage backend dependency
*/
class MissingDependency {
-
- /** @var string */
- private $dependency;
-
/** @var string|null Custom message */
- private $message = null;
+ private ?string $message = null;
+ private bool $optional = false;
/**
* @param string $dependency
*/
- public function __construct($dependency) {
- $this->dependency = $dependency;
+ public function __construct(
+ private string $dependency,
+ ) {
}
public function getDependency(): string {
@@ -41,4 +39,12 @@ public function setMessage($message) {
$this->message = $message;
return $this;
}
+
+ public function isOptional(): bool {
+ return $this->optional;
+ }
+
+ public function setOptional(bool $optional): void {
+ $this->optional = $optional;
+ }
}
diff --git a/apps/files_external/lib/Lib/Storage/SMB.php b/apps/files_external/lib/Lib/Storage/SMB.php
index 7ea615c739469..e0ee289696d29 100644
--- a/apps/files_external/lib/Lib/Storage/SMB.php
+++ b/apps/files_external/lib/Lib/Storage/SMB.php
@@ -5,6 +5,7 @@
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
* SPDX-License-Identifier: AGPL-3.0-only
*/
+
namespace OCA\Files_External\Lib\Storage;
use Icewind\SMB\ACL;
@@ -22,7 +23,7 @@
use Icewind\SMB\Native\NativeServer;
use Icewind\SMB\Options;
use Icewind\SMB\ServerFactory;
-use Icewind\SMB\System;
+use Icewind\SMB\Wrapped\Server;
use Icewind\Streams\CallbackWrapper;
use Icewind\Streams\IteratorDirectory;
use OC\Files\Filesystem;
@@ -93,7 +94,7 @@ public function __construct($params) {
}
$this->logger = $params['logger'];
} else {
- $this->logger = \OC::$server->get(LoggerInterface::class);
+ $this->logger = \OCP\Server::get(LoggerInterface::class);
}
$options = new Options();
@@ -103,7 +104,8 @@ public function __construct($params) {
$options->setTimeout($timeout);
}
}
- $serverFactory = new ServerFactory($options);
+ $system = \OCP\Server::get(SystemBridge::class);
+ $serverFactory = new ServerFactory($options, $system);
$this->server = $serverFactory->createServer($params['host'], $auth);
$this->share = $this->server->getShare(trim($params['share'], '/'));
@@ -721,11 +723,9 @@ public function isDeletable($path) {
/**
* check if smbclient is installed
*/
- public static function checkDependencies() {
- return (
- (bool) \OC_Helper::findBinaryPath('smbclient')
- || NativeServer::available(new System())
- ) ? true : ['smbclient'];
+ public static function checkDependencies(): array|bool {
+ $system = \OCP\Server::get(SystemBridge::class);
+ return Server::available($system) || NativeServer::available($system) ?: ['smbclient'];
}
/**
diff --git a/apps/files_external/lib/Lib/Storage/SystemBridge.php b/apps/files_external/lib/Lib/Storage/SystemBridge.php
new file mode 100644
index 0000000000000..80449b2744bb6
--- /dev/null
+++ b/apps/files_external/lib/Lib/Storage/SystemBridge.php
@@ -0,0 +1,27 @@
+
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCA\Files_External\Lib\Storage;
+
+use Icewind\SMB\System;
+use OCP\IBinaryFinder;
+
+/**
+ * Bridge the NC and SMB binary finding logic
+ */
+class SystemBridge extends System {
+ public function __construct(
+ private IBinaryFinder $binaryFinder,
+ ) {
+ }
+
+ protected function getBinaryPath(string $binary): ?string {
+ $path = $this->binaryFinder->findBinaryPath($binary);
+ return $path !== false ? $path : null;
+ }
+}
diff --git a/apps/files_external/lib/Service/BackendService.php b/apps/files_external/lib/Service/BackendService.php
index 8fe1ff31a7c6d..0535787e535a1 100644
--- a/apps/files_external/lib/Service/BackendService.php
+++ b/apps/files_external/lib/Service/BackendService.php
@@ -13,6 +13,7 @@
use OCA\Files_External\Lib\Backend\Backend;
use OCA\Files_External\Lib\Config\IAuthMechanismProvider;
use OCA\Files_External\Lib\Config\IBackendProvider;
+use OCA\Files_External\Lib\MissingDependency;
use OCP\EventDispatcher\GenericEvent;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\IConfig;
@@ -199,7 +200,8 @@ public function getBackends() {
*/
public function getAvailableBackends() {
return array_filter($this->getBackends(), function ($backend) {
- return !$backend->checkDependencies();
+ $missing = array_filter($backend->checkDependencies(), fn (MissingDependency $dependency) => !$dependency->isOptional());
+ return count($missing) === 0;
});
}
diff --git a/lib/public/IBinaryFinder.php b/lib/public/IBinaryFinder.php
index 3224ef523eda2..28cb62e5c56f0 100644
--- a/lib/public/IBinaryFinder.php
+++ b/lib/public/IBinaryFinder.php
@@ -11,7 +11,7 @@
/**
* Service that find the binary path for a program.
*
- * This interface should be injected via depency injection and must
+ * This interface should be injected via dependency injection and must
* not be implemented in applications.
*
* @since 25.0.0