diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/base.php | 6 | ||||
-rw-r--r-- | lib/connector/sabre/directory.php | 15 | ||||
-rw-r--r-- | lib/connector/sabre/file.php | 15 | ||||
-rw-r--r-- | lib/connector/sabre/locks.php | 6 | ||||
-rw-r--r-- | lib/connector/sabre/node.php | 4 | ||||
-rw-r--r-- | lib/db.php | 78 | ||||
-rw-r--r-- | lib/files/filesystem.php | 16 | ||||
-rw-r--r-- | lib/files/mount/mount.php | 27 | ||||
-rw-r--r-- | lib/files/storage/loader.php | 38 | ||||
-rw-r--r-- | lib/files/storage/wrapper/wrapper.php | 427 | ||||
-rw-r--r-- | lib/files/stream/staticstream.php | 55 | ||||
-rw-r--r-- | lib/files/view.php | 2 | ||||
-rw-r--r-- | lib/l10n/el.php | 1 | ||||
-rw-r--r-- | lib/l10n/eo.php | 18 | ||||
-rw-r--r-- | lib/l10n/sl.php | 1 | ||||
-rw-r--r-- | lib/legacy/log.php | 77 | ||||
-rw-r--r-- | lib/log.php | 153 | ||||
-rw-r--r-- | lib/public/share.php | 34 | ||||
-rw-r--r-- | lib/vcategories.php | 2 |
19 files changed, 850 insertions, 125 deletions
diff --git a/lib/base.php b/lib/base.php index 26e9595e869..fd4870974fe 100644 --- a/lib/base.php +++ b/lib/base.php @@ -288,14 +288,14 @@ class OC { $cookie_path = OC::$WEBROOT ?: '/'; ini_set('session.cookie_path', $cookie_path); + //set the session object to a dummy session so code relying on the session existing still works + self::$session = new \OC\Session\Memory(''); + try{ // set the session name to the instance id - which is unique self::$session = new \OC\Session\Internal(OC_Util::getInstanceId()); // if session cant be started break with http 500 error }catch (Exception $e){ - //set the session object to a dummy session so code relying on the session existing still works - self::$session = new \OC\Session\Memory(''); - OC_Log::write('core', 'Session could not be initialized', OC_Log::ERROR); diff --git a/lib/connector/sabre/directory.php b/lib/connector/sabre/directory.php index 6ccb54b79ab..3d15a2a584d 100644 --- a/lib/connector/sabre/directory.php +++ b/lib/connector/sabre/directory.php @@ -45,9 +45,15 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa * * @param string $name Name of the file * @param resource|string $data Initial payload + * @throws Sabre_DAV_Exception_Forbidden * @return null|string */ public function createFile($name, $data = null) { + + if (!\OC\Files\Filesystem::isCreatable($this->path)) { + throw new \Sabre_DAV_Exception_Forbidden(); + } + if (isset($_SERVER['HTTP_OC_CHUNKED'])) { $info = OC_FileChunking::decodeName($name); if (empty($info)) { @@ -102,10 +108,15 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa * Creates a new subdirectory * * @param string $name + * @throws Sabre_DAV_Exception_Forbidden * @return void */ public function createDirectory($name) { + if (!\OC\Files\Filesystem::isCreatable($this->path)) { + throw new \Sabre_DAV_Exception_Forbidden(); + } + $newPath = $this->path . '/' . $name; if(!\OC\Files\Filesystem::mkdir($newPath)) { throw new Sabre_DAV_Exception_Forbidden('Could not create directory '.$newPath); @@ -203,9 +214,13 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa * Deletes all files in this directory, and then itself * * @return void + * @throws Sabre_DAV_Exception_Forbidden */ public function delete() { + if (!\OC\Files\Filesystem::isDeletable($this->path)) { + throw new \Sabre_DAV_Exception_Forbidden(); + } if ($this->path != "/Shared") { foreach($this->getChildren() as $child) $child->delete(); \OC\Files\Filesystem::rmdir($this->path); diff --git a/lib/connector/sabre/file.php b/lib/connector/sabre/file.php index 91646312e90..438d9871c22 100644 --- a/lib/connector/sabre/file.php +++ b/lib/connector/sabre/file.php @@ -41,24 +41,29 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D * return an ETag, and just return null. * * @param resource $data + * @throws Sabre_DAV_Exception_Forbidden * @return string|null */ public function put($data) { + if (!\OC\Files\Filesystem::isUpdatable($this->path)) { + throw new \Sabre_DAV_Exception_Forbidden(); + } + // mark file as partial while uploading (ignored by the scanner) $partpath = $this->path . '.part'; \OC\Files\Filesystem::file_put_contents($partpath, $data); //detect aborted upload - if (isset ($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'PUT' ) { + if (isset ($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'PUT') { if (isset($_SERVER['CONTENT_LENGTH'])) { $expected = $_SERVER['CONTENT_LENGTH']; $actual = \OC\Files\Filesystem::filesize($partpath); if ($actual != $expected) { \OC\Files\Filesystem::unlink($partpath); throw new Sabre_DAV_Exception_BadRequest( - 'expected filesize ' . $expected . ' got ' . $actual); + 'expected filesize ' . $expected . ' got ' . $actual); } } } @@ -69,7 +74,7 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D //allow sync clients to send the mtime along in a header $mtime = OC_Request::hasModificationTime(); if ($mtime !== false) { - if(\OC\Files\Filesystem::touch($this->path, $mtime)) { + if (\OC\Files\Filesystem::touch($this->path, $mtime)) { header('X-OC-MTime: accepted'); } } @@ -92,9 +97,13 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D * Delete the current file * * @return void + * @throws Sabre_DAV_Exception_Forbidden */ public function delete() { + if (!\OC\Files\Filesystem::isDeletable($this->path)) { + throw new \Sabre_DAV_Exception_Forbidden(); + } \OC\Files\Filesystem::unlink($this->path); } diff --git a/lib/connector/sabre/locks.php b/lib/connector/sabre/locks.php index cbc495dec19..69496c15ada 100644 --- a/lib/connector/sabre/locks.php +++ b/lib/connector/sabre/locks.php @@ -176,9 +176,13 @@ class OC_Connector_Sabre_Locks extends Sabre_DAV_Locks_Backend_Abstract { public function unlock($uri, Sabre_DAV_Locks_LockInfo $lockInfo) { $sql = 'DELETE FROM `*PREFIX*locks` WHERE `userid` = ? AND `uri` = ? AND `token` = ?'; + if (OC_Config::getValue( "dbtype") === 'oci') { + //FIXME oracle hack: need to explicitly cast CLOB to CHAR for comparison + $sql = 'DELETE FROM `*PREFIX*locks` WHERE `userid` = ? AND to_char(`uri`) = ? AND `token` = ?'; + } $result = OC_DB::executeAudited( $sql, array(OC_User::getUser(), $uri, $lockInfo->token)); - return $result->numRows() === 1; + return $result === 1; } diff --git a/lib/connector/sabre/node.php b/lib/connector/sabre/node.php index 1ffa048d6b2..0bffa58af78 100644 --- a/lib/connector/sabre/node.php +++ b/lib/connector/sabre/node.php @@ -189,8 +189,8 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr */ public function getProperties($properties) { if (is_null($this->property_cache)) { - $query = OC_DB::prepare( 'SELECT * FROM `*PREFIX*properties` WHERE `userid` = ? AND `propertypath` = ?' ); - $result = $query->execute( array( OC_User::getUser(), $this->path )); + $sql = 'SELECT * FROM `*PREFIX*properties` WHERE `userid` = ? AND `propertypath` = ?'; + $result = OC_DB::executeAudited( $sql, array( OC_User::getUser(), $this->path ) ); $this->property_cache = array(); while( $row = $result->fetchRow()) { diff --git a/lib/db.php b/lib/db.php index a6b81aaba69..4d6788f2bda 100644 --- a/lib/db.php +++ b/lib/db.php @@ -326,11 +326,12 @@ class OC_DB { * @param string $query Query string * @param int $limit * @param int $offset + * @param bool $isManipulation * @return MDB2_Statement_Common prepared SQL query * * SQL query via MDB2 prepare(), needs to be execute()'d! */ - static public function prepare( $query , $limit=null, $offset=null ) { + static public function prepare( $query , $limit = null, $offset = null, $isManipulation = null) { if (!is_null($limit) && $limit != -1) { if (self::$backend == self::BACKEND_MDB2) { @@ -367,12 +368,23 @@ class OC_DB { OC_Log::write('core', 'DB prepare : '.$query, OC_Log::DEBUG); } self::connect(); + + if ($isManipulation === null) { + //try to guess, so we return the number of rows on manipulations + $isManipulation = self::isManipulation($query); + } + // return the result if(self::$backend==self::BACKEND_MDB2) { - $result = self::$connection->prepare( $query ); + // differentiate between query and manipulation + if ($isManipulation) { + $result = self::$connection->prepare( $query, null, MDB2_PREPARE_MANIP ); + } else { + $result = self::$connection->prepare( $query, null, MDB2_PREPARE_RESULT ); + } // Die if we have an error (error means: bad query, not 0 results!) - if( PEAR::isError($result)) { + if( self::isError($result)) { throw new DatabaseException($result->getMessage(), $query); } }else{ @@ -381,7 +393,8 @@ class OC_DB { }catch(PDOException $e) { throw new DatabaseException($e->getMessage(), $query); } - $result=new PDOStatementWrapper($result); + // differentiate between query and manipulation + $result = new PDOStatementWrapper($result, $isManipulation); } if ((is_null($limit) || $limit == -1) and self::$cachingEnabled ) { $type = OC_Config::getValue( "dbtype", "sqlite" ); @@ -391,7 +404,33 @@ class OC_DB { } return $result; } - + + /** + * tries to guess the type of statement based on the first 10 characters + * the current check allows some whitespace but does not work with IF EXISTS or other more complex statements + * + * @param string $sql + */ + static public function isManipulation( $sql ) { + $selectOccurence = stripos ($sql, "SELECT"); + if ($selectOccurence !== false && $selectOccurence < 10) { + return false; + } + $insertOccurence = stripos ($sql, "INSERT"); + if ($insertOccurence !== false && $insertOccurence < 10) { + return true; + } + $updateOccurence = stripos ($sql, "UPDATE"); + if ($updateOccurence !== false && $updateOccurence < 10) { + return true; + } + $deleteOccurance = stripos ($sql, "DELETE"); + if ($deleteOccurance !== false && $deleteOccurance < 10) { + return true; + } + return false; + } + /** * @brief execute a prepared statement, on error write log and throw exception * @param mixed $stmt PDOStatementWrapper | MDB2_Statement_Common , @@ -718,6 +757,9 @@ class OC_DB { } catch(PDOException $e) { OC_Template::printExceptionErrorPage( $e ); } + if ($result === 0) { + return true; + } return $result; } @@ -754,6 +796,7 @@ class OC_DB { }elseif( $type == 'oci' ) { $query = str_replace( '`', '"', $query ); $query = str_ireplace( 'NOW()', 'CURRENT_TIMESTAMP', $query ); + $query = str_ireplace( 'UNIX_TIMESTAMP()', '((CAST(SYS_EXTRACT_UTC(systimestamp) AS DATE))-TO_DATE(\'1970101000000\',\'YYYYMMDDHH24MiSS\'))*24*3600', $query ); }elseif( $type == 'mssql' ) { $query = preg_replace( "/\`(.*?)`/", "[$1]", $query ); $query = str_replace( 'NOW()', 'CURRENT_TIMESTAMP', $query ); @@ -919,7 +962,7 @@ class OC_DB { * @return bool */ public static function isError($result) { - if(!$result) { + if(self::$backend==self::BACKEND_PDO and $result === false) { return true; }elseif(self::$backend==self::BACKEND_MDB2 and PEAR::isError($result)) { return true; @@ -997,11 +1040,13 @@ class PDOStatementWrapper{ /** * @var PDOStatement */ - private $statement=null; - private $lastArguments=array(); + private $statement = null; + private $isManipulation = false; + private $lastArguments = array(); - public function __construct($statement) { - $this->statement=$statement; + public function __construct($statement, $isManipulation = false) { + $this->statement = $statement; + $this->isManipulation = $isManipulation; } /** @@ -1023,16 +1068,19 @@ class PDOStatementWrapper{ $input = $this->tryFixSubstringLastArgumentDataForMSSQL($input); } - $result=$this->statement->execute($input); + $result = $this->statement->execute($input); } else { - $result=$this->statement->execute(); + $result = $this->statement->execute(); } - if ($result) { - return $this; - } else { + if ($result === false) { return false; } + if ($this->isManipulation) { + return $this->statement->rowCount(); + } else { + return $this; + } } private function tryFixSubstringLastArgumentDataForMSSQL($input) { diff --git a/lib/files/filesystem.php b/lib/files/filesystem.php index d3fddf8c421..3d7d5abf8fe 100644 --- a/lib/files/filesystem.php +++ b/lib/files/filesystem.php @@ -30,6 +30,7 @@ namespace OC\Files; +use OC\Files\Storage\Loader; const FREE_SPACE_UNKNOWN = -2; const FREE_SPACE_UNLIMITED = -3; @@ -143,6 +144,18 @@ class Filesystem { const signal_param_run = 'run'; /** + * @var \OC\Files\Storage\Loader $loader + */ + private static $loader; + + public static function getLoader(){ + if (!self::$loader) { + self::$loader = new Loader(); + } + return self::$loader; + } + + /** * 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 @@ -239,6 +252,7 @@ class Filesystem { if (self::$defaultInstance) { return false; } + self::getLoader(); self::$defaultInstance = new View($root); if (!self::$mounts) { @@ -393,7 +407,7 @@ class Filesystem { if (!self::$mounts) { \OC_Util::setupFS(); } - $mount = new Mount\Mount($class, $mountpoint, $arguments); + $mount = new Mount\Mount($class, $mountpoint, $arguments, self::getLoader()); self::$mounts->addMount($mount); } diff --git a/lib/files/mount/mount.php b/lib/files/mount/mount.php index 69b8285ab4c..17b0055ee84 100644 --- a/lib/files/mount/mount.php +++ b/lib/files/mount/mount.php @@ -9,10 +9,10 @@ namespace OC\Files\Mount; use \OC\Files\Filesystem; +use OC\Files\Storage\Loader; +use OC\Files\Storage\Storage; class Mount { - - /** * @var \OC\Files\Storage\Storage $storage */ @@ -23,19 +23,30 @@ class Mount { private $mountPoint; /** - * @param string|\OC\Files\Storage\Storage $storage + * @var \OC\Files\Storage\Loader $loader + */ + private $loader; + + /** + * @param string | \OC\Files\Storage\Storage $storage * @param string $mountpoint - * @param array $arguments (optional) + * @param array $arguments (optional)\ + * @param \OC\Files\Storage\Loader $loader */ - public function __construct($storage, $mountpoint, $arguments = null) { + public function __construct($storage, $mountpoint, $arguments = null, $loader = null) { if (is_null($arguments)) { $arguments = array(); } + if (is_null($loader)) { + $this->loader = new Loader(); + } else { + $this->loader = $loader; + } $mountpoint = $this->formatPath($mountpoint); - if ($storage instanceof \OC\Files\Storage\Storage) { + if ($storage instanceof Storage) { $this->class = get_class($storage); - $this->storage = $storage; + $this->storage = $this->loader->wrap($mountpoint, $storage); } else { // Update old classes to new namespace if (strpos($storage, 'OC_Filestorage_') !== false) { @@ -62,7 +73,7 @@ class Mount { private function createStorage() { if (class_exists($this->class)) { try { - return new $this->class($this->arguments); + return $this->loader->load($this->mountPoint, $this->class, $this->arguments); } catch (\Exception $exception) { \OC_Log::write('core', $exception->getMessage(), \OC_Log::ERROR); return null; diff --git a/lib/files/storage/loader.php b/lib/files/storage/loader.php new file mode 100644 index 00000000000..2572ef443bc --- /dev/null +++ b/lib/files/storage/loader.php @@ -0,0 +1,38 @@ +<?php +/** + * Copyright (c) 2012 Robin Appelman <icewind@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OC\Files\Storage; + +class Loader { + /** + * @var callable[] $storageWrappers + */ + private $storageWrappers = array(); + + /** + * allow modifier storage behaviour by adding wrappers around storages + * + * $callback should be a function of type (string $mountPoint, Storage $storage) => Storage + * + * @param callable $callback + */ + public function addStorageWrapper($callback) { + $this->storageWrappers[] = $callback; + } + + public function load($mountPoint, $class, $arguments) { + return $this->wrap($mountPoint, new $class($arguments)); + } + + public function wrap($mountPoint, $storage) { + foreach ($this->storageWrappers as $wrapper) { + $storage = $wrapper($mountPoint, $storage); + } + return $storage; + } +} diff --git a/lib/files/storage/wrapper/wrapper.php b/lib/files/storage/wrapper/wrapper.php new file mode 100644 index 00000000000..4feb0520f12 --- /dev/null +++ b/lib/files/storage/wrapper/wrapper.php @@ -0,0 +1,427 @@ +<?php +/** + * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OC\Files\Storage\Wrapper; + +class Wrapper implements \OC\Files\Storage\Storage { + /** + * @var \OC\Files\Storage\Storage $storage + */ + protected $storage; + + /** + * @param array $parameters + */ + public function __construct($parameters) { + $this->storage = $parameters['storage']; + } + + /** + * @return \OC\Files\Storage\Storage + */ + public function getWrapperStorage() { + return $this->storage; + } + + /** + * Get the identifier for the storage, + * the returned id should be the same for every storage object that is created with the same parameters + * and two storage objects with the same id should refer to two storages that display the same files. + * + * @return string + */ + public function getId() { + return $this->storage->getId(); + } + + /** + * see http://php.net/manual/en/function.mkdir.php + * + * @param string $path + * @return bool + */ + public function mkdir($path) { + return $this->storage->mkdir($path); + } + + /** + * see http://php.net/manual/en/function.rmdir.php + * + * @param string $path + * @return bool + */ + public function rmdir($path) { + return $this->storage->rmdir($path); + } + + /** + * see http://php.net/manual/en/function.opendir.php + * + * @param string $path + * @return resource + */ + public function opendir($path) { + return $this->storage->opendir($path); + } + + /** + * see http://php.net/manual/en/function.is_dir.php + * + * @param string $path + * @return bool + */ + public function is_dir($path) { + return $this->storage->is_dir($path); + } + + /** + * see http://php.net/manual/en/function.is_file.php + * + * @param string $path + * @return bool + */ + public function is_file($path) { + return $this->storage->is_file($path); + } + + /** + * see http://php.net/manual/en/function.stat.php + * only the following keys are required in the result: size and mtime + * + * @param string $path + * @return array + */ + public function stat($path) { + return $this->storage->stat($path); + } + + /** + * see http://php.net/manual/en/function.filetype.php + * + * @param string $path + * @return bool + */ + public function filetype($path) { + return $this->storage->filetype($path); + } + + /** + * see http://php.net/manual/en/function.filesize.php + * The result for filesize when called on a folder is required to be 0 + * + * @param string $path + * @return int + */ + public function filesize($path) { + return $this->storage->filesize($path); + } + + /** + * check if a file can be created in $path + * + * @param string $path + * @return bool + */ + public function isCreatable($path) { + return $this->storage->isCreatable($path); + } + + /** + * check if a file can be read + * + * @param string $path + * @return bool + */ + public function isReadable($path) { + return $this->storage->isReadable($path); + } + + /** + * check if a file can be written to + * + * @param string $path + * @return bool + */ + public function isUpdatable($path) { + return $this->storage->isUpdatable($path); + } + + /** + * check if a file can be deleted + * + * @param string $path + * @return bool + */ + public function isDeletable($path) { + return $this->storage->isDeletable($path); + } + + /** + * check if a file can be shared + * + * @param string $path + * @return bool + */ + public function isSharable($path) { + return $this->storage->isSharable($path); + } + + /** + * get the full permissions of a path. + * Should return a combination of the PERMISSION_ constants defined in lib/public/constants.php + * + * @param string $path + * @return int + */ + public function getPermissions($path) { + return $this->storage->getPermissions($path); + } + + /** + * see http://php.net/manual/en/function.file_exists.php + * + * @param string $path + * @return bool + */ + public function file_exists($path) { + return $this->storage->file_exists($path); + } + + /** + * see http://php.net/manual/en/function.filemtime.php + * + * @param string $path + * @return int + */ + public function filemtime($path) { + return $this->storage->filemtime($path); + } + + /** + * see http://php.net/manual/en/function.file_get_contents.php + * + * @param string $path + * @return string + */ + public function file_get_contents($path) { + return $this->storage->file_get_contents($path); + } + + /** + * see http://php.net/manual/en/function.file_put_contents.php + * + * @param string $path + * @param string $data + * @return bool + */ + public function file_put_contents($path, $data) { + return $this->storage->file_put_contents($path, $data); + } + + /** + * see http://php.net/manual/en/function.unlink.php + * + * @param string $path + * @return bool + */ + public function unlink($path) { + return $this->storage->unlink($path); + } + + /** + * see http://php.net/manual/en/function.rename.php + * + * @param string $path1 + * @param string $path2 + * @return bool + */ + public function rename($path1, $path2) { + return $this->storage->rename($path1, $path2); + } + + /** + * see http://php.net/manual/en/function.copy.php + * + * @param string $path1 + * @param string $path2 + * @return bool + */ + public function copy($path1, $path2) { + return $this->storage->copy($path1, $path2); + } + + /** + * see http://php.net/manual/en/function.fopen.php + * + * @param string $path + * @param string $mode + * @return resource + */ + public function fopen($path, $mode) { + return $this->storage->fopen($path, $mode); + } + + /** + * get the mimetype for a file or folder + * The mimetype for a folder is required to be "httpd/unix-directory" + * + * @param string $path + * @return string + */ + public function getMimeType($path) { + return $this->storage->getMimeType($path); + } + + /** + * see http://php.net/manual/en/function.hash.php + * + * @param string $type + * @param string $path + * @param bool $raw + * @return string + */ + public function hash($type, $path, $raw = false) { + return $this->storage->hash($type, $path, $raw); + } + + /** + * see http://php.net/manual/en/function.free_space.php + * + * @param string $path + * @return int + */ + public function free_space($path) { + return $this->storage->free_space($path); + } + + /** + * search for occurrences of $query in file names + * + * @param string $query + * @return array + */ + public function search($query) { + return $this->storage->search($query); + } + + /** + * see http://php.net/manual/en/function.touch.php + * If the backend does not support the operation, false should be returned + * + * @param string $path + * @param int $mtime + * @return bool + */ + public function touch($path, $mtime = null) { + return $this->storage->touch($path, $mtime); + } + + /** + * get the path to a local version of the file. + * The local version of the file can be temporary and doesn't have to be persistent across requests + * + * @param string $path + * @return string + */ + public function getLocalFile($path) { + return $this->storage->getLocalFile($path); + } + + /** + * get the path to a local version of the folder. + * The local version of the folder can be temporary and doesn't have to be persistent across requests + * + * @param string $path + * @return string + */ + public function getLocalFolder($path) { + return $this->storage->getLocalFolder($path); + } + + /** + * check if a file or folder has been updated since $time + * + * @param string $path + * @param int $time + * @return bool + * + * hasUpdated for folders should return at least true if a file inside the folder is add, removed or renamed. + * returning true for other changes in the folder is optional + */ + public function hasUpdated($path, $time) { + return $this->storage->hasUpdated($path, $time); + } + + /** + * get a cache instance for the storage + * + * @param string $path + * @return \OC\Files\Cache\Cache + */ + public function getCache($path = '') { + return $this->storage->getCache($path); + } + + /** + * get a scanner instance for the storage + * + * @param string $path + * @return \OC\Files\Cache\Scanner + */ + public function getScanner($path = '') { + return $this->storage->getScanner($path); + } + + + /** + * get the user id of the owner of a file or folder + * + * @param string $path + * @return string + */ + public function getOwner($path) { + return $this->storage->getOwner($path); + } + + /** + * get a permissions cache instance for the cache + * + * @param string $path + * @return \OC\Files\Cache\Permissions + */ + public function getPermissionsCache($path = '') { + return $this->storage->getPermissions($path); + } + + /** + * get a watcher instance for the cache + * + * @param string $path + * @return \OC\Files\Cache\Watcher + */ + public function getWatcher($path = '') { + return $this->storage->getWatcher($path); + } + + /** + * @return \OC\Files\Cache\Storage + */ + public function getStorageCache() { + return $this->storage->getStorageCache(); + } + + /** + * get the ETag for a file or folder + * + * @param string $path + * @return string + */ + public function getETag($path) { + return $this->storage->getETag($path); + } +} diff --git a/lib/files/stream/staticstream.php b/lib/files/stream/staticstream.php index 7725a6a5a04..45b1a7a81f8 100644 --- a/lib/files/stream/staticstream.php +++ b/lib/files/stream/staticstream.php @@ -9,6 +9,8 @@ namespace OC\Files\Stream; class StaticStream { + const MODE_FILE = 0100000; + public $context; protected static $data = array(); @@ -26,6 +28,10 @@ class StaticStream { public function stream_flush() { } + public static function clear() { + self::$data = array(); + } + public function stream_open($path, $mode, $options, &$opened_path) { switch ($mode[0]) { case 'r': @@ -94,36 +100,7 @@ class StaticStream { } public function stream_stat() { - $size = strlen(self::$data[$this->path]); - $time = time(); - return array( - 0 => 0, - 'dev' => 0, - 1 => 0, - 'ino' => 0, - 2 => 0777, - 'mode' => 0777, - 3 => 1, - 'nlink' => 1, - 4 => 0, - 'uid' => 0, - 5 => 0, - 'gid' => 0, - 6 => '', - 'rdev' => '', - 7 => $size, - 'size' => $size, - 8 => $time, - 'atime' => $time, - 9 => $time, - 'mtime' => $time, - 10 => $time, - 'ctime' => $time, - 11 => -1, - 'blksize' => -1, - 12 => -1, - 'blocks' => -1, - ); + return $this->url_stat($this->path); } public function stream_tell() { @@ -157,34 +134,22 @@ class StaticStream { if (isset(self::$data[$path])) { $size = strlen(self::$data[$path]); $time = time(); - return array( - 0 => 0, + $data = array( 'dev' => 0, - 1 => 0, 'ino' => 0, - 2 => 0777, - 'mode' => 0777, - 3 => 1, + 'mode' => self::MODE_FILE | 0777, 'nlink' => 1, - 4 => 0, 'uid' => 0, - 5 => 0, 'gid' => 0, - 6 => '', 'rdev' => '', - 7 => $size, 'size' => $size, - 8 => $time, 'atime' => $time, - 9 => $time, 'mtime' => $time, - 10 => $time, 'ctime' => $time, - 11 => -1, 'blksize' => -1, - 12 => -1, 'blocks' => -1, ); + return array_values($data) + $data; } return false; } diff --git a/lib/files/view.php b/lib/files/view.php index 25071709fbe..d8d99698023 100644 --- a/lib/files/view.php +++ b/lib/files/view.php @@ -754,7 +754,7 @@ class View { if ($subStorage) { $subCache = $subStorage->getCache(''); $rootEntry = $subCache->get(''); - $data['size'] += $rootEntry['size']; + $data['size'] += isset($rootEntry['size']) ? $rootEntry['size'] : 0; } } } diff --git a/lib/l10n/el.php b/lib/l10n/el.php index 8637b8da269..cd025aec78d 100644 --- a/lib/l10n/el.php +++ b/lib/l10n/el.php @@ -24,6 +24,7 @@ "%s set the database host." => "%s ρυθμίση του κεντρικόυ υπολογιστή βάσης δεδομένων. ", "PostgreSQL username and/or password not valid" => "Μη έγκυρος χρήστης και/ή συνθηματικό της PostgreSQL", "You need to enter either an existing account or the administrator." => "Χρειάζεται να εισάγετε είτε έναν υπάρχον λογαριασμό ή του διαχειριστή.", +"Oracle connection could not be established" => "Αδυναμία σύνδεσης Oracle", "MySQL username and/or password not valid" => "Μη έγκυρος χρήστης και/ή συνθηματικό της MySQL", "DB Error: \"%s\"" => "Σφάλμα Βάσης Δεδομένων: \"%s\"", "Offending command was: \"%s\"" => "Η εντολη παραβατικοτητας ηταν: \"%s\"", diff --git a/lib/l10n/eo.php b/lib/l10n/eo.php index 2782be65da9..327fe75b9d2 100644 --- a/lib/l10n/eo.php +++ b/lib/l10n/eo.php @@ -15,6 +15,24 @@ "Files" => "Dosieroj", "Text" => "Teksto", "Images" => "Bildoj", +"Set an admin username." => "Starigi administran uzantonomon.", +"Set an admin password." => "Starigi administran pasvorton.", +"%s enter the database username." => "%s enigu la uzantonomon de la datumbazo.", +"%s enter the database name." => "%s enigu la nomon de la datumbazo.", +"%s you may not use dots in the database name" => "%s vi ne povas uzi punktojn en la nomo de la datumbazo", +"%s set the database host." => "%s enigu la gastigon de la datumbazo.", +"PostgreSQL username and/or password not valid" => "La uzantonomo de PostgreSQL aŭ la pasvorto ne validas", +"Oracle connection could not be established" => "Konekto al Oracle ne povas stariĝi", +"MySQL username and/or password not valid" => "La uzantonomo de MySQL aŭ la pasvorto ne validas", +"DB Error: \"%s\"" => "Datumbaza eraro: “%s”", +"MySQL user '%s'@'localhost' exists already." => "La uzanto de MySQL “%s”@“localhost” jam ekzistas.", +"Drop this user from MySQL" => "Forigi ĉi tiun uzanton el MySQL", +"MySQL user '%s'@'%%' already exists" => "La uzanto de MySQL “%s”@“%%” jam ekzistas", +"Drop this user from MySQL." => "Forigi ĉi tiun uzanton el MySQL.", +"Oracle username and/or password not valid" => "La uzantonomo de Oracle aŭ la pasvorto ne validas", +"MS SQL username and/or password not valid: %s" => "La uzantonomo de MS SQL aŭ la pasvorto ne validas: %s", +"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Via TTT-servilo ankoraŭ ne ĝuste agordiĝis por permesi sinkronigi dosierojn ĉar la WebDAV-interfaco ŝajnas rompita.", +"Please double check the <a href='%s'>installation guides</a>." => "Bonvolu duoble kontroli la <a href='%s'>gvidilon por instalo</a>.", "seconds ago" => "sekundoj antaŭe", "1 minute ago" => "antaŭ 1 minuto", "%d minutes ago" => "antaŭ %d minutoj", diff --git a/lib/l10n/sl.php b/lib/l10n/sl.php index 7f8827d17f3..2073f545232 100644 --- a/lib/l10n/sl.php +++ b/lib/l10n/sl.php @@ -24,6 +24,7 @@ "%s set the database host." => "%s - vnos gostitelja podatkovne zbirke.", "PostgreSQL username and/or password not valid" => "Uporabniško ime ali geslo PostgreSQL ni veljavno", "You need to enter either an existing account or the administrator." => "Prijaviti se je treba v obstoječi ali pa skrbniški račun.", +"Oracle connection could not be established" => "Povezava z bazo Oracle ni uspela.", "MySQL username and/or password not valid" => "Uporabniško ime ali geslo MySQL ni veljavno", "DB Error: \"%s\"" => "Napaka podatkovne zbirke: \"%s\"", "Offending command was: \"%s\"" => "Napačni ukaz je: \"%s\"", diff --git a/lib/legacy/log.php b/lib/legacy/log.php new file mode 100644 index 00000000000..7802ead2412 --- /dev/null +++ b/lib/legacy/log.php @@ -0,0 +1,77 @@ +<?php +/** + * Copyright (c) 2012 Bart Visscher <bartv@thisnet.nl> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +/** + * logging utilities + * + * Log is saved by default at data/owncloud.log using OC_Log_Owncloud. + * Selecting other backend is done with a config option 'log_type'. + */ + +OC_Log::$object = new \OC\Log(); +class OC_Log { + public static $object; + + const DEBUG=0; + const INFO=1; + const WARN=2; + const ERROR=3; + const FATAL=4; + + static private $level_funcs = array( + self::DEBUG => 'debug', + self::INFO => 'info', + self::WARN => 'warning', + self::ERROR => 'error', + self::FATAL => 'emergency', + ); + + static public $enabled = true; + static protected $class = null; + + /** + * write a message in the log + * @param string $app + * @param string $message + * @param int $level + */ + public static function write($app, $message, $level) { + if (self::$enabled) { + $context = array('app' => $app); + $func = array(self::$object, self::$level_funcs[$level]); + call_user_func($func, $message, $context); + } + } + + //Fatal errors handler + public static function onShutdown() { + $error = error_get_last(); + if($error) { + //ob_end_clean(); + self::write('PHP', $error['message'] . ' at ' . $error['file'] . '#' . $error['line'], self::FATAL); + } else { + return true; + } + } + + // Uncaught exception handler + public static function onException($exception) { + self::write('PHP', + $exception->getMessage() . ' at ' . $exception->getFile() . '#' . $exception->getLine(), + self::FATAL); + } + + //Recoverable errors handler + public static function onError($number, $message, $file, $line) { + if (error_reporting() === 0) { + return; + } + self::write('PHP', $message . ' at ' . $file . '#' . $line, self::WARN); + + } +} diff --git a/lib/log.php b/lib/log.php index 3f3334801e5..e0b9fe3c696 100644 --- a/lib/log.php +++ b/lib/log.php @@ -1,69 +1,136 @@ <?php /** - * Copyright (c) 2012 Bart Visscher <bartv@thisnet.nl> + * Copyright (c) 2013 Bart Visscher <bartv@thisnet.nl> * This file is licensed under the Affero General Public License version 3 or * later. * See the COPYING-README file. */ +namespace OC; + /** * logging utilities * - * Log is saved by default at data/owncloud.log using OC_Log_Owncloud. - * Selecting other backend is done with a config option 'log_type'. + * This is a stand in, this should be replaced by a Psr\Log\LoggerInterface + * compatible logger. See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md + * for the full interface specification. + * + * MonoLog is an example implementing this interface. */ -class OC_Log { - const DEBUG=0; - const INFO=1; - const WARN=2; - const ERROR=3; - const FATAL=4; +class Log { + private $logClass; - static public $enabled = true; - static protected $class = null; + /** + * System is unusable. + * + * @param string $message + * @param array $context + */ + public function emergency($message, array $context = array()) { + $this->log(\OC_Log::FATAL, $message, $context); + } /** - * write a message in the log - * @param string $app + * Action must be taken immediately. + * + * Example: Entire website down, database unavailable, etc. This should + * trigger the SMS alerts and wake you up. + * * @param string $message - * @param int level + * @param array $context */ - public static function write($app, $message, $level) { - if (self::$enabled) { - if (!self::$class) { - self::$class = 'OC_Log_'.ucfirst(OC_Config::getValue('log_type', 'owncloud')); - call_user_func(array(self::$class, 'init')); - } - $log_class=self::$class; - $log_class::write($app, $message, $level); - } + public function alert($message, array $context = array()) { + $this->log(\OC_Log::ERROR, $message, $context); } - //Fatal errors handler - public static function onShutdown() { - $error = error_get_last(); - if($error) { - //ob_end_clean(); - self::write('PHP', $error['message'] . ' at ' . $error['file'] . '#' . $error['line'], self::FATAL); - } else { - return true; - } + /** + * Critical conditions. + * + * Example: Application component unavailable, unexpected exception. + * + * @param string $message + * @param array $context + */ + public function critical($message, array $context = array()) { + $this->log(\OC_Log::ERROR, $message, $context); } - // Uncaught exception handler - public static function onException($exception) { - self::write('PHP', - $exception->getMessage() . ' at ' . $exception->getFile() . '#' . $exception->getLine(), - self::FATAL); + /** + * Runtime errors that do not require immediate action but should typically + * be logged and monitored. + * + * @param string $message + * @param array $context + */ + public function error($message, array $context = array()) { + $this->log(\OC_Log::ERROR, $message, $context); } - //Recoverable errors handler - public static function onError($number, $message, $file, $line) { - if (error_reporting() === 0) { - return; - } - self::write('PHP', $message . ' at ' . $file . '#' . $line, self::WARN); + /** + * Exceptional occurrences that are not errors. + * + * Example: Use of deprecated APIs, poor use of an API, undesirable things + * that are not necessarily wrong. + * + * @param string $message + * @param array $context + */ + public function warning($message, array $context = array()) { + $this->log(\OC_Log::WARN, $message, $context); + } + + /** + * Normal but significant events. + * + * @param string $message + * @param array $context + */ + public function notice($message, array $context = array()) { + $this->log(\OC_Log::INFO, $message, $context); + } + /** + * Interesting events. + * + * Example: User logs in, SQL logs. + * + * @param string $message + * @param array $context + */ + public function info($message, array $context = array()) { + $this->log(\OC_Log::INFO, $message, $context); + } + + /** + * Detailed debug information. + * + * @param string $message + * @param array $context + */ + public function debug($message, array $context = array()) { + $this->log(\OC_Log::DEBUG, $message, $context); + } + + public function __construct() { + $this->logClass = 'OC_Log_'.ucfirst(\OC_Config::getValue('log_type', 'owncloud')); + call_user_func(array($this->logClass, 'init')); + } + + /** + * Logs with an arbitrary level. + * + * @param mixed $level + * @param string $message + * @param array $context + */ + public function log($level, $message, array $context = array()) { + if (isset($context['app'])) { + $app = $context['app']; + } else { + $app = 'no app in context'; + } + $logClass=$this->logClass; + $logClass::write($app, $message, $level); } } diff --git a/lib/public/share.php b/lib/public/share.php index 122ab3fa030..de7025d7b15 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -662,7 +662,13 @@ class Share { // Remove the permissions for all reshares of this item if (!empty($ids)) { $ids = "'".implode("','", $ids)."'"; - $query = \OC_DB::prepare('UPDATE `*PREFIX*share` SET `permissions` = `permissions` & ?' + // TODO this should be done with Doctrine platform objects + if (\OC_Config::getValue( "dbtype") === 'oci') { + $andOp = 'BITAND(`permissions`, ?)'; + } else { + $andOp = '`permissions` & ?'; + } + $query = \OC_DB::prepare('UPDATE `*PREFIX*share` SET `permissions` = '.$andOp .' WHERE `id` IN ('.$ids.')'); $query->execute(array($permissions)); } @@ -963,6 +969,30 @@ class Share { $switchedItems = array(); $mounts = array(); while ($row = $result->fetchRow()) { + if (isset($row['id'])) { + $row['id']=(int)$row['id']; + } + if (isset($row['share_type'])) { + $row['share_type']=(int)$row['share_type']; + } + if (isset($row['parent'])) { + $row['parent']=(int)$row['parent']; + } + if (isset($row['file_parent'])) { + $row['file_parent']=(int)$row['file_parent']; + } + if (isset($row['file_source'])) { + $row['file_source']=(int)$row['file_source']; + } + if (isset($row['permissions'])) { + $row['permissions']=(int)$row['permissions']; + } + if (isset($row['storage'])) { + $row['storage']=(int)$row['storage']; + } + if (isset($row['stime'])) { + $row['stime']=(int)$row['stime']; + } // Filter out duplicate group shares for users with unique targets if ($row['share_type'] == self::$shareTypeGroupUserUnique && isset($items[$row['parent']])) { $row['share_type'] = self::SHARE_TYPE_GROUP; @@ -978,7 +1008,7 @@ class Share { // Check if the same owner shared with the user twice // through a group and user share - this is allowed $id = $targets[$row[$column]]; - if ($items[$id]['uid_owner'] == $row['uid_owner']) { + if (isset($items[$id]) && $items[$id]['uid_owner'] == $row['uid_owner']) { // Switch to group share type to ensure resharing conditions aren't bypassed if ($items[$id]['share_type'] != self::SHARE_TYPE_GROUP) { $items[$id]['share_type'] = self::SHARE_TYPE_GROUP; diff --git a/lib/vcategories.php b/lib/vcategories.php index 7bac6e7d4e3..84036958359 100644 --- a/lib/vcategories.php +++ b/lib/vcategories.php @@ -125,7 +125,7 @@ class OC_VCategories { OC_Log::write('core', __METHOD__. 'DB error: ' . OC_DB::getErrorMessage($result), OC_Log::ERROR); return false; } - return ($result->numRows() == 0); + return ($result->numRows() === 0); } catch(Exception $e) { OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(), OCP\Util::ERROR); |