diff options
author | Thomas Müller <thomas.mueller@tmit.eu> | 2014-03-21 14:05:08 +0100 |
---|---|---|
committer | Thomas Müller <thomas.mueller@tmit.eu> | 2014-03-21 14:05:08 +0100 |
commit | 6ff96b34ad0462ad05c34633ccd08236b93bf195 (patch) | |
tree | 1acd7eb869d512b5a3fc9502961a98591ea20cfa /lib/private | |
parent | e139f7c863d5971a6386070148496cb0f70ad04e (diff) | |
parent | 37af74efb3e3511b2d6eacef67dc90f22a685bd3 (diff) | |
download | nextcloud-server-6ff96b34ad0462ad05c34633ccd08236b93bf195.tar.gz nextcloud-server-6ff96b34ad0462ad05c34633ccd08236b93bf195.zip |
Merge branch 'master' into load-apps-proper-master
Conflicts:
apps/files/ajax/rawlist.php
cron.php
ocs/v1.php
Diffstat (limited to 'lib/private')
144 files changed, 2785 insertions, 1912 deletions
diff --git a/lib/private/activitymanager.php b/lib/private/activitymanager.php index 7e7e2257874..685809581ac 100755 --- a/lib/private/activitymanager.php +++ b/lib/private/activitymanager.php @@ -59,7 +59,6 @@ class ActivityManager implements IManager { * * $callable has to return an instance of OCA\Activity\IConsumer * - * @param string $key * @param \Closure $callable */ function registerConsumer(\Closure $callable) { diff --git a/lib/private/allconfig.php b/lib/private/allconfig.php index a4aa69d43fb..de3ac973637 100644 --- a/lib/private/allconfig.php +++ b/lib/private/allconfig.php @@ -17,7 +17,7 @@ class AllConfig implements \OCP\IConfig { * Sets a new system wide value * * @param string $key the key of the value, under which will be saved - * @param string $value the value that should be stored + * @param mixed $value the value that should be stored * @todo need a use case for this */ // public function setSystemValue($key, $value) { @@ -28,7 +28,7 @@ class AllConfig implements \OCP\IConfig { * Looks up a system wide defined value * * @param string $key the key of the value, under which it was saved - * @param string $default the default value to be returned if the value isn't set + * @param mixed $default the default value to be returned if the value isn't set * @return string the saved value */ public function getSystemValue($key, $default = '') { diff --git a/lib/private/api.php b/lib/private/api.php index c713368125c..b3b5eb1067b 100644 --- a/lib/private/api.php +++ b/lib/private/api.php @@ -65,8 +65,8 @@ class OC_API { $name = strtolower($method).$url; $name = str_replace(array('/', '{', '}'), '_', $name); if(!isset(self::$actions[$name])) { - OC::getRouter()->useCollection('ocs'); - OC::getRouter()->create($name, $url) + OC::$server->getRouter()->useCollection('ocs'); + OC::$server->getRouter()->create($name, $url) ->method($method) ->defaults($defaults) ->requirements($requirements) @@ -116,9 +116,7 @@ class OC_API { ); } $response = self::mergeResponses($responses); - $formats = array('json', 'xml'); - - $format = !empty($_GET['format']) && in_array($_GET['format'], $formats) ? $_GET['format'] : 'xml'; + $format = self::requestedFormat(); if (self::$logoutRequired) { OC_User::logout(); } @@ -270,6 +268,18 @@ class OC_API { * @return string|false (username, or false on failure) */ private static function loginUser(){ + + // reuse existing login + $loggedIn = OC_User::isLoggedIn(); + $ocsApiRequest = isset($_SERVER['HTTP_OCS_APIREQUEST']) ? $_SERVER['HTTP_OCS_APIREQUEST'] === 'true' : false; + if ($loggedIn === true && $ocsApiRequest) { + + // initialize the user's filesystem + \OC_Util::setUpFS(\OC_User::getUser()); + + return OC_User::getUser(); + } + // basic auth $authUser = isset($_SERVER['PHP_AUTH_USER']) ? $_SERVER['PHP_AUTH_USER'] : ''; $authPw = isset($_SERVER['PHP_AUTH_PW']) ? $_SERVER['PHP_AUTH_PW'] : ''; @@ -283,17 +293,6 @@ class OC_API { return $authUser; } - // reuse existing login - $loggedIn = OC_User::isLoggedIn(); - $ocsApiRequest = isset($_SERVER['HTTP_OCS_APIREQUEST']) ? $_SERVER['HTTP_OCS_APIREQUEST'] === 'true' : false; - if ($loggedIn === true && $ocsApiRequest) { - - // initialize the user's filesystem - \OC_Util::setUpFS(\OC_User::getUser()); - - return OC_User::getUser(); - } - return false; } @@ -328,6 +327,9 @@ class OC_API { } } + /** + * @param XMLWriter $writer + */ private static function toXML($array, $writer) { foreach($array as $k => $v) { if ($k[0] === '@') { @@ -346,4 +348,33 @@ class OC_API { } } + /** + * @return string + */ + public static function requestedFormat() { + $formats = array('json', 'xml'); + + $format = !empty($_GET['format']) && in_array($_GET['format'], $formats) ? $_GET['format'] : 'xml'; + return $format; + } + + /** + * Based on the requested format the response content type is set + */ + public static function setContentType() { + $format = \OC_API::requestedFormat(); + if ($format === 'xml') { + header('Content-type: text/xml; charset=UTF-8'); + return; + } + + if ($format === 'json') { + header('Content-Type: application/json; charset=utf-8'); + return; + } + + header('Content-Type: application/octet-stream; charset=utf-8'); + } + + } diff --git a/lib/private/app.php b/lib/private/app.php index da09021cf3f..58bf67c1d47 100644 --- a/lib/private/app.php +++ b/lib/private/app.php @@ -38,7 +38,7 @@ class OC_App{ /** * @brief clean the appid - * @param $app Appid that needs to be cleaned + * @param string|boolean $app Appid that needs to be cleaned * @return string */ public static function cleanAppId($app) { @@ -69,17 +69,6 @@ class OC_App{ } ob_end_clean(); - if (!defined('DEBUG') || !DEBUG) { - if (is_null($types) - && empty(OC_Util::$coreScripts) - && empty(OC_Util::$coreStyles)) { - OC_Util::$coreScripts = OC_Util::$scripts; - OC_Util::$scripts = array(); - OC_Util::$coreStyles = OC_Util::$styles; - OC_Util::$styles = array(); - } - } - // return return true; } @@ -230,6 +219,8 @@ class OC_App{ $appdata=OC_OCSClient::getApplication($app); $download=OC_OCSClient::getApplicationDownload($app, 1); if(isset($download['downloadlink']) and $download['downloadlink']!='') { + // Replace spaces in download link without encoding entire URL + $download['downloadlink'] = str_replace(' ', '%20', $download['downloadlink']); $info = array('source'=>'http', 'href'=>$download['downloadlink'], 'appdata'=>$appdata); $app=OC_Installer::installApp($info); } @@ -261,7 +252,7 @@ class OC_App{ /** * @brief disables an app * @param string $app app - * @return bool + * @return boolean|null * * This function set an app as disabled in appconfig. */ @@ -342,7 +333,7 @@ class OC_App{ /** * @brief Returns the Settings Navigation - * @return array + * @return string * * This function returns an array containing all settings pages added. The * entries are sorted by the key 'order' ascending. @@ -437,6 +428,7 @@ class OC_App{ /** * Get the path where to install apps + * @return string */ public static function getInstallPath() { if(OC_Config::getValue('appstoreenabled', true)==false) { @@ -490,6 +482,7 @@ class OC_App{ /** * get the last version of the app, either from appinfo/version or from appinfo/info.xml + * @return string */ public static function getAppVersion($appid) { $file= self::getAppPath($appid).'/appinfo/version'; @@ -570,7 +563,7 @@ class OC_App{ /** * @brief Returns the navigation - * @return array + * @return string * * This function returns an array containing all entries added. The * entries are sorted by the key 'order' ascending. Additional to the keys @@ -638,6 +631,8 @@ class OC_App{ /** * register an admin form to be shown + * @param string $app + * @param string $page */ public static function registerAdmin($app, $page) { self::$adminForms[]= $app.'/'.$page.'.php'; @@ -854,6 +849,7 @@ class OC_App{ /** * check if the app needs updating and update when needed + * @param string $app */ public static function checkUpgrade($app) { if (in_array($app, self::$checkedApps)) { diff --git a/lib/private/appconfig.php b/lib/private/appconfig.php index da0b2ff8604..cdaaebb87e5 100644 --- a/lib/private/appconfig.php +++ b/lib/private/appconfig.php @@ -33,15 +33,59 @@ * */ +namespace OC; + +use \OC\DB\Connection; + /** * This class provides an easy way for apps to store config values in the * database. */ -class OC_Appconfig { +class AppConfig implements \OCP\IAppConfig { + /** + * @var \OC\DB\Connection $conn + */ + protected $conn; + + private $cache = array(); - private static $cache = array(); + private $appsLoaded = array(); - private static $appsLoaded = array(); + /** + * @param \OC\DB\Connection $conn + */ + public function __construct(Connection $conn) { + $this->conn = $conn; + } + + /** + * @param string $app + * @return string[] + */ + private function getAppCache($app) { + if (!isset($this->cache[$app])) { + $this->cache[$app] = array(); + } + return $this->cache[$app]; + } + + /** + * @param string $app + */ + private function getAppValues($app) { + $appCache = $this->getAppCache($app); + if (array_search($app, $this->appsLoaded) === false) { + $query = 'SELECT `configvalue`, `configkey` FROM `*PREFIX*appconfig`' + . ' WHERE `appid` = ?'; + $result = $this->conn->executeQuery($query, array($app)); + while ($row = $result->fetch()) { + $appCache[$row['configkey']] = $row['configvalue']; + } + $this->appsLoaded[] = $app; + } + $this->cache[$app] = $appCache; + return $appCache; + } /** * @brief Get all apps using the config @@ -50,16 +94,14 @@ class OC_Appconfig { * This function returns a list of all apps that have at least one * entry in the appconfig table. */ - public static function getApps() { - // No magic in here! - $query = OC_DB::prepare('SELECT DISTINCT `appid` FROM `*PREFIX*appconfig` ORDER BY `appid`'); - $result = $query->execute(); + public function getApps() { + $query = 'SELECT DISTINCT `appid` FROM `*PREFIX*appconfig` ORDER BY `appid`'; + $result = $this->conn->executeQuery($query); $apps = array(); - while ($row = $result->fetchRow()) { - $apps[] = $row["appid"]; + while ($appid = $result->fetchColumn()) { + $apps[] = $appid; } - return $apps; } @@ -71,35 +113,13 @@ class OC_Appconfig { * This function gets all keys of an app. Please note that the values are * not returned. */ - public static function getKeys($app) { - // No magic in here as well - $query = OC_DB::prepare('SELECT `configkey` FROM `*PREFIX*appconfig` WHERE `appid` = ?'); - $result = $query->execute(array($app)); - - $keys = array(); - while ($row = $result->fetchRow()) { - $keys[] = $row["configkey"]; - } - + public function getKeys($app) { + $values = $this->getAppValues($app); + $keys = array_keys($values); + sort($keys); return $keys; } - private static function getAppValues($app) { - if (!isset(self::$cache[$app])) { - self::$cache[$app] = array(); - } - if (array_search($app, self::$appsLoaded) === false) { - $query = OC_DB::prepare('SELECT `configvalue`, `configkey` FROM `*PREFIX*appconfig`' - . ' WHERE `appid` = ?'); - $result = $query->execute(array($app)); - while ($row = $result->fetchRow()) { - self::$cache[$app][$row['configkey']] = $row['configvalue']; - } - self::$appsLoaded[] = $app; - } - return self::$cache[$app]; - } - /** * @brief Gets the config value * @param string $app app @@ -110,18 +130,11 @@ class OC_Appconfig { * This function gets a value from the appconfig table. If the key does * not exist the default value will be returned */ - public static function getValue($app, $key, $default = null) { - if (!isset(self::$cache[$app])) { - self::$cache[$app] = array(); - } - if (isset(self::$cache[$app][$key])) { - return self::$cache[$app][$key]; - } - $values = self::getAppValues($app); + public function getValue($app, $key, $default = null) { + $values = $this->getAppValues($app); if (isset($values[$key])) { return $values[$key]; } else { - self::$cache[$app][$key] = $default; return $default; } } @@ -132,12 +145,9 @@ class OC_Appconfig { * @param string $key * @return bool */ - public static function hasKey($app, $key) { - if (isset(self::$cache[$app]) and isset(self::$cache[$app][$key])) { - return true; - } - $exists = self::getKeys($app); - return in_array($key, $exists); + public function hasKey($app, $key) { + $values = $this->getAppValues($app); + return isset($values[$key]); } /** @@ -145,79 +155,78 @@ class OC_Appconfig { * @param string $app app * @param string $key key * @param string $value value - * @return bool * * Sets a value. If the key did not exist before it will be created. */ - public static function setValue($app, $key, $value) { - // Does the key exist? yes: update. No: insert - if (!self::hasKey($app, $key)) { - $query = OC_DB::prepare('INSERT INTO `*PREFIX*appconfig` ( `appid`, `configkey`, `configvalue` )' - . ' VALUES( ?, ?, ? )'); - $query->execute(array($app, $key, $value)); + public function setValue($app, $key, $value) { + // Does the key exist? no: insert, yes: update. + if (!$this->hasKey($app, $key)) { + $data = array( + 'appid' => $app, + 'configkey' => $key, + 'configvalue' => $value, + ); + $this->conn->insert('*PREFIX*appconfig', $data); } else { - $query = OC_DB::prepare('UPDATE `*PREFIX*appconfig` SET `configvalue` = ?' - . ' WHERE `appid` = ? AND `configkey` = ?'); - $query->execute(array($value, $app, $key)); + $data = array( + 'configvalue' => $value, + ); + $where = array( + 'appid' => $app, + 'configkey' => $key, + ); + $this->conn->update('*PREFIX*appconfig', $data, $where); } - // TODO where should this be documented? - \OC_Hook::emit('OC_Appconfig', 'post_set_value', array( - 'app' => $app, - 'key' => $key, - 'value' => $value - )); - if (!isset(self::$cache[$app])) { - self::$cache[$app] = array(); + if (!isset($this->cache[$app])) { + $this->cache[$app] = array(); } - self::$cache[$app][$key] = $value; + $this->cache[$app][$key] = $value; } /** * @brief Deletes a key * @param string $app app * @param string $key key - * @return bool - * - * Deletes a key. + * @return boolean|null */ - public static function deleteKey($app, $key) { - // Boring! - $query = OC_DB::prepare('DELETE FROM `*PREFIX*appconfig` WHERE `appid` = ? AND `configkey` = ?'); - $query->execute(array($app, $key)); - if (isset(self::$cache[$app]) and isset(self::$cache[$app][$key])) { - unset(self::$cache[$app][$key]); + public function deleteKey($app, $key) { + $where = array( + 'appid' => $app, + 'configkey' => $key, + ); + $this->conn->delete('*PREFIX*appconfig', $where); + if (isset($this->cache[$app]) and isset($this->cache[$app][$key])) { + unset($this->cache[$app][$key]); } - - return true; } /** * @brief Remove app from appconfig * @param string $app app - * @return bool + * @return boolean|null * * Removes all keys in appconfig belonging to the app. */ - public static function deleteApp($app) { - // Nothing special - $query = OC_DB::prepare('DELETE FROM `*PREFIX*appconfig` WHERE `appid` = ?'); - $query->execute(array($app)); - self::$cache[$app] = array(); - - return true; + public function deleteApp($app) { + $where = array( + 'appid' => $app, + ); + $this->conn->delete('*PREFIX*appconfig', $where); + unset($this->cache[$app]); } /** * get multiply values, either the app or key can be used as wildcard by setting it to false * - * @param app - * @param key + * @param boolean $app + * @param string $key * @return array */ - public static function getValues($app, $key) { - if ($app !== false and $key !== false) { + public function getValues($app, $key) { + if (($app !== false) == ($key !== false)) { return false; } + $fields = '`configvalue`'; $where = 'WHERE'; $params = array(); @@ -232,13 +241,14 @@ class OC_Appconfig { $params[] = $key; $key = 'appid'; } - $queryString = 'SELECT ' . $fields . ' FROM `*PREFIX*appconfig` ' . $where; - $query = OC_DB::prepare($queryString); - $result = $query->execute($params); + $query = 'SELECT ' . $fields . ' FROM `*PREFIX*appconfig` ' . $where; + $result = $this->conn->executeQuery($query, $params); + $values = array(); - while ($row = $result->fetchRow()) { + while ($row = $result->fetch((\PDO::FETCH_ASSOC))) { $values[$row[$key]] = $row['configvalue']; } + return $values; } } diff --git a/lib/private/appframework/app.php b/lib/private/appframework/app.php index b835188661a..3b13194862d 100644 --- a/lib/private/appframework/app.php +++ b/lib/private/appframework/app.php @@ -25,7 +25,6 @@ namespace OC\AppFramework; use OC\AppFramework\DependencyInjection\DIContainer; -use OCP\AppFramework\IAppContainer; /** diff --git a/lib/private/appframework/dependencyinjection/dicontainer.php b/lib/private/appframework/dependencyinjection/dicontainer.php index e2ea974e104..4821ecaf67b 100644 --- a/lib/private/appframework/dependencyinjection/dicontainer.php +++ b/lib/private/appframework/dependencyinjection/dicontainer.php @@ -34,7 +34,6 @@ use OC\AppFramework\Utility\SimpleContainer; use OC\AppFramework\Utility\TimeFactory; use OCP\AppFramework\IApi; use OCP\AppFramework\IAppContainer; -use OCP\AppFramework\IMiddleWare; use OCP\AppFramework\Middleware; use OCP\IServerContainer; @@ -135,7 +134,7 @@ class DIContainer extends SimpleContainer implements IAppContainer{ /** * @param Middleware $middleWare - * @return boolean + * @return boolean|null */ function registerMiddleWare(Middleware $middleWare) { array_push($this->middleWares, $middleWare); diff --git a/lib/private/appframework/http.php b/lib/private/appframework/http.php index 41fc0db6b38..65d926105f1 100644 --- a/lib/private/appframework/http.php +++ b/lib/private/appframework/http.php @@ -108,7 +108,7 @@ class Http extends BaseHttp { * Gets the correct header * @param Http::CONSTANT $status the constant from the Http class * @param \DateTime $lastModified formatted last modified date - * @param string $Etag the etag + * @param string $ETag the etag */ public function getStatusHeader($status, \DateTime $lastModified=null, $ETag=null) { diff --git a/lib/private/appframework/http/redirectresponse.php b/lib/private/appframework/http/redirectresponse.php index c4e21059480..05353349065 100644 --- a/lib/private/appframework/http/redirectresponse.php +++ b/lib/private/appframework/http/redirectresponse.php @@ -24,8 +24,8 @@ namespace OC\AppFramework\Http; -use OCP\AppFramework\Http\Response, - OCP\AppFramework\Http; +use OCP\AppFramework\Http\Response; +use OCP\AppFramework\Http; /** diff --git a/lib/private/appframework/http/request.php b/lib/private/appframework/http/request.php index 3e1f4ff87ed..40f47a7bd2f 100644 --- a/lib/private/appframework/http/request.php +++ b/lib/private/appframework/http/request.php @@ -114,7 +114,7 @@ class Request implements \ArrayAccess, \Countable, IRequest { * $request['myvar'] = 'something'; // This throws an exception. * * @param string $offset The key to lookup - * @return string|null + * @return boolean */ public function offsetExists($offset) { return isset($this->items['parameters'][$offset]); diff --git a/lib/private/appframework/middleware/middlewaredispatcher.php b/lib/private/appframework/middleware/middlewaredispatcher.php index 681140c2242..598743e523f 100644 --- a/lib/private/appframework/middleware/middlewaredispatcher.php +++ b/lib/private/appframework/middleware/middlewaredispatcher.php @@ -56,7 +56,7 @@ class MiddlewareDispatcher { /** * Adds a new middleware - * @param Middleware $middleware the middleware which will be added + * @param Middleware $middleWare the middleware which will be added */ public function registerMiddleware(Middleware $middleWare){ array_push($this->middlewares, $middleWare); diff --git a/lib/private/appframework/middleware/security/securityexception.php b/lib/private/appframework/middleware/security/securityexception.php index b32a2769ff5..e551675acdf 100644 --- a/lib/private/appframework/middleware/security/securityexception.php +++ b/lib/private/appframework/middleware/security/securityexception.php @@ -32,7 +32,6 @@ class SecurityException extends \Exception { /** * @param string $msg the security error message - * @param bool $ajax true if it resulted because of an ajax request */ public function __construct($msg, $code = 0) { parent::__construct($msg, $code); diff --git a/lib/private/appframework/middleware/security/securitymiddleware.php b/lib/private/appframework/middleware/security/securitymiddleware.php index c3143754823..bb02d565fa4 100644 --- a/lib/private/appframework/middleware/security/securitymiddleware.php +++ b/lib/private/appframework/middleware/security/securitymiddleware.php @@ -66,7 +66,7 @@ class SecurityMiddleware extends Middleware { * This runs all the security checks before a method call. The * security checks are determined by inspecting the controller method * annotations - * @param string/Controller $controller the controllername or string + * @param string $controller the controllername or string * @param string $methodName the name of the method * @throws SecurityException when a security check fails */ diff --git a/lib/private/appframework/routing/routeactionhandler.php b/lib/private/appframework/routing/routeactionhandler.php index 2b9dc38dc43..6a5c64745ae 100644 --- a/lib/private/appframework/routing/routeactionhandler.php +++ b/lib/private/appframework/routing/routeactionhandler.php @@ -30,6 +30,10 @@ class RouteActionHandler { private $actionName; private $container; + /** + * @param string $controllerName + * @param string $actionName + */ public function __construct(DIContainer $container, $controllerName, $actionName) { $this->controllerName = $controllerName; $this->actionName = $actionName; diff --git a/lib/private/appframework/routing/routeconfig.php b/lib/private/appframework/routing/routeconfig.php index 53ab11bf2f5..35bee75cc4d 100644 --- a/lib/private/appframework/routing/routeconfig.php +++ b/lib/private/appframework/routing/routeconfig.php @@ -23,6 +23,7 @@ namespace OC\AppFramework\routing; use OC\AppFramework\DependencyInjection\DIContainer; +use OCP\Route\IRouter; /** * Class RouteConfig @@ -36,11 +37,10 @@ class RouteConfig { /** * @param \OC\AppFramework\DependencyInjection\DIContainer $container - * @param \OC_Router $router - * @param string $pathToYml + * @param \OCP\Route\IRouter $router * @internal param $appName */ - public function __construct(DIContainer $container, \OC_Router $router, $routes) { + public function __construct(DIContainer $container, IRouter $router, $routes) { $this->routes = $routes; $this->container = $container; $this->router = $router; @@ -48,7 +48,7 @@ class RouteConfig { } /** - * The routes and resource will be registered to the \OC_Router + * The routes and resource will be registered to the \OCP\Route\IRouter */ public function register() { diff --git a/lib/private/appframework/utility/simplecontainer.php b/lib/private/appframework/utility/simplecontainer.php index e631e657756..d08a4879e34 100644 --- a/lib/private/appframework/utility/simplecontainer.php +++ b/lib/private/appframework/utility/simplecontainer.php @@ -31,7 +31,7 @@ class SimpleContainer extends \Pimple implements \OCP\IContainer { * Created instance will be cached in case $shared is true. * * @param string $name name of the service to register another backend for - * @param callable $closure the closure to be called on service creation + * @param \Closure $closure the closure to be called on service creation */ function registerService($name, \Closure $closure, $shared = true) { diff --git a/lib/private/archive.php b/lib/private/archive.php index 85bfae57295..6f51066ddf8 100644 --- a/lib/private/archive.php +++ b/lib/private/archive.php @@ -9,7 +9,7 @@ abstract class OC_Archive{ /** * open any of the supported archive types - * @param string path + * @param string $path * @return OC_Archive */ public static function open($path) { @@ -32,39 +32,39 @@ abstract class OC_Archive{ abstract function __construct($source); /** * add an empty folder to the archive - * @param string path + * @param string $path * @return bool */ abstract function addFolder($path); /** * add a file to the archive - * @param string path + * @param string $path * @param string source either a local file or string data * @return bool */ abstract function addFile($path, $source=''); /** * rename a file or folder in the archive - * @param string source - * @param string dest + * @param string $source + * @param string $dest * @return bool */ abstract function rename($source, $dest); /** * get the uncompressed size of a file in the archive - * @param string path + * @param string $path * @return int */ abstract function filesize($path); /** * get the last modified time of a file in the archive - * @param string path + * @param string $path * @return int */ abstract function mtime($path); /** * get the files in a folder - * @param path + * @param string $path * @return array */ abstract function getFolder($path); @@ -75,48 +75,47 @@ abstract class OC_Archive{ abstract function getFiles(); /** * get the content of a file - * @param string path + * @param string $path * @return string */ abstract function getFile($path); /** * extract a single file from the archive - * @param string path - * @param string dest + * @param string $path + * @param string $dest * @return bool */ abstract function extractFile($path, $dest); /** * extract the archive - * @param string path - * @param string dest + * @param string $dest * @return bool */ abstract function extract($dest); /** * check if a file or folder exists in the archive - * @param string path + * @param string $path * @return bool */ abstract function fileExists($path); /** * remove a file or folder from the archive - * @param string path + * @param string $path * @return bool */ abstract function remove($path); /** * get a file handler - * @param string path - * @param string mode + * @param string $path + * @param string $mode * @return resource */ abstract function getStream($path, $mode); /** * add a folder and all its content * @param string $path - * @param string source - * @return bool + * @param string $source + * @return boolean|null */ function addRecursive($path, $source) { $dh = opendir($source); diff --git a/lib/private/archive/tar.php b/lib/private/archive/tar.php index a1c0535b1c3..cbdb565ba35 100644 --- a/lib/private/archive/tar.php +++ b/lib/private/archive/tar.php @@ -22,6 +22,9 @@ class OC_Archive_TAR extends OC_Archive{ private $tar=null; private $path; + /** + * @param string $source + */ function __construct($source) { $types=array(null, 'gz', 'bz'); $this->path=$source; @@ -30,8 +33,8 @@ class OC_Archive_TAR extends OC_Archive{ /** * try to detect the type of tar compression - * @param string file - * @return str + * @param string $file + * @return integer */ static public function getTarType($file) { if(strpos($file, '.')) { @@ -53,7 +56,7 @@ class OC_Archive_TAR extends OC_Archive{ /** * add an empty folder to the archive - * @param string path + * @param string $path * @return bool */ function addFolder($path) { @@ -80,8 +83,8 @@ class OC_Archive_TAR extends OC_Archive{ } /** * add a file to the archive - * @param string path - * @param string source either a local file or string data + * @param string $path + * @param string $source either a local file or string data * @return bool */ function addFile($path, $source='') { @@ -103,8 +106,8 @@ class OC_Archive_TAR extends OC_Archive{ /** * rename a file or folder in the archive - * @param string source - * @param string dest + * @param string $source + * @param string $dest * @return bool */ function rename($source, $dest) { @@ -122,6 +125,9 @@ class OC_Archive_TAR extends OC_Archive{ return true; } + /** + * @param string $file + */ private function getHeader($file) { if ( ! $this->cachedHeaders ) { $this->cachedHeaders = $this->tar->listContent(); @@ -139,7 +145,7 @@ class OC_Archive_TAR extends OC_Archive{ /** * get the uncompressed size of a file in the archive - * @param string path + * @param string $path * @return int */ function filesize($path) { @@ -158,7 +164,7 @@ class OC_Archive_TAR extends OC_Archive{ /** * get the files in a folder - * @param path + * @param string $path * @return array */ function getFolder($path) { @@ -201,7 +207,7 @@ class OC_Archive_TAR extends OC_Archive{ } /** * get the content of a file - * @param string path + * @param string $path * @return string */ function getFile($path) { @@ -209,8 +215,8 @@ class OC_Archive_TAR extends OC_Archive{ } /** * extract a single file from the archive - * @param string path - * @param string dest + * @param string $path + * @param string $dest * @return bool */ function extractFile($path, $dest) { @@ -231,8 +237,7 @@ class OC_Archive_TAR extends OC_Archive{ } /** * extract the archive - * @param string path - * @param string dest + * @param string $dest * @return bool */ function extract($dest) { @@ -240,7 +245,7 @@ class OC_Archive_TAR extends OC_Archive{ } /** * check if a file or folder exists in the archive - * @param string path + * @param string $path * @return bool */ function fileExists($path) { @@ -268,7 +273,7 @@ class OC_Archive_TAR extends OC_Archive{ /** * remove a file or folder from the archive - * @param string path + * @param string $path * @return bool */ function remove($path) { @@ -289,8 +294,8 @@ class OC_Archive_TAR extends OC_Archive{ } /** * get a file handler - * @param string path - * @param string mode + * @param string $path + * @param string $mode * @return resource */ function getStream($path, $mode) { diff --git a/lib/private/archive/zip.php b/lib/private/archive/zip.php index 8a866716a79..fa5630d7665 100644 --- a/lib/private/archive/zip.php +++ b/lib/private/archive/zip.php @@ -13,6 +13,9 @@ class OC_Archive_ZIP extends OC_Archive{ private $zip=null; private $path; + /** + * @param string $source + */ function __construct($source) { $this->path=$source; $this->zip=new ZipArchive(); @@ -23,7 +26,7 @@ class OC_Archive_ZIP extends OC_Archive{ } /** * add an empty folder to the archive - * @param string path + * @param string $path * @return bool */ function addFolder($path) { @@ -31,8 +34,8 @@ class OC_Archive_ZIP extends OC_Archive{ } /** * add a file to the archive - * @param string path - * @param string source either a local file or string data + * @param string $path + * @param string $source either a local file or string data * @return bool */ function addFile($path, $source='') { @@ -49,9 +52,9 @@ class OC_Archive_ZIP extends OC_Archive{ } /** * rename a file or folder in the archive - * @param string source - * @param string dest - * @return bool + * @param string $source + * @param string $dest + * @return boolean|null */ function rename($source, $dest) { $source=$this->stripPath($source); @@ -60,7 +63,7 @@ class OC_Archive_ZIP extends OC_Archive{ } /** * get the uncompressed size of a file in the archive - * @param string path + * @param string $path * @return int */ function filesize($path) { @@ -69,7 +72,7 @@ class OC_Archive_ZIP extends OC_Archive{ } /** * get the last modified time of a file in the archive - * @param string path + * @param string $path * @return int */ function mtime($path) { @@ -77,7 +80,7 @@ class OC_Archive_ZIP extends OC_Archive{ } /** * get the files in a folder - * @param path + * @param string $path * @return array */ function getFolder($path) { @@ -107,7 +110,7 @@ class OC_Archive_ZIP extends OC_Archive{ } /** * get the content of a file - * @param string path + * @param string $path * @return string */ function getFile($path) { @@ -115,9 +118,9 @@ class OC_Archive_ZIP extends OC_Archive{ } /** * extract a single file from the archive - * @param string path - * @param string dest - * @return bool + * @param string $path + * @param string $dest + * @return boolean|null */ function extractFile($path, $dest) { $fp = $this->zip->getStream($path); @@ -125,8 +128,7 @@ class OC_Archive_ZIP extends OC_Archive{ } /** * extract the archive - * @param string path - * @param string dest + * @param string $dest * @return bool */ function extract($dest) { @@ -134,7 +136,7 @@ class OC_Archive_ZIP extends OC_Archive{ } /** * check if a file or folder exists in the archive - * @param string path + * @param string $path * @return bool */ function fileExists($path) { @@ -142,7 +144,7 @@ class OC_Archive_ZIP extends OC_Archive{ } /** * remove a file or folder from the archive - * @param string path + * @param string $path * @return bool */ function remove($path) { @@ -154,8 +156,8 @@ class OC_Archive_ZIP extends OC_Archive{ } /** * get a file handler - * @param string path - * @param string mode + * @param string $path + * @param string $mode * @return resource */ function getStream($path, $mode) { @@ -191,6 +193,10 @@ class OC_Archive_ZIP extends OC_Archive{ } } + /** + * @param string $path + * @return string + */ private function stripPath($path) { if(!$path || $path[0]=='/') { return substr($path, 1); diff --git a/lib/private/arrayparser.php b/lib/private/arrayparser.php index 3bb394a5163..d353e486577 100644 --- a/lib/private/arrayparser.php +++ b/lib/private/arrayparser.php @@ -30,12 +30,18 @@ class ArrayParser { const TYPE_STRING = 3; const TYPE_ARRAY = 4; + /** + * @param string $string + */ function parsePHP($string) { $string = $this->stripPHPTags($string); $string = $this->stripAssignAndReturn($string); return $this->parse($string); } + /** + * @param string $string + */ function stripPHPTags($string) { $string = trim($string); if (substr($string, 0, 5) === '<?php') { @@ -47,6 +53,9 @@ class ArrayParser { return $string; } + /** + * @param string $string + */ function stripAssignAndReturn($string) { $string = trim($string); if (substr($string, 0, 6) === 'return') { @@ -74,6 +83,9 @@ class ArrayParser { return null; } + /** + * @param string $string + */ function getType($string) { $string = strtolower($string); $first = substr($string, 0, 1); @@ -90,19 +102,31 @@ class ArrayParser { } } + /** + * @param string $string + */ function parseString($string) { return substr($string, 1, -1); } + /** + * @param string $string + */ function parseNum($string) { return intval($string); } + /** + * @param string $string + */ function parseBool($string) { $string = strtolower($string); return $string === 'true'; } + /** + * @param string $string + */ function parseArray($string) { $body = substr($string, 5); $body = trim($body); @@ -131,6 +155,9 @@ class ArrayParser { return $result; } + /** + * @param string $body + */ function splitArray($body) { $inSingleQuote = false;//keep track if we are inside quotes $inDoubleQuote = false; diff --git a/lib/private/backgroundjob.php b/lib/private/backgroundjob.php index 9619dcb732c..afc3c270405 100644 --- a/lib/private/backgroundjob.php +++ b/lib/private/backgroundjob.php @@ -37,8 +37,8 @@ class OC_BackgroundJob{ /** * @brief sets the background jobs execution type - * @param $type execution type - * @return boolean + * @param string $type execution type + * @return false|null * * This method sets the execution type of the background jobs. Possible types * are "none", "ajax", "webcron", "cron" diff --git a/lib/private/backgroundjob/job.php b/lib/private/backgroundjob/job.php index 92bd0f8fdbd..0cef401bc24 100644 --- a/lib/private/backgroundjob/job.php +++ b/lib/private/backgroundjob/job.php @@ -8,7 +8,9 @@ namespace OC\BackgroundJob; -abstract class Job { +use OCP\BackgroundJob\IJob; + +abstract class Job implements IJob { /** * @var int $id */ diff --git a/lib/private/backgroundjob/joblist.php b/lib/private/backgroundjob/joblist.php index 99743a70c77..26c90269349 100644 --- a/lib/private/backgroundjob/joblist.php +++ b/lib/private/backgroundjob/joblist.php @@ -1,6 +1,6 @@ <?php /** - * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com> + * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com> * This file is licensed under the Affero General Public License version 3 or * later. * See the COPYING-README file. @@ -8,16 +8,30 @@ namespace OC\BackgroundJob; -/** - * Class QueuedJob - * - * create a background job that is to be executed once - * - * @package OC\BackgroundJob - */ -class JobList { +use OCP\BackgroundJob\IJobList; + +class JobList implements IJobList { + /** + * @var \OCP\IDBConnection + */ + private $conn; + + /** + * @var \OCP\IConfig $config + */ + private $config; + /** - * @param Job|string $job + * @param \OCP\IDBConnection $conn + * @param \OCP\IConfig $config + */ + public function __construct($conn, $config) { + $this->conn = $conn; + $this->config = $config; + } + + /** + * @param \Test\BackgroundJob\TestJob $job * @param mixed $argument */ public function add($job, $argument = null) { @@ -28,13 +42,13 @@ class JobList { $class = $job; } $argument = json_encode($argument); - $query = \OC_DB::prepare('INSERT INTO `*PREFIX*jobs`(`class`, `argument`, `last_run`) VALUES(?, ?, 0)'); + $query = $this->conn->prepare('INSERT INTO `*PREFIX*jobs`(`class`, `argument`, `last_run`) VALUES(?, ?, 0)'); $query->execute(array($class, $argument)); } } /** - * @param Job|string $job + * @param Job $job * @param mixed $argument */ public function remove($job, $argument = null) { @@ -45,10 +59,10 @@ class JobList { } if (!is_null($argument)) { $argument = json_encode($argument); - $query = \OC_DB::prepare('DELETE FROM `*PREFIX*jobs` WHERE `class` = ? AND `argument` = ?'); + $query = $this->conn->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 = $this->conn->prepare('DELETE FROM `*PREFIX*jobs` WHERE `class` = ?'); $query->execute(array($class)); } } @@ -67,9 +81,9 @@ class JobList { $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(); + $query = $this->conn->prepare('SELECT `id` FROM `*PREFIX*jobs` WHERE `class` = ? AND `argument` = ?'); + $query->execute(array($class, $argument)); + return (bool)$query->fetch(); } /** @@ -78,10 +92,10 @@ class JobList { * @return Job[] */ public function getAll() { - $query = \OC_DB::prepare('SELECT `id`, `class`, `last_run`, `argument` FROM `*PREFIX*jobs`'); - $result = $query->execute(); + $query = $this->conn->prepare('SELECT `id`, `class`, `last_run`, `argument` FROM `*PREFIX*jobs`'); + $query->execute(); $jobs = array(); - while ($row = $result->fetchRow()) { + while ($row = $query->fetch()) { $jobs[] = $this->buildJob($row); } return $jobs; @@ -94,15 +108,15 @@ class JobList { */ 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()) { + $query = $this->conn->prepare('SELECT `id`, `class`, `last_run`, `argument` FROM `*PREFIX*jobs` WHERE `id` > ? ORDER BY `id` ASC', 1); + $query->execute(array($lastId)); + if ($row = $query->fetch()) { 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()) { + $query = $this->conn->prepare('SELECT `id`, `class`, `last_run`, `argument` FROM `*PREFIX*jobs` ORDER BY `id` ASC', 1); + $query->execute(); + if ($row = $query->fetch()) { return $this->buildJob($row); } else { return null; //empty job list @@ -115,9 +129,9 @@ class JobList { * @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()) { + $query = $this->conn->prepare('SELECT `id`, `class`, `last_run`, `argument` FROM `*PREFIX*jobs` WHERE `id` = ?'); + $query->execute(array($id)); + if ($row = $query->fetch()) { return $this->buildJob($row); } else { return null; @@ -148,16 +162,16 @@ class JobList { * @param Job $job */ public function setLastJob($job) { - \OC_Appconfig::setValue('backgroundjob', 'lastjob', $job->getId()); + $this->config->setAppValue('backgroundjob', 'lastjob', $job->getId()); } /** * get the id of the last ran job * - * @return int + * @return string */ public function getLastJob() { - return \OC_Appconfig::getValue('backgroundjob', 'lastjob', 0); + return $this->config->getAppValue('backgroundjob', 'lastjob', 0); } /** @@ -166,7 +180,7 @@ class JobList { * @param Job $job */ public function setLastRun($job) { - $query = \OC_DB::prepare('UPDATE `*PREFIX*jobs` SET `last_run` = ? WHERE `id` = ?'); + $query = $this->conn->prepare('UPDATE `*PREFIX*jobs` SET `last_run` = ? WHERE `id` = ?'); $query->execute(array(time(), $job->getId())); } } diff --git a/lib/private/cache/file.php b/lib/private/cache/file.php index b0738d2a92b..8a6ef39f61b 100644 --- a/lib/private/cache/file.php +++ b/lib/private/cache/file.php @@ -29,6 +29,9 @@ class File { } } + /** + * @param string $key + */ public function get($key) { $result = null; $proxyStatus = \OC_FileProxy::$enabled; @@ -59,6 +62,9 @@ class File { return $result; } + /** + * @param string $key + */ public function set($key, $value, $ttl=0) { $storage = $this->getStorage(); $result = false; @@ -87,6 +93,9 @@ class File { return false; } + /** + * @param string $key + */ public function remove($key) { $storage = $this->getStorage(); if(!$storage) { diff --git a/lib/private/cache/fileglobal.php b/lib/private/cache/fileglobal.php index bd049bba4d0..d9e0fd46d37 100644 --- a/lib/private/cache/fileglobal.php +++ b/lib/private/cache/fileglobal.php @@ -21,6 +21,9 @@ class FileGlobal { return str_replace('/', '_', $key); } + /** + * @param string $key + */ public function get($key) { $key = $this->fixKey($key); if ($this->hasKey($key)) { @@ -30,6 +33,10 @@ class FileGlobal { return null; } + /** + * @param string $key + * @param string $value + */ public function set($key, $value, $ttl=0) { $key = $this->fixKey($key); $cache_dir = self::getCacheDir(); @@ -81,13 +88,14 @@ class FileGlobal { } static public function gc() { - $last_run = \OC_AppConfig::getValue('core', 'global_cache_gc_lastrun', 0); + $appConfig = \OC::$server->getAppConfig(); + $last_run = $appConfig->getValue('core', 'global_cache_gc_lastrun', 0); $now = time(); if (($now - $last_run) < 300) { // only do cleanup every 5 minutes return; } - \OC_AppConfig::setValue('core', 'global_cache_gc_lastrun', $now); + $appConfig->setValue('core', 'global_cache_gc_lastrun', $now); $cache_dir = self::getCacheDir(); if($cache_dir and is_dir($cache_dir)) { $dh=opendir($cache_dir); diff --git a/lib/private/cache/usercache.php b/lib/private/cache/usercache.php index baa8820700b..486e08218a2 100644 --- a/lib/private/cache/usercache.php +++ b/lib/private/cache/usercache.php @@ -35,7 +35,7 @@ class UserCache implements \OCP\ICache { * Set a value in the user cache * * @param string $key - * @param mixed $value + * @param string $value * @param int $ttl Time To Live in seconds. Defaults to 60*60*24 * @return bool */ diff --git a/lib/private/config.php b/lib/private/config.php index 8a9d5ca6158..56f47256134 100644 --- a/lib/private/config.php +++ b/lib/private/config.php @@ -77,7 +77,7 @@ class Config { /** * @brief Gets a value from config.php * @param string $key key - * @param string $default = null default value + * @param array|bool|string|null $default = null default value * @return string the value or $default * * This function gets the value from config.php. If it does not exist, diff --git a/lib/private/connector/sabre/aborteduploaddetectionplugin.php b/lib/private/connector/sabre/aborteduploaddetectionplugin.php index 10cca647e8d..ad759d1d84a 100644 --- a/lib/private/connector/sabre/aborteduploaddetectionplugin.php +++ b/lib/private/connector/sabre/aborteduploaddetectionplugin.php @@ -47,7 +47,7 @@ class OC_Connector_Sabre_AbortedUploadDetectionPlugin extends Sabre_DAV_ServerPl } /** - * @param $filePath + * @param string $filePath * @param Sabre_DAV_INode $node * @throws Sabre_DAV_Exception_BadRequest */ diff --git a/lib/private/connector/sabre/auth.php b/lib/private/connector/sabre/auth.php index 0c84fa6b757..5577273df8c 100644 --- a/lib/private/connector/sabre/auth.php +++ b/lib/private/connector/sabre/auth.php @@ -73,6 +73,20 @@ class OC_Connector_Sabre_Auth extends Sabre_DAV_Auth_Backend_AbstractBasic { */ public function authenticate(Sabre_DAV_Server $server, $realm) { + $result = $this->auth($server, $realm); + + // close the session - right after authentication there is not need to write to the session any more + \OC::$session->close(); + + return $result; + } + + /** + * @param Sabre_DAV_Server $server + * @param $realm + * @return bool + */ + private function auth(Sabre_DAV_Server $server, $realm) { if (OC_User::handleApacheAuth() || OC_User::isLoggedIn()) { $user = OC_User::getUser(); OC_Util::setupFS($user); @@ -81,5 +95,5 @@ class OC_Connector_Sabre_Auth extends Sabre_DAV_Auth_Backend_AbstractBasic { } return parent::authenticate($server, $realm); - } + } } diff --git a/lib/private/connector/sabre/directory.php b/lib/private/connector/sabre/directory.php index 02d1a9f4ba2..3ed9e94d69b 100644 --- a/lib/private/connector/sabre/directory.php +++ b/lib/private/connector/sabre/directory.php @@ -50,7 +50,7 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa */ public function createFile($name, $data = null) { - if ($name === 'Shared' && empty($this->path)) { + if (strtolower($name) === 'shared' && empty($this->path)) { throw new \Sabre_DAV_Exception_Forbidden(); } @@ -86,7 +86,7 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa */ public function createDirectory($name) { - if ($name === 'Shared' && empty($this->path)) { + if (strtolower($name) === 'shared' && empty($this->path)) { throw new \Sabre_DAV_Exception_Forbidden(); } diff --git a/lib/private/connector/sabre/file.php b/lib/private/connector/sabre/file.php index ed27cef440d..ef6caaf22a7 100644 --- a/lib/private/connector/sabre/file.php +++ b/lib/private/connector/sabre/file.php @@ -58,6 +58,11 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D throw new \Sabre_DAV_Exception_ServiceUnavailable(); } + $fileName = basename($this->path); + if (!\OCP\Util::isValidFileName($fileName)) { + throw new \Sabre_DAV_Exception_BadRequest(); + } + // chunked handling if (isset($_SERVER['HTTP_OC_CHUNKED'])) { return $this->createFileChunked($data); @@ -142,15 +147,16 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D * @throws Sabre_DAV_Exception_Forbidden */ public function delete() { + $fs = $this->getFS(); if ($this->path === 'Shared') { throw new \Sabre_DAV_Exception_Forbidden(); } - if (!\OC\Files\Filesystem::isDeletable($this->path)) { + if (!$fs->isDeletable($this->path)) { throw new \Sabre_DAV_Exception_Forbidden(); } - \OC\Files\Filesystem::unlink($this->path); + $fs->unlink($this->path); // remove properties $this->removeProperties(); @@ -206,6 +212,9 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D } + /** + * @param resource $data + */ private function createFileChunked($data) { list($path, $name) = \Sabre_DAV_URLUtil::splitPath($this->path); diff --git a/lib/private/connector/sabre/node.php b/lib/private/connector/sabre/node.php index 993aa73faeb..5807c5c7f71 100644 --- a/lib/private/connector/sabre/node.php +++ b/lib/private/connector/sabre/node.php @@ -85,19 +85,24 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr * @return void */ public function setName($name) { + $fs = $this->getFS(); // rename is only allowed if the update privilege is granted - if (!\OC\Files\Filesystem::isUpdatable($this->path)) { + if (!$fs->isUpdatable($this->path)) { throw new \Sabre_DAV_Exception_Forbidden(); } list($parentPath, ) = Sabre_DAV_URLUtil::splitPath($this->path); list(, $newName) = Sabre_DAV_URLUtil::splitPath($name); + if (!\OCP\Util::isValidFileName($newName)) { + throw new \Sabre_DAV_Exception_BadRequest(); + } + $newPath = $parentPath . '/' . $newName; $oldPath = $this->path; - \OC\Files\Filesystem::rename($this->path, $newPath); + $fs->rename($this->path, $newPath); $this->path = $newPath; @@ -153,9 +158,8 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr /** * @brief Updates properties on this node, - * @param array $mutations * @see Sabre_DAV_IProperties::updateProperties - * @return bool|array + * @return boolean */ public function updateProperties($properties) { $existing = $this->getProperties(array()); @@ -267,7 +271,7 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr } /** - * @return mixed + * @return string|null */ public function getFileId() { diff --git a/lib/private/connector/sabre/objecttree.php b/lib/private/connector/sabre/objecttree.php index d1e179af2ec..accf020daa2 100644 --- a/lib/private/connector/sabre/objecttree.php +++ b/lib/private/connector/sabre/objecttree.php @@ -94,6 +94,9 @@ class ObjectTree extends \Sabre_DAV_ObjectTree { } if ($sourceDir !== $destinationDir) { // for a full move we need update privileges on sourcePath and sourceDir as well as destinationDir + if (ltrim($destinationDir, '/') === '' && strtolower($sourceNode->getName()) === 'shared') { + throw new \Sabre_DAV_Exception_Forbidden(); + } if (!$fs->isUpdatable($sourceDir)) { throw new \Sabre_DAV_Exception_Forbidden(); } @@ -105,6 +108,11 @@ class ObjectTree extends \Sabre_DAV_ObjectTree { } } + $fileName = basename($destinationPath); + if (!\OCP\Util::isValidFileName($fileName)) { + throw new \Sabre_DAV_Exception_BadRequest(); + } + $renameOkay = $fs->rename($sourcePath, $destinationPath); if (!$renameOkay) { throw new \Sabre_DAV_Exception_Forbidden(''); diff --git a/lib/private/connector/sabre/principal.php b/lib/private/connector/sabre/principal.php index 59a96797c16..2075aa55c86 100644 --- a/lib/private/connector/sabre/principal.php +++ b/lib/private/connector/sabre/principal.php @@ -62,7 +62,7 @@ class OC_Connector_Sabre_Principal implements Sabre_DAVACL_IPrincipalBackend { * Returns the list of members for a group-principal * * @param string $principal - * @return array + * @return string[] */ public function getGroupMemberSet($principal) { // TODO: for now the group principal has only one member, the user itself diff --git a/lib/private/connector/sabre/quotaplugin.php b/lib/private/connector/sabre/quotaplugin.php index ea2cb81d1f7..8099794f670 100644 --- a/lib/private/connector/sabre/quotaplugin.php +++ b/lib/private/connector/sabre/quotaplugin.php @@ -45,8 +45,8 @@ class OC_Connector_Sabre_QuotaPlugin extends Sabre_DAV_ServerPlugin { /** * This method is called before any HTTP method and validates there is enough free space to store the file * - * @param string $method * @throws Sabre_DAV_Exception + * @param string $uri * @return bool */ public function checkQuota($uri, $data = null) { diff --git a/lib/private/connector/sabre/server.php b/lib/private/connector/sabre/server.php index 41e8885917a..2660b043f46 100644 --- a/lib/private/connector/sabre/server.php +++ b/lib/private/connector/sabre/server.php @@ -67,6 +67,7 @@ class OC_Connector_Sabre_Server extends Sabre_DAV_Server { /** * Small helper to support PROPFIND with DEPTH_INFINITY. + * @param string $path */ private function addPathNodesRecursively(&$nodes, $path) { foreach($this->tree->getChildren($path) as $childNode) { diff --git a/lib/private/davclient.php b/lib/private/davclient.php index 28f48f3b921..afa4e1103b4 100644 --- a/lib/private/davclient.php +++ b/lib/private/davclient.php @@ -31,7 +31,7 @@ class OC_DAVClient extends \Sabre_DAV_Client { /** * @brief Sets the request timeout or 0 to disable timeout. - * @param int timeout in seconds or 0 to disable + * @param integer $timeout in seconds or 0 to disable */ public function setRequestTimeout($timeout) { $this->requestTimeout = (int)$timeout; diff --git a/lib/private/db.php b/lib/private/db.php index 562065259fa..cfdac766bff 100644 --- a/lib/private/db.php +++ b/lib/private/db.php @@ -44,14 +44,14 @@ class OC_DB { /** * @var \OC\DB\Connection $connection */ - static private $connection; //the prefered connection to use, only Doctrine + static private $connection; //the preferred connection to use, only Doctrine static private $prefix=null; static private $type=null; /** * @brief connects to the database - * @return bool true if connection can be established or false on error + * @return boolean|null true if connection can be established or false on error * * Connects to the database as specified in config.php */ @@ -196,7 +196,7 @@ class OC_DB { * @param int $offset * @param bool $isManipulation * @throws DatabaseException - * @return \Doctrine\DBAL\Statement prepared SQL query + * @return OC_DB_StatementWrapper prepared SQL query * * SQL query via Doctrine prepare(), needs to be execute()'d! */ @@ -252,7 +252,7 @@ class OC_DB { * an array with 'sql' and optionally 'limit' and 'offset' keys * .. or a simple sql query string * @param array $parameters - * @return result + * @return OC_DB_StatementWrapper * @throws DatabaseException */ static public function executeAudited( $stmt, array $parameters = null) { @@ -298,7 +298,7 @@ class OC_DB { /** * @brief gets last value of autoincrement * @param string $table The optional table name (will replace *PREFIX*) and add sequence suffix - * @return int id + * @return string id * @throws DatabaseException * * \Doctrine\DBAL\Connection lastInsertId @@ -315,7 +315,8 @@ class OC_DB { * @brief Insert a row if a matching row doesn't exists. * @param string $table. The table to insert into in the form '*PREFIX*tableName' * @param array $input. An array of fieldname/value pairs - * @return int number of updated rows + * @param string $table + * @return boolean number of updated rows */ public static function insertIfNotExist($table, $input) { self::connect(); @@ -368,7 +369,7 @@ class OC_DB { * @brief update the database schema * @param string $file file to read structure from * @throws Exception - * @return bool + * @return string|boolean */ public static function updateDbFromStructure($file) { $schemaManager = self::getMDB2SchemaManager(); diff --git a/lib/private/db/connection.php b/lib/private/db/connection.php index 2581969dbd0..2bd7b093020 100644 --- a/lib/private/db/connection.php +++ b/lib/private/db/connection.php @@ -94,7 +94,7 @@ class Connection extends \Doctrine\DBAL\Connection { * If an SQLLogger is configured, the execution is logged. * * @param string $query The SQL query to execute. - * @param array $params The parameters to bind to the query, if any. + * @param string[] $params The parameters to bind to the query, if any. * @param array $types The types the previous parameters are in. * @param QueryCacheProfile $qcp * @return \Doctrine\DBAL\Driver\Statement The executed statement. diff --git a/lib/private/db/connectionwrapper.php b/lib/private/db/connectionwrapper.php index 93d4fb57f74..c2cfc21d204 100644 --- a/lib/private/db/connectionwrapper.php +++ b/lib/private/db/connectionwrapper.php @@ -31,8 +31,8 @@ class ConnectionWrapper implements \OCP\IDBConnection { /** * Used to get the id of the just inserted element - * @param string $tableName the name of the table where we inserted the item - * @return int the id of the inserted element + * @param string $table the name of the table where we inserted the item + * @return string the id of the inserted element */ public function lastInsertId($table = null) { diff --git a/lib/private/db/mdb2schemamanager.php b/lib/private/db/mdb2schemamanager.php index 6378c769055..aaf2ea543b9 100644 --- a/lib/private/db/mdb2schemamanager.php +++ b/lib/private/db/mdb2schemamanager.php @@ -53,7 +53,7 @@ class MDB2SchemaManager { /** * @brief update the database scheme * @param string $file file to read structure from - * @return bool + * @return string|boolean */ public function updateDbFromStructure($file, $generateSql = false) { $sm = $this->conn->getSchemaManager(); @@ -82,6 +82,9 @@ class MDB2SchemaManager { $platform = $this->conn->getDatabasePlatform(); foreach($schemaDiff->changedTables as $tableDiff) { $tableDiff->name = $platform->quoteIdentifier($tableDiff->name); + foreach($tableDiff->changedColumns as $column) { + $column->oldColumnName = $platform->quoteIdentifier($column->oldColumnName); + } } if ($generateSql) { diff --git a/lib/private/db/mdb2schemareader.php b/lib/private/db/mdb2schemareader.php index b1fd2454cb0..1c16d03eab2 100644 --- a/lib/private/db/mdb2schemareader.php +++ b/lib/private/db/mdb2schemareader.php @@ -41,7 +41,9 @@ class MDB2SchemaReader { */ public function loadSchemaFromFile($file) { $schema = new \Doctrine\DBAL\Schema\Schema(); + $loadEntities = libxml_disable_entity_loader(false); $xml = simplexml_load_file($file); + libxml_disable_entity_loader($loadEntities); foreach ($xml->children() as $child) { /** * @var \SimpleXMLElement $child @@ -288,12 +290,13 @@ class MDB2SchemaReader { if (!empty($fields)) { if (isset($primary) && $primary) { $table->setPrimaryKey($fields, $name); - } else + } else { if (isset($unique) && $unique) { $table->addUniqueIndex($fields, $name); } else { $table->addIndex($fields, $name); } + } } else { throw new \DomainException('Empty index definition: ' . $name . ' options:' . print_r($fields, true)); } diff --git a/lib/private/db/mdb2schemawriter.php b/lib/private/db/mdb2schemawriter.php index 21b43cbfe80..a2a62a81475 100644 --- a/lib/private/db/mdb2schemawriter.php +++ b/lib/private/db/mdb2schemawriter.php @@ -9,7 +9,7 @@ class OC_DB_MDB2SchemaWriter { /** - * @param $file + * @param string $file * @param \Doctrine\DBAL\Schema\AbstractSchemaManager $sm * @return bool */ @@ -26,6 +26,9 @@ class OC_DB_MDB2SchemaWriter { return true; } + /** + * @param SimpleXMLElement $xml + */ private static function saveTable($table, $xml) { $xml->addChild('name', $table->getName()); $declaration = $xml->addChild('declaration'); @@ -48,6 +51,9 @@ class OC_DB_MDB2SchemaWriter { } } + /** + * @param SimpleXMLElement $xml + */ private static function saveColumn($column, $xml) { $xml->addChild('name', $column->getName()); switch($column->getType()) { @@ -111,6 +117,9 @@ class OC_DB_MDB2SchemaWriter { } } + /** + * @param SimpleXMLElement $xml + */ private static function saveIndex($index, $xml) { $xml->addChild('name', $index->getName()); if ($index->isPrimary()) { diff --git a/lib/private/db/statementwrapper.php b/lib/private/db/statementwrapper.php index 5e89261d936..eaf215c7231 100644 --- a/lib/private/db/statementwrapper.php +++ b/lib/private/db/statementwrapper.php @@ -17,6 +17,9 @@ class OC_DB_StatementWrapper { private $isManipulation = false; private $lastArguments = array(); + /** + * @param boolean $isManipulation + */ public function __construct($statement, $isManipulation) { $this->statement = $statement; $this->isManipulation = $isManipulation; @@ -31,6 +34,9 @@ class OC_DB_StatementWrapper { /** * make execute return the result instead of a bool + * + * @param array $input + * @return \OC_DB_StatementWrapper | int */ public function execute($input=array()) { if(OC_Config::getValue( "log_query", false)) { @@ -169,4 +175,18 @@ class OC_DB_StatementWrapper { public function fetchOne($colnum = 0) { return $this->statement->fetchColumn($colnum); } + + /** + * Binds a PHP variable to a corresponding named or question mark placeholder in the + * SQL statement that was use to prepare the statement. + * + * @param mixed $column Either the placeholder name or the 1-indexed placeholder index + * @param mixed $variable The variable to bind + * @param integer|null $type one of the PDO::PARAM_* constants + * @param integer|null $length max length when using an OUT bind + * @return boolean + */ + public function bindParam($column, &$variable, $type = null, $length = null){ + return $this->statement->bindParam($column, $variable, $type, $length); + } } diff --git a/lib/private/defaults.php b/lib/private/defaults.php index cec9a65c7f3..79be211b82f 100644 --- a/lib/private/defaults.php +++ b/lib/private/defaults.php @@ -21,6 +21,7 @@ class OC_Defaults { private $defaultDocBaseUrl; private $defaultSlogan; private $defaultLogoClaim; + private $defaultMailHeaderColor; function __construct() { $this->l = OC_L10N::get('core'); @@ -33,12 +34,16 @@ class OC_Defaults { $this->defaultDocBaseUrl = "http://doc.owncloud.org"; $this->defaultSlogan = $this->l->t("web services under your control"); $this->defaultLogoClaim = ""; + $this->defaultMailHeaderColor = "#1d2d44"; /* header color of mail notifications */ if (class_exists("OC_Theme")) { $this->theme = new OC_Theme(); } } + /** + * @param string $method + */ private function themeExist($method) { if (OC_Util::getTheme() !== '' && method_exists('OC_Theme', $method)) { return true; @@ -171,4 +176,23 @@ class OC_Defaults { return $footer; } + public function buildDocLinkToKey($key) { + if ($this->themeExist('buildDocLinkToKey')) { + return $this->theme->buildDocLinkToKey($key); + } + return $this->getDocBaseUrl() . '/server/6.0/go.php?to=' . $key; + } + + /** + * Returns mail header color + * @return mail header color + */ + public function getMailHeaderColor() { + if ($this->themeExist('getMailHeaderColor')) { + return $this->theme->getMailHeaderColor(); + } else { + return $this->defaultMailHeaderColor; + } + } + } diff --git a/lib/private/eventsource.php b/lib/private/eventsource.php index 4df0bc2e7cd..5a41ddd8b37 100644 --- a/lib/private/eventsource.php +++ b/lib/private/eventsource.php @@ -63,8 +63,9 @@ class OC_EventSource{ $type=null; } if($this->fallback) { + $fallBackId = OC_Util::sanitizeHTML($this->fallBackId); $response='<script type="text/javascript">window.parent.OC.EventSource.fallBackCallBack(' - .$this->fallBackId.',"' . $type . '",' . OCP\JSON::encode($data) . ')</script>' . PHP_EOL; + .$fallBackId.',"' . $type . '",' . OCP\JSON::encode($data) . ')</script>' . PHP_EOL; echo $response; }else{ if($type) { diff --git a/lib/private/filechunking.php b/lib/private/filechunking.php index aa4f73c7c05..be7f4e14a11 100644 --- a/lib/private/filechunking.php +++ b/lib/private/filechunking.php @@ -16,6 +16,9 @@ class OC_FileChunking { return $matches; } + /** + * @param string[] $info + */ public function __construct($info) { $this->info = $info; } @@ -37,8 +40,8 @@ class OC_FileChunking { /** * Stores the given $data under the given $key - the number of stored bytes is returned * - * @param $index - * @param $data + * @param string $index + * @param resource $data * @return int */ public function store($index, $data) { @@ -87,7 +90,7 @@ class OC_FileChunking { /** * Removes one specific chunk - * @param $index + * @param string $index */ public function remove($index) { $cache = $this->getCache(); @@ -124,6 +127,9 @@ class OC_FileChunking { ); } + /** + * @param string $path + */ public function file_assemble($path) { $absolutePath = \OC\Files\Filesystem::normalizePath(\OC\Files\Filesystem::getView()->getAbsolutePath($path)); $data = ''; diff --git a/lib/private/fileproxy.php b/lib/private/fileproxy.php index 2997aaf81b6..88976c1b8e5 100644 --- a/lib/private/fileproxy.php +++ b/lib/private/fileproxy.php @@ -67,6 +67,9 @@ class OC_FileProxy{ self::$proxies[]=$proxy; } + /** + * @param string $operation + */ public static function getProxies($operation = null) { if ($operation === null) { // return all @@ -81,6 +84,10 @@ class OC_FileProxy{ return $proxies; } + /** + * @param string $operation + * @param string|boolean $filepath + */ public static function runPreProxies($operation,&$filepath,&$filepath2=null) { if(!self::$enabled) { return true; @@ -101,6 +108,12 @@ class OC_FileProxy{ return true; } + /** + * @param string $operation + * @param string|boolean $path + * + * @return string + */ public static function runPostProxies($operation, $path, $result) { if(!self::$enabled) { return $result; diff --git a/lib/private/files.php b/lib/private/files.php index 8ce632013cf..7e7a27f48dc 100644 --- a/lib/private/files.php +++ b/lib/private/files.php @@ -21,26 +21,46 @@ * */ +// TODO: get rid of this using proper composer packages +require_once 'mcnetic/phpzipstreamer/ZipStreamer.php'; + +class GET_TYPE { + const FILE = 1; + const ZIP_FILES = 2; + const ZIP_DIR = 3; +} + /** - * Class for fileserver access + * Class for file server access * */ class OC_Files { - static $tmpFiles = array(); - - static public function getFileInfo($path, $includeMountPoints = true){ - return \OC\Files\Filesystem::getFileInfo($path, $includeMountPoints); - } - static public function getDirectoryContent($path){ - return \OC\Files\Filesystem::getDirectoryContent($path); + /** + * @param string $filename + * @param string $name + * @param bool $zip + */ + private static function sendHeaders($filename, $name, $zip = false) { + OC_Response::setContentDispositionHeader($name, 'attachment'); + header('Content-Transfer-Encoding: binary'); + OC_Response::disableCaching(); + if ($zip) { + header('Content-Type: application/zip'); + } else { + $filesize = \OC\Files\Filesystem::filesize($filename); + header('Content-Type: '.\OC\Files\Filesystem::getMimeType($filename)); + if ($filesize > -1) { + header("Content-Length: ".$filesize); + } + } } /** * return the content of a file or return a zip file containing multiple files * * @param string $dir - * @param string $file ; separated list of files to download + * @param string $files ; separated list of files to download * @param boolean $only_header ; boolean to only send header of the request */ public static function get($dir, $files, $only_header = false) { @@ -51,92 +71,50 @@ class OC_Files { $xsendfile = true; } - if (is_array($files) && count($files) == 1) { + if (is_array($files) && count($files) === 1) { $files = $files[0]; } if (is_array($files)) { - self::validateZipDownload($dir, $files); - $executionTime = intval(ini_get('max_execution_time')); - set_time_limit(0); - $zip = new ZipArchive(); - $filename = OC_Helper::tmpFile('.zip'); - if ($zip->open($filename, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE)!==true) { - $l = OC_L10N::get('lib'); - throw new Exception($l->t('cannot open "%s"', array($filename))); - } - foreach ($files as $file) { - $file = $dir . '/' . $file; - if (\OC\Files\Filesystem::is_file($file)) { - $tmpFile = \OC\Files\Filesystem::toTmpFile($file); - self::$tmpFiles[] = $tmpFile; - $zip->addFile($tmpFile, basename($file)); - } elseif (\OC\Files\Filesystem::is_dir($file)) { - self::zipAddDir($file, $zip); - } - } - $zip->close(); - if ($xsendfile) { - $filename = OC_Helper::moveToNoClean($filename); - } + $get_type = GET_TYPE::ZIP_FILES; $basename = basename($dir); if ($basename) { $name = $basename . '.zip'; } else { $name = 'download.zip'; } - - set_time_limit($executionTime); - } elseif (\OC\Files\Filesystem::is_dir($dir . '/' . $files)) { - self::validateZipDownload($dir, $files); - $executionTime = intval(ini_get('max_execution_time')); - set_time_limit(0); - $zip = new ZipArchive(); - $filename = OC_Helper::tmpFile('.zip'); - if ($zip->open($filename, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE)!==true) { - $l = OC_L10N::get('lib'); - throw new Exception($l->t('cannot open "%s"', array($filename))); - } - $file = $dir . '/' . $files; - self::zipAddDir($file, $zip); - $zip->close(); - if ($xsendfile) { - $filename = OC_Helper::moveToNoClean($filename); - } - $name = $files . '.zip'; - set_time_limit($executionTime); + + $filename = $dir . '/' . $name; } else { - $zip = false; $filename = $dir . '/' . $files; - $name = $files; + if (\OC\Files\Filesystem::is_dir($dir . '/' . $files)) { + $get_type = GET_TYPE::ZIP_DIR; + // downloading root ? + if ($files === '') { + $name = 'download.zip'; + } else { + $name = $files . '.zip'; + } + + } else { + $get_type = GET_TYPE::FILE; + $name = $files; + } + } + + if ($get_type === GET_TYPE::FILE) { + $zip = false; if ($xsendfile && OC_App::isEnabled('files_encryption')) { $xsendfile = false; } + } else { + self::validateZipDownload($dir, $files); + $zip = new ZipStreamer(false); } OC_Util::obEnd(); if ($zip or \OC\Files\Filesystem::isReadable($filename)) { - OC_Response::setContentDispositionHeader($name, 'attachment'); - header('Content-Transfer-Encoding: binary'); - OC_Response::disableCaching(); - if ($zip) { - ini_set('zlib.output_compression', 'off'); - header('Content-Type: application/zip'); - header('Content-Length: ' . filesize($filename)); - self::addSendfileHeader($filename); - }else{ - $filesize = \OC\Files\Filesystem::filesize($filename); - header('Content-Type: '.\OC\Files\Filesystem::getMimeType($filename)); - if ($filesize > -1) { - header("Content-Length: ".$filesize); - } - if ($xsendfile) { - list($storage) = \OC\Files\Filesystem::resolvePath(\OC\Files\Filesystem::getView()->getAbsolutePath($filename)); - if ($storage instanceof \OC\Files\Storage\Local) { - self::addSendfileHeader(\OC\Files\Filesystem::getLocalFile($filename)); - } - } - } - } elseif ($zip or !\OC\Files\Filesystem::file_exists($filename)) { + self::sendHeaders($filename, $name, $zip); + } elseif (!\OC\Files\Filesystem::file_exists($filename)) { header("HTTP/1.0 404 Not Found"); $tmpl = new OC_Template('', '404', 'guest'); $tmpl->assign('file', $name); @@ -149,36 +127,52 @@ class OC_Files { return ; } if ($zip) { - $handle = fopen($filename, 'r'); - if ($handle) { - $chunkSize = 8 * 1024; // 1 MB chunks - while (!feof($handle)) { - echo fread($handle, $chunkSize); - flush(); + $executionTime = intval(ini_get('max_execution_time')); + set_time_limit(0); + if ($get_type === GET_TYPE::ZIP_FILES) { + foreach ($files as $file) { + $file = $dir . '/' . $file; + if (\OC\Files\Filesystem::is_file($file)) { + $fh = \OC\Files\Filesystem::fopen($file, 'r'); + $zip->addFileFromStream($fh, basename($file)); + fclose($fh); + } elseif (\OC\Files\Filesystem::is_dir($file)) { + self::zipAddDir($file, $zip); + } } + } elseif ($get_type === GET_TYPE::ZIP_DIR) { + $file = $dir . '/' . $files; + self::zipAddDir($file, $zip); } - if (!$xsendfile) { - unlink($filename); - } - }else{ - \OC\Files\Filesystem::readfile($filename); - } - foreach (self::$tmpFiles as $tmpFile) { - if (file_exists($tmpFile) and is_file($tmpFile)) { - unlink($tmpFile); + $zip->finalize(); + set_time_limit($executionTime); + } else { + if ($xsendfile) { + /** @var $storage \OC\Files\Storage\Storage */ + list($storage) = \OC\Files\Filesystem::resolvePath($filename); + if ($storage->isLocal()) { + self::addSendfileHeader(\OC\Files\Filesystem::getLocalFile($filename)); + } else { + \OC\Files\Filesystem::readfile($filename); + } + } else { + \OC\Files\Filesystem::readfile($filename); } } } + /** + * @param false|string $filename + */ private static function addSendfileHeader($filename) { if (isset($_SERVER['MOD_X_SENDFILE_ENABLED'])) { header("X-Sendfile: " . $filename); } if (isset($_SERVER['MOD_X_SENDFILE2_ENABLED'])) { - if (isset($_SERVER['HTTP_RANGE']) && + if (isset($_SERVER['HTTP_RANGE']) && preg_match("/^bytes=([0-9]+)-([0-9]*)$/", $_SERVER['HTTP_RANGE'], $range)) { $filelength = filesize($filename); - if ($range[2] == "") { + if ($range[2] === "") { $range[2] = $filelength - 1; } header("Content-Range: bytes $range[1]-$range[2]/" . $filelength); @@ -188,24 +182,35 @@ class OC_Files { header("X-Sendfile: " . $filename); } } - + if (isset($_SERVER['MOD_X_ACCEL_REDIRECT_ENABLED'])) { header("X-Accel-Redirect: " . $filename); } } + /** + * @param string $dir + * @param ZipStreamer $zip + * @param string $internalDir + */ public static function zipAddDir($dir, $zip, $internalDir='') { $dirname=basename($dir); - $zip->addEmptyDir($internalDir.$dirname); + $rootDir = $internalDir.$dirname; + if (!empty($rootDir)) { + $zip->addEmptyDir($rootDir); + } $internalDir.=$dirname.='/'; - $files=OC_Files::getDirectoryContent($dir); + // prevent absolute dirs + $internalDir = ltrim($internalDir, '/'); + + $files=\OC\Files\Filesystem::getDirectoryContent($dir); foreach($files as $file) { $filename=$file['name']; $file=$dir.'/'.$filename; if(\OC\Files\Filesystem::is_file($file)) { - $tmpFile=\OC\Files\Filesystem::toTmpFile($file); - OC_Files::$tmpFiles[]=$tmpFile; - $zip->addFile($tmpFile, $internalDir.$filename); + $fh = \OC\Files\Filesystem::fopen($file, 'r'); + $zip->addFileFromStream($fh, $internalDir.$filename); + fclose($fh); }elseif(\OC\Files\Filesystem::is_dir($file)) { self::zipAddDir($file, $zip, $internalDir); } @@ -215,8 +220,8 @@ class OC_Files { /** * checks if the selected files are within the size constraint. If not, outputs an error page. * - * @param dir $dir - * @param files $files + * @param string $dir + * @param array | string $files */ static function validateZipDownload($dir, $files) { if (!OC_Config::getValue('allowZipDownload', true)) { @@ -263,8 +268,8 @@ class OC_Files { /** * set the maximum upload size limit for apache hosts using .htaccess * - * @param int size filesisze in bytes - * @return false on failure, size on success + * @param int $size file size in bytes + * @return bool false on failure, size on success */ static function setUploadLimit($size) { //don't allow user to break his config -- upper boundary @@ -280,11 +285,12 @@ class OC_Files { } //don't allow user to break his config -- broken or malicious size input - if (intval($size) == 0) { + if (intval($size) === 0) { return false; } - $htaccess = @file_get_contents(OC::$SERVERROOT . '/.htaccess'); //supress errors in case we don't have permissions for + //suppress errors in case we don't have permissions for + $htaccess = @file_get_contents(OC::$SERVERROOT . '/.htaccess'); if (!$htaccess) { return false; } @@ -302,7 +308,7 @@ class OC_Files { if ($content !== null) { $htaccess = $content; } - if ($hasReplaced == 0) { + if ($hasReplaced === 0) { $htaccess .= "\n" . $setting; } } diff --git a/lib/private/files/cache/backgroundwatcher.php b/lib/private/files/cache/backgroundwatcher.php index 923804f48d0..2194651233d 100644 --- a/lib/private/files/cache/backgroundwatcher.php +++ b/lib/private/files/cache/backgroundwatcher.php @@ -24,6 +24,9 @@ class BackgroundWatcher { return $row['id']; } + /** + * @param integer $id + */ static private function checkUpdate($id) { $cacheItem = Cache::getById($id); if (is_null($cacheItem)) { diff --git a/lib/private/files/cache/cache.php b/lib/private/files/cache/cache.php index 1e7936ca26d..9b18257088c 100644 --- a/lib/private/files/cache/cache.php +++ b/lib/private/files/cache/cache.php @@ -166,6 +166,16 @@ class Cache { */ public function getFolderContents($folder) { $fileId = $this->getId($folder); + return $this->getFolderContentsById($fileId); + } + + /** + * get the metadata of all files stored in $folder + * + * @param int $fileId the file id of the folder + * @return array + */ + public function getFolderContentsById($fileId) { if ($fileId > -1) { $sql = 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `storage_mtime`, `encrypted`, `unencrypted_size`, `etag` @@ -487,7 +497,7 @@ class Cache { /** * update the folder size and the size of all parent folders * - * @param $path + * @param string|boolean $path */ public function correctFolderSize($path) { $this->calculateFolderSize($path); diff --git a/lib/private/files/cache/homecache.php b/lib/private/files/cache/homecache.php index 71bb944da71..82f31d0867d 100644 --- a/lib/private/files/cache/homecache.php +++ b/lib/private/files/cache/homecache.php @@ -16,7 +16,7 @@ class HomeCache extends Cache { * @return int */ public function calculateFolderSize($path) { - if ($path !== '/' and $path !== '' and $path !== 'files') { + if ($path !== '/' and $path !== '' and $path !== 'files' and $path !== 'files_trashbin') { return parent::calculateFolderSize($path); } @@ -24,20 +24,28 @@ class HomeCache extends Cache { $entry = $this->get($path); if ($entry && $entry['mimetype'] === 'httpd/unix-directory') { $id = $entry['fileid']; - $sql = 'SELECT SUM(`size`) FROM `*PREFIX*filecache` ' . + $sql = 'SELECT SUM(`size`) AS f1, ' . + 'SUM(`unencrypted_size`) AS f2 FROM `*PREFIX*filecache` ' . 'WHERE `parent` = ? AND `storage` = ? AND `size` >= 0'; $result = \OC_DB::executeAudited($sql, array($id, $this->getNumericStorageId())); if ($row = $result->fetchRow()) { - list($sum) = array_values($row); + list($sum, $unencryptedSum) = array_values($row); $totalSize = (int)$sum; + $unencryptedSize = (int)$unencryptedSum; if ($entry['size'] !== $totalSize) { $this->update($id, array('size' => $totalSize)); } + if ($entry['unencrypted_size'] !== $unencryptedSize) { + $this->update($id, array('unencrypted_size' => $unencryptedSize)); + } } } return $totalSize; } + /** + * @param string $path + */ public function get($path) { $data = parent::get($path); if ($path === '' or $path === '/') { diff --git a/lib/private/files/cache/legacy.php b/lib/private/files/cache/legacy.php deleted file mode 100644 index 8eed1f67a5d..00000000000 --- a/lib/private/files/cache/legacy.php +++ /dev/null @@ -1,136 +0,0 @@ -<?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\Cache; - -/** - * Provide read only support for the old filecache - */ -class Legacy { - private $user; - - private $cacheHasItems = null; - - public function __construct($user) { - $this->user = $user; - } - - /** - * get the numbers of items in the legacy cache - * - * @return int - */ - function getCount() { - $sql = 'SELECT COUNT(`id`) AS `count` FROM `*PREFIX*fscache` WHERE `user` = ?'; - $result = \OC_DB::executeAudited($sql, array($this->user)); - if ($row = $result->fetchRow()) { - return $row['count']; - } else { - return 0; - } - } - - /** - * check if a legacy cache is present and holds items - * - * @return bool - */ - function hasItems() { - if (!is_null($this->cacheHasItems)) { - return $this->cacheHasItems; - } - try { - $query = \OC_DB::prepare('SELECT `id` FROM `*PREFIX*fscache` WHERE `user` = ?',1); - } catch (\Exception $e) { - $this->cacheHasItems = false; - return false; - } - try { - $result = $query->execute(array($this->user)); - } catch (\Exception $e) { - $this->cacheHasItems = false; - return false; - } - - if ($result === false || property_exists($result, 'error_message_prefix')) { - $this->cacheHasItems = false; - return false; - } - - $this->cacheHasItems = (bool)$result->fetchRow(); - return $this->cacheHasItems; - } - - /** - * get an item from the legacy cache - * - * @param string|int $path - * @return array - */ - function get($path) { - if (is_numeric($path)) { - $sql = 'SELECT * FROM `*PREFIX*fscache` WHERE `id` = ?'; - } else { - $sql = 'SELECT * FROM `*PREFIX*fscache` WHERE `path` = ?'; - } - $result = \OC_DB::executeAudited($sql, array($path)); - $data = $result->fetchRow(); - $data['etag'] = $this->getEtag($data['path'], $data['user']); - return $data; - } - - /** - * Get the ETag for the given path - * - * @param type $path - * @return string - */ - function getEtag($path, $user = null) { - static $query = null; - - $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\''); - } - $result = \OC_DB::executeAudited($query,array($user, '/' . $relativePath)); - if ($row = $result->fetchRow()) { - return trim($row['propertyvalue'], '"'); - } else { - return ''; - } - } - - /** - * get all child items of an item from the legacy cache - * - * @param int $id - * @return array - */ - function getChildren($id) { - $result = \OC_DB::executeAudited('SELECT * FROM `*PREFIX*fscache` WHERE `parent` = ?', array($id)); - $data = $result->fetchAll(); - foreach ($data as $i => $item) { - $data[$i]['etag'] = $this->getEtag($item['path'], $item['user']); - } - return $data; - } -} diff --git a/lib/private/files/cache/storage.php b/lib/private/files/cache/storage.php index 5657cf06e12..6b6b0bce9d7 100644 --- a/lib/private/files/cache/storage.php +++ b/lib/private/files/cache/storage.php @@ -47,6 +47,9 @@ class Storage { return $this->numericId; } + /** + * @return string + */ public static function getStorageId($numericId) { $sql = 'SELECT `id` FROM `*PREFIX*storages` WHERE `numeric_id` = ?'; @@ -58,6 +61,9 @@ class Storage { } } + /** + * @param string $storageId + */ public static function exists($storageId) { if (strlen($storageId) > 64) { $storageId = md5($storageId); @@ -70,4 +76,23 @@ class Storage { return false; } } + + /** + * remove the entry for the storage + * + * @param string $storageId + */ + public static function remove($storageId) { + $storageCache = new Storage($storageId); + $numericId = $storageCache->getNumericId(); + + if (strlen($storageId) > 64) { + $storageId = md5($storageId); + } + $sql = 'DELETE FROM `*PREFIX*storages` WHERE `id` = ?'; + \OC_DB::executeAudited($sql, array($storageId)); + + $sql = 'DELETE FROM `*PREFIX*filecache` WHERE `storage` = ?'; + \OC_DB::executeAudited($sql, array($numericId)); + } } diff --git a/lib/private/files/cache/updater.php b/lib/private/files/cache/updater.php index 73bc30e538f..7a45b9e9e96 100644 --- a/lib/private/files/cache/updater.php +++ b/lib/private/files/cache/updater.php @@ -8,8 +8,6 @@ namespace OC\Files\Cache; -use OCP\Util; - /** * listen to filesystem hooks and change the cache accordingly */ @@ -112,7 +110,7 @@ class Updater { /** * @brief get file owner and path * @param string $filename - * @return array with the oweners uid and the owners path + * @return string[] with the oweners uid and the owners path */ private static function getUidAndFilename($filename) { diff --git a/lib/private/files/cache/upgrade.php b/lib/private/files/cache/upgrade.php deleted file mode 100644 index e3a46896cbf..00000000000 --- a/lib/private/files/cache/upgrade.php +++ /dev/null @@ -1,235 +0,0 @@ -<?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\Cache; - -class Upgrade { - /** - * @var Legacy $legacy - */ - private $legacy; - - private $numericIds = array(); - - private $mimeTypeIds = array(); - - /** - * @param Legacy $legacy - */ - public function __construct($legacy) { - $this->legacy = $legacy; - } - - /** - * Preform a upgrade a path and it's childs - * - * @param string $path - * @param bool $mode - */ - function upgradePath($path, $mode = Scanner::SCAN_RECURSIVE) { - if (!$this->legacy->hasItems()) { - return; - } - \OC_Hook::emit('\OC\Files\Cache\Upgrade', 'migrate_path', $path); - if ($row = $this->legacy->get($path)) { - $data = $this->getNewData($row); - if ($data) { - $this->insert($data); - $this->upgradeChilds($data['id'], $mode); - } - } - } - - /** - * upgrade all child elements of an item - * - * @param int $id - * @param bool $mode - */ - function upgradeChilds($id, $mode = Scanner::SCAN_RECURSIVE) { - $children = $this->legacy->getChildren($id); - foreach ($children as $child) { - $childData = $this->getNewData($child); - \OC_Hook::emit('\OC\Files\Cache\Upgrade', 'migrate_path', $child['path']); - if ($childData) { - $this->insert($childData); - if ($mode == Scanner::SCAN_RECURSIVE) { - $this->upgradeChilds($child['id']); - } - } - } - } - - /** - * insert data into the new cache - * - * @param array $data the data for the new cache - */ - function insert($data) { - static $insertQuery = null; - if(is_null($insertQuery)) { - $insertQuery = \OC_DB::prepare('INSERT INTO `*PREFIX*filecache` - ( `fileid`, `storage`, `path`, `path_hash`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `etag` ) - VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'); - } - if (!$this->inCache($data['storage'], $data['path_hash'], $data['id'])) { - \OC_DB::executeAudited($insertQuery, array($data['id'], $data['storage'], - $data['path'], $data['path_hash'], $data['parent'], $data['name'], - $data['mimetype'], $data['mimepart'], $data['size'], $data['mtime'], $data['encrypted'], $data['etag'])); - } - } - - /** - * check if an item is already in the new cache - * - * @param string $storage - * @param string $pathHash - * @param string $id - * @return bool - */ - function inCache($storage, $pathHash, $id) { - static $query = null; - if(is_null($query)) { - $query = \OC_DB::prepare('SELECT `fileid` FROM `*PREFIX*filecache` WHERE (`storage` = ? AND `path_hash` = ?) OR `fileid` = ?'); - } - $result = \OC_DB::executeAudited($query, array($storage, $pathHash, $id)); - return (bool)$result->fetchRow(); - } - - /** - * get the new data array from the old one - * - * @param array $data the data from the old cache - * Example data array - * Array - * ( - * [id] => 418 - * [path] => /tina/files/picture.jpg //relative to datadir - * [path_hash] => 66d4547e372888deed80b24fec9b192b - * [parent] => 234 - * [name] => picture.jpg - * [user] => tina - * [size] => 1265283 - * [ctime] => 1363909709 - * [mtime] => 1363909709 - * [mimetype] => image/jpeg - * [mimepart] => image - * [encrypted] => 0 - * [versioned] => 0 - * [writable] => 1 - * ) - * - * @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 - * @var string $internalPath; - */ - list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($data['path']); - if ($storage) { - $newData['etag'] = $data['etag']; - $newData['path_hash'] = md5($internalPath); - $newData['path'] = $internalPath; - $newData['storage'] = $this->getNumericId($storage); - $newData['parent'] = ($internalPath === '') ? -1 : $data['parent']; - $newData['permissions'] = ($data['writable']) ? \OCP\PERMISSION_ALL : \OCP\PERMISSION_READ; - $newData['storage_object'] = $storage; - $newData['mimetype'] = $this->getMimetypeId($newData['mimetype'], $storage); - $newData['mimepart'] = $this->getMimetypeId($newData['mimepart'], $storage); - return $newData; - } else { - \OC_Log::write('core', 'Unable to migrate data from old cache for '.$data['path'].' because the storage was not found', \OC_Log::ERROR); - return false; - } - } - - /** - * get the numeric storage id - * - * @param \OC\Files\Storage\Storage $storage - * @return int - */ - function getNumericId($storage) { - $storageId = $storage->getId(); - if (!isset($this->numericIds[$storageId])) { - $cache = $storage->getCache(); - $this->numericIds[$storageId] = $cache->getNumericStorageId(); - } - return $this->numericIds[$storageId]; - } - - /** - * get the numeric id for a mimetype - * - * @param string $mimetype - * @param \OC\Files\Storage\Storage $storage - * @return int - */ - function getMimetypeId($mimetype, $storage) { - if (!isset($this->mimeTypeIds[$mimetype])) { - $cache = new Cache($storage); - $this->mimeTypeIds[$mimetype] = $cache->getMimetypeId($mimetype); - } - return $this->mimeTypeIds[$mimetype]; - } - - /** - * check if a cache upgrade is required for $user - * - * @param string $user - * @return bool - */ - static function needUpgrade($user) { - $cacheVersion = (int)\OCP\Config::getUserValue($user, 'files', 'cache_version', 4); - if ($cacheVersion < 5) { - $legacy = new \OC\Files\Cache\Legacy($user); - if ($legacy->hasItems()) { - return true; - } - self::upgradeDone($user); - } - - return false; - } - - /** - * mark the filecache as upgrade - * - * @param string $user - */ - static function upgradeDone($user) { - \OCP\Config::setUserValue($user, 'files', 'cache_version', 5); - } - - /** - * Does a "silent" upgrade, i.e. without an Event-Source as triggered - * on User-Login via Ajax. This method is called within the regular - * ownCloud upgrade. - * - * @param string $user a User ID - */ - public static function doSilentUpgrade($user) { - if(!self::needUpgrade($user)) { - return; - } - $legacy = new \OC\Files\Cache\Legacy($user); - if ($legacy->hasItems()) { - \OC_DB::beginTransaction(); - $upgrade = new \OC\Files\Cache\Upgrade($legacy); - $upgrade->upgradePath('/' . $user . '/files'); - \OC_DB::commit(); - } - \OC\Files\Cache\Upgrade::upgradeDone($user); - } -} diff --git a/lib/private/files/cache/watcher.php b/lib/private/files/cache/watcher.php index 251ecbe7071..48aa6f853ce 100644 --- a/lib/private/files/cache/watcher.php +++ b/lib/private/files/cache/watcher.php @@ -12,6 +12,14 @@ namespace OC\Files\Cache; * check the storage backends for updates and change the cache accordingly */ class Watcher { + const CHECK_NEVER = 0; // never check the underlying filesystem for updates + const CHECK_ONCE = 1; // check the underlying filesystem for updates once every request for each file + const CHECK_ALWAYS = 2; // always check the underlying filesystem for updates + + protected $watchPolicy = self::CHECK_ONCE; + + protected $checkedPaths = array(); + /** * @var \OC\Files\Storage\Storage $storage */ @@ -23,7 +31,7 @@ class Watcher { protected $cache; /** - * @var Scanner $scanner; + * @var Scanner $scanner ; */ protected $scanner; @@ -37,26 +45,38 @@ class Watcher { } /** + * @param int $policy either \OC\Files\Cache\Watcher::UPDATE_NEVER, \OC\Files\Cache\Watcher::UPDATE_ONCE, \OC\Files\Cache\Watcher::UPDATE_ALWAYS + */ + public function setPolicy($policy) { + $this->watchPolicy = $policy; + } + + /** * check $path for updates * * @param string $path * @return boolean | array true if path was updated, otherwise the cached data is returned */ public function checkUpdate($path) { - $cachedEntry = $this->cache->get($path); - if ($this->storage->hasUpdated($path, $cachedEntry['storage_mtime'])) { - if ($this->storage->is_dir($path)) { - $this->scanner->scan($path, Scanner::SCAN_SHALLOW); - } else { - $this->scanner->scanFile($path); - } - if ($cachedEntry['mimetype'] === 'httpd/unix-directory') { - $this->cleanFolder($path); + if ($this->watchPolicy === self::CHECK_ALWAYS or ($this->watchPolicy === self::CHECK_ONCE and array_search($path, $this->checkedPaths) === false)) { + $cachedEntry = $this->cache->get($path); + $this->checkedPaths[] = $path; + if ($this->storage->hasUpdated($path, $cachedEntry['storage_mtime'])) { + if ($this->storage->is_dir($path)) { + $this->scanner->scan($path, Scanner::SCAN_SHALLOW); + } else { + $this->scanner->scanFile($path); + } + if ($cachedEntry['mimetype'] === 'httpd/unix-directory') { + $this->cleanFolder($path); + } + $this->cache->correctFolderSize($path); + return true; } - $this->cache->correctFolderSize($path); - return true; + return $cachedEntry; + } else { + return false; } - return $cachedEntry; } /** diff --git a/lib/private/files/fileinfo.php b/lib/private/files/fileinfo.php new file mode 100644 index 00000000000..d6940f50bf1 --- /dev/null +++ b/lib/private/files/fileinfo.php @@ -0,0 +1,199 @@ +<?php +/** + * Copyright (c) 2014 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; + +class FileInfo implements \OCP\Files\FileInfo, \ArrayAccess { + /** + * @var array $data + */ + private $data; + + /** + * @var string $path + */ + private $path; + + /** + * @var \OC\Files\Storage\Storage $storage + */ + private $storage; + + /** + * @var string $internalPath + */ + private $internalPath; + + /** + * @param string|boolean $path + * @param Storage\Storage $storage + */ + public function __construct($path, $storage, $internalPath, $data) { + $this->path = $path; + $this->storage = $storage; + $this->internalPath = $internalPath; + $this->data = $data; + } + + public function offsetSet($offset, $value) { + $this->data[$offset] = $value; + } + + public function offsetExists($offset) { + return isset($this->data[$offset]); + } + + public function offsetUnset($offset) { + unset($this->data[$offset]); + } + + public function offsetGet($offset) { + if ($offset === 'type') { + return $this->getType(); + } elseif (isset($this->data[$offset])) { + return $this->data[$offset]; + } else { + return null; + } + } + + /** + * @return string + */ + public function getPath() { + return $this->path; + } + + /** + * @return \OCP\Files\Storage + */ + public function getStorage() { + return $this->storage; + } + + /** + * @return string + */ + public function getInternalPath() { + return $this->internalPath; + } + + /** + * @return int + */ + public function getId() { + return $this->data['fileid']; + } + + /** + * @return string + */ + public function getMimetype() { + return $this->data['mimetype']; + } + + /** + * @return string + */ + public function getMimePart() { + return $this->data['mimepart']; + } + + /** + * @return string + */ + public function getName() { + return $this->data['name']; + } + + /** + * @return string + */ + public function getEtag() { + return $this->data['etag']; + } + + /** + * @return int + */ + public function getSize() { + return $this->data['size']; + } + + /** + * @return int + */ + public function getMTime() { + return $this->data['mtime']; + } + + /** + * @return bool + */ + public function isEncrypted() { + return $this->data['encrypted']; + } + + /** + * @return int + */ + public function getPermissions() { + return $this->data['permissions']; + } + + /** + * @return \OCP\Files\FileInfo::TYPE_FILE | \OCP\Files\FileInfo::TYPE_FOLDER + */ + public function getType() { + if (isset($this->data['type'])) { + return $this->data['type']; + } else { + return $this->getMimetype() === 'httpd/unix-directory' ? self::TYPE_FOLDER : self::TYPE_FILE; + } + } + + public function getData() { + return $this->data; + } + + /** + * @param int $permissions + * @return bool + */ + protected function checkPermissions($permissions) { + return ($this->getPermissions() & $permissions) === $permissions; + } + + /** + * @return bool + */ + public function isReadable() { + return $this->checkPermissions(\OCP\PERMISSION_READ); + } + + /** + * @return bool + */ + public function isUpdateable() { + return $this->checkPermissions(\OCP\PERMISSION_UPDATE); + } + + /** + * @return bool + */ + public function isDeletable() { + return $this->checkPermissions(\OCP\PERMISSION_DELETE); + } + + /** + * @return bool + */ + public function isShareable() { + return $this->checkPermissions(\OCP\PERMISSION_SHARE); + } +} diff --git a/lib/private/files/filesystem.php b/lib/private/files/filesystem.php index a83e9aa86d2..c31e0c38180 100644 --- a/lib/private/files/filesystem.php +++ b/lib/private/files/filesystem.php @@ -320,81 +320,12 @@ class Filesystem { else { self::mount('\OC\Files\Storage\Local', array('datadir' => $root), $user); } - $datadir = \OC_Config::getValue("datadirectory", \OC::$SERVERROOT . "/data"); - - //move config file to it's new position - if (is_file(\OC::$SERVERROOT . '/config/mount.json')) { - rename(\OC::$SERVERROOT . '/config/mount.json', $datadir . '/mount.json'); - } - // Load system mount points - if (is_file(\OC::$SERVERROOT . '/config/mount.php') or is_file($datadir . '/mount.json')) { - if (is_file($datadir . '/mount.json')) { - $mountConfig = json_decode(file_get_contents($datadir . '/mount.json'), true); - } elseif (is_file(\OC::$SERVERROOT . '/config/mount.php')) { - $mountConfig = $parser->parsePHP(file_get_contents(\OC::$SERVERROOT . '/config/mount.php')); - } - if (isset($mountConfig['global'])) { - foreach ($mountConfig['global'] as $mountPoint => $options) { - self::mount($options['class'], $options['options'], $mountPoint); - } - } - if (isset($mountConfig['group'])) { - foreach ($mountConfig['group'] as $group => $mounts) { - if (\OC_Group::inGroup($user, $group)) { - foreach ($mounts as $mountPoint => $options) { - $mountPoint = self::setUserVars($user, $mountPoint); - foreach ($options as &$option) { - $option = self::setUserVars($user, $option); - } - self::mount($options['class'], $options['options'], $mountPoint); - } - } - } - } - if (isset($mountConfig['user'])) { - foreach ($mountConfig['user'] as $mountUser => $mounts) { - if ($mountUser === 'all' or strtolower($mountUser) === strtolower($user)) { - foreach ($mounts as $mountPoint => $options) { - $mountPoint = self::setUserVars($user, $mountPoint); - foreach ($options as &$option) { - $option = self::setUserVars($user, $option); - } - self::mount($options['class'], $options['options'], $mountPoint); - } - } - } - } - } - // Load personal mount points - if (is_file($root . '/mount.php') or is_file($root . '/mount.json')) { - if (is_file($root . '/mount.json')) { - $mountConfig = json_decode(file_get_contents($root . '/mount.json'), true); - } elseif (is_file($root . '/mount.php')) { - $mountConfig = $parser->parsePHP(file_get_contents($root . '/mount.php')); - } - if (isset($mountConfig['user'][$user])) { - foreach ($mountConfig['user'][$user] as $mountPoint => $options) { - self::mount($options['class'], $options['options'], $mountPoint); - } - } - } // Chance to mount for other storages \OC_Hook::emit('OC_Filesystem', 'post_initMountPoints', array('user' => $user, 'user_dir' => $root)); } /** - * fill in the correct values for $user - * - * @param string $user - * @param string $input - * @return string - */ - private static function setUserVars($user, $input) { - return str_replace('$user', $user, $input); - } - - /** * get the default filesystem view * * @return View @@ -614,6 +545,9 @@ class Filesystem { return self::$defaultInstance->touch($path, $mtime); } + /** + * @return string + */ static public function file_get_contents($path) { return self::$defaultInstance->file_get_contents($path); } @@ -638,6 +572,9 @@ class Filesystem { return self::$defaultInstance->fopen($path, $mode); } + /** + * @return string + */ static public function toTmpFile($path) { return self::$defaultInstance->toTmpFile($path); } @@ -662,6 +599,9 @@ class Filesystem { return self::$defaultInstance->search($query); } + /** + * @param string $query + */ static public function searchByMime($query) { return self::$defaultInstance->searchByMime($query); } @@ -727,14 +667,7 @@ class Filesystem { * @param string $path * @param boolean $includeMountPoints whether to add mountpoint sizes, * defaults to true - * @return array - * - * returns an associative array with the following keys: - * - size - * - mtime - * - mimetype - * - encrypted - * - versioned + * @return \OC\Files\FileInfo */ public static function getFileInfo($path, $includeMountPoints = true) { return self::$defaultInstance->getFileInfo($path, $includeMountPoints); @@ -758,7 +691,7 @@ class Filesystem { * * @param string $directory path under datadirectory * @param string $mimetype_filter limit returned content to this mimetype or mimepart - * @return array + * @return \OC\Files\FileInfo[] */ public static function getDirectoryContent($directory, $mimetype_filter = '') { return self::$defaultInstance->getDirectoryContent($directory, $mimetype_filter); diff --git a/lib/private/files/mapper.php b/lib/private/files/mapper.php index 47abd4e52fe..833d4bd8d1c 100644 --- a/lib/private/files/mapper.php +++ b/lib/private/files/mapper.php @@ -44,7 +44,7 @@ class Mapper /** * @param string $path * @param bool $isLogicPath indicates if $path is logical or physical - * @param $recursive + * @param boolean $recursive * @return void */ public function removePath($path, $isLogicPath, $recursive) { @@ -60,8 +60,8 @@ class Mapper } /** - * @param $path1 - * @param $path2 + * @param string $path1 + * @param string $path2 * @throws \Exception */ public function copy($path1, $path2) @@ -99,7 +99,7 @@ class Mapper /** * @param $path * @param $root - * @return bool|string + * @return false|string */ public function stripRootFolder($path, $root) { if (strpos($path, $root) !== 0) { @@ -120,6 +120,9 @@ class Mapper return $path; } + /** + * @param string $logicPath + */ private function resolveLogicPath($logicPath) { $logicPath = $this->stripLast($logicPath); $sql = 'SELECT * FROM `*PREFIX*file_map` WHERE `logic_path_hash` = ?'; @@ -141,6 +144,10 @@ class Mapper return $result['logic_path']; } + /** + * @param string $logicPath + * @param boolean $store + */ private function create($logicPath, $store) { $logicPath = $this->stripLast($logicPath); $index = 0; @@ -167,6 +174,9 @@ class Mapper \OC_DB::executeAudited($sql, array($logicPath, $physicalPath, md5($logicPath), md5($physicalPath))); } + /** + * @param integer $index + */ public function slugifyPath($path, $index=null) { $path = $this->stripRootFolder($path, $this->unchangedPhysicalRoot); diff --git a/lib/private/files/mount/manager.php b/lib/private/files/mount/manager.php index 4c432dcf724..ff4a336f347 100644 --- a/lib/private/files/mount/manager.php +++ b/lib/private/files/mount/manager.php @@ -106,7 +106,7 @@ class Manager { * Find mounts by numeric storage id * * @param string $id - * @return Mount + * @return Mount[] */ public function findByNumericId($id) { $storageId = \OC\Files\Cache\Storage::getStorageId($id); diff --git a/lib/private/files/node/folder.php b/lib/private/files/node/folder.php index 923f53821b2..d9e0ddc2d61 100644 --- a/lib/private/files/node/folder.php +++ b/lib/private/files/node/folder.php @@ -9,7 +9,6 @@ namespace OC\Files\Node; use OC\Files\Cache\Cache; -use OC\Files\Cache\Scanner; use OCP\Files\NotFoundException; use OCP\Files\NotPermittedException; diff --git a/lib/private/files/node/node.php b/lib/private/files/node/node.php index 063e2424a64..bc075911749 100644 --- a/lib/private/files/node/node.php +++ b/lib/private/files/node/node.php @@ -8,8 +8,6 @@ namespace OC\Files\Node; -use OC\Files\Cache\Cache; -use OC\Files\Cache\Scanner; use OCP\Files\NotFoundException; use OCP\Files\NotPermittedException; @@ -31,7 +29,7 @@ class Node implements \OCP\Files\Node { /** * @param \OC\Files\View $view - * @param \OC\Files\Node\Root Root $root + * @param \OC\Files\Node\Root $root * @param string $path */ public function __construct($root, $view, $path) { diff --git a/lib/private/files/node/root.php b/lib/private/files/node/root.php index e3d58476e9c..70135285b0d 100644 --- a/lib/private/files/node/root.php +++ b/lib/private/files/node/root.php @@ -9,7 +9,6 @@ namespace OC\Files\Node; use OC\Files\Cache\Cache; -use OC\Files\Cache\Scanner; use OC\Files\Mount\Manager; use OC\Files\Mount\Mount; use OCP\Files\NotFoundException; @@ -95,7 +94,7 @@ class Root extends Folder implements Emitter { /** * @param string $scope * @param string $method - * @param array $arguments + * @param Node[] $arguments */ public function emit($scope, $method, $arguments = array()) { $this->emitter->emit($scope, $method, $arguments); @@ -154,7 +153,7 @@ class Root extends Folder implements Emitter { * @param string $path * @throws \OCP\Files\NotFoundException * @throws \OCP\Files\NotPermittedException - * @return Node + * @return string */ public function get($path) { $path = $this->normalizePath($path); diff --git a/lib/private/files/storage/common.php b/lib/private/files/storage/common.php index 678bf419023..3c078d7b1b4 100644 --- a/lib/private/files/storage/common.php +++ b/lib/private/files/storage/common.php @@ -27,6 +27,11 @@ abstract class Common implements \OC\Files\Storage\Storage { protected $watcher; protected $storageCache; + /** + * @var string[] + */ + protected $cachedFiles = array(); + public function __construct($parameters) { } @@ -122,11 +127,13 @@ abstract class Common implements \OC\Files\Storage\Storage { public function file_put_contents($path, $data) { $handle = $this->fopen($path, "w"); + $this->removeCachedFile($path); return fwrite($handle, $data); } public function rename($path1, $path2) { if ($this->copy($path1, $path2)) { + $this->removeCachedFile($path1); return $this->unlink($path1); } else { return false; @@ -137,46 +144,10 @@ abstract class Common implements \OC\Files\Storage\Storage { $source = $this->fopen($path1, 'r'); $target = $this->fopen($path2, 'w'); list($count, $result) = \OC_Helper::streamCopy($source, $target); + $this->removeCachedFile($path2); return $result; } - /** - * @brief Deletes all files and folders recursively within a directory - * @param string $directory The directory whose contents will be deleted - * @param bool $empty Flag indicating whether directory will be emptied - * @returns bool - * - * @note By default the directory specified by $directory will be - * deleted together with its contents. To avoid this set $empty to true - */ - public function deleteAll($directory, $empty = false) { - $directory = trim($directory, '/'); - if (!$this->is_dir($directory) || !$this->isReadable($directory)) { - return false; - } else { - $directoryHandle = $this->opendir($directory); - if (is_resource($directoryHandle)) { - while (($contents = readdir($directoryHandle)) !== false) { - if (!\OC\Files\Filesystem::isIgnoredDir($contents)) { - $path = $directory . '/' . $contents; - if ($this->is_dir($path)) { - $this->deleteAll($path); - } else { - $this->unlink($path); - } - } - } - } - if ($empty === false) { - if (!$this->rmdir($directory)) { - return false; - } - } - return true; - } - - } - public function getMimeType($path) { if ($this->is_dir($path)) { return 'httpd/unix-directory'; @@ -199,10 +170,14 @@ abstract class Common implements \OC\Files\Storage\Storage { } public function getLocalFile($path) { - return $this->toTmpFile($path); + return $this->getCachedFile($path); } - private function toTmpFile($path) { //no longer in the storage api, still useful here + /** + * @param string $path + * @return string + */ + protected function toTmpFile($path) { //no longer in the storage api, still useful here $source = $this->fopen($path, 'r'); if (!$source) { return false; @@ -224,6 +199,10 @@ abstract class Common implements \OC\Files\Storage\Storage { return $baseDir; } + /** + * @param string $path + * @param string $target + */ private function addLocalFolder($path, $target) { $dh = $this->opendir($path); if (is_resource($dh)) { @@ -241,6 +220,9 @@ abstract class Common implements \OC\Files\Storage\Storage { } } + /** + * @param string $query + */ protected function searchInDir($query, $dir = '') { $files = array(); $dh = $this->opendir($dir); @@ -370,4 +352,24 @@ abstract class Common implements \OC\Files\Storage\Storage { public function free_space($path) { return \OC\Files\SPACE_UNKNOWN; } + + /** + * {@inheritdoc} + */ + public function isLocal() { + // the common implementation returns a temporary file by + // default, which is not local + return false; + } + + protected function getCachedFile($path) { + if (!isset($this->cachedFiles[$path])) { + $this->cachedFiles[$path] = $this->toTmpFile($path); + } + return $this->cachedFiles[$path]; + } + + protected function removeCachedFile($path) { + unset($this->cachedFiles[$path]); + } } diff --git a/lib/private/files/storage/loader.php b/lib/private/files/storage/loader.php index 2572ef443bc..966234cb04d 100644 --- a/lib/private/files/storage/loader.php +++ b/lib/private/files/storage/loader.php @@ -25,10 +25,17 @@ class Loader { $this->storageWrappers[] = $callback; } + /** + * @param string|boolean $mountPoint + * @param string $class + */ public function load($mountPoint, $class, $arguments) { return $this->wrap($mountPoint, new $class($arguments)); } + /** + * @param string|boolean $mountPoint + */ public function wrap($mountPoint, $storage) { foreach ($this->storageWrappers as $wrapper) { $storage = $wrapper($mountPoint, $storage); diff --git a/lib/private/files/storage/local.php b/lib/private/files/storage/local.php index db3c6bfca3a..a62230bdba5 100644 --- a/lib/private/files/storage/local.php +++ b/lib/private/files/storage/local.php @@ -203,6 +203,9 @@ if (\OC_Util::runningOnWindows()) { return $return; } + /** + * @param string $dir + */ private function delTree($dir) { $dirRelative = $dir; $dir = $this->datadir . $dir; @@ -224,6 +227,9 @@ if (\OC_Util::runningOnWindows()) { return $return; } + /** + * @param string $fullPath + */ private static function getFileSizeFromOS($fullPath) { $name = strtolower(php_uname('s')); // Windows OS: we use COM to access the filesystem @@ -274,6 +280,9 @@ if (\OC_Util::runningOnWindows()) { return $this->datadir . $path; } + /** + * @param string $query + */ protected function searchInDir($query, $dir = '') { $files = array(); foreach (scandir($this->datadir . $dir) as $item) { @@ -298,5 +307,12 @@ if (\OC_Util::runningOnWindows()) { public function hasUpdated($path, $time) { return $this->filemtime($path) > $time; } + + /** + * {@inheritdoc} + */ + public function isLocal() { + return true; + } } } diff --git a/lib/private/files/storage/mappedlocal.php b/lib/private/files/storage/mappedlocal.php index 6c37d445867..1bab3489a28 100644 --- a/lib/private/files/storage/mappedlocal.php +++ b/lib/private/files/storage/mappedlocal.php @@ -210,6 +210,9 @@ class MappedLocal extends \OC\Files\Storage\Common{ return $return; } + /** + * @param string $dir + */ private function delTree($dir, $isLogicPath=true) { $dirRelative=$dir; if ($isLogicPath) { @@ -244,6 +247,9 @@ class MappedLocal extends \OC\Files\Storage\Common{ return $return; } + /** + * @param string $fullPath + */ private static function getFileSizeFromOS($fullPath) { $name = strtolower(php_uname('s')); // Windows OS: we use COM to access the filesystem @@ -288,6 +294,9 @@ class MappedLocal extends \OC\Files\Storage\Common{ return $this->buildPath($path); } + /** + * @param string $query + */ protected function searchInDir($query, $dir='') { $files=array(); $physicalDir = $this->buildPath($dir); @@ -317,12 +326,18 @@ class MappedLocal extends \OC\Files\Storage\Common{ return $this->filemtime($path)>$time; } + /** + * @param string $path + */ private function buildPath($path, $create=true) { $path = $this->stripLeading($path); $fullPath = $this->datadir.$path; return $this->mapper->logicToPhysical($fullPath, $create); } + /** + * @param string $path + */ private function cleanMapper($path, $isLogicPath=true, $recursive=true) { $fullPath = $path; if ($isLogicPath) { @@ -331,6 +346,10 @@ class MappedLocal extends \OC\Files\Storage\Common{ $this->mapper->removePath($fullPath, $isLogicPath, $recursive); } + /** + * @param string $path1 + * @param string $path2 + */ private function copyMapping($path1, $path2) { $path1 = $this->stripLeading($path1); $path2 = $this->stripLeading($path2); diff --git a/lib/private/files/storage/wrapper/quota.php b/lib/private/files/storage/wrapper/quota.php index a430e3e4617..a878b2c5cf6 100644 --- a/lib/private/files/storage/wrapper/quota.php +++ b/lib/private/files/storage/wrapper/quota.php @@ -16,17 +16,38 @@ class Quota extends Wrapper { protected $quota; /** + * @var string $sizeRoot + */ + protected $sizeRoot; + + /** * @param array $parameters */ public function __construct($parameters) { $this->storage = $parameters['storage']; $this->quota = $parameters['quota']; + $this->sizeRoot = isset($parameters['root']) ? $parameters['root'] : ''; } + /** + * @return quota value + */ + public function getQuota() { + return $this->quota; + } + + /** + * @param string $path + */ protected function getSize($path) { $cache = $this->getCache(); $data = $cache->get($path); if (is_array($data) and isset($data['size'])) { + if (isset($data['unencrypted_size']) + && $data['unencrypted_size'] > 0 + ) { + return $data['unencrypted_size']; + } return $data['size']; } else { return \OC\Files\SPACE_NOT_COMPUTED; @@ -43,12 +64,19 @@ class Quota extends Wrapper { if ($this->quota < 0) { return $this->storage->free_space($path); } else { - $used = $this->getSize(''); + $used = $this->getSize($this->sizeRoot); if ($used < 0) { return \OC\Files\SPACE_NOT_COMPUTED; } else { $free = $this->storage->free_space($path); - return min($free, (max($this->quota - $used, 0))); + $quotaFree = max($this->quota - $used, 0); + // if free space is known + if ($free >= 0) { + $free = min($free, $quotaFree); + } else { + $free = $quotaFree; + } + return $free; } } } diff --git a/lib/private/files/storage/wrapper/wrapper.php b/lib/private/files/storage/wrapper/wrapper.php index f9adda80314..11ea9f71da7 100644 --- a/lib/private/files/storage/wrapper/wrapper.php +++ b/lib/private/files/storage/wrapper/wrapper.php @@ -432,4 +432,12 @@ class Wrapper implements \OC\Files\Storage\Storage { public function test() { return $this->storage->test(); } + + /** + * Returns the wrapped storage's value for isLocal() + * @return bool wrapped storage's isLocal() value + */ + public function isLocal() { + return $this->storage->isLocal(); + } } diff --git a/lib/private/files/stream/close.php b/lib/private/files/stream/close.php index 80de3497c36..0e1f088fcf9 100644 --- a/lib/private/files/stream/close.php +++ b/lib/private/files/stream/close.php @@ -94,6 +94,9 @@ class Close { return unlink($path); } + /** + * @param string $path + */ public static function registerCallback($path, $callback) { self::$callBacks[$path] = $callback; } diff --git a/lib/private/files/stream/dir.php b/lib/private/files/stream/dir.php index 6ca884fc994..2483385c1d8 100644 --- a/lib/private/files/stream/dir.php +++ b/lib/private/files/stream/dir.php @@ -41,6 +41,9 @@ class Dir { return true; } + /** + * @param string $path + */ public static function register($path, $content) { self::$dirs[$path] = $content; } diff --git a/lib/private/files/type/detection.php b/lib/private/files/type/detection.php index d7cc9ebbf4e..11e439032ce 100644 --- a/lib/private/files/type/detection.php +++ b/lib/private/files/type/detection.php @@ -72,11 +72,12 @@ class Detection { and function_exists('finfo_file') and $finfo = finfo_open(FILEINFO_MIME) ) { $info = @strtolower(finfo_file($finfo, $path)); + finfo_close($finfo); if ($info) { $mimeType = substr($info, 0, strpos($info, ';')); return empty($mimeType) ? 'application/octet-stream' : $mimeType; } - finfo_close($finfo); + } $isWrapped = (strpos($path, '://') !== false) and (substr($path, 0, 7) === 'file://'); if (!$isWrapped and $mimeType === 'application/octet-stream' && function_exists("mime_content_type")) { diff --git a/lib/private/files/utils/scanner.php b/lib/private/files/utils/scanner.php index 2cad7dd77bd..a802a8fcb8b 100644 --- a/lib/private/files/utils/scanner.php +++ b/lib/private/files/utils/scanner.php @@ -69,6 +69,9 @@ class Scanner extends PublicEmitter { }); } + /** + * @param string $dir + */ public function backgroundScan($dir) { $mounts = $this->getMounts($dir); foreach ($mounts as $mount) { @@ -81,6 +84,9 @@ class Scanner extends PublicEmitter { } } + /** + * @param string $dir + */ public function scan($dir) { $mounts = $this->getMounts($dir); foreach ($mounts as $mount) { diff --git a/lib/private/files/view.php b/lib/private/files/view.php index d97544b865e..2dbbf5b88c9 100644 --- a/lib/private/files/view.php +++ b/lib/private/files/view.php @@ -48,7 +48,7 @@ class View { * change the root to a fake root * * @param string $fakeRoot - * @return bool + * @return boolean|null */ public function chroot($fakeRoot) { if (!$fakeRoot == '') { @@ -352,6 +352,9 @@ class View { return $this->basicOperation('unlink', $path, array('delete')); } + /** + * @param string $directory + */ public function deleteAll($directory, $empty = false) { return $this->rmdir($directory); } @@ -410,7 +413,7 @@ class View { $result = $this->copy($path1, $path2); if ($result === true) { list($storage1, $internalPath1) = Filesystem::resolvePath($absolutePath1 . $postFix1); - $result = $storage1->deleteAll($internalPath1); + $result = $storage1->unlink($internalPath1); } } else { $source = $this->fopen($path1 . $postFix1, 'r'); @@ -531,6 +534,8 @@ class View { $source = $this->fopen($path1 . $postFix1, 'r'); $target = $this->fopen($path2 . $postFix2, 'w'); list($count, $result) = \OC_Helper::streamCopy($source, $target); + fclose($source); + fclose($target); } } if ($this->shouldEmitHooks() && $result !== false) { @@ -735,6 +740,9 @@ class View { return (strlen($this->fakeRoot) > strlen($defaultRoot)) && (substr($this->fakeRoot, 0, strlen($defaultRoot) + 1) === $defaultRoot . '/'); } + /** + * @param string $path + */ private function runHooks($hooks, $path, $post = false) { $path = $this->getHookPath($path); $prefix = ($post) ? 'post_' : ''; @@ -781,14 +789,7 @@ class View { * @param string $path * @param boolean $includeMountPoints whether to add mountpoint sizes, * defaults to true - * @return array - * - * returns an associative array with the following keys: - * - size - * - mtime - * - mimetype - * - encrypted - * - versioned + * @return \OC\Files\FileInfo | false */ public function getFileInfo($path, $includeMountPoints = true) { $data = array(); @@ -841,10 +842,13 @@ class View { $data['permissions'] = $permissions; } } + if (!$data) { + return false; + } $data = \OC_FileProxy::runPostProxies('getFileInfo', $path, $data); - return $data; + return new FileInfo($path, $storage, $internalPath, $data); } /** @@ -852,7 +856,7 @@ class View { * * @param string $directory path under datadirectory * @param string $mimetype_filter limit returned content to this mimetype or mimepart - * @return array + * @return FileInfo[] */ public function getDirectoryContent($directory, $mimetype_filter = '') { $result = array(); @@ -878,8 +882,13 @@ class View { $watcher->checkUpdate($internalPath); } - $files = $cache->getFolderContents($internalPath); //TODO: mimetype_filter - $permissions = $permissionsCache->getDirectoryPermissions($cache->getId($internalPath), $user); + $folderId = $cache->getId($internalPath); + $files = array(); + $contents = $cache->getFolderContents($internalPath, $folderId); //TODO: mimetype_filter + foreach ($contents as $content) { + $files[] = new FileInfo($path . '/' . $content['name'], $storage, $content['path'], $content); + } + $permissions = $permissionsCache->getDirectoryPermissions($folderId, $user); $ids = array(); foreach ($files as $i => $file) { @@ -936,7 +945,7 @@ class View { break; } } - $files[] = $rootEntry; + $files[] = new FileInfo($path . '/' . $rootEntry['name'], $subStorage, '', $rootEntry); } } } @@ -958,6 +967,7 @@ class View { $result = $files; } } + return $result; } @@ -965,12 +975,15 @@ class View { * change file metadata * * @param string $path - * @param array $data + * @param array | \OCP\Files\FileInfo $data * @return int * * returns the fileid of the updated file */ public function putFileInfo($path, $data) { + if ($data instanceof FileInfo) { + $data = $data->getData(); + } $path = Filesystem::normalizePath($this->fakeRoot . '/' . $path); /** * @var \OC\Files\Storage\Storage $storage @@ -995,7 +1008,7 @@ class View { * search for files with the name matching $query * * @param string $query - * @return array + * @return FileInfo[] */ public function search($query) { return $this->searchCommon('%' . $query . '%', 'search'); @@ -1005,7 +1018,7 @@ class View { * search for files by mimetype * * @param string $mimetype - * @return array + * @return FileInfo[] */ public function searchByMime($mimetype) { return $this->searchCommon($mimetype, 'searchByMime'); @@ -1014,7 +1027,7 @@ class View { /** * @param string $query * @param string $method - * @return array + * @return FileInfo[] */ private function searchCommon($query, $method) { $files = array(); @@ -1028,8 +1041,9 @@ class View { $results = $cache->$method($query); foreach ($results as $result) { if (substr($mountPoint . $result['path'], 0, $rootLength + 1) === $this->fakeRoot . '/') { + $internalPath = $result['path']; $result['path'] = substr($mountPoint . $result['path'], $rootLength); - $files[] = $result; + $files[] = new FileInfo($mountPoint . $result['path'], $storage, $internalPath, $result); } } @@ -1043,8 +1057,9 @@ class View { $results = $cache->$method($query); if ($results) { foreach ($results as $result) { + $internalPath = $result['path']; $result['path'] = $relativeMountPoint . $result['path']; - $files[] = $result; + $files[] = new FileInfo($mountPoint . $result['path'], $storage, $internalPath, $result); } } } diff --git a/lib/private/geo.php b/lib/private/geo.php index ed01ad0b616..7094d885af6 100644 --- a/lib/private/geo.php +++ b/lib/private/geo.php @@ -12,6 +12,10 @@ class OC_Geo{ * @param (string) $longitude - Longitude * @return (string) $timezone - closest timezone */ + /** + * @param integer $latitude + * @param integer $longitude + */ public static function timezone($latitude, $longitude) { $alltimezones = DateTimeZone::listIdentifiers(); $variances = array(); diff --git a/lib/private/group.php b/lib/private/group.php index 444788c97f1..4c187b538af 100644 --- a/lib/private/group.php +++ b/lib/private/group.php @@ -243,7 +243,7 @@ class OC_Group { /** * @brief get a list of all users in several groups - * @param array $gids + * @param string[] $gids * @param string $search * @param int $limit * @param int $offset diff --git a/lib/private/group/dummy.php b/lib/private/group/dummy.php index 9516fd52ff8..da26e1b910e 100644 --- a/lib/private/group/dummy.php +++ b/lib/private/group/dummy.php @@ -28,7 +28,7 @@ class OC_Group_Dummy extends OC_Group_Backend { private $groups=array(); /** * @brief Try to create a new group - * @param $gid The name of the group to create + * @param string $gid The name of the group to create * @returns true/false * * Trys to create a new group. If the group name already exists, false will diff --git a/lib/private/group/manager.php b/lib/private/group/manager.php index bf469d51d12..9b433b64fd4 100644 --- a/lib/private/group/manager.php +++ b/lib/private/group/manager.php @@ -76,12 +76,7 @@ class Manager extends PublicEmitter { if (isset($this->cachedGroups[$gid])) { return $this->cachedGroups[$gid]; } - foreach ($this->backends as $backend) { - if ($backend->groupExists($gid)) { - return $this->getGroupObject($gid); - } - } - return null; + return $this->getGroupObject($gid); } protected function getGroupObject($gid) { @@ -91,6 +86,9 @@ class Manager extends PublicEmitter { $backends[] = $backend; } } + if (count($backends) === 0) { + return null; + } $this->cachedGroups[$gid] = new Group($gid, $backends, $this->userManager, $this); return $this->cachedGroups[$gid]; } @@ -110,8 +108,8 @@ class Manager extends PublicEmitter { public function createGroup($gid) { if (!$gid) { return false; - } else if ($this->groupExists($gid)) { - return $this->get($gid); + } else if ($group = $this->get($gid)) { + return $group; } else { $this->emit('\OC\Group', 'preCreate', array($gid)); foreach ($this->backends as $backend) { diff --git a/lib/private/helper.php b/lib/private/helper.php index 580f81acc62..98a86388d20 100644 --- a/lib/private/helper.php +++ b/lib/private/helper.php @@ -64,7 +64,7 @@ class OC_Helper { */ public static function linkToDocs($key) { $theme = new OC_Defaults(); - return $theme->getDocBaseUrl() . '/server/6.0/go.php?to=' . $key; + return $theme->buildDocLinkToKey($key); } /** @@ -151,7 +151,33 @@ class OC_Helper { */ public static function mimetypeIcon($mimetype) { $alias = array( - 'application/xml' => 'code/xml', + 'application/octet-stream' => 'file', // use file icon as fallback + + 'application/illustrator' => 'image', + 'application/coreldraw' => 'image', + 'application/x-gimp' => 'image', + 'application/x-photoshop' => 'image', + + 'application/x-font-ttf' => 'font', + 'application/font-woff' => 'font', + 'application/vnd.ms-fontobject' => 'font', + + 'application/json' => 'text/code', + 'application/x-perl' => 'text/code', + 'application/x-php' => 'text/code', + 'text/x-shellscript' => 'text/code', + 'application/xml' => 'text/html', + 'text/css' => 'text/code', + 'application/x-tex' => 'text', + + 'application/x-compressed' => 'package/x-generic', + 'application/x-7z-compressed' => 'package/x-generic', + 'application/x-deb' => 'package/x-generic', + 'application/x-gzip' => 'package/x-generic', + 'application/x-rar-compressed' => 'package/x-generic', + 'application/x-tar' => 'package/x-generic', + 'application/zip' => 'package/x-generic', + 'application/msword' => 'x-office/document', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => 'x-office/document', 'application/vnd.openxmlformats-officedocument.wordprocessingml.template' => 'x-office/document', @@ -161,6 +187,7 @@ class OC_Helper { 'application/vnd.oasis.opendocument.text-template' => 'x-office/document', 'application/vnd.oasis.opendocument.text-web' => 'x-office/document', 'application/vnd.oasis.opendocument.text-master' => 'x-office/document', + 'application/mspowerpoint' => 'x-office/presentation', 'application/vnd.ms-powerpoint' => 'x-office/presentation', 'application/vnd.openxmlformats-officedocument.presentationml.presentation' => 'x-office/presentation', @@ -172,6 +199,7 @@ class OC_Helper { 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12' => 'x-office/presentation', 'application/vnd.oasis.opendocument.presentation' => 'x-office/presentation', 'application/vnd.oasis.opendocument.presentation-template' => 'x-office/presentation', + 'application/msexcel' => 'x-office/spreadsheet', 'application/vnd.ms-excel' => 'x-office/spreadsheet', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => 'x-office/spreadsheet', @@ -182,6 +210,8 @@ class OC_Helper { 'application/vnd.ms-excel.sheet.binary.macroEnabled.12' => 'x-office/spreadsheet', 'application/vnd.oasis.opendocument.spreadsheet' => 'x-office/spreadsheet', 'application/vnd.oasis.opendocument.spreadsheet-template' => 'x-office/spreadsheet', + 'text/csv' => 'x-office/spreadsheet', + 'application/msaccess' => 'database', ); @@ -278,7 +308,7 @@ class OC_Helper { /** * @brief Make a computer file size - * @param string $str file size in a fancy format + * @param string $str file size in human readable format * @return int a file size in bytes * * Makes 2kB to 2048. @@ -308,41 +338,12 @@ class OC_Helper { $bytes *= $bytes_array[$matches[1]]; } - $bytes = round($bytes, 2); + $bytes = round($bytes); return $bytes; } /** - * @brief Recursive editing of file permissions - * @param string $path path to file or folder - * @param int $filemode unix style file permissions - * @return bool - */ - static function chmodr($path, $filemode) { - if (!is_dir($path)) - return chmod($path, $filemode); - $dh = opendir($path); - if(is_resource($dh)) { - while (($file = readdir($dh)) !== false) { - if ($file != '.' && $file != '..') { - $fullpath = $path . '/' . $file; - if (is_link($fullpath)) - return false; - elseif (!is_dir($fullpath) && !@chmod($fullpath, $filemode)) - return false; elseif (!self::chmodr($fullpath, $filemode)) - return false; - } - } - closedir($dh); - } - if (@chmod($path, $filemode)) - return true; - else - return false; - } - - /** * @brief Recursive copying of folders * @param string $src source folder * @param string $dest target folder @@ -804,18 +805,22 @@ class OC_Helper { /** * @brief calculates the maximum upload size respecting system settings, free space and user quota * - * @param $dir the current folder where the user currently operates - * @return number of bytes representing + * @param string $dir the current folder where the user currently operates + * @param int $freeSpace the number of bytes free on the storage holding $dir, if not set this will be received from the storage directly + * @return int number of bytes representing */ - public static function maxUploadFilesize($dir) { - return min(self::freeSpace($dir), self::uploadLimit()); + public static function maxUploadFilesize($dir, $freeSpace = null) { + if (is_null($freeSpace) || $freeSpace < 0){ + $freeSpace = self::freeSpace($dir); + } + return min($freeSpace, self::uploadLimit()); } /** * Calculate free space left within user quota * - * @param $dir the current folder where the user currently operates - * @return number of bytes representing + * @param string $dir the current folder where the user currently operates + * @return int number of bytes representing */ public static function freeSpace($dir) { $freeSpace = \OC\Files\Filesystem::free_space($dir); @@ -880,13 +885,22 @@ class OC_Helper { if ($used < 0) { $used = 0; } - $free = \OC\Files\Filesystem::free_space($path); + $quota = 0; + // TODO: need a better way to get total space from storage + $storage = $rootInfo->getStorage(); + if ($storage instanceof \OC\Files\Storage\Wrapper\Quota) { + $quota = $storage->getQuota(); + } + $free = $storage->free_space(''); if ($free >= 0) { $total = $free + $used; } else { $total = $free; //either unknown or unlimited } if ($total > 0) { + if ($quota > 0 && $total > $quota) { + $total = $quota; + } // prevent division by zero or error codes (negative values) $relative = round(($used / $total) * 10000) / 100; } else { diff --git a/lib/private/hooks/emitter.php b/lib/private/hooks/emitter.php index 8e9074bad67..8d58dd936cc 100644 --- a/lib/private/hooks/emitter.php +++ b/lib/private/hooks/emitter.php @@ -20,6 +20,7 @@ interface Emitter { * @param string $scope * @param string $method * @param callable $callback + * @return void */ public function listen($scope, $method, $callback); @@ -27,6 +28,7 @@ interface Emitter { * @param string $scope optional * @param string $method optional * @param callable $callback optional + * @return void */ public function removeListener($scope = null, $method = null, $callback = null); } diff --git a/lib/private/image.php b/lib/private/image.php index 7761a3c7737..c987ce92c3c 100644 --- a/lib/private/image.php +++ b/lib/private/image.php @@ -34,25 +34,25 @@ class OC_Image { /** * @brief Get mime type for an image file. - * @param $filepath The path to a local image file. - * @returns string The mime type if the it could be determined, otherwise an empty string. + * @param string|null $filepath The path to a local image file. + * @return string The mime type if the it could be determined, otherwise an empty string. */ static public function getMimeTypeForFile($filePath) { // exif_imagetype throws "read error!" if file is less than 12 byte if (filesize($filePath) > 11) { $imageType = exif_imagetype($filePath); - } - else { + } else { $imageType = false; } return $imageType ? image_type_to_mime_type($imageType) : ''; } /** - * @brief Constructor. - * @param $imageref The path to a local file, a base64 encoded string or a resource created by an imagecreate* function. - * @returns bool False on error - */ + * @brief Constructor. + * @param resource|string $imageref The path to a local file, a base64 encoded string or a resource created by + * an imagecreate* function. + * @return \OC_Image False on error + */ public function __construct($imageRef = null) { //OC_Log::write('core',__METHOD__.'(): start', OC_Log::DEBUG); if(!extension_loaded('gd') || !function_exists('gd_info')) { @@ -71,7 +71,7 @@ class OC_Image { /** * @brief Determine whether the object contains an image resource. - * @returns bool + * @return bool */ public function valid() { // apparently you can't name a method 'empty'... return is_resource($this->resource); @@ -79,7 +79,7 @@ class OC_Image { /** * @brief Returns the MIME type of the image or an empty string if no image is loaded. - * @returns int + * @return int */ public function mimeType() { return $this->valid() ? $this->mimeType : ''; @@ -87,7 +87,7 @@ class OC_Image { /** * @brief Returns the width of the image or -1 if no image is loaded. - * @returns int + * @return int */ public function width() { return $this->valid() ? imagesx($this->resource) : -1; @@ -95,7 +95,7 @@ class OC_Image { /** * @brief Returns the height of the image or -1 if no image is loaded. - * @returns int + * @return int */ public function height() { return $this->valid() ? imagesy($this->resource) : -1; @@ -103,7 +103,7 @@ class OC_Image { /** * @brief Returns the width when the image orientation is top-left. - * @returns int + * @return int */ public function widthTopLeft() { $o = $this->getOrientation(); @@ -115,20 +115,18 @@ class OC_Image { case 3: case 4: // Not tested return $this->width(); - break; case 5: // Not tested case 6: case 7: // Not tested case 8: return $this->height(); - break; } return $this->width(); } /** * @brief Returns the height when the image orientation is top-left. - * @returns int + * @return int */ public function heightTopLeft() { $o = $this->getOrientation(); @@ -140,45 +138,56 @@ class OC_Image { case 3: case 4: // Not tested return $this->height(); - break; case 5: // Not tested case 6: case 7: // Not tested case 8: return $this->width(); - break; } return $this->height(); } /** - * @brief Outputs the image. - * @returns bool - */ - public function show() { - header('Content-Type: '.$this->mimeType()); - return $this->_output(); + * @brief Outputs the image. + * @param string $mimeType + * @return bool + */ + public function show($mimeType=null) { + if($mimeType === null) { + $mimeType = $this->mimeType(); + } + header('Content-Type: '.$mimeType); + return $this->_output(null, $mimeType); } /** - * @brief Saves the image. - * @returns bool - */ + * @brief Saves the image. + * @param string $filePath + * @param string $mimeType + * @return bool + */ - public function save($filePath=null) { + public function save($filePath=null, $mimeType=null) { + if($mimeType === null) { + $mimeType = $this->mimeType(); + } if($filePath === null && $this->filePath === null) { OC_Log::write('core', __METHOD__.'(): called with no path.', OC_Log::ERROR); return false; } elseif($filePath === null && $this->filePath !== null) { $filePath = $this->filePath; } - return $this->_output($filePath); + return $this->_output($filePath, $mimeType); } /** - * @brief Outputs/saves the image. - */ - private function _output($filePath=null) { + * @brief Outputs/saves the image. + * @param string $filePath + * @param string $mimeType + * @return bool + * @throws Exception + */ + private function _output($filePath=null, $mimeType=null) { if($filePath) { if (!file_exists(dirname($filePath))) mkdir(dirname($filePath), 0777, true); @@ -196,8 +205,30 @@ class OC_Image { return false; } - $retVal = false; - switch($this->imageType) { + $imageType = $this->imageType; + if($mimeType !== null) { + switch($mimeType) { + case 'image/gif': + $imageType = IMAGETYPE_GIF; + break; + case 'image/jpeg': + $imageType = IMAGETYPE_JPEG; + break; + case 'image/png': + $imageType = IMAGETYPE_PNG; + break; + case 'image/x-xbitmap': + $imageType = IMAGETYPE_XBM; + break; + case 'image/bmp': + $imageType = IMAGETYPE_BMP; + break; + default: + throw new Exception('\OC_Image::_output(): "' . $mimeType . '" is not supported when forcing a specific output format'); + } + } + + switch($imageType) { case IMAGETYPE_GIF: $retVal = imagegif($this->resource, $filePath); break; @@ -208,7 +239,12 @@ class OC_Image { $retVal = imagepng($this->resource, $filePath); break; case IMAGETYPE_XBM: - $retVal = imagexbm($this->resource, $filePath); + if (function_exists('imagexbm')) { + $retVal = imagexbm($this->resource, $filePath); + } else { + throw new Exception('\OC_Image::_output(): imagexbm() is not supported.'); + } + break; case IMAGETYPE_WBMP: $retVal = imagewbmp($this->resource, $filePath); @@ -230,14 +266,14 @@ class OC_Image { } /** - * @returns Returns the image resource in any. + * @return resource Returns the image resource in any. */ public function resource() { return $this->resource; } /** - * @returns Returns the raw image data. + * @return string Returns the raw image data. */ function data() { ob_start(); @@ -263,8 +299,8 @@ class OC_Image { } /** - * @returns Returns a base64 encoded string suitable for embedding in a VCard. - */ + * @return string - base64 encoded, which is suitable for embedding in a VCard. + */ function __toString() { return base64_encode($this->data()); } @@ -272,7 +308,7 @@ class OC_Image { /** * (I'm open for suggestions on better method name ;) * @brief Get the orientation based on EXIF data. - * @returns The orientation or -1 if no EXIF data is available. + * @return int The orientation or -1 if no EXIF data is available. */ public function getOrientation() { if(!is_callable('exif_read_data')) { @@ -300,53 +336,43 @@ class OC_Image { /** * (I'm open for suggestions on better method name ;) * @brief Fixes orientation based on EXIF data. - * @returns bool. + * @return bool. */ public function fixOrientation() { $o = $this->getOrientation(); OC_Log::write('core', 'OC_Image->fixOrientation() Orientation: '.$o, OC_Log::DEBUG); $rotate = 0; - $flip = false; switch($o) { case -1: return false; //Nothing to fix - break; case 1: $rotate = 0; - $flip = false; break; case 2: // Not tested $rotate = 0; - $flip = true; break; case 3: $rotate = 180; - $flip = false; break; case 4: // Not tested $rotate = 180; - $flip = true; break; case 5: // Not tested $rotate = 90; - $flip = true; break; case 6: //$rotate = 90; $rotate = 270; - $flip = false; break; case 7: // Not tested $rotate = 270; - $flip = true; break; case 8: $rotate = 90; - $flip = false; break; } if($rotate) { - $res = imagerotate($this->resource, $rotate, -1); + $res = imagerotate($this->resource, $rotate, 0); if($res) { if(imagealphablending($res, true)) { if(imagesavealpha($res, true)) { @@ -366,13 +392,14 @@ class OC_Image { return false; } } + return false; } /** - * @brief Loads an image from a local file, a base64 encoded string or a resource created by an imagecreate* function. - * @param $imageref The path to a local file, a base64 encoded string or a resource created by an imagecreate* function or a file resource (file handle ). - * @returns An image resource or false on error - */ + * @brief Loads an image from a local file, a base64 encoded string or a resource created by an imagecreate* function. + * @param resource|string $imageref The path to a local file, a base64 encoded string or a resource created by an imagecreate* function or a file resource (file handle ). + * @return resource|false An image resource or false on error + */ public function load($imageRef) { if(is_resource($imageRef)) { if(get_resource_type($imageRef) == 'gd') { @@ -381,10 +408,10 @@ class OC_Image { } elseif(in_array(get_resource_type($imageRef), array('file', 'stream'))) { return $this->loadFromFileHandle($imageRef); } - } elseif($this->loadFromFile($imageRef) !== false) { - return $this->resource; } elseif($this->loadFromBase64($imageRef) !== false) { return $this->resource; + } elseif($this->loadFromFile($imageRef) !== false) { + return $this->resource; } elseif($this->loadFromData($imageRef) !== false) { return $this->resource; } else { @@ -396,8 +423,8 @@ class OC_Image { /** * @brief Loads an image from an open file handle. * It is the responsibility of the caller to position the pointer at the correct place and to close the handle again. - * @param $handle - * @returns An image resource or false on error + * @param resource $handle + * @return An image resource or false on error */ public function loadFromFileHandle($handle) { OC_Log::write('core', __METHOD__.'(): Trying', OC_Log::DEBUG); @@ -409,14 +436,13 @@ class OC_Image { /** * @brief Loads an image from a local file. - * @param $imageref The path to a local file. - * @returns An image resource or false on error + * @param bool|string $imagePath The path to a local file. + * @return bool|resource An image resource or false on error */ public function loadFromFile($imagePath=false) { // exif_imagetype throws "read error!" if file is less than 12 byte if(!@is_file($imagePath) || !file_exists($imagePath) || filesize($imagePath) < 12 || !is_readable($imagePath)) { - // Debug output disabled because this method is tried before loadFromBase64? - OC_Log::write('core', 'OC_Image->loadFromFile, couldn\'t load: '.$imagePath, OC_Log::DEBUG); + OC_Log::write('core', 'OC_Image->loadFromFile, couldn\'t load: ' . (string) urlencode($imagePath), OC_Log::DEBUG); return false; } $iType = exif_imagetype($imagePath); @@ -511,8 +537,8 @@ class OC_Image { /** * @brief Loads an image from a string of data. - * @param $str A string of image data as read from a file. - * @returns An image resource or false on error + * @param string $str A string of image data as read from a file. + * @return bool|resource An image resource or false on error */ public function loadFromData($str) { if(is_resource($str)) { @@ -536,8 +562,8 @@ class OC_Image { /** * @brief Loads an image from a base64 encoded string. - * @param $str A string base64 encoded string of image data. - * @returns An image resource or false on error + * @param string $str A string base64 encoded string of image data. + * @return bool|resource An image resource or false on error */ public function loadFromBase64($str) { if(!is_string($str)) { @@ -563,10 +589,10 @@ class OC_Image { * Create a new image from file or URL * @link http://www.programmierer-forum.de/function-imagecreatefrombmp-laeuft-mit-allen-bitraten-t143137.htm * @version 1.00 - * @param string $filename <p> + * @param string $fileName <p> * Path to the BMP image. * </p> - * @return resource an image resource identifier on success, <b>FALSE</b> on errors. + * @return bool|resource an image resource identifier on success, <b>FALSE</b> on errors. */ private function imagecreatefrombmp($fileName) { if (!($fh = fopen($fileName, 'rb'))) { @@ -598,9 +624,9 @@ class OC_Image { $meta['imagesize'] = $meta['filesize'] - $meta['offset']; // in rare cases filesize is equal to offset so we need to read physical size if ($meta['imagesize'] < 1) { - $meta['imagesize'] = @filesize($filename) - $meta['offset']; + $meta['imagesize'] = @filesize($fileName) - $meta['offset']; if ($meta['imagesize'] < 1) { - trigger_error('imagecreatefrombmp: Can not obtain filesize of ' . $filename . '!', E_USER_WARNING); + trigger_error('imagecreatefrombmp: Can not obtain filesize of ' . $fileName . '!', E_USER_WARNING); return false; } } @@ -704,8 +730,8 @@ class OC_Image { /** * @brief Resizes the image preserving ratio. - * @param $maxsize The maximum size of either the width or height. - * @returns bool + * @param integer $maxSize The maximum size of either the width or height. + * @return bool */ public function resize($maxSize) { if(!$this->valid()) { @@ -728,6 +754,11 @@ class OC_Image { return true; } + /** + * @param int $width + * @param int $height + * @return bool + */ public function preciseResize($width, $height) { if (!$this->valid()) { OC_Log::write('core', __METHOD__.'(): No image loaded', OC_Log::ERROR); @@ -763,8 +794,8 @@ class OC_Image { /** * @brief Crops the image to the middle square. If the image is already square it just returns. - * @param int maximum size for the result (optional) - * @returns bool for success or failure + * @param int $size maximum size for the result (optional) + * @return bool for success or failure */ public function centerCrop($size=0) { if(!$this->valid()) { @@ -822,11 +853,11 @@ class OC_Image { /** * @brief Crops the image from point $x$y with dimension $wx$h. - * @param $x Horizontal position - * @param $y Vertical position - * @param $w Width - * @param $h Height - * @returns bool for success or failure + * @param int $x Horizontal position + * @param int $y Vertical position + * @param int $w Width + * @param int $h Height + * @return bool for success or failure */ public function crop($x, $y, $w, $h) { if(!$this->valid()) { @@ -852,9 +883,9 @@ class OC_Image { /** * @brief Resizes the image to fit within a boundry while preserving ratio. - * @param $maxWidth - * @param $maxHeight - * @returns bool + * @param integer $maxWidth + * @param integer $maxHeight + * @return bool */ public function fitIn($maxWidth, $maxHeight) { if(!$this->valid()) { @@ -891,8 +922,7 @@ if ( ! function_exists( 'imagebmp') ) { * @link http://www.programmierer-forum.de/imagebmp-gute-funktion-gefunden-t143716.htm * @author mgutt <marc@gutt.it> * @version 1.00 - * @param resource $image - * @param string $filename [optional] <p>The path to save the file to.</p> + * @param string $fileName [optional] <p>The path to save the file to.</p> * @param int $bit [optional] <p>Bit depth, (default is 24).</p> * @param int $compression [optional] * @return bool <b>TRUE</b> on success or <b>FALSE</b> on failure. @@ -947,7 +977,7 @@ if ( ! function_exists( 'imagebmp') ) { $index = imagecolorat($im, $i, $j); if ($index !== $lastIndex || $sameNum > 255) { if ($sameNum != 0) { - $bmpData .= chr($same_num) . chr($lastIndex); + $bmpData .= chr($sameNum) . chr($lastIndex); } $lastIndex = $index; $sameNum = 1; @@ -1008,7 +1038,7 @@ if ( ! function_exists( 'exif_imagetype' ) ) { /** * Workaround if exif_imagetype does not exist * @link http://www.php.net/manual/en/function.exif-imagetype.php#80383 - * @param string $filename + * @param string $fileName * @return string|boolean */ function exif_imagetype ( $fileName ) { diff --git a/lib/private/installer.php b/lib/private/installer.php index 835b6b4c01a..64e8e3a5e7a 100644 --- a/lib/private/installer.php +++ b/lib/private/installer.php @@ -25,10 +25,6 @@ */ class OC_Installer{ /** - * @brief Installs an app - * @param $data array with all information - * @throws \Exception - * @returns integer * * This function installs an app. All information needed are passed in the * associative array $data. @@ -55,6 +51,11 @@ class OC_Installer{ * * It is the task of oc_app_install to create the tables and do whatever is * needed to get the app working. + * + * @brief Installs an app + * @param array $data with all information + * @throws \Exception + * @return integer */ public static function installApp( $data = array()) { $l = \OC_L10N::get('lib'); @@ -153,7 +154,7 @@ class OC_Installer{ }else{ $version = trim($info['version']); } - + if($version<>trim($data['appdata']['version'])) { OC_Helper::rmdirr($extractDir); throw new \Exception($l->t("App can't be installed because the version in info.xml/version is not the same as the version reported from the app store")); @@ -219,7 +220,7 @@ class OC_Installer{ /** * @brief checks whether or not an app is installed - * @param $app app + * @param string $app app * @returns true/false * * Checks whether or not an app is installed, i.e. registered in apps table. @@ -235,7 +236,6 @@ class OC_Installer{ /** * @brief Update an application - * @param $data array with all information * * This function installs an app. All information needed are passed in the * associative array $data. @@ -269,8 +269,7 @@ class OC_Installer{ /** * @brief Check if an update for the app is available - * @param $name name of the application - * @return boolean false or the version number of the update + * @return string|false false or the version number of the update * * The function will check if an update for a version is available */ @@ -297,8 +296,8 @@ class OC_Installer{ /** * @brief Check if app is already downloaded - * @param $name name of the application to remove - * @returns true/false + * @param string $name name of the application to remove + * @return boolean * * The function will check if the app is already downloaded in the apps repository */ @@ -313,9 +312,9 @@ class OC_Installer{ /** * @brief Removes an app - * @param $name name of the application to remove + * @param string $name name of the application to remove * @param $options array with options - * @returns true/false + * @return boolean|null * * This function removes an app. $options is an associative array. The * following keys are optional:ja @@ -394,7 +393,7 @@ class OC_Installer{ /** * install an app already placed in the app folder * @param string $app id of the app to install - * @returns array see OC_App::getAppInfo + * @return integer */ public static function installShippedApp($app) { //install the database @@ -429,7 +428,7 @@ class OC_Installer{ /** * check the code of an app with some static code checks * @param string $folder the folder of the app to check - * @returns true for app is o.k. and false for app is not o.k. + * @return boolean true for app is o.k. and false for app is not o.k. */ public static function checkCode($appname, $folder) { @@ -465,7 +464,7 @@ class OC_Installer{ // is the code checker enabled? if(OC_Config::getValue('appcodechecker', true)) { // check if grep is installed - $grep = exec('which grep'); + $grep = exec('command -v grep'); if($grep=='') { OC_Log::write('core', 'grep not installed. So checking the code of the app "'.$appname.'" was not possible', diff --git a/lib/private/json.php b/lib/private/json.php index 5c5d7e3a3da..4ccdb490a6c 100644 --- a/lib/private/json.php +++ b/lib/private/json.php @@ -21,6 +21,7 @@ class OC_JSON{ /** * Check if the app is enabled, send json error msg if not + * @param string $app */ public static function checkAppEnabled($app) { if( !OC_App::isEnabled($app)) { diff --git a/lib/private/l10n.php b/lib/private/l10n.php index 98665c84c55..197b2d6791b 100644 --- a/lib/private/l10n.php +++ b/lib/private/l10n.php @@ -73,8 +73,8 @@ class OC_L10N implements \OCP\IL10N { /** * get an L10N instance - * @param $app string - * @param $lang string|null + * @param string $app + * @param string|null $lang * @return OC_L10N */ public static function get($app, $lang=null) { @@ -87,8 +87,8 @@ class OC_L10N implements \OCP\IL10N { /** * @brief The constructor - * @param $app string app requesting l10n - * @param $lang string default: null Language + * @param string $app app requesting l10n + * @param string $lang default: null Language * @returns OC_L10N-Object * * If language is not set, the constructor tries to find the right @@ -99,6 +99,9 @@ class OC_L10N implements \OCP\IL10N { $this->lang = $lang; } + /** + * @param string $transFile + */ public function load($transFile) { $this->app = true; include $transFile; @@ -115,7 +118,7 @@ class OC_L10N implements \OCP\IL10N { return; } $app = OC_App::cleanAppId($this->app); - $lang = $this->lang; + $lang = str_replace(array('\0', '/', '\\', '..'), '', $this->lang); $this->app = true; // Find the right language if(is_null($lang) || $lang == '') { @@ -132,10 +135,10 @@ class OC_L10N implements \OCP\IL10N { $i18ndir = self::findI18nDir($app); // Localization is in /l10n, Texts are in $i18ndir // (Just no need to define date/time format etc. twice) - if((OC_Helper::issubdirectory($i18ndir.$lang.'.php', OC_App::getAppPath($app).'/l10n/') - || OC_Helper::issubdirectory($i18ndir.$lang.'.php', OC::$SERVERROOT.'/core/l10n/') + if((OC_Helper::issubdirectory($i18ndir.$lang.'.php', OC::$SERVERROOT.'/core/l10n/') || OC_Helper::issubdirectory($i18ndir.$lang.'.php', OC::$SERVERROOT.'/lib/l10n/') || OC_Helper::issubdirectory($i18ndir.$lang.'.php', OC::$SERVERROOT.'/settings') + || OC_Helper::issubdirectory($i18ndir.$lang.'.php', OC_App::getAppPath($app).'/l10n/') ) && file_exists($i18ndir.$lang.'.php')) { // Include the file, save the data from $CONFIG @@ -160,7 +163,7 @@ class OC_L10N implements \OCP\IL10N { } } - if(file_exists(OC::$SERVERROOT.'/core/l10n/l10n-'.$lang.'.php')) { + if(file_exists(OC::$SERVERROOT.'/core/l10n/l10n-'.$lang.'.php') && OC_Helper::issubdirectory(OC::$SERVERROOT.'/core/l10n/l10n-'.$lang.'.php', OC::$SERVERROOT.'/core/l10n/')) { // Include the file, save the data from $CONFIG include OC::$SERVERROOT.'/core/l10n/l10n-'.$lang.'.php'; if(isset($LOCALIZATIONS) && is_array($LOCALIZATIONS)) { @@ -234,7 +237,7 @@ class OC_L10N implements \OCP\IL10N { /** * @brief Translating - * @param $text String The text we need a translation for + * @param string $text The text we need a translation for * @param array $parameters default:array() Parameters for sprintf * @return \OC_L10N_String Translation or the same text * @@ -247,9 +250,9 @@ class OC_L10N implements \OCP\IL10N { /** * @brief Translating - * @param $text_singular String the string to translate for exactly one object - * @param $text_plural String the string to translate for n objects - * @param $count Integer Number of objects + * @param string $text_singular the string to translate for exactly one object + * @param string $text_plural the string to translate for n objects + * @param integer $count Number of objects * @param array $parameters default:array() Parameters for sprintf * @return \OC_L10N_String Translation or the same text * @@ -348,7 +351,7 @@ class OC_L10N implements \OCP\IL10N { /** * @brief Localization - * @param $type Type of localization + * @param string $type Type of localization * @param $params parameters for this localization * @returns String or false * @@ -403,7 +406,7 @@ class OC_L10N implements \OCP\IL10N { /** * @brief Choose a language - * @param $texts Associative Array with possible strings + * @param array $text Associative Array with possible strings * @returns String * * $text is an array 'de' => 'hallo welt', 'en' => 'hello world', ... @@ -418,7 +421,7 @@ class OC_L10N implements \OCP\IL10N { /** * @brief find the best language - * @param $app Array or string, details below + * @param array|string $app details below * @returns string language * * If $app is an array, ownCloud assumes that these are the available @@ -491,7 +494,7 @@ class OC_L10N implements \OCP\IL10N { /** * @brief find the l10n directory - * @param $app App that needs to be translated + * @param string $app App that needs to be translated * @returns directory */ protected static function findI18nDir($app) { @@ -511,7 +514,7 @@ class OC_L10N implements \OCP\IL10N { /** * @brief find all available languages for an app - * @param $app App that needs to be translated + * @param string $app App that needs to be translated * @returns array an array of available languages */ public static function findAvailableLanguages($app=null) { @@ -529,6 +532,11 @@ class OC_L10N implements \OCP\IL10N { return $available; } + /** + * @param string $app + * @param string $lang + * @returns bool + */ public static function languageExists($app, $lang) { if ($lang == 'en') {//english is always available return true; diff --git a/lib/private/l10n/string.php b/lib/private/l10n/string.php index 88c85b32e70..04eaacab57b 100644 --- a/lib/private/l10n/string.php +++ b/lib/private/l10n/string.php @@ -27,6 +27,9 @@ class OC_L10N_String{ */ protected $count; + /** + * @param OC_L10N $l10n + */ public function __construct($l10n, $text, $parameters, $count = 1) { $this->l10n = $l10n; $this->text = $text; diff --git a/lib/private/legacy/appconfig.php b/lib/private/legacy/appconfig.php new file mode 100644 index 00000000000..b6c3542a673 --- /dev/null +++ b/lib/private/legacy/appconfig.php @@ -0,0 +1,128 @@ +<?php +/** + * ownCloud + * + * @author Frank Karlitschek + * @author Jakob Sack + * @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/>. + * + */ + +/** + * This class provides an easy way for apps to store config values in the + * database. + */ +class OC_Appconfig { + /** + * @return \OCP\IAppConfig + */ + private static function getAppConfig() { + return \OC::$server->getAppConfig(); + } + + /** + * @brief Get all apps using the config + * @return array with app ids + * + * This function returns a list of all apps that have at least one + * entry in the appconfig table. + */ + public static function getApps() { + return self::getAppConfig()->getApps(); + } + + /** + * @brief Get the available keys for an app + * @param string $app the app we are looking for + * @return array with key names + * + * This function gets all keys of an app. Please note that the values are + * not returned. + */ + public static function getKeys($app) { + return self::getAppConfig()->getKeys($app); + } + + /** + * @brief Gets the config value + * @param string $app app + * @param string $key key + * @param string $default = null, default value if the key does not exist + * @return string the value or $default + * + * This function gets a value from the appconfig table. If the key does + * not exist the default value will be returned + */ + public static function getValue($app, $key, $default = null) { + return self::getAppConfig()->getValue($app, $key, $default); + } + + /** + * @brief check if a key is set in the appconfig + * @param string $app + * @param string $key + * @return bool + */ + public static function hasKey($app, $key) { + return self::getAppConfig()->hasKey($app, $key); + } + + /** + * @brief sets a value in the appconfig + * @param string $app app + * @param string $key key + * @param string $value value + * + * Sets a value. If the key did not exist before it will be created. + */ + public static function setValue($app, $key, $value) { + self::getAppConfig()->setValue($app, $key, $value); + } + + /** + * @brief Deletes a key + * @param string $app app + * @param string $key key + * + * Deletes a key. + */ + public static function deleteKey($app, $key) { + self::getAppConfig()->deleteKey($app, $key); + } + + /** + * @brief Remove app from appconfig + * @param string $app app + * + * Removes all keys in appconfig belonging to the app. + */ + public static function deleteApp($app) { + self::getAppConfig()->deleteApp($app); + } + + /** + * get multiply values, either the app or key can be used as wildcard by setting it to false + * + * @param app + * @param key + * @param string|false $app + * @param string|false $key + * @return array + */ + public static function getValues($app, $key) { + return self::getAppConfig()->getValues($app, $key); + } +} diff --git a/lib/private/legacy/preferences.php b/lib/private/legacy/preferences.php index a663db7598b..fcde12796ca 100644 --- a/lib/private/legacy/preferences.php +++ b/lib/private/legacy/preferences.php @@ -41,7 +41,7 @@ class OC_Preferences{ /** * @brief Get all apps of a user * @param string $user user - * @return array with app ids + * @return integer[] with app ids * * This function returns a list of all apps of the user that have at least * one entry in the preferences table. diff --git a/lib/private/mail.php b/lib/private/mail.php index b339b33e962..9605290fe57 100644 --- a/lib/private/mail.php +++ b/lib/private/mail.php @@ -25,7 +25,7 @@ class OC_Mail { * @param string $mailtext * @param string $fromaddress * @param string $fromname - * @param bool|int $html + * @param integer $html * @param string $altbody * @param string $ccaddress * @param string $ccname @@ -72,11 +72,8 @@ class OC_Mail { $mailo->From = $fromaddress; $mailo->FromName = $fromname;; $mailo->Sender = $fromaddress; - $a=explode(' ', $toaddress); try { - foreach($a as $ad) { - $mailo->AddAddress($ad, $toname); - } + $mailo->AddAddress($toaddress, $toname); if($ccaddress<>'') $mailo->AddCC($ccaddress, $ccname); if($bcc<>'') $mailo->AddBCC($bcc); diff --git a/lib/private/memcache/factory.php b/lib/private/memcache/factory.php index 334cf9a1f0e..d60b157efe2 100644 --- a/lib/private/memcache/factory.php +++ b/lib/private/memcache/factory.php @@ -57,7 +57,7 @@ class Factory implements ICacheFactory { * get a in-server cache instance, will return null if no backend is available * * @param string $prefix - * @return \OC\Memcache\Cache + * @return null|Cache */ public static function createLowLatency($prefix = '') { if (XCache::isAvailable()) { diff --git a/lib/private/memcache/memcached.php b/lib/private/memcache/memcached.php index 978e6c2eff1..075828eebad 100644 --- a/lib/private/memcache/memcached.php +++ b/lib/private/memcache/memcached.php @@ -18,8 +18,16 @@ class Memcached extends Cache { parent::__construct($prefix); if (is_null(self::$cache)) { self::$cache = new \Memcached(); - list($host, $port) = \OC_Config::getValue('memcached_server', array('localhost', 11211)); - self::$cache->addServer($host, $port); + $servers = \OC_Config::getValue('memcached_servers'); + if (!$servers) { + $server = \OC_Config::getValue('memcached_server'); + if ($server) { + $servers = array($server); + } else { + $servers = array(array('localhost', 11211)); + } + } + self::$cache->addServers($servers); } } diff --git a/lib/private/migrate.php b/lib/private/migrate.php index 0b319177400..3fb3e334ea2 100644 --- a/lib/private/migrate.php +++ b/lib/private/migrate.php @@ -35,12 +35,8 @@ class OC_Migrate{ static private $zip=false; // Stores the type of export static private $exporttype=false; - // Array of temp files to be deleted after zip creation - static private $tmpfiles=array(); // Holds the db object - static private $MDB2=false; - // Schema db object - static private $schema=false; + static private $migration_database=false; // Path to the sqlite db static private $dbpath=false; // Holds the path to the zip file @@ -50,7 +46,7 @@ class OC_Migrate{ /** * register a new migration provider - * @param OC_Migrate_Provider $provider + * @param OC_Migration_Provider $provider */ public static function registerProvider($provider) { self::$providers[]=$provider; @@ -76,7 +72,7 @@ class OC_Migrate{ * @param optional $uid string user id of user to export if export type is user, defaults to current * @param ootional $type string type of export, defualts to user * @param otional $path string path to zip output folder - * @return false on error, path to zip on success + * @return string on error, path to zip on success */ public static function export( $uid=null, $type='user', $path=null ) { $datadir = OC_Config::getValue( 'datadirectory' ); @@ -131,7 +127,7 @@ class OC_Migrate{ if( !self::connectDB() ) { return json_encode( array( 'success' => false ) ); } - self::$content = new OC_Migration_Content( self::$zip, self::$MDB2 ); + self::$content = new OC_Migration_Content( self::$zip, self::$migration_database ); // Export the app info $exportdata = self::exportAppData(); // Add the data dir to the zip @@ -257,7 +253,7 @@ class OC_Migrate{ $userfolder = $extractpath . $json->exporteduser; $newuserfolder = $datadir . '/' . self::$uid; foreach(scandir($userfolder) as $file){ - if($file !== '.' && $file !== '..' && is_dir($file)) { + if($file !== '.' && $file !== '..' && is_dir($userfolder.'/'.$file)) { $file = str_replace(array('/', '\\'), '', $file); // Then copy the folder over @@ -311,7 +307,7 @@ class OC_Migrate{ /** * @brief recursively deletes a directory - * @param $dir string path of dir to delete + * @param string $dir string path of dir to delete * $param optional $deleteRootToo bool delete the root directory * @return bool */ @@ -359,24 +355,6 @@ class OC_Migrate{ } /** - * @brief connects to a MDB2 database scheme - * @returns bool - */ - static private function connectScheme() { - // We need a mdb2 database connection - self::$MDB2->loadModule( 'Manager' ); - self::$MDB2->loadModule( 'Reverse' ); - - // Connect if this did not happen before - if( !self::$schema ) { - require_once 'MDB2/Schema.php'; - self::$schema=MDB2_Schema::factory( self::$MDB2 ); - } - - return true; - } - - /** * @brief creates a migration.db in the users data dir with their app data in * @return bool whether operation was successfull */ @@ -429,7 +407,7 @@ class OC_Migrate{ /** * @brief generates json containing export info, and merges any data supplied * @param optional $array array of data to include in the returned json - * @return bool + * @return string */ static private function getExportInfo( $array=array() ) { $info = array( @@ -453,6 +431,7 @@ class OC_Migrate{ /** * @brief connects to migration.db, or creates if not found * @param $db optional path to migration.db, defaults to user data dir + * @param string $path * @return bool whether the operation was successful */ static private function connectDB( $path=null ) { @@ -463,47 +442,18 @@ class OC_Migrate{ return false; } // Already connected - if(!self::$MDB2) { - require_once 'MDB2.php'; - + if(!self::$migration_database) { $datadir = OC_Config::getValue( "datadirectory", OC::$SERVERROOT."/data" ); - - // DB type - if( class_exists( 'SQLite3' ) ) { - $dbtype = 'sqlite3'; - } else if( is_callable( 'sqlite_open' ) ) { - $dbtype = 'sqlite'; - } else { - OC_Log::write( 'migration', 'SQLite not found', OC_Log::ERROR ); - return false; - } - - // Prepare options array - $options = array( - 'portability' => MDB2_PORTABILITY_ALL & (!MDB2_PORTABILITY_FIX_CASE), - 'log_line_break' => '<br>', - 'idxname_format' => '%s', - 'debug' => true, - 'quote_identifier' => true - ); - $dsn = array( - 'phptype' => $dbtype, - 'database' => self::$dbpath, - 'mode' => '0644' + $connectionParams = array( + 'path' => self::$dbpath, + 'driver' => 'pdo_sqlite', ); + $connectionParams['adapter'] = '\OC\DB\AdapterSqlite'; + $connectionParams['wrapperClass'] = 'OC\DB\Connection'; + $connectionParams['tablePrefix'] = ''; // Try to establish connection - self::$MDB2 = MDB2::factory( $dsn, $options ); - // Die if we could not connect - if( PEAR::isError( self::$MDB2 ) ) { - die( self::$MDB2->getMessage() ); - OC_Log::write( 'migration', 'Failed to create/connect to migration.db', OC_Log::FATAL ); - OC_Log::write( 'migration', self::$MDB2->getUserInfo(), OC_Log::FATAL ); - OC_Log::write( 'migration', self::$MDB2->getMessage(), OC_Log::FATAL ); - return false; - } - // We always, really always want associative arrays - self::$MDB2->setFetchMode(MDB2_FETCHMODE_ASSOC); + self::$migration_database = \Doctrine\DBAL\DriverManager::getConnection($connectionParams); } return true; @@ -511,14 +461,11 @@ class OC_Migrate{ /** * @brief creates the tables in migration.db from an apps database.xml - * @param $appid string id of the app + * @param string $appid string id of the app * @return bool whether the operation was successful */ static private function createAppTables( $appid ) { - - if( !self::connectScheme() ) { - return false; - } + $schema_manager = new OC\DB\MDB2SchemaManager(self::$migration_database); // There is a database.xml file $content = file_get_contents(OC_App::getAppPath($appid) . '/appinfo/database.xml' ); @@ -538,29 +485,16 @@ class OC_Migrate{ file_put_contents( $file2, $content ); // Try to create tables - $definition = self::$schema->parseDatabaseDefinitionFile( $file2 ); - - unlink( $file2 ); - - // Die in case something went wrong - if( $definition instanceof MDB2_Schema_Error ) { - OC_Log::write( 'migration', 'Failed to parse database.xml for: '.$appid, OC_Log::FATAL ); - OC_Log::write( 'migration', $definition->getMessage().': '.$definition->getUserInfo(), OC_Log::FATAL ); - return false; - } - - $definition['overwrite'] = true; - - $ret = self::$schema->createDatabase( $definition ); - - // Die in case something went wrong - if( $ret instanceof MDB2_Error ) { + try { + $schema_manager->createDbFromStructure($file2); + } catch(Exception $e) { + unlink( $file2 ); OC_Log::write( 'migration', 'Failed to create tables for: '.$appid, OC_Log::FATAL ); - OC_Log::write( 'migration', $ret->getMessage().': '.$ret->getUserInfo(), OC_Log::FATAL ); + OC_Log::write( 'migration', $e->getMessage(), OC_Log::FATAL ); return false; } - return $tables; + return $tables; } /** @@ -602,7 +536,7 @@ class OC_Migrate{ /** * @brief imports a new user - * @param $db string path to migration.db + * @param string $db string path to migration.db * @param $info object of migration info * @param $uid optional uid to use * @return array of apps with import statuses, or false on failure. @@ -646,7 +580,7 @@ class OC_Migrate{ if( !self::connectDB( $db ) ) { return false; } - $content = new OC_Migration_Content( self::$zip, self::$MDB2 ); + $content = new OC_Migration_Content( self::$zip, self::$migration_database ); $provider->setData( self::$uid, $content, $info ); // Then do the import if( !$appsstatus[$id] = $provider->import( $info->apps->$id, $importinfo ) ) { diff --git a/lib/private/migration/content.php b/lib/private/migration/content.php index 4413d722731..43eba89b8d5 100644 --- a/lib/private/migration/content.php +++ b/lib/private/migration/content.php @@ -27,16 +27,16 @@ class OC_Migration_Content{ private $zip=false; - // Holds the MDB2 object + // Holds the database object private $db=null; // Holds an array of tmpfiles to delete after zip creation private $tmpfiles=array(); /** * @brief sets up the - * @param $zip ZipArchive object - * @param optional $db a MDB2 database object (required for exporttype user) - * @return bool + * @param ZipArchive $zip ZipArchive object + * @param $db a database object (required for exporttype user) + * @return boolean|null */ public function __construct( $zip, $db=null ) { @@ -47,6 +47,10 @@ class OC_Migration_Content{ // @brief prepares the db // @param $query the sql query to prepare + + /** + * @param string $query + */ public function prepare( $query ) { // Only add database to tmpfiles if actually used @@ -63,22 +67,14 @@ class OC_Migration_Content{ // Optimize the query $query = $this->db->prepare( $query ); + $query = new OC_DB_StatementWrapper($query, false); - // Die if we have an error (error means: bad query, not 0 results!) - if( PEAR::isError( $query ) ) { - $entry = 'DB Error: "'.$query->getMessage().'"<br />'; - $entry .= 'Offending command was: '.$query.'<br />'; - OC_Log::write( 'migration', $entry, OC_Log::FATAL ); - return false; - } else { - return $query; - } - + return $query; } /** * @brief processes the db query - * @param $query the query to process + * @param string $query the query to process * @return string of processed query */ private function processQuery( $query ) { @@ -134,7 +130,7 @@ class OC_Migration_Content{ /** * @brief saves a sql data set into migration.db - * @param $data a sql data set returned from self::prepare()->query() + * @param OC_DB_StatementWrapper $data a sql data set returned from self::prepare()->query() * @param $options array of copyRows options * @return void */ @@ -156,20 +152,14 @@ class OC_Migration_Content{ $sql .= $valuessql . " )"; // Make the query $query = $this->prepare( $sql ); - if( !$query ) { - OC_Log::write( 'migration', 'Invalid sql produced: '.$sql, OC_Log::FATAL ); - return false; - exit(); + $query->execute( $values ); + // Do we need to return some values? + if( array_key_exists( 'idcol', $options ) ) { + // Yes we do + $return[] = $row[$options['idcol']]; } else { - $query->execute( $values ); - // Do we need to return some values? - if( array_key_exists( 'idcol', $options ) ) { - // Yes we do - $return[] = $row[$options['idcol']]; - } else { - // Take a guess and return the first field :) - $return[] = reset($row); - } + // Take a guess and return the first field :) + $return[] = reset($row); } $fields = ''; $values = ''; @@ -179,7 +169,7 @@ class OC_Migration_Content{ /** * @brief adds a directory to the zip object - * @param $dir string path of the directory to add + * @param boolean|string $dir string path of the directory to add * @param $recursive bool * @param $internaldir string path of folder to add dir to in zip * @return bool @@ -214,8 +204,8 @@ class OC_Migration_Content{ /** * @brief adds a file to the zip from a given string - * @param $data string of data to add - * @param $path the relative path inside of the zip to save the file to + * @param string $data string of data to add + * @param string $path the relative path inside of the zip to save the file to * @return bool */ public function addFromString( $data, $path ) { diff --git a/lib/private/migration/provider.php b/lib/private/migration/provider.php index 234ab3351f3..2829a97a776 100644 --- a/lib/private/migration/provider.php +++ b/lib/private/migration/provider.php @@ -30,7 +30,7 @@ abstract class OC_Migration_Provider{ /** * @brief sets the OC_Migration_Content object to $this->content - * @param $content a OC_Migration_Content object + * @param OC_Migration_Content $content a OC_Migration_Content object */ public function setData( $uid, $content, $info=null ) { $this->content = $content; diff --git a/lib/private/mimetypes.list.php b/lib/private/mimetypes.list.php index 40fb1d2d97d..91bcf584267 100644 --- a/lib/private/mimetypes.list.php +++ b/lib/private/mimetypes.list.php @@ -24,88 +24,109 @@ * Array mapping file extensions to mimetypes (in alphabetical order). */ return array( - 'accdb'=>'application/msaccess', + '7z' => 'application/x-7z-compressed', + 'accdb' => 'application/msaccess', 'ai' => 'application/illustrator', - 'avi'=>'video/x-msvideo', + 'avi' => 'video/x-msvideo', 'bash' => 'text/x-shellscript', - 'blend'=>'application/x-blender', + 'blend' => 'application/x-blender', + 'bin' => 'application/x-bin', + 'bmp' => 'image/bmp', + 'cb7' => 'application/x-cbr', + 'cba' => 'application/x-cbr', + 'cbr' => 'application/x-cbr', + 'cbt' => 'application/x-cbr', + 'cbtc' => 'application/x-cbr', + 'cbz' => 'application/x-cbr', 'cc' => 'text/x-c', 'cdr' => 'application/coreldraw', 'cpp' => 'text/x-c++src', - 'css'=>'text/css', + 'css' => 'text/css', + 'csv' => 'text/csv', + 'cvbdl' => 'application/x-cbr', 'c' => 'text/x-c', 'c++' => 'text/x-c++src', - 'doc'=>'application/msword', - 'docx'=>'application/vnd.openxmlformats-officedocument.wordprocessingml.document', - 'dot'=>'application/msword', - 'dotx'=>'application/vnd.openxmlformats-officedocument.wordprocessingml.template', - 'dv'=>'video/dv', + 'deb' => 'application/x-deb', + 'doc' => 'application/msword', + 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'dot' => 'application/msword', + 'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template', + 'dv' => 'video/dv', + 'eot' => 'application/vnd.ms-fontobject', 'epub' => 'application/epub+zip', - 'exe'=>'application/x-ms-dos-executable', - 'flac'=>'audio/flac', - 'gif'=>'image/gif', - 'gz'=>'application/x-gzip', - 'gzip'=>'application/x-gzip', - 'html'=>'text/html', - 'htm'=>'text/html', - 'ical'=>'text/calendar', - 'ics'=>'text/calendar', + 'exe' => 'application/x-ms-dos-executable', + 'flac' => 'audio/flac', + 'gif' => 'image/gif', + 'gz' => 'application/x-gzip', + 'gzip' => 'application/x-gzip', + 'html' => 'text/html', + 'htm' => 'text/html', + 'ical' => 'text/calendar', + 'ics' => 'text/calendar', 'impress' => 'text/impress', - 'jpeg'=>'image/jpeg', - 'jpg'=>'image/jpeg', - 'js'=>'application/javascript', - 'keynote'=>'application/x-iwork-keynote-sffkey', - 'kra'=>'application/x-krita', - 'm2t'=>'video/mp2t', - 'm4v'=>'video/mp4', + 'jpeg' => 'image/jpeg', + 'jpg' => 'image/jpeg', + 'js' => 'application/javascript', + 'json' => 'application/json', + 'keynote' => 'application/x-iwork-keynote-sffkey', + 'kra' => 'application/x-krita', + 'm2t' => 'video/mp2t', + 'm4v' => 'video/mp4', 'markdown' => 'text/markdown', 'mdown' => 'text/markdown', 'md' => 'text/markdown', - 'mdb'=>'application/msaccess', + 'mdb' => 'application/msaccess', 'mdwn' => 'text/markdown', + 'mkv' => 'video/x-matroska', 'mobi' => 'application/x-mobipocket-ebook', - 'mov'=>'video/quicktime', - 'mp3'=>'audio/mpeg', - 'mp4'=>'video/mp4', - 'mpeg'=>'video/mpeg', - 'mpg'=>'video/mpeg', - 'msi'=>'application/x-msi', - 'numbers'=>'application/x-iwork-numbers-sffnumbers', - 'odg'=>'application/vnd.oasis.opendocument.graphics', - 'odp'=>'application/vnd.oasis.opendocument.presentation', - 'ods'=>'application/vnd.oasis.opendocument.spreadsheet', - 'odt'=>'application/vnd.oasis.opendocument.text', - 'oga'=>'audio/ogg', - 'ogg'=>'audio/ogg', - 'ogv'=>'video/ogg', - 'pages'=>'application/x-iwork-pages-sffpages', - 'pdf'=>'application/pdf', - 'php'=>'application/x-php', - 'pl'=>'application/x-pearl', - 'png'=>'image/png', - 'ppt'=>'application/mspowerpoint', - 'pptx'=>'application/vnd.openxmlformats-officedocument.presentationml.presentation', - 'psd'=>'application/x-photoshop', - 'py'=>'text/x-script.python', + 'mov' => 'video/quicktime', + 'mp3' => 'audio/mpeg', + 'mp4' => 'video/mp4', + 'mpeg' => 'video/mpeg', + 'mpg' => 'video/mpeg', + 'msi' => 'application/x-msi', + 'numbers' => 'application/x-iwork-numbers-sffnumbers', + 'odg' => 'application/vnd.oasis.opendocument.graphics', + 'odp' => 'application/vnd.oasis.opendocument.presentation', + 'ods' => 'application/vnd.oasis.opendocument.spreadsheet', + 'odt' => 'application/vnd.oasis.opendocument.text', + 'oga' => 'audio/ogg', + 'ogg' => 'audio/ogg', + 'ogv' => 'video/ogg', + 'otf' => 'font/opentype', + 'pages' => 'application/x-iwork-pages-sffpages', + 'pdf' => 'application/pdf', + 'php' => 'application/x-php', + 'pl' => 'application/x-perl', + 'png' => 'image/png', + 'ppt' => 'application/mspowerpoint', + 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation', + 'psd' => 'application/x-photoshop', + 'py' => 'text/x-python', + 'rar' => 'application/x-rar-compressed', 'reveal' => 'text/reveal', 'sgf' => 'application/sgf', 'sh-lib' => 'text/x-shellscript', 'sh' => 'text/x-shellscript', - 'svg'=>'image/svg+xml', - 'tar'=>'application/x-tar', - 'tar.gz'=>'application/x-compressed', - 'tgz'=>'application/x-compressed', - 'tiff'=>'image/tiff', - 'tif'=>'image/tiff', - 'txt'=>'text/plain', + 'svg' => 'image/svg+xml', + 'swf' => 'application/x-shockwave-flash', + 'tar' => 'application/x-tar', + 'tar.gz' => 'application/x-compressed', + 'tex' => 'application/x-tex', + 'tgz' => 'application/x-compressed', + 'tiff' => 'image/tiff', + 'tif' => 'image/tiff', + 'ttf' => 'application/x-font-ttf', + 'txt' => 'text/plain', 'vcard' => 'text/vcard', 'vcf' => 'text/vcard', - 'wav'=>'audio/wav', - 'webm'=>'video/webm', - 'wmv'=>'video/x-ms-asf', - 'xcf'=>'application/x-gimp', - 'xls'=>'application/msexcel', - 'xlsx'=>'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', - 'xml'=>'application/xml', - 'zip'=>'application/zip', + 'wav' => 'audio/wav', + 'webm' => 'video/webm', + 'woff' => 'application/font-woff', + 'wmv' => 'video/x-ms-asf', + 'xcf' => 'application/x-gimp', + 'xls' => 'application/msexcel', + 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'xml' => 'application/xml', + 'zip' => 'application/zip', ); diff --git a/lib/private/minimizer.php b/lib/private/minimizer.php deleted file mode 100644 index db522de74dc..00000000000 --- a/lib/private/minimizer.php +++ /dev/null @@ -1,64 +0,0 @@ -<?php - -abstract class OC_Minimizer { - public function generateETag($files) { - $fullpath_files = array(); - foreach($files as $file_info) { - $fullpath_files[] = $file_info[0] . '/' . $file_info[2]; - } - return OC_Cache::generateCacheKeyFromFiles($fullpath_files); - } - - abstract public function minimizeFiles($files); - - public function output($files, $cache_key) { - header('Content-Type: '.$this->contentType); - OC_Response::enableCaching(); - $etag = $this->generateETag($files); - $cache_key .= '-'.$etag; - - $gzout = false; - $cache = OC_Cache::getGlobalCache(); - if (!OC_Request::isNoCache() && (!defined('DEBUG') || !DEBUG)) { - OC_Response::setETagHeader($etag); - $gzout = $cache->get($cache_key.'.gz'); - } - - if (!$gzout) { - $out = $this->minimizeFiles($files); - $gzout = gzencode($out); - $cache->set($cache_key.'.gz', $gzout); - OC_Response::setETagHeader($etag); - } - // on some systems (e.g. SLES 11, but not Ubuntu) mod_deflate and zlib compression will compress the output twice. - // This results in broken core.css and core.js. To avoid it, we switch off zlib compression. - // Since mod_deflate is still active, Apache will compress what needs to be compressed, i.e. no disadvantage. - if(function_exists('apache_get_modules') && ini_get('zlib.output_compression') && in_array('mod_deflate', apache_get_modules())) { - ini_set('zlib.output_compression', 'Off'); - } - if ($encoding = OC_Request::acceptGZip()) { - header('Content-Encoding: '.$encoding); - $out = $gzout; - } else { - $out = gzdecode($gzout); - } - header('Content-Length: '.strlen($out)); - echo $out; - } - - public function clearCache() { - $cache = OC_Cache::getGlobalCache(); - $cache->clear('core.css'); - $cache->clear('core.js'); - } -} - -if (!function_exists('gzdecode')) { - function gzdecode($data, $maxlength=null, &$filename='', &$error='') - { - if (strcmp(substr($data, 0, 9),"\x1f\x8b\x8\0\0\0\0\0\0")) { - return null; // Not the GZIP format we expect (See RFC 1952) - } - return gzinflate(substr($data, 10, -8)); - } -} diff --git a/lib/private/minimizer/css.php b/lib/private/minimizer/css.php deleted file mode 100644 index 8d130572e2b..00000000000 --- a/lib/private/minimizer/css.php +++ /dev/null @@ -1,38 +0,0 @@ -<?php - -require_once 'mediawiki/CSSMin.php'; - -class OC_Minimizer_CSS extends OC_Minimizer -{ - protected $contentType = 'text/css'; - - public function minimizeFiles($files) { - $css_out = ''; - $webroot = (string) OC::$WEBROOT; - foreach($files as $file_info) { - $file = $file_info[0] . '/' . $file_info[2]; - $css_out .= '/* ' . $file . ' */' . "\n"; - $css = file_get_contents($file); - - $in_root = false; - foreach(OC::$APPSROOTS as $app_root) { - if(strpos($file, $app_root['path'].'/') === 0) { - $in_root = rtrim($webroot.$app_root['url'], '/'); - break; - } - } - if ($in_root !== false) { - $css = str_replace('%appswebroot%', $in_root, $css); - $css = str_replace('%webroot%', $webroot, $css); - } - $remote = $file_info[1]; - $remote .= '/'; - $remote .= dirname($file_info[2]); - $css_out .= CSSMin::remap($css, dirname($file), $remote, true); - } - if (!defined('DEBUG') || !DEBUG) { - $css_out = CSSMin::minify($css_out); - } - return $css_out; - } -} diff --git a/lib/private/minimizer/js.php b/lib/private/minimizer/js.php deleted file mode 100644 index bd2d836deb0..00000000000 --- a/lib/private/minimizer/js.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -require_once 'mediawiki/JavaScriptMinifier.php'; - -class OC_Minimizer_JS extends OC_Minimizer -{ - protected $contentType = 'application/javascript'; - - public function minimizeFiles($files) { - $js_out = ''; - foreach($files as $file_info) { - $file = $file_info[0] . '/' . $file_info[2]; - $js_out .= '/* ' . $file . ' */' . "\n"; - $js_out .= file_get_contents($file); - } - if (!defined('DEBUG') || !DEBUG) { - $js_out = JavaScriptMinifier::minify($js_out); - } - return $js_out; - } -} diff --git a/lib/private/ocs.php b/lib/private/ocs.php index e067196cf11..bbe965ce561 100644 --- a/lib/private/ocs.php +++ b/lib/private/ocs.php @@ -23,9 +23,6 @@ * */ -use Symfony\Component\Routing\Exception\ResourceNotFoundException; -use Symfony\Component\Routing\Exception\MethodNotAllowedException; - /** * Class to handle open collaboration services API requests * @@ -35,11 +32,11 @@ class OC_OCS { /** * reads input date from get/post/cookies and converts the date to a special data-type * - * @param string HTTP method to read the key from - * @param string Parameter to read - * @param string Variable type to format data - * @param mixed Default value to return if the key is not found - * @return mixed Data or if the key is not found and no default is set it will exit with a 400 Bad request + * @param string $method HTTP method to read the key from + * @param string $key Parameter to read + * @param string $type Variable type to format data + * @param string $default Default value to return if the key is not found + * @return string Data or if the key is not found and no default is set it will exit with a 400 Bad request */ public static function readData($method, $key, $type = 'raw', $default = null) { if ($method == 'get') { @@ -96,7 +93,7 @@ class OC_OCS { /** * generated some debug information to make it easier to find faild API calls - * @return debug data string + * @return string data string */ private static function getDebugOutput() { $txt=''; @@ -214,6 +211,9 @@ class OC_OCS { } } + /** + * @param string $node + */ public static function toXml($writer, $data, $node) { foreach($data as $key => $value) { if (is_numeric($key)) { diff --git a/lib/private/ocs/cloud.php b/lib/private/ocs/cloud.php index cbbf3b626f5..06d6a8eb4b0 100644 --- a/lib/private/ocs/cloud.php +++ b/lib/private/ocs/cloud.php @@ -61,17 +61,29 @@ class OC_OCS_Cloud { * the user from whom the information will be returned */ public static function getUser($parameters) { + $return = array(); // Check if they are viewing information on themselves if($parameters['userid'] === OC_User::getUser()) { // Self lookup $storage = OC_Helper::getStorageInfo('/'); - $quota = array( + $return['quota'] = array( 'free' => $storage['free'], 'used' => $storage['used'], 'total' => $storage['total'], 'relative' => $storage['relative'], ); - return new OC_OCS_Result(array('quota' => $quota)); + } + if(OC_User::isAdminUser(OC_User::getUser()) + || OC_Subadmin::isUserAccessible(OC_User::getUser(), $parameters['userid'])) { + if(OC_User::userExists($parameters['userid'])) { + // Is an admin/subadmin so can see display name + $return['displayname'] = OC_User::getDisplayName($parameters['userid']); + } else { + return new OC_OCS_Result(null, 101); + } + } + if(count($return)) { + return new OC_OCS_Result($return); } else { // No permission to view this user data return new OC_OCS_Result(null, 997); diff --git a/lib/private/ocs/result.php b/lib/private/ocs/result.php index 84f06fa01c7..9f14e8da7e8 100644 --- a/lib/private/ocs/result.php +++ b/lib/private/ocs/result.php @@ -29,7 +29,13 @@ class OC_OCS_Result{ * @param $data mixed the data to return */ public function __construct($data=null, $code=100, $message=null) { - $this->data = $data; + if ($data === null) { + $this->data = array(); + } elseif (!is_array($data)) { + $this->data = array($this->data); + } else { + $this->data = $data; + } $this->statusCode = $code; $this->message = $message; } @@ -49,7 +55,7 @@ class OC_OCS_Result{ public function setItemsPerPage(int $items) { $this->perPage = $items; } - + /** * get the status code * @return int @@ -57,7 +63,7 @@ class OC_OCS_Result{ public function getStatusCode() { return $this->statusCode; } - + /** * get the meta data for the result * @return array @@ -76,15 +82,15 @@ class OC_OCS_Result{ return $meta; } - + /** * get the result data - * @return array|string|int + * @return array */ public function getData() { return $this->data; } - + /** * return bool if the method succedded * @return bool diff --git a/lib/private/ocsclient.php b/lib/private/ocsclient.php index e35556d92b8..68dc2c2d6ec 100644 --- a/lib/private/ocsclient.php +++ b/lib/private/ocsclient.php @@ -50,6 +50,7 @@ class OC_OCSClient{ * @brief Get the content of an OCS url call. * @returns string of the response * This function calls an OCS server and returns the response. It also sets a sane timeout + * @param string $url */ private static function getOCSresponse($url) { $data = \OC_Util::getUrlContent($url); @@ -71,7 +72,9 @@ class OC_OCSClient{ if($xml==false) { return null; } - $data=simplexml_load_string($xml); + $loadEntities = libxml_disable_entity_loader(true); + $data = simplexml_load_string($xml); + libxml_disable_entity_loader($loadEntities); $tmp=$data->data; $cats=array(); @@ -92,6 +95,8 @@ class OC_OCSClient{ * @returns array with application data * * This function returns a list of all the applications on the OCS server + * @param integer $page + * @param string $filter */ public static function getApplications($categories, $page, $filter) { if(OC_Config::getValue('appstoreenabled', true)==false) { @@ -114,7 +119,9 @@ class OC_OCSClient{ if($xml==false) { return null; } - $data=simplexml_load_string($xml); + $loadEntities = libxml_disable_entity_loader(true); + $data = simplexml_load_string($xml); + libxml_disable_entity_loader($loadEntities); $tmp=$data->data->content; for($i = 0; $i < count($tmp); $i++) { @@ -156,7 +163,9 @@ class OC_OCSClient{ OC_Log::write('core', 'Unable to parse OCS content', OC_Log::FATAL); return null; } - $data=simplexml_load_string($xml); + $loadEntities = libxml_disable_entity_loader(true); + $data = simplexml_load_string($xml); + libxml_disable_entity_loader($loadEntities); $tmp=$data->data->content; $app=array(); @@ -184,6 +193,7 @@ class OC_OCSClient{ * @returns array with application data * * This function returns an download url for an applications from the OCS server + * @param integer $item */ public static function getApplicationDownload($id, $item) { if(OC_Config::getValue('appstoreenabled', true)==false) { @@ -196,7 +206,9 @@ class OC_OCSClient{ OC_Log::write('core', 'Unable to parse OCS content', OC_Log::FATAL); return null; } - $data=simplexml_load_string($xml); + $loadEntities = libxml_disable_entity_loader(true); + $data = simplexml_load_string($xml); + libxml_disable_entity_loader($loadEntities); $tmp=$data->data->content; $app=array(); diff --git a/lib/private/preferences.php b/lib/private/preferences.php index 359d9a83589..d45e6e77089 100644 --- a/lib/private/preferences.php +++ b/lib/private/preferences.php @@ -43,8 +43,26 @@ use \OC\DB\Connection; * This class provides an easy way for storing user preferences. */ class Preferences { + /** + * @var \OC\DB\Connection + */ protected $conn; + /** + * 3 dimensional array with the following structure: + * [ $userId => + * [ $appId => + * [ $key => $value ] + * ] + * ] + * + * @var array $cache + */ + protected $cache = array(); + + /** + * @param \OC\DB\Connection $conn + */ public function __construct(Connection $conn) { $this->conn = $conn; } @@ -58,10 +76,10 @@ class Preferences { */ public function getUsers() { $query = 'SELECT DISTINCT `userid` FROM `*PREFIX*preferences`'; - $result = $this->conn->executeQuery( $query ); + $result = $this->conn->executeQuery($query); $users = array(); - while( $userid = $result->fetchColumn()) { + while ($userid = $result->fetchColumn()) { $users[] = $userid; } @@ -69,23 +87,38 @@ class Preferences { } /** + * @param string $user + * @return array[] + */ + protected function getUserValues($user) { + if (isset($this->cache[$user])) { + return $this->cache[$user]; + } + $data = array(); + $query = 'SELECT `appid`, `configkey`, `configvalue` FROM `*PREFIX*preferences` WHERE `userid` = ?'; + $result = $this->conn->executeQuery($query, array($user)); + while ($row = $result->fetch()) { + $app = $row['appid']; + if (!isset($data[$app])) { + $data[$app] = array(); + } + $data[$app][$row['configkey']] = $row['configvalue']; + } + $this->cache[$user] = $data; + return $data; + } + + /** * @brief Get all apps of an user * @param string $user user - * @return array with app ids + * @return integer[] with app ids * * This function returns a list of all apps of the user that have at least * one entry in the preferences table. */ - public function getApps( $user ) { - $query = 'SELECT DISTINCT `appid` FROM `*PREFIX*preferences` WHERE `userid` = ?'; - $result = $this->conn->executeQuery( $query, array( $user ) ); - - $apps = array(); - while( $appid = $result->fetchColumn()) { - $apps[] = $appid; - } - - return $apps; + public function getApps($user) { + $data = $this->getUserValues($user); + return array_keys($data); } /** @@ -97,16 +130,13 @@ class Preferences { * This function gets all keys of an app of an user. Please note that the * values are not returned. */ - public function getKeys( $user, $app ) { - $query = 'SELECT `configkey` FROM `*PREFIX*preferences` WHERE `userid` = ? AND `appid` = ?'; - $result = $this->conn->executeQuery( $query, array( $user, $app )); - - $keys = array(); - while( $key = $result->fetchColumn()) { - $keys[] = $key; + public function getKeys($user, $app) { + $data = $this->getUserValues($user); + if (isset($data[$app])) { + return array_keys($data[$app]); + } else { + return array(); } - - return $keys; } /** @@ -120,13 +150,10 @@ class Preferences { * This function gets a value from the preferences table. If the key does * not exist the default value will be returned */ - public function getValue( $user, $app, $key, $default = null ) { - // Try to fetch the value, return default if not exists. - $query = 'SELECT `configvalue` FROM `*PREFIX*preferences`' - .' WHERE `userid` = ? AND `appid` = ? AND `configkey` = ?'; - $row = $this->conn->fetchAssoc( $query, array( $user, $app, $key )); - if($row) { - return $row["configvalue"]; + public function getValue($user, $app, $key, $default = null) { + $data = $this->getUserValues($user); + if (isset($data[$app]) and isset($data[$app][$key])) { + return $data[$app][$key]; } else { return $default; } @@ -142,14 +169,14 @@ class Preferences { * Adds a value to the preferences. If the key did not exist before, it * will be added automagically. */ - public function setValue( $user, $app, $key, $value ) { + public function setValue($user, $app, $key, $value) { // Check if the key does exist $query = 'SELECT COUNT(*) FROM `*PREFIX*preferences`' - .' WHERE `userid` = ? AND `appid` = ? AND `configkey` = ?'; - $count = $this->conn->fetchColumn( $query, array( $user, $app, $key )); + . ' WHERE `userid` = ? AND `appid` = ? AND `configkey` = ?'; + $count = $this->conn->fetchColumn($query, array($user, $app, $key)); $exists = $count > 0; - if( !$exists ) { + if (!$exists) { $data = array( 'userid' => $user, 'appid' => $app, @@ -168,6 +195,14 @@ class Preferences { ); $this->conn->update('*PREFIX*preferences', $data, $where); } + + // only add to the cache if we already loaded data for the user + if (isset($this->cache[$user])) { + if (!isset($this->cache[$user][$app])) { + $this->cache[$user][$app] = array(); + } + $this->cache[$user][$app][$key] = $value; + } } /** @@ -178,13 +213,17 @@ class Preferences { * * Deletes a key. */ - public function deleteKey( $user, $app, $key ) { + public function deleteKey($user, $app, $key) { $where = array( 'userid' => $user, 'appid' => $app, 'configkey' => $key, ); $this->conn->delete('*PREFIX*preferences', $where); + + if (isset($this->cache[$user]) and isset($this->cache[$user][$app])) { + unset($this->cache[$user][$app][$key]); + } } /** @@ -194,12 +233,16 @@ class Preferences { * * Removes all keys in preferences belonging to the app and the user. */ - public function deleteApp( $user, $app ) { + public function deleteApp($user, $app) { $where = array( 'userid' => $user, 'appid' => $app, ); $this->conn->delete('*PREFIX*preferences', $where); + + if (isset($this->cache[$user])) { + unset($this->cache[$user][$app]); + } } /** @@ -208,11 +251,13 @@ class Preferences { * * Removes all keys in preferences belonging to the user. */ - public function deleteUser( $user ) { + public function deleteUser($user) { $where = array( 'userid' => $user, ); $this->conn->delete('*PREFIX*preferences', $where); + + unset($this->cache[$user]); } /** @@ -221,12 +266,16 @@ class Preferences { * * Removes all keys in preferences belonging to the app. */ - public function deleteAppFromAllUsers( $app ) { + public function deleteAppFromAllUsers($app) { $where = array( 'appid' => $app, ); $this->conn->delete('*PREFIX*preferences', $where); + + foreach ($this->cache as &$userCache) { + unset($userCache[$app]); + } } } -require_once __DIR__.'/legacy/'.basename(__FILE__); +require_once __DIR__ . '/legacy/' . basename(__FILE__); diff --git a/lib/private/preview.php b/lib/private/preview.php index ff93f438f73..0c1af3c9588 100755 --- a/lib/private/preview.php +++ b/lib/private/preview.php @@ -42,6 +42,10 @@ class Preview { private $scalingup; private $mimetype; + //filemapper used for deleting previews + // index is path, value is fileinfo + static public $deleteFileMapper = array(); + //preview images object /** * @var \OC_Image @@ -53,6 +57,11 @@ class Preview { static private $registeredProviders = array(); /** + * @var \OCP\Files\FileInfo + */ + protected $info; + + /** * @brief check if thumbnail or bigger version of thumbnail of file is cached * @param string $user userid - if no user is given, OC_User::getUser will be used * @param string $root path of root @@ -61,12 +70,12 @@ class Preview { * @param int $maxY The maximum Y size of the thumbnail. It can be smaller depending on the shape of the image * @param bool $scalingUp Disable/Enable upscaling of previews * @return mixed (bool / string) - * false if thumbnail does not exist - * path to thumbnail if thumbnail exists - */ - public function __construct($user='', $root='/', $file='', $maxX=1, $maxY=1, $scalingUp=true) { + * false if thumbnail does not exist + * path to thumbnail if thumbnail exists + */ + public function __construct($user = '', $root = '/', $file = '', $maxX = 1, $maxY = 1, $scalingUp = true) { //init fileviews - if($user === ''){ + if ($user === '') { $user = \OC_User::getUser(); } $this->fileView = new \OC\Files\View('/' . $user . '/' . $root); @@ -86,11 +95,11 @@ class Preview { $this->preview = null; //check if there are preview backends - if(empty(self::$providers)) { + if (empty(self::$providers)) { self::initProviders(); } - if(empty(self::$providers)) { + if (empty(self::$providers)) { \OC_Log::write('core', 'No preview providers exist', \OC_Log::ERROR); throw new \Exception('No preview providers'); } @@ -99,15 +108,15 @@ class Preview { /** * @brief returns the path of the file you want a thumbnail from * @return string - */ - public function getFile() { + */ + public function getFile() { return $this->file; } /** * @brief returns the max width of the preview * @return integer - */ + */ public function getMaxX() { return $this->maxX; } @@ -115,7 +124,7 @@ class Preview { /** * @brief returns the max height of the preview * @return integer - */ + */ public function getMaxY() { return $this->maxY; } @@ -123,7 +132,7 @@ class Preview { /** * @brief returns whether or not scalingup is enabled * @return bool - */ + */ public function getScalingUp() { return $this->scalingup; } @@ -131,44 +140,59 @@ class Preview { /** * @brief returns the name of the thumbnailfolder * @return string - */ + */ public function getThumbnailsFolder() { return self::THUMBNAILS_FOLDER; } /** * @brief returns the max scale factor - * @return integer - */ + * @return string + */ public function getMaxScaleFactor() { return $this->maxScaleFactor; } /** * @brief returns the max width set in ownCloud's config - * @return integer - */ + * @return string + */ public function getConfigMaxX() { return $this->configMaxX; } /** * @brief returns the max height set in ownCloud's config - * @return integer - */ + * @return string + */ public function getConfigMaxY() { return $this->configMaxY; } + protected function getFileInfo() { + $absPath = $this->fileView->getAbsolutePath($this->file); + $absPath = Files\Filesystem::normalizePath($absPath); + if(array_key_exists($absPath, self::$deleteFileMapper)) { + $this->info = self::$deleteFileMapper[$absPath]; + } else if (!$this->info) { + $this->info = $this->fileView->getFileInfo($this->file); + } + return $this->info; + } + /** * @brief set the path of the file you want a thumbnail from * @param string $file * @return $this - */ + */ public function setFile($file) { $this->file = $file; + $this->info = null; if ($file !== '') { - $this->mimetype = $this->fileView->getMimeType($this->file); + $this->getFileInfo(); + if($this->info !== null && $this->info !== false) { + $this->mimetype = $this->info->getMimetype(); + } } return $this; } @@ -185,14 +209,14 @@ class Preview { * @brief set the the max width of the preview * @param int $maxX * @return $this - */ - public function setMaxX($maxX=1) { - if($maxX <= 0) { + */ + public function setMaxX($maxX = 1) { + if ($maxX <= 0) { throw new \Exception('Cannot set width of 0 or smaller!'); } $configMaxX = $this->getConfigMaxX(); - if(!is_null($configMaxX)) { - if($maxX > $configMaxX) { + if (!is_null($configMaxX)) { + if ($maxX > $configMaxX) { \OC_Log::write('core', 'maxX reduced from ' . $maxX . ' to ' . $configMaxX, \OC_Log::DEBUG); $maxX = $configMaxX; } @@ -205,14 +229,14 @@ class Preview { * @brief set the the max height of the preview * @param int $maxY * @return $this - */ - public function setMaxY($maxY=1) { - if($maxY <= 0) { + */ + public function setMaxY($maxY = 1) { + if ($maxY <= 0) { throw new \Exception('Cannot set height of 0 or smaller!'); } $configMaxY = $this->getConfigMaxY(); - if(!is_null($configMaxY)) { - if($maxY > $configMaxY) { + if (!is_null($configMaxY)) { + if ($maxY > $configMaxY) { \OC_Log::write('core', 'maxX reduced from ' . $maxY . ' to ' . $configMaxY, \OC_Log::DEBUG); $maxY = $configMaxY; } @@ -225,9 +249,9 @@ class Preview { * @brief set whether or not scalingup is enabled * @param bool $scalingUp * @return $this - */ + */ public function setScalingup($scalingUp) { - if($this->getMaxScaleFactor() === 1) { + if ($this->getMaxScaleFactor() === 1) { $scalingUp = false; } $this->scalingup = $scalingUp; @@ -237,15 +261,15 @@ class Preview { /** * @brief check if all parameters are valid * @return bool - */ + */ public function isFileValid() { $file = $this->getFile(); - if($file === '') { + if ($file === '') { \OC_Log::write('core', 'No filename passed', \OC_Log::DEBUG); return false; } - if(!$this->fileView->file_exists($file)) { + if (!$this->fileView->file_exists($file)) { \OC_Log::write('core', 'File:"' . $file . '" not found', \OC_Log::DEBUG); return false; } @@ -256,40 +280,44 @@ class Preview { /** * @brief deletes previews of a file with specific x and y * @return bool - */ + */ public function deletePreview() { $file = $this->getFile(); - $fileInfo = $this->fileView->getFileInfo($file); - $fileId = $fileInfo['fileid']; + $fileInfo = $this->getFileInfo($file); + if($fileInfo !== null && $fileInfo !== false) { + $fileId = $fileInfo->getId(); - $previewPath = $this->getThumbnailsFolder() . '/' . $fileId . '/' . $this->getMaxX() . '-' . $this->getMaxY() . '.png'; - $this->userView->unlink($previewPath); - return !$this->userView->file_exists($previewPath); + $previewPath = $this->getThumbnailsFolder() . '/' . $fileId . '/' . $this->getMaxX() . '-' . $this->getMaxY() . '.png'; + return $this->userView->unlink($previewPath); + } + return false; } /** * @brief deletes all previews of a file * @return bool - */ + */ public function deleteAllPreviews() { $file = $this->getFile(); - $fileInfo = $this->fileView->getFileInfo($file); - $fileId = $fileInfo['fileid']; + $fileInfo = $this->getFileInfo($file); + if($fileInfo !== null && $fileInfo !== false) { + $fileId = $fileInfo->getId(); - $previewPath = $this->getThumbnailsFolder() . '/' . $fileId . '/'; - $this->userView->deleteAll($previewPath); - $this->userView->rmdir($previewPath); - return !$this->userView->is_dir($previewPath); + $previewPath = $this->getThumbnailsFolder() . '/' . $fileId . '/'; + $this->userView->deleteAll($previewPath); + return $this->userView->rmdir($previewPath); + } + return false; } /** * @brief check if thumbnail or bigger version of thumbnail of file is cached * @return mixed (bool / string) - * false if thumbnail does not exist - * path to thumbnail if thumbnail exists - */ + * false if thumbnail does not exist + * path to thumbnail if thumbnail exists + */ private function isCached() { $file = $this->getFile(); $maxX = $this->getMaxX(); @@ -297,75 +325,75 @@ class Preview { $scalingUp = $this->getScalingUp(); $maxScaleFactor = $this->getMaxScaleFactor(); - $fileInfo = $this->fileView->getFileInfo($file); - $fileId = $fileInfo['fileid']; + $fileInfo = $this->getFileInfo($file); + $fileId = $fileInfo->getId(); - if(is_null($fileId)) { + if (is_null($fileId)) { return false; } $previewPath = $this->getThumbnailsFolder() . '/' . $fileId . '/'; - if(!$this->userView->is_dir($previewPath)) { + if (!$this->userView->is_dir($previewPath)) { return false; } //does a preview with the wanted height and width already exist? - if($this->userView->file_exists($previewPath . $maxX . '-' . $maxY . '.png')) { + if ($this->userView->file_exists($previewPath . $maxX . '-' . $maxY . '.png')) { return $previewPath . $maxX . '-' . $maxY . '.png'; } - $wantedAspectRatio = (float) ($maxX / $maxY); + $wantedAspectRatio = (float)($maxX / $maxY); //array for usable cached thumbnails $possibleThumbnails = array(); $allThumbnails = $this->userView->getDirectoryContent($previewPath); - foreach($allThumbnails as $thumbnail) { + foreach ($allThumbnails as $thumbnail) { $name = rtrim($thumbnail['name'], '.png'); $size = explode('-', $name); - $x = (int) $size[0]; - $y = (int) $size[1]; + $x = (int)$size[0]; + $y = (int)$size[1]; - $aspectRatio = (float) ($x / $y); - if($aspectRatio !== $wantedAspectRatio) { + $aspectRatio = (float)($x / $y); + if ($aspectRatio !== $wantedAspectRatio) { continue; } - if($x < $maxX || $y < $maxY) { - if($scalingUp) { + if ($x < $maxX || $y < $maxY) { + if ($scalingUp) { $scalefactor = $maxX / $x; - if($scalefactor > $maxScaleFactor) { + if ($scalefactor > $maxScaleFactor) { continue; } - }else{ + } else { continue; } } $possibleThumbnails[$x] = $thumbnail['path']; } - if(count($possibleThumbnails) === 0) { + if (count($possibleThumbnails) === 0) { return false; } - if(count($possibleThumbnails) === 1) { + if (count($possibleThumbnails) === 1) { return current($possibleThumbnails); } ksort($possibleThumbnails); - if(key(reset($possibleThumbnails)) > $maxX) { + if (key(reset($possibleThumbnails)) > $maxX) { return current(reset($possibleThumbnails)); } - if(key(end($possibleThumbnails)) < $maxX) { + if (key(end($possibleThumbnails)) < $maxX) { return current(end($possibleThumbnails)); } - foreach($possibleThumbnails as $width => $path) { - if($width < $maxX) { + foreach ($possibleThumbnails as $width => $path) { + if ($width < $maxX) { continue; - }else{ + } else { return $path; } } @@ -374,9 +402,9 @@ class Preview { /** * @brief return a preview of a file * @return \OC_Image - */ + */ public function getPreview() { - if(!is_null($this->preview) && $this->preview->valid()){ + if (!is_null($this->preview) && $this->preview->valid()) { return $this->preview; } @@ -386,22 +414,28 @@ class Preview { $maxY = $this->getMaxY(); $scalingUp = $this->getScalingUp(); - $fileInfo = $this->fileView->getFileInfo($file); - $fileId = $fileInfo['fileid']; + $fileInfo = $this->getFileInfo($file); + if($fileInfo === null || $fileInfo === false) { + return new \OC_Image(); + } + $fileId = $fileInfo->getId(); $cached = $this->isCached(); - if($cached) { - $image = new \OC_Image($this->userView->file_get_contents($cached, 'r')); + if ($cached) { + $stream = $this->userView->fopen($cached, 'r'); + $image = new \OC_Image(); + $image->loadFromFileHandle($stream); $this->preview = $image->valid() ? $image : null; $this->resizeAndCrop(); + fclose($stream); } - if(is_null($this->preview)) { + if (is_null($this->preview)) { $preview = null; - foreach(self::$providers as $supportedMimetype => $provider) { - if(!preg_match($supportedMimetype, $this->mimetype)) { + foreach (self::$providers as $supportedMimetype => $provider) { + if (!preg_match($supportedMimetype, $this->mimetype)) { continue; } @@ -409,7 +443,7 @@ class Preview { $preview = $provider->getThumbnail($file, $maxX, $maxY, $scalingUp, $this->fileView); - if(!($preview instanceof \OC_Image)) { + if (!($preview instanceof \OC_Image)) { continue; } @@ -419,11 +453,11 @@ class Preview { $previewPath = $this->getThumbnailsFolder() . '/' . $fileId . '/'; $cachePath = $previewPath . $maxX . '-' . $maxY . '.png'; - if($this->userView->is_dir($this->getThumbnailsFolder() . '/') === false) { + if ($this->userView->is_dir($this->getThumbnailsFolder() . '/') === false) { $this->userView->mkdir($this->getThumbnailsFolder() . '/'); } - if($this->userView->is_dir($previewPath) === false) { + if ($this->userView->is_dir($previewPath) === false) { $this->userView->mkdir($previewPath); } @@ -433,7 +467,7 @@ class Preview { } } - if(is_null($this->preview)) { + if (is_null($this->preview)) { $this->preview = new \OC_Image(); } @@ -443,20 +477,20 @@ class Preview { /** * @brief show preview * @return void - */ + */ public function showPreview() { \OCP\Response::enableCaching(3600 * 24); // 24 hours - if(is_null($this->preview)) { + if (is_null($this->preview)) { $this->getPreview(); } - $this->preview->show(); + $this->preview->show('image/png'); return; } /** * @brief show preview * @return void - */ + */ public function show() { $this->showPreview(); return; @@ -465,7 +499,7 @@ class Preview { /** * @brief resize, crop and fix orientation * @return void - */ + */ private function resizeAndCrop() { $image = $this->preview; $x = $this->getMaxX(); @@ -473,17 +507,17 @@ class Preview { $scalingUp = $this->getScalingUp(); $maxscalefactor = $this->getMaxScaleFactor(); - if(!($image instanceof \OC_Image)) { + if (!($image instanceof \OC_Image)) { \OC_Log::write('core', '$this->preview is not an instance of OC_Image', \OC_Log::DEBUG); return; } $image->fixOrientation(); - $realx = (int) $image->width(); - $realy = (int) $image->height(); + $realx = (int)$image->width(); + $realy = (int)$image->height(); - if($x === $realx && $y === $realy) { + if ($x === $realx && $y === $realy) { $this->preview = $image; return; } @@ -491,36 +525,36 @@ class Preview { $factorX = $x / $realx; $factorY = $y / $realy; - if($factorX >= $factorY) { + if ($factorX >= $factorY) { $factor = $factorX; - }else{ + } else { $factor = $factorY; } - if($scalingUp === false) { - if($factor > 1) { + if ($scalingUp === false) { + if ($factor > 1) { $factor = 1; } } - if(!is_null($maxscalefactor)) { - if($factor > $maxscalefactor) { + if (!is_null($maxscalefactor)) { + if ($factor > $maxscalefactor) { \OC_Log::write('core', 'scalefactor reduced from ' . $factor . ' to ' . $maxscalefactor, \OC_Log::DEBUG); $factor = $maxscalefactor; } } - $newXsize = (int) ($realx * $factor); - $newYsize = (int) ($realy * $factor); + $newXsize = (int)($realx * $factor); + $newYsize = (int)($realy * $factor); $image->preciseResize($newXsize, $newYsize); - if($newXsize === $x && $newYsize === $y) { + if ($newXsize === $x && $newYsize === $y) { $this->preview = $image; return; } - if($newXsize >= $x && $newYsize >= $y) { + if ($newXsize >= $x && $newYsize >= $y) { $cropX = floor(abs($x - $newXsize) * 0.5); //don't crop previews on the Y axis, this sucks if it's a document. //$cropY = floor(abs($y - $newYsize) * 0.5); @@ -532,19 +566,19 @@ class Preview { return; } - if($newXsize < $x || $newYsize < $y) { - if($newXsize > $x) { + if ($newXsize < $x || $newYsize < $y) { + if ($newXsize > $x) { $cropX = floor(($newXsize - $x) * 0.5); $image->crop($cropX, 0, $x, $newYsize); } - if($newYsize > $y) { + if ($newYsize > $y) { $cropY = floor(($newYsize - $y) * 0.5); $image->crop(0, $cropY, $newXsize, $y); } - $newXsize = (int) $image->width(); - $newYsize = (int) $image->height(); + $newXsize = (int)$image->width(); + $newYsize = (int)$image->height(); //create transparent background layer $backgroundlayer = imagecreatetruecolor($x, $y); @@ -570,12 +604,11 @@ class Preview { /** * @brief register a new preview provider to be used - * @param string $provider class name of a Preview_Provider * @param array $options * @return void */ - public static function registerProvider($class, $options=array()) { - self::$registeredProviders[]=array('class'=>$class, 'options'=>$options); + public static function registerProvider($class, $options = array()) { + self::$registeredProviders[] = array('class' => $class, 'options' => $options); } /** @@ -583,19 +616,19 @@ class Preview { * @return void */ private static function initProviders() { - if(!\OC_Config::getValue('enable_previews', true)) { + if (!\OC_Config::getValue('enable_previews', true)) { $provider = new Preview\Unknown(array()); self::$providers = array($provider->getMimeType() => $provider); return; } - if(count(self::$providers)>0) { + if (count(self::$providers) > 0) { return; } - foreach(self::$registeredProviders as $provider) { - $class=$provider['class']; - $options=$provider['options']; + foreach (self::$registeredProviders as $provider) { + $class = $provider['class']; + $options = $provider['options']; $object = new $class($options); @@ -610,29 +643,55 @@ class Preview { self::post_delete($args); } - public static function post_delete($args) { + public static function prepare_delete_files($args) { + self::prepare_delete($args, 'files/'); + } + + public static function prepare_delete($args, $prefix='') { $path = $args['path']; - if(substr($path, 0, 1) === '/') { + if (substr($path, 0, 1) === '/') { $path = substr($path, 1); } - $preview = new Preview(\OC_User::getUser(), 'files/', $path); + + $view = new \OC\Files\View('/' . \OC_User::getUser() . '/' . $prefix); + $info = $view->getFileInfo($path); + + \OC\Preview::$deleteFileMapper = array_merge( + \OC\Preview::$deleteFileMapper, + array( + Files\Filesystem::normalizePath($view->getAbsolutePath($path)) => $info, + ) + ); + } + + public static function post_delete_files($args) { + self::post_delete($args, 'files/'); + } + + public static function post_delete($args, $prefix='') { + $path = Files\Filesystem::normalizePath($args['path']); + + $preview = new Preview(\OC_User::getUser(), $prefix, $path); $preview->deleteAllPreviews(); } + /** + * @param string $mimetype + */ public static function isMimeSupported($mimetype) { - if(!\OC_Config::getValue('enable_previews', true)) { + if (!\OC_Config::getValue('enable_previews', true)) { return false; } //check if there are preview backends - if(empty(self::$providers)) { + if (empty(self::$providers)) { self::initProviders(); } //remove last element because it has the mimetype * $providers = array_slice(self::$providers, 0, -1); - foreach($providers as $supportedMimetype => $provider) { - if(preg_match($supportedMimetype, $mimetype)) { + foreach ($providers as $supportedMimetype => $provider) { + if (preg_match($supportedMimetype, $mimetype)) { return true; } } diff --git a/lib/private/preview/movies.php b/lib/private/preview/movies.php index 71cd3bae057..7e0ff51ad2e 100644 --- a/lib/private/preview/movies.php +++ b/lib/private/preview/movies.php @@ -9,7 +9,7 @@ namespace OC\Preview; function findBinaryPath($program) { - exec('which ' . escapeshellarg($program) . ' 2> /dev/null', $output, $returnCode); + exec('command -v ' . escapeshellarg($program) . ' 2> /dev/null', $output, $returnCode); if ($returnCode === 0 && count($output) > 0) { return escapeshellcmd($output[0]); } diff --git a/lib/private/preview/office-cl.php b/lib/private/preview/office-cl.php index b11fed13ba1..6e4d4321eb7 100644 --- a/lib/private/preview/office-cl.php +++ b/lib/private/preview/office-cl.php @@ -64,12 +64,12 @@ if (!\OC_Util::runningOnWindows()) { $cmd = \OC_Config::getValue('preview_libreoffice_path', null); } - $whichLibreOffice = shell_exec('which libreoffice'); + $whichLibreOffice = shell_exec('command -v libreoffice'); if($cmd === '' && !empty($whichLibreOffice)) { $cmd = 'libreoffice'; } - $whichOpenOffice = shell_exec('which openoffice'); + $whichOpenOffice = shell_exec('command -v openoffice'); if($cmd === '' && !empty($whichOpenOffice)) { $cmd = 'openoffice'; } diff --git a/lib/private/preview/office.php b/lib/private/preview/office.php index 7a4826c76ec..882c4426e6d 100644 --- a/lib/private/preview/office.php +++ b/lib/private/preview/office.php @@ -7,23 +7,28 @@ */ //both, libreoffice backend and php fallback, need imagick if (extension_loaded('imagick')) { - $isShellExecEnabled = \OC_Helper::is_function_enabled('shell_exec'); - // LibreOffice preview is currently not supported on Windows - if (!\OC_Util::runningOnWindows()) { - $whichLibreOffice = ($isShellExecEnabled ? shell_exec('which libreoffice') : ''); - $isLibreOfficeAvailable = !empty($whichLibreOffice); - $whichOpenOffice = ($isShellExecEnabled ? shell_exec('which libreoffice') : ''); - $isOpenOfficeAvailable = !empty($whichOpenOffice); - //let's see if there is libreoffice or openoffice on this machine - if($isShellExecEnabled && ($isLibreOfficeAvailable || $isOpenOfficeAvailable || is_string(\OC_Config::getValue('preview_libreoffice_path', null)))) { - require_once('office-cl.php'); - }else{ + $checkImagick = new Imagick(); + + if(count($checkImagick->queryFormats('PDF')) === 1) { + $isShellExecEnabled = \OC_Helper::is_function_enabled('shell_exec'); + + // LibreOffice preview is currently not supported on Windows + if (!\OC_Util::runningOnWindows()) { + $whichLibreOffice = ($isShellExecEnabled ? shell_exec('command -v libreoffice') : ''); + $isLibreOfficeAvailable = !empty($whichLibreOffice); + $whichOpenOffice = ($isShellExecEnabled ? shell_exec('command -v libreoffice') : ''); + $isOpenOfficeAvailable = !empty($whichOpenOffice); + //let's see if there is libreoffice or openoffice on this machine + if($isShellExecEnabled && ($isLibreOfficeAvailable || $isOpenOfficeAvailable || is_string(\OC_Config::getValue('preview_libreoffice_path', null)))) { + require_once('office-cl.php'); + }else{ + //in case there isn't, use our fallback + require_once('office-fallback.php'); + } + } else { //in case there isn't, use our fallback require_once('office-fallback.php'); } - } else { - //in case there isn't, use our fallback - require_once('office-fallback.php'); } } diff --git a/lib/private/preview/pdf.php b/lib/private/preview/pdf.php index cc974b68818..064a5a3b3d1 100644 --- a/lib/private/preview/pdf.php +++ b/lib/private/preview/pdf.php @@ -7,34 +7,41 @@ */ namespace OC\Preview; +use Imagick; + if (extension_loaded('imagick')) { - class PDF extends Provider { + $checkImagick = new Imagick(); - public function getMimeType() { - return '/application\/pdf/'; - } + if(count($checkImagick->queryFormats('PDF')) === 1) { - public function getThumbnail($path, $maxX, $maxY, $scalingup, $fileview) { - $tmpPath = $fileview->toTmpFile($path); + class PDF extends Provider { - //create imagick object from pdf - try{ - $pdf = new \imagick($tmpPath . '[0]'); - $pdf->setImageFormat('jpg'); - } catch (\Exception $e) { - \OC_Log::write('core', $e->getmessage(), \OC_Log::ERROR); - return false; + public function getMimeType() { + return '/application\/pdf/'; } - unlink($tmpPath); + public function getThumbnail($path, $maxX, $maxY, $scalingup, $fileview) { + $tmpPath = $fileview->toTmpFile($path); + + //create imagick object from pdf + try{ + $pdf = new Imagick($tmpPath . '[0]'); + $pdf->setImageFormat('jpg'); + } catch (\Exception $e) { + \OC_Log::write('core', $e->getmessage(), \OC_Log::ERROR); + return false; + } + + unlink($tmpPath); - //new image object - $image = new \OC_Image($pdf); - //check if image object is valid - return $image->valid() ? $image : false; + //new image object + $image = new \OC_Image($pdf); + //check if image object is valid + return $image->valid() ? $image : false; + } } - } - \OC\Preview::registerProvider('OC\Preview\PDF'); + \OC\Preview::registerProvider('OC\Preview\PDF'); + } } diff --git a/lib/private/preview/provider.php b/lib/private/preview/provider.php index 65d09705f40..88337d64e4b 100644 --- a/lib/private/preview/provider.php +++ b/lib/private/preview/provider.php @@ -15,7 +15,7 @@ abstract class Provider { * @param string $path Path of file * @param int $maxX The maximum X size of the thumbnail. It can be smaller depending on the shape of the image * @param int $maxY The maximum Y size of the thumbnail. It can be smaller depending on the shape of the image - * @param bool $scalingUp Disable/Enable upscaling of previews + * @param bool $scalingup Disable/Enable upscaling of previews * @param object $fileview fileview object of user folder * @return mixed * false if no preview was generated diff --git a/lib/private/preview/svg.php b/lib/private/preview/svg.php index b49e51720fa..505122fddbf 100644 --- a/lib/private/preview/svg.php +++ b/lib/private/preview/svg.php @@ -7,40 +7,46 @@ */ namespace OC\Preview; +use Imagick; + if (extension_loaded('imagick')) { - class SVG extends Provider { + $checkImagick = new Imagick(); - public function getMimeType() { - return '/image\/svg\+xml/'; - } + if(count($checkImagick->queryFormats('SVG')) === 1) { - public function getThumbnail($path,$maxX,$maxY,$scalingup,$fileview) { - try{ - $svg = new \Imagick(); - $svg->setBackgroundColor(new \ImagickPixel('transparent')); + class SVG extends Provider { - $content = stream_get_contents($fileview->fopen($path, 'r')); - if(substr($content, 0, 5) !== '<?xml') { - $content = '<?xml version="1.0" encoding="UTF-8" standalone="no"?>' . $content; - } - - $svg->readImageBlob($content); - $svg->setImageFormat('png32'); - } catch (\Exception $e) { - \OC_Log::write('core', $e->getmessage(), \OC_Log::ERROR); - return false; + public function getMimeType() { + return '/image\/svg\+xml/'; } + public function getThumbnail($path,$maxX,$maxY,$scalingup,$fileview) { + try{ + $svg = new Imagick(); + $svg->setBackgroundColor(new \ImagickPixel('transparent')); + + $content = stream_get_contents($fileview->fopen($path, 'r')); + if(substr($content, 0, 5) !== '<?xml') { + $content = '<?xml version="1.0" encoding="UTF-8" standalone="no"?>' . $content; + } + + $svg->readImageBlob($content); + $svg->setImageFormat('png32'); + } catch (\Exception $e) { + \OC_Log::write('core', $e->getmessage(), \OC_Log::ERROR); + return false; + } + - //new image object - $image = new \OC_Image(); - $image->loadFromData($svg); - //check if image object is valid - return $image->valid() ? $image : false; + //new image object + $image = new \OC_Image(); + $image->loadFromData($svg); + //check if image object is valid + return $image->valid() ? $image : false; + } } - } - - \OC\Preview::registerProvider('OC\Preview\SVG'); + \OC\Preview::registerProvider('OC\Preview\SVG'); + } }
\ No newline at end of file diff --git a/lib/private/preview/unknown.php b/lib/private/preview/unknown.php index 4747f9e25ed..2d3b5c5655e 100644 --- a/lib/private/preview/unknown.php +++ b/lib/private/preview/unknown.php @@ -22,7 +22,7 @@ class Unknown extends Provider { $svgPath = substr_replace($path, 'svg', -3); - if (extension_loaded('imagick') && file_exists($svgPath)) { + if (extension_loaded('imagick') && file_exists($svgPath) && count(@\Imagick::queryFormats("SVG")) === 1) { // http://www.php.net/manual/de/imagick.setresolution.php#85284 $svg = new \Imagick(); diff --git a/lib/private/request.php b/lib/private/request.php index d9d5ae08e28..8041c4f0048 100755 --- a/lib/private/request.php +++ b/lib/private/request.php @@ -11,6 +11,9 @@ class OC_Request { const USER_AGENT_IE = '/MSIE/'; // Android Chrome user agent: https://developers.google.com/chrome/mobile/docs/user-agent const USER_AGENT_ANDROID_MOBILE_CHROME = '#Android.*Chrome/[.0-9]*#'; + const USER_AGENT_FREEBOX = '#^Mozilla/5\.0$#'; + + const REGEX_LOCALHOST = '/^(127\.0\.0\.1|localhost)(:[0-9]+|)$/'; /** * @brief Check overwrite condition @@ -24,39 +27,97 @@ class OC_Request { } /** - * @brief Returns the server host + * @brief Checks whether a domain is considered as trusted from the list + * of trusted domains. If no trusted domains have been configured, returns + * true. + * This is used to prevent Host Header Poisoning. + * @param string $host + * @return bool true if the given domain is trusted or if no trusted domains + * have been configured + */ + public static function isTrustedDomain($domain) { + $trustedList = \OC_Config::getValue('trusted_domains', array()); + if (empty($trustedList)) { + return true; + } + if (preg_match(self::REGEX_LOCALHOST, $domain) === 1) { + return true; + } + return in_array($domain, $trustedList); + } + + /** + * @brief Returns the unverified server host from the headers without checking + * whether it is a trusted domain * @returns string the server host * * Returns the server host, even if the website uses one or more * reverse proxies */ - public static function serverHost() { - if(OC::$CLI) { - return 'localhost'; - } - if(OC_Config::getValue('overwritehost', '') !== '' and self::isOverwriteCondition()) { - return OC_Config::getValue('overwritehost'); - } + public static function insecureServerHost() { + $host = null; if (isset($_SERVER['HTTP_X_FORWARDED_HOST'])) { if (strpos($_SERVER['HTTP_X_FORWARDED_HOST'], ",") !== false) { - $host = trim(array_pop(explode(",", $_SERVER['HTTP_X_FORWARDED_HOST']))); - } - else{ - $host=$_SERVER['HTTP_X_FORWARDED_HOST']; + $parts = explode(',', $_SERVER['HTTP_X_FORWARDED_HOST']); + $host = trim(current($parts)); + } else { + $host = $_SERVER['HTTP_X_FORWARDED_HOST']; } - } - else{ + } else { if (isset($_SERVER['HTTP_HOST'])) { - return $_SERVER['HTTP_HOST']; - } - if (isset($_SERVER['SERVER_NAME'])) { - return $_SERVER['SERVER_NAME']; + $host = $_SERVER['HTTP_HOST']; + } else if (isset($_SERVER['SERVER_NAME'])) { + $host = $_SERVER['SERVER_NAME']; } - return 'localhost'; } return $host; } + /** + * Returns the overwritehost setting from the config if set and + * if the overwrite condition is met + * @return overwritehost value or null if not defined or the defined condition + * isn't met + */ + public static function getOverwriteHost() { + if(OC_Config::getValue('overwritehost', '') !== '' and self::isOverwriteCondition()) { + return OC_Config::getValue('overwritehost'); + } + return null; + } + + /** + * @brief Returns the server host from the headers, or the first configured + * trusted domain if the host isn't in the trusted list + * @returns string the server host + * + * Returns the server host, even if the website uses one or more + * reverse proxies + */ + public static function serverHost() { + if(OC::$CLI) { + return 'localhost'; + } + + // overwritehost is always trusted + $host = self::getOverwriteHost(); + if ($host !== null) { + return $host; + } + + // get the host from the headers + $host = self::insecureServerHost(); + + // Verify that the host is a trusted domain if the trusted domains + // are defined + // If no trusted domain is provided the first trusted domain is returned + if (self::isTrustedDomain($host)) { + return $host; + } else { + $trustedList = \OC_Config::getValue('trusted_domains', array('')); + return $trustedList[0]; + } + } /** * @brief Returns the server protocol @@ -70,14 +131,14 @@ class OC_Request { } if (isset($_SERVER['HTTP_X_FORWARDED_PROTO'])) { $proto = strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']); - }else{ - if(isset($_SERVER['HTTPS']) and !empty($_SERVER['HTTPS']) and ($_SERVER['HTTPS']!='off')) { - $proto = 'https'; - }else{ - $proto = 'http'; - } + // Verify that the protocol is always HTTP or HTTPS + // default to http if an invalid value is provided + return $proto === 'https' ? 'https' : 'http'; + } + if (isset($_SERVER['HTTPS']) && !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') { + return 'https'; } - return $proto; + return 'http'; } /** @@ -86,6 +147,7 @@ class OC_Request { * * Returns the request uri, even if the website uses one or more * reverse proxies + * @return string */ public static function requestUri() { $uri = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : ''; @@ -97,7 +159,7 @@ class OC_Request { /** * @brief Returns the script name - * @returns string the script name + * @return string the script name * * Returns the script name, even if the website uses one or more * reverse proxies @@ -114,7 +176,7 @@ class OC_Request { /** * @brief get Path info from request - * @returns string Path info or false when not found + * @return string Path info or false when not found */ public static function getPathInfo() { if (array_key_exists('PATH_INFO', $_SERVER)) { @@ -138,7 +200,7 @@ class OC_Request { /** * @brief get Path info from request, not urldecoded - * @returns string Path info or false when not found + * @return string Path info or false when not found */ public static function getRawPathInfo() { $requestUri = $_SERVER['REQUEST_URI']; @@ -178,35 +240,8 @@ class OC_Request { } /** - * @brief Check if this is a no-cache request - * @returns boolean true for no-cache - */ - static public function isNoCache() { - if (!isset($_SERVER['HTTP_CACHE_CONTROL'])) { - return false; - } - return $_SERVER['HTTP_CACHE_CONTROL'] == 'no-cache'; - } - - /** - * @brief Check if the requestor understands gzip - * @returns boolean true for gzip encoding supported - */ - static public function acceptGZip() { - if (!isset($_SERVER['HTTP_ACCEPT_ENCODING'])) { - return false; - } - $HTTP_ACCEPT_ENCODING = $_SERVER["HTTP_ACCEPT_ENCODING"]; - if( strpos($HTTP_ACCEPT_ENCODING, 'x-gzip') !== false ) - return 'x-gzip'; - else if( strpos($HTTP_ACCEPT_ENCODING, 'gzip') !== false ) - return 'gzip'; - return false; - } - - /** * @brief Check if the requester sent along an mtime - * @returns false or an mtime + * @return false or an mtime */ static public function hasModificationTime () { if (isset($_SERVER['HTTP_X_OC_MTIME'])) { diff --git a/lib/private/response.php b/lib/private/response.php index 04746437347..983c682bf3f 100644 --- a/lib/private/response.php +++ b/lib/private/response.php @@ -12,10 +12,11 @@ class OC_Response { const STATUS_TEMPORARY_REDIRECT = 307; const STATUS_NOT_FOUND = 404; const STATUS_INTERNAL_SERVER_ERROR = 500; + const STATUS_SERVICE_UNAVAILABLE = 503; /** * @brief Enable response caching by sending correct HTTP headers - * @param $cache_time time to cache the response + * @param integer $cache_time time to cache the response * >0 cache time in seconds * 0 and <0 enable default browser caching * null cache indefinitly @@ -74,13 +75,16 @@ class OC_Response { case self::STATUS_INTERNAL_SERVER_ERROR; $status = $status . ' Internal Server Error'; break; + case self::STATUS_SERVICE_UNAVAILABLE; + $status = $status . ' Service Unavailable'; + break; } header($protocol.' '.$status); } /** * @brief Send redirect response - * @param $location to redirect to + * @param string $location to redirect to */ static public function redirect($location) { self::setStatus(self::STATUS_TEMPORARY_REDIRECT); @@ -153,7 +157,11 @@ class OC_Response { * @param string $type disposition type, either 'attachment' or 'inline' */ static public function setContentDispositionHeader( $filename, $type = 'attachment' ) { - if (OC_Request::isUserAgent(array(OC_Request::USER_AGENT_IE, OC_Request::USER_AGENT_ANDROID_MOBILE_CHROME))) { + if (OC_Request::isUserAgent(array( + OC_Request::USER_AGENT_IE, + OC_Request::USER_AGENT_ANDROID_MOBILE_CHROME, + OC_Request::USER_AGENT_FREEBOX + ))) { header( 'Content-Disposition: ' . rawurlencode($type) . '; filename="' . rawurlencode( $filename ) . '"' ); } else { header( 'Content-Disposition: ' . rawurlencode($type) . '; filename*=UTF-8\'\'' . rawurlencode( $filename ) @@ -163,7 +171,7 @@ class OC_Response { /** * @brief Send file as response, checking and setting caching headers - * @param $filepath of file to send + * @param string $filepath of file to send */ static public function sendFile($filepath) { $fp = fopen($filepath, 'rb'); diff --git a/lib/private/route.php b/lib/private/route/route.php index fb7da456b62..6ade9ec15f6 100644 --- a/lib/private/route.php +++ b/lib/private/route/route.php @@ -6,13 +6,17 @@ * See the COPYING-README file. */ -use Symfony\Component\Routing\Route; +namespace OC\Route; -class OC_Route extends Route { +use OCP\Route\IRoute; +use Symfony\Component\Routing\Route as SymfonyRoute; + +class Route extends SymfonyRoute implements IRoute { /** * Specify the method when this route is to be used * * @param string $method HTTP method (uppercase) + * @return \OC\Route\Route */ public function method($method) { $this->setRequirement('_method', strtoupper($method)); @@ -63,6 +67,7 @@ class OC_Route extends Route { * Defaults to use for this route * * @param array $defaults The defaults + * @return \OC\Route\Route */ public function defaults($defaults) { $action = $this->getDefault('action'); @@ -78,6 +83,7 @@ class OC_Route extends Route { * Requirements for this route * * @param array $requirements The requirements + * @return \OC\Route\Route */ public function requirements($requirements) { $method = $this->getRequirement('_method'); @@ -93,8 +99,10 @@ class OC_Route extends Route { /** * The action to execute when this route matches + * * @param string|callable $class the class or a callable * @param string $function the function to use with the class + * @return \OC\Route\Route * * This function is called with $class set to a callable or * to the class with $function diff --git a/lib/private/router.php b/lib/private/route/router.php index 19c1e4473ec..60ba5878401 100644 --- a/lib/private/router.php +++ b/lib/private/route/router.php @@ -6,68 +6,103 @@ * See the COPYING-README file. */ +namespace OC\Route; + +use OCP\Route\IRouter; use Symfony\Component\Routing\Matcher\UrlMatcher; use Symfony\Component\Routing\Generator\UrlGenerator; use Symfony\Component\Routing\RequestContext; use Symfony\Component\Routing\RouteCollection; -//use Symfony\Component\Routing\Route; -class OC_Router { +class Router implements IRouter { + /** + * @var \Symfony\Component\Routing\RouteCollection[] + */ protected $collections = array(); + + /** + * @var \Symfony\Component\Routing\RouteCollection + */ protected $collection = null; + + /** + * @var \Symfony\Component\Routing\RouteCollection + */ protected $root = null; + /** + * @var \Symfony\Component\Routing\Generator\UrlGenerator + */ protected $generator = null; - protected $routing_files; - protected $cache_key; + + /** + * @var string[] + */ + protected $routingFiles; + + /** + * @var string + */ + protected $cacheKey; + + protected $loaded = false; public function __construct() { - $baseUrl = OC_Helper::linkTo('', 'index.php'); - if ( !OC::$CLI) { + $baseUrl = \OC_Helper::linkTo('', 'index.php'); + if (!\OC::$CLI) { $method = $_SERVER['REQUEST_METHOD']; - }else{ + } else { $method = 'GET'; } - $host = OC_Request::serverHost(); - $schema = OC_Request::serverProtocol(); + $host = \OC_Request::serverHost(); + $schema = \OC_Request::serverProtocol(); $this->context = new RequestContext($baseUrl, $method, $host, $schema); // TODO cache $this->root = $this->getCollection('root'); } + /** + * Get the files to load the routes from + * + * @return string[] + */ public function getRoutingFiles() { - if (!isset($this->routing_files)) { - $this->routing_files = array(); - foreach(OC_APP::getEnabledApps() as $app) { - $file = OC_App::getAppPath($app).'/appinfo/routes.php'; - if(file_exists($file)) { - $this->routing_files[$app] = $file; + if (!isset($this->routingFiles)) { + $this->routingFiles = array(); + foreach (\OC_APP::getEnabledApps() as $app) { + $file = \OC_App::getAppPath($app) . '/appinfo/routes.php'; + if (file_exists($file)) { + $this->routingFiles[$app] = $file; } } } - return $this->routing_files; + return $this->routingFiles; } public function getCacheKey() { - if (!isset($this->cache_key)) { + if (!isset($this->cacheKey)) { $files = $this->getRoutingFiles(); $files[] = 'settings/routes.php'; $files[] = 'core/routes.php'; $files[] = 'ocs/routes.php'; - $this->cache_key = OC_Cache::generateCacheKeyFromFiles($files); + $this->cacheKey = \OC_Cache::generateCacheKeyFromFiles($files); } - return $this->cache_key; + return $this->cacheKey; } /** * loads the api routes */ public function loadRoutes() { - foreach($this->getRoutingFiles() as $app => $file) { + if ($this->loaded) { + return; + } + $this->loaded = true; + foreach ($this->getRoutingFiles() as $app => $file) { $this->useCollection($app); require_once $file; $collection = $this->getCollection($app); - $collection->addPrefix('/apps/'.$app); + $collection->addPrefix('/apps/' . $app); $this->root->addCollection($collection); } $this->useCollection('root'); @@ -81,6 +116,10 @@ class OC_Router { $this->root->addCollection($collection); } + /** + * @param string $name + * @return \Symfony\Component\Routing\RouteCollection + */ protected function getCollection($name) { if (!isset($this->collections[$name])) { $this->collections[$name] = new RouteCollection(); @@ -91,22 +130,23 @@ class OC_Router { /** * Sets the collection to use for adding routes * - * @param string $name Name of the colletion to use. + * @param string $name Name of the collection to use. */ public function useCollection($name) { $this->collection = $this->getCollection($name); } /** - * Create a OC_Route. + * Create a \OC\Route\Route. * * @param string $name Name of the route to create. * @param string $pattern The pattern to match - * @param array $defaults An array of default parameter values - * @param array $requirements An array of requirements for parameters (regexes) + * @param array $defaults An array of default parameter values + * @param array $requirements An array of requirements for parameters (regexes) + * @return \OC\Route\Route */ public function create($name, $pattern, array $defaults = array(), array $requirements = array()) { - $route = new OC_Route($pattern, $defaults, $requirements); + $route = new Route($pattern, $defaults, $requirements); $this->collection->add($name, $route); return $route; } @@ -115,6 +155,7 @@ class OC_Router { * Find the route matching $url. * * @param string $url The url to find + * @throws \Exception */ public function match($url) { $matcher = new UrlMatcher($this->root, $this->context); @@ -123,14 +164,14 @@ class OC_Router { $action = $parameters['action']; if (!is_callable($action)) { var_dump($action); - throw new Exception('not a callable action'); + throw new \Exception('not a callable action'); } unset($parameters['action']); call_user_func($action, $parameters); } elseif (isset($parameters['file'])) { include $parameters['file']; } else { - throw new Exception('no action available'); + throw new \Exception('no action available'); } } @@ -138,8 +179,7 @@ class OC_Router { * Get the url generator * */ - public function getGenerator() - { + public function getGenerator() { if (null !== $this->generator) { return $this->generator; } @@ -152,34 +192,11 @@ class OC_Router { * * @param string $name Name of the route to use. * @param array $parameters Parameters for the route + * @param bool $absolute + * @return string */ - public function generate($name, $parameters = array(), $absolute = false) - { + public function generate($name, $parameters = array(), $absolute = false) { return $this->getGenerator()->generate($name, $parameters, $absolute); } - /** - * Generate JSON response for routing in javascript - */ - public static function JSRoutes() - { - $router = OC::getRouter(); - - $etag = $router->getCacheKey(); - OC_Response::enableCaching(); - OC_Response::setETagHeader($etag); - - $root = $router->getCollection('root'); - $routes = array(); - foreach($root->all() as $name => $route) { - $compiled_route = $route->compile(); - $defaults = $route->getDefaults(); - unset($defaults['action']); - $routes[$name] = array( - 'tokens' => $compiled_route->getTokens(), - 'defaults' => $defaults, - ); - } - OCP\JSON::success ( array( 'data' => $routes ) ); - } } diff --git a/lib/private/search.php b/lib/private/search.php index b9c75dfc333..70d670e048e 100644 --- a/lib/private/search.php +++ b/lib/private/search.php @@ -38,7 +38,6 @@ class OC_Search{ /** * register a new search provider to be used - * @param string $provider class name of a OC_Search_Provider */ public static function registerProvider($class, $options=array()) { self::$registeredProviders[]=array('class'=>$class, 'options'=>$options); diff --git a/lib/private/search/result.php b/lib/private/search/result.php index 42275c2df11..ceefeab2dae 100644 --- a/lib/private/search/result.php +++ b/lib/private/search/result.php @@ -15,6 +15,7 @@ class OC_Search_Result{ * @param string $text some more information about the result * @param string $link link for the result * @param string $type the type of result as human readable string ('File', 'Music', etc) + * @param string $container */ public function __construct($name, $text, $link, $type, $container) { $this->name=$name; diff --git a/lib/private/server.php b/lib/private/server.php index c9e593ec2ed..8c9ea39c562 100644 --- a/lib/private/server.php +++ b/lib/private/server.php @@ -124,6 +124,9 @@ class Server extends SimpleContainer implements IServerContainer { $this->registerService('AllConfig', function($c) { return new \OC\AllConfig(); }); + $this->registerService('AppConfig', function ($c) { + return new \OC\AppConfig(\OC_DB::getConnection()); + }); $this->registerService('L10NFactory', function($c) { return new \OC\L10N\Factory(); }); @@ -148,6 +151,17 @@ class Server extends SimpleContainer implements IServerContainer { $this->registerService('AvatarManager', function($c) { return new AvatarManager(); }); + $this->registerService('JobList', function ($c) { + /** + * @var Server $c + */ + $config = $c->getConfig(); + return new \OC\BackgroundJob\JobList($c->getDatabaseConnection(), $config); + }); + $this->registerService('Router', function ($c){ + $router = new \OC\Route\Router(); + return $router; + }); } /** @@ -270,6 +284,15 @@ class Server extends SimpleContainer implements IServerContainer { } /** + * Returns the app config manager + * + * @return \OCP\IAppConfig + */ + function getAppConfig(){ + return $this->query('AppConfig'); + } + + /** * get an L10N instance * @param $app string appid * @return \OC_L10N @@ -336,4 +359,24 @@ class Server extends SimpleContainer implements IServerContainer { function getActivityManager() { return $this->query('ActivityManager'); } + + /** + * Returns an job list for controlling background jobs + * + * @return \OCP\BackgroundJob\IJobList + */ + function getJobList(){ + return $this->query('JobList'); + } + + /** + * Returns a router for generating and matching urls + * + * @return \OCP\Route\IRouter + */ + function getRouter(){ + $router = $this->query('Router'); + $router->loadRoutes(); + return $router; + } } diff --git a/lib/private/session/internal.php b/lib/private/session/internal.php index a7c9e2fdefd..42ec9606dc9 100644 --- a/lib/private/session/internal.php +++ b/lib/private/session/internal.php @@ -26,8 +26,7 @@ class Internal extends Memory { } public function __destruct() { - $_SESSION = array_merge($_SESSION, $this->data); - session_write_close(); + $this->close(); } /** @@ -47,4 +46,15 @@ class Internal extends Memory { @session_start(); $this->data = $_SESSION = array(); } + + public function close() { + $_SESSION = array_merge($_SESSION, $this->data); + session_write_close(); + + parent::close(); + } + + public function reopen() { + throw new \Exception('The session cannot be reopened - reopen() is ony to be used in unit testing.'); + } } diff --git a/lib/private/session/memory.php b/lib/private/session/memory.php index 134cee582ed..1497c0f8928 100644 --- a/lib/private/session/memory.php +++ b/lib/private/session/memory.php @@ -25,9 +25,10 @@ class Memory extends Session { /** * @param string $key - * @param mixed $value + * @param integer $value */ public function set($key, $value) { + $this->validateSession(); $this->data[$key] = $value; } @@ -54,10 +55,29 @@ class Memory extends Session { * @param string $key */ public function remove($key) { + $this->validateSession(); unset($this->data[$key]); } public function clear() { $this->data = array(); } + + /** + * Helper function for PHPUnit execution - don't use in non-test code + */ + public function reopen() { + $this->sessionClosed = false; + } + + /** + * In case the session has already been locked an exception will be thrown + * + * @throws \Exception + */ + private function validateSession() { + if ($this->sessionClosed) { + throw new \Exception('Session has been closed - no further changes to the session as allowed'); + } + } } diff --git a/lib/private/session/session.php b/lib/private/session/session.php index fe160faa267..6f6c804f384 100644 --- a/lib/private/session/session.php +++ b/lib/private/session/session.php @@ -13,6 +13,11 @@ use OCP\ISession; abstract class Session implements \ArrayAccess, ISession { /** + * @var bool + */ + protected $sessionClosed = false; + + /** * $name serves as a namespace for the session keys * * @param string $name @@ -49,4 +54,11 @@ abstract class Session implements \ArrayAccess, ISession { public function offsetUnset($offset) { $this->remove($offset); } + + /** + * Close the session and release the lock + */ + public function close() { + $this->sessionClosed = true; + } } diff --git a/lib/private/setup.php b/lib/private/setup.php index 5232398d1d7..b1061b3a25b 100644 --- a/lib/private/setup.php +++ b/lib/private/setup.php @@ -65,6 +65,7 @@ class OC_Setup { OC_Config::setValue('passwordsalt', $salt); //write the config file + OC_Config::setValue('trusted_domains', array(OC_Request::serverHost())); OC_Config::setValue('datadirectory', $datadir); OC_Config::setValue('dbtype', $dbtype); OC_Config::setValue('version', implode('.', OC_Util::getVersion())); @@ -94,10 +95,9 @@ class OC_Setup { } if(count($error) == 0) { - OC_Appconfig::setValue('core', 'installedat', microtime(true)); - OC_Appconfig::setValue('core', 'lastupdatedat', microtime(true)); - OC_AppConfig::setValue('core', 'remote_core.css', '/core/minimizer.php'); - OC_AppConfig::setValue('core', 'remote_core.js', '/core/minimizer.php'); + $appConfig = \OC::$server->getAppConfig(); + $appConfig->setValue('core', 'installedat', microtime(true)); + $appConfig->setValue('core', 'lastupdatedat', microtime(true)); OC_Group::createGroup('admin'); OC_Group::addToGroup($username, 'admin'); @@ -106,6 +106,10 @@ class OC_Setup { //guess what this does OC_Installer::installShippedApps(); + // create empty file in data dir, so we can later find + // out that this is indeed an ownCloud data directory + file_put_contents(OC_Config::getValue('datadirectory', OC::$SERVERROOT.'/data').'/.ocdata', ''); + //create htaccess files for apache hosts if (isset($_SERVER['SERVER_SOFTWARE']) && strstr($_SERVER['SERVER_SOFTWARE'], 'Apache')) { self::createHtaccess(); @@ -147,7 +151,7 @@ class OC_Setup { $content.= "RewriteRule ^.well-known/host-meta /public.php?service=host-meta [QSA,L]\n"; $content.= "RewriteRule ^.well-known/carddav /remote.php/carddav/ [R]\n"; $content.= "RewriteRule ^.well-known/caldav /remote.php/caldav/ [R]\n"; - $content.= "RewriteRule ^apps/([^/]*)/(.*\.(css|php))$ index.php?app=$1&getfile=$2 [QSA,L]\n"; + $content.= "RewriteRule ^apps/([^/]*)/(.*\.(php))$ index.php?app=$1&getfile=$2 [QSA,L]\n"; $content.= "RewriteRule ^remote/(.*) remote.php [QSA,L]\n"; $content.= "</IfModule>\n"; $content.= "<IfModule mod_mime.c>\n"; diff --git a/lib/private/setup/mysql.php b/lib/private/setup/mysql.php index d97b6d2602f..b2c28173b1c 100644 --- a/lib/private/setup/mysql.php +++ b/lib/private/setup/mysql.php @@ -3,13 +3,13 @@ namespace OC\Setup; class MySQL extends AbstractDatabase { - public $dbprettyname = 'MySQL'; + public $dbprettyname = 'MySQL/MariaDB'; public function setupDatabase($username) { //check if the database user has admin right $connection = @mysql_connect($this->dbhost, $this->dbuser, $this->dbpassword); if(!$connection) { - throw new \DatabaseSetupException($this->trans->t('MySQL username and/or password not valid'), + throw new \DatabaseSetupException($this->trans->t('MySQL/MariaDB username and/or password not valid'), $this->trans->t('You need to enter either an existing account or the administrator.')); } $oldUser=\OC_Config::getValue('dbuser', false); @@ -82,14 +82,14 @@ class MySQL extends AbstractDatabase { $query = "CREATE USER '$name'@'localhost' IDENTIFIED BY '$password'"; $result = mysql_query($query, $connection); if (!$result) { - throw new \DatabaseSetupException($this->trans->t("MySQL user '%s'@'localhost' exists already.", array($name)), - $this->trans->t("Drop this user from MySQL", array($name))); + throw new \DatabaseSetupException($this->trans->t("MySQL/MariaDB user '%s'@'localhost' exists already.", array($name)), + $this->trans->t("Drop this user from MySQL/MariaDB", array($name))); } $query = "CREATE USER '$name'@'%' IDENTIFIED BY '$password'"; $result = mysql_query($query, $connection); if (!$result) { - throw new \DatabaseSetupException($this->trans->t("MySQL user '%s'@'%%' already exists", array($name)), - $this->trans->t("Drop this user from MySQL.")); + throw new \DatabaseSetupException($this->trans->t("MySQL/MariaDB user '%s'@'%%' already exists", array($name)), + $this->trans->t("Drop this user from MySQL/MariaDB.")); } } } diff --git a/lib/private/setup/postgresql.php b/lib/private/setup/postgresql.php index 89d328ada19..4d0c9b52a4d 100644 --- a/lib/private/setup/postgresql.php +++ b/lib/private/setup/postgresql.php @@ -10,13 +10,20 @@ class PostgreSQL extends AbstractDatabase { $e_user = addslashes($this->dbuser); $e_password = addslashes($this->dbpassword); + // Fix database with port connection + if(strpos($e_host, ':')) { + list($e_host, $port)=explode(':', $e_host, 2); + } else { + $port=false; + } + //check if the database user has admin rights - $connection_string = "host='$e_host' dbname=postgres user='$e_user' password='$e_password'"; + $connection_string = "host='$e_host' dbname=postgres user='$e_user' port='$port' password='$e_password'"; $connection = @pg_connect($connection_string); if(!$connection) { // Try if we can connect to the DB with the specified name $e_dbname = addslashes($this->dbname); - $connection_string = "host='$e_host' dbname='$e_dbname' user='$e_user' password='$e_password'"; + $connection_string = "host='$e_host' dbname='$e_dbname' user='$e_user' port='$port' password='$e_password'"; $connection = @pg_connect($connection_string); if(!$connection) @@ -63,7 +70,14 @@ class PostgreSQL extends AbstractDatabase { $e_user = addslashes($this->dbuser); $e_password = addslashes($this->dbpassword); - $connection_string = "host='$e_host' dbname='$e_dbname' user='$e_user' password='$e_password'"; + // Fix database with port connection + if(strpos($e_host, ':')) { + list($e_host, $port)=explode(':', $e_host, 2); + } else { + $port=false; + } + + $connection_string = "host='$e_host' dbname='$e_dbname' user='$e_user' port='$port' password='$e_password'"; $connection = @pg_connect($connection_string); if(!$connection) { throw new \DatabaseSetupException($this->trans->t('PostgreSQL username and/or password not valid'), diff --git a/lib/private/share/mailnotifications.php b/lib/private/share/mailnotifications.php new file mode 100644 index 00000000000..45734818731 --- /dev/null +++ b/lib/private/share/mailnotifications.php @@ -0,0 +1,163 @@ +<?php +/** +* ownCloud +* +* @author Bjoern Schiessle +* @copyright 2014 Bjoern Schiessle <schiessle@owncloud.com> +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE +* License as published by the Free Software Foundation; either +* version 3 of the License, or any later version. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU AFFERO GENERAL PUBLIC LICENSE for more details. +* +* You should have received a copy of the GNU Affero General Public +* License along with this library. If not, see <http://www.gnu.org/licenses/>. +*/ + +namespace OC\Share; + +class MailNotifications { + + private $senderId; // sender userId + private $from; // sender email address + private $senderDisplayName; + private $l; + + /** + * + * @param string $recipient user id + * @param string $sender user id (if nothing is set we use the currently logged-in user) + */ + public function __construct($sender = null) { + $this->l = \OC_L10N::get('core'); + + $this->senderId = $sender; + + $this->from = \OCP\Util::getDefaultEmailAddress('sharing-noreply'); + if ($this->senderId) { + $this->from = \OCP\Config::getUserValue($this->senderId, 'settings', 'email', $this->from); + $this->senderDisplayName = \OCP\User::getDisplayName($this->senderId); + } else { + $this->senderDisplayName = \OCP\User::getDisplayName(); + } + } + + /** + * @brief inform users if a file was shared with them + * + * @param array $recipientList list of recipients + * @param type $itemSource shared item source + * @param type $itemType shared item type + * @return array list of user to whom the mail send operation failed + */ + public function sendInternalShareMail($recipientList, $itemSource, $itemType) { + + $noMail = array(); + + foreach ($recipientList as $recipient) { + $recipientDisplayName = \OCP\User::getDisplayName($recipient); + $to = \OC_Preferences::getValue($recipient, 'settings', 'email', ''); + + if ($to === '') { + $noMail[] = $recipientDisplayName; + continue; + } + + $items = \OCP\Share::getItemSharedWithUser($itemType, $itemSource, $recipient); + $filename = trim($items[0]['file_target'], '/'); + $subject = (string) $this->l->t('%s shared »%s« with you', array($this->senderDisplayName, $filename)); + $expiration = null; + if (isset($items[0]['expiration'])) { + try { + $date = new DateTime($items[0]['expiration']); + $expiration = $date->getTimestamp(); + } catch (\Exception $e) { + \OCP\Util::writeLog('sharing', "Couldn't read date: " . $e->getMessage(), \OCP\Util::ERROR); + } + } + + if ($itemType === 'folder') { + $foldername = "/Shared/" . $filename; + } else { + // if it is a file we can just link to the Shared folder, + // that's the place where the user will find the file + $foldername = "/Shared"; + } + + $link = \OCP\Util::linkToAbsolute('files', 'index.php', array("dir" => $foldername)); + + list($htmlMail, $alttextMail) = $this->createMailBody($filename, $link, $expiration); + + // send it out now + try { + \OCP\Util::sendMail($to, $recipientDisplayName, $subject, $htmlMail, $this->from, $this->senderDisplayName, 1, $alttextMail); + } catch (\Exception $e) { + \OCP\Util::writeLog('sharing', "Can't send mail to inform the user about an internal share: " . $e->getMessage() , \OCP\Util::ERROR); + $noMail[] = $recipientDisplayName; + } + } + + return $noMail; + + } + + /** + * @brief inform recipient about public link share + * + * @param string $recipient recipient email address + * @param string $filename the shared file + * @param string $link the public link + * @param int $expiration expiration date (timestamp) + * @return array $result of failed recipients + */ + public function sendLinkShareMail($recipient, $filename, $link, $expiration) { + $subject = (string)$this->l->t('%s shared »%s« with you', array($this->senderDisplayName, $filename)); + list($htmlMail, $alttextMail) = $this->createMailBody($filename, $link, $expiration); + $rs = explode(' ', $recipient); + $failed = array(); + foreach ($rs as $r) { + try { + \OCP\Util::sendMail($r, $r, $subject, $htmlMail, $this->from, $this->senderDisplayName, 1, $alttextMail); + } catch (\Exception $e) { + \OCP\Util::writeLog('sharing', "Can't send mail with public link to $r: " . $e->getMessage(), \OCP\Util::ERROR); + $failed[] = $r; + } + } + return $failed; + } + + /** + * @brief create mail body for plain text and html mail + * + * @param string $filename the shared file + * @param string $link link to the shared file + * @param int $expiration expiration date (timestamp) + * @return array with the html mail body and the plain text mail body + */ + private function createMailBody($filename, $link, $expiration) { + + $formatedDate = $expiration ? $this->l->l('date', $expiration) : null; + + $html = new \OC_Template("core", "mail", ""); + $html->assign ('link', $link); + $html->assign ('user_displayname', $this->senderDisplayName); + $html->assign ('filename', $filename); + $html->assign('expiration', $formatedDate); + $htmlMail = $html->fetchPage(); + + $alttext = new \OC_Template("core", "altmail", ""); + $alttext->assign ('link', $link); + $alttext->assign ('user_displayname', $this->senderDisplayName); + $alttext->assign ('filename', $filename); + $alttext->assign('expiration', $formatedDate); + $alttextMail = $alttext->fetchPage(); + + return array($htmlMail, $alttextMail); + } + +} diff --git a/lib/private/share/searchresultsorter.php b/lib/private/share/searchresultsorter.php new file mode 100644 index 00000000000..76abbf30846 --- /dev/null +++ b/lib/private/share/searchresultsorter.php @@ -0,0 +1,59 @@ +<?php +/** + * Copyright (c) 2014 Arthur Schiwon <blizzz@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + * + */ +namespace OC\Share; + +class SearchResultSorter { + private $search; + private $encoding; + private $key; + private $log; + + /** + * @param string $search the search term as was given by the user + * @param string $key the array key containing the value that should be compared + * against + * @param $encoding optional, encoding to use, defaults to UTF-8 + * @param $log optional, an \OC\Log instance + */ + public function __construct($search, $key, \OC\Log $log = null, $encoding = 'UTF-8') { + $this->encoding = $encoding; + $this->key = $key; + $this->log = $log; + $this->search = mb_strtolower($search, $this->encoding); + } + + /** + * User and Group names matching the search term at the beginning shall appear + * on top of the share dialog. Following entries in alphabetical order. + * Callback function for usort. http://php.net/usort + */ + public function sort($a, $b) { + if(!isset($a[$this->key]) || !isset($b[$this->key])) { + if(!is_null($this->log)) { + $this->log->error('Sharing dialogue: cannot sort due to ' . + 'missing array key', array('app' => 'core')); + } + return 0; + } + $nameA = mb_strtolower($a[$this->key], $this->encoding); + $nameB = mb_strtolower($b[$this->key], $this->encoding); + $i = mb_strpos($nameA, $this->search, 0, $this->encoding); + $j = mb_strpos($nameB, $this->search, 0, $this->encoding); + + if($i === $j || $i > 0 && $j > 0) { + return strcmp(mb_strtolower($nameA, $this->encoding), + mb_strtolower($nameB, $this->encoding)); + } elseif ($i === 0) { + return -1; + } else { + return 1; + } + } +} + diff --git a/lib/private/tags.php b/lib/private/tags.php index fe7de1073a0..06550068f76 100644 --- a/lib/private/tags.php +++ b/lib/private/tags.php @@ -73,6 +73,7 @@ class Tags implements \OCP\ITags { * Constructor. * * @param string $user The user whos data the object will operate on. + * @param string $type */ public function __construct($user, $type, $defaultTags = array()) { $this->user = $user; @@ -83,8 +84,6 @@ class Tags implements \OCP\ITags { /** * Load tags from db. * - * @param string $type The type identifier e.g. 'contact' or 'event'. - * @param array $defaultTags An array of default tags to be used if none are stored. */ protected function loadTags($defaultTags=array()) { $this->tags = array(); @@ -176,7 +175,7 @@ class Tags implements \OCP\ITags { * * Throws an exception if the tag could not be found. * - * @param string|integer $tag Tag id or name. + * @param string $tag Tag id or name. * @return array An array of object ids or false on error. */ public function getIdsForTag($tag) { @@ -235,7 +234,7 @@ class Tags implements \OCP\ITags { * Add a new tag. * * @param string $name A string with a name of the tag - * @return int the id of the added tag or false if it already exists. + * @return false|string the id of the added tag or false if it already exists. */ public function add($name) { $name = trim($name); @@ -512,7 +511,7 @@ class Tags implements \OCP\ITags { * Creates a tag/object relation. * * @param int $objid The id of the object - * @param int|string $tag The id or name of the tag + * @param string $tag The id or name of the tag * @return boolean Returns false on database error. */ public function tagAs($objid, $tag) { @@ -544,7 +543,7 @@ class Tags implements \OCP\ITags { * Delete single tag/object relation from the db * * @param int $objid The id of the object - * @param int|string $tag The id or name of the tag + * @param string $tag The id or name of the tag * @return boolean */ public function unTag($objid, $tag) { diff --git a/lib/private/template.php b/lib/private/template.php index b2c3a20f281..c6851c6cc8d 100644 --- a/lib/private/template.php +++ b/lib/private/template.php @@ -156,6 +156,9 @@ class OC_Template extends \OC\Template\Base { * * Will select the template file for the selected theme and formfactor. * Checking all the possible locations. + * @param string $theme + * @param string $app + * @param string $fext */ protected function findTemplate($theme, $app, $name, $fext) { // Check if it is a app template or not. @@ -182,7 +185,7 @@ class OC_Template extends \OC\Template\Base { /** * @brief Process the template - * @return bool + * @return boolean|string * * This function process the template. If $this->renderas is set, it * will produce a full page. @@ -223,7 +226,7 @@ class OC_Template extends \OC\Template\Base { * @param string $application The application we render the template for * @param string $name Name of the template * @param array $parameters Parameters for the template - * @return bool + * @return boolean|null */ public static function printUserPage( $application, $name, $parameters = array() ) { $content = new OC_Template( $application, $name, "user" ); diff --git a/lib/private/template/base.php b/lib/private/template/base.php index 88941bc7132..7aa0cb4a956 100644 --- a/lib/private/template/base.php +++ b/lib/private/template/base.php @@ -14,6 +14,11 @@ class Base { private $l10n; // The l10n-Object private $theme; // theme defaults + /** + * @param string $template + * @param \OC_L10N $l10n + * @param \OC_Defaults $theme + */ public function __construct( $template, $requesttoken, $l10n, $theme ) { $this->vars = array(); $this->vars['requesttoken'] = $requesttoken; @@ -22,6 +27,12 @@ class Base { $this->theme = $theme; } + /** + * @param string $serverroot + * @param string|false $app_dir + * @param string $theme + * @param string $app + */ protected function getAppTemplateDirs($theme, $app, $serverroot, $app_dir) { // Check if the app is in the app folder or in the root if( file_exists($app_dir.'/templates/' )) { @@ -36,6 +47,10 @@ class Base { ); } + /** + * @param string $serverroot + * @param string $theme + */ protected function getCoreTemplateDirs($theme, $serverroot) { return array( $serverroot.'/themes/'.$theme.'/core/templates/', @@ -46,7 +61,7 @@ class Base { /** * @brief Assign variables * @param string $key key - * @param string $value value + * @param array|bool|integer|string $value value * @return bool * * This function assigns a variable. It can be accessed via $_[$key] in @@ -63,7 +78,7 @@ class Base { * @brief Appends a variable * @param string $key key * @param string $value value - * @return bool + * @return boolean|null * * This function assigns a variable in an array context. If the key already * exists, the value will be appended. It can be accessed via @@ -97,7 +112,7 @@ class Base { /** * @brief Process the template - * @return bool + * @return string * * This function processes the template. */ @@ -107,6 +122,7 @@ class Base { /** * @brief doing the actual work + * @param string $file * @return string content * * Includes the template file, fetches its output diff --git a/lib/private/template/cssresourcelocator.php b/lib/private/template/cssresourcelocator.php index 8e7831ca549..e26daa25827 100644 --- a/lib/private/template/cssresourcelocator.php +++ b/lib/private/template/cssresourcelocator.php @@ -22,7 +22,7 @@ class CSSResourceLocator extends ResourceLocator { $app = substr($style, 0, strpos($style, '/')); $style = substr($style, strpos($style, '/')+1); $app_path = \OC_App::getAppPath($app); - $app_url = $this->webroot . '/index.php/apps/' . $app; + $app_url = \OC_App::getAppWebPath($app); if ($this->appendIfExist($app_path, $style.$this->form_factor.'.css', $app_url) || $this->appendIfExist($app_path, $style.'.css', $app_url) ) { diff --git a/lib/private/template/functions.php b/lib/private/template/functions.php index ce42633b364..a72d41f72da 100644 --- a/lib/private/template/functions.php +++ b/lib/private/template/functions.php @@ -78,6 +78,9 @@ function preview_icon( $path ) { return OC_Helper::previewIcon( $path ); } +/** + * @param string $path + */ function publicPreview_icon ( $path, $token ) { return OC_Helper::publicPreviewIcon( $path, $token ); } @@ -110,7 +113,7 @@ function strip_time($timestamp){ * @param int $timestamp timestamp to format * @param int $fromTime timestamp to compare from, defaults to current time * @param bool $dateOnly whether to strip time information - * @return formatted timestamp + * @return OC_L10N_String timestamp */ function relative_modified_date($timestamp, $fromTime = null, $dateOnly = false) { $l=OC_L10N::get('lib'); diff --git a/lib/private/template/resourcelocator.php b/lib/private/template/resourcelocator.php index 9f83673664d..8a3dd5e7fa9 100644 --- a/lib/private/template/resourcelocator.php +++ b/lib/private/template/resourcelocator.php @@ -19,6 +19,10 @@ abstract class ResourceLocator { protected $resources = array(); + /** + * @param string $theme + * @param string $form_factor + */ public function __construct( $theme, $form_factor, $core_map, $party_map ) { $this->theme = $theme; $this->form_factor = $form_factor; @@ -53,6 +57,10 @@ abstract class ResourceLocator { * @param $file the filename * @param $web base for path, default map $root to $webroot */ + /** + * @param string $file + * @param string|false $webroot + */ protected function appendIfExist($root, $file, $webroot = null) { if (is_file($root.'/'.$file)) { if (!$webroot) { diff --git a/lib/private/template/templatefilelocator.php b/lib/private/template/templatefilelocator.php index d5a484b1a14..4676fceb37d 100644 --- a/lib/private/template/templatefilelocator.php +++ b/lib/private/template/templatefilelocator.php @@ -13,11 +13,18 @@ class TemplateFileLocator { protected $dirs; private $path; + /** + * @param string[] $dirs + * @param string $form_factor + */ public function __construct( $form_factor, $dirs ) { $this->form_factor = $form_factor; $this->dirs = $dirs; } + /** + * @param string $template + */ public function find( $template ) { if ($template === '') { throw new \InvalidArgumentException('Empty template name'); diff --git a/lib/private/templatelayout.php b/lib/private/templatelayout.php index d5cd5039753..af17adb11c6 100644 --- a/lib/private/templatelayout.php +++ b/lib/private/templatelayout.php @@ -1,4 +1,11 @@ <?php +use Assetic\Asset\AssetCollection; +use Assetic\Asset\FileAsset; +use Assetic\Asset\GlobAsset; +use Assetic\AssetManager; +use Assetic\AssetWriter; +use Assetic\Filter\CssRewriteFilter; + /** * Copyright (c) 2012 Bart Visscher <bartv@thisnet.nl> * This file is licensed under the Affero General Public License version 3 or @@ -7,6 +14,10 @@ */ class OC_TemplateLayout extends OC_Template { + + /** + * @param string $renderas + */ public function __construct( $renderas ) { // Decide which page we show @@ -53,35 +64,38 @@ class OC_TemplateLayout extends OC_Template { } else { parent::__construct('core', 'layout.base'); } + $versionParameter = '?v=' . md5(implode(OC_Util::getVersion())); - // Add the js files - $jsfiles = self::findJavascriptFiles(OC_Util::$scripts); - $this->assign('jsfiles', array(), false); - if (OC_Config::getValue('installed', false) && $renderas!='error') { + $useAssetPipeline = OC_Config::getValue('asset-pipeline.enabled', false); + if ($useAssetPipeline) { + $this->append( 'jsfiles', OC_Helper::linkToRoute('js_config') . $versionParameter); - } - if (!empty(OC_Util::$coreScripts)) { - $this->append( 'jsfiles', OC_Helper::linkToRemoteBase('core.js', false) . $versionParameter); - } - foreach($jsfiles as $info) { - $root = $info[0]; - $web = $info[1]; - $file = $info[2]; - $this->append( 'jsfiles', $web.'/'.$file . $versionParameter); - } - // Add the css files - $cssfiles = self::findStylesheetFiles(OC_Util::$styles); - $this->assign('cssfiles', array()); - if (!empty(OC_Util::$coreStyles)) { - $this->append( 'cssfiles', OC_Helper::linkToRemoteBase('core.css', false) . $versionParameter); - } - foreach($cssfiles as $info) { - $root = $info[0]; - $web = $info[1]; - $file = $info[2]; + $this->generateAssets(); + + } else { + + // Add the js files + $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') . $versionParameter); + } + foreach($jsfiles as $info) { + $web = $info[1]; + $file = $info[2]; + $this->append( 'jsfiles', $web.'/'.$file . $versionParameter); + } + + // Add the css files + $cssfiles = self::findStylesheetFiles(OC_Util::$styles); + $this->assign('cssfiles', array()); + foreach($cssfiles as $info) { + $web = $info[1]; + $file = $info[2]; - $this->append( 'cssfiles', $web.'/'.$file . $versionParameter); + $this->append( 'cssfiles', $web.'/'.$file . $versionParameter); + } } } @@ -112,4 +126,57 @@ class OC_TemplateLayout extends OC_Template { $locator->find($scripts); return $locator->getResources(); } + + public function generateAssets() + { + $jsFiles = self::findJavascriptFiles(OC_Util::$scripts); + $jsHash = self::hashScriptNames($jsFiles); + + if (!file_exists("assets/$jsHash.js")) { + $jsFiles = array_map(function ($item) { + $root = $item[0]; + $file = $item[2]; + return new FileAsset($root . '/' . $file, array(), $root, $file); + }, $jsFiles); + $jsCollection = new AssetCollection($jsFiles); + $jsCollection->setTargetPath("assets/$jsHash.js"); + + $writer = new AssetWriter(\OC::$SERVERROOT); + $writer->writeAsset($jsCollection); + } + + $cssFiles = self::findStylesheetFiles(OC_Util::$styles); + $cssHash = self::hashScriptNames($cssFiles); + + if (!file_exists("assets/$cssHash.css")) { + $cssFiles = array_map(function ($item) { + $root = $item[0]; + $file = $item[2]; + $assetPath = $root . '/' . $file; + $sourceRoot = \OC::$SERVERROOT; + $sourcePath = substr($assetPath, strlen(\OC::$SERVERROOT)); + return new FileAsset($assetPath, array(new CssRewriteFilter()), $sourceRoot, $sourcePath); + }, $cssFiles); + $cssCollection = new AssetCollection($cssFiles); + $cssCollection->setTargetPath("assets/$cssHash.css"); + + $writer = new AssetWriter(\OC::$SERVERROOT); + $writer->writeAsset($cssCollection); + } + + $this->append('jsfiles', OC_Helper::linkTo('assets', "$jsHash.js")); + $this->append('cssfiles', OC_Helper::linkTo('assets', "$cssHash.css")); + } + + private static function hashScriptNames($files) + { + $files = array_map(function ($item) { + $root = $item[0]; + $file = $item[2]; + return $root . '/' . $file; + }, $files); + + sort($files); + return hash('md5', implode('', $files)); + } } diff --git a/lib/private/updater.php b/lib/private/updater.php index 764a0f14120..9f57aa0b6a0 100644 --- a/lib/private/updater.php +++ b/lib/private/updater.php @@ -16,9 +16,6 @@ use OC\Hooks\BasicEmitter; * - maintenanceStart() * - maintenanceEnd() * - dbUpgrade() - * - filecacheStart() - * - filecacheProgress(int $percentage) - * - filecacheDone() * - failure(string $message) */ class Updater extends BasicEmitter { @@ -76,7 +73,9 @@ class Updater extends BasicEmitter { if ($xml == false) { return array(); } + $loadEntities = libxml_disable_entity_loader(true); $data = @simplexml_load_string($xml); + libxml_disable_entity_loader($loadEntities); $tmp = array(); $tmp['version'] = $data->version; @@ -102,13 +101,29 @@ class Updater extends BasicEmitter { $this->log->debug('starting upgrade from ' . $installedVersion . ' to ' . $currentVersion, array('app' => 'core')); } $this->emit('\OC\Updater', 'maintenanceStart'); + + // create empty file in data dir, so we can later find + // out that this is indeed an ownCloud data directory + // (in case it didn't exist before) + file_put_contents(\OC_Config::getValue('datadirectory', \OC::$SERVERROOT.'/data').'/.ocdata', ''); + + /* + * START CONFIG CHANGES FOR OLDER VERSIONS + */ + if (!\OC::$CLI && version_compare($installedVersion, '6.90.1', '<')) { + // Add the overwriteHost config if it is not existant + // This is added to prevent host header poisoning + \OC_Config::setValue('trusted_domains', \OC_Config::getValue('trusted_domains', array(\OC_Request::serverHost()))); + } + /* + * STOP CONFIG CHANGES FOR OLDER VERSIONS + */ + + try { \OC_DB::updateDbFromStructure(\OC::$SERVERROOT . '/db_structure.xml'); $this->emit('\OC\Updater', 'dbUpgrade'); - // do a file cache upgrade for users with files - // this can take loooooooooooooooooooooooong - $this->upgradeFileCache(); } catch (\Exception $exception) { $this->emit('\OC\Updater', 'failure', array($exception->getMessage())); } @@ -120,45 +135,11 @@ class Updater extends BasicEmitter { $repair = new Repair(); $repair->run(); + //Invalidate update feed + \OC_Appconfig::setValue('core', 'lastupdatedat', 0); \OC_Config::setValue('maintenance', false); $this->emit('\OC\Updater', 'maintenanceEnd'); } - private function upgradeFileCache() { - try { - $query = \OC_DB::prepare(' - SELECT DISTINCT `user` - FROM `*PREFIX*fscache` - '); - $result = $query->execute(); - } catch (\Exception $e) { - return; - } - $users = $result->fetchAll(); - if (count($users) == 0) { - return; - } - $step = 100 / count($users); - $percentCompleted = 0; - $lastPercentCompletedOutput = 0; - $startInfoShown = false; - foreach ($users as $userRow) { - $user = $userRow['user']; - \OC\Files\Filesystem::initMountPoints($user); - \OC\Files\Cache\Upgrade::doSilentUpgrade($user); - if (!$startInfoShown) { - //We show it only now, because otherwise Info about upgraded apps - //will appear between this and progress info - $this->emit('\OC\Updater', 'filecacheStart'); - $startInfoShown = true; - } - $percentCompleted += $step; - $out = floor($percentCompleted); - if ($out != $lastPercentCompletedOutput) { - $this->emit('\OC\Updater', 'filecacheProgress', array($out)); - $lastPercentCompletedOutput = $out; - } - } - $this->emit('\OC\Updater', 'filecacheDone'); - } } + diff --git a/lib/private/urlgenerator.php b/lib/private/urlgenerator.php index 4e3c1109000..44b46ef6700 100644 --- a/lib/private/urlgenerator.php +++ b/lib/private/urlgenerator.php @@ -39,7 +39,7 @@ class URLGenerator implements IURLGenerator { * Returns a url to the given app and file. */ public function linkToRoute($route, $parameters = array()) { - $urlLinkTo = \OC::getRouter()->generate($route, $parameters); + $urlLinkTo = \OC::$server->getRouter()->generate($route, $parameters); return $urlLinkTo; } @@ -147,6 +147,7 @@ class URLGenerator implements IURLGenerator { * @return string the absolute version of the url */ public function getAbsoluteURL($url) { - return \OC_Request::serverProtocol() . '://' . \OC_Request::serverHost() . $url; + $separator = $url[0] === '/' ? '' : '/'; + return \OC_Request::serverProtocol() . '://' . \OC_Request::serverHost() . $separator . $url; } } diff --git a/lib/private/user.php b/lib/private/user.php index 11f96aabf74..dc4c7ec3b61 100644 --- a/lib/private/user.php +++ b/lib/private/user.php @@ -205,6 +205,9 @@ class OC_User { // Delete user files in /data/ OC_Helper::rmdirr(\OC_User::getHome($uid)); + // Delete the users entry in the storage table + \OC\Files\Cache\Storage::remove('home::' . $uid); + // Remove it from the Cache self::getManager()->delete($uid); } @@ -219,11 +222,12 @@ 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 - * @return bool + * @return boolean|null * * Log in a user and regenerate a new session - if the password is ok */ public static function login($uid, $password) { + session_regenerate_id(true); return self::getUserSession()->login($uid, $password); } @@ -243,7 +247,6 @@ class OC_User { OC_Hook::emit( "OC_User", "pre_login", array( "run" => &$run, "uid" => $uid )); if($uid) { - session_regenerate_id(true); self::setUserId($uid); self::setDisplayName($uid); self::getUserSession()->setLoginName($uid); @@ -287,6 +290,7 @@ class OC_User { /** * @brief Sets user display name for session + * @param string $uid */ public static function setDisplayName($uid, $displayName = null) { if (is_null($displayName)) { @@ -476,7 +480,7 @@ class OC_User { * @brief Check if the password is correct * @param string $uid The username * @param string $password The password - * @return mixed user id a string on success, false otherwise + * @return string|false user id a string on success, false otherwise * * Check if the password is correct without logging in the user * returns the user id or false @@ -510,6 +514,8 @@ class OC_User { * @returns array with all uids * * Get a list of all users. + * @param integer $limit + * @param integer $offset */ public static function getUsers($search = '', $limit = null, $offset = null) { $users = self::getManager()->search($search, $limit, $offset); @@ -604,7 +610,7 @@ class OC_User { /** * @brief Returns the first active backend from self::$_usedBackends. - * @return null if no backend active, otherwise OCP\Authentication\IApacheBackend + * @return OCP\Authentication\IApacheBackend|null if no backend active, otherwise OCP\Authentication\IApacheBackend */ private static function findFirstActiveUsedBackend() { foreach (self::$_usedBackends as $backend) { diff --git a/lib/private/user/database.php b/lib/private/user/database.php index 1a63755b980..15e6643dfb3 100644 --- a/lib/private/user/database.php +++ b/lib/private/user/database.php @@ -236,7 +236,7 @@ class OC_User_Database extends OC_User_Backend { /** * @brief get the user's home directory * @param string $uid the username - * @return boolean + * @return string|false */ public function getHome($uid) { if ($this->userExists($uid)) { @@ -256,7 +256,7 @@ class OC_User_Database extends OC_User_Backend { /** * counts the users in the database * - * @return int | bool + * @return false|string | bool */ public function countUsers() { $query = OC_DB::prepare('SELECT COUNT(*) FROM `*PREFIX*users`'); diff --git a/lib/private/user/dummy.php b/lib/private/user/dummy.php index fc15a630cf3..2fb51d02de3 100644 --- a/lib/private/user/dummy.php +++ b/lib/private/user/dummy.php @@ -100,7 +100,7 @@ class OC_User_Dummy extends OC_User_Backend { * @param string $search * @param int $limit * @param int $offset - * @return array with all uids + * @return string[] with all uids * * Get a list of all users. */ diff --git a/lib/private/user/http.php b/lib/private/user/http.php index e99afe59ba7..a0394521012 100644 --- a/lib/private/user/http.php +++ b/lib/private/user/http.php @@ -98,7 +98,7 @@ class OC_User_HTTP extends OC_User_Backend { /** * @brief get the user's home directory * @param string $uid the username - * @return boolean + * @return string|false */ public function getHome($uid) { if($this->userExists($uid)) { diff --git a/lib/private/user/interface.php b/lib/private/user/interface.php index c72bdfaf3fd..cdcab3e5d00 100644 --- a/lib/private/user/interface.php +++ b/lib/private/user/interface.php @@ -30,6 +30,7 @@ interface OC_User_Interface { * * Returns the supported actions as int to be * compared with OC_USER_BACKEND_CREATE_USER etc. + * @return boolean */ public function implementsActions($actions); @@ -39,6 +40,7 @@ interface OC_User_Interface { * @returns true/false * * Deletes a user + * @return boolean */ public function deleteUser($uid); diff --git a/lib/private/user/manager.php b/lib/private/user/manager.php index 90970ef9963..8583a451f2d 100644 --- a/lib/private/user/manager.php +++ b/lib/private/user/manager.php @@ -144,8 +144,8 @@ class Manager extends PublicEmitter { /** * Check if the password is valid for the user * - * @param $loginname - * @param $password + * @param string $loginname + * @param string $password * @return mixed the User object on success, false otherwise */ public function checkPassword($loginname, $password) { diff --git a/lib/private/user/session.php b/lib/private/user/session.php index 1e299416fb3..1740bad5abe 100644 --- a/lib/private/user/session.php +++ b/lib/private/user/session.php @@ -149,7 +149,7 @@ class Session implements Emitter, \OCP\IUserSession { * * @param string $uid * @param string $password - * @return bool + * @return boolean|null */ public function login($uid, $password) { $this->manager->emit('\OC\User', 'preLogin', array($uid, $password)); diff --git a/lib/private/util.php b/lib/private/util.php index 6bccaa00261..dea5f2cafcf 100755 --- a/lib/private/util.php +++ b/lib/private/util.php @@ -11,8 +11,6 @@ class OC_Util { public static $headers=array(); private static $rootMounted=false; private static $fsSetup=false; - public static $coreStyles=array(); - public static $coreScripts=array(); /** * @brief Can be set up @@ -63,7 +61,7 @@ class OC_Util { $user = $storage->getUser()->getUID(); $quota = OC_Util::getUserQuota($user); if ($quota !== \OC\Files\SPACE_UNLIMITED) { - return new \OC\Files\Storage\Wrapper\Quota(array('storage' => $storage, 'quota' => $quota)); + return new \OC\Files\Storage\Wrapper\Quota(array('storage' => $storage, 'quota' => $quota, 'root' => 'files')); } } @@ -88,10 +86,14 @@ class OC_Util { return true; } + /** + * @param string $user + */ public static function getUserQuota($user){ - $userQuota = OC_Preferences::getValue($user, 'files', 'quota', 'default'); + $config = \OC::$server->getConfig(); + $userQuota = $config->getUserValue($user, 'files', 'quota', 'default'); if($userQuota === 'default') { - $userQuota = OC_AppConfig::getValue('files', 'default_quota', 'none'); + $userQuota = $config->getAppValue('files', 'default_quota', 'none'); } if($userQuota === 'none') { return \OC\Files\SPACE_UNLIMITED; @@ -212,7 +214,7 @@ class OC_Util { * @brief add a javascript file * * @param string $application - * @param filename $file + * @param string|null $file filename * @return void */ public static function addScript( $application, $file = null ) { @@ -231,7 +233,7 @@ class OC_Util { * @brief add a css file * * @param string $application - * @param filename $file + * @param string|null $file filename * @return void */ public static function addStyle( $application, $file = null ) { @@ -286,13 +288,19 @@ class OC_Util { * @return array arrays with error messages and hints */ public static function checkServer() { + $errors = array(); + $CONFIG_DATADIRECTORY = OC_Config::getValue('datadirectory', OC::$SERVERROOT . '/data'); + + if (!\OC::needUpgrade() && OC_Config::getValue('installed', false)) { + // this check needs to be done every time + $errors = self::checkDataDirectoryValidity($CONFIG_DATADIRECTORY); + } + // Assume that if checkServer() succeeded before in this session, then all is fine. if(\OC::$session->exists('checkServer_suceeded') && \OC::$session->get('checkServer_suceeded')) { - return array(); + return $errors; } - $errors = array(); - $defaults = new \OC_Defaults(); $webServerRestart = false; @@ -337,7 +345,6 @@ class OC_Util { ); } } - $CONFIG_DATADIRECTORY = OC_Config::getValue( "datadirectory", OC::$SERVERROOT."/data" ); // Create root dir. if(!is_dir($CONFIG_DATADIRECTORY)) { $success=@mkdir($CONFIG_DATADIRECTORY); @@ -510,7 +517,7 @@ class OC_Util { /** * @brief Check for correct file permissions of data directory - * @paran string $dataDirectory + * @param string $dataDirectory * @return array arrays with error messages and hints */ public static function checkDataDirectoryPermissions($dataDirectory) { @@ -522,7 +529,7 @@ class OC_Util { .' cannot be listed by other users.'; $perms = substr(decoct(@fileperms($dataDirectory)), -3); if (substr($perms, -1) != '0') { - OC_Helper::chmodr($dataDirectory, 0770); + chmod($dataDirectory, 0770); clearstatcache(); $perms = substr(decoct(@fileperms($dataDirectory)), -3); if (substr($perms, 2, 1) != '0') { @@ -537,6 +544,25 @@ class OC_Util { } /** + * Check that the data directory exists and is valid by + * checking the existence of the ".ocdata" file. + * + * @param string $dataDirectory data directory path + * @return bool true if the data directory is valid, false otherwise + */ + public static function checkDataDirectoryValidity($dataDirectory) { + $errors = array(); + if (!file_exists($dataDirectory.'/.ocdata')) { + $errors[] = array( + 'error' => 'Data directory (' . $dataDirectory . ') is invalid', + 'hint' => 'Please check that the data directory contains a file' . + ' ".ocdata" in its root.' + ); + } + return $errors; + } + + /** * @return void */ public static function displayLoginPage($errors = array()) { @@ -564,6 +590,7 @@ class OC_Util { /** * @brief Check if the app is enabled, redirects to home if not + * @param string $app * @return void */ public static function checkAppEnabled($app) { @@ -623,7 +650,7 @@ class OC_Util { /** * @brief Check if the user is a subadmin, redirects to home if not - * @return array $groups where the current user is subadmin + * @return null|boolean $groups where the current user is subadmin */ public static function checkSubAdminUser() { OC_Util::checkLoggedIn(); @@ -922,7 +949,7 @@ class OC_Util { /** * @brief Check if the connection to the internet is disabled on purpose - * @return bool + * @return string */ public static function isInternetConnectionEnabled(){ return \OC_Config::getValue("has_internet_connection", true); @@ -1127,6 +1154,7 @@ class OC_Util { } /** + * @param boolean|string $file * @return string */ public static function basename($file) { @@ -1147,4 +1175,25 @@ class OC_Util { } return $version; } + + /** + * Returns whether the given file name is valid + * @param $file string file name to check + * @return bool true if the file name is valid, false otherwise + */ + public static function isValidFileName($file) { + $trimmed = trim($file); + if ($trimmed === '') { + return false; + } + if ($trimmed === '.' || $trimmed === '..') { + return false; + } + foreach (str_split($trimmed) as $char) { + if (strpos(\OCP\FILENAME_INVALID_CHARS, $char) !== false) { + return false; + } + } + return true; + } } |