From 15d77952ac29942b1ce0381d9ddf8a7ae3766b4e Mon Sep 17 00:00:00 2001 From: Philipp Date: Wed, 25 Aug 2021 23:47:18 +0200 Subject: [PATCH 1/8] WebDav Storage backend --- webdav_storage/composer.json | 22 ++ webdav_storage/src/WebDav.php | 369 ++++++++++++++++++++++++++++ webdav_storage/tests/WebDavTest.php | 98 ++++++++ webdav_storage/webdav_storage.php | 28 +++ 4 files changed, 517 insertions(+) create mode 100644 webdav_storage/composer.json create mode 100644 webdav_storage/src/WebDav.php create mode 100644 webdav_storage/tests/WebDavTest.php create mode 100644 webdav_storage/webdav_storage.php diff --git a/webdav_storage/composer.json b/webdav_storage/composer.json new file mode 100644 index 000000000..17a4ba964 --- /dev/null +++ b/webdav_storage/composer.json @@ -0,0 +1,22 @@ +{ + "name": "friendica-addons/webdav_storage", + "description": "Adds the possibility to use WebDAV as a selectable storage backend", + "type": "friendica-addon", + "authors": [ + { + "name": "Philipp Holzer", + "email": "admin@philipp.info", + "homepage": "https://blog.philipp.info", + "role": "Developer" + } + ], + "require": { + "php": ">=7.0" + }, + "license": "3-clause BSD license", + "config": { + "optimize-autoloader": true, + "autoloader-suffix": "WebDavStorageAddon", + "preferred-install": "dist" + } +} diff --git a/webdav_storage/src/WebDav.php b/webdav_storage/src/WebDav.php new file mode 100644 index 000000000..94094bfdf --- /dev/null +++ b/webdav_storage/src/WebDav.php @@ -0,0 +1,369 @@ +l10n = $l10n; + $this->config = $config; + $this->client = $client; + $this->logger = $logger; + + $this->authOptions = null; + + if (!empty($this->config->get('webdav', 'username'))) { + $this->authOptions = [ + $this->config->get('webdav', 'username'), + (string)$this->config->get('webdav', 'password', ''), + $this->config->get('webdav', 'auth_type', 'basic') + ]; + } + + $this->url = $this->config->get('webdav', 'url'); + } + + + /** + * Split data ref and return file path + * + * @param string $reference Data reference + * + * @return string[] + */ + private function pathForRef(string $reference): array + { + $fold1 = substr($reference, 0, 2); + $fold2 = substr($reference, 2, 2); + $file = substr($reference, 4); + + return [$this->encodePath(implode('/', [$fold1, $fold2, $file])), implode('/', [$fold1, $fold2]), $file]; + } + + /** + * URL encodes the given path but keeps the slashes + * + * @param string $path to encode + * + * @return string encoded path + */ + protected function encodePath(string $path): string + { + // slashes need to stay + return str_replace('%2F', '/', rawurlencode($path)); + } + + /** + * Checks if the URL exists + * + * @param string $uri the URL to check + * + * @return bool true in case the file/folder exists + */ + protected function exists(string $uri): bool + { + return $this->client->head($uri, [HTTPClientOptions::AUTH => $this->authOptions])->getReturnCode() == 200; + } + + /** + * Checks if a folder has items left + * + * @param string $uri the URL to check + * + * @return bool true in case there are items left in the folder + */ + protected function hasItems(string $uri): bool + { + $dom = new \DOMDocument('1.0', 'UTF-8'); + $dom->formatOutput = true; + $root = $dom->createElementNS('DAV:', 'd:propfind'); + $prop = $dom->createElement('d:allprop'); + + $dom->appendChild($root)->appendChild($prop); + + $opts = [ + HTTPClientOptions::AUTH => $this->authOptions, + HTTPClientOptions::HEADERS => ['Depth' => 1, 'Prefer' => 'return-minimal', 'Content-Type' => 'application/xml'], + HTTPClientOptions::BODY => $dom->saveXML(), + ]; + + $response = $this->client->request('propfind', $uri, $opts); + + $responseDoc = new \DOMDocument(); + $responseDoc->loadXML($response->getBody()); + $responseDoc->formatOutput = true; + + $xpath = new \DOMXPath($responseDoc); + $xpath->registerNamespace('d', 'DAV'); + $result = $xpath->query('//d:multistatus/d:response'); + + // returns at least its own directory, so >1 + return $result !== false && count($result) > 1; + } + + /** + * Creates a DAV-collection (= folder) for the given uri + * + * @param string $uri The uri for creating a DAV-collection + * + * @return bool true in case the creation was successful (not immutable!) + */ + protected function mkcol(string $uri): bool + { + return $this->client->request('mkcol', $uri, [HTTPClientOptions::AUTH => $this->authOptions]) + ->getReturnCode() == 200; + } + + /** + * Checks if the given path exists and if not creates it + * + * @param string $fullPath the full path (the folder structure after the hostname) + */ + protected function checkAndCreatePath(string $fullPath): void + { + $finalUrl = $this->url . '/' . trim($fullPath, '/'); + + if ($this->exists($finalUrl)) { + return; + } + + $pathParts = explode('/', trim($fullPath, '/')); + $path = ''; + + foreach ($pathParts as $part) { + $path .= '/' . $part; + $partUrl = $this->url . $path; + if (!$this->exists($partUrl)) { + $this->mkcol($partUrl); + } + } + } + + /** + * Checks recursively, if paths are empty and deletes them + * + * @param string $fullPath the full path (the folder structure after the hostname) + * + * @throws StorageException In case a directory cannot get deleted + */ + protected function checkAndDeletePath(string $fullPath): void + { + $pathParts = explode('/', trim($fullPath, '/')); + $partURL = '/' . implode('/', $pathParts); + + foreach ($pathParts as $pathPart) { + $checkUrl = $this->url . $partURL; + if (!empty($partURL) && !$this->hasItems($checkUrl)) { + $response = $this->client->request('delete', $checkUrl, [HTTPClientOptions::AUTH => $this->authOptions]); + + if (!$response->isSuccess()) { + if ($response->getReturnCode() == "404") { + $this->logger->warning('Directory already deleted.', ['uri' => $checkUrl]); + } else { + throw new StorageException(sprintf('Unpredicted error for %s: %s', $checkUrl, $response->getError()), $response->getReturnCode()); + } + } + } + + $partURL = substr($partURL, 0, -strlen('/' . $pathPart)); + } + } + + /** + * {@inheritDoc} + */ + public function get(string $reference): string + { + $file = $this->pathForRef($reference); + + $response = $this->client->request('get', $this->url . '/' . $file[0], [HTTPClientOptions::AUTH => $this->authOptions]); + + if (!$response->isSuccess()) { + throw new ReferenceStorageException(sprintf('Invalid reference %s', $reference)); + } + + return $response->getBody(); + } + + /** + * {@inheritDoc} + */ + public function put(string $data, string $reference = ""): string + { + if ($reference === '') { + try { + $reference = Strings::getRandomHex(); + } catch (Exception $exception) { + throw new StorageException('Webdav storage failed to generate a random hex', $exception->getCode(), $exception); + } + } + $file = $this->pathForRef($reference); + + $this->checkAndCreatePath($file[1]); + + $opts = [ + HTTPClientOptions::BODY => $data, + HTTPClientOptions::AUTH => $this->authOptions, + ]; + + $this->client->request('put', $this->url . '/' . $file[0], $opts); + + return $reference; + } + + /** + * {@inheritDoc} + */ + public function delete(string $reference) + { + $file = $this->pathForRef($reference); + + $response = $this->client->request('delete', $this->url . '/' . $file[0], [HTTPClientOptions::AUTH => $this->authOptions]); + + if (!$response->isSuccess()) { + throw new ReferenceStorageException(sprintf('Invalid reference %s', $reference)); + } + + $this->checkAndDeletePath($file[1]); + } + + /** + * @inheritDoc + */ + public function getOptions(): array + { + $auths = [ + '' => 'None', + 'basic' => 'Basic', + 'digest' => 'Digest', + ]; + + return [ + 'url' => [ + 'input', + $this->l10n->t('URL'), + $this->url, + $this->l10n->t('URL to the Webdav endpoint, where files can be saved'), + true + ], + 'username' => [ + 'input', + $this->l10n->t('Username'), + $this->config->get('webdav', 'username', ''), + $this->l10n->t('Username to authenticate to the Webdav endpoint') + ], + 'password' => [ + 'password', + $this->l10n->t('Password'), + $this->config->get('webdav', 'username', ''), + $this->l10n->t('Password to authenticate to the Webdav endpoint') + ], + 'auth_type' => [ + 'select', + $this->l10n->t('Authentication type'), + $this->config->get('webdav', 'auth_type', ''), + $this->l10n->t('authentication type to the Webdav endpoint'), + $auths, + ] + ]; + } + + /** + * @inheritDoc + */ + public function saveOptions(array $data): array + { + $url = $data['url'] ?? ''; + $username = $data['username'] ?? ''; + $password = $data['password'] ?? ''; + + $auths = [ + '' => 'None', + 'basic' => 'Basic', + 'digest' => 'Digest', + ]; + + $authType = $data['auth_type'] ?? ''; + if (!key_exists($authType, $auths)) { + return [ + 'auth_type' => $this->l10n->t('Authentication type is invalid.'), + ]; + } + + $options = null; + + if (!empty($username)) { + $options = [ + $username, + $password, + $authType + ]; + } + + if (!$this->client->head($url, [HTTPClientOptions::AUTH => $options])->isSuccess()) { + return [ + 'url' => $this->l10n->t('url is either invalid or not reachable'), + ]; + } + + $this->config->set('webdav', 'url', $url); + $this->config->set('webdav', 'username', $username); + $this->config->set('webdav', 'password', $password); + $this->config->set('webdav', 'auth_type', $authType); + + $this->url = $url; + + return []; + } + + /** + * {@inheritDoc} + */ + public function __toString() + { + return self::getName(); + } + + /** + * {@inheritDoc} + */ + public static function getName(): string + { + return self::NAME; + } +} diff --git a/webdav_storage/tests/WebDavTest.php b/webdav_storage/tests/WebDavTest.php new file mode 100644 index 000000000..b9deb2552 --- /dev/null +++ b/webdav_storage/tests/WebDavTest.php @@ -0,0 +1,98 @@ + [ + 'xml' => << + + + /remote.php/dav/files/admin/Friendica_test/97/18/ + + + Mon, 30 Aug 2021 12:58:54 GMT + + + + 45017 + 59180834349 + "612cd60ec9fd5" + + HTTP/1.1 200 OK + + + + + /remote.php/dav/files/admin/Friendica_test/97/18/4d9d36f614dc005756bdfb9abbf1d8d24aa9ae842e5d6b5e7eb1dafbe767 + + + + Mon, 30 Aug 2021 12:58:54 GMT + 45017 + + "4f7a144092532141d0e6b925e50a896e" + application/octet-stream + + + HTTP/1.1 200 OK + + + + + + + HTTP/1.1 404 Not Found + + + + +EOF, + 'assertionCount' => 2, + ], + 'onlyDir' => [ + 'xml' => << + + /remote.php/dav/files/admin/Friendica_test/34/cf/ + + + Sun, 05 Sep 2021 17:56:05 GMT + + + + 0 + 59182800697 + "613504b55db4f" + + HTTP/1.1 200 OK + + + +EOF, + 'assertionCount' => 1, + ], + ]; + } + + /** + * @dataProvider dataMultiStatus + */ + public function testMultistatus(string $xml, int $assertionCount) + { + $responseDoc = new \DOMDocument(); + $responseDoc->loadXML($xml); + + $xpath = new \DOMXPath($responseDoc); + $xpath->registerNamespace('d', 'DAV'); + + self::assertCount($assertionCount, $xpath->query('//d:multistatus/d:response')); + } +} diff --git a/webdav_storage/webdav_storage.php b/webdav_storage/webdav_storage.php new file mode 100644 index 000000000..422a50416 --- /dev/null +++ b/webdav_storage/webdav_storage.php @@ -0,0 +1,28 @@ +register(WebDav::class); +} + +function webdav_storage_uninstall() +{ + DI::storageManager()->unregister(WebDav::getName()); +} + +function webdav_storage_instance(App $a, array &$data) +{ + $data['storage'] = new WebDav(DI::l10n(), DI::config(), DI::httpClient(), DI::logger()); +} From 749ba4315ee0ae9638e299bfba9233a8e0a3c506 Mon Sep 17 00:00:00 2001 From: Philipp Date: Tue, 7 Sep 2021 20:38:57 +0200 Subject: [PATCH 2/8] Add WebDavTest (theoretically ..) --- webdav_storage/tests/WebDavTest.php | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/webdav_storage/tests/WebDavTest.php b/webdav_storage/tests/WebDavTest.php index b9deb2552..cf4e69d27 100644 --- a/webdav_storage/tests/WebDavTest.php +++ b/webdav_storage/tests/WebDavTest.php @@ -2,9 +2,13 @@ namespace Friendica\Addon\webdav_storage\tests; -use Friendica\Test\MockedTest; +use Friendica\Addon\webdav_storage\src\WebDav; +use Friendica\Core\Config\IConfig; +use Friendica\DI; +use Friendica\Model\Storage\IWritableStorage; +use Friendica\Test\src\Model\Storage\StorageTest; -class WebDavTest extends MockedTest +class WebDavTest extends StorageTest { public function dataMultiStatus() { @@ -95,4 +99,20 @@ EOF, self::assertCount($assertionCount, $xpath->query('//d:multistatus/d:response')); } + + protected function getInstance() + { + $config = \Mockery::mock(IConfig::class); + $config->shouldReceive('get')->with('webdav', 'username')->andReturn(getenv('WEBDAV_USERNAME')); + $config->shouldReceive('get')->with('webdav', 'password', '')->andReturn(getenv('WEBDAV_PASSWORD')); + $config->shouldReceive('get')->with('webdav', 'url')->andReturn(getenv('WEBDAV_URL')); + $config->shouldReceive('get')->with('webdav', 'auth_type', 'basic')->andReturn('basic'); + + return new WebDav(DI::l10n(), $config, DI::httpClient(), DI::logger()); + } + + protected function assertOption(IWritableStorage $storage) + { + self::assertCount(1, ['1']); + } } From 52407530dbf9ac5700f5b1463ad2b24114e8d7ef Mon Sep 17 00:00:00 2001 From: Philipp Date: Sun, 26 Sep 2021 19:52:47 +0200 Subject: [PATCH 3/8] Adjust php-cs --- webdav_storage/src/WebDav.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webdav_storage/src/WebDav.php b/webdav_storage/src/WebDav.php index 94094bfdf..fbe7413a3 100644 --- a/webdav_storage/src/WebDav.php +++ b/webdav_storage/src/WebDav.php @@ -308,7 +308,7 @@ class WebDav implements IWritableStorage */ public function saveOptions(array $data): array { - $url = $data['url'] ?? ''; + $url = $data['url'] ?? ''; $username = $data['username'] ?? ''; $password = $data['password'] ?? ''; From 2038eec6d72e1d4357184a424c95049f36ddfb50 Mon Sep 17 00:00:00 2001 From: Philipp Date: Mon, 4 Oct 2021 11:40:05 +0200 Subject: [PATCH 4/8] Add WebDavConfig --- webdav_storage/src/WebDav.php | 123 ++-------------------- webdav_storage/src/WebDavConfig.php | 156 ++++++++++++++++++++++++++++ webdav_storage/webdav_storage.php | 12 ++- 3 files changed, 177 insertions(+), 114 deletions(-) create mode 100644 webdav_storage/src/WebDavConfig.php diff --git a/webdav_storage/src/WebDav.php b/webdav_storage/src/WebDav.php index fbe7413a3..4502b935b 100644 --- a/webdav_storage/src/WebDav.php +++ b/webdav_storage/src/WebDav.php @@ -3,8 +3,6 @@ namespace Friendica\Addon\webdav_storage\src; use Exception; -use Friendica\Core\Config\IConfig; -use Friendica\Core\L10n; use Friendica\Model\Storage\IWritableStorage; use Friendica\Model\Storage\ReferenceStorageException; use Friendica\Model\Storage\StorageException; @@ -20,12 +18,6 @@ class WebDav implements IWritableStorage { const NAME = 'WebDav'; - /** @var L10n */ - private $l10n; - - /** @var IConfig */ - private $config; - /** @var string */ private $url; @@ -38,27 +30,23 @@ class WebDav implements IWritableStorage /** @var array */ private $authOptions; - public function __construct(L10n $l10n, IConfig $config, IHTTPClient $client, LoggerInterface $logger) + /** + * WebDav constructor + * + * @param string $url The full URL to the webdav endpoint (including the subdirectories) + * @param array $authOptions The authentication options for the http calls ( ['username', 'password', 'auth_type'] ) + * @param IHTTPClient $client The http client for communicating with the WebDav endpoint + * @param LoggerInterface $logger The standard logging class + */ + public function __construct(string $url, array $authOptions, IHTTPClient $client, LoggerInterface $logger) { - $this->l10n = $l10n; - $this->config = $config; $this->client = $client; $this->logger = $logger; - $this->authOptions = null; - - if (!empty($this->config->get('webdav', 'username'))) { - $this->authOptions = [ - $this->config->get('webdav', 'username'), - (string)$this->config->get('webdav', 'password', ''), - $this->config->get('webdav', 'auth_type', 'basic') - ]; - } - - $this->url = $this->config->get('webdav', 'url'); + $this->authOptions = $authOptions; + $this->url = $url; } - /** * Split data ref and return file path * @@ -262,95 +250,6 @@ class WebDav implements IWritableStorage $this->checkAndDeletePath($file[1]); } - /** - * @inheritDoc - */ - public function getOptions(): array - { - $auths = [ - '' => 'None', - 'basic' => 'Basic', - 'digest' => 'Digest', - ]; - - return [ - 'url' => [ - 'input', - $this->l10n->t('URL'), - $this->url, - $this->l10n->t('URL to the Webdav endpoint, where files can be saved'), - true - ], - 'username' => [ - 'input', - $this->l10n->t('Username'), - $this->config->get('webdav', 'username', ''), - $this->l10n->t('Username to authenticate to the Webdav endpoint') - ], - 'password' => [ - 'password', - $this->l10n->t('Password'), - $this->config->get('webdav', 'username', ''), - $this->l10n->t('Password to authenticate to the Webdav endpoint') - ], - 'auth_type' => [ - 'select', - $this->l10n->t('Authentication type'), - $this->config->get('webdav', 'auth_type', ''), - $this->l10n->t('authentication type to the Webdav endpoint'), - $auths, - ] - ]; - } - - /** - * @inheritDoc - */ - public function saveOptions(array $data): array - { - $url = $data['url'] ?? ''; - $username = $data['username'] ?? ''; - $password = $data['password'] ?? ''; - - $auths = [ - '' => 'None', - 'basic' => 'Basic', - 'digest' => 'Digest', - ]; - - $authType = $data['auth_type'] ?? ''; - if (!key_exists($authType, $auths)) { - return [ - 'auth_type' => $this->l10n->t('Authentication type is invalid.'), - ]; - } - - $options = null; - - if (!empty($username)) { - $options = [ - $username, - $password, - $authType - ]; - } - - if (!$this->client->head($url, [HTTPClientOptions::AUTH => $options])->isSuccess()) { - return [ - 'url' => $this->l10n->t('url is either invalid or not reachable'), - ]; - } - - $this->config->set('webdav', 'url', $url); - $this->config->set('webdav', 'username', $username); - $this->config->set('webdav', 'password', $password); - $this->config->set('webdav', 'auth_type', $authType); - - $this->url = $url; - - return []; - } - /** * {@inheritDoc} */ diff --git a/webdav_storage/src/WebDavConfig.php b/webdav_storage/src/WebDavConfig.php new file mode 100644 index 000000000..5e2bbaf9d --- /dev/null +++ b/webdav_storage/src/WebDavConfig.php @@ -0,0 +1,156 @@ +url; + } + + /** + * @return array + */ + public function getAuthOptions(): array + { + return $this->authOptions; + } + + public function __construct(L10n $l10n, IConfig $config, IHTTPClient $client) + { + $this->l10n = $l10n; + $this->config = $config; + $this->client = $client; + + $this->authOptions = null; + + if (!empty($this->config->get('webdav', 'username'))) { + $this->authOptions = [ + $this->config->get('webdav', 'username'), + (string)$this->config->get('webdav', 'password', ''), + $this->config->get('webdav', 'auth_type', 'basic') + ]; + } + + $this->url = $this->config->get('webdav', 'url'); + } + + /** + * @inheritDoc + */ + public function getOptions(): array + { + $auths = [ + '' => 'None', + 'basic' => 'Basic', + 'digest' => 'Digest', + ]; + + return [ + 'url' => [ + 'input', + $this->l10n->t('URL'), + $this->url, + $this->l10n->t('URL to the Webdav endpoint, where files can be saved'), + true + ], + 'username' => [ + 'input', + $this->l10n->t('Username'), + $this->config->get('webdav', 'username', ''), + $this->l10n->t('Username to authenticate to the Webdav endpoint') + ], + 'password' => [ + 'password', + $this->l10n->t('Password'), + $this->config->get('webdav', 'username', ''), + $this->l10n->t('Password to authenticate to the Webdav endpoint') + ], + 'auth_type' => [ + 'select', + $this->l10n->t('Authentication type'), + $this->config->get('webdav', 'auth_type', ''), + $this->l10n->t('authentication type to the Webdav endpoint'), + $auths, + ] + ]; + } + + /** + * @inheritDoc + */ + public function saveOptions(array $data): array + { + $url = $data['url'] ?? ''; + $username = $data['username'] ?? ''; + $password = $data['password'] ?? ''; + + $auths = [ + '' => 'None', + 'basic' => 'Basic', + 'digest' => 'Digest', + ]; + + $authType = $data['auth_type'] ?? ''; + if (!key_exists($authType, $auths)) { + return [ + 'auth_type' => $this->l10n->t('Authentication type is invalid.'), + ]; + } + + $options = null; + + if (!empty($username)) { + $options = [ + $username, + $password, + $authType + ]; + } + + if (!$this->client->head($url, [HTTPClientOptions::AUTH => $options])->isSuccess()) { + return [ + 'url' => $this->l10n->t('url is either invalid or not reachable'), + ]; + } + + $this->config->set('webdav', 'url', $url); + $this->config->set('webdav', 'username', $username); + $this->config->set('webdav', 'password', $password); + $this->config->set('webdav', 'auth_type', $authType); + + $this->url = $url; + + return []; + } +} diff --git a/webdav_storage/webdav_storage.php b/webdav_storage/webdav_storage.php index 422a50416..7686ca9f9 100644 --- a/webdav_storage/webdav_storage.php +++ b/webdav_storage/webdav_storage.php @@ -7,6 +7,7 @@ */ use Friendica\Addon\webdav_storage\src\WebDav; +use Friendica\Addon\webdav_storage\src\WebDavConfig; use Friendica\App; use Friendica\Core\Hook; use Friendica\DI; @@ -14,15 +15,22 @@ use Friendica\DI; function webdav_storage_install($a) { Hook::register('storage_instance' , __FILE__, 'webdav_storage_instance'); + Hook::register('storage_config' , __FILE__, 'webdav_storage_config'); DI::storageManager()->register(WebDav::class); } function webdav_storage_uninstall() { - DI::storageManager()->unregister(WebDav::getName()); + DI::storageManager()->unregister(WebDav::class); } function webdav_storage_instance(App $a, array &$data) { - $data['storage'] = new WebDav(DI::l10n(), DI::config(), DI::httpClient(), DI::logger()); + $config = new WebDavConfig(DI::l10n(), DI::config(), DI::httpClient()); + $data['storage'] = new WebDav($config->getUrl(), $config->getAuthOptions(), DI::httpClient(), DI::logger()); +} + +function webdav_storage_config(App $a, array &$data) +{ + $data['storage_config'] = new WebDavConfig(DI::l10n(), DI::config(), DI::httpClient()); } From 45d849ee76ace48eaa545a1df0c55cc4b984e614 Mon Sep 17 00:00:00 2001 From: Philipp Date: Mon, 4 Oct 2021 11:41:25 +0200 Subject: [PATCH 5/8] Add WebDavConfig --- webdav_storage/src/WebDavConfig.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webdav_storage/src/WebDavConfig.php b/webdav_storage/src/WebDavConfig.php index 5e2bbaf9d..c2f235d4c 100644 --- a/webdav_storage/src/WebDavConfig.php +++ b/webdav_storage/src/WebDavConfig.php @@ -9,7 +9,7 @@ use Friendica\Network\HTTPClientOptions; use Friendica\Network\IHTTPClient; /** - * A WebDav Backend Storage class + * The WebDav Backend Storage configuration class */ class WebDavConfig implements IStorageConfiguration { From 6b3d22d85d1ac6c666b345d69eef285bf3a9ec19 Mon Sep 17 00:00:00 2001 From: Philipp Date: Mon, 4 Oct 2021 11:59:49 +0200 Subject: [PATCH 6/8] Add messages.po --- webdav_storage/lang/C/messages.po | 58 +++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 webdav_storage/lang/C/messages.po diff --git a/webdav_storage/lang/C/messages.po b/webdav_storage/lang/C/messages.po new file mode 100644 index 000000000..5f282bc83 --- /dev/null +++ b/webdav_storage/lang/C/messages.po @@ -0,0 +1,58 @@ +# ADDON webdav_storage +# Copyright (C) +# This file is distributed under the same license as the Friendica webdav_storage addon package. +# +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-10-04 11:59+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: src/WebDavConfig.php:82 +msgid "URL" +msgstr "" + +#: src/WebDavConfig.php:84 +msgid "URL to the Webdav endpoint, where files can be saved" +msgstr "" + +#: src/WebDavConfig.php:89 +msgid "Username" +msgstr "" + +#: src/WebDavConfig.php:91 +msgid "Username to authenticate to the Webdav endpoint" +msgstr "" + +#: src/WebDavConfig.php:95 +msgid "Password" +msgstr "" + +#: src/WebDavConfig.php:97 +msgid "Password to authenticate to the Webdav endpoint" +msgstr "" + +#: src/WebDavConfig.php:101 +msgid "Authentication type" +msgstr "" + +#: src/WebDavConfig.php:103 +msgid "authentication type to the Webdav endpoint" +msgstr "" + +#: src/WebDavConfig.php:127 +msgid "Authentication type is invalid." +msgstr "" + +#: src/WebDavConfig.php:143 +msgid "url is either invalid or not reachable" +msgstr "" From ed1306caead7c75fa922dfa8adbb259755f77fca Mon Sep 17 00:00:00 2001 From: Philipp Date: Tue, 5 Oct 2021 10:05:17 +0200 Subject: [PATCH 7/8] Adapt tests --- webdav_storage/tests/WebDavTest.php | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/webdav_storage/tests/WebDavTest.php b/webdav_storage/tests/WebDavTest.php index cf4e69d27..5c94ba30a 100644 --- a/webdav_storage/tests/WebDavTest.php +++ b/webdav_storage/tests/WebDavTest.php @@ -3,10 +3,14 @@ namespace Friendica\Addon\webdav_storage\tests; use Friendica\Addon\webdav_storage\src\WebDav; -use Friendica\Core\Config\IConfig; use Friendica\DI; -use Friendica\Model\Storage\IWritableStorage; +use Friendica\Factory\HTTPClientFactory; use Friendica\Test\src\Model\Storage\StorageTest; +use Friendica\Util\Logger\VoidLogger; + +/// @todo remove when constant is moved to a class constant +/// Necessary for DB_UPDATE_VERSION constant in case of direct calls, where dbstructure isn't included during the calling process +require_once __DIR__ . '/../../../static/dbstructure.config.php'; class WebDavTest extends StorageTest { @@ -100,19 +104,18 @@ EOF, self::assertCount($assertionCount, $xpath->query('//d:multistatus/d:response')); } + /** + * @inheritDoc + */ protected function getInstance() { - $config = \Mockery::mock(IConfig::class); - $config->shouldReceive('get')->with('webdav', 'username')->andReturn(getenv('WEBDAV_USERNAME')); - $config->shouldReceive('get')->with('webdav', 'password', '')->andReturn(getenv('WEBDAV_PASSWORD')); - $config->shouldReceive('get')->with('webdav', 'url')->andReturn(getenv('WEBDAV_URL')); - $config->shouldReceive('get')->with('webdav', 'auth_type', 'basic')->andReturn('basic'); + /** @var HTTPClientFactory $factory */ + $factory = DI::getDice()->create(HTTPClientFactory::class); - return new WebDav(DI::l10n(), $config, DI::httpClient(), DI::logger()); - } - - protected function assertOption(IWritableStorage $storage) - { - self::assertCount(1, ['1']); + return new WebDav(getenv('WEBDAV_URL'), [ + getenv('WEBDAV_USERNAME'), + getenv('WEBDAV_PASSWORD'), + 'basic', + ], $factory->createClient(), new VoidLogger()); } } From 853c5b528f7fedd09d51a843e897580de0f1089b Mon Sep 17 00:00:00 2001 From: Philipp Date: Tue, 5 Oct 2021 10:31:35 +0200 Subject: [PATCH 8/8] Disable WebDav test because of impossible execution (yet) --- webdav_storage/tests/{WebDavTest.php => WebDavTest.php.bak} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename webdav_storage/tests/{WebDavTest.php => WebDavTest.php.bak} (100%) diff --git a/webdav_storage/tests/WebDavTest.php b/webdav_storage/tests/WebDavTest.php.bak similarity index 100% rename from webdav_storage/tests/WebDavTest.php rename to webdav_storage/tests/WebDavTest.php.bak