summaryrefslogtreecommitdiffstats
path: root/lib/private
diff options
context:
space:
mode:
Diffstat (limited to 'lib/private')
-rw-r--r--lib/private/config.php4
-rw-r--r--lib/private/db/adapteroci8.php3
-rw-r--r--lib/private/db/connection.php3
-rw-r--r--lib/private/files/cache/cache.php16
-rw-r--r--lib/private/files/cache/changepropagator.php24
-rw-r--r--lib/private/files/cache/propagator.php66
-rw-r--r--lib/private/files/cache/updater.php168
-rw-r--r--lib/private/files/fileinfo.php36
-rw-r--r--lib/private/files/objectstore/objectstorestorage.php2
-rw-r--r--lib/private/files/storage/common.php30
-rw-r--r--lib/private/files/storage/dav.php9
-rw-r--r--lib/private/files/storage/storage.php16
-rw-r--r--lib/private/files/storage/wrapper/wrapper.php14
-rw-r--r--lib/private/files/stream/encryption.php4
-rw-r--r--lib/private/files/view.php236
-rw-r--r--lib/private/helper.php52
-rw-r--r--lib/private/installer.php2
-rw-r--r--lib/private/notification/inotification.php8
-rw-r--r--lib/private/notification/notification.php16
-rw-r--r--lib/private/share/share.php22
-rw-r--r--lib/private/share20/defaultshareprovider.php122
-rw-r--r--lib/private/share20/ishare.php2
-rw-r--r--lib/private/share20/ishareprovider.php25
-rw-r--r--lib/private/share20/manager.php134
-rw-r--r--lib/private/share20/share.php4
-rw-r--r--lib/private/template/functions.php4
-rw-r--r--lib/private/util.php11
27 files changed, 584 insertions, 449 deletions
diff --git a/lib/private/config.php b/lib/private/config.php
index 3ad800a00be..94b4fd56daa 100644
--- a/lib/private/config.php
+++ b/lib/private/config.php
@@ -234,7 +234,9 @@ class Config {
// File does not exist, this can happen when doing a fresh install
if(!is_resource ($filePointer)) {
- $url = \OC_Helper::linkToDocs('admin-dir_permissions');
+ // TODO fix this via DI once it is very clear that this doesn't cause side effects due to initialization order
+ // currently this breaks app routes but also could have other side effects especially during setup and exception handling
+ $url = \OC::$server->getURLGenerator()->linkToDocs('admin-dir_permissions');
throw new HintException(
"Can't write into config directory!",
'This can usually be fixed by '
diff --git a/lib/private/db/adapteroci8.php b/lib/private/db/adapteroci8.php
index 6e7857e6620..76c265bc178 100644
--- a/lib/private/db/adapteroci8.php
+++ b/lib/private/db/adapteroci8.php
@@ -26,6 +26,9 @@ namespace OC\DB;
class AdapterOCI8 extends Adapter {
public function lastInsertId($table) {
+ if (is_null($table)) {
+ throw new \InvalidArgumentException('Oracle requires a table name to be passed into lastInsertId()');
+ }
if ($table !== null) {
$suffix = '_SEQ';
$table = '"' . $table . $suffix . '"';
diff --git a/lib/private/db/connection.php b/lib/private/db/connection.php
index 1b86d3d383a..85b1b7cd5ea 100644
--- a/lib/private/db/connection.php
+++ b/lib/private/db/connection.php
@@ -214,8 +214,7 @@ class Connection extends \Doctrine\DBAL\Connection implements IDBConnection {
* @param string $seqName Name of the sequence object from which the ID should be returned.
* @return string A string representation of the last inserted ID.
*/
- public function lastInsertId($seqName = null)
- {
+ public function lastInsertId($seqName = null) {
if ($seqName) {
$seqName = $this->replaceTablePrefix($seqName);
}
diff --git a/lib/private/files/cache/cache.php b/lib/private/files/cache/cache.php
index 40477243324..e6110c1925d 100644
--- a/lib/private/files/cache/cache.php
+++ b/lib/private/files/cache/cache.php
@@ -160,6 +160,7 @@ class Cache {
} else {
//fix types
$data['fileid'] = (int)$data['fileid'];
+ $data['parent'] = (int)$data['parent'];
$data['size'] = 0 + $data['size'];
$data['mtime'] = (int)$data['mtime'];
$data['storage_mtime'] = (int)$data['storage_mtime'];
@@ -391,12 +392,17 @@ class Cache {
if ($file === '') {
return -1;
} else {
- $parent = dirname($file);
- if ($parent === '.') {
- $parent = '';
- }
- return $this->getId($parent);
+ $parent = $this->getParentPath($file);
+ return (int) $this->getId($parent);
+ }
+ }
+
+ private function getParentPath($path) {
+ $parent = dirname($path);
+ if ($parent === '.') {
+ $parent = '';
}
+ return $parent;
}
/**
diff --git a/lib/private/files/cache/changepropagator.php b/lib/private/files/cache/changepropagator.php
index 9696a82257e..2a48eb13c59 100644
--- a/lib/private/files/cache/changepropagator.php
+++ b/lib/private/files/cache/changepropagator.php
@@ -22,6 +22,7 @@
namespace OC\Files\Cache;
+use OC\Files\Filesystem;
use OC\Hooks\BasicEmitter;
/**
@@ -61,23 +62,30 @@ class ChangePropagator extends BasicEmitter {
* @param int $time (optional) the mtime to set for the folders, if not set the current time is used
*/
public function propagateChanges($time = null) {
- $parents = $this->getAllParents();
- $this->changedFiles = array();
+ $changes = $this->getChanges();
+ $this->changedFiles = [];
if (!$time) {
$time = time();
}
- foreach ($parents as $parent) {
+ foreach ($changes as $change) {
/**
* @var \OC\Files\Storage\Storage $storage
* @var string $internalPath
*/
- list($storage, $internalPath) = $this->view->resolvePath($parent);
+ $absolutePath = $this->view->getAbsolutePath($change);
+ $mount = $this->view->getMount($change);
+ $storage = $mount->getStorage();
+ $internalPath = $mount->getInternalPath($absolutePath);
if ($storage) {
- $cache = $storage->getCache();
- $entry = $cache->get($internalPath);
- $cache->update($entry['fileid'], array('mtime' => max($time, $entry['mtime']), 'etag' => $storage->getETag($internalPath)));
- $this->emit('\OC\Files', 'propagate', [$parent, $entry]);
+ $propagator = $storage->getPropagator();
+ $propagatedEntries = $propagator->propagateChange($internalPath, $time);
+
+ foreach ($propagatedEntries as $entry) {
+ $absolutePath = Filesystem::normalizePath($mount->getMountPoint() . '/' . $entry['path']);
+ $relativePath = $this->view->getRelativePath($absolutePath);
+ $this->emit('\OC\Files', 'propagate', [$relativePath, $entry]);
+ }
}
}
}
diff --git a/lib/private/files/cache/propagator.php b/lib/private/files/cache/propagator.php
new file mode 100644
index 00000000000..bd11cef5990
--- /dev/null
+++ b/lib/private/files/cache/propagator.php
@@ -0,0 +1,66 @@
+<?php
+/**
+ * @author Robin Appelman <icewind@owncloud.com>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @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 <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OC\Files\Cache;
+
+/**
+ * Propagate etags and mtimes within the storage
+ */
+class Propagator {
+ /**
+ * @var \OC\Files\Storage\Storage
+ */
+ protected $storage;
+
+ /**
+ * @param \OC\Files\Storage\Storage $storage
+ */
+ public function __construct(\OC\Files\Storage\Storage $storage) {
+ $this->storage = $storage;
+ }
+
+
+ /**
+ * @param string $internalPath
+ * @param int $time
+ * @return array[] all propagated entries
+ */
+ public function propagateChange($internalPath, $time) {
+ $cache = $this->storage->getCache($internalPath);
+
+ $parentId = $cache->getParentId($internalPath);
+ $propagatedEntries = [];
+ while ($parentId !== -1) {
+ $entry = $cache->get($parentId);
+ $propagatedEntries[] = $entry;
+ if (!$entry) {
+ return $propagatedEntries;
+ }
+ $mtime = max($time, $entry['mtime']);
+
+ $cache->update($parentId, ['mtime' => $mtime, 'etag' => $this->storage->getETag($entry['path'])]);
+
+ $parentId = $entry['parent'];
+ }
+
+ return $propagatedEntries;
+ }
+}
diff --git a/lib/private/files/cache/updater.php b/lib/private/files/cache/updater.php
index 85dcc8589de..4d11fa3a251 100644
--- a/lib/private/files/cache/updater.php
+++ b/lib/private/files/cache/updater.php
@@ -29,8 +29,6 @@ namespace OC\Files\Cache;
/**
* Update the cache and propagate changes
*
- * Unlike most other classes an Updater is not related to a specific storage but handles updates for all storages in a users filesystem.
- * This is needed because the propagation of mtime and etags need to cross storage boundaries
*/
class Updater {
/**
@@ -39,21 +37,33 @@ class Updater {
protected $enabled = true;
/**
- * @var \OC\Files\View
+ * @var \OC\Files\Storage\Storage
*/
- protected $view;
+ protected $storage;
/**
- * @var \OC\Files\Cache\ChangePropagator
+ * @var \OC\Files\Cache\Propagator
*/
protected $propagator;
/**
- * @param \OC\Files\View $view the view the updater works on, usually the view of the logged in user
+ * @var Scanner
*/
- public function __construct($view) {
- $this->view = $view;
- $this->propagator = new ChangePropagator($view);
+ protected $scanner;
+
+ /**
+ * @var Cache
+ */
+ protected $cache;
+
+ /**
+ * @param \OC\Files\Storage\Storage $storage
+ */
+ public function __construct(\OC\Files\Storage\Storage $storage) {
+ $this->storage = $storage;
+ $this->propagator = $storage->getPropagator();
+ $this->scanner = $storage->getScanner();
+ $this->cache = $storage->getCache();
}
/**
@@ -73,7 +83,7 @@ class Updater {
/**
* Get the propagator for etags and mtime for the view the updater works on
*
- * @return ChangePropagator
+ * @return Propagator
*/
public function getPropagator() {
return $this->propagator;
@@ -89,8 +99,7 @@ class Updater {
if (Scanner::isPartialFile($path)) {
return;
}
- $this->propagator->addChange($path);
- $this->propagator->propagateChanges($time);
+ $this->propagator->propagateChange($path, $time);
}
/**
@@ -103,20 +112,14 @@ class Updater {
if (!$this->enabled or Scanner::isPartialFile($path)) {
return;
}
- /**
- * @var \OC\Files\Storage\Storage $storage
- * @var string $internalPath
- */
- list($storage, $internalPath) = $this->view->resolvePath($path);
- if ($storage) {
- $this->propagator->addChange($path);
- $cache = $storage->getCache($internalPath);
- $scanner = $storage->getScanner($internalPath);
- $data = $scanner->scan($internalPath, Scanner::SCAN_SHALLOW, -1, false);
- $this->correctParentStorageMtime($storage, $internalPath);
- $cache->correctFolderSize($internalPath, $data);
- $this->propagator->propagateChanges($time);
+ if (is_null($time)) {
+ $time = time();
}
+
+ $data = $this->scanner->scan($path, Scanner::SCAN_SHALLOW, -1, false);
+ $this->correctParentStorageMtime($path);
+ $this->cache->correctFolderSize($path, $data);
+ $this->propagator->propagateChange($path, $time);
}
/**
@@ -128,87 +131,71 @@ class Updater {
if (!$this->enabled or Scanner::isPartialFile($path)) {
return;
}
- /**
- * @var \OC\Files\Storage\Storage $storage
- * @var string $internalPath
- */
- list($storage, $internalPath) = $this->view->resolvePath($path);
- if ($storage) {
- $parent = dirname($internalPath);
- if ($parent === '.') {
- $parent = '';
- }
- $this->propagator->addChange($path);
- $cache = $storage->getCache($internalPath);
- $cache->remove($internalPath);
- $cache->correctFolderSize($parent);
- $this->correctParentStorageMtime($storage, $internalPath);
- $this->propagator->propagateChanges();
+
+ $parent = dirname($path);
+ if ($parent === '.') {
+ $parent = '';
}
+
+ $this->cache->remove($path);
+ $this->cache->correctFolderSize($parent);
+ $this->correctParentStorageMtime($path);
+ $this->propagator->propagateChange($path, time());
}
/**
* Rename a file or folder in the cache and update the size, etag and mtime of the parent folders
*
+ * @param \OC\Files\Storage\Storage $sourceStorage
* @param string $source
* @param string $target
*/
- public function rename($source, $target) {
+ public function renameFromStorage(\OC\Files\Storage\Storage $sourceStorage, $source, $target) {
if (!$this->enabled or Scanner::isPartialFile($source) or Scanner::isPartialFile($target)) {
return;
}
- /**
- * @var \OC\Files\Storage\Storage $sourceStorage
- * @var \OC\Files\Storage\Storage $targetStorage
- * @var string $sourceInternalPath
- * @var string $targetInternalPath
- */
- list($sourceStorage, $sourceInternalPath) = $this->view->resolvePath($source);
- // if it's a moved mountpoint we dont need to do anything
- if ($sourceInternalPath === '') {
- return;
- }
- list($targetStorage, $targetInternalPath) = $this->view->resolvePath($target);
-
- if ($sourceStorage && $targetStorage) {
- $targetCache = $targetStorage->getCache($sourceInternalPath);
- if ($sourceStorage->getCache($sourceInternalPath)->inCache($sourceInternalPath)) {
- if ($targetCache->inCache($targetInternalPath)) {
- $targetCache->remove($targetInternalPath);
- }
- if ($sourceStorage === $targetStorage) {
- $targetCache->move($sourceInternalPath, $targetInternalPath);
- } else {
- $targetCache->moveFromCache($sourceStorage->getCache(), $sourceInternalPath, $targetInternalPath);
- }
+
+ $time = time();
+
+ $sourceCache = $sourceStorage->getCache($source);
+ $sourceUpdater = $sourceStorage->getUpdater();
+ $sourcePropagator = $sourceStorage->getPropagator();
+
+ if ($sourceCache->inCache($source)) {
+ if ($this->cache->inCache($target)) {
+ $this->cache->remove($target);
}
- if (pathinfo($sourceInternalPath, PATHINFO_EXTENSION) !== pathinfo($targetInternalPath, PATHINFO_EXTENSION)) {
- // handle mime type change
- $mimeType = $targetStorage->getMimeType($targetInternalPath);
- $fileId = $targetCache->getId($targetInternalPath);
- $targetCache->update($fileId, array('mimetype' => $mimeType));
+ if ($sourceStorage === $this->storage) {
+ $this->cache->move($source, $target);
+ } else {
+ $this->cache->moveFromCache($sourceCache, $source, $target);
}
+ }
- $targetCache->correctFolderSize($sourceInternalPath);
- $targetCache->correctFolderSize($targetInternalPath);
- $this->correctParentStorageMtime($sourceStorage, $sourceInternalPath);
- $this->correctParentStorageMtime($targetStorage, $targetInternalPath);
- $this->updateStorageMTimeOnly($targetStorage, $targetInternalPath);
- $this->propagator->addChange($source);
- $this->propagator->addChange($target);
- $this->propagator->propagateChanges();
+ if (pathinfo($source, PATHINFO_EXTENSION) !== pathinfo($target, PATHINFO_EXTENSION)) {
+ // handle mime type change
+ $mimeType = $this->storage->getMimeType($target);
+ $fileId = $this->cache->getId($target);
+ $this->cache->update($fileId, ['mimetype' => $mimeType]);
}
+
+ $sourceCache->correctFolderSize($source);
+ $this->cache->correctFolderSize($target);
+ $sourceUpdater->correctParentStorageMtime($source);
+ $this->correctParentStorageMtime($target);
+ $this->updateStorageMTimeOnly($target);
+ $sourcePropagator->propagateChange($source, $time);
+ $this->propagator->propagateChange($target, $time);
}
- private function updateStorageMTimeOnly($storage, $internalPath) {
- $cache = $storage->getCache();
- $fileId = $cache->getId($internalPath);
+ private function updateStorageMTimeOnly($internalPath) {
+ $fileId = $this->cache->getId($internalPath);
if ($fileId !== -1) {
- $cache->update(
+ $this->cache->update(
$fileId, [
'mtime' => null, // this magic tells it to not overwrite mtime
- 'storage_mtime' => $storage->filemtime($internalPath)
+ 'storage_mtime' => $this->storage->filemtime($internalPath)
]
);
}
@@ -217,20 +204,13 @@ class Updater {
/**
* update the storage_mtime of the direct parent in the cache to the mtime from the storage
*
- * @param \OC\Files\Storage\Storage $storage
* @param string $internalPath
*/
- private function correctParentStorageMtime($storage, $internalPath) {
- $cache = $storage->getCache();
- $parentId = $cache->getParentId($internalPath);
+ public function correctParentStorageMtime($internalPath) {
+ $parentId = $this->cache->getParentId($internalPath);
$parent = dirname($internalPath);
if ($parentId != -1) {
- $cache->update($parentId, array('storage_mtime' => $storage->filemtime($parent)));
+ $this->cache->update($parentId, array('storage_mtime' => $this->storage->filemtime($parent)));
}
}
-
- public function __destruct() {
- // propagate any leftover changes
- $this->propagator->propagateChanges();
- }
}
diff --git a/lib/private/files/fileinfo.php b/lib/private/files/fileinfo.php
index bb810dd45ed..5b5e8697004 100644
--- a/lib/private/files/fileinfo.php
+++ b/lib/private/files/fileinfo.php
@@ -62,6 +62,11 @@ class FileInfo implements \OCP\Files\FileInfo, \ArrayAccess {
private $owner;
/**
+ * @var string[]
+ */
+ private $childEtags = [];
+
+ /**
* @param string|boolean $path
* @param Storage\Storage $storage
* @param string $internalPath
@@ -93,6 +98,8 @@ class FileInfo implements \OCP\Files\FileInfo, \ArrayAccess {
public function offsetGet($offset) {
if ($offset === 'type') {
return $this->getType();
+ } else if ($offset === 'etag') {
+ return $this->getEtag();
} elseif (isset($this->data[$offset])) {
return $this->data[$offset];
} else {
@@ -153,7 +160,12 @@ class FileInfo implements \OCP\Files\FileInfo, \ArrayAccess {
* @return string
*/
public function getEtag() {
- return $this->data['etag'];
+ if (count($this->childEtags) > 0) {
+ $combinedEtag = $this->data['etag'] . '::' . implode('::', $this->childEtags);
+ return md5($combinedEtag);
+ } else {
+ return $this->data['etag'];
+ }
}
/**
@@ -285,4 +297,26 @@ class FileInfo implements \OCP\Files\FileInfo, \ArrayAccess {
public function getOwner() {
return $this->owner;
}
+
+ /**
+ * Add a cache entry which is the child of this folder
+ *
+ * Sets the size, etag and size to for cross-storage childs
+ *
+ * @param array $data cache entry for the child
+ * @param string $entryPath full path of the child entry
+ */
+ public function addSubEntry($data, $entryPath) {
+ $this->data['size'] += isset($data['size']) ? $data['size'] : 0;
+ if (isset($data['mtime'])) {
+ $this->data['mtime'] = max($this->data['mtime'], $data['mtime']);
+ }
+ if (isset($data['etag'])) {
+ // prefix the etag with the relative path of the subentry to propagate etag on mount moves
+ $relativeEntryPath = substr($entryPath, strlen($this->getPath()));
+ // attach the permissions to propagate etag on permision changes of submounts
+ $permissions = isset($data['permissions']) ? $data['permissions'] : 0;
+ $this->childEtags[] = $relativeEntryPath . '/' . $data['etag'] . $permissions;
+ }
+ }
}
diff --git a/lib/private/files/objectstore/objectstorestorage.php b/lib/private/files/objectstore/objectstorestorage.php
index e108d7662d4..5ec05a3529e 100644
--- a/lib/private/files/objectstore/objectstorestorage.php
+++ b/lib/private/files/objectstore/objectstorestorage.php
@@ -370,7 +370,7 @@ class ObjectStoreStorage extends \OC\Files\Storage\Common {
$stat['size'] = filesize($tmpFile);
$stat['mtime'] = $mTime;
$stat['storage_mtime'] = $mTime;
- $stat['mimetype'] = \OC_Helper::getMimeType($tmpFile);
+ $stat['mimetype'] = \OC::$server->getMimeTypeDetector()->detect($tmpFile);
$stat['etag'] = $this->getETag($path);
$fileId = $this->getCache()->put($path, $stat);
diff --git a/lib/private/files/storage/common.php b/lib/private/files/storage/common.php
index 8e4958a930d..0cd67e343ff 100644
--- a/lib/private/files/storage/common.php
+++ b/lib/private/files/storage/common.php
@@ -37,7 +37,9 @@
namespace OC\Files\Storage;
use OC\Files\Cache\Cache;
+use OC\Files\Cache\Propagator;
use OC\Files\Cache\Scanner;
+use OC\Files\Cache\Updater;
use OC\Files\Filesystem;
use OC\Files\Cache\Watcher;
use OCP\Files\FileNameTooLongException;
@@ -64,7 +66,9 @@ abstract class Common implements Storage {
protected $cache;
protected $scanner;
protected $watcher;
+ protected $propagator;
protected $storageCache;
+ protected $updater;
protected $mountOptions = [];
@@ -345,6 +349,32 @@ abstract class Common implements Storage {
return $this->watcher;
}
+ /**
+ * get a propagator instance for the cache
+ *
+ * @param \OC\Files\Storage\Storage (optional) the storage to pass to the watcher
+ * @return \OC\Files\Cache\Propagator
+ */
+ public function getPropagator($storage = null) {
+ if (!$storage) {
+ $storage = $this;
+ }
+ if (!isset($this->propagator)) {
+ $this->propagator = new Propagator($storage);
+ }
+ return $this->propagator;
+ }
+
+ public function getUpdater($storage = null) {
+ if (!$storage) {
+ $storage = $this;
+ }
+ if (!isset($this->updater)) {
+ $this->updater = new Updater($storage);
+ }
+ return $this->updater;
+ }
+
public function getStorageCache($storage = null) {
if (!$storage) {
$storage = $this;
diff --git a/lib/private/files/storage/dav.php b/lib/private/files/storage/dav.php
index dcde7b8029b..9147f572461 100644
--- a/lib/private/files/storage/dav.php
+++ b/lib/private/files/storage/dav.php
@@ -47,6 +47,7 @@ use OCP\Files\StorageNotAvailableException;
use OCP\Util;
use Sabre\DAV\Client;
use Sabre\DAV\Exception\NotFound;
+use Sabre\DAV\Xml\Property\ResourceType;
use Sabre\HTTP\ClientException;
use Sabre\HTTP\ClientHttpException;
@@ -137,7 +138,7 @@ class DAV extends Common {
$this->client->setThrowExceptions(true);
if ($this->secure === true && $this->certPath) {
- $this->client->addTrustedCertificates($this->certPath);
+ $this->client->addCurlSetting(CURLOPT_CAINFO, $this->certPath);
}
}
@@ -280,7 +281,8 @@ class DAV extends Common {
$response = $this->propfind($path);
$responseType = array();
if (isset($response["{DAV:}resourcetype"])) {
- $responseType = $response["{DAV:}resourcetype"]->resourceType;
+ /** @var ResourceType[] $response */
+ $responseType = $response["{DAV:}resourcetype"]->getValue();
}
return (count($responseType) > 0 and $responseType[0] == "{DAV:}collection") ? 'dir' : 'file';
} catch (ClientHttpException $e) {
@@ -554,7 +556,8 @@ class DAV extends Common {
$response = $this->propfind($path);
$responseType = array();
if (isset($response["{DAV:}resourcetype"])) {
- $responseType = $response["{DAV:}resourcetype"]->resourceType;
+ /** @var ResourceType[] $response */
+ $responseType = $response["{DAV:}resourcetype"]->getValue();
}
$type = (count($responseType) > 0 and $responseType[0] == "{DAV:}collection") ? 'dir' : 'file';
if ($type == 'dir') {
diff --git a/lib/private/files/storage/storage.php b/lib/private/files/storage/storage.php
index f46ac544b56..fb59752ede1 100644
--- a/lib/private/files/storage/storage.php
+++ b/lib/private/files/storage/storage.php
@@ -68,6 +68,22 @@ interface Storage extends \OCP\Files\Storage {
public function getWatcher($path = '', $storage = null);
/**
+ * get a propagator instance for the cache
+ *
+ * @param \OC\Files\Storage\Storage (optional) the storage to pass to the watcher
+ * @return \OC\Files\Cache\Propagator
+ */
+ public function getPropagator($storage = null);
+
+ /**
+ * get a updater instance for the cache
+ *
+ * @param \OC\Files\Storage\Storage (optional) the storage to pass to the watcher
+ * @return \OC\Files\Cache\Updater
+ */
+ public function getUpdater($storage = null);
+
+ /**
* @return \OC\Files\Cache\Storage
*/
public function getStorageCache();
diff --git a/lib/private/files/storage/wrapper/wrapper.php b/lib/private/files/storage/wrapper/wrapper.php
index 048738170db..81284c7aa69 100644
--- a/lib/private/files/storage/wrapper/wrapper.php
+++ b/lib/private/files/storage/wrapper/wrapper.php
@@ -430,6 +430,20 @@ class Wrapper implements \OC\Files\Storage\Storage {
return $this->storage->getWatcher($path, $storage);
}
+ public function getPropagator($storage = null) {
+ if (!$storage) {
+ $storage = $this;
+ }
+ return $this->storage->getPropagator($storage);
+ }
+
+ public function getUpdater($storage = null) {
+ if (!$storage) {
+ $storage = $this;
+ }
+ return $this->storage->getUpdater($storage);
+ }
+
/**
* @return \OC\Files\Cache\Storage
*/
diff --git a/lib/private/files/stream/encryption.php b/lib/private/files/stream/encryption.php
index 4c328993ef7..585a697c5d1 100644
--- a/lib/private/files/stream/encryption.php
+++ b/lib/private/files/stream/encryption.php
@@ -167,7 +167,7 @@ class Encryption extends Wrapper {
)
));
- return self::wrapSource($source, $mode, $context, 'ocencryption', $wrapper);
+ return self::wrapSource($source, $context, 'ocencryption', $wrapper, $mode);
}
/**
@@ -181,7 +181,7 @@ class Encryption extends Wrapper {
* @return resource
* @throws \BadMethodCallException
*/
- protected static function wrapSource($source, $mode, $context, $protocol, $class) {
+ protected static function wrapSource($source, $context, $protocol, $class, $mode = 'r+') {
try {
stream_wrapper_register($protocol, $class);
if (@rewinddir($source) === false) {
diff --git a/lib/private/files/view.php b/lib/private/files/view.php
index cee4b182425..7854790d0e5 100644
--- a/lib/private/files/view.php
+++ b/lib/private/files/view.php
@@ -46,6 +46,7 @@ namespace OC\Files;
use Icewind\Streams\CallbackWrapper;
use OC\Files\Cache\Updater;
use OC\Files\Mount\MoveableMount;
+use OC\Files\Storage\Storage;
use OC\User\User;
use OCP\Files\FileNameTooLongException;
use OCP\Files\InvalidCharacterInPathException;
@@ -76,9 +77,6 @@ class View {
/** @var string */
private $fakeRoot = '';
- /** @var \OC\Files\Cache\Updater */
- protected $updater;
-
/**
* @var \OCP\Lock\ILockingProvider
*/
@@ -86,6 +84,8 @@ class View {
private $lockingEnabled;
+ private $updaterEnabled = true;
+
/**
* @param string $root
* @throws \Exception If $root contains an invalid path
@@ -99,7 +99,6 @@ class View {
}
$this->fakeRoot = $root;
- $this->updater = new Updater($this);
$this->lockingProvider = \OC::$server->getLockingProvider();
$this->lockingEnabled = !($this->lockingProvider instanceof \OC\Lock\NoopLockingProvider);
}
@@ -286,6 +285,35 @@ class View {
}
}
+ public function disableCacheUpdate() {
+ $this->updaterEnabled = false;
+ }
+
+ public function enableCacheUpdate() {
+ $this->updaterEnabled = true;
+ }
+
+ protected function writeUpdate(Storage $storage, $internalPath, $time = null) {
+ if ($this->updaterEnabled) {
+ if (is_null($time)) {
+ $time = time();
+ }
+ $storage->getUpdater()->update($internalPath, $time);
+ }
+ }
+
+ protected function removeUpdate(Storage $storage, $internalPath) {
+ if ($this->updaterEnabled) {
+ $storage->getUpdater()->remove($internalPath);
+ }
+ }
+
+ protected function renameUpdate(Storage $sourceStorage, Storage $targetStorage, $sourceInternalPath, $targetInternalPath) {
+ if ($this->updaterEnabled) {
+ $targetStorage->getUpdater()->renameFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath);
+ }
+ }
+
/**
* @param string $path
* @return bool|mixed
@@ -569,7 +597,7 @@ class View {
fclose($target);
fclose($data);
- $this->updater->update($path);
+ $this->writeUpdate($storage, $internalPath);
$this->changeLock($path, ILockingProvider::LOCK_SHARED);
@@ -703,14 +731,11 @@ class View {
if ((Cache\Scanner::isPartialFile($path1) && !Cache\Scanner::isPartialFile($path2)) && $result !== false) {
// if it was a rename from a part file to a regular file it was a write and not a rename operation
- $this->updater->update($path2);
+
+ $this->writeUpdate($storage2, $internalPath2);
} else if ($result) {
if ($internalPath1 !== '') { // dont do a cache update for moved mounts
- $this->updater->rename($path1, $path2);
- } else { // only do etag propagation
- $this->getUpdater()->getPropagator()->addChange($path1);
- $this->getUpdater()->getPropagator()->addChange($path2);
- $this->getUpdater()->getPropagator()->propagateChanges();
+ $this->renameUpdate($storage1, $storage2, $internalPath1, $internalPath2);
}
}
@@ -807,7 +832,7 @@ class View {
$result = $storage2->copyFromStorage($storage1, $internalPath1, $internalPath2);
}
- $this->updater->update($path2);
+ $this->writeUpdate($storage2, $internalPath2);
$this->changeLock($path2, ILockingProvider::LOCK_SHARED);
$lockTypePath2 = ILockingProvider::LOCK_SHARED;
@@ -1017,6 +1042,7 @@ class View {
}
$run = $this->runHooks($hooks, $path);
+ /** @var \OC\Files\Storage\Storage $storage */
list($storage, $internalPath) = Filesystem::resolvePath($absolutePath . $postFix);
if ($run and $storage) {
if (in_array('write', $hooks) || in_array('delete', $hooks)) {
@@ -1038,13 +1064,13 @@ class View {
}
if (in_array('delete', $hooks) and $result) {
- $this->updater->remove($path);
+ $this->removeUpdate($storage, $internalPath);
}
if (in_array('write', $hooks) and $operation !== 'fopen') {
- $this->updater->update($path);
+ $this->writeUpdate($storage, $internalPath);
}
if (in_array('touch', $hooks)) {
- $this->updater->update($path, $extraParam);
+ $this->writeUpdate($storage, $internalPath, $extraParam);
}
if ((in_array('write', $hooks) || in_array('delete', $hooks)) && ($operation !== 'fopen' || $result === false)) {
@@ -1179,6 +1205,48 @@ class View {
}
/**
+ * Get file info from cache
+ *
+ * If the file is not in cached it will be scanned
+ * If the file has changed on storage the cache will be updated
+ *
+ * @param \OC\Files\Storage\Storage $storage
+ * @param string $internalPath
+ * @param string $relativePath
+ * @return array|bool
+ */
+ private function getCacheEntry($storage, $internalPath, $relativePath) {
+ $cache = $storage->getCache($internalPath);
+ $data = $cache->get($internalPath);
+ $watcher = $storage->getWatcher($internalPath);
+
+ try {
+ // if the file is not in the cache or needs to be updated, trigger the scanner and reload the data
+ if (!$data || $data['size'] === -1) {
+ $this->lockFile($relativePath, ILockingProvider::LOCK_SHARED);
+ if (!$storage->file_exists($internalPath)) {
+ $this->unlockFile($relativePath, ILockingProvider::LOCK_SHARED);
+ return false;
+ }
+ $scanner = $storage->getScanner($internalPath);
+ $scanner->scan($internalPath, Cache\Scanner::SCAN_SHALLOW);
+ $data = $cache->get($internalPath);
+ $this->unlockFile($relativePath, ILockingProvider::LOCK_SHARED);
+ } else if (!Cache\Scanner::isPartialFile($internalPath) && $watcher->needsUpdate($internalPath, $data)) {
+ $this->lockFile($relativePath, ILockingProvider::LOCK_SHARED);
+ $watcher->update($internalPath, $data);
+ $storage->getPropagator()->propagateChange($internalPath, time());
+ $data = $cache->get($internalPath);
+ $this->unlockFile($relativePath, ILockingProvider::LOCK_SHARED);
+ }
+ } catch (LockedException $e) {
+ // if the file is locked we just use the old cache info
+ }
+
+ return $data;
+ }
+
+ /**
* get the filesystem info
*
* @param string $path
@@ -1189,9 +1257,8 @@ class View {
*/
public function getFileInfo($path, $includeMountPoints = true) {
$this->assertPathLength($path);
- $data = array();
if (!Filesystem::isValidPath($path)) {
- return $data;
+ return false;
}
if (Cache\Scanner::isPartialFile($path)) {
return $this->getPartFileInfo($path);
@@ -1202,48 +1269,27 @@ class View {
$mount = Filesystem::getMountManager()->find($path);
$storage = $mount->getStorage();
$internalPath = $mount->getInternalPath($path);
- $data = null;
if ($storage) {
- $cache = $storage->getCache($internalPath);
+ $data = $this->getCacheEntry($storage, $internalPath, $relativePath);
- $data = $cache->get($internalPath);
- $watcher = $storage->getWatcher($internalPath);
+ if (!is_array($data)) {
+ return false;
+ }
- try {
- // if the file is not in the cache or needs to be updated, trigger the scanner and reload the data
- if (!$data) {
- $this->lockFile($relativePath, ILockingProvider::LOCK_SHARED);
- if (!$storage->file_exists($internalPath)) {
- $this->unlockFile($relativePath, ILockingProvider::LOCK_SHARED);
- return false;
- }
- $scanner = $storage->getScanner($internalPath);
- $scanner->scan($internalPath, Cache\Scanner::SCAN_SHALLOW);
- $data = $cache->get($internalPath);
- $this->unlockFile($relativePath, ILockingProvider::LOCK_SHARED);
- } else if (!Cache\Scanner::isPartialFile($internalPath) && $watcher->needsUpdate($internalPath, $data)) {
- $this->lockFile($relativePath, ILockingProvider::LOCK_SHARED);
- $watcher->update($internalPath, $data);
- $this->updater->propagate($path);
- $data = $cache->get($internalPath);
- $this->unlockFile($relativePath, ILockingProvider::LOCK_SHARED);
- }
- } catch (LockedException $e) {
- // if the file is locked we just use the old cache info
+ if ($mount instanceof MoveableMount && $internalPath === '') {
+ $data['permissions'] |= \OCP\Constants::PERMISSION_DELETE;
}
+ $owner = $this->getUserObjectForOwner($storage->getOwner($internalPath));
+ $info = new FileInfo($path, $storage, $internalPath, $data, $mount, $owner);
+
if ($data and isset($data['fileid'])) {
- // upgrades from oc6 or lower might not have the permissions set in the file cache
- if ($data['permissions'] === 0) {
- $data['permissions'] = $storage->getPermissions($data['path']);
- $cache->update($data['fileid'], array('permissions' => $data['permissions']));
- }
if ($includeMountPoints and $data['mimetype'] === 'httpd/unix-directory') {
//add the sizes of other mount points to the folder
$extOnly = ($includeMountPoints === 'ext');
- $mountPoints = Filesystem::getMountPoints($path);
- foreach ($mountPoints as $mountPoint) {
- $subStorage = Filesystem::getStorage($mountPoint);
+ $mounts = Filesystem::getMountManager()->findIn($path);
+ foreach ($mounts as $mount) {
+ $subStorage = $mount->getStorage();
if ($subStorage) {
// exclude shared storage ?
if ($extOnly && $subStorage instanceof \OC\Files\Storage\Shared) {
@@ -1251,22 +1297,16 @@ class View {
}
$subCache = $subStorage->getCache('');
$rootEntry = $subCache->get('');
- $data['size'] += isset($rootEntry['size']) ? $rootEntry['size'] : 0;
+ $info->addSubEntry($rootEntry, $mount->getMountPoint());
}
}
}
}
- }
- if (!$data) {
- return false;
- }
- if ($mount instanceof MoveableMount && $internalPath === '') {
- $data['permissions'] |= \OCP\Constants::PERMISSION_DELETE;
+ return $info;
}
- $owner = $this->getUserObjectForOwner($storage->getOwner($internalPath));
- return new FileInfo($path, $storage, $internalPath, $data, $mount, $owner);
+ return false;
}
/**
@@ -1278,9 +1318,8 @@ class View {
*/
public function getDirectoryContent($directory, $mimetype_filter = '') {
$this->assertPathLength($directory);
- $result = array();
if (!Filesystem::isValidPath($directory)) {
- return $result;
+ return [];
}
$path = $this->getAbsolutePath($directory);
$path = Filesystem::normalizePath($path);
@@ -1291,50 +1330,25 @@ class View {
$cache = $storage->getCache($internalPath);
$user = \OC_User::getUser();
- /**
- * @var \OC\Files\FileInfo[] $files
- */
- $files = array();
+ $data = $this->getCacheEntry($storage, $internalPath, $directory);
- $data = $cache->get($internalPath);
- $watcher = $storage->getWatcher($internalPath);
- try {
- if (!$data or $data['size'] === -1) {
- $this->lockFile($directory, ILockingProvider::LOCK_SHARED);
- if (!$storage->file_exists($internalPath)) {
- $this->unlockFile($directory, ILockingProvider::LOCK_SHARED);
- return array();
- }
- $scanner = $storage->getScanner($internalPath);
- $scanner->scan($internalPath, Cache\Scanner::SCAN_SHALLOW);
- $data = $cache->get($internalPath);
- $this->unlockFile($directory, ILockingProvider::LOCK_SHARED);
- } else if ($watcher->needsUpdate($internalPath, $data)) {
- $this->lockFile($directory, ILockingProvider::LOCK_SHARED);
- $watcher->update($internalPath, $data);
- $this->updater->propagate($path);
- $data = $cache->get($internalPath);
- $this->unlockFile($directory, ILockingProvider::LOCK_SHARED);
- }
- } catch (LockedException $e) {
- // if the file is locked we just use the old cache info
+ if (!is_array($data) || !isset($data['fileid'])) {
+ return [];
}
$folderId = $data['fileid'];
$contents = $cache->getFolderContentsById($folderId); //TODO: mimetype_filter
- foreach ($contents as $content) {
- if ($content['permissions'] === 0) {
- $content['permissions'] = $storage->getPermissions($content['path']);
- $cache->update($content['fileid'], array('permissions' => $content['permissions']));
- }
- // if sharing was disabled for the user we remove the share permissions
+ /**
+ * @var \OC\Files\FileInfo[] $files
+ */
+ $files = array_map(function (array $content) use ($path, $storage, $mount) {
if (\OCP\Util::isSharingDisabledForUser()) {
$content['permissions'] = $content['permissions'] & ~\OCP\Constants::PERMISSION_SHARE;
}
$owner = $this->getUserObjectForOwner($storage->getOwner($content['path']));
- $files[] = new FileInfo($path . '/' . $content['name'], $storage, $content['path'], $content, $mount, $owner);
- }
+ return new FileInfo($path . '/' . $content['name'], $storage, $content['path'], $content, $mount, $owner);
+ }, $contents);
//add a folder for any mountpoint in this directory and add the sizes of other mountpoints to the folders
$mounts = Filesystem::getMountManager()->findIn($path);
@@ -1345,7 +1359,8 @@ class View {
if ($subStorage) {
$subCache = $subStorage->getCache('');
- if ($subCache->getStatus('') === Cache\Cache::NOT_FOUND) {
+ $rootEntry = $subCache->get('');
+ if (!$rootEntry) {
$subScanner = $subStorage->getScanner('');
try {
$subScanner->scanFile('');
@@ -1363,17 +1378,17 @@ class View {
);
continue;
}
+ $rootEntry = $subCache->get('');
}
- $rootEntry = $subCache->get('');
if ($rootEntry) {
$relativePath = trim(substr($mountPoint, $dirLength), '/');
if ($pos = strpos($relativePath, '/')) {
//mountpoint inside subfolder add size to the correct folder
$entryName = substr($relativePath, 0, $pos);
foreach ($files as &$entry) {
- if ($entry['name'] === $entryName) {
- $entry['size'] += $rootEntry['size'];
+ if ($entry->getName() === $entryName) {
+ $entry->addSubEntry($rootEntry, $mountPoint);
}
}
} else { //mountpoint in this folder, add an entry for it
@@ -1410,23 +1425,23 @@ class View {
}
if ($mimetype_filter) {
- foreach ($files as $file) {
+ $files = array_filter($files, function (FileInfo $file) use ($mimetype_filter) {
if (strpos($mimetype_filter, '/')) {
- if ($file['mimetype'] === $mimetype_filter) {
+ if ($file->getMimetype() === $mimetype_filter) {
$result[] = $file;
}
} else {
- if ($file['mimepart'] === $mimetype_filter) {
+ if ($file->getMimePart() === $mimetype_filter) {
$result[] = $file;
}
}
- }
- } else {
- $result = $files;
+ });
}
- }
- return $result;
+ return $files;
+ } else {
+ return [];
+ }
}
/**
@@ -1707,13 +1722,6 @@ class View {
}
/**
- * @return Updater
- */
- public function getUpdater() {
- return $this->updater;
- }
-
- /**
* @param string $path
* @param string $fileName
* @throws InvalidPathException
diff --git a/lib/private/helper.php b/lib/private/helper.php
index ee2f520fe2b..fb8e38cc26e 100644
--- a/lib/private/helper.php
+++ b/lib/private/helper.php
@@ -82,15 +82,6 @@ class OC_Helper {
}
/**
- * @param string $key
- * @return string url to the online documentation
- * @deprecated Use \OC::$server->getURLGenerator()->linkToDocs($key)
- */
- public static function linkToDocs($key) {
- return OC::$server->getURLGenerator()->linkToDocs($key);
- }
-
- /**
* Creates an absolute url
* @param string $app app
* @param string $file file
@@ -402,18 +393,6 @@ class OC_Helper {
}
/**
- * get the mimetype form a local file
- *
- * @param string $path
- * @return string
- * does NOT work for ownClouds filesystem, use OC_FileSystem::getMimeType instead
- * @deprecated 8.2.0 Use \OC::$server->getMimeTypeDetector()->detect($path)
- */
- static function getMimeType($path) {
- return \OC::$server->getMimeTypeDetector()->detect($path);
- }
-
- /**
* Get a secure mimetype that won't expose potential XSS.
*
* @param string $mimeType
@@ -645,37 +624,6 @@ class OC_Helper {
}
/**
- * replaces a copy of string delimited by the start and (optionally) length parameters with the string given in replacement.
- *
- * @param string $string
- * @param string $replacement The replacement string.
- * @param int $start If start is positive, the replacing will begin at the start'th offset into string. If start is negative, the replacing will begin at the start'th character from the end of string.
- * @param int $length Length of the part to be replaced
- * @param string $encoding The encoding parameter is the character encoding. Defaults to UTF-8
- * @return string
- * @deprecated 8.2.0 Use substr_replace() instead.
- */
- public static function mb_substr_replace($string, $replacement, $start, $length = 0, $encoding = 'UTF-8') {
- return substr_replace($string, $replacement, $start, $length);
- }
-
- /**
- * Replace all occurrences of the search string with the replacement string
- *
- * @param string $search The value being searched for, otherwise known as the needle.
- * @param string $replace The replacement
- * @param string $subject The string or array being searched and replaced on, otherwise known as the haystack.
- * @param string $encoding The encoding parameter is the character encoding. Defaults to UTF-8
- * @param int $count If passed, this will be set to the number of replacements performed.
- * @return string
- * @deprecated 8.2.0 Use str_replace() instead.
- *
- */
- public static function mb_str_replace($search, $replace, $subject, $encoding = 'UTF-8', &$count = null) {
- return str_replace($search, $replace, $subject, $count);
- }
-
- /**
* performs a search in a nested array
* @param array $haystack the array to be searched
* @param string $needle the search string
diff --git a/lib/private/installer.php b/lib/private/installer.php
index 86968a7c189..021e496392f 100644
--- a/lib/private/installer.php
+++ b/lib/private/installer.php
@@ -278,7 +278,7 @@ class OC_Installer{
}
//detect the archive type
- $mime=OC_Helper::getMimeType($path);
+ $mime = \OC::$server->getMimeTypeDetector()->detect($path);
if ($mime !=='application/zip' && $mime !== 'application/x-gzip' && $mime !== 'application/x-bzip2') {
throw new \Exception($l->t("Archives of type %s are not supported", array($mime)));
}
diff --git a/lib/private/notification/inotification.php b/lib/private/notification/inotification.php
index b79b7f6d9d3..0187abab152 100644
--- a/lib/private/notification/inotification.php
+++ b/lib/private/notification/inotification.php
@@ -76,10 +76,11 @@ interface INotification {
/**
* @param string $type
- * @param int $id
+ * @param string $id
* @return $this
- * @throws \InvalidArgumentException if the object type or id are invalid
+ * @throws \InvalidArgumentException if the object type or id is invalid
* @since 8.2.0
+ * @changed 9.0.0 Type of $id changed to string
*/
public function setObject($type, $id);
@@ -90,8 +91,9 @@ interface INotification {
public function getObjectType();
/**
- * @return int
+ * @return string
* @since 8.2.0
+ * @changed 9.0.0 Return type changed to string
*/
public function getObjectId();
diff --git a/lib/private/notification/notification.php b/lib/private/notification/notification.php
index a22d5446f45..70964fc0366 100644
--- a/lib/private/notification/notification.php
+++ b/lib/private/notification/notification.php
@@ -35,7 +35,7 @@ class Notification implements INotification {
/** @var string */
protected $objectType;
- /** @var int */
+ /** @var string */
protected $objectId;
/** @var string */
@@ -83,7 +83,7 @@ class Notification implements INotification {
$this->dateTime = new \DateTime();
$this->dateTime->setTimestamp(0);
$this->objectType = '';
- $this->objectId = 0;
+ $this->objectId = '';
$this->subject = '';
$this->subjectParameters = [];
$this->subjectParsed = '';
@@ -164,10 +164,11 @@ class Notification implements INotification {
/**
* @param string $type
- * @param int $id
+ * @param string $id
* @return $this
* @throws \InvalidArgumentException if the object type or id is invalid
* @since 8.2.0
+ * @changed 9.0.0 Type of $id changed to string
*/
public function setObject($type, $id) {
if (!is_string($type) || $type === '' || isset($type[64])) {
@@ -175,10 +176,10 @@ class Notification implements INotification {
}
$this->objectType = $type;
- if (!is_int($id)) {
+ if (!is_int($id) && (!is_string($id) || $id === '' || isset($id[64]))) {
throw new \InvalidArgumentException('The given object id is invalid');
}
- $this->objectId = $id;
+ $this->objectId = (string) $id;
return $this;
}
@@ -191,8 +192,9 @@ class Notification implements INotification {
}
/**
- * @return int
+ * @return string
* @since 8.2.0
+ * @changed 9.0.0 Return type changed to string
*/
public function getObjectId() {
return $this->objectId;
@@ -443,7 +445,7 @@ class Notification implements INotification {
&&
$this->getObjectType() !== ''
&&
- $this->getObjectId() !== 0
+ $this->getObjectId() !== ''
;
}
}
diff --git a/lib/private/share/share.php b/lib/private/share/share.php
index d377708a268..1308c99f804 100644
--- a/lib/private/share/share.php
+++ b/lib/private/share/share.php
@@ -2332,22 +2332,7 @@ class Share extends Constants {
$id = false;
if ($result) {
- $id = \OC::$server->getDatabaseConnection()->lastInsertId();
- // Fallback, if lastInterId() doesn't work we need to perform a select
- // to get the ID (seems to happen sometimes on Oracle)
- if (!$id) {
- $getId = \OC_DB::prepare('
- SELECT `id`
- FROM`*PREFIX*share`
- WHERE `uid_owner` = ? AND `item_target` = ? AND `item_source` = ? AND `stime` = ?
- ');
- $r = $getId->execute(array($shareData['uidOwner'], $shareData['itemTarget'], $shareData['itemSource'], $shareData['shareTime']));
- if ($r) {
- $row = $r->fetchRow();
- $id = $row['id'];
- }
- }
-
+ $id = \OC::$server->getDatabaseConnection()->lastInsertId('*PREFIX*share');
}
return $id;
@@ -2581,7 +2566,10 @@ class Share extends Constants {
$result = self::tryHttpPost($url, $fields);
$status = json_decode($result['result'], true);
- return ($result['success'] && $status['ocs']['meta']['statuscode'] === 100);
+ if ($result['success'] && $status['ocs']['meta']['statuscode'] === 100) {
+ \OC_Hook::emit('OCP\Share', 'federated_share_added', ['server' => $remote]);
+ return true;
+ }
}
diff --git a/lib/private/share20/defaultshareprovider.php b/lib/private/share20/defaultshareprovider.php
index 7f21d3aadf5..bc3bc0ce9ed 100644
--- a/lib/private/share20/defaultshareprovider.php
+++ b/lib/private/share20/defaultshareprovider.php
@@ -23,65 +23,78 @@ namespace OC\Share20;
use OC\Share20\Exception\ShareNotFound;
use OC\Share20\Exception\BackendError;
use OCP\IUser;
+use OCP\IGroupManager;
+use OCP\IUserManager;
+use OCP\Files\IRootFolder;
+use OCP\IDBConnection;
+use OCP\Files\Node;
class DefaultShareProvider implements IShareProvider {
- /** @var \OCP\IDBConnection */
+ /** @var IDBConnection */
private $dbConn;
- /** @var \OCP\IUserManager */
+ /** @var IUserManager */
private $userManager;
- /** @var \OCP\IGroupManager */
+ /** @var IGroupManager */
private $groupManager;
- /** @var \OCP\Files\Folder */
- private $userFolder;
+ /** @var IRootFolder */
+ private $rootFolder;
- public function __construct(\OCP\IDBConnection $connection,
- \OCP\IUserManager $userManager,
- \OCP\IGroupManager $groupManager,
- \OCP\Files\Folder $userFolder) {
+ /**
+ * DefaultShareProvider constructor.
+ *
+ * @param IDBConnection $connection
+ * @param IUserManager $userManager
+ * @param IGroupManager $groupManager
+ * @param IRootFolder $rootFolder
+ */
+ public function __construct(
+ IDBConnection $connection,
+ IUserManager $userManager,
+ IGroupManager $groupManager,
+ IRootFolder $rootFolder) {
$this->dbConn = $connection;
$this->userManager = $userManager;
$this->groupManager = $groupManager;
- $this->userFolder = $userFolder;
+ $this->rootFolder = $rootFolder;
}
/**
* Share a path
*
- * @param Share $share
- * @return Share The share object
+ * @param IShare $share
+ * @return IShare The share object
*/
- public function create(Share $share) {
- throw new \Exception();
+ public function create(IShare $share) {
}
/**
* Update a share
*
- * @param Share $share
- * @return Share The share object
+ * @param IShare $share
+ * @return IShare The share object
*/
- public function update(Share $share) {
- throw new \Exception();
+ public function update(IShare $share) {
}
/**
- * Get all childre of this share
+ * Get all children of this share
*
- * @param IShare $share
+ * @param IShare $parent
* @return IShare[]
*/
- private function getChildren(IShare $share) {
+ public function getChildren(IShare $parent) {
$children = [];
$qb = $this->dbConn->getQueryBuilder();
$qb->select('*')
->from('share')
->where($qb->expr()->eq('parent', $qb->createParameter('parent')))
- ->setParameter(':parent', $share->getId());
+ ->setParameter(':parent', $parent->getId())
+ ->orderBy('id');
$cursor = $qb->execute();
while($data = $cursor->fetch()) {
@@ -93,50 +106,15 @@ class DefaultShareProvider implements IShareProvider {
}
/**
- * Delete all the children of this share
- *
- * @param IShare $share
- */
- protected function deleteChildren(IShare $share) {
- foreach($this->getChildren($share) as $child) {
- $this->delete($child);
- }
- }
-
- /**
* Delete a share
*
- * @param Share $share
+ * @param IShare $share
* @throws BackendError
*/
public function delete(IShare $share) {
- $this->deleteChildren($share);
-
// Fetch share to make sure it exists
$share = $this->getShareById($share->getId());
- $shareType = $share->getShareType();
- $sharedWith = '';
- if ($shareType === \OCP\Share::SHARE_TYPE_USER) {
- $sharedWith = $share->getSharedWith()->getUID();
- } else if ($shareType === \OCP\Share::SHARE_TYPE_GROUP) {
- $sharedWith = $share->getSharedWith()->getGID();
- }
-
- $hookParams = [
- 'id' => $share->getId(),
- 'itemType' => $share->getPath() instanceof \OCP\Files\File ? 'file' : 'folder',
- 'itemSource' => $share->getPath()->getId(),
- 'shareType' => $shareType,
- 'shareWith' => $sharedWith,
- 'itemparent' => $share->getParent(),
- 'uidOwner' => $share->getSharedBy()->getUID(),
- 'fileSource' => $share->getPath()->getId(),
- 'fileTarget' => $share->getTarget()
- ];
-
- \OC_Hook::emit('OCP\Share', 'pre_unshare', $hookParams);
-
$qb = $this->dbConn->getQueryBuilder();
$qb->delete('share')
->where($qb->expr()->eq('id', $qb->createParameter('id')))
@@ -147,8 +125,6 @@ class DefaultShareProvider implements IShareProvider {
} catch (\Exception $e) {
throw new BackendError();
}
-
- \OC_Hook::emit('OCP\Share', 'post_unshare', $hookParams);
}
/**
@@ -161,7 +137,6 @@ class DefaultShareProvider implements IShareProvider {
* @return Share[]
*/
public function getShares(IUser $user, $shareType, $offset, $limit) {
- throw new \Exception();
}
/**
@@ -195,11 +170,11 @@ class DefaultShareProvider implements IShareProvider {
/**
* Get shares for a given path
*
+ * @param \OCP\IUser $user
* @param \OCP\Files\Node $path
- * @param Share[]
+ * @return IShare[]
*/
- public function getSharesByPath(\OCP\IUser $user, \OCP\Files\Node $path) {
- throw new \Exception();
+ public function getSharesByPath(IUser $user, Node $path) {
}
/**
@@ -210,7 +185,6 @@ class DefaultShareProvider implements IShareProvider {
* @param Share
*/
public function getSharedWithMe(IUser $user, $shareType = null) {
- throw new \Exception();
}
/**
@@ -221,7 +195,6 @@ class DefaultShareProvider implements IShareProvider {
* @param Share
*/
public function getShareByToken($token, $password = null) {
- throw new \Exception();
}
/**
@@ -253,14 +226,14 @@ class DefaultShareProvider implements IShareProvider {
$share->setSharedBy($this->userManager->get($data['uid_owner']));
// TODO: getById can return an array. How to handle this properly??
- $path = $this->userFolder->getById($data['file_source']);
- $path = $path[0];
- $share->setPath($path);
+ $folder = $this->rootFolder->getUserFolder($share->getSharedBy()->getUID());
+ $path = $folder->getById((int)$data['file_source'])[0];
- $owner = $path->getStorage()->getOwner('.');
- if ($owner !== false) {
- $share->setShareOwner($this->userManager->get($owner));
- }
+ $owner = $path->getOwner();
+ $share->setShareOwner($owner);
+
+ $path = $this->rootFolder->getUserFolder($owner->getUID())->getById((int)$data['file_source'])[0];
+ $share->setPath($path);
if ($data['expiration'] !== null) {
$expiration = \DateTime::createFromFormat('Y-m-d H:i:s', $data['expiration']);
@@ -270,5 +243,4 @@ class DefaultShareProvider implements IShareProvider {
return $share;
}
-
-}
+} \ No newline at end of file
diff --git a/lib/private/share20/ishare.php b/lib/private/share20/ishare.php
index a80abebd71c..2e54da7a029 100644
--- a/lib/private/share20/ishare.php
+++ b/lib/private/share20/ishare.php
@@ -38,7 +38,7 @@ interface IShare {
/**
* Set the path of this share
*
- * @param File|Folder $path
+ * @param Node $path
* @return Share The modified object
*/
public function setPath(Node $path);
diff --git a/lib/private/share20/ishareprovider.php b/lib/private/share20/ishareprovider.php
index b3f4eb6868f..56a550acf71 100644
--- a/lib/private/share20/ishareprovider.php
+++ b/lib/private/share20/ishareprovider.php
@@ -29,23 +29,23 @@ interface IShareProvider {
/**
* Share a path
*
- * @param Share $share
- * @return Share The share object
+ * @param IShare $share
+ * @return IShare The share object
*/
- public function create(Share $share);
+ public function create(IShare $share);
/**
* Update a share
*
- * @param Share $share
- * @return Share The share object
+ * @param IShare $share
+ * @return IShare The share object
*/
- public function update(Share $share);
+ public function update(IShare $share);
/**
* Delete a share
*
- * @param Share $share
+ * @param IShare $share
* @throws BackendError
*/
public function delete(IShare $share);
@@ -71,10 +71,19 @@ interface IShareProvider {
public function getShareById($id);
/**
+ * Get children
+ *
+ * @param IShare $parent
+ * @return IShare[]
+ */
+ public function getChildren(IShare $parent);
+
+ /**
* Get shares for a given path
*
+ * @param \OCP\IUser $user
* @param \OCP\Files\Node $path
- * @param Share[]
+ * @return IShare[]
*/
public function getSharesByPath(\OCP\IUser $user, \OCP\Files\Node $path);
diff --git a/lib/private/share20/manager.php b/lib/private/share20/manager.php
index 52e43a9aa9f..882b281c490 100644
--- a/lib/private/share20/manager.php
+++ b/lib/private/share20/manager.php
@@ -22,11 +22,7 @@ namespace OC\Share20;
use OCP\IAppConfig;
-use OCP\IUserManager;
-use OCP\IGroupManager;
-use OCP\IUser;
use OCP\ILogger;
-use OCP\Files\Folder;
use OC\Share20\Exception\ShareNotFound;
@@ -40,37 +36,26 @@ class Manager {
*/
private $defaultProvider;
- /** @var IUser */
- private $currentUser;
-
- /** @var IUserManager */
- private $userManager;
-
- /** @var IGroupManager */
- private $groupManager;
-
/** @var ILogger */
private $logger;
/** @var IAppConfig */
private $appConfig;
- /** @var IFolder */
- private $userFolder;
-
- public function __construct(IUser $user,
- IUserManager $userManager,
- IGroupManager $groupManager,
- ILogger $logger,
- IAppConfig $appConfig,
- Folder $userFolder,
- IShareProvider $defaultProvider) {
- $this->currentUser = $user;
- $this->userManager = $userManager;
- $this->groupManager = $groupManager;
+ /**
+ * Manager constructor.
+ *
+ * @param ILogger $logger
+ * @param IAppConfig $appConfig
+ * @param IShareProvider $defaultProvider
+ */
+ public function __construct(
+ ILogger $logger,
+ IAppConfig $appConfig,
+ IShareProvider $defaultProvider
+ ) {
$this->logger = $logger;
$this->appConfig = $appConfig;
- $this->userFolder = $userFolder;
// TEMP SOLUTION JUST TO GET STARTED
$this->defaultProvider = $defaultProvider;
@@ -78,12 +63,11 @@ class Manager {
/**
* Share a path
- *
+ *
* @param Share $share
* @return Share The share object
*/
public function createShare(Share $share) {
- throw new \Exception();
}
/**
@@ -93,22 +77,87 @@ class Manager {
* @return Share The share object
*/
public function updateShare(Share $share) {
- throw new \Exception();
+ }
+
+ /**
+ * Delete all the children of this share
+ *
+ * @param IShare $share
+ * @return IShare[] List of deleted shares
+ */
+ protected function deleteChildren(IShare $share) {
+ $deletedShares = [];
+ foreach($this->defaultProvider->getChildren($share) as $child) {
+ $deletedChildren = $this->deleteChildren($child);
+ $deletedShares = array_merge($deletedShares, $deletedChildren);
+
+ $this->defaultProvider->delete($child);
+ $deletedShares[] = $child;
+ }
+
+ return $deletedShares;
}
/**
* Delete a share
*
- * @param Share $share
+ * @param IShare $share
* @throws ShareNotFound
* @throws \OC\Share20\Exception\BackendError
*/
public function deleteShare(IShare $share) {
- if ($share->getId() === null) {
- throw new ShareNotFound();
- }
-
+ // Just to make sure we have all the info
+ $share = $this->getShareById($share->getId());
+
+ $formatHookParams = function(IShare $share) {
+ // Prepare hook
+ $shareType = $share->getShareType();
+ $sharedWith = '';
+ if ($shareType === \OCP\Share::SHARE_TYPE_USER) {
+ $sharedWith = $share->getSharedWith()->getUID();
+ } else if ($shareType === \OCP\Share::SHARE_TYPE_GROUP) {
+ $sharedWith = $share->getSharedWith()->getGID();
+ } else if ($shareType === \OCP\Share::SHARE_TYPE_REMOTE) {
+ $sharedWith = $share->getSharedWith();
+ }
+
+ $hookParams = [
+ 'id' => $share->getId(),
+ 'itemType' => $share->getPath() instanceof \OCP\Files\File ? 'file' : 'folder',
+ 'itemSource' => $share->getPath()->getId(),
+ 'shareType' => $shareType,
+ 'shareWith' => $sharedWith,
+ 'itemparent' => $share->getParent(),
+ 'uidOwner' => $share->getSharedBy()->getUID(),
+ 'fileSource' => $share->getPath()->getId(),
+ 'fileTarget' => $share->getTarget()
+ ];
+ return $hookParams;
+ };
+
+ $hookParams = $formatHookParams($share);
+
+ // Emit pre-hook
+ \OC_Hook::emit('OCP\Share', 'pre_unshare', $hookParams);
+
+ // Get all children and delete them as well
+ $deletedShares = $this->deleteChildren($share);
+
+ // Do the actual delete
$this->defaultProvider->delete($share);
+
+ // All the deleted shares caused by this delete
+ $deletedShares[] = $share;
+
+ //Format hook info
+ $formattedDeletedShares = array_map(function($share) use ($formatHookParams) {
+ return $formatHookParams($share);
+ }, $deletedShares);
+
+ $hookParams['deletedShares'] = $formattedDeletedShares;
+
+ // Emit post hook
+ \OC_Hook::emit('OCP\Share', 'post_unshare', $hookParams);
}
/**
@@ -119,7 +168,6 @@ class Manager {
* @return Share[]
*/
public function getShares($page=0, $perPage=50) {
- throw new \Exception();
}
/**
@@ -131,14 +179,12 @@ class Manager {
* @throws ShareNotFound
*/
public function getShareById($id) {
- $share = $this->defaultProvider->getShareById($id);
-
- if ($share->getSharedWith() !== $this->currentUser &&
- $share->getSharedBy() !== $this->currentUser &&
- $share->getShareOwner() !== $this->currentUser) {
+ if ($id === null) {
throw new ShareNotFound();
}
+ $share = $this->defaultProvider->getShareById($id);
+
return $share;
}
@@ -152,7 +198,6 @@ class Manager {
* @return Share[]
*/
public function getSharesByPath(\OCP\Files\Node $path, $page=0, $perPage=50) {
- throw new \Exception();
}
/**
@@ -165,7 +210,6 @@ class Manager {
* @return Share[]
*/
public function getSharedWithMe($shareType = null, $page=0, $perPage=50) {
- throw new \Exception();
}
/**
@@ -176,10 +220,9 @@ class Manager {
*
* @return Share
*
- * @throws ShareNotFoundException
+ * @throws ShareNotFound
*/
public function getShareByToken($token, $password=null) {
- throw new \Exception();
}
/**
@@ -207,6 +250,5 @@ class Manager {
* @param \OCP\Files\Node $path
*/
public function getAccessList(\OCP\Files\Node $path) {
- throw new \Exception();
}
}
diff --git a/lib/private/share20/share.php b/lib/private/share20/share.php
index 4200816799e..b7ce38ac61d 100644
--- a/lib/private/share20/share.php
+++ b/lib/private/share20/share.php
@@ -58,7 +58,7 @@ class Share implements IShare {
/**
* Set the id of the share
*
- * @param int id
+ * @param string $id
* @return Share The modified object
*/
public function setId($id) {
@@ -292,7 +292,7 @@ class Share implements IShare {
/**
* Set the target of this share
*
- * @param string target
+ * @param string $target
* @return Share The modified object
*/
public function setTarget($target) {
diff --git a/lib/private/template/functions.php b/lib/private/template/functions.php
index 1c6eaa9a389..79d18632d2f 100644
--- a/lib/private/template/functions.php
+++ b/lib/private/template/functions.php
@@ -30,7 +30,7 @@
/**
* Prints a sanitized string
- * @param string|array $string the string which will be escaped and printed
+ * @param string $string the string which will be escaped and printed
*/
function p($string) {
print(OC_Util::sanitizeHTML($string));
@@ -154,7 +154,7 @@ function link_to( $app, $file, $args = array() ) {
* @return string url to the online documentation
*/
function link_to_docs($key) {
- return OC_Helper::linkToDocs($key);
+ return \OC::$server->getURLGenerator()->linkToDocs($key);
}
/**
diff --git a/lib/private/util.php b/lib/private/util.php
index 69f01c22be9..84a8c49c383 100644
--- a/lib/private/util.php
+++ b/lib/private/util.php
@@ -621,6 +621,9 @@ class OC_Util {
$webServerRestart = false;
$setup = new \OC\Setup($config, \OC::$server->getIniWrapper(), \OC::$server->getL10N('lib'),
new \OC_Defaults(), \OC::$server->getLogger(), \OC::$server->getSecureRandom());
+
+ $urlGenerator = \OC::$server->getURLGenerator();
+
$availableDatabases = $setup->getSupportedDatabases();
if (empty($availableDatabases)) {
$errors[] = array(
@@ -649,7 +652,7 @@ class OC_Util {
'error' => $l->t('Cannot write into "config" directory'),
'hint' => $l->t('This can usually be fixed by '
. '%sgiving the webserver write access to the config directory%s.',
- array('<a href="' . \OC_Helper::linkToDocs('admin-dir_permissions') . '" target="_blank">', '</a>'))
+ array('<a href="' . $urlGenerator->linkToDocs('admin-dir_permissions') . '" target="_blank">', '</a>'))
);
}
@@ -664,7 +667,7 @@ class OC_Util {
'hint' => $l->t('This can usually be fixed by '
. '%sgiving the webserver write access to the apps directory%s'
. ' or disabling the appstore in the config file.',
- array('<a href="' . \OC_Helper::linkToDocs('admin-dir_permissions') . '" target="_blank">', '</a>'))
+ array('<a href="' . $urlGenerator->linkToDocs('admin-dir_permissions') . '" target="_blank">', '</a>'))
);
}
}
@@ -679,14 +682,14 @@ class OC_Util {
'error' => $l->t('Cannot create "data" directory (%s)', array($CONFIG_DATADIRECTORY)),
'hint' => $l->t('This can usually be fixed by '
. '<a href="%s" target="_blank">giving the webserver write access to the root directory</a>.',
- array(OC_Helper::linkToDocs('admin-dir_permissions')))
+ array($urlGenerator->linkToDocs('admin-dir_permissions')))
);
}
} else if (!is_writable($CONFIG_DATADIRECTORY) or !is_readable($CONFIG_DATADIRECTORY)) {
//common hint for all file permissions error messages
$permissionsHint = $l->t('Permissions can usually be fixed by '
. '%sgiving the webserver write access to the root directory%s.',
- array('<a href="' . \OC_Helper::linkToDocs('admin-dir_permissions') . '" target="_blank">', '</a>'));
+ array('<a href="' . $urlGenerator->linkToDocs('admin-dir_permissions') . '" target="_blank">', '</a>'));
$errors[] = array(
'error' => 'Data directory (' . $CONFIG_DATADIRECTORY . ') not writable by ownCloud',
'hint' => $permissionsHint