diff --git a/apps/files_sharing/ajax/external.php b/apps/files_sharing/ajax/external.php index f0283d9f268f..baeb8980cd0a 100644 --- a/apps/files_sharing/ajax/external.php +++ b/apps/files_sharing/ajax/external.php @@ -122,31 +122,28 @@ \OCP\JSON::error(['data' => ['message' => $l->t('Storage not valid')]]); exit(); } -$result = $storage->file_exists(''); -if ($result) { - try { - $storage->getScanner()->scanAll(); - \OCP\JSON::success(); - } catch (\OCP\Files\StorageInvalidException $e) { - \OCP\Util::writeLog( - 'files_sharing', - 'Invalid remote storage: ' . get_class($e) . ': ' . $e->getMessage(), - \OCP\Util::DEBUG - ); - \OCP\JSON::error(['data' => ['message' => $l->t('Storage not valid')]]); - } catch (\Exception $e) { + +try { + $result = $storage->file_exists(''); + if (!$result) { + $externalManager->removeShare($mount->getMountPoint()); \OCP\Util::writeLog( 'files_sharing', - 'Invalid remote storage: ' . get_class($e) . ': ' . $e->getMessage(), + 'Couldn\'t add remote share', \OCP\Util::DEBUG ); - \OCP\JSON::error(['data' => ['message' => $l->t('Couldn\'t add remote share')]]); } -} else { - $externalManager->removeShare($mount->getMountPoint()); +} catch (\OCP\Files\StorageInvalidException $e) { \OCP\Util::writeLog( 'files_sharing', - 'Couldn\'t add remote share', + 'Invalid remote storage: ' . get_class($e) . ': ' . $e->getMessage(), + \OCP\Util::DEBUG + ); + \OCP\JSON::error(['data' => ['message' => $l->t('Storage not valid')]]); +} catch (\Exception $e) { + \OCP\Util::writeLog( + 'files_sharing', + 'Invalid remote storage: ' . get_class($e) . ': ' . $e->getMessage(), \OCP\Util::DEBUG ); \OCP\JSON::error(['data' => ['message' => $l->t('Couldn\'t add remote share')]]); diff --git a/apps/files_sharing/ajax/shareinfo.php b/apps/files_sharing/ajax/shareinfo.php index f2ee72e1dd21..8c2c9663072c 100644 --- a/apps/files_sharing/ajax/shareinfo.php +++ b/apps/files_sharing/ajax/shareinfo.php @@ -25,8 +25,17 @@ * */ +/** + * @deprecated fetches all metadata, kept for compatibility with older instances + */ + OCP\JSON::checkAppEnabled('files_sharing'); +OC::$server->getLogger()->warning( + 'Deprecated api access from '.OC::$server->getRequest()->getRemoteAddress(). + '. Ask remote to upgrade.', ['app' => 'files_sharing'] +); + if (!isset($_GET['t'])) { \OC_Response::setStatus(400); //400 Bad Request exit; @@ -101,4 +110,4 @@ function getChildInfo($dir, $view, $sharePermissions) { $result['children'] = getChildInfo($rootInfo, $rootView, $sharePermissions); } -OCP\JSON::success(['data' => $result]); +OCP\JSON::success(['data' => $result, 'message' => 'DEPRECATED API']); diff --git a/apps/files_sharing/lib/External/Scanner.php b/apps/files_sharing/lib/External/Scanner.php deleted file mode 100644 index 782400007d6d..000000000000 --- a/apps/files_sharing/lib/External/Scanner.php +++ /dev/null @@ -1,127 +0,0 @@ - - * @author Morris Jobke - * @author Olivier Paroz - * @author Robin Appelman - * @author Vincent Petry - * - * @copyright Copyright (c) 2017, ownCloud GmbH - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License, version 3, - * along with this program. If not, see - * - */ - -namespace OCA\Files_Sharing\External; - -use OC\ForbiddenException; -use OCP\Files\NotFoundException; -use OCP\Files\StorageInvalidException; -use OCP\Files\StorageNotAvailableException; - -class Scanner extends \OC\Files\Cache\Scanner { - /** @var \OCA\Files_Sharing\External\Storage */ - protected $storage; - - /** {@inheritDoc} */ - public function scan($path, $recursive = self::SCAN_RECURSIVE, $reuse = -1, $lock = true) { - if(!$this->storage->remoteIsOwnCloud()) { - return parent::scan($path, $recursive, $recursive, $lock); - } - - $this->scanAll(); - } - - /** - * Scan a single file and store it in the cache. - * If an exception happened while accessing the external storage, - * the storage will be checked for availability and removed - * if it is not available any more. - * - * @param string $file file to scan - * @param int $reuseExisting - * @param int $parentId - * @param array | null $cacheData existing data in the cache for the file to be scanned - * @param bool $lock set to false to disable getting an additional read lock during scanning - * @return array an array of metadata of the scanned file - */ - public function scanFile($file, $reuseExisting = 0, $parentId = -1, $cacheData = null, $lock = true) { - try { - return parent::scanFile($file, $reuseExisting); - } catch (ForbiddenException $e) { - $this->storage->checkStorageAvailability(); - } catch (NotFoundException $e) { - // if the storage isn't found, the call to - // checkStorageAvailable() will verify it and remove it - // if appropriate - $this->storage->checkStorageAvailability(); - } catch (StorageInvalidException $e) { - $this->storage->checkStorageAvailability(); - } catch (StorageNotAvailableException $e) { - $this->storage->checkStorageAvailability(); - } - } - - /** - * Checks the remote share for changes. - * If changes are available, scan them and update - * the cache. - * @throws NotFoundException - * @throws StorageInvalidException - * @throws \Exception - */ - public function scanAll() { - try { - $data = $this->storage->getShareInfo(); - } catch (\Exception $e) { - $this->storage->checkStorageAvailability(); - throw new \Exception( - 'Error while scanning remote share: "' . - $this->storage->getRemote() . '" ' . - $e->getMessage() - ); - } - if ($data['status'] === 'success') { - $this->addResult($data['data'], ''); - } else { - throw new \Exception( - 'Error while scanning remote share: "' . - $this->storage->getRemote() . '"' - ); - } - } - - /** - * @param array $data - * @param string $path - */ - private function addResult($data, $path) { - $id = $this->cache->put($path, $data); - if (isset($data['children'])) { - $children = []; - foreach ($data['children'] as $child) { - $children[$child['name']] = true; - $this->addResult($child, ltrim($path . '/' . $child['name'], '/')); - } - - $existingCache = $this->cache->getFolderContentsById($id); - foreach ($existingCache as $existingChild) { - // if an existing child is not in the new data, remove it - if (!isset($children[$existingChild['name']])) { - $this->cache->remove(ltrim($path . '/' . $existingChild['name'], '/')); - } - } - } - } -} diff --git a/apps/files_sharing/lib/External/Storage.php b/apps/files_sharing/lib/External/Storage.php index 822f46ad66b7..49a599282c01 100644 --- a/apps/files_sharing/lib/External/Storage.php +++ b/apps/files_sharing/lib/External/Storage.php @@ -30,13 +30,11 @@ use GuzzleHttp\Exception\ClientException; use GuzzleHttp\Exception\ConnectException; use OC\Files\Storage\DAV; -use OC\ForbiddenException; use OCA\FederatedFileSharing\DiscoveryManager; use OCA\Files_Sharing\ISharedStorage; -use OCP\AppFramework\Http; -use OCP\Files\NotFoundException; use OCP\Files\StorageInvalidException; use OCP\Files\StorageNotAvailableException; +use Sabre\DAV\Client; class Storage extends DAV implements ISharedStorage { /** @var string */ @@ -89,7 +87,9 @@ public function __construct($options) { 'host' => $host, 'root' => $root, 'user' => $options['token'], - 'password' => (string)$options['password'] + 'password' => (string)$options['password'], + // Federated sharing always uses BASIC auth + 'authType' => Client::AUTH_BASIC ]); } @@ -139,21 +139,6 @@ public function getCache($path = '', $storage = null) { return $this->cache; } - /** - * @param string $path - * @param \OC\Files\Storage\Storage $storage - * @return \OCA\Files_Sharing\External\Scanner - */ - public function getScanner($path = '', $storage = null) { - if (!$storage) { - $storage = $this; - } - if (!isset($this->scanner)) { - $this->scanner = new Scanner($storage); - } - return $this->scanner; - } - /** * check if a file or folder has been updated since $time * @@ -207,29 +192,25 @@ public function test() { public function checkStorageAvailability() { // see if we can find out why the share is unavailable try { - $this->getShareInfo(); - } catch (NotFoundException $e) { - // a 404 can either mean that the share no longer exists or there is no ownCloud on the remote - if ($this->testRemote()) { - // valid ownCloud instance means that the public share no longer exists - // since this is permanent (re-sharing the file will create a new token) - // we remove the invalid storage - $this->manager->removeShare($this->mountPoint); - $this->manager->getMountManager()->removeMount($this->mountPoint); - throw new StorageInvalidException(); - } else { - // ownCloud instance is gone, likely to be a temporary server configuration error - throw new StorageNotAvailableException(); + if ( ! $this->propfind('') ) { + // a 404 can either mean that the share no longer exists or there is no ownCloud on the remote + if ($this->testRemote()) { + // valid ownCloud instance means that the public share no longer exists + // since this is permanent (re-sharing the file will create a new token) + // we remove the invalid storage + $this->manager->removeShare($this->mountPoint); + $this->manager->getMountManager()->removeMount($this->mountPoint); + throw new StorageInvalidException(); + } else { + // ownCloud instance is gone, likely to be a temporary server configuration error + throw new StorageNotAvailableException(); + } } - } catch (ForbiddenException $e) { + } catch (StorageInvalidException $e) { // auth error, remove share for now (provide a dialog in the future) $this->manager->removeShare($this->mountPoint); $this->manager->getMountManager()->removeMount($this->mountPoint); - throw new StorageInvalidException(); - } catch (\GuzzleHttp\Exception\ConnectException $e) { - throw new StorageNotAvailableException(); - } catch (\GuzzleHttp\Exception\RequestException $e) { - throw new StorageNotAvailableException(); + throw $e; } catch (\Exception $e) { throw $e; } @@ -286,61 +267,6 @@ private function testRemoteUrl($url) { return $returnValue; } - /** - * Whether the remote is an ownCloud, used since some sharing features are not - * standardized. Let's use this to detect whether to use it. - * - * @return bool - */ - public function remoteIsOwnCloud() { - if(defined('PHPUNIT_RUN') || !$this->testRemoteUrl($this->getRemote() . '/status.php')) { - return false; - } - return true; - } - - /** - * @return mixed - * @throws ForbiddenException - * @throws NotFoundException - * @throws \Exception - */ - public function getShareInfo() { - $remote = $this->getRemote(); - $token = $this->getToken(); - $password = $this->getPassword(); - - // If remote is not an ownCloud do not try to get any share info - if(!$this->remoteIsOwnCloud()) { - return ['status' => 'unsupported']; - } - - $url = rtrim($remote, '/') . '/index.php/apps/files_sharing/shareinfo?t=' . $token; - - // TODO: DI - $client = \OC::$server->getHTTPClientService()->newClient(); - try { - $response = $client->post($url, [ - 'body' => ['password' => $password], - 'timeout' => 10, - 'connect_timeout' => 10, - ]); - } catch (\GuzzleHttp\Exception\RequestException $e) { - if ($e->getCode() === Http::STATUS_UNAUTHORIZED || $e->getCode() === Http::STATUS_FORBIDDEN) { - throw new ForbiddenException(); - } - if ($e->getCode() === Http::STATUS_NOT_FOUND) { - throw new NotFoundException(); - } - // throw this to be on the safe side: the share will still be visible - // in the UI in case the failure is intermittent, and the user will - // be able to decide whether to remove it if it's really gone - throw new StorageNotAvailableException(); - } - - return json_decode($response->getBody(), true); - } - public function getOwner($path) { list(, $remote) = explode('://', $this->remote, 2); return $this->remoteUser . '@' . $remote; diff --git a/apps/files_sharing/tests/External/ScannerTest.php b/apps/files_sharing/tests/External/ScannerTest.php deleted file mode 100644 index c2da2705b7f1..000000000000 --- a/apps/files_sharing/tests/External/ScannerTest.php +++ /dev/null @@ -1,82 +0,0 @@ - - * - * @copyright Copyright (c) 2017, ownCloud GmbH - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License, version 3, - * along with this program. If not, see - * - */ - -namespace OCA\Files_Sharing\Tests\External; - -use OCA\Files_Sharing\External\Scanner; -use Test\TestCase; - -class ScannerTest extends TestCase { - /** @var \OCA\Files_Sharing\External\Scanner */ - protected $scanner; - /** @var \OCA\Files_Sharing\External\Storage|\PHPUnit_Framework_MockObject_MockObject */ - protected $storage; - /** @var \OC\Files\Cache\Cache|\PHPUnit_Framework_MockObject_MockObject */ - protected $cache; - - protected function setUp() { - parent::setUp(); - - $this->storage = $this->getMockBuilder('\OCA\Files_Sharing\External\Storage') - ->disableOriginalConstructor() - ->getMock(); - $this->cache = $this->getMockBuilder('\OC\Files\Cache\Cache') - ->disableOriginalConstructor() - ->getMock(); - $this->storage->expects($this->any()) - ->method('getCache') - ->willReturn($this->cache); - - $this->scanner = new Scanner($this->storage); - } - - public function testScanAll() { - $this->storage->expects($this->any()) - ->method('getShareInfo') - ->willReturn(['status' => 'success', 'data' => []]); - - // FIXME add real tests, we are currently only checking for - // Declaration of OCA\Files_Sharing\External\Scanner::*() should be - // compatible with OC\Files\Cache\Scanner::*() - $this->scanner->scanAll(); - $this->assertTrue(true); - } - - public function testScan() { - $this->storage->expects($this->any()) - ->method('getShareInfo') - ->willReturn(['status' => 'success', 'data' => []]); - - // FIXME add real tests, we are currently only checking for - // Declaration of OCA\Files_Sharing\External\Scanner::*() should be - // compatible with OC\Files\Cache\Scanner::*() - $this->scanner->scan('test', Scanner::SCAN_RECURSIVE); - $this->assertTrue(true); - } - - public function testScanFile() { - // FIXME add real tests, we are currently only checking for - // Declaration of OCA\Files_Sharing\External\Scanner::*() should be - // compatible with OC\Files\Cache\Scanner::*() - $this->scanner->scanFile('test', Scanner::SCAN_RECURSIVE); - $this->assertTrue(true); - } -} diff --git a/lib/private/Files/Storage/DAV.php b/lib/private/Files/Storage/DAV.php index dd987f2c202e..36b39cfbfe37 100644 --- a/lib/private/Files/Storage/DAV.php +++ b/lib/private/Files/Storage/DAV.php @@ -273,7 +273,7 @@ protected function propfind($path) { ); $this->statCache->set($path, $response); } catch (ClientHttpException $e) { - if ($e->getHttpStatus() === 404) { + if ($e->getHttpStatus() === Http::STATUS_NOT_FOUND) { $this->statCache->clear($path . '/'); $this->statCache->set($path, false); return false; @@ -352,7 +352,7 @@ public function fopen($path, $mode) { ]); } catch (RequestException $e) { if ($e->getResponse() instanceof ResponseInterface - && $e->getResponse()->getStatusCode() === 404) { + && $e->getResponse()->getStatusCode() === Http::STATUS_NOT_FOUND) { return false; } else { throw $e; @@ -656,7 +656,7 @@ private function simpleResponse($method, $path, $body, $expected) { $response = $this->client->request($method, $this->encodePath($path), $body); return $response['statusCode'] == $expected; } catch (ClientHttpException $e) { - if ($e->getHttpStatus() === 404 && $method === 'DELETE') { + if ($e->getHttpStatus() === Http::STATUS_NOT_FOUND && $method === 'DELETE') { $this->statCache->clear($path . '/'); $this->statCache->set($path, false); return false; @@ -769,7 +769,7 @@ public function hasUpdated($path, $time) { if ($response === false) { if ($path === '') { // if root is gone it means the storage is not available - throw new StorageNotAvailableException(get_class($e) . ': ' . $e->getMessage()); + throw new StorageNotAvailableException('remote root vanished'); } return false; }