diff options
author | Michael Gapczynski <mtgap@owncloud.com> | 2013-06-04 18:19:08 -0400 |
---|---|---|
committer | Michael Gapczynski <mtgap@owncloud.com> | 2013-06-04 18:19:08 -0400 |
commit | cb9fe475c4481993d2c95b040f7abb653f0971e7 (patch) | |
tree | 874e56e888745676fe815c3c8f75e2741ce275af /lib | |
parent | 9ead7c4776bd512c2a50ab917b99dcdc37e8db68 (diff) | |
parent | c59ee99d932eb9a5d7df8fdfb6c318abfdef88b7 (diff) | |
download | nextcloud-server-cb9fe475c4481993d2c95b040f7abb653f0971e7.tar.gz nextcloud-server-cb9fe475c4481993d2c95b040f7abb653f0971e7.zip |
Merge branch 'master' into hook-improvements
Conflicts:
lib/files/view.php
Diffstat (limited to 'lib')
130 files changed, 3597 insertions, 1836 deletions
diff --git a/lib/MDB2/Driver/sqlite3.php b/lib/MDB2/Driver/sqlite3.php index 8f057cfb6e8..693ceffa01c 100644 --- a/lib/MDB2/Driver/sqlite3.php +++ b/lib/MDB2/Driver/sqlite3.php @@ -387,7 +387,7 @@ class MDB2_Driver_sqlite3 extends MDB2_Driver_Common $php_errormsg = ''; $this->connection = new SQLite3($database_file); if(is_callable(array($this->connection, 'busyTimeout'))) {//busy timout is only available in php>=5.3 - $this->connection->busyTimeout(100); + $this->connection->busyTimeout(60000); } $this->_lasterror = $this->connection->lastErrorMsg(); if (!$this->connection) { @@ -892,10 +892,10 @@ class MDB2_Driver_sqlite3 extends MDB2_Driver_Common $connection = $this->getConnection(); if (PEAR::isError($connection)) { return $connection; - } + } $statement =$this->connection->prepare($query); if (!$statement) { - return $this->db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, + return $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null, 'unable to prepare statement: '.$query); } diff --git a/lib/api.php b/lib/api.php index 8d6bbb7cc09..fc76836995b 100644 --- a/lib/api.php +++ b/lib/api.php @@ -89,7 +89,7 @@ class OC_API { $responses = array(); foreach(self::$actions[$name] as $action) { // Check authentication and availability - if(!self::isAuthorised(self::$actions[$name])) { + if(!self::isAuthorised($action)) { $responses[] = array( 'app' => $action['app'], 'response' => new OC_OCS_Result(null, OC_API::RESPOND_UNAUTHORISED, 'Unauthorised'), @@ -111,9 +111,11 @@ class OC_API { } $response = self::mergeResponses($responses); $formats = array('json', 'xml'); + $format = !empty($_GET['format']) && in_array($_GET['format'], $formats) ? $_GET['format'] : 'xml'; - self::respond($response); OC_User::logout(); + + self::respond($response, $format); } /** @@ -147,6 +149,7 @@ class OC_API { } } } + // Remove any error responses if there is one shipped response that succeeded if(!empty($shipped['succeeded'])) { $responses = array_merge($shipped['succeeded'], $thirdparty['succeeded']); @@ -155,16 +158,19 @@ class OC_API { // They may have failed for different reasons (different status codes) // Which reponse code should we return? // Maybe any that are not OC_API::RESPOND_SERVER_ERROR - $response = $shipped['failed'][0]; + $response = reset($shipped['failed']); return $response; - } else { + } elseif(!empty($thirdparty['failed'])) { // Return the third party failure result - $response = $thirdparty['failed'][0]; + $response = reset($thirdparty['failed']); return $response; + } else { + $responses = array_merge($shipped['succeeded'], $thirdparty['succeeded']); } // Merge the successful responses $meta = array(); $data = array(); + foreach($responses as $app => $response) { if(OC_App::isShipped($app)) { $data = array_merge_recursive($response->getData(), $data); diff --git a/lib/app.php b/lib/app.php index 55b4543ec9f..c6f6e92e60e 100644 --- a/lib/app.php +++ b/lib/app.php @@ -172,9 +172,17 @@ class OC_App{ return array(); } $apps=array('files'); - $query = OC_DB::prepare( 'SELECT `appid` FROM `*PREFIX*appconfig`' - .' WHERE `configkey` = \'enabled\' AND `configvalue`=\'yes\'' ); + $sql = 'SELECT `appid` FROM `*PREFIX*appconfig`' + .' WHERE `configkey` = \'enabled\' AND `configvalue`=\'yes\''; + if (OC_Config::getValue( 'dbtype', 'sqlite' ) === 'oci') { //FIXME oracle hack + $sql = 'SELECT `appid` FROM `*PREFIX*appconfig`' + .' WHERE `configkey` = \'enabled\' AND to_char(`configvalue`)=\'yes\''; + } + $query = OC_DB::prepare( $sql ); $result=$query->execute(); + if( \OC_DB::isError($result)) { + throw new DatabaseException($result->getMessage(), $query); + } while($row=$result->fetchRow()) { if(array_search($row['appid'], $apps)===false) { $apps[]=$row['appid']; diff --git a/lib/autoloader.php b/lib/autoloader.php new file mode 100644 index 00000000000..9615838a9a2 --- /dev/null +++ b/lib/autoloader.php @@ -0,0 +1,126 @@ +<?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; + +class Autoloader { + private $useGlobalClassPath = true; + + private $prefixPaths = array(); + + private $classPaths = array(); + + /** + * Add a custom prefix to the autoloader + * + * @param string $prefix + * @param string $path + */ + public function registerPrefix($prefix, $path) { + $this->prefixPaths[$prefix] = $path; + } + + /** + * Add a custom classpath to the autoloader + * + * @param string $class + * @param string $path + */ + public function registerClass($class, $path) { + $this->classPaths[$class] = $path; + } + + /** + * disable the usage of the global classpath \OC::$CLASSPATH + */ + public function disableGlobalClassPath() { + $this->useGlobalClassPath = false; + } + + /** + * enable the usage of the global classpath \OC::$CLASSPATH + */ + public function enableGlobalClassPath() { + $this->useGlobalClassPath = true; + } + + /** + * get the possible paths for a class + * + * @param string $class + * @return array|bool an array of possible paths or false if the class is not part of ownCloud + */ + public function findClass($class) { + $class = trim($class, '\\'); + + $paths = array(); + if (array_key_exists($class, $this->classPaths)) { + $paths[] = $this->classPaths[$class]; + } else if ($this->useGlobalClassPath and array_key_exists($class, \OC::$CLASSPATH)) { + $paths[] = \OC::$CLASSPATH[$class]; + /** + * @TODO: Remove this when necessary + * Remove "apps/" from inclusion path for smooth migration to mutli app dir + */ + if (strpos(\OC::$CLASSPATH[$class], 'apps/') === 0) { + \OC_Log::write('core', 'include path for class "' . $class . '" starts with "apps/"', \OC_Log::DEBUG); + $paths[] = str_replace('apps/', '', \OC::$CLASSPATH[$class]); + } + } elseif (strpos($class, 'OC_') === 0) { + // first check for legacy classes if underscores are used + $paths[] = 'legacy/' . strtolower(str_replace('_', '/', substr($class, 3)) . '.php'); + $paths[] = strtolower(str_replace('_', '/', substr($class, 3)) . '.php'); + } elseif (strpos($class, 'OC\\') === 0) { + $paths[] = strtolower(str_replace('\\', '/', substr($class, 3)) . '.php'); + } elseif (strpos($class, 'OCP\\') === 0) { + $paths[] = 'public/' . strtolower(str_replace('\\', '/', substr($class, 4)) . '.php'); + } elseif (strpos($class, 'OCA\\') === 0) { + list(, $app, $rest) = explode('\\', $class, 3); + $app = strtolower($app); + foreach (\OC::$APPSROOTS as $appDir) { + if (stream_resolve_include_path($appDir['path'] . '/' . $app)) { + $paths[] = $appDir['path'] . '/' . $app . '/' . strtolower(str_replace('\\', '/', $rest) . '.php'); + // If not found in the root of the app directory, insert '/lib' after app id and try again. + $paths[] = $appDir['path'] . '/' . $app . '/lib/' . strtolower(str_replace('\\', '/', $rest) . '.php'); + } + } + } elseif (strpos($class, 'Test_') === 0) { + $paths[] = 'tests/lib/' . strtolower(str_replace('_', '/', substr($class, 5)) . '.php'); + } elseif (strpos($class, 'Test\\') === 0) { + $paths[] = 'tests/lib/' . strtolower(str_replace('\\', '/', substr($class, 5)) . '.php'); + } else { + foreach ($this->prefixPaths as $prefix => $dir) { + if (0 === strpos($class, $prefix)) { + $path = str_replace('\\', DIRECTORY_SEPARATOR, $class) . '.php'; + $path = str_replace('_', DIRECTORY_SEPARATOR, $path); + $paths[] = $dir . '/' . $path; + } + } + } + return $paths; + } + + /** + * Load the specified class + * + * @param string $class + * @return bool + */ + public function load($class) { + $paths = $this->findClass($class); + + if (is_array($paths)) { + foreach ($paths as $path) { + if ($fullPath = stream_resolve_include_path($path)) { + require_once $fullPath; + } + } + } + return false; + } +} diff --git a/lib/backgroundjob/job.php b/lib/backgroundjob/job.php new file mode 100644 index 00000000000..49fbffbd684 --- /dev/null +++ b/lib/backgroundjob/job.php @@ -0,0 +1,49 @@ +<?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\BackgroundJob; + +abstract class Job { + protected $id; + protected $lastRun; + protected $argument; + + /** + * @param JobList $jobList + */ + public function execute($jobList) { + $jobList->setLastRun($this); + $this->run($this->argument); + } + + abstract protected function run($argument); + + public function setId($id) { + $this->id = $id; + } + + public function setLastRun($lastRun) { + $this->lastRun = $lastRun; + } + + public function setArgument($argument) { + $this->argument = $argument; + } + + public function getId() { + return $this->id; + } + + public function getLastRun() { + return $this->lastRun; + } + + public function getArgument() { + return $this->argument; + } +} diff --git a/lib/backgroundjob/joblist.php b/lib/backgroundjob/joblist.php new file mode 100644 index 00000000000..cc803dd9b5f --- /dev/null +++ b/lib/backgroundjob/joblist.php @@ -0,0 +1,172 @@ +<?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\BackgroundJob; + +/** + * Class QueuedJob + * + * create a background job that is to be executed once + * + * @package OC\BackgroundJob + */ +class JobList { + /** + * @param Job|string $job + * @param mixed $argument + */ + public function add($job, $argument = null) { + if (!$this->has($job, $argument)) { + if ($job instanceof Job) { + $class = get_class($job); + } else { + $class = $job; + } + $argument = json_encode($argument); + $query = \OC_DB::prepare('INSERT INTO `*PREFIX*jobs`(`class`, `argument`, `last_run`) VALUES(?, ?, 0)'); + $query->execute(array($class, $argument)); + } + } + + /** + * @param Job|string $job + * @param mixed $argument + */ + public function remove($job, $argument = null) { + if ($job instanceof Job) { + $class = get_class($job); + } else { + $class = $job; + } + if (!is_null($argument)) { + $argument = json_encode($argument); + $query = \OC_DB::prepare('DELETE FROM `*PREFIX*jobs` WHERE `class` = ? AND `argument` = ?'); + $query->execute(array($class, $argument)); + } else { + $query = \OC_DB::prepare('DELETE FROM `*PREFIX*jobs` WHERE `class` = ?'); + $query->execute(array($class)); + } + } + + /** + * check if a job is in the list + * + * @param $job + * @param mixed $argument + * @return bool + */ + public function has($job, $argument) { + if ($job instanceof Job) { + $class = get_class($job); + } else { + $class = $job; + } + $argument = json_encode($argument); + $query = \OC_DB::prepare('SELECT `id` FROM `*PREFIX*jobs` WHERE `class` = ? AND `argument` = ?'); + $result = $query->execute(array($class, $argument)); + return (bool)$result->fetchRow(); + } + + /** + * get all jobs in the list + * + * @return Job[] + */ + public function getAll() { + $query = \OC_DB::prepare('SELECT `id`, `class`, `last_run`, `argument` FROM `*PREFIX*jobs`'); + $result = $query->execute(); + $jobs = array(); + while ($row = $result->fetchRow()) { + $jobs[] = $this->buildJob($row); + } + return $jobs; + } + + /** + * get the next job in the list + * + * @return Job + */ + public function getNext() { + $lastId = $this->getLastJob(); + $query = \OC_DB::prepare('SELECT `id`, `class`, `last_run`, `argument` FROM `*PREFIX*jobs` WHERE `id` > ? ORDER BY `id` ASC', 1); + $result = $query->execute(array($lastId)); + if ($row = $result->fetchRow()) { + return $this->buildJob($row); + } else { + //begin at the start of the queue + $query = \OC_DB::prepare('SELECT `id`, `class`, `last_run`, `argument` FROM `*PREFIX*jobs` ORDER BY `id` ASC', 1); + $result = $query->execute(); + if ($row = $result->fetchRow()) { + return $this->buildJob($row); + } else { + return null; //empty job list + } + } + } + + /** + * @param int $id + * @return Job + */ + public function getById($id) { + $query = \OC_DB::prepare('SELECT `id`, `class`, `last_run`, `argument` FROM `*PREFIX*jobs` WHERE `id` = ?'); + $result = $query->execute(array($id)); + if ($row = $result->fetchRow()) { + return $this->buildJob($row); + } else { + return null; + } + } + + /** + * get the job object from a row in the db + * + * @param array $row + * @return Job + */ + private function buildJob($row) { + $class = $row['class']; + /** + * @var Job $job + */ + $job = new $class(); + $job->setId($row['id']); + $job->setLastRun($row['last_run']); + $job->setArgument(json_decode($row['argument'])); + return $job; + } + + /** + * set the job that was last ran + * + * @param Job $job + */ + public function setLastJob($job) { + \OC_Appconfig::setValue('backgroundjob', 'lastjob', $job->getId()); + } + + /** + * get the id of the last ran job + * + * @return int + */ + public function getLastJob() { + return \OC_Appconfig::getValue('backgroundjob', 'lastjob', 0); + } + + /** + * set the lastRun of $job to now + * + * @param Job $job + */ + public function setLastRun($job) { + $query = \OC_DB::prepare('UPDATE `*PREFIX*jobs` SET `last_run` = ? WHERE `id` = ?'); + $query->execute(array(time(), $job->getId())); + } +} diff --git a/lib/backgroundjob/legacy/queuedjob.php b/lib/backgroundjob/legacy/queuedjob.php new file mode 100644 index 00000000000..2bc001103b8 --- /dev/null +++ b/lib/backgroundjob/legacy/queuedjob.php @@ -0,0 +1,18 @@ +<?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\BackgroundJob\Legacy; + +class QueuedJob extends \OC\BackgroundJob\QueuedJob { + public function run($argument) { + $class = $argument['klass']; + $method = $argument['method']; + $parameters = $argument['parameters']; + call_user_func(array($class, $method), $parameters); + } +} diff --git a/lib/backgroundjob/legacy/regularjob.php b/lib/backgroundjob/legacy/regularjob.php new file mode 100644 index 00000000000..d4cfa348cea --- /dev/null +++ b/lib/backgroundjob/legacy/regularjob.php @@ -0,0 +1,15 @@ +<?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\BackgroundJob\Legacy; + +class RegularJob extends \OC\BackgroundJob\Job { + public function run($argument) { + call_user_func($argument); + } +} diff --git a/lib/backgroundjob/queuedjob.php b/lib/backgroundjob/queuedjob.php new file mode 100644 index 00000000000..1714182820d --- /dev/null +++ b/lib/backgroundjob/queuedjob.php @@ -0,0 +1,28 @@ +<?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\BackgroundJob; + +/** + * Class QueuedJob + * + * create a background job that is to be executed once + * + * @package OC\BackgroundJob + */ +abstract class QueuedJob extends Job { + /** + * run the job, then remove it from the joblist + * + * @param JobList $jobList + */ + public function execute($jobList) { + $jobList->remove($this); + $this->run($this->argument); + } +} diff --git a/lib/backgroundjob/queuedtask.php b/lib/backgroundjob/queuedtask.php deleted file mode 100644 index b2ce6f39ed8..00000000000 --- a/lib/backgroundjob/queuedtask.php +++ /dev/null @@ -1,105 +0,0 @@ -<?php -/** -* ownCloud -* -* @author Jakob Sack -* @copyright 2012 Jakob Sack owncloud@jakobsack.de -* -* 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/>. -* -*/ - -/** - * This class manages our queued tasks. - */ -class OC_BackgroundJob_QueuedTask{ - /** - * @brief Gets one queued task - * @param $id ID of the task - * @return associative array - */ - public static function find( $id ) { - $stmt = OC_DB::prepare( 'SELECT * FROM `*PREFIX*queuedtasks` WHERE `id` = ?' ); - $result = $stmt->execute(array($id)); - return $result->fetchRow(); - } - - /** - * @brief Gets all queued tasks - * @return array with associative arrays - */ - public static function all() { - // Array for objects - $return = array(); - - // Get Data - $stmt = OC_DB::prepare( 'SELECT * FROM `*PREFIX*queuedtasks`' ); - $result = $stmt->execute(array()); - while( $row = $result->fetchRow()) { - $return[] = $row; - } - - return $return; - } - - /** - * @brief Gets all queued tasks of a specific app - * @param $app app name - * @return array with associative arrays - */ - public static function whereAppIs( $app ) { - // Array for objects - $return = array(); - - // Get Data - $stmt = OC_DB::prepare( 'SELECT * FROM `*PREFIX*queuedtasks` WHERE `app` = ?' ); - $result = $stmt->execute(array($app)); - while( $row = $result->fetchRow()) { - $return[] = $row; - } - - // Und weg damit - return $return; - } - - /** - * @brief queues a task - * @param $app app name - * @param $klass class name - * @param $method method name - * @param $parameters all useful data as text - * @return id of task - */ - public static function add( $app, $klass, $method, $parameters ) { - $stmt = OC_DB::prepare( 'INSERT INTO `*PREFIX*queuedtasks` (`app`, `klass`, `method`, `parameters`)' - .' VALUES(?,?,?,?)' ); - $result = $stmt->execute(array($app, $klass, $method, $parameters )); - - return OC_DB::insertid(); - } - - /** - * @brief deletes a queued task - * @param $id id of task - * @return true/false - * - * Deletes a report - */ - public static function delete( $id ) { - $stmt = OC_DB::prepare( 'DELETE FROM `*PREFIX*queuedtasks` WHERE `id` = ?' ); - $result = $stmt->execute(array($id)); - - return true; - } -} diff --git a/lib/backgroundjob/regulartask.php b/lib/backgroundjob/regulartask.php deleted file mode 100644 index 9976872ee13..00000000000 --- a/lib/backgroundjob/regulartask.php +++ /dev/null @@ -1,52 +0,0 @@ -<?php -/** -* ownCloud -* -* @author Jakob Sack -* @copyright 2012 Jakob Sack owncloud@jakobsack.de -* -* 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/>. -* -*/ - -/** - * This class manages the regular tasks. - */ -class OC_BackgroundJob_RegularTask{ - static private $registered = array(); - - /** - * @brief creates a regular task - * @param $klass class name - * @param $method method name - * @return true - */ - static public function register( $klass, $method ) { - // Create the data structure - self::$registered["$klass-$method"] = array( $klass, $method ); - - // No chance for failure ;-) - return true; - } - - /** - * @brief gets all regular tasks - * @return associative array - * - * key is string "$klass-$method", value is array( $klass, $method ) - */ - static public function all() { - return self::$registered; - } -} diff --git a/lib/backgroundjob/timedjob.php b/lib/backgroundjob/timedjob.php new file mode 100644 index 00000000000..ae9f33505ab --- /dev/null +++ b/lib/backgroundjob/timedjob.php @@ -0,0 +1,41 @@ +<?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\BackgroundJob; + +/** + * Class QueuedJob + * + * create a background job that is to be executed at an interval + * + * @package OC\BackgroundJob + */ +abstract class TimedJob extends Job { + protected $interval = 0; + + /** + * set the interval for the job + * + * @param int $interval + */ + public function setInterval($interval) { + $this->interval = $interval; + } + + /** + * run the job if + * + * @param JobList $jobList + */ + public function execute($jobList) { + if ((time() - $this->lastRun) > $this->interval) { + $jobList->setLastRun($this); + $this->run($this->argument); + } + } +} diff --git a/lib/backgroundjob/worker.php b/lib/backgroundjob/worker.php deleted file mode 100644 index e966ac9647c..00000000000 --- a/lib/backgroundjob/worker.php +++ /dev/null @@ -1,118 +0,0 @@ -<?php -/** -* ownCloud -* -* @author Jakob Sack -* @copyright 2012 Jakob Sack owncloud@jakobsack.de -* -* 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/>. -* -*/ - -/** - * This class does the dirty work. - * - * TODO: locking in doAllSteps - */ -class OC_BackgroundJob_Worker{ - /** - * @brief executes all tasks - * @return boolean - * - * This method executes all regular tasks and then all queued tasks. - * This method should be called by cli scripts that do not let the user - * wait. - */ - public static function doAllSteps() { - // Do our regular work - $lasttask = OC_Appconfig::getValue( 'core', 'backgroundjobs_task', '' ); - - $regular_tasks = OC_BackgroundJob_RegularTask::all(); - ksort( $regular_tasks ); - foreach( $regular_tasks as $key => $value ) { - if( strcmp( $key, $lasttask ) > 0 ) { - // Set "restart here" config value - OC_Appconfig::setValue( 'core', 'backgroundjobs_task', $key ); - call_user_func( $value ); - } - } - // Reset "start here" config value - OC_Appconfig::setValue( 'core', 'backgroundjobs_task', '' ); - - // Do our queued tasks - $queued_tasks = OC_BackgroundJob_QueuedTask::all(); - foreach( $queued_tasks as $task ) { - OC_BackgroundJob_QueuedTask::delete( $task['id'] ); - call_user_func( array( $task['klass'], $task['method'] ), $task['parameters'] ); - } - - return true; - } - - /** - * @brief does a single task - * @return boolean - * - * This method executes one task. It saves the last state and continues - * with the next step. This method should be used by webcron and ajax - * services. - */ - public static function doNextStep() { - $laststep = OC_Appconfig::getValue( 'core', 'backgroundjobs_step', 'regular_tasks' ); - - if( $laststep == 'regular_tasks' ) { - // get last app - $lasttask = OC_Appconfig::getValue( 'core', 'backgroundjobs_task', '' ); - - // What's the next step? - $regular_tasks = OC_BackgroundJob_RegularTask::all(); - ksort( $regular_tasks ); - $done = false; - - // search for next background job - foreach( $regular_tasks as $key => $value ) { - if( strcmp( $key, $lasttask ) > 0 ) { - OC_Appconfig::setValue( 'core', 'backgroundjobs_task', $key ); - $done = true; - call_user_func( $value ); - break; - } - } - - if( $done == false ) { - // Next time load queued tasks - OC_Appconfig::setValue( 'core', 'backgroundjobs_step', 'queued_tasks' ); - } - } - else{ - $tasks = OC_BackgroundJob_QueuedTask::all(); - if( count( $tasks )) { - $task = $tasks[0]; - // delete job before we execute it. This prevents endless loops - // of failing jobs. - OC_BackgroundJob_QueuedTask::delete($task['id']); - - // execute job - call_user_func( array( $task['klass'], $task['method'] ), $task['parameters'] ); - } - else{ - // Next time load queued tasks - OC_Appconfig::setValue( 'core', 'backgroundjobs_step', 'regular_tasks' ); - OC_Appconfig::setValue( 'core', 'backgroundjobs_task', '' ); - } - } - - return true; - } -} diff --git a/lib/base.php b/lib/base.php index dde994a7e57..a6e4a47dbf5 100644 --- a/lib/base.php +++ b/lib/base.php @@ -75,54 +75,14 @@ class OC { protected static $router = null; /** - * SPL autoload + * @var \OC\Session\Session */ - public static function autoload($className) { - $className = trim($className, '\\'); - - if (array_key_exists($className, OC::$CLASSPATH)) { - $path = OC::$CLASSPATH[$className]; - /** @TODO: Remove this when necessary - Remove "apps/" from inclusion path for smooth migration to mutli app dir - */ - if (strpos($path, 'apps/') === 0) { - OC_Log::write('core', 'include path for class "' . $className . '" starts with "apps/"', OC_Log::DEBUG); - $path = str_replace('apps/', '', $path); - } - } elseif (strpos($className, 'OC_') === 0) { - $path = strtolower(str_replace('_', '/', substr($className, 3)) . '.php'); - } elseif (strpos($className, 'OC\\') === 0) { - $path = strtolower(str_replace('\\', '/', substr($className, 3)) . '.php'); - } elseif (strpos($className, 'OCP\\') === 0) { - $path = 'public/' . strtolower(str_replace('\\', '/', substr($className, 3)) . '.php'); - } elseif (strpos($className, 'OCA\\') === 0) { - foreach (self::$APPSROOTS as $appDir) { - $path = $appDir['path'] . '/' . strtolower(str_replace('\\', '/', substr($className, 3)) . '.php'); - $fullPath = stream_resolve_include_path($path); - if (file_exists($fullPath)) { - require_once $fullPath; - return false; - } - } - } elseif (strpos($className, 'Sabre_') === 0) { - $path = str_replace('_', '/', $className) . '.php'; - } elseif (strpos($className, 'Symfony\\Component\\Routing\\') === 0) { - $path = 'symfony/routing/' . str_replace('\\', '/', $className) . '.php'; - } elseif (strpos($className, 'Sabre\\VObject') === 0) { - $path = str_replace('\\', '/', $className) . '.php'; - } elseif (strpos($className, 'Test_') === 0) { - $path = 'tests/lib/' . strtolower(str_replace('_', '/', substr($className, 5)) . '.php'); - } elseif (strpos($className, 'Test\\') === 0) { - $path = 'tests/lib/' . strtolower(str_replace('\\', '/', substr($className, 5)) . '.php'); - } else { - return false; - } + public static $session = null; - if ($fullPath = stream_resolve_include_path($path)) { - require_once $fullPath; - } - return false; - } + /** + * @var \OC\Autoloader $loader + */ + public static $loader = null; public static function initPaths() { // calculate the root directories @@ -278,7 +238,7 @@ class OC { OC_Config::setValue('maintenance', true); OC_Log::write('core', 'starting upgrade from ' . $installedVersion . ' to ' . $currentVersion, - OC_Log::DEBUG); + OC_Log::WARN); $minimizerCSS = new OC_Minimizer_CSS(); $minimizerCSS->clearCache(); $minimizerJS = new OC_Minimizer_JS(); @@ -298,13 +258,16 @@ class OC { public static function initTemplateEngine() { // Add the stuff we need always - OC_Util::addScript("jquery-1.7.2.min"); + OC_Util::addScript("jquery-1.10.0.min"); + OC_Util::addScript("jquery-migrate-1.2.1.min"); OC_Util::addScript("jquery-ui-1.10.0.custom"); OC_Util::addScript("jquery-showpassword"); OC_Util::addScript("jquery.infieldlabel"); OC_Util::addScript("jquery-tipsy"); OC_Util::addScript("compatibility"); + OC_Util::addScript("jquery.ocdialog"); OC_Util::addScript("oc-dialogs"); + OC_Util::addScript("octemplate"); OC_Util::addScript("js"); OC_Util::addScript("eventsource"); OC_Util::addScript("config"); @@ -316,6 +279,7 @@ class OC { OC_Util::addStyle("multiselect"); OC_Util::addStyle("jquery-ui-1.10.0.custom"); OC_Util::addStyle("jquery-tipsy"); + OC_Util::addStyle("jquery.ocdialog"); OC_Util::addScript("oc-requesttoken"); } @@ -324,16 +288,20 @@ class OC { ini_set('session.cookie_httponly', '1;'); // set the cookie path to the ownCloud directory - ini_set('session.cookie_path', OC::$WEBROOT); - - // set the session name to the instance id - which is unique - session_name(OC_Util::getInstanceId()); - - // if session cant be started break with http 500 error - if (session_start() === false){ - OC_Log::write('core', 'Session could not be initialized', + $cookie_path = OC::$WEBROOT ?: '/'; + ini_set('session.cookie_path', $cookie_path); + + 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); - + header('HTTP/1.1 500 Internal Server Error'); OC_Util::addStyle("styles"); $error = 'Session could not be initialized. Please contact your '; @@ -347,23 +315,24 @@ class OC { } // regenerate session id periodically to avoid session fixation - if (!isset($_SESSION['SID_CREATED'])) { - $_SESSION['SID_CREATED'] = time(); - } else if (time() - $_SESSION['SID_CREATED'] > 60*60*12) { + if (!self::$session->exists('SID_CREATED')) { + self::$session->set('SID_CREATED', time()); + } else if (time() - self::$session->get('SID_CREATED') > 60*60*12) { session_regenerate_id(true); - $_SESSION['SID_CREATED'] = time(); + self::$session->set('SID_CREATED', time()); } // session timeout - if (isset($_SESSION['LAST_ACTIVITY']) && (time() - $_SESSION['LAST_ACTIVITY'] > 60*60*24)) { + if (self::$session->exists('LAST_ACTIVITY') && (time() - self::$session->get('LAST_ACTIVITY') > 60*60*24)) { if (isset($_COOKIE[session_name()])) { - setcookie(session_name(), '', time() - 42000, OC::$WEBROOT); + setcookie(session_name(), '', time() - 42000, $cookie_path); } session_unset(); session_destroy(); session_start(); } - $_SESSION['LAST_ACTIVITY'] = time(); + + self::$session->set('LAST_ACTIVITY', time()); } public static function getRouter() { @@ -388,8 +357,14 @@ class OC { public static function init() { // register autoloader - spl_autoload_register(array('OC', 'autoload')); - OC_Util::issetlocaleworking(); + require_once __DIR__ . '/autoloader.php'; + self::$loader=new \OC\Autoloader(); + self::$loader->registerPrefix('Doctrine\\Common', 'doctrine/common/lib'); + self::$loader->registerPrefix('Doctrine\\DBAL', 'doctrine/dbal/lib'); + self::$loader->registerPrefix('Symfony\\Component\\Routing', 'symfony/routing'); + self::$loader->registerPrefix('Sabre\\VObject', '3rdparty'); + self::$loader->registerPrefix('Sabre_', '3rdparty'); + spl_autoload_register(array(self::$loader, 'load')); // set some stuff //ob_start(); @@ -446,6 +421,7 @@ class OC { } self::initPaths(); + OC_Util::issetlocaleworking(); // set debug mode if an xdebug session is active if (!defined('DEBUG') || !DEBUG) { @@ -466,11 +442,15 @@ class OC { stream_wrapper_register('close', 'OC\Files\Stream\Close'); stream_wrapper_register('oc', 'OC\Files\Stream\OC'); + self::initTemplateEngine(); + if ( !self::$CLI ) { + self::initSession(); + } else { + self::$session = new \OC\Session\Memory(''); + } self::checkConfig(); self::checkInstalled(); self::checkSSL(); - self::initSession(); - self::initTemplateEngine(); $errors = OC_Util::checkServer(); if (count($errors) > 0) { @@ -480,14 +460,14 @@ class OC { // User and Groups if (!OC_Config::getValue("installed", false)) { - $_SESSION['user_id'] = ''; + self::$session->set('user_id',''); } OC_User::useBackend(new OC_User_Database()); OC_Group::useBackend(new OC_Group_Database()); - if (isset($_SERVER['PHP_AUTH_USER']) && isset($_SESSION['user_id']) - && $_SERVER['PHP_AUTH_USER'] != $_SESSION['user_id']) { + if (isset($_SERVER['PHP_AUTH_USER']) && self::$session->exists('user_id') + && $_SERVER['PHP_AUTH_USER'] != self::$session->get('user_id')) { OC_User::logout(); } @@ -559,9 +539,15 @@ class OC { * register hooks for the cache */ public static function registerCacheHooks() { - // register cache cleanup jobs - OC_BackgroundJob_RegularTask::register('OC_Cache_FileGlobal', 'gc'); - OC_Hook::connect('OC_User', 'post_login', 'OC_Cache_File', 'loginListener'); + if (OC_Config::getValue('installed', false)) { //don't try to do this before we are properly setup + // register cache cleanup jobs + try { //if this is executed before the upgrade to the new backgroundjob system is completed it will throw an exception + \OCP\BackgroundJob::registerJob('OC_Cache_FileGlobalGC'); + } catch (Exception $e) { + + } + OC_Hook::connect('OC_User', 'post_login', 'OC_Cache_File', 'loginListener'); + } } /** @@ -577,10 +563,12 @@ class OC { * register hooks for sharing */ public static function registerShareHooks() { - OC_Hook::connect('OC_User', 'post_deleteUser', 'OCP\Share', 'post_deleteUser'); - OC_Hook::connect('OC_User', 'post_addToGroup', 'OCP\Share', 'post_addToGroup'); - OC_Hook::connect('OC_User', 'post_removeFromGroup', 'OCP\Share', 'post_removeFromGroup'); - OC_Hook::connect('OC_User', 'post_deleteGroup', 'OCP\Share', 'post_deleteGroup'); + if(\OC_Config::getValue('installed')) { + OC_Hook::connect('OC_User', 'post_deleteUser', 'OCP\Share', 'post_deleteUser'); + OC_Hook::connect('OC_User', 'post_addToGroup', 'OCP\Share', 'post_addToGroup'); + OC_Hook::connect('OC_User', 'post_removeFromGroup', 'OCP\Share', 'post_removeFromGroup'); + OC_Hook::connect('OC_User', 'post_deleteGroup', 'OCP\Share', 'post_deleteGroup'); + } } /** @@ -630,8 +618,13 @@ class OC { // Handle redirect URL for logged in users if (isset($_REQUEST['redirect_url']) && OC_User::isLoggedIn()) { $location = OC_Helper::makeURLAbsolute(urldecode($_REQUEST['redirect_url'])); - header('Location: ' . $location); - return; + + // Deny the redirect if the URL contains a @ + // This prevents unvalidated redirects like ?redirect_url=:user@domain.com + if (strpos($location, '@') === false) { + header('Location: ' . $location); + return; + } } // Handle WebDAV if ($_SERVER['REQUEST_METHOD'] == 'PROPFIND') { @@ -775,7 +768,7 @@ class OC { if (OC_User::login($_POST["user"], $_POST["password"])) { // setting up the time zone if (isset($_POST['timezone-offset'])) { - $_SESSION['timezone'] = $_POST['timezone-offset']; + self::$session->set('timezone', $_POST['timezone-offset']); } self::cleanupLoginTokens($_POST['user']); diff --git a/lib/cache/file.php b/lib/cache/file.php index f9ecf41dcac..531e1d50f40 100644 --- a/lib/cache/file.php +++ b/lib/cache/file.php @@ -14,6 +14,7 @@ class OC_Cache_File{ return $this->storage; } if(OC_User::isLoggedIn()) { + \OC\Files\Filesystem::initMountPoints(OC_User::getUser()); $subdir = 'cache'; $view = new \OC\Files\View('/'.OC_User::getUser()); if(!$view->file_exists($subdir)) { diff --git a/lib/cache/fileglobalgc.php b/lib/cache/fileglobalgc.php new file mode 100644 index 00000000000..a29c31f9063 --- /dev/null +++ b/lib/cache/fileglobalgc.php @@ -0,0 +1,8 @@ +<?php + + +class OC_Cache_FileGlobalGC extends \OC\BackgroundJob\Job{ + public function run($argument){ + OC_Cache_FileGlobal::gc(); + } +} diff --git a/lib/connector/sabre/node.php b/lib/connector/sabre/node.php index 360c3066d05..1ffa048d6b2 100644 --- a/lib/connector/sabre/node.php +++ b/lib/connector/sabre/node.php @@ -101,7 +101,7 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr /** * @brief Ensure that the fileinfo cache is filled - & @note Uses OC_FileCache or a direct stat + * @note Uses OC_FileCache or a direct stat */ protected function getFileinfoCache() { if (!isset($this->fileinfo_cache)) { diff --git a/lib/db.php b/lib/db.php index 8f6f50bda6e..61836551833 100644 --- a/lib/db.php +++ b/lib/db.php @@ -273,18 +273,13 @@ class OC_DB { break; case 'oci': $dsn = array( - 'phptype' => 'oci8', - 'username' => $user, - 'password' => $pass, - 'charset' => 'AL32UTF8', + 'phptype' => 'oci8', + 'username' => $user, + 'password' => $pass, + 'service' => $name, + 'hostspec' => $host, + 'charset' => 'AL32UTF8', ); - if ($host != '') { - $dsn['hostspec'] = $host; - $dsn['database'] = $name; - } else { // use dbname for hostspec - $dsn['hostspec'] = $name; - $dsn['database'] = $user; - } break; case 'mssql': $dsn = array( diff --git a/lib/files.php b/lib/files.php index 04ba51d9d24..abb1617c25e 100644 --- a/lib/files.php +++ b/lib/files.php @@ -59,11 +59,7 @@ class OC_Files { $executionTime = intval(ini_get('max_execution_time')); set_time_limit(0); $zip = new ZipArchive(); - if ($xsendfile) { - $filename = OC_Helper::tmpFileNoClean('.zip'); - }else{ - $filename = OC_Helper::tmpFile('.zip'); - } + $filename = OC_Helper::tmpFile('.zip'); if ($zip->open($filename, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE)!==true) { exit("cannot open <$filename>\n"); } @@ -78,6 +74,9 @@ class OC_Files { } } $zip->close(); + if ($xsendfile) { + $filename = OC_Helper::moveToNoClean($filename); + } $basename = basename($dir); if ($basename) { $name = $basename . '.zip'; @@ -91,17 +90,16 @@ class OC_Files { $executionTime = intval(ini_get('max_execution_time')); set_time_limit(0); $zip = new ZipArchive(); - if ($xsendfile) { - $filename = OC_Helper::tmpFileNoClean('.zip'); - }else{ - $filename = OC_Helper::tmpFile('.zip'); - } + $filename = OC_Helper::tmpFile('.zip'); if ($zip->open($filename, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE)!==true) { exit("cannot open <$filename>\n"); } $file = $dir . '/' . $files; self::zipAddDir($file, $zip); $zip->close(); + if ($xsendfile) { + $filename = OC_Helper::moveToNoClean($filename); + } $name = $files . '.zip'; set_time_limit($executionTime); } else { @@ -125,8 +123,11 @@ class OC_Files { header('Content-Length: ' . filesize($filename)); self::addSendfileHeader($filename); }else{ + $filesize = \OC\Files\Filesystem::filesize($filename); header('Content-Type: '.\OC\Files\Filesystem::getMimeType($filename)); - header("Content-Length: ".\OC\Files\Filesystem::filesize($filename)); + if ($filesize > -1) { + header("Content-Length: ".$filesize); + } list($storage) = \OC\Files\Filesystem::resolvePath($filename); if ($storage instanceof \OC\Files\Storage\Local) { self::addSendfileHeader(\OC\Files\Filesystem::getLocalFile($filename)); diff --git a/lib/files/cache/backgroundwatcher.php b/lib/files/cache/backgroundwatcher.php new file mode 100644 index 00000000000..8933101577d --- /dev/null +++ b/lib/files/cache/backgroundwatcher.php @@ -0,0 +1,104 @@ +<?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\Cache; + +use \OC\Files\Mount; +use \OC\Files\Filesystem; + +class BackgroundWatcher { + static $folderMimetype = null; + + static private function getFolderMimetype() { + if (!is_null(self::$folderMimetype)) { + return self::$folderMimetype; + } + $query = \OC_DB::prepare('SELECT `id` FROM `*PREFIX*mimetypes` WHERE `mimetype` = ?'); + $result = $query->execute(array('httpd/unix-directory')); + $row = $result->fetchRow(); + return $row['id']; + } + + static private function checkUpdate($id) { + $cacheItem = Cache::getById($id); + if (is_null($cacheItem)) { + return; + } + list($storageId, $internalPath) = $cacheItem; + $mounts = Filesystem::getMountByStorageId($storageId); + + if (count($mounts) === 0) { + //if the storage we need isn't mounted on default, try to find a user that has access to the storage + $permissionsCache = new Permissions($storageId); + $users = $permissionsCache->getUsers($id); + if (count($users) === 0) { + return; + } + Filesystem::initMountPoints($users[0]); + $mounts = Filesystem::getMountByStorageId($storageId); + if (count($mounts) === 0) { + return; + } + } + $storage = $mounts[0]->getStorage(); + $watcher = new Watcher($storage); + $watcher->checkUpdate($internalPath); + } + + /** + * get the next fileid in the cache + * + * @param int $previous + * @param bool $folder + * @return int + */ + static private function getNextFileId($previous, $folder) { + if ($folder) { + $query = \OC_DB::prepare('SELECT `fileid` FROM `*PREFIX*filecache` WHERE `fileid` > ? AND mimetype = ' . self::getFolderMimetype() . ' ORDER BY `fileid` ASC', 1); + } else { + $query = \OC_DB::prepare('SELECT `fileid` FROM `*PREFIX*filecache` WHERE `fileid` > ? AND mimetype != ' . self::getFolderMimetype() . ' ORDER BY `fileid` ASC', 1); + } + $result = $query->execute(array($previous)); + if ($row = $result->fetchRow()) { + return $row['fileid']; + } else { + return 0; + } + } + + static public function checkNext() { + // check both 1 file and 1 folder, this way new files are detected quicker because there are less folders than files usually + $previousFile = \OC_Appconfig::getValue('files', 'backgroundwatcher_previous_file', 0); + $previousFolder = \OC_Appconfig::getValue('files', 'backgroundwatcher_previous_folder', 0); + $nextFile = self::getNextFileId($previousFile, false); + $nextFolder = self::getNextFileId($previousFolder, true); + \OC_Appconfig::setValue('files', 'backgroundwatcher_previous_file', $nextFile); + \OC_Appconfig::setValue('files', 'backgroundwatcher_previous_folder', $nextFolder); + if ($nextFile > 0) { + self::checkUpdate($nextFile); + } + if ($nextFolder > 0) { + self::checkUpdate($nextFolder); + } + } + + static public function checkAll() { + $previous = 0; + $next = 1; + while ($next != 0) { + $next = self::getNextFileId($previous, true); + self::checkUpdate($next); + } + $previous = 0; + $next = 1; + while ($next != 0) { + $next = self::getNextFileId($previous, false); + self::checkUpdate($next); + } + } +} diff --git a/lib/files/cache/cache.php b/lib/files/cache/cache.php index 71b70abe3fe..cae2e63e4dc 100644 --- a/lib/files/cache/cache.php +++ b/lib/files/cache/cache.php @@ -30,11 +30,9 @@ class Cache { private $storageId; /** - * numeric storage id - * - * @var int $numericId + * @var Storage $storageCache */ - private $numericId; + private $storageCache; private $mimetypeIds = array(); private $mimetypes = array(); @@ -52,19 +50,11 @@ class Cache { $this->storageId = md5($this->storageId); } - $query = \OC_DB::prepare('SELECT `numeric_id` FROM `*PREFIX*storages` WHERE `id` = ?'); - $result = $query->execute(array($this->storageId)); - if ($row = $result->fetchRow()) { - $this->numericId = $row['numeric_id']; - } else { - $query = \OC_DB::prepare('INSERT INTO `*PREFIX*storages`(`id`) VALUES(?)'); - $query->execute(array($this->storageId)); - $this->numericId = \OC_DB::insertid('*PREFIX*storages'); - } + $this->storageCache = new Storage($storage); } public function getNumericStorageId() { - return $this->numericId; + return $this->storageCache->getNumericId(); } /** @@ -110,14 +100,17 @@ class Cache { */ public function get($file) { if (is_string($file) or $file == '') { + // normalize file + $file = $this->normalize($file); + $where = 'WHERE `storage` = ? AND `path_hash` = ?'; - $params = array($this->numericId, md5($file)); + $params = array($this->getNumericStorageId(), md5($file)); } else { //file id $where = 'WHERE `fileid` = ?'; $params = array($file); } $query = \OC_DB::prepare( - 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `etag` + 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `storage_mtime`, `encrypted`, `unencrypted_size`, `etag` FROM `*PREFIX*filecache` ' . $where); $result = $query->execute($params); $data = $result->fetchRow(); @@ -133,9 +126,13 @@ class Cache { $data['size'] = (int)$data['size']; $data['mtime'] = (int)$data['mtime']; $data['encrypted'] = (bool)$data['encrypted']; + $data['unencrypted_size'] = (int)$data['unencrypted_size']; $data['storage'] = $this->storageId; $data['mimetype'] = $this->getMimetype($data['mimetype']); $data['mimepart'] = $this->getMimetype($data['mimepart']); + if ($data['storage_mtime'] == 0) { + $data['storage_mtime'] = $data['mtime']; + } } return $data; @@ -151,13 +148,20 @@ class Cache { $fileId = $this->getId($folder); if ($fileId > -1) { $query = \OC_DB::prepare( - 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `etag` - FROM `*PREFIX*filecache` WHERE parent = ? ORDER BY `name` ASC'); + 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `storage_mtime`, `encrypted`, `unencrypted_size`, `etag` + FROM `*PREFIX*filecache` WHERE `parent` = ? ORDER BY `name` ASC'); + $result = $query->execute(array($fileId)); + if (\OC_DB::isError($result)) { + \OCP\Util::writeLog('cache', 'getFolderContents failed: ' . $result->getMessage(), \OCP\Util::ERROR); + } $files = $result->fetchAll(); foreach ($files as &$file) { $file['mimetype'] = $this->getMimetype($file['mimetype']); $file['mimepart'] = $this->getMimetype($file['mimepart']); + if ($file['storage_mtime'] == 0) { + $file['storage_mtime'] = $file['mtime']; + } } return $files; } else { @@ -178,6 +182,9 @@ class Cache { $this->update($id, $data); return $id; } else { + // normalize file + $file = $this->normalize($file); + if (isset($this->partial[$file])) { //add any saved partial data $data = array_merge($this->partial[$file], $data); unset($this->partial[$file]); @@ -198,14 +205,14 @@ class Cache { list($queryParts, $params) = $this->buildParts($data); $queryParts[] = '`storage`'; - $params[] = $this->numericId; + $params[] = $this->getNumericStorageId(); $valuesPlaceholder = array_fill(0, count($queryParts), '?'); $query = \OC_DB::prepare('INSERT INTO `*PREFIX*filecache`(' . implode(', ', $queryParts) . ')' . ' VALUES(' . implode(', ', $valuesPlaceholder) . ')'); $result = $query->execute($params); if (\OC_DB::isError($result)) { - \OCP\Util::writeLog('cache', 'Insert to cache failed: '.$result, \OCP\Util::ERROR); + \OCP\Util::writeLog('cache', 'Insert to cache failed: ' . $result->getMessage(), \OCP\Util::ERROR); } return (int)\OC_DB::insertid('*PREFIX*filecache'); @@ -219,6 +226,17 @@ class Cache { * @param array $data */ public function update($id, array $data) { + + if(isset($data['path'])) { + // normalize path + $data['path'] = $this->normalize($data['path']); + } + + if(isset($data['name'])) { + // normalize path + $data['name'] = $this->normalize($data['name']); + } + list($queryParts, $params) = $this->buildParts($data); $params[] = $id; @@ -234,7 +252,7 @@ class Cache { * @return array */ function buildParts(array $data) { - $fields = array('path', 'parent', 'name', 'mimetype', 'size', 'mtime', 'encrypted', 'etag'); + $fields = array('path', 'parent', 'name', 'mimetype', 'size', 'mtime', 'storage_mtime', 'encrypted', 'unencrypted_size', 'etag'); $params = array(); $queryParts = array(); foreach ($data as $name => $value) { @@ -246,6 +264,11 @@ class Cache { $params[] = $this->getMimetypeId(substr($value, 0, strpos($value, '/'))); $queryParts[] = '`mimepart`'; $value = $this->getMimetypeId($value); + } elseif ($name === 'storage_mtime') { + if (!isset($data['mtime'])) { + $params[] = $value; + $queryParts[] = '`mtime`'; + } } $params[] = $value; $queryParts[] = '`' . $name . '`'; @@ -261,10 +284,13 @@ class Cache { * @return int */ public function getId($file) { + // normalize file + $file = $this->normalize($file); + $pathHash = md5($file); $query = \OC_DB::prepare('SELECT `fileid` FROM `*PREFIX*filecache` WHERE `storage` = ? AND `path_hash` = ?'); - $result = $query->execute(array($this->numericId, $pathHash)); + $result = $query->execute(array($this->getNumericStorageId(), $pathHash)); if ($row = $result->fetchRow()) { return $row['fileid']; @@ -328,19 +354,26 @@ class Cache { * @param string $target */ public function move($source, $target) { - $sourceId = $this->getId($source); - $newParentId = $this->getParentId($target); + // normalize source and target + $source = $this->normalize($source); + $target = $this->normalize($target); - //find all child entries - $query = \OC_DB::prepare('SELECT `path`, `fileid` FROM `*PREFIX*filecache` WHERE `path` LIKE ?'); - $result = $query->execute(array($source . '/%')); - $childEntries = $result->fetchAll(); - $sourceLength = strlen($source); - $query = \OC_DB::prepare('UPDATE `*PREFIX*filecache` SET `path` = ?, `path_hash` = ? WHERE `fileid` = ?'); + $sourceData = $this->get($source); + $sourceId = $sourceData['fileid']; + $newParentId = $this->getParentId($target); - foreach ($childEntries as $child) { - $targetPath = $target . substr($child['path'], $sourceLength); - $query->execute(array($targetPath, md5($targetPath), $child['fileid'])); + if ($sourceData['mimetype'] === 'httpd/unix-directory') { + //find all child entries + $query = \OC_DB::prepare('SELECT `path`, `fileid` FROM `*PREFIX*filecache` WHERE `storage` = ? AND `path` LIKE ?'); + $result = $query->execute(array($this->getNumericStorageId(), $source . '/%')); + $childEntries = $result->fetchAll(); + $sourceLength = strlen($source); + $query = \OC_DB::prepare('UPDATE `*PREFIX*filecache` SET `path` = ?, `path_hash` = ? WHERE `fileid` = ?'); + + foreach ($childEntries as $child) { + $targetPath = $target . substr($child['path'], $sourceLength); + $query->execute(array($targetPath, md5($targetPath), $child['fileid'])); + } } $query = \OC_DB::prepare('UPDATE `*PREFIX*filecache` SET `path` = ?, `path_hash` = ?, `name` = ?, `parent` =?' @@ -353,7 +386,7 @@ class Cache { */ public function clear() { $query = \OC_DB::prepare('DELETE FROM `*PREFIX*filecache` WHERE storage = ?'); - $query->execute(array($this->numericId)); + $query->execute(array($this->getNumericStorageId())); $query = \OC_DB::prepare('DELETE FROM `*PREFIX*storages` WHERE id = ?'); $query->execute(array($this->storageId)); @@ -365,9 +398,15 @@ class Cache { * @return int, Cache::NOT_FOUND, Cache::PARTIAL, Cache::SHALLOW or Cache::COMPLETE */ public function getStatus($file) { + // normalize file + $file = $this->normalize($file); + $pathHash = md5($file); $query = \OC_DB::prepare('SELECT `size` FROM `*PREFIX*filecache` WHERE `storage` = ? AND `path_hash` = ?'); - $result = $query->execute(array($this->numericId, $pathHash)); + $result = $query->execute(array($this->getNumericStorageId(), $pathHash)); + if( \OC_DB::isError($result)) { + \OCP\Util::writeLog('cache', 'get status failed: ' . $result->getMessage(), \OCP\Util::ERROR); + } if ($row = $result->fetchRow()) { if ((int)$row['size'] === -1) { return self::SHALLOW; @@ -390,11 +429,15 @@ class Cache { * @return array of file data */ public function search($pattern) { + + // normalize pattern + $pattern = $this->normalize($pattern); + $query = \OC_DB::prepare(' - SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `etag` + SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `unencrypted_size`, `etag` FROM `*PREFIX*filecache` WHERE `name` LIKE ? AND `storage` = ?' ); - $result = $query->execute(array($pattern, $this->numericId)); + $result = $query->execute(array($pattern, $this->getNumericStorageId())); $files = array(); while ($row = $result->fetchRow()) { $row['mimetype'] = $this->getMimetype($row['mimetype']); @@ -417,11 +460,11 @@ class Cache { $where = '`mimepart` = ?'; } $query = \OC_DB::prepare(' - SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `etag` + SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `unencrypted_size`, `etag` FROM `*PREFIX*filecache` WHERE ' . $where . ' AND `storage` = ?' ); $mimetype = $this->getMimetypeId($mimetype); - $result = $query->execute(array($mimetype, $this->numericId)); + $result = $query->execute(array($mimetype, $this->getNumericStorageId())); $files = array(); while ($row = $result->fetchRow()) { $row['mimetype'] = $this->getMimetype($row['mimetype']); @@ -440,7 +483,7 @@ class Cache { $this->calculateFolderSize($path); if ($path !== '') { $parent = dirname($path); - if ($parent === '.') { + if ($parent === '.' or $parent === '/') { $parent = ''; } $this->correctFolderSize($parent); @@ -459,7 +502,7 @@ class Cache { return 0; } $query = \OC_DB::prepare('SELECT `size` FROM `*PREFIX*filecache` WHERE `parent` = ? AND `storage` = ?'); - $result = $query->execute(array($id, $this->numericId)); + $result = $query->execute(array($id, $this->getNumericStorageId())); $totalSize = 0; $hasChilds = 0; while ($row = $result->fetchRow()) { @@ -486,7 +529,7 @@ class Cache { */ public function getAll() { $query = \OC_DB::prepare('SELECT `fileid` FROM `*PREFIX*filecache` WHERE `storage` = ?'); - $result = $query->execute(array($this->numericId)); + $result = $query->execute(array($this->getNumericStorageId())); $ids = array(); while ($row = $result->fetchRow()) { $ids[] = $row['fileid']; @@ -505,8 +548,11 @@ class Cache { */ public function getIncomplete() { $query = \OC_DB::prepare('SELECT `path` FROM `*PREFIX*filecache`' - . ' WHERE `storage` = ? AND `size` = -1 ORDER BY `fileid` DESC LIMIT 1'); - $result = $query->execute(array($this->numericId)); + . ' WHERE `storage` = ? AND `size` = -1 ORDER BY `fileid` DESC',1); + $result = $query->execute(array($this->getNumericStorageId())); + if (\OC_DB::isError($result)) { + \OCP\Util::writeLog('cache', 'getIncomplete failed: ' . $result->getMessage(), \OCP\Util::ERROR); + } if ($row = $result->fetchRow()) { return $row['path']; } else { @@ -517,6 +563,7 @@ class Cache { /** * get the storage id of the storage for a file and the internal path of the file * + * @param int $id * @return array, first element holding the storage id, second the path */ static public function getById($id) { @@ -529,12 +576,20 @@ class Cache { return null; } - $query = \OC_DB::prepare('SELECT `id` FROM `*PREFIX*storages` WHERE `numeric_id` = ?'); - $result = $query->execute(array($numericId)); - if ($row = $result->fetchRow()) { - return array($row['id'], $path); + if ($id = Storage::getStorageId($numericId)) { + return array($id, $path); } else { return null; } } + + /** + * normalize the given path + * @param $path + * @return string + */ + public function normalize($path) { + + return \OC_Util::normalizeUnicode($path); + } } diff --git a/lib/files/cache/legacy.php b/lib/files/cache/legacy.php index 9556a2639a3..b8e2548639b 100644 --- a/lib/files/cache/legacy.php +++ b/lib/files/cache/legacy.php @@ -80,7 +80,7 @@ class Legacy { } $result = $query->execute(array($path)); $data = $result->fetchRow(); - $data['etag'] = $this->getEtag($data['path']); + $data['etag'] = $this->getEtag($data['path'], $data['user']); return $data; } @@ -90,12 +90,24 @@ class Legacy { * @param type $path * @return string */ - function getEtag($path) { + function getEtag($path, $user = null) { static $query = null; - list(, $user, , $relativePath) = explode('/', $path, 4); - if (is_null($relativePath)) { + + $pathDetails = explode('/', $path, 4); + if((!$user) && !isset($pathDetails[1])) { + //no user!? Too odd, return empty string. + return ''; + } else if(!$user) { + //guess user from path, if no user passed. + $user = $pathDetails[1]; + } + + if(!isset($pathDetails[3]) || is_null($pathDetails[3])) { $relativePath = ''; + } else { + $relativePath = $pathDetails[3]; } + if(is_null($query)){ $query = \OC_DB::prepare('SELECT `propertyvalue` FROM `*PREFIX*properties` WHERE `userid` = ? AND `propertypath` = ? AND `propertyname` = \'{DAV:}getetag\''); } @@ -118,7 +130,7 @@ class Legacy { $result = $query->execute(array($id)); $data = $result->fetchAll(); foreach ($data as $i => $item) { - $data[$i]['etag'] = $this->getEtag($item['path']); + $data[$i]['etag'] = $this->getEtag($item['path'], $item['user']); } return $data; } diff --git a/lib/files/cache/permissions.php b/lib/files/cache/permissions.php index a5c9c144054..29c30b0f36c 100644 --- a/lib/files/cache/permissions.php +++ b/lib/files/cache/permissions.php @@ -86,6 +86,26 @@ class Permissions { } /** + * get the permissions for all files in a folder + * + * @param int $parentId + * @param string $user + * @return int[] + */ + public function getDirectoryPermissions($parentId, $user) { + $query = \OC_DB::prepare('SELECT `*PREFIX*permissions`.`fileid`, `permissions` + FROM `*PREFIX*permissions` INNER JOIN `*PREFIX*filecache` ON `*PREFIX*permissions`.`fileid` = `*PREFIX*filecache`.`fileid` + WHERE `*PREFIX*filecache`.`parent` = ? AND `*PREFIX*permissions`.`user` = ?'); + + $result = $query->execute(array($parentId, $user)); + $filePermissions = array(); + while ($row = $result->fetchRow()) { + $filePermissions[$row['fileid']] = $row['permissions']; + } + return $filePermissions; + } + + /** * remove the permissions for a file * * @param int $fileId @@ -107,4 +127,19 @@ class Permissions { $query->execute(array($fileId, $user)); } } + + /** + * get the list of users which have permissions stored for a file + * + * @param int $fileId + */ + public function getUsers($fileId) { + $query = \OC_DB::prepare('SELECT `user` FROM `*PREFIX*permissions` WHERE `fileid` = ?'); + $result = $query->execute(array($fileId)); + $users = array(); + while ($row = $result->fetchRow()) { + $users[] = $row['user']; + } + return $users; + } } diff --git a/lib/files/cache/scanner.php b/lib/files/cache/scanner.php index f019d4fc608..8f9a7921956 100644 --- a/lib/files/cache/scanner.php +++ b/lib/files/cache/scanner.php @@ -51,6 +51,7 @@ class Scanner { $data['size'] = $this->storage->filesize($path); } $data['etag'] = $this->storage->getETag($path); + $data['storage_mtime'] = $data['mtime']; return $data; } @@ -62,31 +63,36 @@ class Scanner { * @return array with metadata of the scanned file */ public function scanFile($file, $checkExisting = false) { - if (!self::isIgnoredFile($file)) { + if ( ! self::isPartialFile($file) + and ! \OC\Files\Filesystem::isFileBlacklisted($file) + ) { \OC_Hook::emit('\OC\Files\Cache\Scanner', 'scan_file', array('path' => $file, 'storage' => $this->storageId)); $data = $this->getData($file); if ($data) { if ($file) { $parent = dirname($file); - if ($parent === '.') { + if ($parent === '.' or $parent === '/') { $parent = ''; } if (!$this->cache->inCache($parent)) { $this->scanFile($parent); } } - if($cacheData = $this->cache->get($file)) { + $newData = $data; + if ($cacheData = $this->cache->get($file)) { + if ($checkExisting && $data['size'] === -1) { + $data['size'] = $cacheData['size']; + } if ($data['mtime'] === $cacheData['mtime'] && $data['size'] === $cacheData['size']) { $data['etag'] = $cacheData['etag']; } + // Only update metadata that has changed + $newData = array_diff($data, $cacheData); } - if ($checkExisting and $cacheData) { - if ($data['size'] === -1) { - $data['size'] = $cacheData['size']; - } + if (!empty($newData)) { + $this->cache->put($file, $newData); } - $this->cache->put($file, $data); } return $data; } @@ -113,7 +119,7 @@ class Scanner { \OC_DB::beginTransaction(); while ($file = readdir($dh)) { $child = ($path) ? $path . '/' . $file : $file; - if (!$this->isIgnoredDir($file)) { + if (!\OC\Files\Filesystem::isIgnoredDir($file)) { $data = $this->scanFile($child, $recursive === self::SCAN_SHALLOW); if ($data) { if ($data['size'] === -1) { @@ -148,28 +154,14 @@ class Scanner { } /** - * @brief check if the directory should be ignored when scanning - * NOTE: the special directories . and .. would cause never ending recursion - * @param String $dir - * @return boolean - */ - private function isIgnoredDir($dir) { - if ($dir === '.' || $dir === '..') { - return true; - } - return false; - } - /** * @brief check if the file should be ignored when scanning * NOTE: files with a '.part' extension are ignored as well! * prevents unfinished put requests to be scanned * @param String $file * @return boolean */ - public static function isIgnoredFile($file) { - if (pathinfo($file, PATHINFO_EXTENSION) === 'part' - || \OC\Files\Filesystem::isFileBlacklisted($file) - ) { + public static function isPartialFile($file) { + if (pathinfo($file, PATHINFO_EXTENSION) === 'part') { return true; } return false; @@ -179,9 +171,11 @@ class Scanner { * walk over any folders that are not fully scanned yet and scan them */ public function backgroundScan() { - while (($path = $this->cache->getIncomplete()) !== false) { + $lastPath = null; + while (($path = $this->cache->getIncomplete()) !== false && $path !== $lastPath) { $this->scan($path); $this->cache->correctFolderSize($path); + $lastPath = $path; } } } diff --git a/lib/files/cache/storage.php b/lib/files/cache/storage.php new file mode 100644 index 00000000000..72de376798c --- /dev/null +++ b/lib/files/cache/storage.php @@ -0,0 +1,59 @@ +<?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\Cache; + +/** + * Class Storage + * + * cache storage specific data + * + * @package OC\Files\Cache + */ +class Storage { + private $storageId; + private $numericId; + + /** + * @param \OC\Files\Storage\Storage|string $storage + */ + public function __construct($storage) { + if ($storage instanceof \OC\Files\Storage\Storage) { + $this->storageId = $storage->getId(); + } else { + $this->storageId = $storage; + } + if (strlen($this->storageId) > 64) { + $this->storageId = md5($this->storageId); + } + + $query = \OC_DB::prepare('SELECT `numeric_id` FROM `*PREFIX*storages` WHERE `id` = ?'); + $result = $query->execute(array($this->storageId)); + if ($row = $result->fetchRow()) { + $this->numericId = $row['numeric_id']; + } else { + $query = \OC_DB::prepare('INSERT INTO `*PREFIX*storages`(`id`) VALUES(?)'); + $query->execute(array($this->storageId)); + $this->numericId = \OC_DB::insertid('*PREFIX*storages'); + } + } + + public function getNumericId() { + return $this->numericId; + } + + public static function getStorageId($numericId) { + $query = \OC_DB::prepare('SELECT `id` FROM `*PREFIX*storages` WHERE `numeric_id` = ?'); + $result = $query->execute(array($numericId)); + if ($row = $result->fetchRow()) { + return $row['id']; + } else { + return null; + } + } +} diff --git a/lib/files/cache/updater.php b/lib/files/cache/updater.php index 92a16d9d9b6..417a47f3830 100644 --- a/lib/files/cache/updater.php +++ b/lib/files/cache/updater.php @@ -132,7 +132,14 @@ class Updater { * @param array $params */ static public function touchHook($params) { - self::writeUpdate($params['path']); + $path = $params['path']; + list($storage, $internalPath) = self::resolvePath($path); + $cache = $storage->getCache(); + $id = $cache->getId($internalPath); + if ($id !== -1) { + $cache->update($id, array('etag' => $storage->getETag($internalPath))); + } + self::writeUpdate($path); } /** diff --git a/lib/files/cache/upgrade.php b/lib/files/cache/upgrade.php index 797f4e6ba8c..ca044ba81de 100644 --- a/lib/files/cache/upgrade.php +++ b/lib/files/cache/upgrade.php @@ -127,6 +127,10 @@ class Upgrade { * @return array */ function getNewData($data) { + //Make sure there is a path, otherwise we can do nothing. + if(!isset($data['path'])) { + return false; + } $newData = $data; /** * @var \OC\Files\Storage\Storage $storage diff --git a/lib/files/cache/watcher.php b/lib/files/cache/watcher.php index 31059ec7f56..8bfd4602f3a 100644 --- a/lib/files/cache/watcher.php +++ b/lib/files/cache/watcher.php @@ -43,7 +43,7 @@ class Watcher { */ public function checkUpdate($path) { $cachedEntry = $this->cache->get($path); - if ($this->storage->hasUpdated($path, $cachedEntry['mtime'])) { + if ($this->storage->hasUpdated($path, $cachedEntry['storage_mtime'])) { if ($this->storage->is_dir($path)) { $this->scanner->scan($path, Scanner::SCAN_SHALLOW); } else { diff --git a/lib/files/filesystem.php b/lib/files/filesystem.php index c8e62956f19..d3fddf8c421 100644 --- a/lib/files/filesystem.php +++ b/lib/files/filesystem.php @@ -34,6 +34,11 @@ const FREE_SPACE_UNKNOWN = -2; const FREE_SPACE_UNLIMITED = -3; class Filesystem { + /** + * @var Mount\Manager $mounts + */ + private static $mounts; + public static $loaded = false; /** * @var \OC\Files\View $defaultInstance @@ -147,7 +152,10 @@ class Filesystem { * @return string */ static public function getMountPoint($path) { - $mount = Mount::find($path); + if (!self::$mounts) { + \OC_Util::setupFS(); + } + $mount = self::$mounts->find($path); if ($mount) { return $mount->getMountPoint(); } else { @@ -162,8 +170,11 @@ class Filesystem { * @return string[] */ static public function getMountPoints($path) { + if (!self::$mounts) { + \OC_Util::setupFS(); + } $result = array(); - $mounts = Mount::findIn($path); + $mounts = self::$mounts->findIn($path); foreach ($mounts as $mount) { $result[] = $mount->getMountPoint(); } @@ -177,18 +188,46 @@ class Filesystem { * @return \OC\Files\Storage\Storage */ public static function getStorage($mountPoint) { - $mount = Mount::find($mountPoint); + if (!self::$mounts) { + \OC_Util::setupFS(); + } + $mount = self::$mounts->find($mountPoint); return $mount->getStorage(); } /** + * @param $id + * @return Mount\Mount[] + */ + public static function getMountByStorageId($id) { + if (!self::$mounts) { + \OC_Util::setupFS(); + } + return self::$mounts->findByStorageId($id); + } + + /** + * @param $id + * @return Mount\Mount[] + */ + public static function getMountByNumericId($id) { + if (!self::$mounts) { + \OC_Util::setupFS(); + } + return self::$mounts->findByNumericId($id); + } + + /** * resolve a path to a storage and internal path * * @param string $path * @return array consisting of the storage and the internal path */ static public function resolvePath($path) { - $mount = Mount::find($path); + if (!self::$mounts) { + \OC_Util::setupFS(); + } + $mount = self::$mounts->find($path); if ($mount) { return array($mount->getStorage(), $mount->getInternalPath($path)); } else { @@ -202,6 +241,10 @@ class Filesystem { } self::$defaultInstance = new View($root); + if (!self::$mounts) { + self::$mounts = new Mount\Manager(); + } + //load custom mount config self::initMountPoints($user); @@ -210,6 +253,12 @@ class Filesystem { return true; } + static public function initMounts() { + if (!self::$mounts) { + self::$mounts = new Mount\Manager(); + } + } + /** * Initialize system and personal mount points for a user * @@ -287,9 +336,9 @@ class Filesystem { } /** - * fill in the correct values for $user, and $password placeholders + * fill in the correct values for $user * - * @param string $input + * @param string $user * @param string $input * @return string */ @@ -311,6 +360,7 @@ class Filesystem { */ static public function tearDown() { self::clearMounts(); + self::$defaultInstance = null; } /** @@ -327,7 +377,9 @@ class Filesystem { * clear all mounts and storage backends */ public static function clearMounts() { - Mount::clear(); + if (self::$mounts) { + self::$mounts->clear(); + } } /** @@ -338,7 +390,11 @@ class Filesystem { * @param string $mountpoint */ static public function mount($class, $arguments, $mountpoint) { - new Mount($class, $mountpoint, $arguments); + if (!self::$mounts) { + \OC_Util::setupFS(); + } + $mount = new Mount\Mount($class, $mountpoint, $arguments); + self::$mounts->addMount($mount); } /** @@ -423,6 +479,19 @@ class Filesystem { } /** + * @brief check if the directory should be ignored when scanning + * NOTE: the special directories . and .. would cause never ending recursion + * @param String $dir + * @return boolean + */ + static public function isIgnoredDir($dir) { + if ($dir === '.' || $dir === '..') { + return true; + } + return false; + } + + /** * following functions are equivalent to their php builtin equivalents for arguments/return values. */ static public function mkdir($path) { @@ -585,9 +654,8 @@ class Filesystem { $path = substr($path, 0, -1); } //normalize unicode if possible - if (class_exists('Normalizer')) { - $path = \Normalizer::normalize($path); - } + $path = \OC_Util::normalizeUnicode($path); + return $path; } @@ -665,9 +733,4 @@ class Filesystem { } } -\OC_Hook::connect('OC_Filesystem', 'post_write', '\OC\Files\Cache\Updater', 'writeHook'); -\OC_Hook::connect('OC_Filesystem', 'post_touch', '\OC\Files\Cache\Updater', 'touchHook'); -\OC_Hook::connect('OC_Filesystem', 'post_delete', '\OC\Files\Cache\Updater', 'deleteHook'); -\OC_Hook::connect('OC_Filesystem', 'post_rename', '\OC\Files\Cache\Updater', 'renameHook'); - \OC_Util::setupFS(); diff --git a/lib/files/mount/manager.php b/lib/files/mount/manager.php new file mode 100644 index 00000000000..25a5fe241cc --- /dev/null +++ b/lib/files/mount/manager.php @@ -0,0 +1,120 @@ +<?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\Mount; + +use \OC\Files\Filesystem; + +class Manager { + /** + * @var Mount[] + */ + private $mounts = array(); + + /** + * @param Mount $mount + */ + public function addMount($mount) { + $this->mounts[$mount->getMountPoint()] = $mount; + } + + /** + * Find the mount for $path + * + * @param $path + * @return Mount + */ + public function find($path) { + \OC_Util::setupFS(); + $path = $this->formatPath($path); + if (isset($this->mounts[$path])) { + return $this->mounts[$path]; + } + + \OC_Hook::emit('OC_Filesystem', 'get_mountpoint', array('path' => $path)); + $foundMountPoint = ''; + $mountPoints = array_keys($this->mounts); + foreach ($mountPoints as $mountpoint) { + if (strpos($path, $mountpoint) === 0 and strlen($mountpoint) > strlen($foundMountPoint)) { + $foundMountPoint = $mountpoint; + } + } + if (isset($this->mounts[$foundMountPoint])) { + return $this->mounts[$foundMountPoint]; + } else { + return null; + } + } + + /** + * Find all mounts in $path + * + * @param $path + * @return Mount[] + */ + public function findIn($path) { + \OC_Util::setupFS(); + $path = $this->formatPath($path); + $result = array(); + $pathLength = strlen($path); + $mountPoints = array_keys($this->mounts); + foreach ($mountPoints as $mountPoint) { + if (substr($mountPoint, 0, $pathLength) === $path and strlen($mountPoint) > $pathLength) { + $result[] = $this->mounts[$mountPoint]; + } + } + return $result; + } + + public function clear() { + $this->mounts = array(); + } + + /** + * Find mounts by storage id + * + * @param string $id + * @return Mount[] + */ + public function findByStorageId($id) { + \OC_Util::setupFS(); + if (strlen($id) > 64) { + $id = md5($id); + } + $result = array(); + foreach ($this->mounts as $mount) { + if ($mount->getStorageId() === $id) { + $result[] = $mount; + } + } + return $result; + } + + /** + * Find mounts by numeric storage id + * + * @param string $id + * @return Mount + */ + public function findByNumericId($id) { + $storageId = \OC\Files\Cache\Storage::getStorageId($id); + return $this->findByStorageId($storageId); + } + + /** + * @param string $path + * @return string + */ + private function formatPath($path) { + $path = Filesystem::normalizePath($path); + if (strlen($path) > 1) { + $path .= '/'; + } + return $path; + } +} diff --git a/lib/files/mount.php b/lib/files/mount/mount.php index 59c98e9dcc8..69b8285ab4c 100644 --- a/lib/files/mount.php +++ b/lib/files/mount/mount.php @@ -6,13 +6,12 @@ * See the COPYING-README file. */ -namespace OC\Files; +namespace OC\Files\Mount; + +use \OC\Files\Filesystem; class Mount { - /** - * @var Mount[] - */ - static private $mounts = array(); + /** * @var \OC\Files\Storage\Storage $storage @@ -33,7 +32,7 @@ class Mount { $arguments = array(); } - $mountpoint = self::formatPath($mountpoint); + $mountpoint = $this->formatPath($mountpoint); if ($storage instanceof \OC\Files\Storage\Storage) { $this->class = get_class($storage); $this->storage = $storage; @@ -46,8 +45,6 @@ class Mount { $this->arguments = $arguments; } $this->mountPoint = $mountpoint; - - self::$mounts[$this->mountPoint] = $this; } /** @@ -58,6 +55,8 @@ class Mount { } /** + * create the storage that is mounted + * * @return \OC\Files\Storage\Storage */ private function createStorage() { @@ -121,100 +120,11 @@ class Mount { * @param string $path * @return string */ - private static function formatPath($path) { + private function formatPath($path) { $path = Filesystem::normalizePath($path); if (strlen($path) > 1) { $path .= '/'; } return $path; } - - /** - * Find the mount for $path - * - * @param $path - * @return Mount - */ - public static function find($path) { - $path = self::formatPath($path); - if (isset(self::$mounts[$path])) { - return self::$mounts[$path]; - } - - \OC_Hook::emit('OC_Filesystem', 'get_mountpoint', array('path' => $path)); - $foundMountPoint = ''; - $mountPoints = array_keys(self::$mounts); - foreach ($mountPoints as $mountpoint) { - if (strpos($path, $mountpoint) === 0 and strlen($mountpoint) > strlen($foundMountPoint)) { - $foundMountPoint = $mountpoint; - } - } - if (isset(self::$mounts[$foundMountPoint])) { - return self::$mounts[$foundMountPoint]; - } else { - return null; - } - } - - /** - * Find all mounts in $path - * - * @param $path - * @return Mount[] - */ - public static function findIn($path) { - $path = self::formatPath($path); - $result = array(); - $pathLength = strlen($path); - $mountPoints = array_keys(self::$mounts); - foreach ($mountPoints as $mountPoint) { - if (substr($mountPoint, 0, $pathLength) === $path and strlen($mountPoint) > $pathLength) { - $result[] = self::$mounts[$mountPoint]; - } - } - return $result; - } - - public static function clear() { - self::$mounts = array(); - } - - /** - * Find mounts by storage id - * - * @param string $id - * @return Mount[] - */ - public static function findByStorageId($id) { - if (strlen($id) > 64) { - $id = md5($id); - } - $result = array(); - foreach (self::$mounts as $mount) { - if ($mount->getStorageId() === $id) { - $result[] = $mount; - } - } - return $result; - } - - /** - * Find mounts by numeric storage id - * - * @param string $id - * @return Mount - */ - public static function findByNumericId($id) { - $query = \OC_DB::prepare('SELECT `id` FROM `*PREFIX*storages` WHERE `numeric_id` = ?'); - $result = $query->execute(array($id))->fetchOne(); - if ($result) { - $id = $result; - foreach (self::$mounts as $mount) { - if ($mount->getStorageId() === $id) { - return $mount; - } - } - } - return false; - } } diff --git a/lib/files/storage/common.php b/lib/files/storage/common.php index 38fe5e546f6..3da13ac4df0 100644 --- a/lib/files/storage/common.php +++ b/lib/files/storage/common.php @@ -25,6 +25,7 @@ abstract class Common implements \OC\Files\Storage\Storage { private $scanner; private $permissioncache; private $watcher; + private $storageCache; public function __construct($parameters) { } @@ -137,27 +138,21 @@ abstract class Common implements \OC\Files\Storage\Storage { */ public function deleteAll($directory, $empty = false) { $directory = trim($directory, '/'); - - if (!$this->file_exists(\OCP\USER::getUser() . '/' . $directory) - || !$this->is_dir(\OCP\USER::getUser() . '/' . $directory) - ) { - return false; - } elseif (!$this->isReadable(\OCP\USER::getUser() . '/' . $directory)) { + if (!$this->is_dir($directory) || !$this->isReadable($directory)) { return false; } else { - $directoryHandle = $this->opendir(\OCP\USER::getUser() . '/' . $directory); + $directoryHandle = $this->opendir($directory); while ($contents = readdir($directoryHandle)) { - if ($contents != '.' && $contents != '..') { - $path = $directory . "/" . $contents; + if (!\OC\Files\Filesystem::isIgnoredDir($contents)) { + $path = $directory . '/' . $contents; if ($this->is_dir($path)) { $this->deleteAll($path); } else { - $this->unlink(\OCP\USER::getUser() . '/' . $path); // TODO: make unlink use same system path as is_dir + $this->unlink($path); } } } - //$this->closedir( $directoryHandle ); // TODO: implement closedir in OC_FSV - if ($empty == false) { + if ($empty === false) { if (!$this->rmdir($directory)) { return false; } @@ -300,6 +295,13 @@ abstract class Common implements \OC\Files\Storage\Storage { return $this->watcher; } + public function getStorageCache(){ + if (!isset($this->storageCache)) { + $this->storageCache = new \OC\Files\Cache\Storage($this); + } + return $this->storageCache; + } + /** * get the owner of a path * @@ -361,7 +363,7 @@ abstract class Common implements \OC\Files\Storage\Storage { * get the free space in the storage * * @param $path - * return int + * @return int */ public function free_space($path) { return \OC\Files\FREE_SPACE_UNKNOWN; diff --git a/lib/files/storage/local.php b/lib/files/storage/local.php index 81e32587fca..d684905bf9a 100644 --- a/lib/files/storage/local.php +++ b/lib/files/storage/local.php @@ -14,252 +14,277 @@ if (\OC_Util::runningOnWindows()) { } } else { -/** - * for local filestore, we only have to map the paths - */ -class Local extends \OC\Files\Storage\Common{ - protected $datadir; - public function __construct($arguments) { - $this->datadir=$arguments['datadir']; - if(substr($this->datadir, -1)!=='/') { - $this->datadir.='/'; + /** + * for local filestore, we only have to map the paths + */ + class Local extends \OC\Files\Storage\Common { + protected $datadir; + + public function __construct($arguments) { + $this->datadir = $arguments['datadir']; + if (substr($this->datadir, -1) !== '/') { + $this->datadir .= '/'; + } } - } - public function __destruct() { - } - public function getId(){ - return 'local::'.$this->datadir; - } - public function mkdir($path) { - return @mkdir($this->datadir.$path); - } - public function rmdir($path) { - return @rmdir($this->datadir.$path); - } - public function opendir($path) { - return opendir($this->datadir.$path); - } - public function is_dir($path) { - if(substr($path, -1)=='/') { - $path=substr($path, 0, -1); + + public function __destruct() { } - return is_dir($this->datadir.$path); - } - public function is_file($path) { - return is_file($this->datadir.$path); - } - public function stat($path) { - $fullPath = $this->datadir . $path; - $statResult = stat($fullPath); - if ($statResult['size'] < 0) { - $size = self::getFileSizeFromOS($fullPath); - $statResult['size'] = $size; - $statResult[7] = $size; + public function getId() { + return 'local::' . $this->datadir; } - return $statResult; - } - public function filetype($path) { - $filetype=filetype($this->datadir.$path); - if($filetype=='link') { - $filetype=filetype(realpath($this->datadir.$path)); + + public function mkdir($path) { + return @mkdir($this->datadir . $path); } - return $filetype; - } - public function filesize($path) { - if($this->is_dir($path)) { - return 0; - }else{ - $fullPath = $this->datadir . $path; - $fileSize = filesize($fullPath); - if ($fileSize < 0) { - return self::getFileSizeFromOS($fullPath); + + public function rmdir($path) { + return @rmdir($this->datadir . $path); + } + + public function opendir($path) { + return opendir($this->datadir . $path); + } + + public function is_dir($path) { + if (substr($path, -1) == '/') { + $path = substr($path, 0, -1); } + return is_dir($this->datadir . $path); + } - return $fileSize; + public function is_file($path) { + return is_file($this->datadir . $path); } - } - public function isReadable($path) { - return is_readable($this->datadir.$path); - } - public function isUpdatable($path) { - return is_writable($this->datadir.$path); - } - public function file_exists($path) { - return file_exists($this->datadir.$path); - } - public function filemtime($path) { - return filemtime($this->datadir.$path); - } - public function touch($path, $mtime=null) { - // sets the modification time of the file to the given value. - // If mtime is nil the current time is set. - // note that the access time of the file always changes to the current time. - if($this->file_exists($path) and !$this->isUpdatable($path)) { - return false; + + public function stat($path) { + $fullPath = $this->datadir . $path; + $statResult = stat($fullPath); + + if ($statResult['size'] < 0) { + $size = self::getFileSizeFromOS($fullPath); + $statResult['size'] = $size; + $statResult[7] = $size; + } + return $statResult; } - if(!is_null($mtime)) { - $result=touch( $this->datadir.$path, $mtime ); - }else{ - $result=touch( $this->datadir.$path); + + public function filetype($path) { + $filetype = filetype($this->datadir . $path); + if ($filetype == 'link') { + $filetype = filetype(realpath($this->datadir . $path)); + } + return $filetype; } - if( $result ) { - clearstatcache( true, $this->datadir.$path ); + + public function filesize($path) { + if ($this->is_dir($path)) { + return 0; + } else { + $fullPath = $this->datadir . $path; + $fileSize = filesize($fullPath); + if ($fileSize < 0) { + return self::getFileSizeFromOS($fullPath); + } + + return $fileSize; + } } - return $result; - } - public function file_get_contents($path) { - return file_get_contents($this->datadir.$path); - } - public function file_put_contents($path, $data) {//trigger_error("$path = ".var_export($path, 1)); - return file_put_contents($this->datadir.$path, $data); - } - public function unlink($path) { - return $this->delTree($path); - } - public function rename($path1, $path2) { - if (!$this->isUpdatable($path1)) { - \OC_Log::write('core', 'unable to rename, file is not writable : '.$path1, \OC_Log::ERROR); - return false; + public function isReadable($path) { + return is_readable($this->datadir . $path); } - if(! $this->file_exists($path1)) { - \OC_Log::write('core', 'unable to rename, file does not exists : '.$path1, \OC_Log::ERROR); - return false; + + public function isUpdatable($path) { + return is_writable($this->datadir . $path); } - if($return=rename($this->datadir.$path1, $this->datadir.$path2)) { + public function file_exists($path) { + return file_exists($this->datadir . $path); } - return $return; - } - public function copy($path1, $path2) { - if($this->is_dir($path2)) { - if(!$this->file_exists($path2)) { - $this->mkdir($path2); + + public function filemtime($path) { + return filemtime($this->datadir . $path); + } + + public function touch($path, $mtime = null) { + // sets the modification time of the file to the given value. + // If mtime is nil the current time is set. + // note that the access time of the file always changes to the current time. + if ($this->file_exists($path) and !$this->isUpdatable($path)) { + return false; } - $source=substr($path1, strrpos($path1, '/')+1); - $path2.=$source; + if (!is_null($mtime)) { + $result = touch($this->datadir . $path, $mtime); + } else { + $result = touch($this->datadir . $path); + } + if ($result) { + clearstatcache(true, $this->datadir . $path); + } + + return $result; } - return copy($this->datadir.$path1, $this->datadir.$path2); - } - public function fopen($path, $mode) { - if($return=fopen($this->datadir.$path, $mode)) { - switch($mode) { - case 'r': - break; - case 'r+': - case 'w+': - case 'x+': - case 'a+': - break; - case 'w': - case 'x': - case 'a': - break; + + public function file_get_contents($path) { + return file_get_contents($this->datadir . $path); + } + + public function file_put_contents($path, $data) { //trigger_error("$path = ".var_export($path, 1)); + return file_put_contents($this->datadir . $path, $data); + } + + public function unlink($path) { + return $this->delTree($path); + } + + public function rename($path1, $path2) { + if (!$this->isUpdatable($path1)) { + \OC_Log::write('core', 'unable to rename, file is not writable : ' . $path1, \OC_Log::ERROR); + return false; + } + if (!$this->file_exists($path1)) { + \OC_Log::write('core', 'unable to rename, file does not exists : ' . $path1, \OC_Log::ERROR); + return false; } + + if ($return = rename($this->datadir . $path1, $this->datadir . $path2)) { + } + return $return; } - return $return; - } - public function getMimeType($path) { - if($this->isReadable($path)) { - return \OC_Helper::getMimeType($this->datadir . $path); - }else{ - return false; + public function copy($path1, $path2) { + if ($this->is_dir($path2)) { + if (!$this->file_exists($path2)) { + $this->mkdir($path2); + } + $source = substr($path1, strrpos($path1, '/') + 1); + $path2 .= $source; + } + return copy($this->datadir . $path1, $this->datadir . $path2); } - } - private function delTree($dir) { - $dirRelative=$dir; - $dir=$this->datadir.$dir; - if (!file_exists($dir)) return true; - if (!is_dir($dir) || is_link($dir)) return unlink($dir); - foreach (scandir($dir) as $item) { - if ($item == '.' || $item == '..') continue; - if(is_file($dir.'/'.$item)) { - if(unlink($dir.'/'.$item)) { + public function fopen($path, $mode) { + if ($return = fopen($this->datadir . $path, $mode)) { + switch ($mode) { + case 'r': + break; + case 'r+': + case 'w+': + case 'x+': + case 'a+': + break; + case 'w': + case 'x': + case 'a': + break; } - }elseif(is_dir($dir.'/'.$item)) { - if (!$this->delTree($dirRelative. "/" . $item)) { - return false; - }; } + return $return; } - if($return=rmdir($dir)) { + + public function getMimeType($path) { + if ($this->isReadable($path)) { + return \OC_Helper::getMimeType($this->datadir . $path); + } else { + return false; + } } - return $return; - } - private static function getFileSizeFromOS($fullPath) { - $name = strtolower(php_uname('s')); - // Windows OS: we use COM to access the filesystem - if (strpos($name, 'win') !== false) { - if (class_exists('COM')) { - $fsobj = new \COM("Scripting.FileSystemObject"); - $f = $fsobj->GetFile($fullPath); - return $f->Size; + private function delTree($dir) { + $dirRelative = $dir; + $dir = $this->datadir . $dir; + if (!file_exists($dir)) return true; + if (!is_dir($dir) || is_link($dir)) return unlink($dir); + foreach (scandir($dir) as $item) { + if ($item == '.' || $item == '..') continue; + if (is_file($dir . '/' . $item)) { + if (unlink($dir . '/' . $item)) { + } + } elseif (is_dir($dir . '/' . $item)) { + if (!$this->delTree($dirRelative . "/" . $item)) { + return false; + }; + } } - } else if (strpos($name, 'bsd') !== false) { - if (\OC_Helper::is_function_enabled('exec')) { - return (float)exec('stat -f %z ' . escapeshellarg($fullPath)); + if ($return = rmdir($dir)) { } - } else if (strpos($name, 'linux') !== false) { - if (\OC_Helper::is_function_enabled('exec')) { - return (float)exec('stat -c %s ' . escapeshellarg($fullPath)); + return $return; + } + + private static function getFileSizeFromOS($fullPath) { + $name = strtolower(php_uname('s')); + // Windows OS: we use COM to access the filesystem + if (strpos($name, 'win') !== false) { + if (class_exists('COM')) { + $fsobj = new \COM("Scripting.FileSystemObject"); + $f = $fsobj->GetFile($fullPath); + return $f->Size; + } + } else if (strpos($name, 'bsd') !== false) { + if (\OC_Helper::is_function_enabled('exec')) { + return (float)exec('stat -f %z ' . escapeshellarg($fullPath)); + } + } else if (strpos($name, 'linux') !== false) { + if (\OC_Helper::is_function_enabled('exec')) { + return (float)exec('stat -c %s ' . escapeshellarg($fullPath)); + } + } else { + \OC_Log::write('core', + 'Unable to determine file size of "' . $fullPath . '". Unknown OS: ' . $name, + \OC_Log::ERROR); } - } else { - \OC_Log::write('core', - 'Unable to determine file size of "'.$fullPath.'". Unknown OS: '.$name, - \OC_Log::ERROR); + + return 0; } - return 0; - } + public function hash($path, $type, $raw = false) { + return hash_file($type, $this->datadir . $path, $raw); + } - public function hash($path, $type, $raw=false) { - return hash_file($type, $this->datadir.$path, $raw); - } + public function free_space($path) { + $space = @disk_free_space($this->datadir . $path); + if ($space === false) { + return \OC\Files\FREE_SPACE_UNKNOWN; + } + return $space; + } - public function free_space($path) { - $space = @disk_free_space($this->datadir.$path); - if($space === false){ - return \OC\Files\FREE_SPACE_UNKNOWN; + public function search($query) { + return $this->searchInDir($query); } - return $space; - } - public function search($query) { - return $this->searchInDir($query); - } - public function getLocalFile($path) { - return $this->datadir.$path; - } - public function getLocalFolder($path) { - return $this->datadir.$path; - } + public function getLocalFile($path) { + return $this->datadir . $path; + } - protected function searchInDir($query, $dir='') { - $files=array(); - foreach (scandir($this->datadir.$dir) as $item) { - if ($item == '.' || $item == '..') continue; - if(strstr(strtolower($item), strtolower($query))!==false) { - $files[]=$dir.'/'.$item; - } - if(is_dir($this->datadir.$dir.'/'.$item)) { - $files=array_merge($files, $this->searchInDir($query, $dir.'/'.$item)); + public function getLocalFolder($path) { + return $this->datadir . $path; + } + + protected function searchInDir($query, $dir = '') { + $files = array(); + foreach (scandir($this->datadir . $dir) as $item) { + if ($item == '.' || $item == '..') continue; + if (strstr(strtolower($item), strtolower($query)) !== false) { + $files[] = $dir . '/' . $item; + } + if (is_dir($this->datadir . $dir . '/' . $item)) { + $files = array_merge($files, $this->searchInDir($query, $dir . '/' . $item)); + } } + return $files; } - return $files; - } - /** - * check if a file or folder has been updated since $time - * @param string $path - * @param int $time - * @return bool - */ - public function hasUpdated($path, $time) { - return $this->filemtime($path)>$time; + /** + * check if a file or folder has been updated since $time + * + * @param string $path + * @param int $time + * @return bool + */ + public function hasUpdated($path, $time) { + return $this->filemtime($path) > $time; + } } } -} diff --git a/lib/files/storage/storage.php b/lib/files/storage/storage.php index 1da82da2163..c96caebf4af 100644 --- a/lib/files/storage/storage.php +++ b/lib/files/storage/storage.php @@ -329,6 +329,11 @@ interface Storage { public function getWatcher($path = ''); /** + * @return \OC\Files\Cache\Storage + */ + public function getStorageCache(); + + /** * get the ETag for a file or folder * * @param string $path diff --git a/lib/files/view.php b/lib/files/view.php index d2d1a99818b..e2fc8d965b8 100644 --- a/lib/files/view.php +++ b/lib/files/view.php @@ -245,14 +245,17 @@ class View { if (!is_null($mtime) and !is_numeric($mtime)) { $mtime = strtotime($mtime); } - + $hooks = array('touch'); - + if (!$this->file_exists($path)) { $hooks[] = 'write'; } - - return $this->basicOperation('touch', $path, $hooks, $mtime); + $result = $this->basicOperation('touch', $path, $hooks, $mtime); + if (!$result) { //if native touch fails, we emulate it by changing the mtime in the cache + $this->putFileInfo($path, array('mtime' => $mtime)); + } + return true; } public function file_get_contents($path) { @@ -263,11 +266,13 @@ class View { if (is_resource($data)) { //not having to deal with streams in file_put_contents makes life easier $absolutePath = Filesystem::normalizePath($this->getAbsolutePath($path)); if (\OC_FileProxy::runPreProxies('file_put_contents', $absolutePath, $data) - && Filesystem::isValidPath($path)) { + and Filesystem::isValidPath($path) + and !Filesystem::isFileBlacklisted($path) + ) { $path = $this->getRelativePath($absolutePath); $exists = $this->file_exists($path); $run = true; - if ($this->fakeRoot == Filesystem::getRoot() && ! Cache\Scanner::isIgnoredFile($path) ) { + if ($this->fakeRoot == Filesystem::getRoot() && !Cache\Scanner::isPartialFile($path)) { if (!$exists) { \OC_Hook::emit( Filesystem::CLASSNAME, @@ -295,7 +300,7 @@ class View { list ($count, $result) = \OC_Helper::streamCopy($data, $target); fclose($target); fclose($data); - if ($this->fakeRoot == Filesystem::getRoot() && ! Cache\Scanner::isIgnoredFile($path) && $result !== false) { + if ($this->fakeRoot == Filesystem::getRoot() && !Cache\Scanner::isPartialFile($path) && $result !== false) { if (!$exists) { \OC_Hook::emit( Filesystem::CLASSNAME, @@ -335,8 +340,12 @@ class View { $postFix2 = (substr($path2, -1, 1) === '/') ? '/' : ''; $absolutePath1 = Filesystem::normalizePath($this->getAbsolutePath($path1)); $absolutePath2 = Filesystem::normalizePath($this->getAbsolutePath($path2)); - if (\OC_FileProxy::runPreProxies('rename', $absolutePath1, $absolutePath2) - and Filesystem::isValidPath($path2)) { + if ( + \OC_FileProxy::runPreProxies('rename', $absolutePath1, $absolutePath2) + and Filesystem::isValidPath($path2) + and Filesystem::isValidPath($path1) + and !Filesystem::isFileBlacklisted($path2) + ) { $path1 = $this->getRelativePath($absolutePath1); $path2 = $this->getRelativePath($absolutePath2); @@ -344,7 +353,7 @@ class View { return false; } $run = true; - if ($this->fakeRoot == Filesystem::getRoot()) { + if ($this->fakeRoot == Filesystem::getRoot() && !Cache\Scanner::isPartialFile($path1)) { \OC_Hook::emit( Filesystem::CLASSNAME, Filesystem::signal_rename, array( @@ -362,19 +371,28 @@ class View { list(, $internalPath2) = Filesystem::resolvePath($absolutePath2 . $postFix2); if ($storage) { $result = $storage->rename($internalPath1, $internalPath2); + \OC_FileProxy::runPostProxies('rename', $absolutePath1, $absolutePath2); } else { $result = false; } } else { - $source = $this->fopen($path1 . $postFix1, 'r'); - $target = $this->fopen($path2 . $postFix2, 'w'); - list($count, $result) = \OC_Helper::streamCopy($source, $target); - list($storage1, $internalPath1) = Filesystem::resolvePath($absolutePath1 . $postFix1); - if ($result !== false) { - $storage1->unlink($internalPath1); + if ($this->is_dir($path1)) { + $result = $this->copy($path1, $path2); + if ($result === true) { + list($storage1, $internalPath1) = Filesystem::resolvePath($absolutePath1 . $postFix1); + $result = $storage1->deleteAll($internalPath1); + } + } else { + $source = $this->fopen($path1 . $postFix1, 'r'); + $target = $this->fopen($path2 . $postFix2, 'w'); + list($count, $result) = \OC_Helper::streamCopy($source, $target); + if ($result !== false) { + list($storage1, $internalPath1) = Filesystem::resolvePath($absolutePath1 . $postFix1); + $storage1->unlink($internalPath1); + } } } - if ($this->fakeRoot == Filesystem::getRoot() && $result !== false) { + if ($this->fakeRoot == Filesystem::getRoot() && !Cache\Scanner::isPartialFile($path1) && $result !== false) { \OC_Hook::emit( Filesystem::CLASSNAME, Filesystem::signal_post_rename, @@ -398,7 +416,12 @@ class View { $postFix2 = (substr($path2, -1, 1) === '/') ? '/' : ''; $absolutePath1 = Filesystem::normalizePath($this->getAbsolutePath($path1)); $absolutePath2 = Filesystem::normalizePath($this->getAbsolutePath($path2)); - if (\OC_FileProxy::runPreProxies('copy', $absolutePath1, $absolutePath2) and Filesystem::isValidPath($path2)) { + if ( + \OC_FileProxy::runPreProxies('copy', $absolutePath1, $absolutePath2) + and Filesystem::isValidPath($path2) + and Filesystem::isValidPath($path1) + and !Filesystem::isFileBlacklisted($path2) + ) { $path1 = $this->getRelativePath($absolutePath1); $path2 = $this->getRelativePath($absolutePath2); @@ -450,9 +473,18 @@ class View { $result = false; } } else { - $source = $this->fopen($path1 . $postFix1, 'r'); - $target = $this->fopen($path2 . $postFix2, 'w'); - list($count, $result) = \OC_Helper::streamCopy($source, $target); + if ($this->is_dir($path1) && ($dh = $this->opendir($path1))) { + $result = $this->mkdir($path2); + while ($file = readdir($dh)) { + if (!Filesystem::isIgnoredDir($file)) { + $result = $this->copy($path1 . '/' . $file, $path2 . '/' . $file); + } + } + } else { + $source = $this->fopen($path1 . $postFix1, 'r'); + $target = $this->fopen($path2 . $postFix2, 'w'); + list($count, $result) = \OC_Helper::streamCopy($source, $target); + } } if ($this->fakeRoot == Filesystem::getRoot() && $result !== false) { \OC_Hook::emit( @@ -600,7 +632,10 @@ class View { private function basicOperation($operation, $path, $hooks = array(), $extraParam = null) { $postFix = (substr($path, -1, 1) === '/') ? '/' : ''; $absolutePath = Filesystem::normalizePath($this->getAbsolutePath($path)); - if (\OC_FileProxy::runPreProxies($operation, $absolutePath, $extraParam) and Filesystem::isValidPath($path)) { + if (\OC_FileProxy::runPreProxies($operation, $absolutePath, $extraParam) + and Filesystem::isValidPath($path) + and !Filesystem::isFileBlacklisted($path) + ) { $path = $this->getRelativePath($absolutePath); if ($path == null) { return false; @@ -629,7 +664,7 @@ class View { private function runHooks($hooks, $path, $post = false) { $prefix = ($post) ? 'post_' : ''; $run = true; - if (Filesystem::$loaded and $this->fakeRoot == Filesystem::getRoot() && ! Cache\Scanner::isIgnoredFile($path) ) { + if (Filesystem::$loaded and $this->fakeRoot == Filesystem::getRoot()) { foreach ($hooks as $hook) { if ($hook != 'read') { \OC_Hook::emit( @@ -726,6 +761,9 @@ class View { $data['permissions'] = $permissions; } } + + $data = \OC_FileProxy::runPostProxies('getFileInfo', $path, $data); + return $data; } @@ -761,18 +799,18 @@ class View { } $files = $cache->getFolderContents($internalPath); //TODO: mimetype_filter + $permissions = $permissionsCache->getDirectoryPermissions($cache->getId($internalPath), $user); $ids = array(); foreach ($files as $i => $file) { $files[$i]['type'] = $file['mimetype'] === 'httpd/unix-directory' ? 'dir' : 'file'; $ids[] = $file['fileid']; - $permissions = $permissionsCache->get($file['fileid'], $user); - if ($permissions === -1) { - $permissions = $storage->getPermissions($file['path']); - $permissionsCache->set($file['fileid'], $user, $permissions); + if (!isset($permissions[$file['fileid']])) { + $permissions[$file['fileid']] = $storage->getPermissions($file['path']); + $permissionsCache->set($file['fileid'], $user, $permissions[$file['fileid']]); } - $files[$i]['permissions'] = $permissions; + $files[$i]['permissions'] = $permissions[$file['fileid']]; } //add a folder for any mountpoint in this directory and add the sizes of other mountpoints to the folders @@ -933,11 +971,11 @@ class View { } /** - * Get the owner for a file or folder - * - * @param string $path - * @return string - */ + * Get the owner for a file or folder + * + * @param string $path + * @return string + */ public function getOwner($path) { return $this->basicOperation('getOwner', $path); } @@ -971,7 +1009,7 @@ class View { */ public function getPath($id) { list($storage, $internalPath) = Cache\Cache::getById($id); - $mounts = Mount::findByStorageId($storage); + $mounts = Filesystem::getMountByStorageId($storage); foreach ($mounts as $mount) { /** * @var \OC\Files\Mount $mount diff --git a/lib/helper.php b/lib/helper.php index 73484ad913f..225e9fd2a9a 100644 --- a/lib/helper.php +++ b/lib/helper.php @@ -27,6 +27,7 @@ class OC_Helper { private static $mimetypes=array(); private static $tmpFiles=array(); + private static $mimetypeIcons = array(); /** * @brief Creates an url using a defined route @@ -159,7 +160,7 @@ class OC_Helper { */ public static function imagePath( $app, $image ) { // Read the selected theme from the config file - $theme=OC_Config::getValue( "theme" ); + $theme = OC_Util::getTheme(); // Check if the app is in the app folder if( file_exists( OC::$SERVERROOT."/themes/$theme/apps/$app/img/$image" )) { @@ -187,31 +188,38 @@ class OC_Helper { * * Returns the path to the image of this file type. */ - public static function mimetypeIcon( $mimetype ) { - $alias=array('application/xml'=>'code/xml'); - if(isset($alias[$mimetype])) { - $mimetype=$alias[$mimetype]; + public static function mimetypeIcon($mimetype) { + $alias = array('application/xml' => 'code/xml'); + if (isset($alias[$mimetype])) { + $mimetype = $alias[$mimetype]; + } + if (isset(self::$mimetypeIcons[$mimetype])) { + return self::$mimetypeIcons[$mimetype]; } // Replace slash and backslash with a minus - $mimetype = str_replace( "/", "-", $mimetype ); - $mimetype = str_replace( "\\", "-", $mimetype ); + $icon = str_replace('/', '-', $mimetype); + $icon = str_replace( '\\', '-', $icon); // Is it a dir? - if( $mimetype == "dir" ) { - return OC::$WEBROOT."/core/img/filetypes/folder.png"; + if ($mimetype === 'dir') { + self::$mimetypeIcons[$mimetype] = OC::$WEBROOT.'/core/img/filetypes/folder.png'; + return OC::$WEBROOT.'/core/img/filetypes/folder.png'; } // Icon exists? - if( file_exists( OC::$SERVERROOT."/core/img/filetypes/$mimetype.png" )) { - return OC::$WEBROOT."/core/img/filetypes/$mimetype.png"; - } - //try only the first part of the filetype - $mimetype=substr($mimetype, 0, strpos($mimetype, '-')); - if( file_exists( OC::$SERVERROOT."/core/img/filetypes/$mimetype.png" )) { - return OC::$WEBROOT."/core/img/filetypes/$mimetype.png"; + if (file_exists(OC::$SERVERROOT.'/core/img/filetypes/'.$icon.'.png')) { + self::$mimetypeIcons[$mimetype] = OC::$WEBROOT.'/core/img/filetypes/'.$icon.'.png'; + return OC::$WEBROOT.'/core/img/filetypes/'.$icon.'.png'; } - else{ - return OC::$WEBROOT."/core/img/filetypes/file.png"; + + // Try only the first part of the filetype + $mimePart = substr($icon, 0, strpos($icon, '-')); + if (file_exists(OC::$SERVERROOT.'/core/img/filetypes/'.$mimePart.'.png')) { + self::$mimetypeIcons[$mimetype] = OC::$WEBROOT.'/core/img/filetypes/'.$mimePart.'.png'; + return OC::$WEBROOT.'/core/img/filetypes/'.$mimePart.'.png'; + } else { + self::$mimetypeIcons[$mimetype] = OC::$WEBROOT.'/core/img/filetypes/file.png'; + return OC::$WEBROOT.'/core/img/filetypes/file.png'; } } @@ -541,13 +549,15 @@ class OC_Helper { } /** - * create a temporary file with an unique filename. It will not be deleted - * automatically - * @param string $postfix - * @return string + * move a file to oc-noclean temp dir + * @param string $filename + * @return mixed * */ - public static function tmpFileNoClean($postfix='') { + public static function moveToNoClean($filename='') { + if ($filename == '') { + return false; + } $tmpDirNoClean=get_temp_dir().'/oc-noclean/'; if (!file_exists($tmpDirNoClean) || !is_dir($tmpDirNoClean)) { if (file_exists($tmpDirNoClean)) { @@ -555,10 +565,12 @@ class OC_Helper { } mkdir($tmpDirNoClean); } - $file=$tmpDirNoClean.md5(time().rand()).$postfix; - $fh=fopen($file, 'w'); - fclose($fh); - return $file; + $newname=$tmpDirNoClean.basename($filename); + if (rename($filename, $newname)) { + return $newname; + } else { + return false; + } } /** @@ -597,7 +609,7 @@ class OC_Helper { } /** - * remove all files created by self::tmpFileNoClean + * remove all files in PHP /oc-noclean temp dir */ public static function cleanTmpNoClean() { $tmpDirNoCleanFile=get_temp_dir().'/oc-noclean/'; diff --git a/lib/hooks/basicemitter.php b/lib/hooks/basicemitter.php new file mode 100644 index 00000000000..e615a58cfe8 --- /dev/null +++ b/lib/hooks/basicemitter.php @@ -0,0 +1,89 @@ +<?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\Hooks; + +abstract class BasicEmitter implements Emitter { + + /** + * @var (callable[])[] $listeners + */ + private $listeners = array(); + + /** + * @param string $scope + * @param string $method + * @param callable $callback + */ + public function listen($scope, $method, $callback) { + $eventName = $scope . '::' . $method; + if (!isset($this->listeners[$eventName])) { + $this->listeners[$eventName] = array(); + } + if (array_search($callback, $this->listeners[$eventName]) === false) { + $this->listeners[$eventName][] = $callback; + } + } + + /** + * @param string $scope optional + * @param string $method optional + * @param callable $callback optional + */ + public function removeListener($scope = null, $method = null, $callback = null) { + $names = array(); + $allNames = array_keys($this->listeners); + if ($scope and $method) { + $name = $scope . '::' . $method; + if (isset($this->listeners[$name])) { + $names[] = $name; + } + } elseif ($scope) { + foreach ($allNames as $name) { + $parts = explode('::', $name, 2); + if ($parts[0] == $scope) { + $names[] = $name; + } + } + } elseif ($method) { + foreach ($allNames as $name) { + $parts = explode('::', $name, 2); + if ($parts[1] == $method) { + $names[] = $name; + } + } + } else { + $names = $allNames; + } + + foreach ($names as $name) { + if ($callback) { + $index = array_search($callback, $this->listeners[$name]); + if ($index !== false) { + unset($this->listeners[$name][$index]); + } + } else { + $this->listeners[$name] = array(); + } + } + } + + /** + * @param string $scope + * @param string $method + * @param array $arguments optional + */ + protected function emit($scope, $method, $arguments = array()) { + $eventName = $scope . '::' . $method; + if (isset($this->listeners[$eventName])) { + foreach ($this->listeners[$eventName] as $callback) { + call_user_func_array($callback, $arguments); + } + } + } +} diff --git a/lib/hooks/emitter.php b/lib/hooks/emitter.php new file mode 100644 index 00000000000..8e9074bad67 --- /dev/null +++ b/lib/hooks/emitter.php @@ -0,0 +1,32 @@ +<?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\Hooks; + +/** + * Class Emitter + * + * interface for all classes that are able to emit events + * + * @package OC\Hooks + */ +interface Emitter { + /** + * @param string $scope + * @param string $method + * @param callable $callback + */ + public function listen($scope, $method, $callback); + + /** + * @param string $scope optional + * @param string $method optional + * @param callable $callback optional + */ + public function removeListener($scope = null, $method = null, $callback = null); +} diff --git a/lib/hooks/legacyemitter.php b/lib/hooks/legacyemitter.php new file mode 100644 index 00000000000..a2d16ace9a7 --- /dev/null +++ b/lib/hooks/legacyemitter.php @@ -0,0 +1,16 @@ +<?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\Hooks; + +abstract class LegacyEmitter extends BasicEmitter { + protected function emit($scope, $method, $arguments = array()) { + \OC_Hook::emit($scope, $method, $arguments); + parent::emit($scope, $method, $arguments); + } +} diff --git a/lib/hooks/publicemitter.php b/lib/hooks/publicemitter.php new file mode 100644 index 00000000000..e2371713ac3 --- /dev/null +++ b/lib/hooks/publicemitter.php @@ -0,0 +1,20 @@ +<?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\Hooks; + +class PublicEmitter extends BasicEmitter { + /** + * @param string $scope + * @param string $method + * @param array $arguments optional + */ + public function emit($scope, $method, $arguments = array()) { + parent::emit($scope, $method, $arguments); + } +} diff --git a/lib/json.php b/lib/json.php index f929e958957..6ba0b13806b 100644 --- a/lib/json.php +++ b/lib/json.php @@ -14,7 +14,7 @@ class OC_JSON{ public static function setContentTypeHeader($type='application/json') { if (!self::$send_content_type_header) { // We send json data - header( 'Content-Type: '.$type ); + header( 'Content-Type: '.$type . '; charset=utf-8'); self::$send_content_type_header = true; } } diff --git a/lib/l10n.php b/lib/l10n.php index 1e07a9b9557..d35ce5fed14 100644 --- a/lib/l10n.php +++ b/lib/l10n.php @@ -122,9 +122,21 @@ class OC_L10N{ ) && file_exists($i18ndir.$lang.'.php')) { // Include the file, save the data from $CONFIG - include strip_tags($i18ndir).strip_tags($lang).'.php'; + $transFile = strip_tags($i18ndir).strip_tags($lang).'.php'; + include $transFile; if(isset($TRANSLATIONS) && is_array($TRANSLATIONS)) { $this->translations = $TRANSLATIONS; + //merge with translations from theme + $theme = OC_Config::getValue( "theme" ); + if (!is_null($theme)) { + $transFile = OC::$SERVERROOT.'/themes/'.$theme.substr($transFile, strlen(OC::$SERVERROOT)); + if (file_exists($transFile)) { + include $transFile; + if (isset($TRANSLATIONS) && is_array($TRANSLATIONS)) { + $this->translations = array_merge($this->translations, $TRANSLATIONS); + } + } + } } } @@ -298,10 +310,16 @@ class OC_L10N{ $temp = explode(';', $i); $temp[0] = str_replace('-', '_', $temp[0]); if( ($key = array_search($temp[0], $available)) !== false) { + if (is_null($app)) { + self::$language = $available[$key]; + } return $available[$key]; } foreach($available as $l) { if ( $temp[0] == substr($l, 0, 2) ) { + if (is_null($app)) { + self::$language = $l; + } return $l; } } diff --git a/lib/l10n/ar.php b/lib/l10n/ar.php index 8b7324f3ff4..22c934e238d 100644 --- a/lib/l10n/ar.php +++ b/lib/l10n/ar.php @@ -1,7 +1,7 @@ <?php $TRANSLATIONS = array( "Help" => "المساعدة", "Personal" => "شخصي", -"Settings" => "تعديلات", +"Settings" => "إعدادات", "Users" => "المستخدمين", "Apps" => "التطبيقات", "Admin" => "المدير", @@ -18,14 +18,12 @@ "Images" => "صور", "Set an admin username." => "اعداد اسم مستخدم للمدير", "Set an admin password." => "اعداد كلمة مرور للمدير", -"Specify a data folder." => "تحديد مجلد ", "%s enter the database username." => "%s ادخل اسم المستخدم الخاص بقاعدة البيانات.", "%s enter the database name." => "%s ادخل اسم فاعدة البيانات", "%s you may not use dots in the database name" => "%s لا يسمح لك باستخدام نقطه (.) في اسم قاعدة البيانات", "%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 username and/or password not valid" => "اسم المستخدم و/أو كلمة المرور لنظام Oracle غير صحيح", "MySQL username and/or password not valid" => "اسم المستخدم و/أو كلمة المرور لنظام MySQL غير صحيح", "DB Error: \"%s\"" => "خطأ في قواعد البيانات : \"%s\"", "Offending command was: \"%s\"" => "الأمر المخالف كان : \"%s\"", @@ -33,6 +31,7 @@ "Drop this user from MySQL" => "احذف اسم المستخدم هذا من الـ MySQL", "MySQL user '%s'@'%%' already exists" => "أسم المستخدم '%s'@'%%' الخاص بـ MySQL موجود مسبقا", "Drop this user from MySQL." => "احذف اسم المستخدم هذا من الـ MySQL.", +"Oracle username and/or password not valid" => "اسم المستخدم و/أو كلمة المرور لنظام Oracle غير صحيح", "Offending command was: \"%s\", name: %s, password: %s" => "الأمر المخالف كان : \"%s\", اسم المستخدم : %s, كلمة المرور: %s", "MS SQL username and/or password not valid: %s" => "اسم المستخدم و/أو كلمة المرور لنظام MS SQL غير صحيح : %s", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "اعدادات خادمك غير صحيحة بشكل تسمح لك بمزامنة ملفاتك وذلك بسبب أن واجهة WebDAV تبدو معطلة", @@ -49,8 +48,5 @@ "%d months ago" => "%d شهر مضت", "last year" => "السنةالماضية", "years ago" => "سنة مضت", -"%s is available. Get <a href=\"%s\">more information</a>" => "%s متاح . احصل على <a href=\"%s\">المزيد من المعلومات </a>", -"up to date" => "محدّث", -"updates check is disabled" => "فحص التحديثات معطّل", "Could not find category \"%s\"" => "تعذر العثور على المجلد \"%s\"" ); diff --git a/lib/l10n/bg_BG.php b/lib/l10n/bg_BG.php index d32e2aadfc5..2de4c0a6e68 100644 --- a/lib/l10n/bg_BG.php +++ b/lib/l10n/bg_BG.php @@ -18,19 +18,18 @@ "Images" => "Снимки", "Set an admin username." => "Въведете потребителско име за администратор.", "Set an admin password." => "Въведете парола за администратор.", -"Specify a data folder." => "Укажете папка за данни", "%s enter the database username." => "%s въведете потребителско име за базата с данни.", "%s enter the database name." => "%s въведете име на базата с данни.", "%s you may not use dots in the database name" => "%s, не можете да ползвате точки в името на базата от данни", "PostgreSQL username and/or password not valid" => "Невалидно PostgreSQL потребителско име и/или парола", "You need to enter either an existing account or the administrator." => "Необходимо е да влезете в всъществуващ акаунт или като администратора", -"Oracle username and/or password not valid" => "Невалидно Oracle потребителско име и/или парола", "MySQL username and/or password not valid" => "Невалидно MySQL потребителско име и/или парола", "DB Error: \"%s\"" => "Грешка в базата от данни: \"%s\"", "MySQL user '%s'@'localhost' exists already." => "MySQL потребителят '%s'@'localhost' вече съществува", "Drop this user from MySQL" => "Изтриване на потребителя от MySQL", "MySQL user '%s'@'%%' already exists" => "MySQL потребителят '%s'@'%%' вече съществува.", "Drop this user from MySQL." => "Изтриване на потребителя от MySQL.", +"Oracle username and/or password not valid" => "Невалидно Oracle потребителско име и/или парола", "MS SQL username and/or password not valid: %s" => "Невалидно MS SQL потребителско име и/или парола: %s", "Please double check the <a href='%s'>installation guides</a>." => "Моля направете повторна справка с <a href='%s'>ръководството за инсталиране</a>.", "seconds ago" => "преди секунди", @@ -45,8 +44,5 @@ "%d months ago" => "преди %d месеца", "last year" => "последната година", "years ago" => "последните години", -"%s is available. Get <a href=\"%s\">more information</a>" => "%s е налична. Получете <a href=\"%s\">повече информация</a>", -"up to date" => "е актуална", -"updates check is disabled" => "проверката за обновления е изключена", "Could not find category \"%s\"" => "Невъзможно откриване на категорията \"%s\"" ); diff --git a/lib/l10n/bn_BD.php b/lib/l10n/bn_BD.php index cb6ff4455a9..f7c8f57466d 100644 --- a/lib/l10n/bn_BD.php +++ b/lib/l10n/bn_BD.php @@ -2,9 +2,9 @@ "Help" => "সহায়িকা", "Personal" => "ব্যক্তিগত", "Settings" => "নিয়ামকসমূহ", -"Users" => "ব্যভহারকারী", +"Users" => "ব্যবহারকারী", "Apps" => "অ্যাপ", -"Admin" => "প্রশাসক", +"Admin" => "প্রশাসন", "ZIP download is turned off." => "ZIP ডাউনলোড বন্ধ করা আছে।", "Files need to be downloaded one by one." => "ফাইলগুলো একে একে ডাউনলোড করা আবশ্যক।", "Back to Files" => "ফাইলে ফিরে চল", @@ -13,6 +13,7 @@ "Authentication error" => "অনুমোদন ঘটিত সমস্যা", "Token expired. Please reload page." => "টোকেন মেয়াদোত্তীর্ণ। দয়া করে পৃষ্ঠাটি পূনরায় লোড করুন।", "Files" => "ফাইল", +"Text" => "টেক্সট", "seconds ago" => "সেকেন্ড পূর্বে", "1 minute ago" => "১ মিনিট পূর্বে", "%d minutes ago" => "%d মিনিট পূর্বে", @@ -22,8 +23,5 @@ "%d days ago" => "%d দিন পূর্বে", "last month" => "গত মাস", "last year" => "গত বছর", -"years ago" => "বছর পূর্বে", -"%s is available. Get <a href=\"%s\">more information</a>" => "%s এখন সুলভ। <a href=\"%s\">আরও জানুন</a>", -"up to date" => "সর্বশেষ", -"updates check is disabled" => "পরিবর্ধন পরীক্ষণ করা বন্ধ রাখা হয়েছে" +"years ago" => "বছর পূর্বে" ); diff --git a/lib/l10n/ca.php b/lib/l10n/ca.php index 108bb5c09be..5c368a85b28 100644 --- a/lib/l10n/ca.php +++ b/lib/l10n/ca.php @@ -18,14 +18,13 @@ "Images" => "Imatges", "Set an admin username." => "Establiu un nom d'usuari per l'administrador.", "Set an admin password." => "Establiu una contrasenya per l'administrador.", -"Specify a data folder." => "Especifiqueu una carpeta de dades.", "%s enter the database username." => "%s escriviu el nom d'usuari de la base de dades.", "%s enter the database name." => "%s escriviu el nom de la base de dades.", "%s you may not use dots in the database name" => "%s no podeu usar punts en el nom de la base de dades", "%s set the database host." => "%s establiu l'ordinador central de la base de dades.", "PostgreSQL username and/or password not valid" => "Nom d'usuari i/o contrasenya PostgreSQL no vàlids", "You need to enter either an existing account or the administrator." => "Heu d'escriure un compte existent o el d'administrador.", -"Oracle username and/or password not valid" => "Nom d'usuari i/o contrasenya Oracle no vàlids", +"Oracle connection could not be established" => "No s'ha pogut establir la connexió Oracle", "MySQL username and/or password not valid" => "Nom d'usuari i/o contrasenya MySQL no vàlids", "DB Error: \"%s\"" => "Error DB: \"%s\"", "Offending command was: \"%s\"" => "L'ordre en conflicte és: \"%s\"", @@ -33,6 +32,7 @@ "Drop this user from MySQL" => "Elimina aquest usuari de MySQL", "MySQL user '%s'@'%%' already exists" => "L'usuari MySQL '%s'@'%%' ja existeix", "Drop this user from MySQL." => "Elimina aquest usuari de MySQL.", +"Oracle username and/or password not valid" => "Nom d'usuari i/o contrasenya Oracle no vàlids", "Offending command was: \"%s\", name: %s, password: %s" => "L'ordre en conflicte és: \"%s\", nom: %s, contrasenya: %s", "MS SQL username and/or password not valid: %s" => "Nom d'usuari i/o contrasenya MS SQL no vàlids: %s", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "El servidor web no està configurat correctament per permetre la sincronització de fitxers perquè la interfície WebDAV sembla no funcionar correctament.", @@ -48,9 +48,6 @@ "last month" => "el mes passat", "%d months ago" => "fa %d mesos", "last year" => "l'any passat", -"years ago" => "fa anys", -"%s is available. Get <a href=\"%s\">more information</a>" => "%s està disponible. Obtén <a href=\"%s\">més informació</a>", -"up to date" => "actualitzat", -"updates check is disabled" => "la comprovació d'actualitzacions està desactivada", +"years ago" => "anys enrere", "Could not find category \"%s\"" => "No s'ha trobat la categoria \"%s\"" ); diff --git a/lib/l10n/cs_CZ.php b/lib/l10n/cs_CZ.php index d9ec3d82cf7..36469507d40 100644 --- a/lib/l10n/cs_CZ.php +++ b/lib/l10n/cs_CZ.php @@ -18,14 +18,12 @@ "Images" => "Obrázky", "Set an admin username." => "Zadejte uživatelské jméno správce.", "Set an admin password." => "Zadejte heslo správce.", -"Specify a data folder." => "Určete složku dat.", "%s enter the database username." => "Zadejte uživatelské jméno %s databáze.", "%s enter the database name." => "Zadejte název databáze pro %s databáze.", "%s you may not use dots in the database name" => "V názvu databáze %s nesmíte používat tečky.", "%s set the database host." => "Zadejte název počítače s databází %s.", "PostgreSQL username and/or password not valid" => "Uživatelské jméno, či heslo PostgreSQL není platné", "You need to enter either an existing account or the administrator." => "Musíte zadat existující účet, či správce.", -"Oracle username and/or password not valid" => "Uživatelské jméno, či heslo Oracle není platné", "MySQL username and/or password not valid" => "Uživatelské jméno, či heslo MySQL není platné", "DB Error: \"%s\"" => "Chyba DB: \"%s\"", "Offending command was: \"%s\"" => "Podezřelý příkaz byl: \"%s\"", @@ -33,12 +31,13 @@ "Drop this user from MySQL" => "Zahodit uživatele z MySQL", "MySQL user '%s'@'%%' already exists" => "Uživatel '%s'@'%%' již v MySQL existuje", "Drop this user from MySQL." => "Zahodit uživatele z MySQL.", +"Oracle username and/or password not valid" => "Uživatelské jméno, či heslo Oracle není platné", "Offending command was: \"%s\", name: %s, password: %s" => "Podezřelý příkaz byl: \"%s\", jméno: %s, heslo: %s", "MS SQL username and/or password not valid: %s" => "Uživatelské jméno, či heslo MSSQL není platné: %s", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Váš webový server není správně nastaven pro umožnění synchronizace, protože rozhraní WebDAV je rozbité.", "Please double check the <a href='%s'>installation guides</a>." => "Zkonzultujte, prosím, <a href='%s'>průvodce instalací</a>.", -"seconds ago" => "před vteřinami", -"1 minute ago" => "před 1 minutou", +"seconds ago" => "před pár vteřinami", +"1 minute ago" => "před minutou", "%d minutes ago" => "před %d minutami", "1 hour ago" => "před hodinou", "%d hours ago" => "před %d hodinami", @@ -47,10 +46,7 @@ "%d days ago" => "před %d dny", "last month" => "minulý měsíc", "%d months ago" => "Před %d měsíci", -"last year" => "loni", +"last year" => "minulý rok", "years ago" => "před lety", -"%s is available. Get <a href=\"%s\">more information</a>" => "%s je dostupná. Získat <a href=\"%s\">více informací</a>", -"up to date" => "aktuální", -"updates check is disabled" => "kontrola aktualizací je vypnuta", "Could not find category \"%s\"" => "Nelze nalézt kategorii \"%s\"" ); diff --git a/lib/l10n/cy_GB.php b/lib/l10n/cy_GB.php new file mode 100644 index 00000000000..b3503dcc572 --- /dev/null +++ b/lib/l10n/cy_GB.php @@ -0,0 +1,52 @@ +<?php $TRANSLATIONS = array( +"Help" => "Cymorth", +"Personal" => "Personol", +"Settings" => "Gosodiadau", +"Users" => "Defnyddwyr", +"Apps" => "Pecynnau", +"Admin" => "Gweinyddu", +"ZIP download is turned off." => "Mae llwytho ZIP wedi ei ddiffodd.", +"Files need to be downloaded one by one." => "Mae angen llwytho ffeiliau i lawr fesul un.", +"Back to Files" => "Nôl i Ffeiliau", +"Selected files too large to generate zip file." => "Mae'r ffeiliau ddewiswyd yn rhy fawr i gynhyrchu ffeil zip.", +"couldn't be determined" => "methwyd pennu", +"Application is not enabled" => "Nid yw'r pecyn wedi'i alluogi", +"Authentication error" => "Gwall dilysu", +"Token expired. Please reload page." => "Tocyn wedi dod i ben. Ail-lwythwch y dudalen.", +"Files" => "Ffeiliau", +"Text" => "Testun", +"Images" => "Delweddau", +"Set an admin username." => "Creu enw defnyddiwr i'r gweinyddwr.", +"Set an admin password." => "Gosod cyfrinair y gweinyddwr.", +"%s enter the database username." => "%s rhowch enw defnyddiwr y gronfa ddata.", +"%s enter the database name." => "%s rhowch enw'r gronfa ddata.", +"%s you may not use dots in the database name" => "%s does dim hawl defnyddio dot yn enw'r gronfa ddata", +"%s set the database host." => "%s gosod gwesteiwr y gronfa ddata.", +"PostgreSQL username and/or password not valid" => "Enw a/neu gyfrinair PostgreSQL annilys", +"You need to enter either an existing account or the administrator." => "Rhaid i chi naill ai gyflwyno cyfrif presennol neu'r gweinyddwr.", +"MySQL username and/or password not valid" => "Enw a/neu gyfrinair MySQL annilys", +"DB Error: \"%s\"" => "Gwall DB: \"%s\"", +"Offending command was: \"%s\"" => "Y gorchymyn wnaeth beri tramgwydd oedd: \"%s\"", +"MySQL user '%s'@'localhost' exists already." => "Defnyddiwr MySQL '%s'@'localhost' yn bodoli eisoes.", +"Drop this user from MySQL" => "Gollwng y defnyddiwr hwn o MySQL", +"MySQL user '%s'@'%%' already exists" => "Defnyddiwr MySQL '%s'@'%%' eisoes yn bodoli", +"Drop this user from MySQL." => "Gollwng y defnyddiwr hwn o MySQL.", +"Oracle username and/or password not valid" => "Enw a/neu gyfrinair Oracle annilys", +"Offending command was: \"%s\", name: %s, password: %s" => "Y gorchymyn wnaeth beri tramgwydd oedd: \"%s\", enw: %s, cyfrinair: %s", +"MS SQL username and/or password not valid: %s" => "Enw a/neu gyfrinair MS SQL annilys: %s", +"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Nid yw eich gweinydd wedi'i gyflunio eto i ganiatáu cydweddu ffeiliau oherwydd bod y rhyngwyneb WebDAV wedi torri.", +"Please double check the <a href='%s'>installation guides</a>." => "Gwiriwch y <a href='%s'>canllawiau gosod</a> eto.", +"seconds ago" => "eiliad yn ôl", +"1 minute ago" => "1 munud yn ôl", +"%d minutes ago" => "%d munud yn ôl", +"1 hour ago" => "1 awr yn ôl", +"%d hours ago" => "%d awr yn ôl", +"today" => "heddiw", +"yesterday" => "ddoe", +"%d days ago" => "%d diwrnod yn ôl", +"last month" => "mis diwethaf", +"%d months ago" => "%d mis yn ôl", +"last year" => "y llynedd", +"years ago" => "blwyddyn yn ôl", +"Could not find category \"%s\"" => "Methu canfod categori \"%s\"" +); diff --git a/lib/l10n/da.php b/lib/l10n/da.php index 38ccbbe8e21..aead17f510e 100644 --- a/lib/l10n/da.php +++ b/lib/l10n/da.php @@ -1,6 +1,6 @@ <?php $TRANSLATIONS = array( "Help" => "Hjælp", -"Personal" => "Personlig", +"Personal" => "Personligt", "Settings" => "Indstillinger", "Users" => "Brugere", "Apps" => "Apps", @@ -18,14 +18,12 @@ "Images" => "Billeder", "Set an admin username." => "Angiv et admin brugernavn.", "Set an admin password." => "Angiv et admin kodeord.", -"Specify a data folder." => "Specificer en data mappe.", "%s enter the database username." => "%s indtast database brugernavnet.", "%s enter the database name." => "%s indtast database navnet.", "%s you may not use dots in the database name" => "%s du må ikke bruge punktummer i databasenavnet.", "%s set the database host." => "%s sæt database værten.", "PostgreSQL username and/or password not valid" => "PostgreSQL brugernavn og/eller kodeord er ikke gyldigt.", "You need to enter either an existing account or the administrator." => "Du bliver nødt til at indtaste en eksisterende bruger eller en administrator.", -"Oracle username and/or password not valid" => "Oracle brugernavn og/eller kodeord er ikke gyldigt.", "MySQL username and/or password not valid" => "MySQL brugernavn og/eller kodeord er ikke gyldigt.", "DB Error: \"%s\"" => "Databasefejl: \"%s\"", "Offending command was: \"%s\"" => "Fejlende kommando var: \"%s\"", @@ -33,6 +31,7 @@ "Drop this user from MySQL" => "Slet denne bruger fra MySQL", "MySQL user '%s'@'%%' already exists" => "MySQL brugeren '%s'@'%%' eksisterer allerede.", "Drop this user from MySQL." => "Slet denne bruger fra MySQL", +"Oracle username and/or password not valid" => "Oracle brugernavn og/eller kodeord er ikke gyldigt.", "Offending command was: \"%s\", name: %s, password: %s" => "Fejlende kommando var: \"%s\", navn: %s, password: %s", "MS SQL username and/or password not valid: %s" => "MS SQL brugernavn og/eller adgangskode ikke er gyldigt: %s", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Din webserver er endnu ikke sat op til at tillade fil synkronisering fordi WebDAV grænsefladen virker ødelagt.", @@ -42,15 +41,12 @@ "%d minutes ago" => "%d minutter siden", "1 hour ago" => "1 time siden", "%d hours ago" => "%d timer siden", -"today" => "I dag", -"yesterday" => "I går", +"today" => "i dag", +"yesterday" => "i går", "%d days ago" => "%d dage siden", -"last month" => "Sidste måned", +"last month" => "sidste måned", "%d months ago" => "%d måneder siden", -"last year" => "Sidste år", +"last year" => "sidste år", "years ago" => "år siden", -"%s is available. Get <a href=\"%s\">more information</a>" => "%s er tilgængelig. Få <a href=\"%s\">mere information</a>", -"up to date" => "opdateret", -"updates check is disabled" => "Check for opdateringer er deaktiveret", "Could not find category \"%s\"" => "Kunne ikke finde kategorien \"%s\"" ); diff --git a/lib/l10n/de.php b/lib/l10n/de.php index 3c2069d4637..74715bc66eb 100644 --- a/lib/l10n/de.php +++ b/lib/l10n/de.php @@ -4,28 +4,26 @@ "Settings" => "Einstellungen", "Users" => "Benutzer", "Apps" => "Apps", -"Admin" => "Administrator", +"Admin" => "Administration", "ZIP download is turned off." => "Der ZIP-Download ist deaktiviert.", "Files need to be downloaded one by one." => "Die Dateien müssen einzeln heruntergeladen werden.", "Back to Files" => "Zurück zu \"Dateien\"", "Selected files too large to generate zip file." => "Die gewählten Dateien sind zu groß, um eine ZIP-Datei zu erstellen.", "couldn't be determined" => "konnte nicht festgestellt werden", "Application is not enabled" => "Die Anwendung ist nicht aktiviert", -"Authentication error" => "Authentifizierungs-Fehler", +"Authentication error" => "Fehler bei der Anmeldung", "Token expired. Please reload page." => "Token abgelaufen. Bitte lade die Seite neu.", "Files" => "Dateien", "Text" => "Text", "Images" => "Bilder", "Set an admin username." => "Setze Administrator Benutzername.", "Set an admin password." => "Setze Administrator Passwort", -"Specify a data folder." => "Datei-Verzeichnis angeben.", "%s enter the database username." => "%s gib den Datenbank-Benutzernamen an.", "%s enter the database name." => "%s gib den Datenbank-Namen an.", "%s you may not use dots in the database name" => "%s Der Datenbank-Name darf keine Punkte enthalten", "%s set the database host." => "%s setze den Datenbank-Host", "PostgreSQL username and/or password not valid" => "PostgreSQL Benutzername und/oder Passwort ungültig", "You need to enter either an existing account or the administrator." => "Du musst entweder ein existierendes Benutzerkonto oder das Administratoren-Konto angeben.", -"Oracle username and/or password not valid" => "Oracle Benutzername und/oder Passwort ungültig", "MySQL username and/or password not valid" => "MySQL Benutzername und/oder Passwort ungültig", "DB Error: \"%s\"" => "DB Fehler: \"%s\"", "Offending command was: \"%s\"" => "Fehlerhafter Befehl war: \"%s\"", @@ -33,12 +31,13 @@ "Drop this user from MySQL" => "Lösche diesen Benutzer von MySQL", "MySQL user '%s'@'%%' already exists" => "MySQL Benutzer '%s'@'%%' existiert bereits", "Drop this user from MySQL." => "Lösche diesen Benutzer aus MySQL.", +"Oracle username and/or password not valid" => "Oracle Benutzername und/oder Passwort ungültig", "Offending command was: \"%s\", name: %s, password: %s" => "Fehlerhafter Befehl war: \"%s\", Name: %s, Passwort: %s", "MS SQL username and/or password not valid: %s" => "MS SQL Benutzername und/oder Password ungültig: %s", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Dein Web-Server ist noch nicht für Datei-Synchronisation bereit, weil die WebDAV-Schnittstelle vermutlich defekt ist.", -"Please double check the <a href='%s'>installation guides</a>." => "Bitte prüfe die <a href='%s'>Instalationsanleitungen</a>.", +"Please double check the <a href='%s'>installation guides</a>." => "Bitte prüfe die <a href='%s'>Installationsanleitungen</a>.", "seconds ago" => "Gerade eben", -"1 minute ago" => "Vor einer Minute", +"1 minute ago" => "vor einer Minute", "%d minutes ago" => "Vor %d Minuten", "1 hour ago" => "Vor einer Stunde", "%d hours ago" => "Vor %d Stunden", @@ -49,8 +48,5 @@ "%d months ago" => "Vor %d Monaten", "last year" => "Letztes Jahr", "years ago" => "Vor Jahren", -"%s is available. Get <a href=\"%s\">more information</a>" => "%s ist verfügbar. <a href=\"%s\">Weitere Informationen</a>", -"up to date" => "aktuell", -"updates check is disabled" => "Die Update-Überprüfung ist ausgeschaltet", "Could not find category \"%s\"" => "Die Kategorie \"%s\" konnte nicht gefunden werden." ); diff --git a/lib/l10n/de_DE.php b/lib/l10n/de_DE.php index 9978cdf8b31..5ebe4fb26fc 100644 --- a/lib/l10n/de_DE.php +++ b/lib/l10n/de_DE.php @@ -18,14 +18,13 @@ "Images" => "Bilder", "Set an admin username." => "Setze Administrator Benutzername.", "Set an admin password." => "Setze Administrator Passwort", -"Specify a data folder." => "Datei-Verzeichnis angeben", "%s enter the database username." => "%s geben Sie den Datenbank-Benutzernamen an.", "%s enter the database name." => "%s geben Sie den Datenbank-Namen an.", "%s you may not use dots in the database name" => "%s Der Datenbank-Name darf keine Punkte enthalten", "%s set the database host." => "%s setze den Datenbank-Host", "PostgreSQL username and/or password not valid" => "PostgreSQL Benutzername und/oder Passwort ungültig", "You need to enter either an existing account or the administrator." => "Sie müssen entweder ein existierendes Benutzerkonto oder das Administratoren-Konto angeben.", -"Oracle username and/or password not valid" => "Oracle Benutzername und/oder Passwort ungültig", +"Oracle connection could not be established" => "Die Oracle-Verbindung konnte nicht aufgebaut werden.", "MySQL username and/or password not valid" => "MySQL Benutzername und/oder Passwort ungültig", "DB Error: \"%s\"" => "DB Fehler: \"%s\"", "Offending command was: \"%s\"" => "Fehlerhafter Befehl war: \"%s\"", @@ -33,12 +32,13 @@ "Drop this user from MySQL" => "Lösche diesen Benutzer aus MySQL", "MySQL user '%s'@'%%' already exists" => "MySQL Benutzer '%s'@'%%' existiert bereits", "Drop this user from MySQL." => "Lösche diesen Benutzer aus MySQL.", +"Oracle username and/or password not valid" => "Oracle Benutzername und/oder Passwort ungültig", "Offending command was: \"%s\", name: %s, password: %s" => "Fehlerhafter Befehl war: \"%s\", Name: %s, Passwort: %s", "MS SQL username and/or password not valid: %s" => "MS SQL Benutzername und/oder Passwort ungültig: %s", -"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Ihr Web-Server ist noch nicht für Datei-Synchronisation bereit, weil die WebDAV-Schnittstelle vermutlich defekt ist.", -"Please double check the <a href='%s'>installation guides</a>." => "Bitte prüfen Sie die <a href='%s'>Instalationsanleitungen</a>.", +"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Ihr Web-Server ist noch nicht für eine Datei-Synchronisation konfiguriert, weil die WebDAV-Schnittstelle vermutlich defekt ist.", +"Please double check the <a href='%s'>installation guides</a>." => "Bitte prüfen Sie die <a href='%s'>Installationsanleitungen</a>.", "seconds ago" => "Gerade eben", -"1 minute ago" => "Vor einer Minute", +"1 minute ago" => "Vor 1 Minute", "%d minutes ago" => "Vor %d Minuten", "1 hour ago" => "Vor einer Stunde", "%d hours ago" => "Vor %d Stunden", @@ -49,8 +49,5 @@ "%d months ago" => "Vor %d Monaten", "last year" => "Letztes Jahr", "years ago" => "Vor Jahren", -"%s is available. Get <a href=\"%s\">more information</a>" => "%s ist verfügbar. <a href=\"%s\">Weitere Informationen</a>", -"up to date" => "aktuell", -"updates check is disabled" => "Die Update-Überprüfung ist ausgeschaltet", "Could not find category \"%s\"" => "Die Kategorie \"%s\" konnte nicht gefunden werden." ); diff --git a/lib/l10n/el.php b/lib/l10n/el.php index a3599095258..8637b8da269 100644 --- a/lib/l10n/el.php +++ b/lib/l10n/el.php @@ -18,14 +18,12 @@ "Images" => "Εικόνες", "Set an admin username." => "Εισάγετε όνομα χρήστη διαχειριστή.", "Set an admin password." => "Εισάγετε συνθηματικό διαχειριστή.", -"Specify a data folder." => "Καθορίστε τον φάκελο δεδομένων.", "%s enter the database username." => "%s εισάγετε το όνομα χρήστη της βάσης δεδομένων.", "%s enter the database name." => "%s εισάγετε το όνομα της βάσης δεδομένων.", "%s you may not use dots in the database name" => "%s μάλλον δεν χρησιμοποιείτε τελείες στο όνομα της βάσης δεδομένων", "%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 username and/or password not valid" => "Μη έγκυρος χρήστης και/ή συνθηματικό της Oracle", "MySQL username and/or password not valid" => "Μη έγκυρος χρήστης και/ή συνθηματικό της MySQL", "DB Error: \"%s\"" => "Σφάλμα Βάσης Δεδομένων: \"%s\"", "Offending command was: \"%s\"" => "Η εντολη παραβατικοτητας ηταν: \"%s\"", @@ -33,6 +31,7 @@ "Drop this user from MySQL" => "Απόρριψη αυτού του χρήστη από την MySQL", "MySQL user '%s'@'%%' already exists" => "Ο χρήστης '%s'@'%%' της MySQL υπάρχει ήδη", "Drop this user from MySQL." => "Απόρριψη αυτού του χρήστη από την MySQL", +"Oracle username and/or password not valid" => "Μη έγκυρος χρήστης και/ή συνθηματικό της Oracle", "Offending command was: \"%s\", name: %s, password: %s" => "Η εντολη παραβατικοτητας ηταν: \"%s\", ονομα: %s, κωδικος: %s", "MS SQL username and/or password not valid: %s" => "Το όνομα χρήστη και/ή ο κωδικός της MS SQL δεν είναι έγκυρα: %s", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Ο διακομιστής σας δεν έχει ρυθμιστεί κατάλληλα ώστε να επιτρέπει τον συγχρονισμό αρχείων γιατί η διεπαφή WebDAV πιθανόν να είναι κατεστραμμένη.", @@ -43,14 +42,11 @@ "1 hour ago" => "1 ώρα πριν", "%d hours ago" => "%d ώρες πριν", "today" => "σήμερα", -"yesterday" => "χθές", +"yesterday" => "χτες", "%d days ago" => "%d ημέρες πριν", -"last month" => "τον προηγούμενο μήνα", +"last month" => "τελευταίο μήνα", "%d months ago" => "%d μήνες πριν", -"last year" => "τον προηγούμενο χρόνο", +"last year" => "τελευταίο χρόνο", "years ago" => "χρόνια πριν", -"%s is available. Get <a href=\"%s\">more information</a>" => "%s είναι διαθέσιμο. Δείτε <a href=\"%s\">περισσότερες πληροφορίες</a>", -"up to date" => "ενημερωμένο", -"updates check is disabled" => "ο έλεγχος ενημερώσεων είναι απενεργοποιημένος", "Could not find category \"%s\"" => "Αδυναμία εύρεσης κατηγορίας \"%s\"" ); diff --git a/lib/l10n/eo.php b/lib/l10n/eo.php index dac11ffe7e6..2782be65da9 100644 --- a/lib/l10n/eo.php +++ b/lib/l10n/eo.php @@ -15,7 +15,7 @@ "Files" => "Dosieroj", "Text" => "Teksto", "Images" => "Bildoj", -"seconds ago" => "sekundojn antaŭe", +"seconds ago" => "sekundoj antaŭe", "1 minute ago" => "antaŭ 1 minuto", "%d minutes ago" => "antaŭ %d minutoj", "1 hour ago" => "antaŭ 1 horo", @@ -23,12 +23,9 @@ "today" => "hodiaŭ", "yesterday" => "hieraŭ", "%d days ago" => "antaŭ %d tagoj", -"last month" => "lasta monato", +"last month" => "lastamonate", "%d months ago" => "antaŭ %d monatoj", -"last year" => "lasta jaro", -"years ago" => "jarojn antaŭe", -"%s is available. Get <a href=\"%s\">more information</a>" => "%s haveblas. Ekhavu <a href=\"%s\">pli da informo</a>", -"up to date" => "ĝisdata", -"updates check is disabled" => "ĝisdateckontrolo estas malkapabligita", +"last year" => "lastajare", +"years ago" => "jaroj antaŭe", "Could not find category \"%s\"" => "Ne troviĝis kategorio “%s”" ); diff --git a/lib/l10n/es.php b/lib/l10n/es.php index 37b15a375c4..3b32036d3af 100644 --- a/lib/l10n/es.php +++ b/lib/l10n/es.php @@ -18,14 +18,13 @@ "Images" => "Imágenes", "Set an admin username." => "Configurar un nombre de usuario del administrador", "Set an admin password." => "Configurar la contraseña del administrador.", -"Specify a data folder." => "Especificar la carpeta de datos.", "%s enter the database username." => "%s ingresar el usuario de la base de datos.", "%s enter the database name." => "%s ingresar el nombre de la base de datos", "%s you may not use dots in the database name" => "%s no se puede utilizar puntos en el nombre de la base de datos", "%s set the database host." => "%s ingresar el host de la base de datos.", "PostgreSQL username and/or password not valid" => "Usuario y/o contraseña de PostgreSQL no válidos", "You need to enter either an existing account or the administrator." => "Tiene que ingresar una cuenta existente o la del administrador.", -"Oracle username and/or password not valid" => "Usuario y/o contraseña de Oracle no válidos", +"Oracle connection could not be established" => "No se pudo establecer la conexión a Oracle", "MySQL username and/or password not valid" => "Usuario y/o contraseña de MySQL no válidos", "DB Error: \"%s\"" => "Error BD: \"%s\"", "Offending command was: \"%s\"" => "Comando infractor: \"%s\"", @@ -33,6 +32,7 @@ "Drop this user from MySQL" => "Eliminar este usuario de MySQL", "MySQL user '%s'@'%%' already exists" => "Usuario MySQL '%s'@'%%' ya existe", "Drop this user from MySQL." => "Eliminar este usuario de MySQL.", +"Oracle username and/or password not valid" => "Usuario y/o contraseña de Oracle no válidos", "Offending command was: \"%s\", name: %s, password: %s" => "Comando infractor: \"%s\", nombre: %s, contraseña: %s", "MS SQL username and/or password not valid: %s" => "Usuario y/o contraseña de MS SQL no válidos: %s", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Su servidor web aún no está configurado adecuadamente para permitir sincronización de archivos ya que la interfaz WebDAV parece no estar funcionando.", @@ -45,12 +45,9 @@ "today" => "hoy", "yesterday" => "ayer", "%d days ago" => "hace %d días", -"last month" => "este mes", +"last month" => "mes pasado", "%d months ago" => "Hace %d meses", -"last year" => "este año", +"last year" => "año pasado", "years ago" => "hace años", -"%s is available. Get <a href=\"%s\">more information</a>" => "%s está disponible. Obtén <a href=\"%s\">más información</a>", -"up to date" => "actualizado", -"updates check is disabled" => "comprobar actualizaciones está desactivado", "Could not find category \"%s\"" => "No puede encontrar la categoria \"%s\"" ); diff --git a/lib/l10n/es_AR.php b/lib/l10n/es_AR.php index ff3d47285fc..1df1b16de65 100644 --- a/lib/l10n/es_AR.php +++ b/lib/l10n/es_AR.php @@ -1,7 +1,7 @@ <?php $TRANSLATIONS = array( "Help" => "Ayuda", "Personal" => "Personal", -"Settings" => "Ajustes", +"Settings" => "Configuración", "Users" => "Usuarios", "Apps" => "Aplicaciones", "Admin" => "Administración", @@ -11,21 +11,19 @@ "Selected files too large to generate zip file." => "Los archivos seleccionados son demasiado grandes para generar el archivo zip.", "couldn't be determined" => "no pudo ser determinado", "Application is not enabled" => "La aplicación no está habilitada", -"Authentication error" => "Error de autenticación", +"Authentication error" => "Error al autenticar", "Token expired. Please reload page." => "Token expirado. Por favor, recargá la página.", "Files" => "Archivos", "Text" => "Texto", "Images" => "Imágenes", "Set an admin username." => "Configurar un nombre de administrador", "Set an admin password." => "Configurar una palabra clave de administrador", -"Specify a data folder." => "Especificar un directorio de datos", "%s enter the database username." => "%s Entre el Usuario de la Base de Datos", "%s enter the database name." => "%s Entre el Nombre de la Base de Datos", "%s you may not use dots in the database name" => "%s no puede usar puntos en el nombre de la Base de Datos", "%s set the database host." => "%s Especifique la dirección de la Base de Datos", "PostgreSQL username and/or password not valid" => "Nombre de usuario o contraseña de PostgradeSQL no válido.", "You need to enter either an existing account or the administrator." => "Debe ingresar una cuenta existente o el administrador", -"Oracle username and/or password not valid" => "El nombre de usuario y contraseña no son válidos", "MySQL username and/or password not valid" => "Usuario y/o contraseña MySQL no válido", "DB Error: \"%s\"" => "Error DB: \"%s\"", "Offending command was: \"%s\"" => "El comando no comprendido es: \"%s\"", @@ -33,11 +31,12 @@ "Drop this user from MySQL" => "Borrar este usuario de MySQL", "MySQL user '%s'@'%%' already exists" => "Usuario MySQL '%s'@'%%' ya existente", "Drop this user from MySQL." => "Borrar este usuario de MySQL", +"Oracle username and/or password not valid" => "El nombre de usuario y contraseña no son válidos", "Offending command was: \"%s\", name: %s, password: %s" => "El comando no comprendido es: \"%s\", nombre: \"%s\", contraseña: \"%s\"", "MS SQL username and/or password not valid: %s" => "Nombre de usuario y contraseña de MS SQL no son válidas: %s", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Tu servidor web no está configurado todavía para permitir sincronización de archivos porque la interfaz WebDAV parece no funcionar.", "Please double check the <a href='%s'>installation guides</a>." => "Por favor, comprobá nuevamente la <a href='%s'>guía de instalación</a>.", -"seconds ago" => "hace unos segundos", +"seconds ago" => "segundos atrás", "1 minute ago" => "hace 1 minuto", "%d minutes ago" => "hace %d minutos", "1 hour ago" => "1 hora atrás", @@ -45,12 +44,9 @@ "today" => "hoy", "yesterday" => "ayer", "%d days ago" => "hace %d días", -"last month" => "este mes", +"last month" => "el mes pasado", "%d months ago" => "%d meses atrás", -"last year" => "este año", -"years ago" => "hace años", -"%s is available. Get <a href=\"%s\">more information</a>" => "%s está disponible. Conseguí <a href=\"%s\">más información</a>", -"up to date" => "actualizado", -"updates check is disabled" => "comprobar actualizaciones está desactivado", +"last year" => "el año pasado", +"years ago" => "años atrás", "Could not find category \"%s\"" => "No fue posible encontrar la categoría \"%s\"" ); diff --git a/lib/l10n/et_EE.php b/lib/l10n/et_EE.php index 6948686b7f6..24fc98bde64 100644 --- a/lib/l10n/et_EE.php +++ b/lib/l10n/et_EE.php @@ -9,7 +9,7 @@ "Files need to be downloaded one by one." => "Failid tuleb alla laadida ükshaaval.", "Back to Files" => "Tagasi failide juurde", "Selected files too large to generate zip file." => "Valitud failid on ZIP-faili loomiseks liiga suured.", -"couldn't be determined" => "Ei suuda tuvastada", +"couldn't be determined" => "ei suudetud tuvastada", "Application is not enabled" => "Rakendus pole sisse lülitatud", "Authentication error" => "Autentimise viga", "Token expired. Please reload page." => "Kontrollkood aegus. Paelun lae leht uuesti.", @@ -18,14 +18,13 @@ "Images" => "Pildid", "Set an admin username." => "Määra admin kasutajanimi.", "Set an admin password." => "Määra admini parool.", -"Specify a data folder." => "Määra andmete kaust.", -"%s enter the database username." => "%s sisesta andmebaasi kasutajatunnus", +"%s enter the database username." => "%s sisesta andmebaasi kasutajatunnus.", "%s enter the database name." => "%s sisesta andmebaasi nimi.", "%s you may not use dots in the database name" => "%s punktide kasutamine andmebaasi nimes pole lubatud", "%s set the database host." => "%s määra andmebaasi server.", "PostgreSQL username and/or password not valid" => "PostgreSQL kasutajatunnus ja/või parool pole õiged", "You need to enter either an existing account or the administrator." => "Sisesta kas juba olemasolev konto või administrator.", -"Oracle username and/or password not valid" => "Oracle kasutajatunnus ja/või parool pole õiged", +"Oracle connection could not be established" => "Ei suuda luua ühendust Oracle baasiga", "MySQL username and/or password not valid" => "MySQL kasutajatunnus ja/või parool pole õiged", "DB Error: \"%s\"" => "Andmebaasi viga: \"%s\"", "Offending command was: \"%s\"" => "Tõrkuv käsk oli: \"%s\"", @@ -33,6 +32,7 @@ "Drop this user from MySQL" => "Kustuta see kasutaja MySQL-ist", "MySQL user '%s'@'%%' already exists" => "MySQL kasutaja '%s'@'%%' on juba olemas", "Drop this user from MySQL." => "Kustuta see kasutaja MySQL-ist.", +"Oracle username and/or password not valid" => "Oracle kasutajatunnus ja/või parool pole õiged", "Offending command was: \"%s\", name: %s, password: %s" => "Tõrkuv käsk oli: \"%s\", nimi: %s, parool: %s", "MS SQL username and/or password not valid: %s" => "MS SQL kasutajatunnus ja/või parool pole õiged: %s", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Veebiserveri ei ole veel korralikult seadistatud võimaldamaks failide sünkroniseerimist, kuna WebDAV liides näib olevat mittetoimiv.", @@ -45,12 +45,9 @@ "today" => "täna", "yesterday" => "eile", "%d days ago" => "%d päeva tagasi", -"last month" => "eelmisel kuul", +"last month" => "viimasel kuul", "%d months ago" => "%d kuud tagasi", -"last year" => "eelmisel aastal", +"last year" => "viimasel aastal", "years ago" => "aastat tagasi", -"%s is available. Get <a href=\"%s\">more information</a>" => "%s on saadaval. Vaata <a href=\"%s\">lisainfot</a>", -"up to date" => "ajakohane", -"updates check is disabled" => "uuenduste kontrollimine on välja lülitatud", "Could not find category \"%s\"" => "Ei leia kategooriat \"%s\"" ); diff --git a/lib/l10n/eu.php b/lib/l10n/eu.php index 36eb397e425..05b68b062c5 100644 --- a/lib/l10n/eu.php +++ b/lib/l10n/eu.php @@ -11,21 +11,19 @@ "Selected files too large to generate zip file." => "Hautatuko fitxategiak oso handiak dira zip fitxategia sortzeko.", "couldn't be determined" => "ezin izan da zehaztu", "Application is not enabled" => "Aplikazioa ez dago gaituta", -"Authentication error" => "Autentikazio errorea", +"Authentication error" => "Autentifikazio errorea", "Token expired. Please reload page." => "Tokena iraungitu da. Mesedez birkargatu orria.", "Files" => "Fitxategiak", "Text" => "Testua", "Images" => "Irudiak", "Set an admin username." => "Ezarri administraziorako erabiltzaile izena.", "Set an admin password." => "Ezarri administraziorako pasahitza.", -"Specify a data folder." => "Zehaztu data karpeta.", "%s enter the database username." => "%s sartu datu basearen erabiltzaile izena.", "%s enter the database name." => "%s sartu datu basearen izena.", "%s you may not use dots in the database name" => "%s ezin duzu punturik erabili datu basearen izenean.", "%s set the database host." => "%s sartu datu basearen hostalaria.", "PostgreSQL username and/or password not valid" => "PostgreSQL erabiltzaile edota pasahitza ez dira egokiak.", "You need to enter either an existing account or the administrator." => "Existitzen den kontu bat edo administradorearena jarri behar duzu.", -"Oracle username and/or password not valid" => "Oracle erabiltzaile edota pasahitza ez dira egokiak.", "MySQL username and/or password not valid" => "MySQL erabiltzaile edota pasahitza ez dira egokiak.", "DB Error: \"%s\"" => "DB errorea: \"%s\"", "Offending command was: \"%s\"" => "Errorea komando honek sortu du: \"%s\"", @@ -33,11 +31,12 @@ "Drop this user from MySQL" => "Ezabatu erabiltzaile hau MySQLtik", "MySQL user '%s'@'%%' already exists" => "MySQL '%s'@'%%' erabiltzailea dagoeneko existitzen da", "Drop this user from MySQL." => "Ezabatu erabiltzaile hau MySQLtik.", +"Oracle username and/or password not valid" => "Oracle erabiltzaile edota pasahitza ez dira egokiak.", "Offending command was: \"%s\", name: %s, password: %s" => "Errorea komando honek sortu du: \"%s\", izena: %s, pasahitza: %s", "MS SQL username and/or password not valid: %s" => "MS SQL erabiltzaile izena edota pasahitza ez dira egokiak: %s", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Zure web zerbitzaria ez dago oraindik ongi konfiguratuta fitxategien sinkronizazioa egiteko, WebDAV interfazea ongi ez dagoela dirudi.", "Please double check the <a href='%s'>installation guides</a>." => "Mesedez begiratu <a href='%s'>instalazio gidak</a>.", -"seconds ago" => "orain dela segundu batzuk", +"seconds ago" => "segundu", "1 minute ago" => "orain dela minutu 1", "%d minutes ago" => "orain dela %d minutu", "1 hour ago" => "orain dela ordu bat", @@ -45,12 +44,9 @@ "today" => "gaur", "yesterday" => "atzo", "%d days ago" => "orain dela %d egun", -"last month" => "joan den hilabetea", +"last month" => "joan den hilabetean", "%d months ago" => "orain dela %d hilabete", -"last year" => "joan den urtea", -"years ago" => "orain dela urte batzuk", -"%s is available. Get <a href=\"%s\">more information</a>" => "%s eskuragarri dago. Lortu <a href=\"%s\">informazio gehiago</a>", -"up to date" => "eguneratuta", -"updates check is disabled" => "eguneraketen egiaztapena ez dago gaituta", +"last year" => "joan den urtean", +"years ago" => "urte", "Could not find category \"%s\"" => "Ezin da \"%s\" kategoria aurkitu" ); diff --git a/lib/l10n/fa.php b/lib/l10n/fa.php index f05195f5b8b..b0d423421df 100644 --- a/lib/l10n/fa.php +++ b/lib/l10n/fa.php @@ -14,7 +14,6 @@ "Files" => "پروندهها", "Text" => "متن", "Images" => "تصاویر", -"Specify a data folder." => "پوشه ای برای داده ها مشخص کنید.", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "احتمالاً وب سرور شما طوری تنظیم نشده است که اجازه ی همگام سازی فایلها را بدهد زیرا به نظر میرسد رابط WebDAV از کار افتاده است.", "Please double check the <a href='%s'>installation guides</a>." => "لطفاً دوباره <a href='%s'>راهنمای نصب</a>را بررسی کنید.", "seconds ago" => "ثانیهها پیش", diff --git a/lib/l10n/fi_FI.php b/lib/l10n/fi_FI.php index 2c85931e1d0..0caa7b12df6 100644 --- a/lib/l10n/fi_FI.php +++ b/lib/l10n/fi_FI.php @@ -11,25 +11,25 @@ "Selected files too large to generate zip file." => "Valitut tiedostot ovat liian suurikokoisia mahtuakseen zip-tiedostoon.", "couldn't be determined" => "ei voitu määrittää", "Application is not enabled" => "Sovellusta ei ole otettu käyttöön", -"Authentication error" => "Todennusvirhe", +"Authentication error" => "Tunnistautumisvirhe", "Token expired. Please reload page." => "Valtuutus vanheni. Lataa sivu uudelleen.", "Files" => "Tiedostot", "Text" => "Teksti", "Images" => "Kuvat", "Set an admin username." => "Aseta ylläpitäjän käyttäjätunnus.", "Set an admin password." => "Aseta ylläpitäjän salasana.", -"Specify a data folder." => "Määritä datakansio.", "%s enter the database username." => "%s anna tietokannan käyttäjätunnus.", "%s enter the database name." => "%s anna tietokannan nimi.", "%s you may not use dots in the database name" => "%s et voi käyttää pisteitä tietokannan nimessä", "PostgreSQL username and/or password not valid" => "PostgreSQL:n käyttäjätunnus ja/tai salasana on väärin", -"Oracle username and/or password not valid" => "Oraclen käyttäjätunnus ja/tai salasana on väärin", +"Oracle connection could not be established" => "Oracle-yhteyttä ei voitu muodostaa", "MySQL username and/or password not valid" => "MySQL:n käyttäjätunnus ja/tai salasana on väärin", "DB Error: \"%s\"" => "Tietokantavirhe: \"%s\"", "MySQL user '%s'@'localhost' exists already." => "MySQL-käyttäjä '%s'@'localhost' on jo olemassa.", "Drop this user from MySQL" => "Pudota tämä käyttäjä MySQL:stä", "MySQL user '%s'@'%%' already exists" => "MySQL-käyttäjä '%s'@'%%' on jo olemassa", "Drop this user from MySQL." => "Pudota tämä käyttäjä MySQL:stä.", +"Oracle username and/or password not valid" => "Oraclen käyttäjätunnus ja/tai salasana on väärin", "MS SQL username and/or password not valid: %s" => "MS SQL -käyttäjätunnus ja/tai -salasana on väärin: %s", "Please double check the <a href='%s'>installation guides</a>." => "Lue tarkasti <a href='%s'>asennusohjeet</a>.", "seconds ago" => "sekuntia sitten", @@ -44,8 +44,5 @@ "%d months ago" => "%d kuukautta sitten", "last year" => "viime vuonna", "years ago" => "vuotta sitten", -"%s is available. Get <a href=\"%s\">more information</a>" => "%s on saatavilla. Lue <a href=\"%s\">lisätietoja</a>", -"up to date" => "ajan tasalla", -"updates check is disabled" => "päivitysten tarkistus on pois käytöstä", "Could not find category \"%s\"" => "Luokkaa \"%s\" ei löytynyt" ); diff --git a/lib/l10n/fr.php b/lib/l10n/fr.php index 9448502df6a..aed5d056f37 100644 --- a/lib/l10n/fr.php +++ b/lib/l10n/fr.php @@ -18,14 +18,13 @@ "Images" => "Images", "Set an admin username." => "Spécifiez un nom d'utilisateur pour l'administrateur.", "Set an admin password." => "Spécifiez un mot de passe administrateur.", -"Specify a data folder." => "Spécifiez un répertoire pour les données.", "%s enter the database username." => "%s entrez le nom d'utilisateur de la base de données.", "%s enter the database name." => "%s entrez le nom de la base de données.", "%s you may not use dots in the database name" => "%s vous nez pouvez pas utiliser de points dans le nom de la base de données", "%s set the database host." => "%s spécifiez l'hôte de la base de données.", "PostgreSQL username and/or password not valid" => "Nom d'utilisateur et/ou mot de passe de la base PostgreSQL invalide", "You need to enter either an existing account or the administrator." => "Vous devez spécifier soit le nom d'un compte existant, soit celui de l'administrateur.", -"Oracle username and/or password not valid" => "Nom d'utilisateur et/ou mot de passe de la base Oracle invalide", +"Oracle connection could not be established" => "La connexion Oracle ne peut pas être établie", "MySQL username and/or password not valid" => "Nom d'utilisateur et/ou mot de passe de la base MySQL invalide", "DB Error: \"%s\"" => "Erreur de la base de données : \"%s\"", "Offending command was: \"%s\"" => "La requête en cause est : \"%s\"", @@ -33,12 +32,13 @@ "Drop this user from MySQL" => "Retirer cet utilisateur de la base MySQL", "MySQL user '%s'@'%%' already exists" => "L'utilisateur MySQL '%s'@'%%' existe déjà", "Drop this user from MySQL." => "Retirer cet utilisateur de la base MySQL.", +"Oracle username and/or password not valid" => "Nom d'utilisateur et/ou mot de passe de la base Oracle invalide", "Offending command was: \"%s\", name: %s, password: %s" => "La requête en cause est : \"%s\", nom : %s, mot de passe : %s", "MS SQL username and/or password not valid: %s" => "Le nom d'utilisateur et/ou le mot de passe de la base MS SQL est invalide : %s", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Votre serveur web, n'est pas correctement configuré pour permettre la synchronisation des fichiers, car l'interface WebDav ne fonctionne pas comme il faut.", "Please double check the <a href='%s'>installation guides</a>." => "Veuillez vous référer au <a href='%s'>guide d'installation</a>.", -"seconds ago" => "à l'instant", -"1 minute ago" => "il y a 1 minute", +"seconds ago" => "il y a quelques secondes", +"1 minute ago" => "il y a une minute", "%d minutes ago" => "il y a %d minutes", "1 hour ago" => "Il y a une heure", "%d hours ago" => "Il y a %d heures", @@ -49,8 +49,5 @@ "%d months ago" => "Il y a %d mois", "last year" => "l'année dernière", "years ago" => "il y a plusieurs années", -"%s is available. Get <a href=\"%s\">more information</a>" => "%s est disponible. Obtenez <a href=\"%s\">plus d'informations</a>", -"up to date" => "À jour", -"updates check is disabled" => "la vérification des mises à jour est désactivée", "Could not find category \"%s\"" => "Impossible de trouver la catégorie \"%s\"" ); diff --git a/lib/l10n/gl.php b/lib/l10n/gl.php index a11724fef43..1b4db4b30af 100644 --- a/lib/l10n/gl.php +++ b/lib/l10n/gl.php @@ -1,7 +1,7 @@ <?php $TRANSLATIONS = array( "Help" => "Axuda", "Personal" => "Persoal", -"Settings" => "Configuracións", +"Settings" => "Axustes", "Users" => "Usuarios", "Apps" => "Aplicativos", "Admin" => "Administración", @@ -11,21 +11,20 @@ "Selected files too large to generate zip file." => "Os ficheiros seleccionados son demasiado grandes como para xerar un ficheiro zip.", "couldn't be determined" => "non foi posíbel determinalo", "Application is not enabled" => "O aplicativo non está activado", -"Authentication error" => "Produciuse un erro na autenticación", +"Authentication error" => "Produciuse un erro de autenticación", "Token expired. Please reload page." => "Testemuña caducada. Recargue a páxina.", "Files" => "Ficheiros", "Text" => "Texto", "Images" => "Imaxes", "Set an admin username." => "Estabeleza un nome de usuario administrador", "Set an admin password." => "Estabeleza un contrasinal de administrador", -"Specify a data folder." => "Especifique un cartafol de datos.", "%s enter the database username." => "%s introduza o nome de usuario da base de datos", "%s enter the database name." => "%s introduza o nome da base de datos", "%s you may not use dots in the database name" => "%s non se poden empregar puntos na base de datos", "%s set the database host." => "%s estabeleza o servidor da base de datos", "PostgreSQL username and/or password not valid" => "Nome de usuario e/ou contrasinal de PostgreSQL incorrecto", "You need to enter either an existing account or the administrator." => "Deberá introducir unha conta existente ou o administrador.", -"Oracle username and/or password not valid" => "Nome de usuario e/ou contrasinal de Oracle incorrecto", +"Oracle connection could not be established" => "Non foi posíbel estabelecer a conexión con Oracle", "MySQL username and/or password not valid" => "Nome de usuario e/ou contrasinal de MySQL incorrecto", "DB Error: \"%s\"" => "Produciuse un erro na base de datos: «%s»", "Offending command was: \"%s\"" => "A orde ofensiva foi: «%s»", @@ -33,6 +32,7 @@ "Drop this user from MySQL" => "Omitir este usuario de MySQL", "MySQL user '%s'@'%%' already exists" => "O usuario MySQL «%s»@«%%» xa existe.", "Drop this user from MySQL." => "Omitir este usuario de MySQL.", +"Oracle username and/or password not valid" => "Nome de usuario e/ou contrasinal de Oracle incorrecto", "Offending command was: \"%s\", name: %s, password: %s" => "A orde ofensiva foi: «%s», nome: %s, contrasinal: %s", "MS SQL username and/or password not valid: %s" => "Nome de usuario e/ou contrasinal de MS SQL incorrecto: %s", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "O seu servidor web non está aínda configurado adecuadamente para permitir a sincronización de ficheiros xa que semella que a interface WebDAV non está a funcionar.", @@ -49,8 +49,5 @@ "%d months ago" => "Vai %d meses", "last year" => "último ano", "years ago" => "anos atrás", -"%s is available. Get <a href=\"%s\">more information</a>" => "%s está dispoñíbel. Obtéña <a href=\"%s\">máis información</a>", -"up to date" => "actualizado", -"updates check is disabled" => "a comprobación de actualizacións está desactivada", "Could not find category \"%s\"" => "Non foi posíbel atopar a categoría «%s»" ); diff --git a/lib/l10n/he.php b/lib/l10n/he.php index 078a731afc0..dcd0545adba 100644 --- a/lib/l10n/he.php +++ b/lib/l10n/he.php @@ -27,8 +27,5 @@ "%d months ago" => "לפני %d חודשים", "last year" => "שנה שעברה", "years ago" => "שנים", -"%s is available. Get <a href=\"%s\">more information</a>" => "%s זמין. קבלת <a href=\"%s\">מידע נוסף</a>", -"up to date" => "עדכני", -"updates check is disabled" => "בדיקת עדכונים מנוטרלת", "Could not find category \"%s\"" => "לא ניתן למצוא את הקטגוריה „%s“" ); diff --git a/lib/l10n/hr.php b/lib/l10n/hr.php index 8b0dd6de0a1..3ce75c99f0e 100644 --- a/lib/l10n/hr.php +++ b/lib/l10n/hr.php @@ -3,6 +3,7 @@ "Personal" => "Osobno", "Settings" => "Postavke", "Users" => "Korisnici", +"Apps" => "Aplikacije", "Admin" => "Administrator", "Authentication error" => "Greška kod autorizacije", "Files" => "Datoteke", diff --git a/lib/l10n/hu_HU.php b/lib/l10n/hu_HU.php index 537066c6fea..3b5c886bd2c 100644 --- a/lib/l10n/hu_HU.php +++ b/lib/l10n/hu_HU.php @@ -11,21 +11,20 @@ "Selected files too large to generate zip file." => "A kiválasztott fájlok túl nagyok a zip tömörítéshez.", "couldn't be determined" => "nem határozható meg", "Application is not enabled" => "Az alkalmazás nincs engedélyezve", -"Authentication error" => "Hitelesítési hiba", +"Authentication error" => "Azonosítási hiba", "Token expired. Please reload page." => "A token lejárt. Frissítse az oldalt.", "Files" => "Fájlok", "Text" => "Szöveg", "Images" => "Képek", "Set an admin username." => "Állítson be egy felhasználói nevet az adminisztrációhoz.", "Set an admin password." => "Állítson be egy jelszót az adminisztrációhoz.", -"Specify a data folder." => "Adja meg az adatokat tartalmazó könyvtár nevét.", "%s enter the database username." => "%s adja meg az adatbázist elérő felhasználó login nevét.", "%s enter the database name." => "%s adja meg az adatbázis nevét.", "%s you may not use dots in the database name" => "%s az adatbázis neve nem tartalmazhat pontot", "%s set the database host." => "%s adja meg az adatbázist szolgáltató számítógép nevét.", "PostgreSQL username and/or password not valid" => "A PostgreSQL felhasználói név és/vagy jelszó érvénytelen", "You need to enter either an existing account or the administrator." => "Vagy egy létező felhasználó vagy az adminisztrátor bejelentkezési nevét kell megadnia", -"Oracle username and/or password not valid" => "Az Oracle felhasználói név és/vagy jelszó érvénytelen", +"Oracle connection could not be established" => "Az Oracle kapcsolat nem hozható létre", "MySQL username and/or password not valid" => "A MySQL felhasználói név és/vagy jelszó érvénytelen", "DB Error: \"%s\"" => "Adatbázis hiba: \"%s\"", "Offending command was: \"%s\"" => "A hibát ez a parancs okozta: \"%s\"", @@ -33,11 +32,12 @@ "Drop this user from MySQL" => "Törölje ezt a felhasználót a MySQL-ből", "MySQL user '%s'@'%%' already exists" => "A '%s'@'%%' MySQL felhasználó már létezik", "Drop this user from MySQL." => "Törölje ezt a felhasználót a MySQL-ből.", +"Oracle username and/or password not valid" => "Az Oracle felhasználói név és/vagy jelszó érvénytelen", "Offending command was: \"%s\", name: %s, password: %s" => "A hibát okozó parancs ez volt: \"%s\", login név: %s, jelszó: %s", "MS SQL username and/or password not valid: %s" => "Az MS SQL felhasználónév és/vagy jelszó érvénytelen: %s", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Az Ön webkiszolgálója nincs megfelelően beállítva az állományok szinkronizálásához, mert a WebDAV-elérés úgy tűnik, nem működik.", "Please double check the <a href='%s'>installation guides</a>." => "Kérjük tüzetesen tanulmányozza át a <a href='%s'>telepítési útmutatót</a>.", -"seconds ago" => "másodperce", +"seconds ago" => "pár másodperce", "1 minute ago" => "1 perce", "%d minutes ago" => "%d perce", "1 hour ago" => "1 órája", @@ -48,9 +48,6 @@ "last month" => "múlt hónapban", "%d months ago" => "%d hónapja", "last year" => "tavaly", -"years ago" => "éve", -"%s is available. Get <a href=\"%s\">more information</a>" => "%s elérhető. <a href=\"%s\">További információ</a>.", -"up to date" => "a legfrissebb változat", -"updates check is disabled" => "A frissitések ellenőrzése nincs engedélyezve.", +"years ago" => "több éve", "Could not find category \"%s\"" => "Ez a kategória nem található: \"%s\"" ); diff --git a/lib/l10n/ia.php b/lib/l10n/ia.php index e790c41d072..573281553fc 100644 --- a/lib/l10n/ia.php +++ b/lib/l10n/ia.php @@ -3,6 +3,7 @@ "Personal" => "Personal", "Settings" => "Configurationes", "Users" => "Usatores", +"Apps" => "Applicationes", "Admin" => "Administration", "Files" => "Files", "Text" => "Texto" diff --git a/lib/l10n/id.php b/lib/l10n/id.php index b34fa0ac59d..29843a95327 100644 --- a/lib/l10n/id.php +++ b/lib/l10n/id.php @@ -18,14 +18,12 @@ "Images" => "Gambar", "Set an admin username." => "Setel nama pengguna admin.", "Set an admin password." => "Setel sandi admin.", -"Specify a data folder." => "Tentukan folder data.", "%s enter the database username." => "%s masukkan nama pengguna basis data.", "%s enter the database name." => "%s masukkan nama basis data.", "%s you may not use dots in the database name" => "%sAnda tidak boleh menggunakan karakter titik pada nama basis data", "%s set the database host." => "%s setel host basis data.", "PostgreSQL username and/or password not valid" => "Nama pengguna dan/atau sandi PostgreSQL tidak valid", "You need to enter either an existing account or the administrator." => "Anda harus memasukkan akun yang sudah ada atau administrator.", -"Oracle username and/or password not valid" => "Nama pengguna dan/atau sandi Oracle tidak valid", "MySQL username and/or password not valid" => "Nama pengguna dan/atau sandi MySQL tidak valid", "DB Error: \"%s\"" => "Galat Basis Data: \"%s\"", "Offending command was: \"%s\"" => "Perintah yang bermasalah: \"%s\"", @@ -33,6 +31,7 @@ "Drop this user from MySQL" => "Hapus pengguna ini dari MySQL", "MySQL user '%s'@'%%' already exists" => "Pengguna MySQL '%s'@'%%' sudah ada.", "Drop this user from MySQL." => "Hapus pengguna ini dari MySQL.", +"Oracle username and/or password not valid" => "Nama pengguna dan/atau sandi Oracle tidak valid", "Offending command was: \"%s\", name: %s, password: %s" => "Perintah yang bermasalah: \"%s\", nama pengguna: %s, sandi: %s", "MS SQL username and/or password not valid: %s" => "Nama pengguna dan/atau sandi MySQL tidak valid: %s", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Web server Anda belum dikonfigurasikan dengan baik untuk mengizinkan sinkronisasi berkas karena tampaknya antarmuka WebDAV rusak.", @@ -49,8 +48,5 @@ "%d months ago" => "%d bulan yang lalu", "last year" => "tahun kemarin", "years ago" => "beberapa tahun lalu", -"%s is available. Get <a href=\"%s\">more information</a>" => "%s tersedia. Dapatkan <a href=\"%s\">info lebih lanjut</a>", -"up to date" => "terbaru", -"updates check is disabled" => "Pemeriksaan pembaruan dinonaktifkan.", "Could not find category \"%s\"" => "Tidak dapat menemukan kategori \"%s\"" ); diff --git a/lib/l10n/is.php b/lib/l10n/is.php index 8fdb45a05cd..05bb6883953 100644 --- a/lib/l10n/is.php +++ b/lib/l10n/is.php @@ -27,8 +27,5 @@ "%d months ago" => "fyrir %d mánuðum", "last year" => "síðasta ári", "years ago" => "einhverjum árum", -"%s is available. Get <a href=\"%s\">more information</a>" => "%s er í boði. Sækja <a href=\"%s\">meiri upplýsingar</a>", -"up to date" => "nýjasta útgáfa", -"updates check is disabled" => "uppfærslupróf er ekki virkjað", "Could not find category \"%s\"" => "Fann ekki flokkinn \"%s\"" ); diff --git a/lib/l10n/it.php b/lib/l10n/it.php index 297f1efde05..db26ac82ae3 100644 --- a/lib/l10n/it.php +++ b/lib/l10n/it.php @@ -18,14 +18,13 @@ "Images" => "Immagini", "Set an admin username." => "Imposta un nome utente di amministrazione.", "Set an admin password." => "Imposta una password di amministrazione.", -"Specify a data folder." => "Specifica una cartella dei dati.", "%s enter the database username." => "%s digita il nome utente del database.", "%s enter the database name." => "%s digita il nome del database.", "%s you may not use dots in the database name" => "%s non dovresti utilizzare punti nel nome del database", "%s set the database host." => "%s imposta l'host del database.", "PostgreSQL username and/or password not valid" => "Nome utente e/o password di PostgreSQL non validi", "You need to enter either an existing account or the administrator." => "È necessario inserire un account esistente o l'amministratore.", -"Oracle username and/or password not valid" => "Nome utente e/o password di Oracle non validi", +"Oracle connection could not be established" => "La connessione a Oracle non può essere stabilita", "MySQL username and/or password not valid" => "Nome utente e/o password di MySQL non validi", "DB Error: \"%s\"" => "Errore DB: \"%s\"", "Offending command was: \"%s\"" => "Il comando non consentito era: \"%s\"", @@ -33,24 +32,22 @@ "Drop this user from MySQL" => "Elimina questo utente da MySQL", "MySQL user '%s'@'%%' already exists" => "L'utente MySQL '%s'@'%%' esiste già", "Drop this user from MySQL." => "Elimina questo utente da MySQL.", +"Oracle username and/or password not valid" => "Nome utente e/o password di Oracle non validi", "Offending command was: \"%s\", name: %s, password: %s" => "Il comando non consentito era: \"%s\", nome: %s, password: %s", "MS SQL username and/or password not valid: %s" => "Nome utente e/o password MS SQL non validi: %s", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Il tuo server web non è configurato correttamente per consentire la sincronizzazione dei file poiché l'interfaccia WebDAV sembra essere danneggiata.", "Please double check the <a href='%s'>installation guides</a>." => "Leggi attentamente le <a href='%s'>guide d'installazione</a>.", "seconds ago" => "secondi fa", -"1 minute ago" => "1 minuto fa", +"1 minute ago" => "Un minuto fa", "%d minutes ago" => "%d minuti fa", "1 hour ago" => "1 ora fa", "%d hours ago" => "%d ore fa", "today" => "oggi", "yesterday" => "ieri", "%d days ago" => "%d giorni fa", -"last month" => "il mese scorso", +"last month" => "mese scorso", "%d months ago" => "%d mesi fa", -"last year" => "l'anno scorso", +"last year" => "anno scorso", "years ago" => "anni fa", -"%s is available. Get <a href=\"%s\">more information</a>" => "%s è disponibile. Ottieni <a href=\"%s\">ulteriori informazioni</a>", -"up to date" => "aggiornato", -"updates check is disabled" => "il controllo degli aggiornamenti è disabilitato", "Could not find category \"%s\"" => "Impossibile trovare la categoria \"%s\"" ); diff --git a/lib/l10n/ja_JP.php b/lib/l10n/ja_JP.php index 529eec3ac52..a2eb4bee67b 100644 --- a/lib/l10n/ja_JP.php +++ b/lib/l10n/ja_JP.php @@ -1,10 +1,10 @@ <?php $TRANSLATIONS = array( "Help" => "ヘルプ", -"Personal" => "個人設定", +"Personal" => "個人", "Settings" => "設定", "Users" => "ユーザ", "Apps" => "アプリ", -"Admin" => "管理者", +"Admin" => "管理", "ZIP download is turned off." => "ZIPダウンロードは無効です。", "Files need to be downloaded one by one." => "ファイルは1つずつダウンロードする必要があります。", "Back to Files" => "ファイルに戻る", @@ -18,14 +18,13 @@ "Images" => "画像", "Set an admin username." => "管理者のユーザ名を設定。", "Set an admin password." => "管理者のパスワードを設定。", -"Specify a data folder." => "データフォルダを指定。", "%s enter the database username." => "%s のデータベースのユーザ名を入力してください。", "%s enter the database name." => "%s のデータベース名を入力してください。", "%s you may not use dots in the database name" => "%s ではデータベース名にドットを利用できないかもしれません。", "%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 username and/or password not valid" => "Oracleのユーザ名もしくはパスワードは有効ではありません", +"Oracle connection could not be established" => "Oracleへの接続が確立できませんでした。", "MySQL username and/or password not valid" => "MySQLのユーザ名もしくはパスワードは有効ではありません", "DB Error: \"%s\"" => "DBエラー: \"%s\"", "Offending command was: \"%s\"" => "違反コマンド: \"%s\"", @@ -33,24 +32,22 @@ "Drop this user from MySQL" => "MySQLからこのユーザを削除", "MySQL user '%s'@'%%' already exists" => "MySQLのユーザ '%s'@'%%' はすでに存在します。", "Drop this user from MySQL." => "MySQLからこのユーザを削除する。", +"Oracle username and/or password not valid" => "Oracleのユーザ名もしくはパスワードは有効ではありません", "Offending command was: \"%s\", name: %s, password: %s" => "違反コマンド: \"%s\"、名前: %s、パスワード: %s", "MS SQL username and/or password not valid: %s" => "MS SQL サーバーのユーザー名/パスワードが正しくありません: %s", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "WebDAVインタフェースが動作していないと考えられるため、あなたのWEBサーバはまだファイルの同期を許可するように適切な設定がされていません。", "Please double check the <a href='%s'>installation guides</a>." => "<a href='%s'>インストールガイド</a>をよく確認してください。", -"seconds ago" => "秒前", -"1 minute ago" => "1分前", +"seconds ago" => "数秒前", +"1 minute ago" => "1 分前", "%d minutes ago" => "%d 分前", "1 hour ago" => "1 時間前", "%d hours ago" => "%d 時間前", "today" => "今日", "yesterday" => "昨日", "%d days ago" => "%d 日前", -"last month" => "先月", +"last month" => "一月前", "%d months ago" => "%d 分前", -"last year" => "昨年", +"last year" => "一年前", "years ago" => "年前", -"%s is available. Get <a href=\"%s\">more information</a>" => "%s が利用可能です。<a href=\"%s\">詳細情報</a> を確認ください", -"up to date" => "最新です", -"updates check is disabled" => "更新チェックは無効です", "Could not find category \"%s\"" => "カテゴリ \"%s\" が見つかりませんでした" ); diff --git a/lib/l10n/ka_GE.php b/lib/l10n/ka_GE.php index 26b356b6341..93835e4ead7 100644 --- a/lib/l10n/ka_GE.php +++ b/lib/l10n/ka_GE.php @@ -18,14 +18,12 @@ "Images" => "სურათები", "Set an admin username." => "დააყენეთ ადმინისტრატორის სახელი.", "Set an admin password." => "დააყენეთ ადმინისტრატორის პაროლი.", -"Specify a data folder." => "მიუთითეთ data ფოლდერი.", "%s enter the database username." => "%s შეიყვანეთ ბაზის იუზერნეიმი.", "%s enter the database name." => "%s შეიყვანეთ ბაზის სახელი.", "%s you may not use dots in the database name" => "%s არ მიუთითოთ წერტილი ბაზის სახელში", "%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 username and/or password not valid" => "Oracle იუზერნეიმი და/ან პაროლი არ არის სწორი", "MySQL username and/or password not valid" => "MySQL იუზერნეიმი და/ან პაროლი არ არის სწორი", "DB Error: \"%s\"" => "DB შეცდომა: \"%s\"", "Offending command was: \"%s\"" => "Offending ბრძანება იყო: \"%s\"", @@ -33,6 +31,7 @@ "Drop this user from MySQL" => "წაშალე ეს მომხამრებელი MySQL–იდან", "MySQL user '%s'@'%%' already exists" => "MySQL მომხმარებელი '%s'@'%%' უკვე არსებობს", "Drop this user from MySQL." => "წაშალე ეს მომხამრებელი MySQL–იდან", +"Oracle username and/or password not valid" => "Oracle იუზერნეიმი და/ან პაროლი არ არის სწორი", "Offending command was: \"%s\", name: %s, password: %s" => "Offending ბრძანება იყო: \"%s\", სახელი: %s, პაროლი: %s", "MS SQL username and/or password not valid: %s" => "MS SQL მომხმარებელი და/ან პაროლი არ არის მართებული: %s", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "თქვენი web სერვერი არ არის კონფიგურირებული ფაილ სინქრონიზაციისთვის, რადგან WebDAV ინტერფეისი შეიძლება იყოს გატეხილი.", @@ -49,8 +48,5 @@ "%d months ago" => "%d თვის წინ", "last year" => "ბოლო წელს", "years ago" => "წლის წინ", -"%s is available. Get <a href=\"%s\">more information</a>" => "%s ხელმისაწვდომია. მიიღეთ <a href=\"%s\">უფრო მეტი ინფორმაცია</a>", -"up to date" => "განახლებულია", -"updates check is disabled" => "განახლების ძებნა გათიშულია", "Could not find category \"%s\"" => "\"%s\" კატეგორიის მოძებნა ვერ მოხერხდა" ); diff --git a/lib/l10n/ko.php b/lib/l10n/ko.php index 859657f46b4..bf2a68369f1 100644 --- a/lib/l10n/ko.php +++ b/lib/l10n/ko.php @@ -28,8 +28,5 @@ "%d months ago" => "%d개월 전", "last year" => "작년", "years ago" => "년 전", -"%s is available. Get <a href=\"%s\">more information</a>" => "%s을(를) 사용할 수 있습니다. <a href=\"%s\">자세한 정보 보기</a>", -"up to date" => "최신", -"updates check is disabled" => "업데이트 확인이 비활성화됨", "Could not find category \"%s\"" => "분류 \"%s\"을(를) 찾을 수 없습니다." ); diff --git a/lib/l10n/ku_IQ.php b/lib/l10n/ku_IQ.php index f3165b8586b..20d0249f569 100644 --- a/lib/l10n/ku_IQ.php +++ b/lib/l10n/ku_IQ.php @@ -2,5 +2,6 @@ "Help" => "یارمەتی", "Settings" => "دهستكاری", "Users" => "بهكارهێنهر", +"Apps" => "بهرنامهكان", "Admin" => "بهڕێوهبهری سهرهكی" ); diff --git a/lib/l10n/lb.php b/lib/l10n/lb.php index 16f1f674e95..889fc3a377d 100644 --- a/lib/l10n/lb.php +++ b/lib/l10n/lb.php @@ -2,6 +2,8 @@ "Help" => "Hëllef", "Personal" => "Perséinlech", "Settings" => "Astellungen", +"Users" => "Benotzer", +"Apps" => "Applicatiounen", "Admin" => "Admin", "Authentication error" => "Authentifikatioun's Fehler", "Files" => "Dateien", diff --git a/lib/l10n/lt_LT.php b/lib/l10n/lt_LT.php index b84c155633b..cebaa6937d8 100644 --- a/lib/l10n/lt_LT.php +++ b/lib/l10n/lt_LT.php @@ -14,16 +14,13 @@ "Token expired. Please reload page." => "Sesija baigėsi. Prašome perkrauti puslapį.", "Files" => "Failai", "Text" => "Žinučių", -"seconds ago" => "prieš kelias sekundes", -"1 minute ago" => "prieš 1 minutę", +"seconds ago" => "prieš sekundę", +"1 minute ago" => "Prieš 1 minutę", "%d minutes ago" => "prieš %d minučių", "today" => "šiandien", "yesterday" => "vakar", "%d days ago" => "prieš %d dienų", -"last month" => "praėjusį mėnesį", -"last year" => "pereitais metais", -"years ago" => "prieš metus", -"%s is available. Get <a href=\"%s\">more information</a>" => "%s yra galimas. Platesnė <a href=\"%s\">informacija čia</a>", -"up to date" => "pilnai atnaujinta", -"updates check is disabled" => "atnaujinimų tikrinimas išjungtas" +"last month" => "praeitą mėnesį", +"last year" => "praeitais metais", +"years ago" => "prieš metus" ); diff --git a/lib/l10n/lv.php b/lib/l10n/lv.php index c73d306ca0a..140c75af3ce 100644 --- a/lib/l10n/lv.php +++ b/lib/l10n/lv.php @@ -18,14 +18,12 @@ "Images" => "Attēli", "Set an admin username." => "Iestatiet administratora lietotājvārdu.", "Set an admin password." => "Iestatiet administratora paroli.", -"Specify a data folder." => "Norādiet datu mapi.", "%s enter the database username." => "%s ievadiet datubāzes lietotājvārdu.", "%s enter the database name." => "%s ievadiet datubāzes nosaukumu.", "%s you may not use dots in the database name" => "%s datubāžu nosaukumos nedrīkst izmantot punktus", "%s set the database host." => "%s iestatiet datubāžu serveri.", "PostgreSQL username and/or password not valid" => "Nav derīga PostgreSQL parole un/vai lietotājvārds", "You need to enter either an existing account or the administrator." => "Jums jāievada vai nu esošs vai administratora konts.", -"Oracle username and/or password not valid" => "Nav derīga Oracle parole un/vai lietotājvārds", "MySQL username and/or password not valid" => "Nav derīga MySQL parole un/vai lietotājvārds", "DB Error: \"%s\"" => "DB kļūda — “%s”", "Offending command was: \"%s\"" => "Vainīgā komanda bija “%s”", @@ -33,6 +31,7 @@ "Drop this user from MySQL" => "Izmest šo lietotāju no MySQL", "MySQL user '%s'@'%%' already exists" => "MySQL lietotājs '%s'@'%%' jau eksistē", "Drop this user from MySQL." => "Izmest šo lietotāju no MySQL.", +"Oracle username and/or password not valid" => "Nav derīga Oracle parole un/vai lietotājvārds", "Offending command was: \"%s\", name: %s, password: %s" => "Vainīgā komanda bija \"%s\", vārds: %s, parole: %s", "MS SQL username and/or password not valid: %s" => "Nav derīga MySQL parole un/vai lietotājvārds — %s", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Jūsu serveris vēl nav pareizi iestatīts, lai ļautu sinhronizēt datnes, jo izskatās, ka WebDAV saskarne ir salauzta.", @@ -49,8 +48,5 @@ "%d months ago" => "pirms %d mēnešiem", "last year" => "gājušajā gadā", "years ago" => "gadus atpakaļ", -"%s is available. Get <a href=\"%s\">more information</a>" => "%s ir pieejams. Iegūt <a href=\"%s\">vairāk informācijas</a>", -"up to date" => "ir aktuāls", -"updates check is disabled" => "atjauninājumu pārbaude ir deaktivēta", "Could not find category \"%s\"" => "Nevarēja atrast kategoriju “%s”" ); diff --git a/lib/l10n/mk.php b/lib/l10n/mk.php index 5b3efffb22a..34790c93745 100644 --- a/lib/l10n/mk.php +++ b/lib/l10n/mk.php @@ -1,7 +1,7 @@ <?php $TRANSLATIONS = array( "Help" => "Помош", "Personal" => "Лично", -"Settings" => "Параметри", +"Settings" => "Подесувања", "Users" => "Корисници", "Apps" => "Аппликации", "Admin" => "Админ", @@ -27,8 +27,5 @@ "%d months ago" => "пред %d месеци", "last year" => "минатата година", "years ago" => "пред години", -"%s is available. Get <a href=\"%s\">more information</a>" => "%s е достапно. Земи <a href=\"%s\">повеќе информации</a>", -"up to date" => "ажурно", -"updates check is disabled" => "проверката за ажурирања е оневозможена", "Could not find category \"%s\"" => "Не можам да најдам категорија „%s“" ); diff --git a/lib/l10n/ms_MY.php b/lib/l10n/ms_MY.php index 732ea96c6b7..6abbbe86e80 100644 --- a/lib/l10n/ms_MY.php +++ b/lib/l10n/ms_MY.php @@ -3,6 +3,7 @@ "Personal" => "Peribadi", "Settings" => "Tetapan", "Users" => "Pengguna", +"Apps" => "Aplikasi", "Admin" => "Admin", "Authentication error" => "Ralat pengesahan", "Files" => "Fail-fail", diff --git a/lib/l10n/my_MM.php b/lib/l10n/my_MM.php index d725a06a3a9..5d1812fd742 100644 --- a/lib/l10n/my_MM.php +++ b/lib/l10n/my_MM.php @@ -24,8 +24,5 @@ "%d months ago" => "%d လအရင်က", "last year" => "မနှစ်က", "years ago" => "နှစ် အရင်က", -"%s is available. Get <a href=\"%s\">more information</a>" => "%s ကိုရရှိနိုင်ပါပြီ။ <a href=\"%s\">နောက်ထပ်အချက်အလက်များ</a>ရယူပါ။", -"up to date" => "နောက်ဆုံးပေါ်", -"updates check is disabled" => "နောက်ဆုံးပေါ်စစ်ဆေးခြင်းကိုပိတ်ထားသည်", "Could not find category \"%s\"" => "\"%s\"ခေါင်းစဉ်ကို ရှာမတွေ့ပါ" ); diff --git a/lib/l10n/nb_NO.php b/lib/l10n/nb_NO.php index 01144672caa..23146154c77 100644 --- a/lib/l10n/nb_NO.php +++ b/lib/l10n/nb_NO.php @@ -10,11 +10,13 @@ "Back to Files" => "Tilbake til filer", "Selected files too large to generate zip file." => "De valgte filene er for store til å kunne generere ZIP-fil", "Application is not enabled" => "Applikasjon er ikke påslått", -"Authentication error" => "Autentiseringsfeil", +"Authentication error" => "Autentikasjonsfeil", "Token expired. Please reload page." => "Symbol utløpt. Vennligst last inn siden på nytt.", "Files" => "Filer", "Text" => "Tekst", "Images" => "Bilder", +"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Din nettservev er ikke konfigurert korrekt for filsynkronisering. WebDAV ser ut til å ikke funkere.", +"Please double check the <a href='%s'>installation guides</a>." => "Vennligst dobbelsjekk <a href='%s'>installasjonsguiden</a>.", "seconds ago" => "sekunder siden", "1 minute ago" => "1 minutt siden", "%d minutes ago" => "%d minutter siden", @@ -25,10 +27,7 @@ "%d days ago" => "%d dager siden", "last month" => "forrige måned", "%d months ago" => "%d måneder siden", -"last year" => "i fjor", +"last year" => "forrige år", "years ago" => "år siden", -"%s is available. Get <a href=\"%s\">more information</a>" => "%s er tilgjengelig. Få <a href=\"%s\">mer informasjon</a>", -"up to date" => "oppdatert", -"updates check is disabled" => "versjonssjekk er avslått", "Could not find category \"%s\"" => "Kunne ikke finne kategori \"%s\"" ); diff --git a/lib/l10n/nl.php b/lib/l10n/nl.php index 10a4060e119..2a6086a5968 100644 --- a/lib/l10n/nl.php +++ b/lib/l10n/nl.php @@ -18,14 +18,13 @@ "Images" => "Afbeeldingen", "Set an admin username." => "Stel de gebruikersnaam van de beheerder in.", "Set an admin password." => "Stel een beheerderswachtwoord in.", -"Specify a data folder." => "Geef een datamap op.", "%s enter the database username." => "%s opgeven database gebruikersnaam.", "%s enter the database name." => "%s opgeven databasenaam.", "%s you may not use dots in the database name" => "%s er mogen geen puntjes in de databasenaam voorkomen", "%s set the database host." => "%s instellen databaseservernaam.", "PostgreSQL username and/or password not valid" => "PostgreSQL gebruikersnaam en/of wachtwoord ongeldig", "You need to enter either an existing account or the administrator." => "Geef of een bestaand account op of het beheerdersaccount.", -"Oracle username and/or password not valid" => "Oracle gebruikersnaam en/of wachtwoord ongeldig", +"Oracle connection could not be established" => "Er kon geen verbinding met Oracle worden bereikt", "MySQL username and/or password not valid" => "MySQL gebruikersnaam en/of wachtwoord ongeldig", "DB Error: \"%s\"" => "DB Fout: \"%s\"", "Offending command was: \"%s\"" => "Onjuiste commande was: \"%s\"", @@ -33,6 +32,7 @@ "Drop this user from MySQL" => "Verwijder deze gebruiker uit MySQL", "MySQL user '%s'@'%%' already exists" => "MySQL gebruiker '%s'@'%%' bestaat al", "Drop this user from MySQL." => "Verwijder deze gebruiker uit MySQL.", +"Oracle username and/or password not valid" => "Oracle gebruikersnaam en/of wachtwoord ongeldig", "Offending command was: \"%s\", name: %s, password: %s" => "Onjuiste commando was: \"%s\", naam: %s, wachtwoord: %s", "MS SQL username and/or password not valid: %s" => "MS SQL gebruikersnaam en/of wachtwoord niet geldig: %s", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Uw webserver is nog niet goed ingesteld voor bestandssynchronisatie omdat de WebDAV interface verbroken lijkt.", @@ -49,8 +49,5 @@ "%d months ago" => "%d maanden geleden", "last year" => "vorig jaar", "years ago" => "jaar geleden", -"%s is available. Get <a href=\"%s\">more information</a>" => "%s is beschikbaar. Verkrijg <a href=\"%s\">meer informatie</a>", -"up to date" => "bijgewerkt", -"updates check is disabled" => "Meest recente versie controle is uitgeschakeld", "Could not find category \"%s\"" => "Kon categorie \"%s\" niet vinden" ); diff --git a/lib/l10n/nn_NO.php b/lib/l10n/nn_NO.php index 4de21cd9c23..8241573f9ae 100644 --- a/lib/l10n/nn_NO.php +++ b/lib/l10n/nn_NO.php @@ -3,8 +3,19 @@ "Personal" => "Personleg", "Settings" => "Innstillingar", "Users" => "Brukarar", +"Apps" => "Program", "Admin" => "Administrer", "Authentication error" => "Feil i autentisering", "Files" => "Filer", -"Text" => "Tekst" +"Text" => "Tekst", +"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Tenaren din er ikkje enno rett innstilt til å tilby filsynkronisering sidan WebDAV-grensesnittet ser ut til å vera øydelagt.", +"Please double check the <a href='%s'>installation guides</a>." => "Ver vennleg og dobbeltsjekk <a href='%s'>installasjonsrettleiinga</a>.", +"seconds ago" => "sekund sidan", +"1 minute ago" => "1 minutt sidan", +"1 hour ago" => "1 time sidan", +"today" => "i dag", +"yesterday" => "i går", +"last month" => "førre månad", +"last year" => "i fjor", +"years ago" => "år sidan" ); diff --git a/lib/l10n/oc.php b/lib/l10n/oc.php index 89161393380..85e2a27b431 100644 --- a/lib/l10n/oc.php +++ b/lib/l10n/oc.php @@ -18,7 +18,5 @@ "%d days ago" => "%d jorns a", "last month" => "mes passat", "last year" => "an passat", -"years ago" => "ans a", -"up to date" => "a jorn", -"updates check is disabled" => "la verificacion de mesa a jorn es inactiva" +"years ago" => "ans a" ); diff --git a/lib/l10n/pl.php b/lib/l10n/pl.php index 9a1a5e836c9..53a9290785c 100644 --- a/lib/l10n/pl.php +++ b/lib/l10n/pl.php @@ -18,14 +18,13 @@ "Images" => "Obrazy", "Set an admin username." => "Ustaw nazwę administratora.", "Set an admin password." => "Ustaw hasło administratora.", -"Specify a data folder." => "Określ folder danych.", "%s enter the database username." => "%s wpisz nazwę użytkownika do bazy", "%s enter the database name." => "%s wpisz nazwę bazy.", "%s you may not use dots in the database name" => "%s nie można używać kropki w nazwie bazy danych", "%s set the database host." => "%s ustaw hosta bazy danych.", "PostgreSQL username and/or password not valid" => "PostgreSQL: Nazwa użytkownika i/lub hasło jest niepoprawne", "You need to enter either an existing account or the administrator." => "Należy wprowadzić istniejące konto użytkownika lub administratora.", -"Oracle username and/or password not valid" => "Oracle: Nazwa użytkownika i/lub hasło jest niepoprawne", +"Oracle connection could not be established" => "Nie można ustanowić połączenia z bazą Oracle", "MySQL username and/or password not valid" => "MySQL: Nazwa użytkownika i/lub hasło jest niepoprawne", "DB Error: \"%s\"" => "Błąd DB: \"%s\"", "Offending command was: \"%s\"" => "Niepoprawna komenda: \"%s\"", @@ -33,24 +32,22 @@ "Drop this user from MySQL" => "Usuń tego użytkownika z MySQL", "MySQL user '%s'@'%%' already exists" => "Użytkownik MySQL '%s'@'%%t' już istnieje", "Drop this user from MySQL." => "Usuń tego użytkownika z MySQL.", +"Oracle username and/or password not valid" => "Oracle: Nazwa użytkownika i/lub hasło jest niepoprawne", "Offending command was: \"%s\", name: %s, password: %s" => "Niepoprawne polecania: \"%s\", nazwa: %s, hasło: %s", "MS SQL username and/or password not valid: %s" => "Nazwa i/lub hasło serwera MS SQL jest niepoprawne: %s.", -"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Serwer www nie jest jeszcze poprawnie ustawiony, aby umożliwić synchronizację plików, ponieważ interfejs WebDAV wydaje się być uszkodzony. Sprawdź ustawienia serwera.", -"Please double check the <a href='%s'>installation guides</a>." => "Proszę sprawdź ponownie <a href='%s'>przewodnik instalacji</a>.", +"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Serwer internetowy nie jest jeszcze poprawnie skonfigurowany, aby umożliwić synchronizację plików, ponieważ interfejs WebDAV wydaje się być uszkodzony.", +"Please double check the <a href='%s'>installation guides</a>." => "Sprawdź ponownie <a href='%s'>przewodniki instalacji</a>.", "seconds ago" => "sekund temu", "1 minute ago" => "1 minutę temu", "%d minutes ago" => "%d minut temu", -"1 hour ago" => "1 godzine temu", +"1 hour ago" => "1 godzinę temu", "%d hours ago" => "%d godzin temu", -"today" => "dzisiaj", +"today" => "dziś", "yesterday" => "wczoraj", "%d days ago" => "%d dni temu", -"last month" => "ostatni miesiąc", +"last month" => "w zeszłym miesiącu", "%d months ago" => "%d miesiecy temu", -"last year" => "ostatni rok", +"last year" => "w zeszłym roku", "years ago" => "lat temu", -"%s is available. Get <a href=\"%s\">more information</a>" => "%s jest dostępna. Uzyskaj <a href=\"%s\">więcej informacji</a>", -"up to date" => "Aktualne", -"updates check is disabled" => "wybór aktualizacji jest wyłączony", "Could not find category \"%s\"" => "Nie można odnaleźć kategorii \"%s\"" ); diff --git a/lib/l10n/pt_BR.php b/lib/l10n/pt_BR.php index d4f410d8885..9606477d945 100644 --- a/lib/l10n/pt_BR.php +++ b/lib/l10n/pt_BR.php @@ -18,14 +18,13 @@ "Images" => "Imagens", "Set an admin username." => "Defina um nome de usuário de administrador.", "Set an admin password." => "Defina uma senha de administrador.", -"Specify a data folder." => "Especifique uma pasta de dados.", "%s enter the database username." => "%s insira o nome de usuário do banco de dados.", "%s enter the database name." => "%s insira o nome do banco de dados.", "%s you may not use dots in the database name" => "%s você não pode usar pontos no nome do banco de dados", "%s set the database host." => "%s defina o host do banco de dados.", "PostgreSQL username and/or password not valid" => "Nome de usuário e/ou senha PostgreSQL inválido(s)", "You need to enter either an existing account or the administrator." => "Você precisa inserir uma conta existente ou o administrador.", -"Oracle username and/or password not valid" => "Nome de usuário e/ou senha Oracle inválido(s)", +"Oracle connection could not be established" => "Conexão Oracle não pode ser estabelecida", "MySQL username and/or password not valid" => "Nome de usuário e/ou senha MySQL inválido(s)", "DB Error: \"%s\"" => "Erro no BD: \"%s\"", "Offending command was: \"%s\"" => "Comando ofensivo era: \"%s\"", @@ -33,6 +32,7 @@ "Drop this user from MySQL" => "Derrubar este usuário do MySQL", "MySQL user '%s'@'%%' already exists" => "Usuário MySQL '%s'@'%%' já existe", "Drop this user from MySQL." => "Derrube este usuário do MySQL.", +"Oracle username and/or password not valid" => "Nome de usuário e/ou senha Oracle inválido(s)", "Offending command was: \"%s\", name: %s, password: %s" => "Comando ofensivo era: \"%s\", nome: %s, senha: %s", "MS SQL username and/or password not valid: %s" => "Nome de usuário e/ou senha MS SQL inválido(s): %s", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Seu servidor web não está configurado corretamente para permitir sincronização de arquivos porque a interface WebDAV parece estar quebrada.", @@ -49,8 +49,5 @@ "%d months ago" => "%d meses atrás", "last year" => "último ano", "years ago" => "anos atrás", -"%s is available. Get <a href=\"%s\">more information</a>" => "%s está disponível. Obtenha <a href=\"%s\">mais informações</a>", -"up to date" => "atualizado", -"updates check is disabled" => "checagens de atualização estão desativadas", "Could not find category \"%s\"" => "Impossível localizar categoria \"%s\"" ); diff --git a/lib/l10n/pt_PT.php b/lib/l10n/pt_PT.php index 2c813f5b07c..f49258157ed 100644 --- a/lib/l10n/pt_PT.php +++ b/lib/l10n/pt_PT.php @@ -18,14 +18,13 @@ "Images" => "Imagens", "Set an admin username." => "Definir um nome de utilizador de administrador", "Set an admin password." => "Definiar uma password de administrador", -"Specify a data folder." => "Especificar a pasta para os dados.", "%s enter the database username." => "%s introduza o nome de utilizador da base de dados", "%s enter the database name." => "%s introduza o nome da base de dados", "%s you may not use dots in the database name" => "%s não é permitido utilizar pontos (.) no nome da base de dados", "%s set the database host." => "%s defina o servidor da base de dados (geralmente localhost)", "PostgreSQL username and/or password not valid" => "Nome de utilizador/password do PostgreSQL inválido", "You need to enter either an existing account or the administrator." => "Precisa de introduzir uma conta existente ou de administrador", -"Oracle username and/or password not valid" => "Nome de utilizador/password do Oracle inválida", +"Oracle connection could not be established" => "Não foi possível estabelecer a ligação Oracle", "MySQL username and/or password not valid" => "Nome de utilizador/password do MySQL inválida", "DB Error: \"%s\"" => "Erro na BD: \"%s\"", "Offending command was: \"%s\"" => "O comando gerador de erro foi: \"%s\"", @@ -33,24 +32,22 @@ "Drop this user from MySQL" => "Eliminar este utilizador do MySQL", "MySQL user '%s'@'%%' already exists" => "O utilizador '%s'@'%%' do MySQL já existe", "Drop this user from MySQL." => "Eliminar este utilizador do MySQL", +"Oracle username and/or password not valid" => "Nome de utilizador/password do Oracle inválida", "Offending command was: \"%s\", name: %s, password: %s" => "O comando gerador de erro foi: \"%s\", nome: %s, password: %s", "MS SQL username and/or password not valid: %s" => "Nome de utilizador/password do MySQL é inválido: %s", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "O seu servidor web não está configurado correctamente para autorizar sincronização de ficheiros, pois o interface WebDAV parece estar com problemas.", "Please double check the <a href='%s'>installation guides</a>." => "Por favor verifique <a href='%s'>installation guides</a>.", -"seconds ago" => "há alguns segundos", -"1 minute ago" => "há 1 minuto", +"seconds ago" => "Minutos atrás", +"1 minute ago" => "Há 1 minuto", "%d minutes ago" => "há %d minutos", "1 hour ago" => "Há 1 horas", "%d hours ago" => "Há %d horas", "today" => "hoje", "yesterday" => "ontem", "%d days ago" => "há %d dias", -"last month" => "mês passado", +"last month" => "ultímo mês", "%d months ago" => "Há %d meses atrás", "last year" => "ano passado", -"years ago" => "há anos", -"%s is available. Get <a href=\"%s\">more information</a>" => "%s está disponível. Obtenha <a href=\"%s\">mais informação</a>", -"up to date" => "actualizado", -"updates check is disabled" => "a verificação de actualizações está desligada", +"years ago" => "anos atrás", "Could not find category \"%s\"" => "Não foi encontrado a categoria \"%s\"" ); diff --git a/lib/l10n/ro.php b/lib/l10n/ro.php index 3f8e59cdac2..6661caf86e7 100644 --- a/lib/l10n/ro.php +++ b/lib/l10n/ro.php @@ -28,8 +28,5 @@ "%d months ago" => "%d luni in urma", "last year" => "ultimul an", "years ago" => "ani în urmă", -"%s is available. Get <a href=\"%s\">more information</a>" => "%s este disponibil. Vezi <a href=\"%s\">mai multe informații</a>", -"up to date" => "la zi", -"updates check is disabled" => "verificarea după actualizări este dezactivată", "Could not find category \"%s\"" => "Cloud nu a gasit categoria \"%s\"" ); diff --git a/lib/l10n/ru.php b/lib/l10n/ru.php index 25a88d5efc2..e077b688c09 100644 --- a/lib/l10n/ru.php +++ b/lib/l10n/ru.php @@ -1,7 +1,7 @@ <?php $TRANSLATIONS = array( "Help" => "Помощь", "Personal" => "Личное", -"Settings" => "Настройки", +"Settings" => "Конфигурация", "Users" => "Пользователи", "Apps" => "Приложения", "Admin" => "Admin", @@ -18,14 +18,12 @@ "Images" => "Изображения", "Set an admin username." => "Установить имя пользователя для admin.", "Set an admin password." => "становит пароль для admin.", -"Specify a data folder." => "Указать папку данных.", "%s enter the database username." => "%s введите имя пользователя базы данных.", "%s enter the database name." => "%s введите имя базы данных.", "%s you may not use dots in the database name" => "%s Вы не можете использовать точки в имени базы данных", "%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 username and/or password not valid" => "Неверное имя пользователя и/или пароль Oracle", "MySQL username and/or password not valid" => "Неверное имя пользователя и/или пароль MySQL", "DB Error: \"%s\"" => "Ошибка БД: \"%s\"", "Offending command was: \"%s\"" => "Вызываемая команда была: \"%s\"", @@ -33,11 +31,12 @@ "Drop this user from MySQL" => "Удалить этого пользователя из MySQL", "MySQL user '%s'@'%%' already exists" => "Пользователь MySQL '%s'@'%%' уже существует", "Drop this user from MySQL." => "Удалить этого пользователя из MySQL.", +"Oracle username and/or password not valid" => "Неверное имя пользователя и/или пароль Oracle", "Offending command was: \"%s\", name: %s, password: %s" => "Вызываемая команда была: \"%s\", имя: %s, пароль: %s", "MS SQL username and/or password not valid: %s" => "Имя пользователя и/или пароль MS SQL не подходит: %s", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Ваш веб сервер до сих пор не настроен правильно для возможности синхронизации файлов, похоже что проблема в неисправности интерфейса WebDAV.", "Please double check the <a href='%s'>installation guides</a>." => "Пожалуйста, дважды просмотрите <a href='%s'>инструкции по установке</a>.", -"seconds ago" => "менее минуты", +"seconds ago" => "несколько секунд назад", "1 minute ago" => "1 минуту назад", "%d minutes ago" => "%d минут назад", "1 hour ago" => "час назад", @@ -48,9 +47,6 @@ "last month" => "в прошлом месяце", "%d months ago" => "%d месяцев назад", "last year" => "в прошлом году", -"years ago" => "годы назад", -"%s is available. Get <a href=\"%s\">more information</a>" => "Возможно обновление до %s. <a href=\"%s\">Подробнее</a>", -"up to date" => "актуальная версия", -"updates check is disabled" => "проверка обновлений отключена", +"years ago" => "несколько лет назад", "Could not find category \"%s\"" => "Категория \"%s\" не найдена" ); diff --git a/lib/l10n/ru_RU.php b/lib/l10n/ru_RU.php index de770563662..7639a3cc97e 100644 --- a/lib/l10n/ru_RU.php +++ b/lib/l10n/ru_RU.php @@ -1,37 +1,4 @@ <?php $TRANSLATIONS = array( -"Help" => "Помощь", -"Personal" => "Персональный", "Settings" => "Настройки", -"Users" => "Пользователи", -"Apps" => "Приложения", -"Admin" => "Админ", -"ZIP download is turned off." => "Загрузка ZIP выключена.", -"Files need to be downloaded one by one." => "Файлы должны быть загружены один за другим.", -"Back to Files" => "Обратно к файлам", -"Selected files too large to generate zip file." => "Выбранные файлы слишком велики для генерации zip-архива.", -"couldn't be determined" => "не может быть определено", -"Application is not enabled" => "Приложение не запущено", -"Authentication error" => "Ошибка аутентификации", -"Token expired. Please reload page." => "Маркер истек. Пожалуйста, перезагрузите страницу.", -"Files" => "Файлы", -"Text" => "Текст", -"Images" => "Изображения", -"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Ваш веб сервер ещё не достаточно точно настроен для возможности синхронизации, т.к. похоже, что интерфейс WebDAV сломан.", -"Please double check the <a href='%s'>installation guides</a>." => "Пожалуйста проверте дважды <a href='%s'>гиды по установке</a>.", -"seconds ago" => "секунд назад", -"1 minute ago" => "1 минуту назад", -"%d minutes ago" => "%d минут назад", -"1 hour ago" => "1 час назад", -"%d hours ago" => "%d часов назад", -"today" => "сегодня", -"yesterday" => "вчера", -"%d days ago" => "%d дней назад", -"last month" => "в прошлом месяце", -"%d months ago" => "%d месяцев назад", -"last year" => "в прошлом году", -"years ago" => "год назад", -"%s is available. Get <a href=\"%s\">more information</a>" => "%s доступно. Получите <a href=\"%s\">more information</a>", -"up to date" => "до настоящего времени", -"updates check is disabled" => "Проверка обновлений отключена", -"Could not find category \"%s\"" => "Не удалось найти категорию \"%s\"" +"Text" => "Текст" ); diff --git a/lib/l10n/si_LK.php b/lib/l10n/si_LK.php index 25624acf705..4846fdcc066 100644 --- a/lib/l10n/si_LK.php +++ b/lib/l10n/si_LK.php @@ -10,7 +10,7 @@ "Back to Files" => "ගොනු වෙතට නැවත යන්න", "Selected files too large to generate zip file." => "තෝරාගත් ගොනු ZIP ගොනුවක් තැනීමට විශාල වැඩිය.", "Application is not enabled" => "යෙදුම සක්රිය කර නොමැත", -"Authentication error" => "සත්යාපනය කිරීමේ දෝශයක්", +"Authentication error" => "සත්යාපන දෝෂයක්", "Token expired. Please reload page." => "ටෝකනය කල් ඉකුත් වී ඇත. පිටුව නැවුම් කරන්න", "Files" => "ගොනු", "Text" => "පෙළ", @@ -23,8 +23,5 @@ "%d days ago" => "%d දිනකට පෙර", "last month" => "පෙර මාසයේ", "last year" => "පෙර අවුරුද්දේ", -"years ago" => "අවුරුදු කීපයකට පෙර", -"%s is available. Get <a href=\"%s\">more information</a>" => "%s යොදාගත හැක. <a href=\"%s\">තව විස්තර</a> ලබාගන්න", -"up to date" => "යාවත්කාලීනයි", -"updates check is disabled" => "යාවත්කාලීන බව පරීක්ෂණය අක්රියයි" +"years ago" => "අවුරුදු කීපයකට පෙර" ); diff --git a/lib/l10n/sk_SK.php b/lib/l10n/sk_SK.php index 8c9ce61622c..c1ec2470b46 100644 --- a/lib/l10n/sk_SK.php +++ b/lib/l10n/sk_SK.php @@ -18,14 +18,13 @@ "Images" => "Obrázky", "Set an admin username." => "Zadajte používateľské meno administrátora.", "Set an admin password." => "Zadajte heslo administrátora.", -"Specify a data folder." => "Zadajte priečinok pre dáta.", "%s enter the database username." => "Zadajte používateľské meno %s databázy..", "%s enter the database name." => "Zadajte názov databázy pre %s databázy.", "%s you may not use dots in the database name" => "V názve databázy %s nemôžete používať bodky", "%s set the database host." => "Zadajte názov počítača s databázou %s.", "PostgreSQL username and/or password not valid" => "Používateľské meno a/alebo heslo pre PostgreSQL databázu je neplatné", "You need to enter either an existing account or the administrator." => "Musíte zadať jestvujúci účet alebo administrátora.", -"Oracle username and/or password not valid" => "Používateľské meno a/alebo heslo pre Oracle databázu je neplatné", +"Oracle connection could not be established" => "Nie je možné pripojiť sa k Oracle", "MySQL username and/or password not valid" => "Používateľské meno a/alebo heslo pre MySQL databázu je neplatné", "DB Error: \"%s\"" => "Chyba DB: \"%s\"", "Offending command was: \"%s\"" => "Podozrivý príkaz bol: \"%s\"", @@ -33,12 +32,13 @@ "Drop this user from MySQL" => "Zahodiť používateľa z MySQL.", "MySQL user '%s'@'%%' already exists" => "Používateľ '%s'@'%%' už v MySQL existuje", "Drop this user from MySQL." => "Zahodiť používateľa z MySQL.", +"Oracle username and/or password not valid" => "Používateľské meno a/alebo heslo pre Oracle databázu je neplatné", "Offending command was: \"%s\", name: %s, password: %s" => "Podozrivý príkaz bol: \"%s\", meno: %s, heslo: %s", "MS SQL username and/or password not valid: %s" => "Používateľské meno, alebo heslo MS SQL nie je platné: %s", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Váš webový server nie je správne nastavený na synchronizáciu, pretože rozhranie WebDAV je poškodené.", "Please double check the <a href='%s'>installation guides</a>." => "Prosím skontrolujte <a href='%s'>inštalačnú príručku</a>.", "seconds ago" => "pred sekundami", -"1 minute ago" => "pred 1 minútou", +"1 minute ago" => "pred minútou", "%d minutes ago" => "pred %d minútami", "1 hour ago" => "Pred 1 hodinou", "%d hours ago" => "Pred %d hodinami.", @@ -49,8 +49,5 @@ "%d months ago" => "Pred %d mesiacmi.", "last year" => "minulý rok", "years ago" => "pred rokmi", -"%s is available. Get <a href=\"%s\">more information</a>" => "%s je dostupné. Získať <a href=\"%s\">pre viac informácií</a>", -"up to date" => "aktuálny", -"updates check is disabled" => "sledovanie aktualizácií je vypnuté", "Could not find category \"%s\"" => "Nemožno nájsť danú kategóriu \"%s\"" ); diff --git a/lib/l10n/sl.php b/lib/l10n/sl.php index a2e1719de87..7f8827d17f3 100644 --- a/lib/l10n/sl.php +++ b/lib/l10n/sl.php @@ -11,21 +11,19 @@ "Selected files too large to generate zip file." => "Izbrane datoteke so prevelike za ustvarjanje datoteke arhiva zip.", "couldn't be determined" => "ni mogoče določiti", "Application is not enabled" => "Program ni omogočen", -"Authentication error" => "Napaka overitve", +"Authentication error" => "Napaka pri overjanju", "Token expired. Please reload page." => "Žeton je potekel. Stran je treba ponovno naložiti.", "Files" => "Datoteke", "Text" => "Besedilo", "Images" => "Slike", "Set an admin username." => "Nastavi uporabniško ime skrbnika.", "Set an admin password." => "Nastavi geslo skrbnika.", -"Specify a data folder." => "Določi podatkovno mapo.", "%s enter the database username." => "%s - vnos uporabniškega imena podatkovne zbirke.", "%s enter the database name." => "%s - vnos imena podatkovne zbirke.", "%s you may not use dots in the database name" => "%s - v imenu podatkovne zbirke ni dovoljeno uporabljati pik.", "%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 username and/or password not valid" => "Uporabniško ime ali geslo Oracle ni veljavno", "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\"", @@ -33,6 +31,7 @@ "Drop this user from MySQL" => "Odstrani uporabnika s podatkovne zbirke MySQL", "MySQL user '%s'@'%%' already exists" => "Uporabnik MySQL '%s'@'%%' že obstaja.", "Drop this user from MySQL." => "Odstrani uporabnika s podatkovne zbirke MySQL", +"Oracle username and/or password not valid" => "Uporabniško ime ali geslo Oracle ni veljavno", "Offending command was: \"%s\", name: %s, password: %s" => "Napačni ukaz je: \"%s\", ime: %s, geslo: %s", "MS SQL username and/or password not valid: %s" => "Uporabniško ime ali geslo MS SQL ni veljavno: %s", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Spletni stražnik še ni ustrezno nastavljen in ne omogoča usklajevanja, saj je nastavitev WebDAV okvarjena.", @@ -45,12 +44,9 @@ "today" => "danes", "yesterday" => "včeraj", "%d days ago" => "pred %d dnevi", -"last month" => "prejšnji mesec", +"last month" => "zadnji mesec", "%d months ago" => "Pred %d meseci", "last year" => "lansko leto", -"years ago" => "pred nekaj leti", -"%s is available. Get <a href=\"%s\">more information</a>" => "%s je na voljo. <a href=\"%s\">Več podrobnosti.</a>", -"up to date" => "posodobljeno", -"updates check is disabled" => "preverjanje za posodobitve je onemogočeno", +"years ago" => "let nazaj", "Could not find category \"%s\"" => "Kategorije \"%s\" ni mogoče najti." ); diff --git a/lib/l10n/sq.php b/lib/l10n/sq.php index 743c52850ac..04186f62102 100644 --- a/lib/l10n/sq.php +++ b/lib/l10n/sq.php @@ -1,7 +1,7 @@ <?php $TRANSLATIONS = array( "Help" => "Ndihmë", "Personal" => "Personale", -"Settings" => "Parametrat", +"Settings" => "Parametra", "Users" => "Përdoruesit", "Apps" => "App", "Admin" => "Admin", @@ -18,14 +18,12 @@ "Images" => "Foto", "Set an admin username." => "Cakto emrin e administratorit.", "Set an admin password." => "Cakto kodin e administratorit.", -"Specify a data folder." => "Specifiko dosjen e të dhënave.", "%s enter the database username." => "% shkruani përdoruesin e database-it.", "%s enter the database name." => "%s shkruani emrin e database-it.", "%s you may not use dots in the database name" => "%s nuk mund të përdorni pikat tek emri i database-it", "%s set the database host." => "%s caktoni pozicionin (host) e database-it.", "PostgreSQL username and/or password not valid" => "Përdoruesi dhe/apo kodi i PostgreSQL i pavlefshëm", "You need to enter either an existing account or the administrator." => "Duhet të përdorni një llogari ekzistuese ose llogarinë e administratorit.", -"Oracle username and/or password not valid" => "Përdoruesi dhe/apo kodi i Oracle-it i pavlefshëm", "MySQL username and/or password not valid" => "Përdoruesi dhe/apo kodi i MySQL-it i pavlefshëm.", "DB Error: \"%s\"" => "Veprim i gabuar i DB-it: \"%s\"", "Offending command was: \"%s\"" => "Komanda e gabuar ishte: \"%s\"", @@ -33,6 +31,7 @@ "Drop this user from MySQL" => "Eliminoni këtë përdorues nga MySQL", "MySQL user '%s'@'%%' already exists" => "Përdoruesi MySQL '%s'@'%%' ekziston", "Drop this user from MySQL." => "Eliminoni këtë përdorues nga MySQL.", +"Oracle username and/or password not valid" => "Përdoruesi dhe/apo kodi i Oracle-it i pavlefshëm", "Offending command was: \"%s\", name: %s, password: %s" => "Komanda e gabuar ishte: \"%s\", përdoruesi: %s, kodi: %s", "MS SQL username and/or password not valid: %s" => "Përdoruesi dhe/apo kodi i MS SQL i pavlefshëm: %s", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Serveri web i juaji nuk është konfiguruar akoma për të lejuar sinkronizimin e skedarëve sepse ndërfaqja WebDAV mund të jetë e dëmtuar.", @@ -49,8 +48,5 @@ "%d months ago" => "%d muaj më parë", "last year" => "vitin e shkuar", "years ago" => "vite më parë", -"%s is available. Get <a href=\"%s\">more information</a>" => "%s është i disponueshëm. <a href=\"%s\">Informohuni këtu</a>", -"up to date" => "i azhornuar", -"updates check is disabled" => "kontrollimi i azhurnimeve është i çaktivizuar", "Could not find category \"%s\"" => "Kategoria \"%s\" nuk u gjet" ); diff --git a/lib/l10n/sr.php b/lib/l10n/sr.php index 1161b0a44b7..45b8e06200c 100644 --- a/lib/l10n/sr.php +++ b/lib/l10n/sr.php @@ -16,10 +16,12 @@ "Files" => "Датотеке", "Text" => "Текст", "Images" => "Слике", +"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Ваш веб сервер тренутно не подржава синхронизацију датотека јер се чини да је WebDAV сучеље неисправно.", +"Please double check the <a href='%s'>installation guides</a>." => "Погледајте <a href='%s'>водиче за инсталацију</a>.", "seconds ago" => "пре неколико секунди", "1 minute ago" => "пре 1 минут", "%d minutes ago" => "пре %d минута", -"1 hour ago" => "пре 1 сат", +"1 hour ago" => "Пре једног сата", "%d hours ago" => "пре %d сата/и", "today" => "данас", "yesterday" => "јуче", @@ -28,8 +30,5 @@ "%d months ago" => "пре %d месеца/и", "last year" => "прошле године", "years ago" => "година раније", -"%s is available. Get <a href=\"%s\">more information</a>" => "%s је доступна. Погледајте <a href=\"%s\">више информација</a>.", -"up to date" => "је ажурна", -"updates check is disabled" => "провера ажурирања је онемогућена", "Could not find category \"%s\"" => "Не могу да пронађем категорију „%s“." ); diff --git a/lib/l10n/sr@latin.php b/lib/l10n/sr@latin.php index 2f0a97fd77f..13cedc83279 100644 --- a/lib/l10n/sr@latin.php +++ b/lib/l10n/sr@latin.php @@ -3,6 +3,7 @@ "Personal" => "Lično", "Settings" => "Podešavanja", "Users" => "Korisnici", +"Apps" => "Programi", "Admin" => "Adninistracija", "Authentication error" => "Greška pri autentifikaciji", "Files" => "Fajlovi", diff --git a/lib/l10n/sv.php b/lib/l10n/sv.php index 63ca60e89cd..3dcb26d5d8d 100644 --- a/lib/l10n/sv.php +++ b/lib/l10n/sv.php @@ -23,15 +23,12 @@ "%d minutes ago" => "%d minuter sedan", "1 hour ago" => "1 timme sedan", "%d hours ago" => "%d timmar sedan", -"today" => "idag", -"yesterday" => "igår", +"today" => "i dag", +"yesterday" => "i går", "%d days ago" => "%d dagar sedan", "last month" => "förra månaden", "%d months ago" => "%d månader sedan", "last year" => "förra året", "years ago" => "år sedan", -"%s is available. Get <a href=\"%s\">more information</a>" => "%s finns. Få <a href=\"%s\">mer information</a>", -"up to date" => "uppdaterad", -"updates check is disabled" => "uppdateringskontroll är inaktiverad", "Could not find category \"%s\"" => "Kunde inte hitta kategorin \"%s\"" ); diff --git a/lib/l10n/ta_LK.php b/lib/l10n/ta_LK.php index c76394bcb4f..c9bb578b40f 100644 --- a/lib/l10n/ta_LK.php +++ b/lib/l10n/ta_LK.php @@ -2,7 +2,7 @@ "Help" => "உதவி", "Personal" => "தனிப்பட்ட", "Settings" => "அமைப்புகள்", -"Users" => "பயனாளர்கள்", +"Users" => "பயனாளர்", "Apps" => "செயலிகள்", "Admin" => "நிர்வாகம்", "ZIP download is turned off." => "வீசொலிப் பூட்டு பதிவிறக்கம் நிறுத்தப்பட்டுள்ளது.", @@ -27,8 +27,5 @@ "%d months ago" => "%d மாதத்திற்கு முன்", "last year" => "கடந்த வருடம்", "years ago" => "வருடங்களுக்கு முன்", -"%s is available. Get <a href=\"%s\">more information</a>" => "%s இன்னும் இருக்கின்றன. <a href=\"%s\">மேலதிக தகவல்களுக்கு</a> எடுக்க", -"up to date" => "நவீன", -"updates check is disabled" => "இற்றைப்படுத்தலை சரிபார்ப்பதை செயலற்றதாக்குக", "Could not find category \"%s\"" => "பிரிவு \"%s\" ஐ கண்டுப்பிடிக்க முடியவில்லை" ); diff --git a/lib/l10n/th_TH.php b/lib/l10n/th_TH.php index 0da607a0589..7cda4ab6ae6 100644 --- a/lib/l10n/th_TH.php +++ b/lib/l10n/th_TH.php @@ -16,8 +16,8 @@ "Files" => "ไฟล์", "Text" => "ข้อความ", "Images" => "รูปภาพ", -"seconds ago" => "วินาทีที่ผ่านมา", -"1 minute ago" => "1 นาทีมาแล้ว", +"seconds ago" => "วินาที ก่อนหน้านี้", +"1 minute ago" => "1 นาทีก่อนหน้านี้", "%d minutes ago" => "%d นาทีที่ผ่านมา", "1 hour ago" => "1 ชั่วโมงก่อนหน้านี้", "%d hours ago" => "%d ชั่วโมงก่อนหน้านี้", @@ -27,9 +27,6 @@ "last month" => "เดือนที่แล้ว", "%d months ago" => "%d เดือนมาแล้ว", "last year" => "ปีที่แล้ว", -"years ago" => "ปีที่ผ่านมา", -"%s is available. Get <a href=\"%s\">more information</a>" => "%s พร้อมให้ใช้งานได้แล้ว. <a href=\"%s\">ดูรายละเอียดเพิ่มเติม</a>", -"up to date" => "ทันสมัย", -"updates check is disabled" => "การตรวจสอบชุดอัพเดทถูกปิดใช้งานไว้", +"years ago" => "ปี ที่ผ่านมา", "Could not find category \"%s\"" => "ไม่พบหมวดหมู่ \"%s\"" ); diff --git a/lib/l10n/tr.php b/lib/l10n/tr.php index 84278f6d4c4..7996447b95d 100644 --- a/lib/l10n/tr.php +++ b/lib/l10n/tr.php @@ -1,5 +1,5 @@ <?php $TRANSLATIONS = array( -"Help" => "Yardı", +"Help" => "Yardım", "Personal" => "Kişisel", "Settings" => "Ayarlar", "Users" => "Kullanıcılar", @@ -16,6 +16,24 @@ "Files" => "Dosyalar", "Text" => "Metin", "Images" => "Resimler", +"Set an admin username." => "Bir adi kullanici vermek. ", +"Set an admin password." => "Parola yonetici birlemek. ", +"%s enter the database username." => "%s veritabanı kullanıcı adını gir.", +"%s enter the database name." => "%s veritabanı adını gir.", +"%s you may not use dots in the database name" => "%s veritabanı adında nokta kullanamayabilirsiniz", +"%s set the database host." => "%s veritabanı sunucu adını tanımla", +"PostgreSQL username and/or password not valid" => "PostgreSQL adi kullanici ve/veya parola yasal degildir. ", +"You need to enter either an existing account or the administrator." => "Bir konto veya kullanici birlemek ihtiyacin. ", +"MySQL username and/or password not valid" => "MySQL kullanıcı adı ve/veya parolası geçerli değil", +"DB Error: \"%s\"" => "DB Hata: ''%s''", +"Offending command was: \"%s\"" => "Komut rahasiz ''%s''. ", +"MySQL user '%s'@'localhost' exists already." => "MySQL kullanici '%s @local host zatan var. ", +"Drop this user from MySQL" => "Bu kullanici MySQLden list disari koymak. ", +"MySQL user '%s'@'%%' already exists" => "MySQL kullanici '%s @ % % zaten var (zaten yazili)", +"Drop this user from MySQL." => "Bu kulanıcıyı MySQL veritabanından kaldır", +"Oracle username and/or password not valid" => "Adi klullanici ve/veya parola Oracle mantikli değildir. ", +"Offending command was: \"%s\", name: %s, password: %s" => "Hatalı komut: \"%s\", ad: %s, parola: %s", +"MS SQL username and/or password not valid: %s" => "MS SQL kullanıcı adı ve/veya parolası geçersiz: %s", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Web sunucunuz dosya transferi için düzgün bir şekilde yapılandırılmamış. WevDAV arabirimini sorunlu gözüküyor.", "Please double check the <a href='%s'>installation guides</a>." => "Lütfen <a href='%s'>kurulum kılavuzlarını</a> iki kez kontrol edin.", "seconds ago" => "saniye önce", @@ -30,8 +48,5 @@ "%d months ago" => "%d ay önce", "last year" => "geçen yıl", "years ago" => "yıl önce", -"%s is available. Get <a href=\"%s\">more information</a>" => "%s kullanılabilir durumda. <a href=\"%s\">Daha fazla bilgi</a> alın", -"up to date" => "güncel", -"updates check is disabled" => "güncelleme kontrolü kapalı", "Could not find category \"%s\"" => "\"%s\" kategorisi bulunamadı" ); diff --git a/lib/l10n/ug.php b/lib/l10n/ug.php new file mode 100644 index 00000000000..62d91616c1d --- /dev/null +++ b/lib/l10n/ug.php @@ -0,0 +1,19 @@ +<?php $TRANSLATIONS = array( +"Help" => "ياردەم", +"Personal" => "شەخسىي", +"Settings" => "تەڭشەكلەر", +"Users" => "ئىشلەتكۈچىلەر", +"Apps" => "ئەپلەر", +"Authentication error" => "سالاھىيەت دەلىللەش خاتالىقى", +"Files" => "ھۆججەتلەر", +"Text" => "قىسقا ئۇچۇر", +"Images" => "سۈرەتلەر", +"1 minute ago" => "1 مىنۇت ئىلگىرى", +"%d minutes ago" => "%d مىنۇت ئىلگىرى", +"1 hour ago" => "1 سائەت ئىلگىرى", +"%d hours ago" => "%d سائەت ئىلگىرى", +"today" => "بۈگۈن", +"yesterday" => "تۈنۈگۈن", +"%d days ago" => "%d كۈن ئىلگىرى", +"%d months ago" => "%d ئاي ئىلگىرى" +); diff --git a/lib/l10n/uk.php b/lib/l10n/uk.php index 68f7151d15e..676879629ef 100644 --- a/lib/l10n/uk.php +++ b/lib/l10n/uk.php @@ -18,14 +18,12 @@ "Images" => "Зображення", "Set an admin username." => "Встановіть ім'я адміністратора.", "Set an admin password." => "Встановіть пароль адміністратора.", -"Specify a data folder." => "Вкажіть теку для даних.", "%s enter the database username." => "%s введіть ім'я користувача бази даних.", "%s enter the database name." => "%s введіть назву бази даних.", "%s you may not use dots in the database name" => "%s не можна використовувати крапки в назві бази даних", "%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." => "Вам потрібно ввести або існуючий обліковий запис або administrator.", -"Oracle username and/or password not valid" => "Oracle ім'я користувача та/або пароль не дійсні", "MySQL username and/or password not valid" => "MySQL ім'я користувача та/або пароль не дійсні", "DB Error: \"%s\"" => "Помилка БД: \"%s\"", "Offending command was: \"%s\"" => "Команда, що викликала проблему: \"%s\"", @@ -33,6 +31,7 @@ "Drop this user from MySQL" => "Видалити цього користувача з MySQL", "MySQL user '%s'@'%%' already exists" => "Користувач MySQL '%s'@'%%' вже існує", "Drop this user from MySQL." => "Видалити цього користувача з MySQL.", +"Oracle username and/or password not valid" => "Oracle ім'я користувача та/або пароль не дійсні", "Offending command was: \"%s\", name: %s, password: %s" => "Команда, що викликала проблему: \"%s\", ім'я: %s, пароль: %s", "MS SQL username and/or password not valid: %s" => "MS SQL ім'я користувача та/або пароль не дійсні: %s", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Ваш Web-сервер ще не налаштований належним чином для того, щоб дозволити синхронізацію файлів, через те що інтерфейс WebDAV, здається, зламаний.", @@ -49,8 +48,5 @@ "%d months ago" => "%d місяців тому", "last year" => "минулого року", "years ago" => "роки тому", -"%s is available. Get <a href=\"%s\">more information</a>" => "%s доступно. Отримати <a href=\"%s\">детальну інформацію</a>", -"up to date" => "оновлено", -"updates check is disabled" => "перевірка оновлень відключена", "Could not find category \"%s\"" => "Не вдалося знайти категорію \"%s\"" ); diff --git a/lib/l10n/vi.php b/lib/l10n/vi.php index ea9660093ae..6a4b8ebac93 100644 --- a/lib/l10n/vi.php +++ b/lib/l10n/vi.php @@ -13,10 +13,10 @@ "Application is not enabled" => "Ứng dụng không được BẬT", "Authentication error" => "Lỗi xác thực", "Token expired. Please reload page." => "Mã Token đã hết hạn. Hãy tải lại trang.", -"Files" => "Các tập tin", +"Files" => "Tập tin", "Text" => "Văn bản", "Images" => "Hình ảnh", -"seconds ago" => "1 giây trước", +"seconds ago" => "vài giây trước", "1 minute ago" => "1 phút trước", "%d minutes ago" => "%d phút trước", "1 hour ago" => "1 giờ trước", @@ -28,8 +28,5 @@ "%d months ago" => "%d tháng trước", "last year" => "năm trước", "years ago" => "năm trước", -"%s is available. Get <a href=\"%s\">more information</a>" => "%s có sẵn. <a href=\"%s\">xem thêm ở đây</a>", -"up to date" => "đến ngày", -"updates check is disabled" => "đã TĂT chức năng cập nhật ", "Could not find category \"%s\"" => "không thể tìm thấy mục \"%s\"" ); diff --git a/lib/l10n/zh_CN.GB2312.php b/lib/l10n/zh_CN.GB2312.php index 16487339421..3ab35f2bafa 100644 --- a/lib/l10n/zh_CN.GB2312.php +++ b/lib/l10n/zh_CN.GB2312.php @@ -26,8 +26,5 @@ "%d days ago" => "%d 天前", "last month" => "上个月", "last year" => "去年", -"years ago" => "年前", -"%s is available. Get <a href=\"%s\">more information</a>" => "%s 不可用。获知 <a href=\"%s\">详情</a>", -"up to date" => "最新", -"updates check is disabled" => "更新检测已禁用" +"years ago" => "年前" ); diff --git a/lib/l10n/zh_CN.php b/lib/l10n/zh_CN.php index b79fdfcca1d..61e405d8058 100644 --- a/lib/l10n/zh_CN.php +++ b/lib/l10n/zh_CN.php @@ -18,14 +18,12 @@ "Images" => "图片", "Set an admin username." => "请设置一个管理员用户名。", "Set an admin password." => "请设置一个管理员密码。", -"Specify a data folder." => "请指定一个数据目录。", "%s enter the database username." => "%s 输入数据库用户名。", "%s enter the database name." => "%s 输入数据库名称。", "%s you may not use dots in the database name" => "%s 您不能在数据库名称中使用英文句号。", "%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 username and/or password not valid" => "Oracle 数据库用户名和/或密码无效", "MySQL username and/or password not valid" => "MySQL 数据库用户名和/或密码无效", "DB Error: \"%s\"" => "数据库错误:\"%s\"", "Offending command was: \"%s\"" => "冲突命令为:\"%s\"", @@ -33,12 +31,13 @@ "Drop this user from MySQL" => "建议从 MySQL 数据库中丢弃 Drop 此用户", "MySQL user '%s'@'%%' already exists" => "MySQL 用户 '%s'@'%%' 已存在", "Drop this user from MySQL." => "建议从 MySQL 数据库中丢弃 Drop 此用户。", +"Oracle username and/or password not valid" => "Oracle 数据库用户名和/或密码无效", "Offending command was: \"%s\", name: %s, password: %s" => "冲突命令为:\"%s\",名称:%s,密码:%s", "MS SQL username and/or password not valid: %s" => "MS SQL 用户名和/或密码无效:%s", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "您的Web服务器尚未正确设置以允许文件同步, 因为WebDAV的接口似乎已损坏.", "Please double check the <a href='%s'>installation guides</a>." => "请认真检查<a href='%s'>安装指南</a>.", -"seconds ago" => "几秒前", -"1 minute ago" => "1分钟前", +"seconds ago" => "秒前", +"1 minute ago" => "一分钟前", "%d minutes ago" => "%d 分钟前", "1 hour ago" => "1小时前", "%d hours ago" => "%d小时前", @@ -48,9 +47,6 @@ "last month" => "上月", "%d months ago" => "%d 月前", "last year" => "去年", -"years ago" => "几年前", -"%s is available. Get <a href=\"%s\">more information</a>" => "%s 已存在。点此 <a href=\"%s\">获取更多信息</a>", -"up to date" => "已更新。", -"updates check is disabled" => "更新检查功能被禁用。", +"years ago" => "年前", "Could not find category \"%s\"" => "无法找到分类 \"%s\"" ); diff --git a/lib/l10n/zh_TW.php b/lib/l10n/zh_TW.php index 62a55ebbb47..4e0d50e7fc9 100644 --- a/lib/l10n/zh_TW.php +++ b/lib/l10n/zh_TW.php @@ -5,10 +5,10 @@ "Users" => "使用者", "Apps" => "應用程式", "Admin" => "管理", -"ZIP download is turned off." => "ZIP 下載已關閉", -"Files need to be downloaded one by one." => "檔案需要逐一下載", +"ZIP download is turned off." => "ZIP 下載已關閉。", +"Files need to be downloaded one by one." => "檔案需要逐一下載。", "Back to Files" => "回到檔案列表", -"Selected files too large to generate zip file." => "選擇的檔案太大以致於無法產生壓縮檔", +"Selected files too large to generate zip file." => "選擇的檔案太大以致於無法產生壓縮檔。", "couldn't be determined" => "無法判斷", "Application is not enabled" => "應用程式未啟用", "Authentication error" => "認證錯誤", @@ -16,12 +16,25 @@ "Files" => "檔案", "Text" => "文字", "Images" => "圖片", -"Set an admin username." => "設置一個管理員用戶名。", -"Set an admin password." => "設置一個管理員密碼。", -"PostgreSQL username and/or password not valid" => "PostgreSQL用戶名和/或密碼無效", -"You need to enter either an existing account or the administrator." => "您必須輸入一個現有的賬戶或管理員", -"Oracle username and/or password not valid" => "Oracle用戶名和/或密碼無效", -"MySQL username and/or password not valid" => "MySQL用戶名和/或密碼無效", +"Set an admin username." => "設定管理員帳號。", +"Set an admin password." => "設定管理員密碼。", +"%s enter the database username." => "%s 輸入資料庫使用者名稱。", +"%s enter the database name." => "%s 輸入資料庫名稱。", +"%s you may not use dots in the database name" => "%s 資料庫名稱不能包含小數點", +"%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\"", +"MySQL user '%s'@'localhost' exists already." => "MySQL 使用者 '%s'@'localhost' 已經存在。", +"Drop this user from MySQL" => "在 MySQL 移除這個使用者", +"MySQL user '%s'@'%%' already exists" => "MySQL 使用者 '%s'@'%%' 已經存在", +"Drop this user from MySQL." => "在 MySQL 移除這個使用者。", +"Oracle username and/or password not valid" => "Oracle 用戶名和/或密碼無效", +"Offending command was: \"%s\", name: %s, password: %s" => "有問題的指令是:\"%s\" ,使用者:\"%s\",密碼:\"%s\"", +"MS SQL username and/or password not valid: %s" => "MS SQL 使用者和/或密碼無效:%s", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "您的網頁伺服器尚未被正確設定來進行檔案同步,因為您的 WebDAV 界面似乎無法使用。", "Please double check the <a href='%s'>installation guides</a>." => "請參考<a href='%s'>安裝指南</a>。", "seconds ago" => "幾秒前", @@ -36,8 +49,5 @@ "%d months ago" => "%d 個月之前", "last year" => "去年", "years ago" => "幾年前", -"%s is available. Get <a href=\"%s\">more information</a>" => "%s 已經可用。取得 <a href=\"%s\">更多資訊</a>", -"up to date" => "最新的", -"updates check is disabled" => "檢查更新已停用", "Could not find category \"%s\"" => "找不到分類:\"%s\"" ); diff --git a/lib/filesystem.php b/lib/legacy/filesystem.php index 34f92b357ca..34f92b357ca 100644 --- a/lib/filesystem.php +++ b/lib/legacy/filesystem.php diff --git a/lib/filesystemview.php b/lib/legacy/filesystemview.php index d6bca62e06a..d6bca62e06a 100644 --- a/lib/filesystemview.php +++ b/lib/legacy/filesystemview.php diff --git a/lib/log/owncloud.php b/lib/log/owncloud.php index 20df52c27bb..7a11a588330 100644 --- a/lib/log/owncloud.php +++ b/lib/log/owncloud.php @@ -49,7 +49,8 @@ class OC_Log_Owncloud { public static function write($app, $message, $level) { $minLevel=min(OC_Config::getValue( "loglevel", OC_Log::WARN ), OC_Log::ERROR); if($level>=$minLevel) { - $entry=array('app'=>$app, 'message'=>$message, 'level'=>$level, 'time'=>time()); + $time = date("F d, Y H:i:s", time()); + $entry=array('app'=>$app, 'message'=>$message, 'level'=>$level, 'time'=> $time); $handle = @fopen(self::$logFile, 'a'); if ($handle) { fwrite($handle, json_encode($entry)."\n"); diff --git a/lib/mail.php b/lib/mail.php index 61634632efc..e15af277a64 100644 --- a/lib/mail.php +++ b/lib/mail.php @@ -113,7 +113,7 @@ class OC_Mail { */ public static function getfooter() { - $txt="\n--\n"; + $txt="\n-- \n"; $txt.="ownCloud\n"; $txt.="Your Cloud, Your Data, Your Way!\n"; return($txt); diff --git a/lib/mimetypes.list.php b/lib/mimetypes.list.php index 86ce9c6c237..2aac3bbfd27 100644 --- a/lib/mimetypes.list.php +++ b/lib/mimetypes.list.php @@ -86,11 +86,11 @@ return array( 'vcf' => 'text/vcard', 'vcard' => 'text/vcard', 'doc'=>'application/msword', - 'docx'=>'application/msword', + 'docx'=>'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'xls'=>'application/msexcel', - 'xlsx'=>'application/msexcel', + 'xlsx'=>'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'ppt'=>'application/mspowerpoint', - 'pptx'=>'application/mspowerpoint', + 'pptx'=>'application/vnd.openxmlformats-officedocument.presentationml.presentation', 'sgf' => 'application/sgf', 'cdr' => 'application/coreldraw', 'impress' => 'text/impress', @@ -98,5 +98,9 @@ return array( 'epub' => 'application/epub+zip', 'mobi' => 'application/x-mobipocket-ebook', 'exe' => 'application', - 'msi' => 'application' + 'msi' => 'application', + 'md' => 'text/markdown', + 'markdown' => 'text/markdown', + 'mdown' => 'text/markdown', + 'mdwn' => 'text/markdown' ); diff --git a/lib/ocs/result.php b/lib/ocs/result.php index 8ab378d79c5..729c39056d9 100644 --- a/lib/ocs/result.php +++ b/lib/ocs/result.php @@ -22,7 +22,7 @@ class OC_OCS_Result{ - private $data, $message, $statusCode, $items, $perPage; + protected $data, $message, $statusCode, $items, $perPage; /** * create the OCS_Result object diff --git a/lib/public/backgroundjob.php b/lib/public/backgroundjob.php index 601046fe691..cc076a3a845 100644 --- a/lib/public/backgroundjob.php +++ b/lib/public/backgroundjob.php @@ -1,49 +1,46 @@ <?php /** -* ownCloud -* -* @author Jakob Sack -* @copyright 2012 Jakob Sack owncloud@jakobsack.de -* -* 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/>. -* -*/ + * ownCloud + * + * @author Jakob Sack + * @copyright 2012 Jakob Sack owncloud@jakobsack.de + * + * 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/>. + * + */ /** - * Public interface of ownCloud forbackground jobs. + * Public interface of ownCloud for background jobs. */ // use OCP namespace for all classes that are considered public. // This means that they should be used by apps instead of the internal ownCloud classes namespace OCP; +use \OC\BackgroundJob\JobList; + /** - * This class provides functions to manage backgroundjobs in ownCloud - * - * There are two kind of background jobs in ownCloud: regular tasks and - * queued tasks. + * This class provides functions to register backgroundjobs in ownCloud * - * Regular tasks have to be registered in appinfo.php and - * will run on a regular base. Fetching news could be a task that should run - * frequently. + * To create a new backgroundjob create a new class that inharits from either \OC\BackgroundJob\Job, + * \OC\BackgroundJob\QueuedJob or \OC\BackgroundJob\TimedJob and register it using + * \OCP\BackgroundJob->registerJob($job, $argument), $argument will be passed to the run() function + * of the job when the job is executed. * - * Queued tasks have to be registered each time you want to execute them. - * An example of the queued task would be the creation of the thumbnail. As - * soon as the user uploads a picture the gallery app registers the queued - * task "create thumbnail" and saves the path in the parameter instead of doing - * the work right away. This makes the app more responsive. As soon as the task - * is done it will be deleted from the list. + * A regular Job will be executed every time cron.php is run, a QueuedJob will only run once and a TimedJob + * will only run at a specific interval which is to be specified in the constructor of the job by calling + * $this->setInterval($interval) with $interval in seconds. */ class BackgroundJob { /** @@ -59,82 +56,136 @@ class BackgroundJob { /** * @brief sets the background jobs execution type - * @param $type execution type + * @param string $type execution type * @return boolean * * This method sets the execution type of the background jobs. Possible types * are "none", "ajax", "webcron", "cron" */ - public static function setExecutionType( $type ) { - return \OC_BackgroundJob::setExecutionType( $type ); + public static function setExecutionType($type) { + return \OC_BackgroundJob::setExecutionType($type); + } + + /** + * @param \OC\BackgroundJob\Job|string $job + * @param mixed $argument + */ + public static function registerJob($job, $argument = null) { + $jobList = new JobList(); + $jobList->add($job, $argument); } /** + * @deprecated * @brief creates a regular task - * @param $klass class name - * @param $method method name + * @param string $klass class name + * @param string $method method name * @return true */ - public static function addRegularTask( $klass, $method ) { - return \OC_BackgroundJob_RegularTask::register( $klass, $method ); + public static function addRegularTask($klass, $method) { + self::registerJob('OC\BackgroundJob\Legacy\RegularJob', array($klass, $method)); + return true; } /** + * @deprecated * @brief gets all regular tasks * @return associative array * * key is string "$klass-$method", value is array( $klass, $method ) */ static public function allRegularTasks() { - return \OC_BackgroundJob_RegularTask::all(); + $jobList = new JobList(); + $allJobs = $jobList->getAll(); + $regularJobs = array(); + foreach ($allJobs as $job) { + if ($job instanceof RegularLegacyJob) { + $key = implode('-', $job->getArgument()); + $regularJobs[$key] = $job->getArgument(); + } + } + return $regularJobs; } /** + * @deprecated * @brief Gets one queued task - * @param $id ID of the task + * @param int $id ID of the task * @return associative array */ - public static function findQueuedTask( $id ) { - return \OC_BackgroundJob_QueuedTask::find( $id ); + public static function findQueuedTask($id) { + $jobList = new JobList(); + return $jobList->getById($id); } /** + * @deprecated * @brief Gets all queued tasks * @return array with associative arrays */ public static function allQueuedTasks() { - return \OC_BackgroundJob_QueuedTask::all(); + $jobList = new JobList(); + $allJobs = $jobList->getAll(); + $queuedJobs = array(); + foreach ($allJobs as $job) { + if ($job instanceof QueuedLegacyJob) { + $queuedJob = $job->getArgument(); + $queuedJob['id'] = $job->getId(); + $queuedJobs[] = $queuedJob; + } + } + return $queuedJobs; } /** + * @deprecated * @brief Gets all queued tasks of a specific app - * @param $app app name + * @param string $app app name * @return array with associative arrays */ - public static function queuedTaskWhereAppIs( $app ) { - return \OC_BackgroundJob_QueuedTask::whereAppIs( $app ); + public static function queuedTaskWhereAppIs($app) { + $jobList = new JobList(); + $allJobs = $jobList->getAll(); + $queuedJobs = array(); + foreach ($allJobs as $job) { + if ($job instanceof QueuedLegacyJob) { + $queuedJob = $job->getArgument(); + $queuedJob['id'] = $job->getId(); + if ($queuedJob['app'] === $app) { + $queuedJobs[] = $queuedJob; + } + } + } + return $queuedJobs; } /** + * @deprecated * @brief queues a task - * @param $app app name - * @param $klass class name - * @param $method method name - * @param $parameters all useful data as text - * @return id of task + * @param string $app app name + * @param string $class class name + * @param string $method method name + * @param string $parameters all useful data as text + * @return int id of task */ - public static function addQueuedTask( $app, $klass, $method, $parameters ) { - return \OC_BackgroundJob_QueuedTask::add( $app, $klass, $method, $parameters ); + public static function addQueuedTask($app, $class, $method, $parameters) { + self::registerJob('OC\BackgroundJob\Legacy\QueuedJob', array('app' => $app, 'klass' => $class, 'method' => $method, 'parameters' => $parameters)); + return true; } /** + * @deprecated * @brief deletes a queued task - * @param $id id of task - * @return true/false + * @param int $id id of task + * @return bool * * Deletes a report */ - public static function deleteQueuedTask( $id ) { - return \OC_BackgroundJob_QueuedTask::delete( $id ); + public static function deleteQueuedTask($id) { + $jobList = new JobList(); + $job = $jobList->getById($id); + if ($job) { + $jobList->remove($job); + } } } diff --git a/lib/public/share.php b/lib/public/share.php index 4b337530be8..81f5515bb4b 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -106,6 +106,125 @@ class Share { } return false; } + + /** + * @brief Prepare a path to be passed to DB as file_target + * @return string Prepared path + */ + public static function prepFileTarget( $path ) { + + // Paths in DB are stored with leading slashes, so add one if necessary + if ( substr( $path, 0, 1 ) !== '/' ) { + + $path = '/' . $path; + + } + + return $path; + + } + + /** + * @brief Find which users can access a shared item + * @param $path to the file + * @param $user owner of the file + * @param include owner to the list of users with access to the file + * @return array + * @note $path needs to be relative to user data dir, e.g. 'file.txt' + * not '/admin/data/file.txt' + */ + public static function getUsersSharingFile($path, $user, $includeOwner = false) { + + $shares = array(); + $publicShare = false; + $source = -1; + $cache = false; + + $view = new \OC\Files\View('/' . $user . '/files/'); + $meta = $view->getFileInfo(\OC\Files\Filesystem::normalizePath($path)); + + if($meta !== false) { + $source = $meta['fileid']; + $cache = new \OC\Files\Cache\Cache($meta['storage']); + } + + while ($source !== -1) { + + // Fetch all shares of this file path from DB + $query = \OC_DB::prepare( + 'SELECT share_with + FROM + `*PREFIX*share` + WHERE + item_source = ? AND share_type = ?' + ); + + $result = $query->execute(array($source, self::SHARE_TYPE_USER)); + + if (\OCP\DB::isError($result)) { + \OCP\Util::writeLog('OCP\Share', \OC_DB::getErrorMessage($result), \OC_Log::ERROR); + } else { + while ($row = $result->fetchRow()) { + $shares[] = $row['share_with']; + } + } + // We also need to take group shares into account + + $query = \OC_DB::prepare( + 'SELECT share_with + FROM + `*PREFIX*share` + WHERE + item_source = ? AND share_type = ?' + ); + + $result = $query->execute(array($source, self::SHARE_TYPE_GROUP)); + + if (\OCP\DB::isError($result)) { + \OCP\Util::writeLog('OCP\Share', \OC_DB::getErrorMessage($result), \OC_Log::ERROR); + } else { + while ($row = $result->fetchRow()) { + $usersInGroup = \OC_Group::usersInGroup($row['share_with']); + $shares = array_merge($shares, $usersInGroup); + } + } + + //check for public link shares + if (!$publicShare) { + $query = \OC_DB::prepare( + 'SELECT share_with + FROM + `*PREFIX*share` + WHERE + item_source = ? AND share_type = ?' + ); + + $result = $query->execute(array($source, self::SHARE_TYPE_LINK)); + + if (\OCP\DB::isError($result)) { + \OCP\Util::writeLog('OCP\Share', \OC_DB::getErrorMessage($result), \OC_Log::ERROR); + } else { + if ($result->fetchRow()) { + $publicShare = true; + } + } + } + + // let's get the parent for the next round + $meta = $cache->get((int)$source); + if($meta !== false) { + $source = (int)$meta['parent']; + } else { + $source = -1; + } + } + // Include owner in list of users, if requested + if ($includeOwner) { + $shares[] = $user; + } + + return array("users" => array_unique($shares), "public" => $publicShare); + } /** * @brief Get the items of item type shared with the current user @@ -132,7 +251,7 @@ class Share { return self::getItems($itemType, $itemTarget, self::$shareTypeUserAndGroups, \OC_User::getUser(), null, $format, $parameters, 1, $includeCollections); } - + /** * @brief Get the item of item type shared with the current user by source * @param string Item type @@ -409,8 +528,16 @@ class Share { 'fileSource' => $item['file_source'], 'shareType' => $shareType, 'shareWith' => $shareWith, + 'itemParent' => $item['parent'], )); self::delete($item['id']); + \OC_Hook::emit('OCP\Share', 'post_unshare', array( + 'itemType' => $itemType, + 'itemSource' => $itemSource, + 'shareType' => $shareType, + 'shareWith' => $shareWith, + 'itemParent' => $item['parent'], + )); return true; } return false; @@ -433,6 +560,11 @@ class Share { foreach ($shares as $share) { self::delete($share['id']); } + \OC_Hook::emit('OCP\Share', 'post_unshareAll', array( + 'itemType' => $itemType, + 'itemSource' => $itemSource, + 'shares' => $shares + )); return true; } return false; @@ -875,7 +1007,10 @@ class Share { $row['path'] = '/Shared/'.basename($row['path']); } else { if (!isset($mounts[$row['storage']])) { - $mounts[$row['storage']] = \OC\Files\Mount::findByNumericId($row['storage']); + $mountPoints = \OC\Files\Filesystem::getMountByNumericId($row['storage']); + if (is_array($mountPoints)) { + $mounts[$row['storage']] = current($mountPoints); + } } if ($mounts[$row['storage']]) { $path = $mounts[$row['storage']]->getMountPoint().$row['path']; @@ -1086,6 +1221,17 @@ class Share { if ($shareType == self::SHARE_TYPE_GROUP) { $groupItemTarget = self::generateTarget($itemType, $itemSource, $shareType, $shareWith['group'], $uidOwner, $suggestedItemTarget); + \OC_Hook::emit('OCP\Share', 'pre_shared', array( + 'itemType' => $itemType, + 'itemSource' => $itemSource, + 'itemTarget' => $groupItemTarget, + 'shareType' => $shareType, + 'shareWith' => $shareWith['group'], + 'uidOwner' => $uidOwner, + 'permissions' => $permissions, + 'fileSource' => $fileSource, + 'token' => $token + )); if (isset($fileSource)) { if ($parentFolder) { if ($parentFolder === true) { @@ -1161,6 +1307,17 @@ class Share { } else { $itemTarget = self::generateTarget($itemType, $itemSource, $shareType, $shareWith, $uidOwner, $suggestedItemTarget); + \OC_Hook::emit('OCP\Share', 'pre_shared', array( + 'itemType' => $itemType, + 'itemSource' => $itemSource, + 'itemTarget' => $itemTarget, + 'shareType' => $shareType, + 'shareWith' => $shareWith, + 'uidOwner' => $uidOwner, + 'permissions' => $permissions, + 'fileSource' => $fileSource, + 'token' => $token + )); if (isset($fileSource)) { if ($parentFolder) { if ($parentFolder === true) { diff --git a/lib/request.php b/lib/request.php index 9f74cf9beb5..4d8380eb9ac 100755 --- a/lib/request.php +++ b/lib/request.php @@ -11,9 +11,10 @@ class OC_Request { * @brief Check overwrite condition * @returns true/false */ - private static function isOverwriteCondition() { + private static function isOverwriteCondition($type = '') { $regex = '/' . OC_Config::getValue('overwritecondaddr', '') . '/'; - return $regex === '//' or preg_match($regex, $_SERVER['REMOTE_ADDR']) === 1; + return $regex === '//' or preg_match($regex, $_SERVER['REMOTE_ADDR']) === 1 + or ($type !== 'protocol' and OC_Config::getValue('forcessl', false)); } /** @@ -27,7 +28,7 @@ class OC_Request { if(OC::$CLI) { return 'localhost'; } - if(OC_Config::getValue('overwritehost', '')<>'' and self::isOverwriteCondition()) { + if(OC_Config::getValue('overwritehost', '') !== '' and self::isOverwriteCondition()) { return OC_Config::getValue('overwritehost'); } if (isset($_SERVER['HTTP_X_FORWARDED_HOST'])) { @@ -52,7 +53,7 @@ class OC_Request { * Returns the server protocol. It respects reverse proxy servers and load balancers */ public static function serverProtocol() { - if(OC_Config::getValue('overwriteprotocol', '')<>'' and self::isOverwriteCondition()) { + if(OC_Config::getValue('overwriteprotocol', '') !== '' and self::isOverwriteCondition('protocol')) { return OC_Config::getValue('overwriteprotocol'); } if (isset($_SERVER['HTTP_X_FORWARDED_PROTO'])) { @@ -76,7 +77,7 @@ class OC_Request { */ public static function requestUri() { $uri = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : ''; - if (OC_Config::getValue('overwritewebroot', '') <> '' and self::isOverwriteCondition()) { + if (OC_Config::getValue('overwritewebroot', '') !== '' and self::isOverwriteCondition()) { $uri = self::scriptName() . substr($uri, strlen($_SERVER['SCRIPT_NAME'])); } return $uri; @@ -91,7 +92,7 @@ class OC_Request { */ public static function scriptName() { $name = $_SERVER['SCRIPT_NAME']; - if (OC_Config::getValue('overwritewebroot', '') <> '' and self::isOverwriteCondition()) { + if (OC_Config::getValue('overwritewebroot', '') !== '' and self::isOverwriteCondition()) { $serverroot = str_replace("\\", '/', substr(__DIR__, 0, -4)); $suburi = str_replace("\\", "/", substr(realpath($_SERVER["SCRIPT_FILENAME"]), strlen($serverroot))); $name = OC_Config::getValue('overwritewebroot', '') . $suburi; diff --git a/lib/session/internal.php b/lib/session/internal.php new file mode 100644 index 00000000000..60aecccc8aa --- /dev/null +++ b/lib/session/internal.php @@ -0,0 +1,39 @@ +<?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\Session; + +/** + * Class Internal + * + * wrap php's internal session handling into the Session interface + * + * @package OC\Session + */ +class Internal extends Memory { + public function __construct($name) { + session_name($name); + session_start(); + if (!isset($_SESSION)) { + throw new \Exception('Failed to start session'); + } + $this->data = $_SESSION; + } + + public function __destruct() { + $_SESSION = $this->data; + session_write_close(); + } + + public function clear() { + session_unset(); + @session_regenerate_id(true); + @session_start(); + $this->data = $_SESSION = array(); + } +} diff --git a/lib/session/memory.php b/lib/session/memory.php new file mode 100644 index 00000000000..c148ff4b9b9 --- /dev/null +++ b/lib/session/memory.php @@ -0,0 +1,63 @@ +<?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\Session; + +/** + * Class Internal + * + * store session data in an in-memory array, not persistance + * + * @package OC\Session + */ +class Memory extends Session { + protected $data; + + public function __construct($name) { + //no need to use $name since all data is already scoped to this instance + $this->data = array(); + } + + /** + * @param string $key + * @param mixed $value + */ + public function set($key, $value) { + $this->data[$key] = $value; + } + + /** + * @param string $key + * @return mixed + */ + public function get($key) { + if (!$this->exists($key)) { + return null; + } + return $this->data[$key]; + } + + /** + * @param string $key + * @return bool + */ + public function exists($key) { + return isset($this->data[$key]); + } + + /** + * @param string $key + */ + public function remove($key) { + unset($this->data[$key]); + } + + public function clear() { + $this->data = array(); + } +} diff --git a/lib/session/session.php b/lib/session/session.php new file mode 100644 index 00000000000..55515f57a87 --- /dev/null +++ b/lib/session/session.php @@ -0,0 +1,79 @@ +<?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\Session; + +abstract class Session implements \ArrayAccess { + /** + * $name serves as a namespace for the session keys + * + * @param string $name + */ + abstract public function __construct($name); + + /** + * @param string $key + * @param mixed $value + */ + abstract public function set($key, $value); + + /** + * @param string $key + * @return mixed should return null if $key does not exist + */ + abstract public function get($key); + + /** + * @param string $key + * @return bool + */ + abstract public function exists($key); + + /** + * should not throw any errors if $key does not exist + * + * @param string $key + */ + abstract public function remove($key); + + /** + * removes all entries within the cache namespace + */ + abstract public function clear(); + + /** + * @param mixed $offset + * @return bool + */ + public function offsetExists($offset) { + return $this->exists($offset); + } + + /** + * @param mixed $offset + * @return mixed + */ + public function offsetGet($offset) { + return $this->get($offset); + } + + /** + * @param mixed $offset + * @param mixed $value + */ + public function offsetSet($offset, $value) { + $this->set($offset, $value); + } + + /** + * @param mixed $offset + */ + public function offsetUnset($offset) { + $this->remove($offset); + } +} diff --git a/lib/setup.php b/lib/setup.php index 7082f0b2afd..a63cc664dbc 100644 --- a/lib/setup.php +++ b/lib/setup.php @@ -37,7 +37,7 @@ class OC_Setup { $error[] = $l->t('Set an admin password.'); } if(empty($options['directory'])) { - $error[] = $l->t('Specify a data folder.'); + $options['directory'] = OC::$SERVERROOT."/data"; } if($dbtype == 'mysql' or $dbtype == 'pgsql' or $dbtype == 'oci' or $dbtype == 'mssql') { //mysql and postgresql needs more config options @@ -152,8 +152,12 @@ class OC_Setup { self::setupOCIDatabase($dbhost, $dbuser, $dbpass, $dbname, $dbtableprefix, $dbtablespace, $username); } catch (Exception $e) { $error[] = array( - 'error' => $l->t('Oracle username and/or password not valid'), - 'hint' => $l->t('You need to enter either an existing account or the administrator.') + 'error' => $l->t('Oracle connection could not be established'), + 'hint' => $e->getMessage().' Check environment: ORACLE_HOME='.getenv('ORACLE_HOME') + .' ORACLE_SID='.getenv('ORACLE_SID') + .' LD_LIBRARY_PATH='.getenv('LD_LIBRARY_PATH') + .' NLS_LANG='.getenv('NLS_LANG') + .' tnsnames.ora is '.(is_readable(getenv('ORACLE_HOME').'/network/admin/tnsnames.ora')?'':'not ').'readable' ); return $error; } @@ -187,6 +191,7 @@ class OC_Setup { unlink("$datadir/owncloud.db"); } //in case of sqlite, we can always fill the database + error_log("creating sqlite db"); OC_DB::createDbFromStructure('db_structure.xml'); } @@ -195,7 +200,7 @@ class OC_Setup { OC_User::createUser($username, $password); } catch(Exception $exception) { - $error[] = $exception->getMessage(); + $error[] = 'Error while trying to create admin user: ' . $exception->getMessage(); } if(count($error) == 0) { @@ -451,9 +456,13 @@ class OC_Setup { } else { $easy_connect_string = '//'.$e_host.'/'.$e_dbname; } + \OC_Log::write('setup oracle', 'connect string: ' . $easy_connect_string, \OC_Log::DEBUG); $connection = @oci_connect($dbuser, $dbpass, $easy_connect_string); if(!$connection) { $e = oci_error(); + if (is_array ($e) && isset ($e['message'])) { + throw new Exception($e['message']); + } throw new Exception($l->t('Oracle username and/or password not valid')); } //check for roles creation rights in oracle @@ -810,6 +819,7 @@ class OC_Setup { $content.= "php_value upload_max_filesize 512M\n";//upload limit $content.= "php_value post_max_size 512M\n"; $content.= "php_value memory_limit 512M\n"; + $content.= "php_value mbstring.func_overload 0\n"; $content.= "<IfModule env_module>\n"; $content.= " SetEnv htaccessWorking true\n"; $content.= "</IfModule>\n"; @@ -827,6 +837,10 @@ class OC_Setup { $content.= "AddType image/svg+xml svg svgz\n"; $content.= "AddEncoding gzip svgz\n"; $content.= "</IfModule>\n"; + $content.= "<IfModule dir_module>\n"; + $content.= "DirectoryIndex index.php index.html\n"; + $content.= "</IfModule>\n"; + $content.= "AddDefaultCharset utf-8\n"; $content.= "Options -Indexes\n"; @file_put_contents(OC::$SERVERROOT.'/.htaccess', $content); //supress errors in case we don't have permissions for it diff --git a/lib/template.php b/lib/template.php index 434c1e9e990..9467dedb62a 100644 --- a/lib/template.php +++ b/lib/template.php @@ -186,10 +186,15 @@ class OC_Template{ $this->l10n = OC_L10N::get($parts[0]); // Some headers to enhance security - header('X-Frame-Options: Sameorigin'); // Disallow iFraming from other domains header('X-XSS-Protection: 1; mode=block'); // Enforce browser based XSS filters header('X-Content-Type-Options: nosniff'); // Disable sniffing the content type for IE + // iFrame Restriction Policy + $xFramePolicy = OC_Config::getValue('xframe_restriction', true); + if($xFramePolicy) { + header('X-Frame-Options: Sameorigin'); // Disallow iFraming from other domains + } + // Content Security Policy // If you change the standard policy, please also change it in config.sample.php $policy = OC_Config::getValue('custom_csp_policy', @@ -198,7 +203,8 @@ class OC_Template{ .'style-src \'self\' \'unsafe-inline\'; ' .'frame-src *; ' .'img-src *; ' - .'font-src \'self\' data:'); + .'font-src \'self\' data:; ' + .'media-src *'); header('Content-Security-Policy:'.$policy); // Standard $this->findTemplate($name); @@ -240,14 +246,14 @@ class OC_Template{ // if the formfactor is not yet autodetected do the // autodetection now. For possible formfactors check the // detectFormfactor documentation - if(!isset($_SESSION['formfactor'])) { - $_SESSION['formfactor'] = self::detectFormfactor(); + if (!\OC::$session->exists('formfactor')) { + \OC::$session->set('formfactor', self::detectFormfactor()); } // allow manual override via GET parameter if(isset($_GET['formfactor'])) { - $_SESSION['formfactor']=$_GET['formfactor']; + \OC::$session->set('formfactor', $_GET['formfactor']); } - $formfactor=$_SESSION['formfactor']; + $formfactor = \OC::$session->get('formfactor'); if($formfactor=='default') { $fext=''; }elseif($formfactor=='mobile') { @@ -272,7 +278,7 @@ class OC_Template{ protected function findTemplate($name) { // Read the selected theme from the config file - $theme=OC_Config::getValue( "theme" ); + $theme = OC_Util::getTheme(); // Read the detected formfactor and use the right file name. $fext = self::getFormFactorExtension(); diff --git a/lib/templatelayout.php b/lib/templatelayout.php index 73094232230..7115b8f0306 100644 --- a/lib/templatelayout.php +++ b/lib/templatelayout.php @@ -18,6 +18,20 @@ class OC_TemplateLayout extends OC_Template { $this->assign('bodyid', 'body-user'); } + // Update notification + if(OC_Config::getValue('updatechecker', true) === true) { + $data=OC_Updater::check(); + if(isset($data['version']) && $data['version'] != '' and $data['version'] !== Array() && OC_User::isAdminUser(OC_User::getUser())) { + $this->assign('updateAvailable', true); + $this->assign('updateVersion', $data['versionstring']); + $this->assign('updateLink', $data['web']); + } else { + $this->assign('updateAvailable', false); // No update available or not an admin user + } + } else { + $this->assign('updateAvailable', false); // Update check is disabled + } + // Add navigation entry $this->assign( 'application', '', false ); $navigation = OC_App::getNavigation(); @@ -42,7 +56,7 @@ class OC_TemplateLayout extends OC_Template { $jsfiles = self::findJavascriptFiles(OC_Util::$scripts); $this->assign('jsfiles', array(), false); if (OC_Config::getValue('installed', false) && $renderas!='error') { - $this->append( 'jsfiles', OC_Helper::linkToRoute('js_config')); + $this->append( 'jsfiles', OC_Helper::linkToRoute('js_config') . $versionParameter); } if (!empty(OC_Util::$core_scripts)) { $this->append( 'jsfiles', OC_Helper::linkToRemoteBase('core.js', false) . $versionParameter); @@ -64,25 +78,8 @@ class OC_TemplateLayout extends OC_Template { $root = $info[0]; $web = $info[1]; $file = $info[2]; - $paths = explode('/', $file); - $in_root = false; - foreach(OC::$APPSROOTS as $app_root) { - if($root == $app_root['path']) { - $in_root = true; - break; - } - } - - if($in_root ) { - $app = $paths[0]; - unset($paths[0]); - $path = implode('/', $paths); - $this->append( 'cssfiles', OC_Helper::linkTo($app, $path) . $versionParameter); - } - else { - $this->append( 'cssfiles', $web.'/'.$file); - } + $this->append( 'cssfiles', $web.'/'.$file . $versionParameter); } } @@ -103,7 +100,7 @@ class OC_TemplateLayout extends OC_Template { static public function findStylesheetFiles($styles) { // Read the selected theme from the config file - $theme=OC_Config::getValue( 'theme' ); + $theme = OC_Util::getTheme(); // Read the detected formfactor and use the right file name. $fext = self::getFormFactorExtension(); @@ -111,7 +108,8 @@ class OC_TemplateLayout extends OC_Template { $files = array(); foreach($styles as $style) { // is it in 3rdparty? - if(self::appendIfExist($files, OC::$THIRDPARTYROOT, OC::$THIRDPARTYWEBROOT, $style.'.css')) { + if(strpos($style, '3rdparty') === 0 && + self::appendIfExist($files, OC::$THIRDPARTYROOT, OC::$THIRDPARTYWEBROOT, $style.'.css')) { // or in the owncloud root? }elseif(self::appendIfExist($files, OC::$SERVERROOT, OC::$WEBROOT, "$style$fext.css" )) { @@ -122,20 +120,15 @@ class OC_TemplateLayout extends OC_Template { }elseif(self::appendIfExist($files, OC::$SERVERROOT, OC::$WEBROOT, "core/$style.css" )) { }else{ - $append = false; - // or in apps? - foreach( OC::$APPSROOTS as $apps_dir) - { - if(self::appendIfExist($files, $apps_dir['path'], $apps_dir['url'], "$style$fext.css")) { - $append = true; - break; - } - elseif(self::appendIfExist($files, $apps_dir['path'], $apps_dir['url'], "$style.css")) { - $append = true; - break; - } + $app = substr($style, 0, strpos($style, '/')); + $style = substr($style, strpos($style, '/')+1); + $app_path = OC_App::getAppPath($app); + $app_url = OC::$WEBROOT . '/index.php/apps/' . $app; + if(self::appendIfExist($files, $app_path, $app_url, "$style$fext.css")) { } - if(! $append) { + elseif(self::appendIfExist($files, $app_path, $app_url, "$style.css")) { + } + else { echo('css file not found: style:'.$style.' formfactor:'.$fext .' webroot:'.OC::$WEBROOT.' serverroot:'.OC::$SERVERROOT); die(); @@ -161,7 +154,7 @@ class OC_TemplateLayout extends OC_Template { static public function findJavascriptFiles($scripts) { // Read the selected theme from the config file - $theme=OC_Config::getValue( 'theme' ); + $theme = OC_Util::getTheme(); // Read the detected formfactor and use the right file name. $fext = self::getFormFactorExtension(); @@ -169,7 +162,8 @@ class OC_TemplateLayout extends OC_Template { $files = array(); foreach($scripts as $script) { // Is it in 3rd party? - if(self::appendIfExist($files, OC::$THIRDPARTYROOT, OC::$THIRDPARTYWEBROOT, $script.'.js')) { + if(strpos($script, '3rdparty') === 0 && + self::appendIfExist($files, OC::$THIRDPARTYROOT, OC::$THIRDPARTYWEBROOT, $script.'.js')) { // Is it in apps and overwritten by the theme? }elseif(self::appendIfExist($files, OC::$SERVERROOT, OC::$WEBROOT, "themes/$theme/apps/$script$fext.js" )) { @@ -193,18 +187,15 @@ class OC_TemplateLayout extends OC_Template { }else{ // Is it part of an app? - $append = false; - foreach( OC::$APPSROOTS as $apps_dir) { - if(self::appendIfExist($files, $apps_dir['path'], OC::$WEBROOT.$apps_dir['url'], "$script$fext.js")) { - $append = true; - break; - } - elseif(self::appendIfExist($files, $apps_dir['path'], OC::$WEBROOT.$apps_dir['url'], "$script.js")) { - $append = true; - break; - } + $app = substr($script, 0, strpos($script, '/')); + $script = substr($script, strpos($script, '/')+1); + $app_path = OC_App::getAppPath($app); + $app_url = OC_App::getAppWebPath($app); + if(self::appendIfExist($files, $app_path, $app_url, "$script$fext.js")) { + } + elseif(self::appendIfExist($files, $app_path, $app_url, "$script.js")) { } - if(! $append) { + else { echo('js file not found: script:'.$script.' formfactor:'.$fext .' webroot:'.OC::$WEBROOT.' serverroot:'.OC::$SERVERROOT); die(); diff --git a/lib/updater.php b/lib/updater.php index e7d33ac2bb9..9081bfc4be8 100644 --- a/lib/updater.php +++ b/lib/updater.php @@ -29,7 +29,14 @@ class OC_Updater{ * Check if a new version is available */ public static function check() { - OC_Appconfig::setValue('core', 'lastupdatedat', microtime(true)); + + // Look up the cache - it is invalidated all 30 minutes + if((OC_Appconfig::getValue('core', 'lastupdatedat') + 1800) > time()) { + return json_decode(OC_Appconfig::getValue('core', 'lastupdateResult'), true); + } + + OC_Appconfig::setValue('core', 'lastupdatedat', time()); + if(OC_Appconfig::getValue('core', 'installedat', '')=='') { OC_Appconfig::setValue('core', 'installedat', microtime(true)); } @@ -65,38 +72,9 @@ class OC_Updater{ $tmp['url'] = $data->url; $tmp['web'] = $data->web; - return $tmp; - } - - public static function ShowUpdatingHint() { - $l = OC_L10N::get('lib'); - - if(OC_Config::getValue('updatechecker', true)==true) { - $data=OC_Updater::check(); - if(isset($data['version']) and $data['version']<>'') { - $txt='<span style="color:#AA0000; font-weight:bold;">' - .$l->t('%s is available. Get <a href="%s">more information</a>', - array($data['versionstring'], $data['web'])).'</span>'; - }else{ - $txt=$l->t('up to date'); - } - }else{ - $txt=$l->t('updates check is disabled'); - } - return($txt); - } - - - /** - * do ownCloud update - */ - public static function doUpdate() { - - //update ownCloud core - - //update all apps - - //update version in config + // Cache the result + OC_Appconfig::setValue('core', 'lastupdateResult', json_encode($data)); + return $tmp; } -} +}
\ No newline at end of file diff --git a/lib/user.php b/lib/user.php index b19af940795..503ac3f7493 100644 --- a/lib/user.php +++ b/lib/user.php @@ -30,35 +30,85 @@ * post_createUser(uid, password) * pre_deleteUser(&run, uid) * post_deleteUser(uid) - * pre_setPassword(&run, uid, password) - * post_setPassword(uid, password) - * pre_login(&run, uid) + * pre_setPassword(&run, uid, password, recoveryPassword) + * post_setPassword(uid, password, recoveryPassword) + * pre_login(&run, uid, password) * post_login(uid) * logout() */ class OC_User { - // The backend used for user management - private static $_usedBackends = array(); + public static $userSession = null; + + private static function getUserSession() { + if (!self::$userSession) { + $manager = new \OC\User\Manager(); + self::$userSession = new \OC\User\Session($manager, \OC::$session); + self::$userSession->listen('\OC\User', 'preCreateUser', function ($uid, $password) { + \OC_Hook::emit('OC_User', 'pre_createUser', array('run' => true, 'uid' => $uid, 'password' => $password)); + }); + self::$userSession->listen('\OC\User', 'postCreateUser', function ($user, $password) { + /** @var $user \OC\User\User */ + \OC_Hook::emit('OC_User', 'post_createUser', array('uid' => $user->getUID(), 'password' => $password)); + }); + self::$userSession->listen('\OC\User', 'preDelete', function ($user) { + /** @var $user \OC\User\User */ + \OC_Hook::emit('OC_User', 'pre_deleteUser', array('run' => true, 'uid' => $user->getUID())); + }); + self::$userSession->listen('\OC\User', 'postDelete', function ($user) { + /** @var $user \OC\User\User */ + \OC_Hook::emit('OC_User', 'post_deleteUser', array('uid' => $user->getUID())); + }); + self::$userSession->listen('\OC\User', 'preSetPassword', function ($user, $password, $recoveryPassword) { + /** @var $user \OC\User\User */ + OC_Hook::emit('OC_User', 'pre_setPassword', array('run' => true, 'uid' => $user->getUID(), 'password' => $password, 'recoveryPassword' => $recoveryPassword)); + }); + self::$userSession->listen('\OC\User', 'postSetPassword', function ($user, $password, $recoveryPassword) { + /** @var $user \OC\User\User */ + OC_Hook::emit('OC_User', 'post_setPassword', array('run' => true, 'uid' => $user->getUID(), 'password' => $password, 'recoveryPassword' => $recoveryPassword)); + }); + self::$userSession->listen('\OC\User', 'preLogin', function ($uid, $password) { + \OC_Hook::emit('OC_User', 'pre_login', array('run' => true, 'uid' => $uid, 'password' => $password)); + }); + self::$userSession->listen('\OC\User', 'postLogin', function ($user, $password) { + /** @var $user \OC\User\User */ + \OC_Hook::emit('OC_User', 'post_login', array('run' => true, 'uid' => $user->getUID(), 'password' => $password)); + }); + self::$userSession->listen('\OC\User', 'logout', function () { + \OC_Hook::emit('OC_User', 'logout', array()); + }); + } + return self::$userSession; + } - private static $_setupedBackends = array(); + /** + * @return \OC\User\Manager + */ + private static function getManager() { + return self::getUserSession()->getManager(); + } - // Backends available (except database) private static $_backends = array(); + private static $_usedBackends = array(); + + private static $_setupedBackends = array(); + /** * @brief registers backend - * @param $name name of the backend - * @returns true/false + * @param string $backend name of the backend + * @deprecated Add classes by calling useBackend with a class instance instead + * @return bool * * Makes a list of backends that can be used by other modules */ - public static function registerBackend( $backend ) { + public static function registerBackend($backend) { self::$_backends[] = $backend; return true; } /** * @brief gets available backends + * @deprecated * @returns array of backends * * Returns the names of all backends. @@ -69,6 +119,7 @@ class OC_User { /** * @brief gets used backends + * @deprecated * @returns array of backends * * Returns the names of all used backends. @@ -79,33 +130,36 @@ class OC_User { /** * @brief Adds the backend to the list of used backends - * @param $backend default: database The backend to use for user managment - * @returns true/false + * @param string | OC_User_Backend $backend default: database The backend to use for user management + * @return bool * * Set the User Authentication Module */ - public static function useBackend( $backend = 'database' ) { - if($backend instanceof OC_User_Interface) { - OC_Log::write('core', 'Adding user backend instance of '.get_class($backend).'.', OC_Log::DEBUG); - self::$_usedBackends[get_class($backend)]=$backend; + public static function useBackend($backend = 'database') { + if ($backend instanceof OC_User_Interface) { + OC_Log::write('core', 'Adding user backend instance of ' . get_class($backend) . '.', OC_Log::DEBUG); + self::$_usedBackends[get_class($backend)] = $backend; + self::getManager()->registerBackend($backend); } else { // You'll never know what happens - if( null === $backend OR !is_string( $backend )) { + if (null === $backend OR !is_string($backend)) { $backend = 'database'; } // Load backend - switch( $backend ) { + switch ($backend) { case 'database': case 'mysql': case 'sqlite': - OC_Log::write('core', 'Adding user backend '.$backend.'.', OC_Log::DEBUG); + OC_Log::write('core', 'Adding user backend ' . $backend . '.', OC_Log::DEBUG); self::$_usedBackends[$backend] = new OC_User_Database(); + self::getManager()->registerBackend(self::$_usedBackends[$backend]); break; default: - OC_Log::write('core', 'Adding default user backend '.$backend.'.', OC_Log::DEBUG); + OC_Log::write('core', 'Adding default user backend ' . $backend . '.', OC_Log::DEBUG); $className = 'OC_USER_' . strToUpper($backend); self::$_usedBackends[$backend] = new $className(); + self::getManager()->registerBackend(self::$_usedBackends[$backend]); break; } } @@ -116,121 +170,73 @@ class OC_User { * remove all used backends */ public static function clearBackends() { - self::$_usedBackends=array(); + self::$_usedBackends = array(); + self::getManager()->clearBackends(); } /** * setup the configured backends in config.php */ public static function setupBackends() { - $backends=OC_Config::getValue('user_backends', array()); - foreach($backends as $i=>$config) { - $class=$config['class']; - $arguments=$config['arguments']; - if(class_exists($class)) { - if(array_search($i, self::$_setupedBackends)===false) { + $backends = OC_Config::getValue('user_backends', array()); + foreach ($backends as $i => $config) { + $class = $config['class']; + $arguments = $config['arguments']; + if (class_exists($class)) { + if (array_search($i, self::$_setupedBackends) === false) { // make a reflection object $reflectionObj = new ReflectionClass($class); // use Reflection to create a new instance, using the $args $backend = $reflectionObj->newInstanceArgs($arguments); self::useBackend($backend); - $_setupedBackends[]=$i; + $_setupedBackends[] = $i; } else { - OC_Log::write('core', 'User backend '.$class.' already initialized.', OC_Log::DEBUG); + OC_Log::write('core', 'User backend ' . $class . ' already initialized.', OC_Log::DEBUG); } } else { - OC_Log::write('core', 'User backend '.$class.' not found.', OC_Log::ERROR); + OC_Log::write('core', 'User backend ' . $class . ' not found.', OC_Log::ERROR); } } } /** * @brief Create a new user - * @param $uid The username of the user to create - * @param $password The password of the new user - * @returns true/false + * @param string $uid The username of the user to create + * @param string $password The password of the new user + * @throws Exception + * @return bool true/false * * Creates a new user. Basic checking of username is done in OC_User * itself, not in its subclasses. * * Allowed characters in the username are: "a-z", "A-Z", "0-9" and "_.@-" */ - public static function createUser( $uid, $password ) { - // Check the name for bad characters - // Allowed are: "a-z", "A-Z", "0-9" and "_.@-" - if( preg_match( '/[^a-zA-Z0-9 _\.@\-]/', $uid )) { - throw new Exception('Only the following characters are allowed in a username:' - .' "a-z", "A-Z", "0-9", and "_.@-"'); - } - // No empty username - if(trim($uid) == '') { - throw new Exception('A valid username must be provided'); - } - // No empty password - if(trim($password) == '') { - throw new Exception('A valid password must be provided'); - } - - // Check if user already exists - if( self::userExistsForCreation($uid) ) { - throw new Exception('The username is already being used'); - } - - - $run = true; - OC_Hook::emit( "OC_User", "pre_createUser", array( "run" => &$run, "uid" => $uid, "password" => $password )); - - if( $run ) { - //create the user in the first backend that supports creating users - foreach(self::$_usedBackends as $backend) { - if(!$backend->implementsActions(OC_USER_BACKEND_CREATE_USER)) - continue; - - $backend->createUser($uid, $password); - OC_Hook::emit( "OC_User", "post_createUser", array( "uid" => $uid, "password" => $password )); - - return self::userExists($uid); - } - } - return false; + public static function createUser($uid, $password) { + self::getManager()->createUser($uid, $password); } /** * @brief delete a user - * @param $uid The username of the user to delete - * @returns true/false + * @param string $uid The username of the user to delete + * @return bool * * Deletes a user */ - public static function deleteUser( $uid ) { - $run = true; - OC_Hook::emit( "OC_User", "pre_deleteUser", array( "run" => &$run, "uid" => $uid )); - - if( $run ) { - //delete the user from all backends - foreach(self::$_usedBackends as $backend) { - $backend->deleteUser($uid); - } - if (self::userExists($uid)) { - return false; - } + public static function deleteUser($uid) { + $user = self::getManager()->get($uid); + if ($user) { + $user->delete(); + // We have to delete the user from all groups - foreach( OC_Group::getUserGroups( $uid ) as $i ) { - OC_Group::removeFromGroup( $uid, $i ); + foreach (OC_Group::getUserGroups($uid) as $i) { + OC_Group::removeFromGroup($uid, $i); } // Delete the user's keys in preferences OC_Preferences::deleteUser($uid); // Delete user files in /data/ - OC_Helper::rmdirr(OC_Config::getValue( "datadirectory", OC::$SERVERROOT."/data" ) . '/'.$uid.'/'); - - // Emit and exit - OC_Hook::emit( "OC_User", "post_deleteUser", array( "uid" => $uid )); - return true; - } - else{ - return false; + OC_Helper::rmdirr(OC_Config::getValue('datadirectory', OC::$SERVERROOT . '/data') . '/' . $uid . '/'); } } @@ -238,75 +244,34 @@ class OC_User { * @brief Try to login a user * @param $uid The username of the user to log in * @param $password The password of the user - * @returns true/false + * @return bool * * Log in a user and regenerate a new session - if the password is ok */ - public static function login( $uid, $password ) { - $run = true; - OC_Hook::emit( "OC_User", "pre_login", array( "run" => &$run, "uid" => $uid )); - - if( $run ) { - $uid = self::checkPassword( $uid, $password ); - $enabled = self::isEnabled($uid); - if($uid && $enabled) { - session_regenerate_id(true); - self::setUserId($uid); - self::setDisplayName($uid); - OC_Hook::emit( "OC_User", "post_login", array( "uid" => $uid, 'password'=>$password )); - return true; - } - } - return false; + public static function login($uid, $password) { + return self::getUserSession()->login($uid, $password); } /** * @brief Sets user id for session and triggers emit */ public static function setUserId($uid) { - $_SESSION['user_id'] = $uid; + OC::$session->set('user_id', $uid); } /** * @brief Sets user display name for session */ public static function setDisplayName($uid, $displayName = null) { - $result = false; - if ($displayName ) { - foreach(self::$_usedBackends as $backend) { - if($backend->implementsActions(OC_USER_BACKEND_SET_DISPLAYNAME)) { - if($backend->userExists($uid)) { - $result |= $backend->setDisplayName($uid, $displayName); - } - } - } - } else { - $displayName = self::determineDisplayName($uid); - $result = true; + if (is_null($displayName)) { + $displayName = $uid; } - if (OC_User::getUser() === $uid) { - $_SESSION['display_name'] = $displayName; - } - return $result; - } - - - /** - * @brief get display name - * @param $uid The username - * @returns string display name or uid if no display name is defined - * - */ - private static function determineDisplayName( $uid ) { - foreach(self::$_usedBackends as $backend) { - if($backend->implementsActions(OC_USER_BACKEND_GET_DISPLAYNAME)) { - $result=$backend->getDisplayName( $uid ); - if($result) { - return $result; - } - } + $user = self::getManager()->get($uid); + if ($user) { + return $user->setDisplayName($displayName); + } else { + return false; } - return $uid; } /** @@ -315,36 +280,31 @@ class OC_User { * Logout, destroys session */ public static function logout() { - OC_Hook::emit( "OC_User", "logout", array()); - session_unset(); - session_destroy(); - OC_User::unsetMagicInCookie(); + self::getUserSession()->logout(); } /** * @brief Check if the user is logged in - * @returns true/false + * @returns bool * * Checks if the user is logged in */ public static function isLoggedIn() { - if( isset($_SESSION['user_id']) AND $_SESSION['user_id']) { + if (\OC::$session->get('user_id')) { OC_App::loadApps(array('authentication')); self::setupBackends(); - if (self::userExists($_SESSION['user_id']) ) { - return true; - } + return self::userExists(\OC::$session->get('user_id')); } return false; } /** * @brief Check if the user is an admin user - * @param $uid uid of the admin - * @returns bool + * @param string $uid uid of the admin + * @return bool */ public static function isAdminUser($uid) { - if(OC_Group::inGroup($uid, 'admin' )) { + if (OC_Group::inGroup($uid, 'admin')) { return true; } return false; @@ -356,32 +316,40 @@ class OC_User { * @return string uid or false */ public static function getUser() { - if( isset($_SESSION['user_id']) AND $_SESSION['user_id'] ) { - return $_SESSION['user_id']; - } - else{ + $uid = OC::$session->get('user_id'); + if (!is_null($uid)) { + return $uid; + } else { return false; } } /** * @brief get the display name of the user currently logged in. + * @param string $uid * @return string uid or false */ - public static function getDisplayName($user=null) { - if ( $user ) { - return self::determineDisplayName($user); - } else if( isset($_SESSION['display_name']) AND $_SESSION['display_name'] ) { - return $_SESSION['display_name']; - } - else{ - return false; + public static function getDisplayName($uid = null) { + if ($uid) { + $user = self::getManager()->get($uid); + if ($user) { + return $user->getDisplayName(); + } else { + return $uid; + } + } else { + $user = self::getUserSession()->getUser(); + if ($user) { + return $user->getDisplayName(); + } else { + return false; + } } } /** * @brief Autogenerate a password - * @returns string + * @return string * * generates a password */ @@ -391,111 +359,89 @@ class OC_User { /** * @brief Set password - * @param $uid The username - * @param $password The new password - * @returns true/false + * @param string $uid The username + * @param string $password The new password + * @param string $recoveryPassword for the encryption app to reset encryption keys + * @return bool * * Change the password of a user */ - public static function setPassword( $uid, $password ) { - $run = true; - OC_Hook::emit( "OC_User", "pre_setPassword", array( "run" => &$run, "uid" => $uid, "password" => $password )); - - if( $run ) { - $success = false; - foreach(self::$_usedBackends as $backend) { - if($backend->implementsActions(OC_USER_BACKEND_SET_PASSWORD)) { - if($backend->userExists($uid)) { - $success |= $backend->setPassword($uid, $password); - } - } - } - // invalidate all login cookies - OC_Preferences::deleteApp($uid, 'login_token'); - OC_Hook::emit( "OC_User", "post_setPassword", array( "uid" => $uid, "password" => $password )); - return $success; - } - else{ + public static function setPassword($uid, $password, $recoveryPassword = null) { + $user = self::getManager()->get($uid); + if ($user) { + return $user->setPassword($password, $recoveryPassword); + } else { return false; } } /** * @brief Check whether user can change his password - * @param $uid The username - * @returns true/false + * @param string $uid The username + * @return bool * * Check whether a specified user can change his password */ public static function canUserChangePassword($uid) { - foreach(self::$_usedBackends as $backend) { - if($backend->implementsActions(OC_USER_BACKEND_SET_PASSWORD)) { - if($backend->userExists($uid)) { - return true; - } - } + $user = self::getManager()->get($uid); + if ($user) { + return $user->canChangePassword(); + } else { + return false; } - return false; } /** * @brief Check whether user can change his display name - * @param $uid The username - * @returns true/false + * @param string $uid The username + * @return bool * * Check whether a specified user can change his display name */ public static function canUserChangeDisplayName($uid) { - if (OC_Config::getValue('allow_user_to_change_display_name', true)) { - foreach(self::$_usedBackends as $backend) { - if($backend->implementsActions(OC_USER_BACKEND_SET_DISPLAYNAME)) { - if($backend->userExists($uid)) { - return true; - } - } - } + $user = self::getManager()->get($uid); + if ($user) { + return $user->canChangeDisplayName(); + } else { + return false; } - return false; } /** * @brief Check if the password is correct - * @param $uid The username - * @param $password The password - * @returns string + * @param string $uid The username + * @param string $password The password + * @return bool * * Check if the password is correct without logging in the user * returns the user id or false */ - public static function checkPassword( $uid, $password ) { - foreach(self::$_usedBackends as $backend) { - if($backend->implementsActions(OC_USER_BACKEND_CHECK_PASSWORD)) { - $result=$backend->checkPassword( $uid, $password ); - if($result) { - return $result; - } + public static function checkPassword($uid, $password) { + $user = self::getManager()->get($uid); + if ($user) { + if ($user->checkPassword($password)) { + return $user->getUID(); + } else { + return false; } + } else { + return false; } } /** - * @brief Check if the password is correct * @param string $uid The username - * @param string $password The password - * @returns string + * @return string * * returns the path to the users home directory */ public static function getHome($uid) { - foreach(self::$_usedBackends as $backend) { - if($backend->implementsActions(OC_USER_BACKEND_GET_HOME) && $backend->userExists($uid)) { - $result=$backend->getHome($uid); - if($result) { - return $result; - } - } + $user = self::getManager()->get($uid); + if ($user) { + return $user->getHome(); + } else { + return OC_Config::getValue('datadirectory', OC::$SERVERROOT . '/data') . '/' . $uid; } - return OC_Config::getValue( "datadirectory", OC::$SERVERROOT."/data" ) . '/' . $uid; } /** @@ -505,148 +451,93 @@ class OC_User { * Get a list of all users. */ public static function getUsers($search = '', $limit = null, $offset = null) { - $users = array(); - foreach (self::$_usedBackends as $backend) { - $backendUsers = $backend->getUsers($search, $limit, $offset); - if (is_array($backendUsers)) { - $users = array_merge($users, $backendUsers); - } + $users = self::getManager()->search($search, $limit, $offset); + $uids = array(); + foreach ($users as $user) { + $uids[] = $user->getUID(); } - asort($users); - return $users; + return $uids; } /** * @brief Get a list of all users display name - * @returns associative array with all display names (value) and corresponding uids (key) + * @param string $search + * @param int $limit + * @param int $offset + * @return array associative array with all display names (value) and corresponding uids (key) * * Get a list of all display names and user ids. */ public static function getDisplayNames($search = '', $limit = null, $offset = null) { $displayNames = array(); - foreach (self::$_usedBackends as $backend) { - $backendDisplayNames = $backend->getDisplayNames($search, $limit, $offset); - if (is_array($backendDisplayNames)) { - $displayNames = array_merge($displayNames, $backendDisplayNames); - } + $users = self::getManager()->searchDisplayName($search, $limit, $offset); + foreach ($users as $user) { + $displayNames[$user->getUID()] = $user->getDisplayName(); } - asort($displayNames); return $displayNames; } /** * @brief check if a user exists * @param string $uid the username - * @param string $excludingBackend (default none) * @return boolean */ - public static function userExists($uid, $excludingBackend=null) { - foreach(self::$_usedBackends as $backend) { - if (!is_null($excludingBackend) && !strcmp(get_class($backend), $excludingBackend)) { - OC_Log::write('OC_User', $excludingBackend . 'excluded from user existance check.', OC_Log::DEBUG); - continue; - } - $result=$backend->userExists($uid); - if($result===true) { - return true; - } - } - return false; + public static function userExists($uid) { + return self::getManager()->userExists($uid); } - public static function userExistsForCreation($uid) { - foreach(self::$_usedBackends as $backend) { - if(!$backend->hasUserListings()) - continue; - - $result=$backend->userExists($uid); - if($result===true) { - return true; - } - } - return false; - } - /** * disables a user - * @param string $userid the user to disable + * + * @param string $uid the user to disable */ - public static function disableUser($userid) { - $sql = "INSERT INTO `*PREFIX*preferences` (`userid`, `appid`, `configkey`, `configvalue`) VALUES(?, ?, ?, ?)"; - $stmt = OC_DB::prepare($sql); - if ( ! OC_DB::isError($stmt) ) { - $result = $stmt->execute(array($userid, 'core', 'enabled', 'false')); - if ( OC_DB::isError($result) ) { - OC_Log::write('OC_User', 'could not enable user: '. OC_DB::getErrorMessage($result), OC_Log::ERROR); - } - } else { - OC_Log::write('OC_User', 'could not disable user: '. OC_DB::getErrorMessage($stmt), OC_Log::ERROR); + public static function disableUser($uid) { + $user = self::getManager()->get($uid); + if ($user) { + $user->setEnabled(false); } } /** * enable a user - * @param string $userid + * + * @param string $uid */ - public static function enableUser($userid) { - $sql = 'DELETE FROM `*PREFIX*preferences`' - ." WHERE `userid` = ? AND `appid` = ? AND `configkey` = ? AND `configvalue` = ?"; - $stmt = OC_DB::prepare($sql); - if ( ! OC_DB::isError($stmt) ) { - $result = $stmt->execute(array($userid, 'core', 'enabled', 'false')); - if ( OC_DB::isError($result) ) { - OC_Log::write('OC_User', 'could not enable user: '. OC_DB::getErrorMessage($result), OC_Log::ERROR); - } - } else { - OC_Log::write('OC_User', 'could not enable user: '. OC_DB::getErrorMessage($stmt), OC_Log::ERROR); + public static function enableUser($uid) { + $user = self::getManager()->get($uid); + if ($user) { + $user->setEnabled(true); } } /** * checks if a user is enabled - * @param string $userid + * + * @param string $uid * @return bool */ - public static function isEnabled($userid) { - $sql = 'SELECT `userid` FROM `*PREFIX*preferences`' - .' WHERE `userid` = ? AND `appid` = ? AND `configkey` = ? AND `configvalue` = ?'; - $stmt = OC_DB::prepare($sql); - if ( ! OC_DB::isError($stmt) ) { - $result = $stmt->execute(array($userid, 'core', 'enabled', 'false')); - if ( ! OC_DB::isError($result) ) { - return $result->numRows() ? false : true; - } else { - OC_Log::write('OC_User', - 'could not check if enabled: '. OC_DB::getErrorMessage($result), - OC_Log::ERROR); - } + public static function isEnabled($uid) { + $user = self::getManager()->get($uid); + if ($user) { + return $user->isEnabled(); } else { - OC_Log::write('OC_User', 'could not check if enabled: '. OC_DB::getErrorMessage($stmt), OC_Log::ERROR); + return false; } - return false; } /** * @brief Set cookie value to use in next page load * @param string $username username to be set + * @param string $token */ public static function setMagicInCookie($username, $token) { - $secure_cookie = OC_Config::getValue("forcessl", false); - $expires = time() + OC_Config::getValue('remember_login_cookie_lifetime', 60*60*24*15); - setcookie("oc_username", $username, $expires, OC::$WEBROOT, '', $secure_cookie); - setcookie("oc_token", $token, $expires, OC::$WEBROOT, '', $secure_cookie, true); - setcookie("oc_remember_login", true, $expires, OC::$WEBROOT, '', $secure_cookie); + self::getUserSession()->setMagicInCookie($username, $token); } /** * @brief Remove cookie for "remember username" */ public static function unsetMagicInCookie() { - unset($_COOKIE["oc_username"]); - unset($_COOKIE["oc_token"]); - unset($_COOKIE["oc_remember_login"]); - setcookie("oc_username", null, -1); - setcookie("oc_token", null, -1); - setcookie("oc_remember_login", null, -1); + self::getUserSession()->unsetMagicInCookie(); } } diff --git a/lib/user/backend.php b/lib/user/backend.php index 93e8f17ca98..e9be08e429c 100644 --- a/lib/user/backend.php +++ b/lib/user/backend.php @@ -58,7 +58,7 @@ abstract class OC_User_Backend implements OC_User_Interface { /** * @brief Get all supported actions - * @returns bitwise-or'ed actions + * @return int bitwise-or'ed actions * * Returns the supported actions as int to be * compared with OC_USER_BACKEND_CREATE_USER etc. @@ -76,8 +76,8 @@ abstract class OC_User_Backend implements OC_User_Interface { /** * @brief Check if backend implements actions - * @param $actions bitwise-or'ed actions - * @returns boolean + * @param int $actions bitwise-or'ed actions + * @return boolean * * Returns the supported actions as int to be * compared with OC_USER_BACKEND_CREATE_USER etc. @@ -87,12 +87,12 @@ abstract class OC_User_Backend implements OC_User_Interface { } /** - * @brief delete a user - * @param $uid The username of the user to delete - * @returns true/false - * - * Deletes a user - */ + * @brief delete a user + * @param string $uid The username of the user to delete + * @return bool + * + * Deletes a user + */ public function deleteUser( $uid ) { return false; } @@ -127,8 +127,8 @@ abstract class OC_User_Backend implements OC_User_Interface { /** * @brief get display name of the user - * @param $uid user ID of the user - * @return display name + * @param string $uid user ID of the user + * @return string display name */ public function getDisplayName($uid) { return $uid; diff --git a/lib/user/database.php b/lib/user/database.php index 210c7f3e1eb..d70b620f2ab 100644 --- a/lib/user/database.php +++ b/lib/user/database.php @@ -46,7 +46,7 @@ class OC_User_Database extends OC_User_Backend { private function getHasher() { if(!self::$hasher) { - //we don't want to use DES based crypt(), since it doesn't return a has with a recognisable prefix + //we don't want to use DES based crypt(), since it doesn't return a hash with a recognisable prefix $forcePortable=(CRYPT_BLOWFISH!=1); self::$hasher=new PasswordHash(8, $forcePortable); } @@ -136,7 +136,7 @@ class OC_User_Database extends OC_User_Backend { */ public function getDisplayName($uid) { if( $this->userExists($uid) ) { - $query = OC_DB::prepare( 'SELECT displayname FROM `*PREFIX*users` WHERE `uid` = ?' ); + $query = OC_DB::prepare( 'SELECT `displayname` FROM `*PREFIX*users` WHERE `uid` = ?' ); $result = $query->execute( array( $uid ))->fetchAll(); $displayName = trim($result[0]['displayname'], ' '); if ( !empty($displayName) ) { @@ -237,13 +237,13 @@ class OC_User_Database extends OC_User_Backend { * @return boolean */ public function userExists($uid) { - $query = OC_DB::prepare( 'SELECT * FROM `*PREFIX*users` WHERE LOWER(`uid`) = LOWER(?)' ); + $query = OC_DB::prepare( 'SELECT COUNT(*) FROM `*PREFIX*users` WHERE LOWER(`uid`) = LOWER(?)' ); $result = $query->execute( array( $uid )); if (OC_DB::isError($result)) { OC_Log::write('core', OC_DB::getErrorMessage($result), OC_Log::ERROR); return false; } - return $result->numRows() > 0; + return $result->fetchOne() > 0; } /** diff --git a/lib/user/dummy.php b/lib/user/dummy.php index d63f60efbeb..b5b7a6c3c7a 100644 --- a/lib/user/dummy.php +++ b/lib/user/dummy.php @@ -1,114 +1,118 @@ <?php /** -* ownCloud -* -* @author Frank Karlitschek -* @copyright 2012 Frank Karlitschek frank@owncloud.org -* -* 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/>. -* -*/ + * ownCloud + * + * @author Frank Karlitschek + * @copyright 2012 Frank Karlitschek frank@owncloud.org + * + * 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/>. + * + */ /** * dummy user backend, does not keep state, only for testing use */ class OC_User_Dummy extends OC_User_Backend { - private $users=array(); + private $users = array(); + /** - * @brief Create a new user - * @param $uid The username of the user to create - * @param $password The password of the new user - * @returns true/false - * - * Creates a new user. Basic checking of username is done in OC_User - * itself, not in its subclasses. - */ + * @brief Create a new user + * @param string $uid The username of the user to create + * @param string $password The password of the new user + * @return bool + * + * Creates a new user. Basic checking of username is done in OC_User + * itself, not in its subclasses. + */ public function createUser($uid, $password) { - if(isset($this->users[$uid])) { + if (isset($this->users[$uid])) { return false; - }else{ - $this->users[$uid]=$password; + } else { + $this->users[$uid] = $password; return true; } } /** - * @brief delete a user - * @param $uid The username of the user to delete - * @returns true/false - * - * Deletes a user - */ - public function deleteUser( $uid ) { - if(isset($this->users[$uid])) { + * @brief delete a user + * @param string $uid The username of the user to delete + * @return bool + * + * Deletes a user + */ + public function deleteUser($uid) { + if (isset($this->users[$uid])) { unset($this->users[$uid]); return true; - }else{ + } else { return false; } } /** - * @brief Set password - * @param $uid The username - * @param $password The new password - * @returns true/false - * - * Change the password of a user - */ + * @brief Set password + * @param string $uid The username + * @param string $password The new password + * @return bool + * + * Change the password of a user + */ public function setPassword($uid, $password) { - if(isset($this->users[$uid])) { - $this->users[$uid]=$password; + if (isset($this->users[$uid])) { + $this->users[$uid] = $password; return true; - }else{ + } else { return false; } } /** - * @brief Check if the password is correct - * @param $uid The username - * @param $password The password - * @returns string - * - * Check if the password is correct without logging in the user - * returns the user id or false - */ + * @brief Check if the password is correct + * @param string $uid The username + * @param string $password The password + * @return string + * + * Check if the password is correct without logging in the user + * returns the user id or false + */ public function checkPassword($uid, $password) { - if(isset($this->users[$uid])) { - return ($this->users[$uid]==$password); - }else{ + if (isset($this->users[$uid])) { + return ($this->users[$uid] == $password); + } else { return false; } } /** - * @brief Get a list of all users - * @returns array with all uids - * - * Get a list of all users. - */ + * @brief Get a list of all users + * @param string $search + * @param int $limit + * @param int $offset + * @return array with all uids + * + * Get a list of all users. + */ public function getUsers($search = '', $limit = null, $offset = null) { return array_keys($this->users); } /** - * @brief check if a user exists - * @param string $uid the username - * @return boolean - */ + * @brief check if a user exists + * @param string $uid the username + * @return boolean + */ public function userExists($uid) { return isset($this->users[$uid]); } diff --git a/lib/user/manager.php b/lib/user/manager.php new file mode 100644 index 00000000000..d17cdf1a200 --- /dev/null +++ b/lib/user/manager.php @@ -0,0 +1,228 @@ +<?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\User; + +use OC\Hooks\PublicEmitter; + +/** + * Class Manager + * + * Hooks available in scope \OC\User: + * - preSetPassword(\OC\User\User $user, string $password, string $recoverPassword) + * - postSetPassword(\OC\User\User $user, string $password, string $recoverPassword) + * - preDelete(\OC\User\User $user) + * - postDelete(\OC\User\User $user) + * - preCreateUser(string $uid, string $password) + * - postCreateUser(\OC\User\User $user, string $password) + * + * @package OC\User + */ +class Manager extends PublicEmitter { + /** + * @var \OC_User_Backend[] $backends + */ + private $backends = array(); + + private $cachedUsers = array(); + + public function __construct() { + $cachedUsers = $this->cachedUsers; + $this->listen('\OC\User', 'postDelete', function ($user) use (&$cachedUsers) { + $i = array_search($user, $cachedUsers); + if ($i !== false) { + unset($cachedUsers[$i]); + } + }); + } + + /** + * register a user backend + * + * @param \OC_User_Backend $backend + */ + public function registerBackend($backend) { + $this->backends[] = $backend; + } + + /** + * remove a user backend + * + * @param \OC_User_Backend $backend + */ + public function removeBackend($backend) { + $this->cachedUsers = array(); + if (($i = array_search($backend, $this->backends)) !== false) { + unset($this->backends[$i]); + } + } + + /** + * remove all user backends + */ + public function clearBackends() { + $this->cachedUsers = array(); + $this->backends = array(); + } + + /** + * get a user by user id + * + * @param string $uid + * @return \OC\User\User + */ + public function get($uid) { + if (isset($this->cachedUsers[$uid])) { //check the cache first to prevent having to loop over the backends + return $this->cachedUsers[$uid]; + } + foreach ($this->backends as $backend) { + if ($backend->userExists($uid)) { + return $this->getUserObject($uid, $backend); + } + } + return null; + } + + /** + * get or construct the user object + * + * @param string $uid + * @param \OC_User_Backend $backend + * @return \OC\User\User + */ + protected function getUserObject($uid, $backend) { + if (isset($this->cachedUsers[$uid])) { + return $this->cachedUsers[$uid]; + } + $this->cachedUsers[$uid] = new User($uid, $backend, $this); + return $this->cachedUsers[$uid]; + } + + /** + * check if a user exists + * + * @param string $uid + * @return bool + */ + public function userExists($uid) { + $user = $this->get($uid); + return ($user !== null); + } + + /** + * search by user id + * + * @param string $pattern + * @param int $limit + * @param int $offset + * @return \OC\User\User[] + */ + public function search($pattern, $limit = null, $offset = null) { + $users = array(); + foreach ($this->backends as $backend) { + $backendUsers = $backend->getUsers($pattern, $limit, $offset); + if (is_array($backendUsers)) { + foreach ($backendUsers as $uid) { + $users[] = $this->getUserObject($uid, $backend); + if (!is_null($limit)) { + $limit--; + } + if (!is_null($offset) and $offset > 0) { + $offset--; + } + + } + } + } + + usort($users, function ($a, $b) { + /** + * @var \OC\User\User $a + * @var \OC\User\User $b + */ + return strcmp($a->getUID(), $b->getUID()); + }); + return $users; + } + + /** + * search by displayName + * + * @param string $pattern + * @param int $limit + * @param int $offset + * @return \OC\User\User[] + */ + public function searchDisplayName($pattern, $limit = null, $offset = null) { + $users = array(); + foreach ($this->backends as $backend) { + $backendUsers = $backend->getDisplayNames($pattern, $limit, $offset); + if (is_array($backendUsers)) { + foreach ($backendUsers as $uid => $displayName) { + $users[] = $this->getUserObject($uid, $backend); + if (!is_null($limit)) { + $limit--; + } + if (!is_null($offset) and $offset > 0) { + $offset--; + } + + } + } + } + + usort($users, function ($a, $b) { + /** + * @var \OC\User\User $a + * @var \OC\User\User $b + */ + return strcmp($a->getDisplayName(), $b->getDisplayName()); + }); + return $users; + } + + /** + * @param string $uid + * @param string $password + * @throws \Exception + * @return bool | \OC\User\User the created user of false + */ + public function createUser($uid, $password) { + // Check the name for bad characters + // Allowed are: "a-z", "A-Z", "0-9" and "_.@-" + if (preg_match('/[^a-zA-Z0-9 _\.@\-]/', $uid)) { + throw new \Exception('Only the following characters are allowed in a username:' + . ' "a-z", "A-Z", "0-9", and "_.@-"'); + } + // No empty username + if (trim($uid) == '') { + throw new \Exception('A valid username must be provided'); + } + // No empty password + if (trim($password) == '') { + throw new \Exception('A valid password must be provided'); + } + + // Check if user already exists + if ($this->userExists($uid)) { + throw new \Exception('The username is already being used'); + } + + $this->emit('\OC\User', 'preCreateUser', array($uid, $password)); + foreach ($this->backends as $backend) { + if ($backend->implementsActions(\OC_USER_BACKEND_CREATE_USER)) { + $backend->createUser($uid, $password); + $user = $this->getUserObject($uid, $backend); + $this->emit('\OC\User', 'postCreateUser', array($user, $password)); + return $user; + } + } + return false; + } +} diff --git a/lib/user/session.php b/lib/user/session.php new file mode 100644 index 00000000000..cf93d9593af --- /dev/null +++ b/lib/user/session.php @@ -0,0 +1,173 @@ +<?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\User; + +use OC\Hooks\Emitter; + +/** + * Class Session + * + * Hooks available in scope \OC\User: + * - preSetPassword(\OC\User\User $user, string $password, string $recoverPassword) + * - postSetPassword(\OC\User\User $user, string $password, string $recoverPassword) + * - preDelete(\OC\User\User $user) + * - postDelete(\OC\User\User $user) + * - preCreateUser(string $uid, string $password) + * - postCreateUser(\OC\User\User $user) + * - preLogin(string $user, string $password) + * - postLogin(\OC\User\User $user) + * - logout() + * + * @package OC\User + */ +class Session implements Emitter { + /** + * @var \OC\User\Manager $manager + */ + private $manager; + + /** + * @var \OC\Session\Session $session + */ + private $session; + + /** + * @var \OC\User\User $activeUser + */ + protected $activeUser; + + /** + * @param \OC\User\Manager $manager + * @param \OC\Session\Session $session + */ + public function __construct($manager, $session) { + $this->manager = $manager; + $this->session = $session; + } + + /** + * @param string $scope + * @param string $method + * @param callable $callback + */ + public function listen($scope, $method, $callback) { + $this->manager->listen($scope, $method, $callback); + } + + /** + * @param string $scope optional + * @param string $method optional + * @param callable $callback optional + */ + public function removeListener($scope = null, $method = null, $callback = null) { + $this->manager->removeListener($scope, $method, $callback); + } + + /** + * get the manager object + * + * @return \OC\User\Manager + */ + public function getManager() { + return $this->manager; + } + + /** + * set the currently active user + * + * @param \OC\User\User $user + */ + public function setUser($user) { + if (is_null($user)) { + $this->session->remove('user_id'); + } else { + $this->session->set('user_id', $user->getUID()); + } + $this->activeUser = $user; + } + + /** + * get the current active user + * + * @return \OC\User\User + */ + public function getUser() { + if ($this->activeUser) { + return $this->activeUser; + } else { + $uid = $this->session->get('user_id'); + if ($uid) { + $this->activeUser = $this->manager->get($uid); + return $this->activeUser; + } else { + return null; + } + } + } + + /** + * try to login with the provided credentials + * + * @param string $uid + * @param string $password + * @return bool + */ + public function login($uid, $password) { + $this->manager->emit('\OC\User', 'preLogin', array($uid, $password)); + $user = $this->manager->get($uid); + if ($user) { + $result = $user->checkPassword($password); + if ($result and $user->isEnabled()) { + $this->setUser($user); + $this->manager->emit('\OC\User', 'postLogin', array($user, $password)); + return true; + } else { + return false; + } + } else { + return false; + } + } + + /** + * logout the user from the session + */ + public function logout() { + $this->manager->emit('\OC\User', 'logout'); + $this->setUser(null); + $this->unsetMagicInCookie(); + } + + /** + * Set cookie value to use in next page load + * + * @param string $username username to be set + * @param string $token + */ + public function setMagicInCookie($username, $token) { + $secure_cookie = \OC_Config::getValue("forcessl", false); //TODO: DI for cookies and OC_Config + $expires = time() + \OC_Config::getValue('remember_login_cookie_lifetime', 60 * 60 * 24 * 15); + setcookie("oc_username", $username, $expires, \OC::$WEBROOT, '', $secure_cookie); + setcookie("oc_token", $token, $expires, \OC::$WEBROOT, '', $secure_cookie, true); + setcookie("oc_remember_login", true, $expires, \OC::$WEBROOT, '', $secure_cookie); + } + + /** + * Remove cookie for "remember username" + */ + public function unsetMagicInCookie() { + unset($_COOKIE["oc_username"]); //TODO: DI + unset($_COOKIE["oc_token"]); + unset($_COOKIE["oc_remember_login"]); + setcookie("oc_username", null, -1); + setcookie("oc_token", null, -1); + setcookie("oc_remember_login", null, -1); + } +} diff --git a/lib/user/user.php b/lib/user/user.php new file mode 100644 index 00000000000..f9466b71499 --- /dev/null +++ b/lib/user/user.php @@ -0,0 +1,197 @@ +<?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\User; + +use OC\Hooks\Emitter; + +class User { + /** + * @var string $uid + */ + private $uid; + + /** + * @var string $displayName + */ + private $displayName; + + /** + * @var \OC_User_Backend $backend + */ + private $backend; + + /** + * @var bool $enabled + */ + private $enabled; + + /** + * @var Emitter | Manager $emitter + */ + private $emitter; + + /** + * @param string $uid + * @param \OC_User_Backend $backend + * @param Emitter $emitter + */ + public function __construct($uid, $backend, $emitter = null) { + $this->uid = $uid; + if ($backend->implementsActions(OC_USER_BACKEND_GET_DISPLAYNAME)) { + $this->displayName = $backend->getDisplayName($uid); + } else { + $this->displayName = $uid; + } + $this->backend = $backend; + $this->emitter = $emitter; + $enabled = \OC_Preferences::getValue($uid, 'core', 'enabled', 'true'); //TODO: DI for OC_Preferences + $this->enabled = ($enabled === 'true'); + } + + /** + * get the user id + * + * @return string + */ + public function getUID() { + return $this->uid; + } + + /** + * get the displayname for the user, if no specific displayname is set it will fallback to the user id + * + * @return string + */ + public function getDisplayName() { + return $this->displayName; + } + + /** + * set the displayname for the user + * + * @param string $displayName + * @return bool + */ + public function setDisplayName($displayName) { + if ($this->canChangeDisplayName()) { + $this->displayName = $displayName; + $result = $this->backend->setDisplayName($this->uid, $displayName); + return $result !== false; + } else { + return false; + } + } + + /** + * Delete the user + * + * @return bool + */ + public function delete() { + if ($this->emitter) { + $this->emitter->emit('\OC\User', 'preDelete', array($this)); + } + $result = $this->backend->deleteUser($this->uid); + if ($this->emitter) { + $this->emitter->emit('\OC\User', 'postDelete', array($this)); + } + return !($result === false); + } + + /** + * Check if the password is valid for the user + * + * @param $password + * @return bool + */ + public function checkPassword($password) { + if ($this->backend->implementsActions(\OC_USER_BACKEND_CHECK_PASSWORD)) { + $result = $this->backend->checkPassword($this->uid, $password); + if ($result !== false) { + $this->uid = $result; + } + return !($result === false); + } else { + return false; + } + } + + /** + * Set the password of the user + * + * @param string $password + * @param string $recoveryPassword for the encryption app to reset encryption keys + * @return bool + */ + public function setPassword($password, $recoveryPassword) { + if ($this->backend->implementsActions(\OC_USER_BACKEND_SET_PASSWORD)) { + if ($this->emitter) { + $this->emitter->emit('\OC\User', 'preSetPassword', array($this, $password, $recoveryPassword)); + } + $result = $this->backend->setPassword($this->uid, $password); + if ($this->emitter) { + $this->emitter->emit('\OC\User', 'postSetPassword', array($this, $password, $recoveryPassword)); + } + return !($result === false); + } else { + return false; + } + } + + /** + * get the users home folder to mount + * + * @return string + */ + public function getHome() { + if ($this->backend->implementsActions(\OC_USER_BACKEND_GET_HOME) and $home = $this->backend->getHome($this->uid)) { + return $home; + } + return \OC_Config::getValue("datadirectory", \OC::$SERVERROOT . "/data") . '/' . $this->uid; //TODO switch to Config object once implemented + } + + /** + * check if the backend supports changing passwords + * + * @return bool + */ + public function canChangePassword() { + return $this->backend->implementsActions(\OC_USER_BACKEND_SET_PASSWORD); + } + + /** + * check if the backend supports changing display names + * + * @return bool + */ + public function canChangeDisplayName() { + return $this->backend->implementsActions(\OC_USER_BACKEND_SET_DISPLAYNAME); + } + + /** + * check if the user is enabled + * + * @return bool + */ + public function isEnabled() { + return $this->enabled; + } + + /** + * set the enabled status for the user + * + * @param bool $enabled + */ + public function setEnabled($enabled) { + $this->enabled = $enabled; + $enabled = ($enabled) ? 'true' : 'false'; + \OC_Preferences::setValue($this->uid, 'core', 'enabled', $enabled); + } +} diff --git a/lib/util.php b/lib/util.php index 37fb1bd9d06..95af22ed0ee 100755 --- a/lib/util.php +++ b/lib/util.php @@ -1,4 +1,7 @@ <?php + +require_once 'Patchwork/PHP/Shim/Normalizer.php'; + /** * Class for utility functions * @@ -38,6 +41,7 @@ class OC_Util { $CONFIG_DATADIRECTORY = OC_Config::getValue( "datadirectory", OC::$SERVERROOT."/data" ); //first set up the local "root" storage + \OC\Files\Filesystem::initMounts(); if(!self::$rootMounted) { \OC\Files\Filesystem::mount('\OC\Files\Storage\Local', array('datadir'=>$CONFIG_DATADIRECTORY), '/'); self::$rootMounted=true; @@ -66,6 +70,7 @@ class OC_Util { public static function tearDownFS() { \OC\Files\Filesystem::tearDown(); self::$fsSetup=false; + self::$rootMounted=false; } /** @@ -75,7 +80,7 @@ class OC_Util { public static function getVersion() { // hint: We only can count up. Reset minor/patchlevel when // updating major/minor version number. - return array(5, 80, 01); + return array(5, 80, 05); } /** @@ -149,10 +154,10 @@ class OC_Util { * @param bool dateOnly option to omit time from the result */ public static function formatDate( $timestamp, $dateOnly=false) { - if(isset($_SESSION['timezone'])) {//adjust to clients timezone if we know it + if(\OC::$session->exists('timezone')) {//adjust to clients timezone if we know it $systemTimeZone = intval(date('O')); $systemTimeZone=(round($systemTimeZone/100, 0)*60)+($systemTimeZone%100); - $clientTimeZone=$_SESSION['timezone']*60; + $clientTimeZone=\OC::$session->get('timezone')*60; $offset=$clientTimeZone-$systemTimeZone; $timestamp=$timestamp+$offset*60; } @@ -171,7 +176,8 @@ class OC_Util { //check for database drivers if(!(is_callable('sqlite_open') or class_exists('SQLite3')) and !is_callable('mysql_connect') - and !is_callable('pg_connect')) { + and !is_callable('pg_connect') + and !is_callable('oci_connect')) { $errors[]=array('error'=>'No database drivers (sqlite, mysql, or postgresql) installed.', 'hint'=>'');//TODO: sane hint $web_server_restart= true; @@ -220,63 +226,63 @@ class OC_Util { if(!class_exists('ZipArchive')) { $errors[]=array('error'=>'PHP module zip not installed.', 'hint'=>'Please ask your server administrator to install the module.'); - $web_server_restart= false; + $web_server_restart=true; } if(!class_exists('DOMDocument')) { $errors[] = array('error' => 'PHP module dom not installed.', 'hint' => 'Please ask your server administrator to install the module.'); - $web_server_restart = false; + $web_server_restart =true; } if(!function_exists('xml_parser_create')) { $errors[] = array('error' => 'PHP module libxml not installed.', 'hint' => 'Please ask your server administrator to install the module.'); - $web_server_restart = false; + $web_server_restart =true; } if(!function_exists('mb_detect_encoding')) { $errors[]=array('error'=>'PHP module mb multibyte not installed.', 'hint'=>'Please ask your server administrator to install the module.'); - $web_server_restart= false; + $web_server_restart=true; } if(!function_exists('ctype_digit')) { $errors[]=array('error'=>'PHP module ctype is not installed.', 'hint'=>'Please ask your server administrator to install the module.'); - $web_server_restart= false; + $web_server_restart=true; } if(!function_exists('json_encode')) { $errors[]=array('error'=>'PHP module JSON is not installed.', 'hint'=>'Please ask your server administrator to install the module.'); - $web_server_restart= false; + $web_server_restart=true; } - if(!function_exists('imagepng')) { + if(!extension_loaded('gd') || !function_exists('gd_info')) { $errors[]=array('error'=>'PHP module GD is not installed.', 'hint'=>'Please ask your server administrator to install the module.'); - $web_server_restart= false; + $web_server_restart=true; } if(!function_exists('gzencode')) { $errors[]=array('error'=>'PHP module zlib is not installed.', 'hint'=>'Please ask your server administrator to install the module.'); - $web_server_restart= false; + $web_server_restart=true; } if(!function_exists('iconv')) { $errors[]=array('error'=>'PHP module iconv is not installed.', 'hint'=>'Please ask your server administrator to install the module.'); - $web_server_restart= false; + $web_server_restart=true; } if(!function_exists('simplexml_load_string')) { $errors[]=array('error'=>'PHP module SimpleXML is not installed.', 'hint'=>'Please ask your server administrator to install the module.'); - $web_server_restart= false; + $web_server_restart=true; } if(floatval(phpversion())<5.3) { $errors[]=array('error'=>'PHP 5.3 is required.', 'hint'=>'Please ask your server administrator to update PHP to version 5.3 or higher.' .' PHP 5.2 is no longer supported by ownCloud and the PHP community.'); - $web_server_restart= false; + $web_server_restart=true; } if(!defined('PDO::ATTR_DRIVER_NAME')) { $errors[]=array('error'=>'PHP PDO module is not installed.', 'hint'=>'Please ask your server administrator to install the module.'); - $web_server_restart= false; + $web_server_restart=true; } if (((strtolower(@ini_get('safe_mode')) == 'on') || (strtolower(@ini_get('safe_mode')) == 'yes') @@ -284,7 +290,12 @@ class OC_Util { || (ini_get("safe_mode") == 1 ))) { $errors[]=array('error'=>'PHP Safe Mode is enabled. ownCloud requires that it is disabled to work properly.', 'hint'=>'PHP Safe Mode is a deprecated and mostly useless setting that should be disabled. Please ask your server administrator to disable it in php.ini or in your webserver config.'); - $web_server_restart= false; + $web_server_restart=true; + } + if (get_magic_quotes_gpc() == 1 ) { + $errors[]=array('error'=>'Magic Quotes is enabled. ownCloud requires that it is disabled to work properly.', + 'hint'=>'Magic Quotes is a deprecated and mostly useless setting that should be disabled. Please ask your server administrator to disable it in php.ini or in your webserver config.'); + $web_server_restart=true; } if($web_server_restart) { @@ -450,13 +461,13 @@ class OC_Util { */ public static function callRegister() { // Check if a token exists - if(!isset($_SESSION['requesttoken'])) { + if(!\OC::$session->exists('requesttoken')) { // No valid token found, generate a new one. $requestToken = self::generate_random_bytes(20); - $_SESSION['requesttoken']=$requestToken; + \OC::$session->set('requesttoken', $requestToken); } else { // Valid token already exists, send it - $requestToken = $_SESSION['requesttoken']; + $requestToken = \OC::$session->get('requesttoken'); } return($requestToken); } @@ -468,7 +479,7 @@ class OC_Util { * @see OC_Util::callRegister() */ public static function isCallRegistered() { - if(!isset($_SESSION['requesttoken'])) { + if(!\OC::$session->exists('requesttoken')) { return false; } @@ -484,7 +495,7 @@ class OC_Util { } // Check if the token is valid - if($token !== $_SESSION['requesttoken']) { + if($token !== \OC::$session->get('requesttoken')) { // Not valid return false; } else { @@ -595,7 +606,7 @@ class OC_Util { } catch(\Sabre_DAV_Exception_NotAuthenticated $e) { $return = true; } catch(\Exception $e) { - OC_Log::write('core', 'isWebDAVWorking: NO - Reason: '.$e, OC_Log::WARN); + OC_Log::write('core', 'isWebDAVWorking: NO - Reason: '.$e->getMessage(). ' ('.get_class($e).')', OC_Log::WARN); $return = false; } @@ -633,11 +644,10 @@ class OC_Util { /** * Check if the ownCloud server can connect to the internet */ - public static function isinternetconnectionworking() { - - // in case there is no internet connection on purpose there is no need to display a warning - if (!\OC_Config::getValue("has_internet_connection", true)) { - return true; + public static function isInternetConnectionWorking() { + // in case there is no internet connection on purpose return false + if (self::isInternetConnectionEnabled() === false) { + return false; } // try to connect to owncloud.org to see if http connections to the internet are possible. @@ -659,6 +669,13 @@ class OC_Util { } } + + /** + * Check if the connection to the internet is disabled on purpose + */ + public static function isInternetConnectionEnabled(){ + return \OC_Config::getValue("has_internet_connection", true); + } /** * clear all levels of output buffering @@ -795,4 +812,41 @@ class OC_Util { return (substr(PHP_OS, 0, 3) === "WIN"); } + + /** + * Handles the case that there may not be a theme, then check if a "default" + * theme exists and take that one + * @return string the theme + */ + public static function getTheme() { + $theme = OC_Config::getValue("theme"); + + if(is_null($theme)) { + + if(is_dir(OC::$SERVERROOT . '/themes/default')) { + $theme = 'default'; + } + + } + + return $theme; + } + + /** + * Normalize a unicode string + * @param string $value a not normalized string + * @return bool|string + */ + public static function normalizeUnicode($value) { + if(class_exists('Patchwork\PHP\Shim\Normalizer')) { + $normalizedValue = \Patchwork\PHP\Shim\Normalizer::normalize($value); + if($normalizedValue === false) { + \OC_Log::write( 'core', 'normalizing failed for "' . $value . '"', \OC_Log::WARN); + } else { + $value = $normalizedValue; + } + } + + return $value; + } } diff --git a/lib/vcategories.php b/lib/vcategories.php index 5975e688b75..91c72d5dfae 100644 --- a/lib/vcategories.php +++ b/lib/vcategories.php @@ -325,6 +325,37 @@ class OC_VCategories { } /** + * @brief Rename category. + * @param string $from The name of the existing category + * @param string $to The new name of the category. + * @returns bool + */ + public function rename($from, $to) { + $id = $this->array_searchi($from, $this->categories); + if($id === false) { + OCP\Util::writeLog('core', __METHOD__.', category: ' . $from. ' does not exist', OCP\Util::DEBUG); + return false; + } + + $sql = 'UPDATE `' . self::CATEGORY_TABLE . '` SET `category` = ? ' + . 'WHERE `uid` = ? AND `type` = ? AND `id` = ?'; + try { + $stmt = OCP\DB::prepare($sql); + $result = $stmt->execute(array($to, $this->user, $this->type, $id)); + if (OC_DB::isError($result)) { + OC_Log::write('core', __METHOD__. 'DB error: ' . OC_DB::getErrorMessage($result), OC_Log::ERROR); + return false; + } + } catch(Exception $e) { + OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(), + OCP\Util::ERROR); + return false; + } + $this->categories[$id] = $to; + return true; + } + + /** * @brief Add a new category. * @param $names A string with a name or an array of strings containing * the name(s) of the categor(y|ies) to add. diff --git a/lib/vobject/compoundproperty.php b/lib/vobject/compoundproperty.php new file mode 100644 index 00000000000..d702ab802e0 --- /dev/null +++ b/lib/vobject/compoundproperty.php @@ -0,0 +1,70 @@ +<?php +/** + * ownCloud - VObject Compound Property + * + * @author Thomas Tanghus + * @author Evert Pot (http://www.rooftopsolutions.nl/) + * + * 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\VObject; + +/** + * This class overrides \Sabre\VObject\Property::serialize() to not + * double escape commas and semi-colons in compound properties. +*/ +class CompoundProperty extends \Sabre\VObject\Property\Compound { + + /** + * Turns the object back into a serialized blob. + * + * @return string + */ + public function serialize() { + + $str = $this->name; + if ($this->group) { + $str = $this->group . '.' . $this->name; + } + + foreach($this->parameters as $param) { + $str.=';' . $param->serialize(); + } + $src = array( + "\n", + ); + $out = array( + '\n', + ); + $str.=':' . str_replace($src, $out, $this->value); + + $out = ''; + while(strlen($str) > 0) { + if (strlen($str) > 75) { + $out .= mb_strcut($str, 0, 75, 'utf-8') . "\r\n"; + $str = ' ' . mb_strcut($str, 75, strlen($str), 'utf-8'); + } else { + $out .= $str . "\r\n"; + $str = ''; + break; + } + } + + return $out; + + } + +}
\ No newline at end of file |