summaryrefslogtreecommitdiffstats
path: root/lib/private
diff options
context:
space:
mode:
Diffstat (limited to 'lib/private')
-rw-r--r--lib/private/api.php10
-rw-r--r--lib/private/connector/sabre/directory.php31
-rw-r--r--lib/private/connector/sabre/node.php11
-rw-r--r--lib/private/connector/sabre/objecttree.php6
-rw-r--r--lib/private/connector/sabre/server.php7
-rw-r--r--lib/private/connector/sabre/taglist.php102
-rw-r--r--lib/private/connector/sabre/tagsplugin.php289
-rw-r--r--lib/private/files/fileinfo.php21
-rw-r--r--lib/private/files/mount/mountpoint.php33
-rw-r--r--lib/private/files/node/node.php4
-rw-r--r--lib/private/files/view.php48
-rw-r--r--lib/private/image.php2
-rw-r--r--lib/private/memcache/apc.php2
-rw-r--r--lib/private/memcache/factory.php4
-rw-r--r--lib/private/memcache/memcached.php8
-rw-r--r--lib/private/memcache/redis.php94
-rw-r--r--lib/private/preview.php5
-rw-r--r--lib/private/template.php2
-rw-r--r--lib/private/user.php17
-rw-r--r--lib/private/user/database.php10
-rw-r--r--lib/private/user/dummy.php10
-rw-r--r--lib/private/user/http.php10
-rw-r--r--lib/private/user/manager.php14
-rw-r--r--lib/private/user/user.php3
-rw-r--r--lib/private/util.php34
25 files changed, 721 insertions, 56 deletions
diff --git a/lib/private/api.php b/lib/private/api.php
index 66b763fdc3e..c58d2620684 100644
--- a/lib/private/api.php
+++ b/lib/private/api.php
@@ -47,6 +47,7 @@ class OC_API {
*/
protected static $actions = array();
private static $logoutRequired = false;
+ private static $isLoggedIn = false;
/**
* registers an api call
@@ -269,7 +270,10 @@ class OC_API {
* http basic auth
* @return string|false (username, or false on failure)
*/
- private static function loginUser(){
+ private static function loginUser() {
+ if(self::$isLoggedIn === true) {
+ return \OC_User::getUser();
+ }
// reuse existing login
$loggedIn = OC_User::isLoggedIn();
@@ -279,6 +283,7 @@ class OC_API {
// initialize the user's filesystem
\OC_Util::setUpFS(\OC_User::getUser());
+ self::$isLoggedIn = true;
return OC_User::getUser();
}
@@ -296,8 +301,9 @@ class OC_API {
// initialize the user's filesystem
\OC_Util::setUpFS(\OC_User::getUser());
+ self::$isLoggedIn = true;
- return $authUser;
+ return \OC_User::getUser();
}
}
diff --git a/lib/private/connector/sabre/directory.php b/lib/private/connector/sabre/directory.php
index ec5f82f9daa..c878e5ee4b4 100644
--- a/lib/private/connector/sabre/directory.php
+++ b/lib/private/connector/sabre/directory.php
@@ -25,6 +25,13 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node
implements \Sabre\DAV\ICollection, \Sabre\DAV\IQuota {
/**
+ * Cached directory content
+ *
+ * @var \OCP\Files\FileInfo[]
+ */
+ private $dirContent;
+
+ /**
* Creates a new file in the directory
*
* Data will either be supplied as a stream resource, or in certain cases
@@ -72,7 +79,7 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node
$path = $this->fileView->getAbsolutePath($this->path) . '/' . $name;
// using a dummy FileInfo is acceptable here since it will be refreshed after the put is complete
- $info = new \OC\Files\FileInfo($path, null, null, array());
+ $info = new \OC\Files\FileInfo($path, null, null, array(), null);
$node = new OC_Connector_Sabre_File($this->fileView, $info);
return $node->put($data);
} catch (\OCP\Files\StorageNotAvailableException $e) {
@@ -138,13 +145,20 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node
* @return \Sabre\DAV\INode[]
*/
public function getChildren() {
+ if (!is_null($this->dirContent)) {
+ return $this->dirContent;
+ }
+ $folderContent = $this->fileView->getDirectoryContent($this->path);
- $folder_content = $this->fileView->getDirectoryContent($this->path);
+ $properties = array();
$paths = array();
- foreach($folder_content as $info) {
- $paths[] = $this->path.'/'.$info['name'];
- $properties[$this->path.'/'.$info['name']][self::GETETAG_PROPERTYNAME] = '"' . $info['etag'] . '"';
+ foreach($folderContent as $info) {
+ $name = $info->getName();
+ $paths[] = $this->path . '/' . $name;
+ $properties[$this->path.'/' . $name][self::GETETAG_PROPERTYNAME] = '"' . $info->getEtag() . '"';
}
+ // TODO: move this to a beforeGetPropertiesForPath event to pre-cache properties
+ // TODO: only fetch the requested properties
if(count($paths)>0) {
//
// the number of arguments within IN conditions are limited in most databases
@@ -169,12 +183,13 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node
}
$nodes = array();
- foreach($folder_content as $info) {
+ foreach($folderContent as $info) {
$node = $this->getChild($info->getName(), $info);
- $node->setPropertyCache($properties[$this->path.'/'.$info['name']]);
+ $node->setPropertyCache($properties[$this->path . '/' . $info->getName()]);
$nodes[] = $node;
}
- return $nodes;
+ $this->dirContent = $nodes;
+ return $this->dirContent;
}
/**
diff --git a/lib/private/connector/sabre/node.php b/lib/private/connector/sabre/node.php
index a22dc9c5fbe..3173ab8a30f 100644
--- a/lib/private/connector/sabre/node.php
+++ b/lib/private/connector/sabre/node.php
@@ -1,5 +1,7 @@
<?php
+
use Sabre\DAV\URLUtil;
+use OC\Connector\Sabre\TagList;
/**
* ownCloud
@@ -227,6 +229,15 @@ abstract class OC_Connector_Sabre_Node implements \Sabre\DAV\INode, \Sabre\DAV\I
}
/**
+ * Returns the cache's file id
+ *
+ * @return int
+ */
+ public function getId() {
+ return $this->info->getId();
+ }
+
+ /**
* @return string|null
*/
public function getFileId() {
diff --git a/lib/private/connector/sabre/objecttree.php b/lib/private/connector/sabre/objecttree.php
index 14a55b5cada..d2759d7a3ba 100644
--- a/lib/private/connector/sabre/objecttree.php
+++ b/lib/private/connector/sabre/objecttree.php
@@ -71,7 +71,9 @@ class ObjectTree extends \Sabre\DAV\ObjectTree {
if (pathinfo($path, PATHINFO_EXTENSION) === 'part') {
// read from storage
$absPath = $this->fileView->getAbsolutePath($path);
- list($storage, $internalPath) = Filesystem::resolvePath('/' . $absPath);
+ $mount = $this->fileView->getMount($path);
+ $storage = $mount->getStorage();
+ $internalPath = $mount->getInternalPath($absPath);
if ($storage) {
/**
* @var \OC\Files\Storage\Storage $storage
@@ -79,7 +81,7 @@ class ObjectTree extends \Sabre\DAV\ObjectTree {
$scanner = $storage->getScanner($internalPath);
// get data directly
$data = $scanner->getData($internalPath);
- $info = new FileInfo($absPath, $storage, $internalPath, $data);
+ $info = new FileInfo($absPath, $storage, $internalPath, $data, $mount);
} else {
$info = null;
}
diff --git a/lib/private/connector/sabre/server.php b/lib/private/connector/sabre/server.php
index 137082eea67..a836af2a0b8 100644
--- a/lib/private/connector/sabre/server.php
+++ b/lib/private/connector/sabre/server.php
@@ -144,6 +144,13 @@ class OC_Connector_Sabre_Server extends Sabre\DAV\Server {
$path = rtrim($path,'/');
+ // This event allows people to intercept these requests early on in the
+ // process.
+ //
+ // We're not doing anything with the result, but this can be helpful to
+ // pre-fetch certain expensive live properties.
+ $this->broadCastEvent('beforeGetPropertiesForPath', array($path, $propertyNames, $depth));
+
$returnPropertyList = array();
$parentNode = $this->tree->getNodeForPath($path);
diff --git a/lib/private/connector/sabre/taglist.php b/lib/private/connector/sabre/taglist.php
new file mode 100644
index 00000000000..56cab393fea
--- /dev/null
+++ b/lib/private/connector/sabre/taglist.php
@@ -0,0 +1,102 @@
+<?php
+/**
+ * ownCloud
+ *
+ * @author Vincent Petry
+ * @copyright 2014 Vincent Petry <pvince81@owncloud.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library 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 along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OC\Connector\Sabre;
+
+use Sabre\DAV;
+
+/**
+ * TagList property
+ *
+ * This property contains multiple "tag" elements, each containing a tag name.
+ */
+class TagList extends DAV\Property {
+ const NS_OWNCLOUD = 'http://owncloud.org/ns';
+
+ /**
+ * tags
+ *
+ * @var array
+ */
+ private $tags;
+
+ /**
+ * @param array $tags
+ */
+ public function __construct(array $tags) {
+ $this->tags = $tags;
+ }
+
+ /**
+ * Returns the tags
+ *
+ * @return array
+ */
+ public function getTags() {
+
+ return $this->tags;
+
+ }
+
+ /**
+ * Serializes this property.
+ *
+ * @param DAV\Server $server
+ * @param \DOMElement $dom
+ * @return void
+ */
+ public function serialize(DAV\Server $server,\DOMElement $dom) {
+
+ $prefix = $server->xmlNamespaces[self::NS_OWNCLOUD];
+
+ foreach($this->tags as $tag) {
+
+ $elem = $dom->ownerDocument->createElement($prefix . ':tag');
+ $elem->appendChild($dom->ownerDocument->createTextNode($tag));
+
+ $dom->appendChild($elem);
+ }
+
+ }
+
+ /**
+ * Unserializes this property from a DOM Element
+ *
+ * This method returns an instance of this class.
+ * It will only decode tag values.
+ *
+ * @param \DOMElement $dom
+ * @return \OC\Connector\Sabre\TagList
+ */
+ static function unserialize(\DOMElement $dom) {
+
+ $tags = array();
+ foreach($dom->childNodes as $child) {
+ if (DAV\XMLUtil::toClarkNotation($child)==='{' . self::NS_OWNCLOUD . '}tag') {
+ $tags[] = $child->textContent;
+ }
+ }
+ return new self($tags);
+
+ }
+
+}
diff --git a/lib/private/connector/sabre/tagsplugin.php b/lib/private/connector/sabre/tagsplugin.php
new file mode 100644
index 00000000000..dd0b5172bd6
--- /dev/null
+++ b/lib/private/connector/sabre/tagsplugin.php
@@ -0,0 +1,289 @@
+<?php
+
+namespace OC\Connector\Sabre;
+
+/**
+ * ownCloud
+ *
+ * @author Vincent Petry
+ * @copyright 2014 Vincent Petry <pvince81@owncloud.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library 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 along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+class TagsPlugin extends \Sabre\DAV\ServerPlugin
+{
+
+ // namespace
+ const NS_OWNCLOUD = 'http://owncloud.org/ns';
+ const TAGS_PROPERTYNAME = '{http://owncloud.org/ns}tags';
+ const FAVORITE_PROPERTYNAME = '{http://owncloud.org/ns}favorite';
+ const TAG_FAVORITE = '_$!<Favorite>!$_';
+
+ /**
+ * Reference to main server object
+ *
+ * @var \Sabre\DAV\Server
+ */
+ private $server;
+
+ /**
+ * @var \OCP\ITagManager
+ */
+ private $tagManager;
+
+ /**
+ * @var \OCP\ITags
+ */
+ private $tagger;
+
+ /**
+ * Array of file id to tags array
+ * The null value means the cache wasn't initialized.
+ *
+ * @var array
+ */
+ private $cachedTags;
+
+ /**
+ * @param \OCP\ITagManager $tagManager tag manager
+ */
+ public function __construct(\Sabre\DAV\ObjectTree $objectTree, \OCP\ITagManager $tagManager) {
+ $this->objectTree = $objectTree;
+ $this->tagManager = $tagManager;
+ $this->tagger = null;
+ $this->cachedTags = null;
+ }
+
+ /**
+ * This initializes the plugin.
+ *
+ * This function is called by \Sabre\DAV\Server, after
+ * addPlugin is called.
+ *
+ * This method should set up the required event subscriptions.
+ *
+ * @param \Sabre\DAV\Server $server
+ * @return void
+ */
+ public function initialize(\Sabre\DAV\Server $server) {
+
+ $server->xmlNamespaces[self::NS_OWNCLOUD] = 'oc';
+ $server->propertyMap[self::TAGS_PROPERTYNAME] = 'OC\\Connector\\Sabre\\TagList';
+
+ $this->server = $server;
+ $this->server->subscribeEvent('beforeGetProperties', array($this, 'beforeGetProperties'));
+ $this->server->subscribeEvent('beforeGetPropertiesForPath', array($this, 'beforeGetPropertiesForPath'));
+ $this->server->subscribeEvent('updateProperties', array($this, 'updateProperties'));
+ }
+
+ /**
+ * Searches and removes a value from the given array
+ *
+ * @param array $requestedProps
+ * @param string $propName to remove
+ * @return boolean true if the property was present, false otherwise
+ */
+ private function findAndRemoveProperty(&$requestedProps, $propName) {
+ $index = array_search($propName, $requestedProps);
+ if ($index !== false) {
+ unset($requestedProps[$index]);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Returns the tagger
+ *
+ * @return \OCP\ITags tagger
+ */
+ private function getTagger() {
+ if (!$this->tagger) {
+ $this->tagger = $this->tagManager->load('files');
+ }
+ return $this->tagger;
+ }
+
+ /**
+ * Returns tags and favorites.
+ *
+ * @param integer $fileId file id
+ * @return array list($tags, $favorite) with $tags as tag array
+ * and $favorite is a boolean whether the file was favorited
+ */
+ private function getTagsAndFav($fileId) {
+ $isFav = false;
+ $tags = $this->getTags($fileId);
+ if ($tags) {
+ $favPos = array_search(self::TAG_FAVORITE, $tags);
+ if ($favPos !== false) {
+ $isFav = true;
+ unset($tags[$favPos]);
+ }
+ }
+ return array($tags, $isFav);
+ }
+
+ /**
+ * Returns tags for the given file id
+ *
+ * @param integer $fileId file id
+ * @return array list of tags for that file
+ */
+ private function getTags($fileId) {
+ if (isset($this->cachedTags[$fileId])) {
+ return $this->cachedTags[$fileId];
+ } else {
+ $tags = $this->getTagger()->getTagsForObjects(array($fileId));
+ if ($tags) {
+ return current($tags);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Updates the tags of the given file id
+ *
+ * @param int $fileId
+ * @param array $tags array of tag strings
+ */
+ private function updateTags($fileId, $tags) {
+ $tagger = $this->getTagger();
+ $currentTags = $this->getTags($fileId);
+
+ $newTags = array_diff($tags, $currentTags);
+ foreach ($newTags as $tag) {
+ if ($tag === self::TAG_FAVORITE) {
+ continue;
+ }
+ $tagger->tagAs($fileId, $tag);
+ }
+ $deletedTags = array_diff($currentTags, $tags);
+ foreach ($deletedTags as $tag) {
+ if ($tag === self::TAG_FAVORITE) {
+ continue;
+ }
+ $tagger->unTag($fileId, $tag);
+ }
+ }
+
+ /**
+ * Pre-fetch tags info
+ *
+ * @param string $path
+ * @param array $requestedProperties
+ * @param integer $depth
+ * @return void
+ */
+ public function beforeGetPropertiesForPath(
+ $path,
+ array $requestedProperties,
+ $depth
+ ) {
+ $node = $this->objectTree->getNodeForPath($path);
+ if (!($node instanceof \OC_Connector_Sabre_Directory)) {
+ return;
+ }
+
+ if ($this->findAndRemoveProperty($requestedProperties, self::TAGS_PROPERTYNAME)
+ || $this->findAndRemoveProperty($requestedProperties, self::FAVORITE_PROPERTYNAME)
+ ) {
+ $fileIds = array();
+ // note: pre-fetching only supported for depth <= 1
+ $folderContent = $node->getChildren();
+ // TODO: refactor somehow with the similar array that is created
+ // in getChildren()
+ foreach ($folderContent as $info) {
+ $fileIds[] = $info->getId();
+ }
+ $tags = $this->getTagger()->getTagsForObjects($fileIds);
+ if ($tags) {
+ $this->cachedTags = $tags;
+ }
+ }
+ }
+
+ /**
+ * Adds tags and favorites properties to the response,
+ * if requested.
+ *
+ * @param string $path
+ * @param \Sabre\DAV\INode $node
+ * @param array $requestedProperties
+ * @param array $returnedProperties
+ * @return void
+ */
+ public function beforeGetProperties(
+ $path,
+ \Sabre\DAV\INode $node,
+ array &$requestedProperties,
+ array &$returnedProperties
+ ) {
+ if (!($node instanceof \OC_Connector_Sabre_Node)) {
+ return;
+ }
+
+ $tags = null;
+ $isFav = null;
+ if ($this->findAndRemoveProperty($requestedProperties, self::TAGS_PROPERTYNAME)) {
+ list($tags, $isFav) = $this->getTagsAndFav($node->getId());
+ $returnedProperties[200][self::TAGS_PROPERTYNAME] = new TagList($tags);
+ }
+ if ($this->findAndRemoveProperty($requestedProperties, self::FAVORITE_PROPERTYNAME)) {
+ if (is_null($tags)) {
+ list($tags, $isFav) = $this->getTagsAndFav($node->getId());
+ }
+ $returnedProperties[200][self::FAVORITE_PROPERTYNAME] = $isFav;
+ }
+ }
+
+ /**
+ * Updates tags and favorites properties, if applicable.
+ *
+ * @param string $path
+ * @param \Sabre\DAV\INode $node
+ * @param array $requestedProperties
+ * @param array $returnedProperties
+ * @return bool success status
+ */
+ public function updateProperties(array &$properties, array &$result, \Sabre\DAV\INode $node) {
+ if (!($node instanceof \OC_Connector_Sabre_Node)) {
+ return;
+ }
+
+ $fileId = $node->getId();
+ if (isset($properties[self::TAGS_PROPERTYNAME])) {
+ $tagsProp = $properties[self::TAGS_PROPERTYNAME];
+ unset($properties[self::TAGS_PROPERTYNAME]);
+ $this->updateTags($fileId, $tagsProp->getTags());
+ $result[200][self::TAGS_PROPERTYNAME] = new TagList($tagsProp->getTags());
+ }
+ if (isset($properties[self::FAVORITE_PROPERTYNAME])) {
+ $favState = $properties[self::FAVORITE_PROPERTYNAME];
+ unset($properties[self::FAVORITE_PROPERTYNAME]);
+ if ((int)$favState === 1 || $favState === 'true') {
+ $favState = true;
+ $this->getTagger()->tagAs($fileId, self::TAG_FAVORITE);
+ } else {
+ $favState = false;
+ $this->getTagger()->unTag($fileId, self::TAG_FAVORITE);
+ }
+ $result[200][self::FAVORITE_PROPERTYNAME] = $favState;
+ }
+ return true;
+ }
+}
diff --git a/lib/private/files/fileinfo.php b/lib/private/files/fileinfo.php
index 8bab51f0737..e4a397dcca2 100644
--- a/lib/private/files/fileinfo.php
+++ b/lib/private/files/fileinfo.php
@@ -30,14 +30,23 @@ class FileInfo implements \OCP\Files\FileInfo, \ArrayAccess {
private $internalPath;
/**
+ * @var \OCP\Files\Mount\IMountPoint
+ */
+ private $mount;
+
+ /**
* @param string|boolean $path
* @param Storage\Storage $storage
+ * @param string $internalPath
+ * @param array $data
+ * @param \OCP\Files\Mount\IMountPoint $mount
*/
- public function __construct($path, $storage, $internalPath, $data) {
+ public function __construct($path, $storage, $internalPath, $data, $mount) {
$this->path = $path;
$this->storage = $storage;
$this->internalPath = $internalPath;
$this->data = $data;
+ $this->mount = $mount;
}
public function offsetSet($offset, $value) {
@@ -208,6 +217,7 @@ class FileInfo implements \OCP\Files\FileInfo, \ArrayAccess {
/**
* Check if a file or folder is shared
+ *
* @return bool
*/
public function isShared() {
@@ -229,4 +239,13 @@ class FileInfo implements \OCP\Files\FileInfo, \ArrayAccess {
return false;
}
+
+ /**
+ * Get the mountpoint the file belongs to
+ *
+ * @return \OCP\Files\Mount\IMountPoint
+ */
+ public function getMountPoint() {
+ return $this->mount;
+ }
}
diff --git a/lib/private/files/mount/mountpoint.php b/lib/private/files/mount/mountpoint.php
index b2c50f9d881..77a51a17020 100644
--- a/lib/private/files/mount/mountpoint.php
+++ b/lib/private/files/mount/mountpoint.php
@@ -20,10 +20,23 @@ class MountPoint implements IMountPoint {
protected $storage = null;
protected $class;
protected $storageId;
+
+ /**
+ * Configuration options for the storage backend
+ *
+ * @var array
+ */
protected $arguments = array();
protected $mountPoint;
/**
+ * Mount specific options
+ *
+ * @var array
+ */
+ protected $mountOptions = array();
+
+ /**
* @var \OC\Files\Storage\StorageFactory $loader
*/
private $loader;
@@ -31,10 +44,11 @@ class MountPoint implements IMountPoint {
/**
* @param string|\OC\Files\Storage\Storage $storage
* @param string $mountpoint
- * @param array $arguments (optional)\
+ * @param array $arguments (optional) configuration for the storage backend
* @param \OCP\Files\Storage\IStorageFactory $loader
+ * @param array $mountOptions mount specific options
*/
- public function __construct($storage, $mountpoint, $arguments = null, $loader = null) {
+ public function __construct($storage, $mountpoint, $arguments = null, $loader = null, $mountOptions = null) {
if (is_null($arguments)) {
$arguments = array();
}
@@ -44,6 +58,10 @@ class MountPoint implements IMountPoint {
$this->loader = $loader;
}
+ if (!is_null($mountOptions)) {
+ $this->mountOptions = $mountOptions;
+ }
+
$mountpoint = $this->formatPath($mountpoint);
if ($storage instanceof Storage) {
$this->class = get_class($storage);
@@ -161,4 +179,15 @@ class MountPoint implements IMountPoint {
public function wrapStorage($wrapper) {
$this->storage = $wrapper($this->mountPoint, $this->getStorage());
}
+
+ /**
+ * Get a mount option
+ *
+ * @param string $name Name of the mount option to get
+ * @param mixed $default Default value for the mount option
+ * @return mixed
+ */
+ public function getOption($name, $default) {
+ return isset($this->mountOptions[$name]) ? $this->mountOptions[$name] : $default;
+ }
}
diff --git a/lib/private/files/node/node.php b/lib/private/files/node/node.php
index 87d4a4b9156..17907a53044 100644
--- a/lib/private/files/node/node.php
+++ b/lib/private/files/node/node.php
@@ -288,4 +288,8 @@ class Node implements \OCP\Files\Node, FileInfo {
public function isEncrypted() {
return $this->getFileInfo()->isEncrypted();
}
+
+ public function getMountPoint() {
+ return $this->getFileInfo()->getMountPoint();
+ }
}
diff --git a/lib/private/files/view.php b/lib/private/files/view.php
index c01763cdad3..f1c15e197d9 100644
--- a/lib/private/files/view.php
+++ b/lib/private/files/view.php
@@ -113,6 +113,19 @@ class View {
}
/**
+ * get the mountpoint of the storage object for a path
+ * ( note: because a storage is not always mounted inside the fakeroot, the
+ * returned mountpoint is relative to the absolute root of the filesystem
+ * and doesn't take the chroot into account )
+ *
+ * @param string $path
+ * @return \OCP\Files\Mount\IMountPoint
+ */
+ public function getMount($path) {
+ return Filesystem::getMountManager()->find($this->getAbsolutePath($path));
+ }
+
+ /**
* resolve a path to a storage and internal path
*
* @param string $path
@@ -280,6 +293,11 @@ class View {
}
public function isDeletable($path) {
+ $absolutePath = $this->getAbsolutePath($path);
+ $mount = Filesystem::getMountManager()->find($absolutePath);
+ if ($mount->getInternalPath($absolutePath) === '') {
+ return $mount instanceof MoveableMount;
+ }
return $this->basicOperation('isDeletable', $path);
}
@@ -938,7 +956,7 @@ class View {
$data = \OC_FileProxy::runPostProxies('getFileInfo', $path, $data);
- return new FileInfo($path, $storage, $internalPath, $data);
+ return new FileInfo($path, $storage, $internalPath, $data, $mount);
}
/**
@@ -955,8 +973,10 @@ class View {
return $result;
}
$path = $this->getAbsolutePath($directory);
- /** @var \OC\Files\Storage\Storage $storage */
- list($storage, $internalPath) = $this->resolvePath($directory);
+ $path = Filesystem::normalizePath($path);
+ $mount = $this->getMount($directory);
+ $storage = $mount->getStorage();
+ $internalPath = $mount->getInternalPath($path);
if ($storage) {
$cache = $storage->getCache($internalPath);
$user = \OC_User::getUser();
@@ -990,7 +1010,7 @@ class View {
if (\OCP\Util::isSharingDisabledForUser()) {
$content['permissions'] = $content['permissions'] & ~\OCP\Constants::PERMISSION_SHARE;
}
- $files[] = new FileInfo($path . '/' . $content['name'], $storage, $content['path'], $content);
+ $files[] = new FileInfo($path . '/' . $content['name'], $storage, $content['path'], $content, $mount);
}
//add a folder for any mountpoint in this directory and add the sizes of other mountpoints to the folders
@@ -998,7 +1018,7 @@ class View {
$dirLength = strlen($path);
foreach ($mounts as $mount) {
$mountPoint = $mount->getMountPoint();
- $subStorage = Filesystem::getStorage($mountPoint);
+ $subStorage = $mount->getStorage();
if ($subStorage) {
$subCache = $subStorage->getCache('');
@@ -1044,7 +1064,7 @@ class View {
$content['permissions'] = $content['permissions'] & ~\OCP\Constants::PERMISSION_SHARE;
}
- $files[] = new FileInfo($path . '/' . $rootEntry['name'], $subStorage, '', $rootEntry);
+ $files[] = new FileInfo($path . '/' . $rootEntry['name'], $subStorage, '', $rootEntry, $mount);
}
}
}
@@ -1154,8 +1174,9 @@ class View {
$files = array();
$rootLength = strlen($this->fakeRoot);
- $mountPoint = Filesystem::getMountPoint($this->fakeRoot);
- $storage = Filesystem::getStorage($mountPoint);
+ $mount = $this->getMount('');
+ $mountPoint = $mount->getMountPoint();
+ $storage = $mount->getStorage();
if ($storage) {
$cache = $storage->getCache('');
@@ -1165,13 +1186,14 @@ class View {
$internalPath = $result['path'];
$path = $mountPoint . $result['path'];
$result['path'] = substr($mountPoint . $result['path'], $rootLength);
- $files[] = new FileInfo($path, $storage, $internalPath, $result);
+ $files[] = new FileInfo($path, $storage, $internalPath, $result, $mount);
}
}
- $mountPoints = Filesystem::getMountPoints($this->fakeRoot);
- foreach ($mountPoints as $mountPoint) {
- $storage = Filesystem::getStorage($mountPoint);
+ $mounts = Filesystem::getMountManager()->findIn($this->fakeRoot);
+ foreach ($mounts as $mount) {
+ $mountPoint = $mount->getMountPoint();
+ $storage = $mount->getStorage();
if ($storage) {
$cache = $storage->getCache('');
@@ -1182,7 +1204,7 @@ class View {
$internalPath = $result['path'];
$result['path'] = rtrim($relativeMountPoint . $result['path'], '/');
$path = rtrim($mountPoint . $internalPath, '/');
- $files[] = new FileInfo($path, $storage, $internalPath, $result);
+ $files[] = new FileInfo($path, $storage, $internalPath, $result, $mount);
}
}
}
diff --git a/lib/private/image.php b/lib/private/image.php
index 78cacc84452..07cfb0f72d3 100644
--- a/lib/private/image.php
+++ b/lib/private/image.php
@@ -37,7 +37,7 @@ class OC_Image {
*/
static public function getMimeTypeForFile($filePath) {
// exif_imagetype throws "read error!" if file is less than 12 byte
- if (filesize($filePath) > 11) {
+ if ($filePath !== null && filesize($filePath) > 11) {
$imageType = exif_imagetype($filePath);
} else {
$imageType = false;
diff --git a/lib/private/memcache/apc.php b/lib/private/memcache/apc.php
index 332bbfead00..2c0a93db321 100644
--- a/lib/private/memcache/apc.php
+++ b/lib/private/memcache/apc.php
@@ -32,7 +32,7 @@ class APC extends Cache {
public function clear($prefix = '') {
$ns = $this->getPrefix() . $prefix;
$ns = preg_quote($ns, '/');
- $iter = new \APCIterator('user', '/^' . $ns . '/');
+ $iter = new \APCIterator('user', '/^' . $ns . '/', APC_ITER_KEY);
return apc_delete($iter);
}
diff --git a/lib/private/memcache/factory.php b/lib/private/memcache/factory.php
index 8e47a8899fc..dba9e8a0e00 100644
--- a/lib/private/memcache/factory.php
+++ b/lib/private/memcache/factory.php
@@ -37,6 +37,8 @@ class Factory implements ICacheFactory {
return new APCu($prefix);
} elseif (APC::isAvailable()) {
return new APC($prefix);
+ } elseif (Redis::isAvailable()) {
+ return new Redis($prefix);
} elseif (Memcached::isAvailable()) {
return new Memcached($prefix);
} else {
@@ -50,7 +52,7 @@ class Factory implements ICacheFactory {
* @return bool
*/
public function isAvailable() {
- return XCache::isAvailable() || APCu::isAvailable() || APC::isAvailable() || Memcached::isAvailable();
+ return XCache::isAvailable() || APCu::isAvailable() || APC::isAvailable() || Redis::isAvailable() || Memcached::isAvailable();
}
/**
diff --git a/lib/private/memcache/memcached.php b/lib/private/memcache/memcached.php
index cd8e2e8d0b6..042fead3347 100644
--- a/lib/private/memcache/memcached.php
+++ b/lib/private/memcache/memcached.php
@@ -74,7 +74,13 @@ class Memcached extends Cache {
$keys[] = $key;
}
}
- self::$cache->deleteMulti($keys);
+ if (method_exists(self::$cache, 'deleteMulti')) {
+ self::$cache->deleteMulti($keys);
+ } else {
+ foreach ($keys as $key) {
+ self::$cache->delete($key);
+ }
+ }
return true;
}
diff --git a/lib/private/memcache/redis.php b/lib/private/memcache/redis.php
new file mode 100644
index 00000000000..f21619887d0
--- /dev/null
+++ b/lib/private/memcache/redis.php
@@ -0,0 +1,94 @@
+<?php
+/**
+ * Copyright (c) 2014 Jörn Friedrich Dreyer <jfd@butonic.de>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OC\Memcache;
+
+class Redis extends Cache {
+
+ /**
+ * @var \Redis $cache
+ */
+ private static $cache = null;
+
+ public function __construct($prefix = '') {
+ parent::__construct($prefix);
+ if (is_null(self::$cache)) {
+ // TODO allow configuring a RedisArray, see https://github.com/nicolasff/phpredis/blob/master/arrays.markdown#redis-arrays
+ self::$cache = new \Redis();
+ $config = \OC::$server->getSystemConfig()->getValue('redis', array());
+ if (isset($config['host'])) {
+ $host = $config['host'];
+ } else {
+ $host = '127.0.0.1';
+ }
+ if (isset($config['port'])) {
+ $port = $config['port'];
+ } else {
+ $port = 6379;
+ }
+ if (isset($config['timeout'])) {
+ $timeout = $config['timeout'];
+ } else {
+ $timeout = 0.0; // unlimited
+ }
+ self::$cache->connect( $host, $port, $timeout );
+ }
+ }
+
+ /**
+ * entries in redis get namespaced to prevent collisions between ownCloud instances and users
+ */
+ protected function getNameSpace() {
+ return $this->prefix;
+ }
+
+ public function get($key) {
+ $result = self::$cache->get($this->getNamespace() . $key);
+ if ($result === false and ! self::$cache->exists($this->getNamespace() . $key)) {
+ return null;
+ } else {
+ return $result;
+ }
+ }
+
+ public function set($key, $value, $ttl = 0) {
+ if ($ttl > 0) {
+ return self::$cache->setex($this->getNamespace() . $key, $ttl, $value);
+ } else {
+ return self::$cache->set($this->getNamespace() . $key, $value);
+ }
+ }
+
+ public function hasKey($key) {
+ return self::$cache->exists($this->getNamespace() . $key);
+ }
+
+ public function remove($key) {
+ if (self::$cache->delete($this->getNamespace() . $key)) {
+ return true;
+ } else {
+ return false;
+ }
+
+ }
+
+ public function clear($prefix = '') {
+ $prefix = $this->getNamespace() . $prefix.'*';
+ $it = null;
+ self::$cache->setOption(\Redis::OPT_SCAN, \Redis::SCAN_RETRY);
+ while($keys = self::$cache->scan($it, $prefix)) {
+ self::$cache->delete($keys);
+ }
+ return true;
+ }
+
+ static public function isAvailable() {
+ return extension_loaded('redis');
+ }
+}
+
diff --git a/lib/private/preview.php b/lib/private/preview.php
index 7305bf1cc0e..a586c94fd11 100644
--- a/lib/private/preview.php
+++ b/lib/private/preview.php
@@ -922,6 +922,11 @@ class Preview {
return false;
}
+ $mount = $file->getMountPoint();
+ if ($mount and !$mount->getOption('previews', true)){
+ return false;
+ }
+
//check if there are preview backends
if (empty(self::$providers)) {
self::initProviders();
diff --git a/lib/private/template.php b/lib/private/template.php
index bda802fd2e2..78ebb506385 100644
--- a/lib/private/template.php
+++ b/lib/private/template.php
@@ -122,7 +122,7 @@ class OC_Template extends \OC\Template\Base {
foreach(OC_Util::$headers as $header) {
$headers .= '<'.OC_Util::sanitizeHTML($header['tag']);
foreach($header['attributes'] as $name=>$value) {
- $headers .= ' "'.OC_Util::sanitizeHTML($name).'"="'.OC_Util::sanitizeHTML($value).'"';
+ $headers .= ' '.OC_Util::sanitizeHTML($name).'="'.OC_Util::sanitizeHTML($value).'"';
}
if ($header['text'] !== null) {
$headers .= '>'.OC_Util::sanitizeHTML($header['text']).'</'.OC_Util::sanitizeHTML($header['tag']).'>';
diff --git a/lib/private/user.php b/lib/private/user.php
index 516b789d430..d66354b247d 100644
--- a/lib/private/user.php
+++ b/lib/private/user.php
@@ -212,9 +212,6 @@ class OC_User {
* Log in a user and regenerate a new session - if the password is ok
*/
public static function login($loginname, $password) {
- $loginname = str_replace("\0", '', $loginname);
- $password = str_replace("\0", '', $password);
-
session_regenerate_id(true);
$result = self::getUserSession()->login($loginname, $password);
if ($result) {
@@ -320,6 +317,15 @@ class OC_User {
}
/**
+ * Tries to login the user with HTTP Basic Authentication
+ */
+ public static function tryBasicAuthLogin() {
+ if(!empty($_SERVER['PHP_AUTH_USER']) && !empty($_SERVER['PHP_AUTH_USER'])) {
+ \OC_User::login($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']);
+ }
+ }
+
+ /**
* Check if the user is logged in, considers also the HTTP basic credentials
* @return bool
*/
@@ -328,11 +334,6 @@ class OC_User {
return self::userExists(\OC::$server->getSession()->get('user_id'));
}
- // Check whether the user has authenticated using Basic Authentication
- if (isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW'])) {
- return \OC_User::login($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']);
- }
-
return false;
}
diff --git a/lib/private/user/database.php b/lib/private/user/database.php
index a6289066f05..de6c72e4745 100644
--- a/lib/private/user/database.php
+++ b/lib/private/user/database.php
@@ -36,7 +36,7 @@
/**
* Class for user management in a SQL Database (e.g. MySQL, SQLite)
*/
-class OC_User_Database extends OC_User_Backend {
+class OC_User_Database extends OC_User_Backend implements \OCP\IUserBackend {
private $cache = array();
/**
@@ -260,4 +260,12 @@ class OC_User_Database extends OC_User_Backend {
return $result->fetchOne();
}
+ /**
+ * Backend name to be shown in user management
+ * @return string the name of the backend to be shown
+ */
+ public function getBackendName(){
+ return 'Database';
+ }
+
}
diff --git a/lib/private/user/dummy.php b/lib/private/user/dummy.php
index fd0201734fa..322a4562ee6 100644
--- a/lib/private/user/dummy.php
+++ b/lib/private/user/dummy.php
@@ -24,7 +24,7 @@
/**
* dummy user backend, does not keep state, only for testing use
*/
-class OC_User_Dummy extends OC_User_Backend {
+class OC_User_Dummy extends OC_User_Backend implements \OCP\IUserBackend {
private $users = array();
private $displayNames = array();
@@ -156,4 +156,12 @@ class OC_User_Dummy extends OC_User_Backend {
public function getDisplayName($uid) {
return isset($this->displayNames[$uid])? $this->displayNames[$uid]: $uid;
}
+
+ /**
+ * Backend name to be shown in user management
+ * @return string the name of the backend to be shown
+ */
+ public function getBackendName(){
+ return 'Dummy';
+ }
}
diff --git a/lib/private/user/http.php b/lib/private/user/http.php
index 617e8adb3f2..8375c4e1e22 100644
--- a/lib/private/user/http.php
+++ b/lib/private/user/http.php
@@ -24,7 +24,7 @@
/**
* user backend using http auth requests
*/
-class OC_User_HTTP extends OC_User_Backend {
+class OC_User_HTTP extends OC_User_Backend implements \OCP\IUserBackend {
/**
* split http://user@host/path into a user and url part
* @param string $url
@@ -109,4 +109,12 @@ class OC_User_HTTP extends OC_User_Backend {
return false;
}
}
+
+ /**
+ * Backend name to be shown in user management
+ * @return string the name of the backend to be shown
+ */
+ public function getBackendName(){
+ return 'HTTP';
+ }
}
diff --git a/lib/private/user/manager.php b/lib/private/user/manager.php
index 1bc3b51c2ef..1fc89f8c2c2 100644
--- a/lib/private/user/manager.php
+++ b/lib/private/user/manager.php
@@ -151,6 +151,9 @@ class Manager extends PublicEmitter implements IUserManager {
* @return mixed the User object on success, false otherwise
*/
public function checkPassword($loginname, $password) {
+ $loginname = str_replace("\0", '', $loginname);
+ $password = str_replace("\0", '', $password);
+
foreach ($this->backends as $backend) {
if ($backend->implementsActions(\OC_User_Backend::CHECK_PASSWORD)) {
$uid = $backend->checkPassword($loginname, $password);
@@ -276,10 +279,15 @@ class Manager extends PublicEmitter implements IUserManager {
if ($backend->implementsActions(\OC_User_Backend::COUNT_USERS)) {
$backendusers = $backend->countUsers();
if($backendusers !== false) {
- if(isset($userCountStatistics[get_class($backend)])) {
- $userCountStatistics[get_class($backend)] += $backendusers;
+ if($backend instanceof \OCP\IUserBackend) {
+ $name = $backend->getBackendName();
} else {
- $userCountStatistics[get_class($backend)] = $backendusers;
+ $name = get_class($backend);
+ }
+ if(isset($userCountStatistics[$name])) {
+ $userCountStatistics[$name] += $backendusers;
+ } else {
+ $userCountStatistics[$name] = $backendusers;
}
}
}
diff --git a/lib/private/user/user.php b/lib/private/user/user.php
index 062081d51d4..0b4f9a24276 100644
--- a/lib/private/user/user.php
+++ b/lib/private/user/user.php
@@ -225,6 +225,9 @@ class User implements IUser {
* @return string
*/
public function getBackendClassName() {
+ if($this->backend instanceof \OCP\IUserBackend) {
+ return $this->backend->getBackendName();
+ }
return get_class($this->backend);
}
diff --git a/lib/private/util.php b/lib/private/util.php
index 6ccb9dba087..b97c0684629 100644
--- a/lib/private/util.php
+++ b/lib/private/util.php
@@ -333,9 +333,9 @@ class OC_Util {
/**
* generates a path for JS/CSS files. If no application is provided it will create the path for core.
*
- * @param $application application to get the files from
- * @param $directory directory withing this application (css, js, vendor, etc)
- * @param $file the file inside of the above folder
+ * @param string $application application to get the files from
+ * @param string $directory directory withing this application (css, js, vendor, etc)
+ * @param string $file the file inside of the above folder
* @return string the path
*/
private static function generatePath($application, $directory, $file) {
@@ -358,7 +358,10 @@ class OC_Util {
* @return void
*/
public static function addScript($application, $file = null) {
- self::$scripts[] = OC_Util::generatePath($application, 'js', $file);
+ $path = OC_Util::generatePath($application, 'js', $file);
+ if (!in_array($path, self::$scripts)) {
+ self::$scripts[] = $path;
+ }
}
/**
@@ -369,7 +372,10 @@ class OC_Util {
* @return void
*/
public static function addVendorScript($application, $file = null) {
- self::$scripts[] = OC_Util::generatePath($application, 'vendor', $file);
+ $path = OC_Util::generatePath($application, 'vendor', $file);
+ if (!in_array($path, self::$scripts)) {
+ self::$scripts[] = $path;
+ }
}
/**
@@ -384,9 +390,12 @@ class OC_Util {
$languageCode = $l->getLanguageCode($application);
}
if (!empty($application)) {
- self::$scripts[] = "$application/l10n/$languageCode";
+ $path = "$application/l10n/$languageCode";
} else {
- self::$scripts[] = "l10n/$languageCode";
+ $path = "l10n/$languageCode";
+ }
+ if (!in_array($path, self::$scripts)) {
+ self::$scripts[] = $path;
}
}
@@ -398,7 +407,10 @@ class OC_Util {
* @return void
*/
public static function addStyle($application, $file = null) {
- self::$styles[] = OC_Util::generatePath($application, 'css', $file);
+ $path = OC_Util::generatePath($application, 'css', $file);
+ if (!in_array($path, self::$styles)) {
+ self::$styles[] = $path;
+ }
}
/**
@@ -409,7 +421,10 @@ class OC_Util {
* @return void
*/
public static function addVendorStyle($application, $file = null) {
- self::$styles[] = OC_Util::generatePath($application, 'vendor', $file);
+ $path = OC_Util::generatePath($application, 'vendor', $file);
+ if (!in_array($path, self::$styles)) {
+ self::$styles[] = $path;
+ }
}
/**
@@ -1344,4 +1359,5 @@ class OC_Util {
public static function isPhpCharSetUtf8() {
return ini_get('default_charset') === 'UTF-8';
}
+
}