diff options
author | Vincent Petry <pvince81@owncloud.com> | 2015-01-20 19:45:32 +0100 |
---|---|---|
committer | Vincent Petry <pvince81@owncloud.com> | 2015-01-26 13:59:49 +0100 |
commit | f6e644b43fe3c33ba298ee34a73536c85cc92b4a (patch) | |
tree | 7e8fe8eaa51f56765d6147f37a91fad9a1b325d0 /apps | |
parent | dc4ceda2f5d1c8007ffd9b5cacbd794f06b1957d (diff) | |
download | nextcloud-server-f6e644b43fe3c33ba298ee34a73536c85cc92b4a.tar.gz nextcloud-server-f6e644b43fe3c33ba298ee34a73536c85cc92b4a.zip |
Catch storage exception in scanner for remote shares
Whenever an exception occurs during scan of a remote share, the share is
checked for availability. If the storage is gone, it will be removed
automatically.
Also, getDirectoryContent() will now skip unavailable storages.
Diffstat (limited to 'apps')
-rw-r--r-- | apps/files_sharing/ajax/external.php | 58 | ||||
-rw-r--r-- | apps/files_sharing/js/external.js | 2 | ||||
-rw-r--r-- | apps/files_sharing/lib/external/scanner.php | 53 | ||||
-rw-r--r-- | apps/files_sharing/lib/external/storage.php | 56 |
4 files changed, 144 insertions, 25 deletions
diff --git a/apps/files_sharing/ajax/external.php b/apps/files_sharing/ajax/external.php index 1a709eda07c..3d6d589aff8 100644 --- a/apps/files_sharing/ajax/external.php +++ b/apps/files_sharing/ajax/external.php @@ -42,20 +42,70 @@ $name = OCP\Files::buildNotExistingFileName('/', $name); // check for ssl cert if (substr($remote, 0, 5) === 'https' and !OC_Util::getUrlContent($remote)) { - \OCP\JSON::error(array('data' => array('message' => $l->t("Invalid or untrusted SSL certificate")))); + \OCP\JSON::error(array('data' => array('message' => $l->t('Invalid or untrusted SSL certificate')))); exit; } else { $mount = $externalManager->addShare($remote, $token, $password, $name, $owner, true); + /** * @var \OCA\Files_Sharing\External\Storage $storage */ $storage = $mount->getStorage(); + try { + // check if storage exists + $storage->checkStorageAvailability(); + } catch (\OCP\Files\StorageInvalidException $e) { + // note: checkStorageAvailability will already remove the invalid share + \OCP\Util::writeLog( + 'files_sharing', + 'Invalid remote storage: ' . get_class($e) . ': ' . $e->getMessage(), + \OCP\Util::DEBUG + ); + \OCP\JSON::error( + array( + 'data' => array( + 'message' => $l->t('Could not authenticate to remote share, password might be wrong') + ) + ) + ); + exit(); + } catch (\Exception $e) { + \OCP\Util::writeLog( + 'files_sharing', + 'Invalid remote storage: ' . get_class($e) . ': ' . $e->getMessage(), + \OCP\Util::DEBUG + ); + $externalManager->removeShare($mount->getMountPoint()); + \OCP\JSON::error(array('data' => array('message' => $l->t('Storage not valid')))); + throw new \OCP\Files\StorageNotAvailableException(get_class($e).': '.$e->getMessage()); + } $result = $storage->file_exists(''); if ($result) { - $storage->getScanner()->scanAll(); - \OCP\JSON::success(); + 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(array('data' => array('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(array('data' => array('message' => $l->t('Couldn\'t add remote share')))); + } } else { $externalManager->removeShare($mount->getMountPoint()); - \OCP\JSON::error(array('data' => array('message' => $l->t("Couldn't add remote share")))); + \OCP\Util::writeLog( + 'files_sharing', + 'Couldn\'t add remote share', + \OCP\Util::DEBUG + ); + \OCP\JSON::error(array('data' => array('message' => $l->t('Couldn\'t add remote share')))); } } diff --git a/apps/files_sharing/js/external.js b/apps/files_sharing/js/external.js index 31407f28ffd..85a9159fa69 100644 --- a/apps/files_sharing/js/external.js +++ b/apps/files_sharing/js/external.js @@ -95,7 +95,7 @@ name: share.name, password: password}, function(result) { if (result.status === 'error') { - OC.Notification.show(result.data.message); + OC.Notification.showTemporary(result.data.message); } else { fileList.reload(); } diff --git a/apps/files_sharing/lib/external/scanner.php b/apps/files_sharing/lib/external/scanner.php index 4e61e0c4ccb..b45a8942e96 100644 --- a/apps/files_sharing/lib/external/scanner.php +++ b/apps/files_sharing/lib/external/scanner.php @@ -8,6 +8,11 @@ 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 @@ -18,12 +23,56 @@ class Scanner extends \OC\Files\Cache\Scanner { $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 + * @return array an array of metadata of the scanned file + */ + public function scanFile($file, $reuseExisting = 0) { + 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. + */ public function scanAll() { - $data = $this->storage->getShareInfo(); + 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'); + throw new \Exception( + 'Error while scanning remote share: "' . + $this->storage->getRemote() . '"' + ); } } diff --git a/apps/files_sharing/lib/external/storage.php b/apps/files_sharing/lib/external/storage.php index 0d41176e45a..d5b1b1df440 100644 --- a/apps/files_sharing/lib/external/storage.php +++ b/apps/files_sharing/lib/external/storage.php @@ -142,27 +142,47 @@ class Storage extends DAV implements ISharedStorage { $this->updateChecked = true; try { return parent::hasUpdated('', $time); + } catch (StorageInvalidException $e) { + // check if it needs to be removed + $this->checkStorageAvailability(); + throw $e; } catch (StorageNotAvailableException $e) { - // see if we can find out why the share is unavailable\ - try { - $this->getShareInfo(); - } catch (NotFoundException $shareException) { - // 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 $e; - } - } catch (\Exception $shareException) { - // todo, maybe handle 403 better and ask the user for a new password + // check if it needs to be removed or just temp unavailable + $this->checkStorageAvailability(); + throw $e; + } + } + + /** + * Check whether this storage is permanently or temporarily + * unavailable + * + * @throws \OCP\Files\StorageNotAvailableException + * @throws \OCP\Files\StorageInvalidException + */ + 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 $e; } + } catch (ForbiddenException $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 (\Exception $e) { throw $e; } } |