diff options
Diffstat (limited to 'lib/private')
50 files changed, 728 insertions, 727 deletions
diff --git a/lib/private/App/AppManager.php b/lib/private/App/AppManager.php index 0e921ba1b7f..4bf15c23fab 100644 --- a/lib/private/App/AppManager.php +++ b/lib/private/App/AppManager.php @@ -380,10 +380,10 @@ class AppManager implements IAppManager { return $data; } - public function getAppVersion(string $appId, bool $useCache = true) { + public function getAppVersion(string $appId, bool $useCache = true): string { if(!$useCache || !isset($this->appVersions[$appId])) { $appInfo = \OC::$server->getAppManager()->getAppInfo($appId); - $this->appVersions[$appId] = ($appInfo !== null) ? $appInfo['version'] : '0'; + $this->appVersions[$appId] = ($appInfo !== null && isset($appInfo['version'])) ? $appInfo['version'] : '0'; } return $this->appVersions[$appId]; } @@ -397,7 +397,7 @@ class AppManager implements IAppManager { * * @internal */ - public function getIncompatibleApps($version) { + public function getIncompatibleApps(string $version): array { $apps = $this->getInstalledApps(); $incompatibleApps = array(); foreach ($apps as $appId) { @@ -411,6 +411,7 @@ class AppManager implements IAppManager { /** * @inheritdoc + * In case you change this method, also change \OC\App\CodeChecker\InfoChecker::isShipped() */ public function isShipped($appId) { $this->loadShippedJson(); @@ -422,6 +423,10 @@ class AppManager implements IAppManager { return in_array($appId, $alwaysEnabled, true); } + /** + * In case you change this method, also change \OC\App\CodeChecker\InfoChecker::loadShippedJson() + * @throws \Exception + */ private function loadShippedJson() { if ($this->shippedApps === null) { $shippedJson = \OC::$SERVERROOT . '/core/shipped.json'; diff --git a/lib/private/App/AppStore/Fetcher/Fetcher.php b/lib/private/App/AppStore/Fetcher/Fetcher.php index 8bf9ca15349..4dbc360c0c4 100644 --- a/lib/private/App/AppStore/Fetcher/Fetcher.php +++ b/lib/private/App/AppStore/Fetcher/Fetcher.php @@ -174,6 +174,7 @@ abstract class Fetcher { $this->logger->logException($e, ['app' => 'appstoreFetcher', 'level' => Util::INFO, 'message' => 'Could not connect to appstore']); return []; } catch (\Exception $e) { + $this->logger->logException($e, ['app' => 'appstoreFetcher', 'level' => Util::INFO]); return []; } } diff --git a/lib/private/App/CodeChecker/DeprecationCheck.php b/lib/private/App/CodeChecker/DeprecationCheck.php index c337e71f27e..722697f3313 100644 --- a/lib/private/App/CodeChecker/DeprecationCheck.php +++ b/lib/private/App/CodeChecker/DeprecationCheck.php @@ -146,6 +146,8 @@ class DeprecationCheck extends AbstractCheck { 'OCP\IServerContainer::getDb' => '8.1.0', 'OCP\IServerContainer::getHTTPHelper' => '8.1.0', + 'OCP\Response::disableCaching' => '14.0.0', + 'OCP\User::getUser' => '8.0.0', 'OCP\User::getUsers' => '8.1.0', 'OCP\User::getDisplayName' => '8.1.0', diff --git a/lib/private/App/CodeChecker/InfoChecker.php b/lib/private/App/CodeChecker/InfoChecker.php index e8791bd7037..f5de6d376d8 100644 --- a/lib/private/App/CodeChecker/InfoChecker.php +++ b/lib/private/App/CodeChecker/InfoChecker.php @@ -23,121 +23,88 @@ namespace OC\App\CodeChecker; -use OC\App\InfoParser; use OC\Hooks\BasicEmitter; +use OCP\App\AppPathNotFoundException; +use OCP\App\IAppManager; class InfoChecker extends BasicEmitter { - /** @var InfoParser */ - private $infoParser; + /** @var string[] */ + private $shippedApps; - private $mandatoryFields = [ - 'author', - 'description', - 'dependencies', - 'id', - 'licence', - 'name', - 'version', - ]; - private $optionalFields = [ - 'bugs', - 'category', - 'default_enable', - 'documentation', - 'namespace', - 'ocsid', - 'public', - 'remote', - 'repository', - 'types', - 'website', - ]; - private $deprecatedFields = [ - 'info', - 'require', - 'requiremax', - 'requiremin', - 'shipped', - 'standalone', - ]; - - public function __construct(InfoParser $infoParser) { - $this->infoParser = $infoParser; - } + /** @var string[] */ + private $alwaysEnabled; /** * @param string $appId * @return array + * @throws \RuntimeException */ - public function analyse($appId) { + public function analyse($appId): array { $appPath = \OC_App::getAppPath($appId); if ($appPath === false) { throw new \RuntimeException("No app with given id <$appId> known."); } - $errors = []; - - $info = $this->infoParser->parse($appPath . '/appinfo/info.xml'); - - if (!isset($info['dependencies']['nextcloud']['@attributes']['min-version'])) { - $errors[] = [ - 'type' => 'missingRequirement', - 'field' => 'min', - ]; - $this->emit('InfoChecker', 'missingRequirement', ['min']); - } - - if (!isset($info['dependencies']['nextcloud']['@attributes']['max-version'])) { - $errors[] = [ - 'type' => 'missingRequirement', - 'field' => 'max', - ]; - $this->emit('InfoChecker', 'missingRequirement', ['max']); - } - - foreach ($info as $key => $value) { - if(is_array($value)) { - $value = json_encode($value); - } - if (in_array($key, $this->mandatoryFields)) { - $this->emit('InfoChecker', 'mandatoryFieldFound', [$key, $value]); - continue; - } + $xml = new \DOMDocument(); + $xml->load($appPath . '/appinfo/info.xml'); - if (in_array($key, $this->optionalFields)) { - $this->emit('InfoChecker', 'optionalFieldFound', [$key, $value]); - continue; + $schema = \OC::$SERVERROOT . '/resources/app-info.xsd'; + try { + if ($this->isShipped($appId)) { + // Shipped apps are allowed to have the public and default_enabled tags + $schema = \OC::$SERVERROOT . '/resources/app-info-shipped.xsd'; } - - if (in_array($key, $this->deprecatedFields)) { - // skip empty arrays - empty arrays for remote and public are always added - if($value === '[]' && in_array($key, ['public', 'remote', 'info'])) { - continue; - } - $this->emit('InfoChecker', 'deprecatedFieldFound', [$key, $value]); - continue; - } - - $this->emit('InfoChecker', 'unusedFieldFound', [$key, $value]); + } catch (\Exception $e) { + // Assume it is not shipped } - foreach ($this->mandatoryFields as $key) { - if(!isset($info[$key])) { - $this->emit('InfoChecker', 'mandatoryFieldMissing', [$key]); + $errors = []; + if (!$xml->schemaValidate($schema)) { + foreach (libxml_get_errors() as $error) { $errors[] = [ - 'type' => 'mandatoryFieldMissing', - 'field' => $key, + 'type' => 'parseError', + 'field' => $error->message, ]; + $this->emit('InfoChecker', 'parseError', [$error->message]); } } - $versionFile = $appPath . '/appinfo/version'; - if (is_file($versionFile)) { - $version = trim(file_get_contents($versionFile)); - $this->emit('InfoChecker', 'migrateVersion', [$version]); - } - return $errors; } + + /** + * This is a copy of \OC\App\AppManager::isShipped(), keep both in sync. + * This method is copied, so the code checker works even when Nextcloud is + * not installed yet. The AppManager requires a database connection, which + * fails in that case. + * + * @param string $appId + * @return bool + * @throws \Exception + */ + protected function isShipped(string $appId): bool { + $this->loadShippedJson(); + return \in_array($appId, $this->shippedApps, true); + } + + /** + * This is a copy of \OC\App\AppManager::loadShippedJson(), keep both in sync + * This method is copied, so the code checker works even when Nextcloud is + * not installed yet. The AppManager requires a database connection, which + * fails in that case. + * + * @throws \Exception + */ + protected function loadShippedJson() { + if ($this->shippedApps === null) { + $shippedJson = \OC::$SERVERROOT . '/core/shipped.json'; + if (!file_exists($shippedJson)) { + throw new \Exception("File not found: $shippedJson"); + } + $content = json_decode(file_get_contents($shippedJson), true); + $this->shippedApps = $content['shippedApps']; + $this->alwaysEnabled = $content['alwaysEnabled']; + } + } } diff --git a/lib/private/App/DependencyAnalyzer.php b/lib/private/App/DependencyAnalyzer.php index 4193ee5083f..e8da5a0b63a 100644 --- a/lib/private/App/DependencyAnalyzer.php +++ b/lib/private/App/DependencyAnalyzer.php @@ -140,19 +140,19 @@ class DependencyAnalyzer { if (isset($dependencies['php']['@attributes']['min-version'])) { $minVersion = $dependencies['php']['@attributes']['min-version']; if ($this->compareSmaller($this->platform->getPhpVersion(), $minVersion)) { - $missing[] = (string)$this->l->t('PHP %s or higher is required.', $minVersion); + $missing[] = (string)$this->l->t('PHP %s or higher is required.', [$minVersion]); } } if (isset($dependencies['php']['@attributes']['max-version'])) { $maxVersion = $dependencies['php']['@attributes']['max-version']; if ($this->compareBigger($this->platform->getPhpVersion(), $maxVersion)) { - $missing[] = (string)$this->l->t('PHP with a version lower than %s is required.', $maxVersion); + $missing[] = (string)$this->l->t('PHP with a version lower than %s is required.', [$maxVersion]); } } if (isset($dependencies['php']['@attributes']['min-int-size'])) { $intSize = $dependencies['php']['@attributes']['min-int-size']; if ($intSize > $this->platform->getIntSize()*8) { - $missing[] = (string)$this->l->t('%sbit or higher PHP required.', $intSize); + $missing[] = (string)$this->l->t('%sbit or higher PHP required.', [$intSize]); } } return $missing; @@ -209,7 +209,7 @@ class DependencyAnalyzer { } $commandName = $this->getValue($command); if (!$this->platform->isCommandKnown($commandName)) { - $missing[] = (string)$this->l->t('The command line tool %s could not be found', $commandName); + $missing[] = (string)$this->l->t('The command line tool %s could not be found', [$commandName]); } } return $missing; @@ -236,7 +236,7 @@ class DependencyAnalyzer { $libName = $this->getValue($lib); $libVersion = $this->platform->getLibraryVersion($libName); if (is_null($libVersion)) { - $missing[] = (string)$this->l->t('The library %s is not available.', $libName); + $missing[] = (string)$this->l->t('The library %s is not available.', [$libName]); continue; } diff --git a/lib/private/AppFramework/DependencyInjection/DIContainer.php b/lib/private/AppFramework/DependencyInjection/DIContainer.php index 5fe925c2998..44c268bdea6 100644 --- a/lib/private/AppFramework/DependencyInjection/DIContainer.php +++ b/lib/private/AppFramework/DependencyInjection/DIContainer.php @@ -152,10 +152,6 @@ class DIContainer extends SimpleContainer implements IAppContainer { return $c->query('ServerContainer')->getWebRoot(); }); - $this->registerService('fromMailAddress', function() { - return Util::getDefaultEmailAddress('no-reply'); - }); - $this->registerService('OC_Defaults', function ($c) { return $c->getServer()->getThemingDefaults(); }); diff --git a/lib/private/AppFramework/Http/Dispatcher.php b/lib/private/AppFramework/Http/Dispatcher.php index ecf8462ebb6..7b9ad015de6 100644 --- a/lib/private/AppFramework/Http/Dispatcher.php +++ b/lib/private/AppFramework/Http/Dispatcher.php @@ -1,4 +1,5 @@ <?php +declare(strict_types=1); /** * @copyright Copyright (c) 2016, ownCloud, Inc. * @@ -44,9 +45,16 @@ use OCP\IRequest; */ class Dispatcher { + /** @var MiddlewareDispatcher */ private $middlewareDispatcher; + + /** @var Http */ private $protocol; + + /** @var ControllerMethodReflector */ private $reflector; + + /** @var IRequest */ private $request; /** @@ -78,8 +86,8 @@ class Dispatcher { * the response output * @throws \Exception */ - public function dispatch(Controller $controller, $methodName) { - $out = array(null, array(), null); + public function dispatch(Controller $controller, string $methodName): array { + $out = [null, [], null]; try { // prefill reflector with everything thats needed for the @@ -97,9 +105,6 @@ class Dispatcher { } catch(\Exception $exception){ $response = $this->middlewareDispatcher->afterException( $controller, $methodName, $exception); - if (is_null($response)) { - throw $exception; - } } $response = $this->middlewareDispatcher->afterController( @@ -126,11 +131,11 @@ class Dispatcher { * @param string $methodName the method on the controller that should be executed * @return Response */ - private function executeController($controller, $methodName) { - $arguments = array(); + private function executeController(Controller $controller, string $methodName): Response { + $arguments = []; // valid types that will be casted - $types = array('int', 'integer', 'bool', 'boolean', 'float'); + $types = ['int', 'integer', 'bool', 'boolean', 'float']; foreach($this->reflector->getParameters() as $param => $default) { @@ -151,14 +156,14 @@ class Dispatcher { ) { $value = false; - } elseif($value !== null && in_array($type, $types)) { + } elseif($value !== null && \in_array($type, $types, true)) { settype($value, $type); } $arguments[] = $value; } - $response = call_user_func_array(array($controller, $methodName), $arguments); + $response = \call_user_func_array([$controller, $methodName], $arguments); // format response if($response instanceof DataResponse || !($response instanceof Response)) { diff --git a/lib/private/AppFramework/Http/Request.php b/lib/private/AppFramework/Http/Request.php index 975c4255d5a..86ba884141f 100644 --- a/lib/private/AppFramework/Http/Request.php +++ b/lib/private/AppFramework/Http/Request.php @@ -1,4 +1,5 @@ <?php +declare(strict_types=1); /** * @copyright Copyright (c) 2016, ownCloud, Inc. * @@ -87,8 +88,8 @@ class Request implements \ArrayAccess, \Countable, IRequest { protected $inputStream; protected $content; - protected $items = array(); - protected $allowedKeys = array( + protected $items = []; + protected $allowedKeys = [ 'get', 'post', 'files', @@ -99,7 +100,7 @@ class Request implements \ArrayAccess, \Countable, IRequest { 'parameters', 'method', 'requesttoken', - ); + ]; /** @var ISecureRandom */ protected $secureRandom; /** @var IConfig */ @@ -131,13 +132,13 @@ class Request implements \ArrayAccess, \Countable, IRequest { * @param string $stream * @see http://www.php.net/manual/en/reserved.variables.php */ - public function __construct(array $vars=array(), + public function __construct(array $vars= [], ISecureRandom $secureRandom = null, IConfig $config, CsrfTokenManager $csrfTokenManager = null, - $stream = 'php://input') { + string $stream = 'php://input') { $this->inputStream = $stream; - $this->items['params'] = array(); + $this->items['params'] = []; $this->secureRandom = $secureRandom; $this->config = $config; $this->csrfTokenManager = $csrfTokenManager; @@ -149,7 +150,7 @@ class Request implements \ArrayAccess, \Countable, IRequest { foreach($this->allowedKeys as $name) { $this->items[$name] = isset($vars[$name]) ? $vars[$name] - : array(); + : []; } $this->items['parameters'] = array_merge( @@ -175,8 +176,8 @@ class Request implements \ArrayAccess, \Countable, IRequest { * Countable method * @return int */ - public function count() { - return count(array_keys($this->items['parameters'])); + public function count(): int { + return \count($this->items['parameters']); } /** @@ -199,13 +200,15 @@ class Request implements \ArrayAccess, \Countable, IRequest { * @param string $offset The key to lookup * @return boolean */ - public function offsetExists($offset) { + public function offsetExists($offset): bool { return isset($this->items['parameters'][$offset]); } /** - * @see offsetExists - */ + * @see offsetExists + * @param string $offset + * @return mixed + */ public function offsetGet($offset) { return isset($this->items['parameters'][$offset]) ? $this->items['parameters'][$offset] @@ -213,15 +216,18 @@ class Request implements \ArrayAccess, \Countable, IRequest { } /** - * @see offsetExists - */ + * @see offsetExists + * @param string $offset + * @param mixed $value + */ public function offsetSet($offset, $value) { throw new \RuntimeException('You cannot change the contents of the request object'); } /** - * @see offsetExists - */ + * @see offsetExists + * @param string $offset + */ public function offsetUnset($offset) { throw new \RuntimeException('You cannot change the contents of the request object'); } @@ -284,7 +290,7 @@ class Request implements \ArrayAccess, \Countable, IRequest { * @return bool */ public function __isset($name) { - if (in_array($name, $this->allowedKeys, true)) { + if (\in_array($name, $this->allowedKeys, true)) { return true; } return isset($this->items['parameters'][$name]); @@ -305,9 +311,9 @@ class Request implements \ArrayAccess, \Countable, IRequest { * @param string $name * @return string */ - public function getHeader($name) { + public function getHeader(string $name): string { - $name = strtoupper(str_replace(array('-'),array('_'),$name)); + $name = strtoupper(str_replace('-', '_',$name)); if (isset($this->server['HTTP_' . $name])) { return $this->server['HTTP_' . $name]; } @@ -340,7 +346,7 @@ class Request implements \ArrayAccess, \Countable, IRequest { * @param mixed $default If the key is not found, this value will be returned * @return mixed the content of the array */ - public function getParam($key, $default = null) { + public function getParam(string $key, $default = null) { return isset($this->parameters[$key]) ? $this->parameters[$key] : $default; @@ -351,7 +357,7 @@ class Request implements \ArrayAccess, \Countable, IRequest { * (as GET or POST) or throuh the URL by the route * @return array the array with all parameters */ - public function getParams() { + public function getParams(): array { return $this->parameters; } @@ -359,7 +365,7 @@ class Request implements \ArrayAccess, \Countable, IRequest { * Returns the method of the request * @return string the method of the request (POST, GET, etc) */ - public function getMethod() { + public function getMethod(): string { return $this->method; } @@ -368,7 +374,7 @@ class Request implements \ArrayAccess, \Countable, IRequest { * @param string $key the key that will be taken from the $_FILES array * @return array the file in the $_FILES element */ - public function getUploadedFile($key) { + public function getUploadedFile(string $key) { return isset($this->files[$key]) ? $this->files[$key] : null; } @@ -377,7 +383,7 @@ class Request implements \ArrayAccess, \Countable, IRequest { * @param string $key the key that will be taken from the $_ENV array * @return array the value in the $_ENV element */ - public function getEnv($key) { + public function getEnv(string $key) { return isset($this->env[$key]) ? $this->env[$key] : null; } @@ -386,7 +392,7 @@ class Request implements \ArrayAccess, \Countable, IRequest { * @param string $key the key that will be taken from the $_COOKIE array * @return string the value in the $_COOKIE element */ - public function getCookie($key) { + public function getCookie(string $key) { return isset($this->cookies[$key]) ? $this->cookies[$key] : null; } @@ -435,7 +441,7 @@ class Request implements \ArrayAccess, \Countable, IRequest { // 'application/json' must be decoded manually. if (strpos($this->getHeader('Content-Type'), 'application/json') !== false) { $params = json_decode(file_get_contents($this->inputStream), true); - if($params !== null && count($params) > 0) { + if($params !== null && \count($params) > 0) { $this->items['params'] = $params; if($this->method === 'POST') { $this->items['post'] = $params; @@ -449,12 +455,12 @@ class Request implements \ArrayAccess, \Countable, IRequest { && strpos($this->getHeader('Content-Type'), 'application/x-www-form-urlencoded') !== false) { parse_str(file_get_contents($this->inputStream), $params); - if(is_array($params)) { + if(\is_array($params)) { $this->items['params'] = $params; } } - if (is_array($params)) { + if (\is_array($params)) { $this->items['parameters'] = array_merge($this->items['parameters'], $params); } $this->contentDecoded = true; @@ -465,7 +471,7 @@ class Request implements \ArrayAccess, \Countable, IRequest { * Checks if the CSRF check was correct * @return bool true if CSRF check passed */ - public function passesCSRFCheck() { + public function passesCSRFCheck(): bool { if($this->csrfTokenManager === null) { return false; } @@ -494,7 +500,7 @@ class Request implements \ArrayAccess, \Countable, IRequest { * * @return bool */ - private function cookieCheckRequired() { + private function cookieCheckRequired(): bool { if ($this->getHeader('OCS-APIREQUEST')) { return false; } @@ -510,7 +516,7 @@ class Request implements \ArrayAccess, \Countable, IRequest { * * @return array */ - public function getCookieParams() { + public function getCookieParams(): array { return session_get_cookie_params(); } @@ -520,7 +526,7 @@ class Request implements \ArrayAccess, \Countable, IRequest { * @param string $name * @return string */ - protected function getProtectedCookieName($name) { + protected function getProtectedCookieName(string $name): string { $cookieParams = $this->getCookieParams(); $prefix = ''; if($cookieParams['secure'] === true && $cookieParams['path'] === '/') { @@ -537,7 +543,7 @@ class Request implements \ArrayAccess, \Countable, IRequest { * @return bool * @since 9.1.0 */ - public function passesStrictCookieCheck() { + public function passesStrictCookieCheck(): bool { if(!$this->cookieCheckRequired()) { return true; } @@ -557,7 +563,7 @@ class Request implements \ArrayAccess, \Countable, IRequest { * @return bool * @since 9.1.0 */ - public function passesLaxCookieCheck() { + public function passesLaxCookieCheck(): bool { if(!$this->cookieCheckRequired()) { return true; } @@ -575,7 +581,7 @@ class Request implements \ArrayAccess, \Countable, IRequest { * If `mod_unique_id` is installed this value will be taken. * @return string */ - public function getId() { + public function getId(): string { if(isset($this->server['UNIQUE_ID'])) { return $this->server['UNIQUE_ID']; } @@ -595,11 +601,11 @@ class Request implements \ArrayAccess, \Countable, IRequest { * Do always use this instead of $_SERVER['REMOTE_ADDR'] * @return string IP address */ - public function getRemoteAddress() { + public function getRemoteAddress(): string { $remoteAddress = isset($this->server['REMOTE_ADDR']) ? $this->server['REMOTE_ADDR'] : ''; $trustedProxies = $this->config->getSystemValue('trusted_proxies', []); - if(is_array($trustedProxies) && in_array($remoteAddress, $trustedProxies)) { + if(\is_array($trustedProxies) && \in_array($remoteAddress, $trustedProxies)) { $forwardedForHeaders = $this->config->getSystemValue('forwarded_for_headers', [ 'HTTP_X_FORWARDED_FOR' // only have one default, so we cannot ship an insecure product out of the box @@ -625,7 +631,7 @@ class Request implements \ArrayAccess, \Countable, IRequest { * @param string $type * @return bool */ - private function isOverwriteCondition($type = '') { + private function isOverwriteCondition(string $type = ''): bool { $regex = '/' . $this->config->getSystemValue('overwritecondaddr', '') . '/'; $remoteAddr = isset($this->server['REMOTE_ADDR']) ? $this->server['REMOTE_ADDR'] : ''; return $regex === '//' || preg_match($regex, $remoteAddr) === 1 @@ -637,7 +643,7 @@ class Request implements \ArrayAccess, \Countable, IRequest { * and load balancers * @return string Server protocol (http or https) */ - public function getServerProtocol() { + public function getServerProtocol(): string { if($this->config->getSystemValue('overwriteprotocol') !== '' && $this->isOverwriteCondition('protocol')) { return $this->config->getSystemValue('overwriteprotocol'); @@ -671,8 +677,12 @@ class Request implements \ArrayAccess, \Countable, IRequest { * * @return string HTTP protocol. HTTP/2, HTTP/1.1 or HTTP/1.0. */ - public function getHttpProtocol() { - $claimedProtocol = strtoupper($this->server['SERVER_PROTOCOL']); + public function getHttpProtocol(): string { + $claimedProtocol = $this->server['SERVER_PROTOCOL']; + + if (\is_string($claimedProtocol)) { + $claimedProtocol = strtoupper($claimedProtocol); + } $validProtocols = [ 'HTTP/1.0', @@ -680,7 +690,7 @@ class Request implements \ArrayAccess, \Countable, IRequest { 'HTTP/2', ]; - if(in_array($claimedProtocol, $validProtocols, true)) { + if(\in_array($claimedProtocol, $validProtocols, true)) { return $claimedProtocol; } @@ -692,10 +702,10 @@ class Request implements \ArrayAccess, \Countable, IRequest { * reverse proxies * @return string */ - public function getRequestUri() { + public function getRequestUri(): string { $uri = isset($this->server['REQUEST_URI']) ? $this->server['REQUEST_URI'] : ''; if($this->config->getSystemValue('overwritewebroot') !== '' && $this->isOverwriteCondition()) { - $uri = $this->getScriptName() . substr($uri, strlen($this->server['SCRIPT_NAME'])); + $uri = $this->getScriptName() . substr($uri, \strlen($this->server['SCRIPT_NAME'])); } return $uri; } @@ -705,7 +715,7 @@ class Request implements \ArrayAccess, \Countable, IRequest { * @throws \Exception * @return string Path info */ - public function getRawPathInfo() { + public function getRawPathInfo(): string { $requestUri = isset($this->server['REQUEST_URI']) ? $this->server['REQUEST_URI'] : ''; // remove too many leading slashes - can be caused by reverse proxy configuration if (strpos($requestUri, '/') === 0) { @@ -727,16 +737,20 @@ class Request implements \ArrayAccess, \Countable, IRequest { list($path, $name) = \Sabre\Uri\split($scriptName); if (!empty($path)) { if($path === $pathInfo || strpos($pathInfo, $path.'/') === 0) { - $pathInfo = substr($pathInfo, strlen($path)); + $pathInfo = substr($pathInfo, \strlen($path)); } else { throw new \Exception("The requested uri($requestUri) cannot be processed by the script '$scriptName')"); } } + if ($name === null) { + $name = ''; + } + if (strpos($pathInfo, '/'.$name) === 0) { - $pathInfo = substr($pathInfo, strlen($name) + 1); + $pathInfo = substr($pathInfo, \strlen($name) + 1); } - if (strpos($pathInfo, $name) === 0) { - $pathInfo = substr($pathInfo, strlen($name)); + if ($name !== '' && strpos($pathInfo, $name) === 0) { + $pathInfo = substr($pathInfo, \strlen($name)); } if($pathInfo === false || $pathInfo === '/'){ return ''; @@ -770,13 +784,13 @@ class Request implements \ArrayAccess, \Countable, IRequest { * reverse proxies * @return string the script name */ - public function getScriptName() { + public function getScriptName(): string { $name = $this->server['SCRIPT_NAME']; $overwriteWebRoot = $this->config->getSystemValue('overwritewebroot'); if ($overwriteWebRoot !== '' && $this->isOverwriteCondition()) { // FIXME: This code is untestable due to __DIR__, also that hardcoded path is really dangerous - $serverRoot = str_replace('\\', '/', substr(__DIR__, 0, -strlen('lib/private/appframework/http/'))); - $suburi = str_replace('\\', '/', substr(realpath($this->server['SCRIPT_FILENAME']), strlen($serverRoot))); + $serverRoot = str_replace('\\', '/', substr(__DIR__, 0, -\strlen('lib/private/appframework/http/'))); + $suburi = str_replace('\\', '/', substr(realpath($this->server['SCRIPT_FILENAME']), \strlen($serverRoot))); $name = '/' . ltrim($overwriteWebRoot . $suburi, '/'); } return $name; @@ -787,7 +801,7 @@ class Request implements \ArrayAccess, \Countable, IRequest { * @param array $agent array of agent names * @return bool true if at least one of the given agent matches, false otherwise */ - public function isUserAgent(array $agent) { + public function isUserAgent(array $agent): bool { if (!isset($this->server['HTTP_USER_AGENT'])) { return false; } @@ -804,7 +818,7 @@ class Request implements \ArrayAccess, \Countable, IRequest { * whether it is a trusted domain * @return string Server host */ - public function getInsecureServerHost() { + public function getInsecureServerHost(): string { $host = 'localhost'; if (isset($this->server['HTTP_X_FORWARDED_HOST'])) { if (strpos($this->server['HTTP_X_FORWARDED_HOST'], ',') !== false) { @@ -829,7 +843,7 @@ class Request implements \ArrayAccess, \Countable, IRequest { * trusted domain if the host isn't in the trusted list * @return string Server host */ - public function getServerHost() { + public function getServerHost(): string { // overwritehost is always trusted $host = $this->getOverwriteHost(); if ($host !== null) { diff --git a/lib/private/AppFramework/Middleware/MiddlewareDispatcher.php b/lib/private/AppFramework/Middleware/MiddlewareDispatcher.php index 60d2ae8b5c9..e1262b6c712 100644 --- a/lib/private/AppFramework/Middleware/MiddlewareDispatcher.php +++ b/lib/private/AppFramework/Middleware/MiddlewareDispatcher.php @@ -1,4 +1,5 @@ <?php +declare(strict_types=1); /** * @copyright Copyright (c) 2016, ownCloud, Inc. * @@ -30,7 +31,7 @@ namespace OC\AppFramework\Middleware; use OCP\AppFramework\Controller; use OCP\AppFramework\Http\Response; -use OCP\AppFramework\MiddleWare; +use OCP\AppFramework\Middleware; /** * This class is used to store and run all the middleware in correct order @@ -53,7 +54,7 @@ class MiddlewareDispatcher { * Constructor */ public function __construct(){ - $this->middlewares = array(); + $this->middlewares = []; $this->middlewareCounter = 0; } @@ -71,7 +72,7 @@ class MiddlewareDispatcher { * returns an array with all middleware elements * @return array the middlewares */ - public function getMiddlewares(){ + public function getMiddlewares(): array { return $this->middlewares; } @@ -84,10 +85,10 @@ class MiddlewareDispatcher { * @param string $methodName the name of the method that will be called on * the controller */ - public function beforeController(Controller $controller, $methodName){ + public function beforeController(Controller $controller, string $methodName){ // we need to count so that we know which middlewares we have to ask in // case there is an exception - $middlewareCount = count($this->middlewares); + $middlewareCount = \count($this->middlewares); for($i = 0; $i < $middlewareCount; $i++){ $this->middlewareCounter++; $middleware = $this->middlewares[$i]; @@ -111,7 +112,7 @@ class MiddlewareDispatcher { * exception * @throws \Exception the passed in exception if it can't handle it */ - public function afterException(Controller $controller, $methodName, \Exception $exception){ + public function afterException(Controller $controller, string $methodName, \Exception $exception): Response { for($i=$this->middlewareCounter-1; $i>=0; $i--){ $middleware = $this->middlewares[$i]; try { @@ -134,8 +135,8 @@ class MiddlewareDispatcher { * @param Response $response the generated response from the controller * @return Response a Response object */ - public function afterController(Controller $controller, $methodName, Response $response){ - for($i=count($this->middlewares)-1; $i>=0; $i--){ + public function afterController(Controller $controller, string $methodName, Response $response): Response { + for($i= \count($this->middlewares)-1; $i>=0; $i--){ $middleware = $this->middlewares[$i]; $response = $middleware->afterController($controller, $methodName, $response); } @@ -153,8 +154,8 @@ class MiddlewareDispatcher { * @param string $output the generated output from a response * @return string the output that should be printed */ - public function beforeOutput(Controller $controller, $methodName, $output){ - for($i=count($this->middlewares)-1; $i>=0; $i--){ + public function beforeOutput(Controller $controller, string $methodName, string $output): string { + for($i= \count($this->middlewares)-1; $i>=0; $i--){ $middleware = $this->middlewares[$i]; $output = $middleware->beforeOutput($controller, $methodName, $output); } diff --git a/lib/private/AppFramework/Middleware/Security/BruteForceMiddleware.php b/lib/private/AppFramework/Middleware/Security/BruteForceMiddleware.php index 79359b142ac..e09dfdfcb87 100644 --- a/lib/private/AppFramework/Middleware/Security/BruteForceMiddleware.php +++ b/lib/private/AppFramework/Middleware/Security/BruteForceMiddleware.php @@ -26,7 +26,6 @@ namespace OC\AppFramework\Middleware\Security; use OC\AppFramework\Utility\ControllerMethodReflector; use OC\Security\Bruteforce\Throttler; -use OCP\AppFramework\Controller; use OCP\AppFramework\Http\Response; use OCP\AppFramework\Middleware; use OCP\IRequest; diff --git a/lib/private/AppFramework/Middleware/Security/RateLimitingMiddleware.php b/lib/private/AppFramework/Middleware/Security/RateLimitingMiddleware.php index c3b5a844ed5..dca761bdfc0 100644 --- a/lib/private/AppFramework/Middleware/Security/RateLimitingMiddleware.php +++ b/lib/private/AppFramework/Middleware/Security/RateLimitingMiddleware.php @@ -27,7 +27,6 @@ namespace OC\AppFramework\Middleware\Security; use OC\AppFramework\Utility\ControllerMethodReflector; use OC\Security\RateLimiting\Exception\RateLimitExceededException; use OC\Security\RateLimiting\Limiter; -use OCP\AppFramework\Controller; use OCP\AppFramework\Http\JSONResponse; use OCP\AppFramework\Http\TemplateResponse; use OCP\AppFramework\Middleware; diff --git a/lib/private/AppFramework/Utility/ControllerMethodReflector.php b/lib/private/AppFramework/Utility/ControllerMethodReflector.php index 7c777c52c12..ef4a1959d66 100644 --- a/lib/private/AppFramework/Utility/ControllerMethodReflector.php +++ b/lib/private/AppFramework/Utility/ControllerMethodReflector.php @@ -1,4 +1,5 @@ <?php +declare(strict_types=1); /** * @copyright Copyright (c) 2016, ownCloud, Inc. * @@ -42,32 +43,34 @@ class ControllerMethodReflector implements IControllerMethodReflector { * @param object $object an object or classname * @param string $method the method which we want to inspect */ - public function reflect($object, $method){ + public function reflect($object, string $method){ $reflection = new \ReflectionMethod($object, $method); $docs = $reflection->getDocComment(); - // extract everything prefixed by @ and first letter uppercase - preg_match_all('/^\h+\*\h+@(?P<annotation>[A-Z]\w+)((?P<parameter>.*))?$/m', $docs, $matches); - foreach($matches['annotation'] as $key => $annontation) { - $annotationValue = $matches['parameter'][$key]; - if(isset($annotationValue[0]) && $annotationValue[0] === '(' && $annotationValue[strlen($annotationValue) - 1] === ')') { - $cutString = substr($annotationValue, 1, -1); - $cutString = str_replace(' ', '', $cutString); - $splittedArray = explode(',', $cutString); - foreach($splittedArray as $annotationValues) { - list($key, $value) = explode('=', $annotationValues); - $this->annotations[$annontation][$key] = $value; + if ($docs !== false) { + // extract everything prefixed by @ and first letter uppercase + preg_match_all('/^\h+\*\h+@(?P<annotation>[A-Z]\w+)((?P<parameter>.*))?$/m', $docs, $matches); + foreach ($matches['annotation'] as $key => $annontation) { + $annotationValue = $matches['parameter'][$key]; + if (isset($annotationValue[0]) && $annotationValue[0] === '(' && $annotationValue[\strlen($annotationValue) - 1] === ')') { + $cutString = substr($annotationValue, 1, -1); + $cutString = str_replace(' ', '', $cutString); + $splittedArray = explode(',', $cutString); + foreach ($splittedArray as $annotationValues) { + list($key, $value) = explode('=', $annotationValues); + $this->annotations[$annontation][$key] = $value; + } + continue; } - continue; + + $this->annotations[$annontation] = [$annotationValue]; } - $this->annotations[$annontation] = [$annotationValue]; + // extract type parameter information + preg_match_all('/@param\h+(?P<type>\w+)\h+\$(?P<var>\w+)/', $docs, $matches); + $this->types = array_combine($matches['var'], $matches['type']); } - // extract type parameter information - preg_match_all('/@param\h+(?P<type>\w+)\h+\$(?P<var>\w+)/', $docs, $matches); - $this->types = array_combine($matches['var'], $matches['type']); - foreach ($reflection->getParameters() as $param) { // extract type information from PHP 7 scalar types and prefer them // over phpdoc annotations @@ -78,10 +81,9 @@ class ControllerMethodReflector implements IControllerMethodReflector { } } + $default = null; if($param->isOptional()) { $default = $param->getDefaultValue(); - } else { - $default = null; } $this->parameters[$param->name] = $default; } @@ -94,18 +96,18 @@ class ControllerMethodReflector implements IControllerMethodReflector { * @return string|null type in the type parameters (@param int $something) * would return int or null if not existing */ - public function getType($parameter) { + public function getType(string $parameter) { if(array_key_exists($parameter, $this->types)) { return $this->types[$parameter]; - } else { - return null; } + + return null; } /** * @return array the arguments of the method with key => default value */ - public function getParameters() { + public function getParameters(): array { return $this->parameters; } @@ -114,7 +116,7 @@ class ControllerMethodReflector implements IControllerMethodReflector { * @param string $name the name of the annotation * @return bool true if the annotation is found */ - public function hasAnnotation($name) { + public function hasAnnotation(string $name): bool { return array_key_exists($name, $this->annotations); } @@ -125,7 +127,7 @@ class ControllerMethodReflector implements IControllerMethodReflector { * @param string $key the string of the annotation * @return string */ - public function getAnnotationParameter($name, $key) { + public function getAnnotationParameter(string $name, string $key): string { if(isset($this->annotations[$name][$key])) { return $this->annotations[$name][$key]; } diff --git a/lib/private/Avatar.php b/lib/private/Avatar.php index 4cacc801689..14632075ca1 100644 --- a/lib/private/Avatar.php +++ b/lib/private/Avatar.php @@ -263,7 +263,7 @@ class Avatar implements IAvatar { * @return string */ private function generateAvatar($userDisplayName, $size) { - $text = strtoupper($userDisplayName[0]); + $text = mb_strtoupper(mb_substr($userDisplayName, 0, 1), 'UTF-8'); $backgroundColor = $this->avatarBackgroundColor($userDisplayName); $im = imagecreatetruecolor($size, $size); @@ -271,7 +271,7 @@ class Avatar implements IAvatar { $white = imagecolorallocate($im, 255, 255, 255); imagefilledrectangle($im, 0, 0, $size, $size, $background); - $font = __DIR__ . '/../../core/fonts/OpenSans-Semibold.woff'; + $font = __DIR__ . '/../../core/fonts/OpenSans-Semibold.ttf'; $fontSize = $size * 0.4; $box = imagettfbbox($fontSize, 0, $font, $text); diff --git a/lib/private/Collaboration/Collaborators/MailPlugin.php b/lib/private/Collaboration/Collaborators/MailPlugin.php index 2d85ff334bc..b4964825182 100644 --- a/lib/private/Collaboration/Collaborators/MailPlugin.php +++ b/lib/private/Collaboration/Collaborators/MailPlugin.php @@ -175,6 +175,8 @@ class MailPlugin implements ISearchPlugin { if (!$this->shareeEnumeration) { $result['wide'] = []; + } else { + $result['wide'] = array_slice($result['wide'], $offset, $limit); } if (!$searchResult->hasExactIdMatch($emailType) && filter_var($search, FILTER_VALIDATE_EMAIL)) { diff --git a/lib/private/Collaboration/Collaborators/RemotePlugin.php b/lib/private/Collaboration/Collaborators/RemotePlugin.php index b17a64e4ff1..e0f5298f83b 100644 --- a/lib/private/Collaboration/Collaborators/RemotePlugin.php +++ b/lib/private/Collaboration/Collaborators/RemotePlugin.php @@ -102,6 +102,8 @@ class RemotePlugin implements ISearchPlugin { if (!$this->shareeEnumeration) { $result['wide'] = []; + } else { + $result['wide'] = array_slice($result['wide'], $offset, $limit); } if (!$searchResult->hasExactIdMatch($resultType) && $this->cloudIdManager->isValidCloudId($search) && $offset === 0) { diff --git a/lib/private/Contacts/ContactsMenu/ContactsStore.php b/lib/private/Contacts/ContactsMenu/ContactsStore.php index 43600470e1f..73319151d6e 100644 --- a/lib/private/Contacts/ContactsMenu/ContactsStore.php +++ b/lib/private/Contacts/ContactsMenu/ContactsStore.php @@ -27,14 +27,12 @@ namespace OC\Contacts\ContactsMenu; -use OC\Share\Share; use OCP\Contacts\ContactsMenu\IEntry; use OCP\Contacts\IManager; use OCP\IConfig; use OCP\IGroupManager; use OCP\IUser; use OCP\IUserManager; -use OCP\IUserSession; use OCP\Contacts\ContactsMenu\IContactsStore; class ContactsStore implements IContactsStore { diff --git a/lib/private/DB/MigrationService.php b/lib/private/DB/MigrationService.php index 29f717b886c..77ac23fe5d2 100644 --- a/lib/private/DB/MigrationService.php +++ b/lib/private/DB/MigrationService.php @@ -31,8 +31,6 @@ use OCP\AppFramework\QueryException; use OCP\IDBConnection; use OCP\Migration\IMigrationStep; use OCP\Migration\IOutput; -use Doctrine\DBAL\Schema\Column; -use Doctrine\DBAL\Schema\Table; use Doctrine\DBAL\Types\Type; class MigrationService { diff --git a/lib/private/DB/SchemaWrapper.php b/lib/private/DB/SchemaWrapper.php index 4f05b7b00ef..35aae082699 100644 --- a/lib/private/DB/SchemaWrapper.php +++ b/lib/private/DB/SchemaWrapper.php @@ -23,7 +23,6 @@ namespace OC\DB; -use Doctrine\DBAL\DBALException; use Doctrine\DBAL\Schema\Schema; use OCP\DB\ISchemaWrapper; use OCP\IDBConnection; diff --git a/lib/private/Files/Config/UserMountCache.php b/lib/private/Files/Config/UserMountCache.php index 384e6e5e457..cc655018f8d 100644 --- a/lib/private/Files/Config/UserMountCache.php +++ b/lib/private/Files/Config/UserMountCache.php @@ -25,7 +25,6 @@ namespace OC\Files\Config; -use OC\DB\QueryBuilder\Literal; use OCA\Files_Sharing\SharedMount; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\Files\Config\ICachedMountFileInfo; diff --git a/lib/private/Files/ObjectStore/S3ObjectTrait.php b/lib/private/Files/ObjectStore/S3ObjectTrait.php index defeda4c21a..280a8efa81c 100644 --- a/lib/private/Files/ObjectStore/S3ObjectTrait.php +++ b/lib/private/Files/ObjectStore/S3ObjectTrait.php @@ -23,10 +23,7 @@ namespace OC\Files\ObjectStore; -use Aws\Exception\MultipartUploadException; -use Aws\S3\MultipartUploader; use Aws\S3\S3Client; -use Psr\Http\Message\StreamInterface; const S3_UPLOAD_PART_SIZE = 524288000; // 500MB diff --git a/lib/private/Files/ObjectStore/Swift.php b/lib/private/Files/ObjectStore/Swift.php index a3cba488f5f..4451fbcc750 100644 --- a/lib/private/Files/ObjectStore/Swift.php +++ b/lib/private/Files/ObjectStore/Swift.php @@ -25,223 +25,37 @@ namespace OC\Files\ObjectStore; -use Guzzle\Http\Exception\ClientErrorResponseException; -use Guzzle\Http\Exception\CurlException; +use function GuzzleHttp\Psr7\stream_for; use Icewind\Streams\RetryWrapper; use OCP\Files\ObjectStore\IObjectStore; use OCP\Files\StorageAuthException; -use OCP\Files\StorageNotAvailableException; -use OpenCloud\Common\Service\Catalog; -use OpenCloud\Common\Service\CatalogItem; -use OpenCloud\Identity\Resource\Token; -use OpenCloud\ObjectStore\Service; -use OpenCloud\OpenStack; -use OpenCloud\Rackspace; class Swift implements IObjectStore { - - /** - * @var \OpenCloud\OpenStack - */ - private $client; - /** * @var array */ private $params; /** - * @var \OpenCloud\ObjectStore\Service - */ - private $objectStoreService; - - /** - * @var \OpenCloud\ObjectStore\Resource\Container + * @var \OpenStack\ObjectStore\v1\Models\Container|null */ - private $container; - - private $memcache; - - public function __construct($params) { - if (isset($params['bucket'])) { - $params['container'] = $params['bucket']; - } - if (!isset($params['container'])) { - $params['container'] = 'owncloud'; - } - if (!isset($params['autocreate'])) { - // should only be true for tests - $params['autocreate'] = false; - } - - if (isset($params['apiKey'])) { - $this->client = new Rackspace($params['url'], $params); - $cacheKey = $params['username'] . '@' . $params['url'] . '/' . $params['bucket']; - } else { - $this->client = new OpenStack($params['url'], $params); - $cacheKey = $params['username'] . '@' . $params['url'] . '/' . $params['bucket']; - } + private $container = null; - $cacheFactory = \OC::$server->getMemCacheFactory(); - $this->memcache = $cacheFactory->createDistributed('swift::' . $cacheKey); + /** @var SwiftFactory */ + private $swiftFactory; + public function __construct($params, SwiftFactory $connectionFactory = null) { + $this->swiftFactory = $connectionFactory ?: new SwiftFactory(\OC::$server->getMemCacheFactory()->createDistributed('swift::'), $params); $this->params = $params; } /** - * @suppress PhanNonClassMethodCall - */ - protected function init() { - if ($this->container) { - return; - } - - $this->importToken(); - - /** @var Token $token */ - $token = $this->client->getTokenObject(); - - if (!$token || $token->hasExpired()) { - try { - $this->client->authenticate(); - $this->exportToken(); - } catch (ClientErrorResponseException $e) { - $statusCode = $e->getResponse()->getStatusCode(); - if ($statusCode == 412) { - throw new StorageAuthException('Precondition failed, verify the keystone url', $e); - } else if ($statusCode === 401) { - throw new StorageAuthException('Authentication failed, verify the username, password and possibly tenant', $e); - } else { - throw new StorageAuthException('Unknown error', $e); - } - } - } - - - /** @var Catalog $catalog */ - $catalog = $this->client->getCatalog(); - - if (count($catalog->getItems()) === 0) { - throw new StorageAuthException('Keystone did not provide a valid catalog, verify the credentials'); - } - - if (isset($this->params['serviceName'])) { - $serviceName = $this->params['serviceName']; - } else { - $serviceName = Service::DEFAULT_NAME; - } - - if (isset($this->params['urlType'])) { - $urlType = $this->params['urlType']; - if ($urlType !== 'internalURL' && $urlType !== 'publicURL') { - throw new StorageNotAvailableException('Invalid url type'); - } - } else { - $urlType = Service::DEFAULT_URL_TYPE; - } - - $catalogItem = $this->getCatalogForService($catalog, $serviceName); - if (!$catalogItem) { - $available = implode(', ', $this->getAvailableServiceNames($catalog)); - throw new StorageNotAvailableException( - "Service $serviceName not found in service catalog, available services: $available" - ); - } else if (isset($this->params['region'])) { - $this->validateRegion($catalogItem, $this->params['region']); - } - - $this->objectStoreService = $this->client->objectStoreService($serviceName, $this->params['region'], $urlType); - - try { - $this->container = $this->objectStoreService->getContainer($this->params['container']); - } catch (ClientErrorResponseException $ex) { - // if the container does not exist and autocreate is true try to create the container on the fly - if (isset($this->params['autocreate']) && $this->params['autocreate'] === true) { - $this->container = $this->objectStoreService->createContainer($this->params['container']); - } else { - throw $ex; - } - } catch (CurlException $e) { - if ($e->getErrorNo() === 7) { - $host = $e->getCurlHandle()->getUrl()->getHost() . ':' . $e->getCurlHandle()->getUrl()->getPort(); - \OC::$server->getLogger()->error("Can't connect to object storage server at $host"); - throw new StorageNotAvailableException("Can't connect to object storage server at $host", StorageNotAvailableException::STATUS_ERROR, $e); - } - throw $e; - } - } - - private function exportToken() { - $export = $this->client->exportCredentials(); - $export['catalog'] = array_map(function (CatalogItem $item) { - return [ - 'name' => $item->getName(), - 'endpoints' => $item->getEndpoints(), - 'type' => $item->getType() - ]; - }, $export['catalog']->getItems()); - $this->memcache->set('token', json_encode($export)); - } - - private function importToken() { - $cachedTokenString = $this->memcache->get('token'); - if ($cachedTokenString) { - $cachedToken = json_decode($cachedTokenString, true); - $cachedToken['catalog'] = array_map(function (array $item) { - $itemClass = new \stdClass(); - $itemClass->name = $item['name']; - $itemClass->endpoints = array_map(function (array $endpoint) { - return (object)$endpoint; - }, $item['endpoints']); - $itemClass->type = $item['type']; - - return $itemClass; - }, $cachedToken['catalog']); - try { - $this->client->importCredentials($cachedToken); - } catch (\Exception $e) { - $this->client->setTokenObject(new Token()); - } - } - } - - /** - * @param Catalog $catalog - * @param $name - * @return null|CatalogItem + * @return \OpenStack\ObjectStore\v1\Models\Container + * @throws StorageAuthException + * @throws \OCP\Files\StorageNotAvailableException */ - private function getCatalogForService(Catalog $catalog, $name) { - foreach ($catalog->getItems() as $item) { - /** @var CatalogItem $item */ - if ($item->hasType(Service::DEFAULT_TYPE) && $item->hasName($name)) { - return $item; - } - } - - return null; - } - - private function validateRegion(CatalogItem $item, $region) { - $endPoints = $item->getEndpoints(); - foreach ($endPoints as $endPoint) { - if ($endPoint->region === $region) { - return; - } - } - - $availableRegions = implode(', ', array_map(function ($endpoint) { - return $endpoint->region; - }, $endPoints)); - - throw new StorageNotAvailableException("Invalid region '$region', available regions: $availableRegions"); - } - - private function getAvailableServiceNames(Catalog $catalog) { - return array_map(function (CatalogItem $item) { - return $item->getName(); - }, array_filter($catalog->getItems(), function (CatalogItem $item) { - return $item->hasType(Service::DEFAULT_TYPE); - })); + private function getContainer() { + return $this->swiftFactory->getContainer(); } /** @@ -254,29 +68,29 @@ class Swift implements IObjectStore { /** * @param string $urn the unified resource name used to identify the object * @param resource $stream stream with the data to write - * @throws Exception from openstack lib when something goes wrong + * @throws \Exception from openstack lib when something goes wrong */ public function writeObject($urn, $stream) { - $this->init(); - $this->container->uploadObject($urn, $stream); + $this->getContainer()->createObject([ + 'name' => $urn, + 'stream' => stream_for($stream) + ]); } /** * @param string $urn the unified resource name used to identify the object * @return resource stream with the read data - * @throws Exception from openstack lib when something goes wrong + * @throws \Exception from openstack lib when something goes wrong */ public function readObject($urn) { - $this->init(); - $object = $this->container->getObject($urn); + $object = $this->getContainer()->getObject($urn); // we need to keep a reference to objectContent or // the stream will be closed before we can do anything with it - /** @var $objectContent \Guzzle\Http\EntityBody * */ - $objectContent = $object->getContent(); + $objectContent = $object->download(); $objectContent->rewind(); - $stream = $objectContent->getStream(); + $stream = $objectContent->detach(); // save the object content in the context of the stream to prevent it being gc'd until the stream is closed stream_context_set_option($stream, 'swift', 'content', $objectContent); @@ -286,17 +100,18 @@ class Swift implements IObjectStore { /** * @param string $urn Unified Resource Name * @return void - * @throws Exception from openstack lib when something goes wrong + * @throws \Exception from openstack lib when something goes wrong */ public function deleteObject($urn) { - $this->init(); - // see https://github.com/rackspace/php-opencloud/issues/243#issuecomment-30032242 - $this->container->dataObject()->setName($urn)->delete(); + $this->getContainer()->getObject($urn)->delete(); } - public function deleteContainer($recursive = false) { - $this->init(); - $this->container->delete($recursive); + /** + * @return void + * @throws \Exception from openstack lib when something goes wrong + */ + public function deleteContainer() { + $this->getContainer()->delete(); } } diff --git a/lib/private/Files/ObjectStore/SwiftFactory.php b/lib/private/Files/ObjectStore/SwiftFactory.php new file mode 100644 index 00000000000..0df6fb6efcd --- /dev/null +++ b/lib/private/Files/ObjectStore/SwiftFactory.php @@ -0,0 +1,174 @@ +<?php +declare(strict_types=1); +/** + * @copyright Copyright (c) 2018 Robin Appelman <robin@icewind.nl> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OC\Files\ObjectStore; + +use GuzzleHttp\Client; +use GuzzleHttp\Exception\ClientException; +use GuzzleHttp\Exception\ConnectException; +use GuzzleHttp\Exception\RequestException; +use GuzzleHttp\HandlerStack; +use OCP\Files\StorageAuthException; +use OCP\Files\StorageNotAvailableException; +use OCP\ICache; +use OpenStack\Common\Error\BadResponseError; +use OpenStack\Identity\v2\Models\Token; +use OpenStack\Identity\v2\Service; +use OpenStack\OpenStack; +use OpenStack\Common\Transport\Utils as TransportUtils; +use Psr\Http\Message\RequestInterface; +use OpenStack\ObjectStore\v1\Models\Container; + +class SwiftFactory { + private $cache; + private $params; + /** @var Container|null */ + private $container = null; + + public function __construct(ICache $cache, array $params) { + $this->cache = $cache; + $this->params = $params; + } + + private function getCachedToken(string $cacheKey) { + $cachedTokenString = $this->cache->get($cacheKey . '/token'); + if ($cachedTokenString) { + return json_decode($cachedTokenString); + } else { + return null; + } + } + + private function cacheToken(Token $token, string $cacheKey) { + $this->cache->set($cacheKey . '/token', json_encode($token)); + } + + /** + * @return OpenStack + * @throws StorageAuthException + */ + private function getClient() { + if (isset($this->params['bucket'])) { + $this->params['container'] = $this->params['bucket']; + } + if (!isset($this->params['container'])) { + $this->params['container'] = 'owncloud'; + } + if (!isset($this->params['autocreate'])) { + // should only be true for tests + $this->params['autocreate'] = false; + } + if (!isset($this->params['username']) && isset($this->params['user'])) { + $this->params['username'] = $this->params['user']; + } + if (!isset($this->params['tenantName']) && isset($this->params['tenant'])) { + $this->params['tenantName'] = $this->params['tenant']; + } + + $cacheKey = $this->params['username'] . '@' . $this->params['url'] . '/' . $this->params['bucket']; + $token = $this->getCachedToken($cacheKey); + $hasToken = is_array($token) && (new \DateTimeImmutable($token['expires_at'])) > (new \DateTimeImmutable('now')); + if ($hasToken) { + $this->params['cachedToken'] = $token; + } + $httpClient = new Client([ + 'base_uri' => TransportUtils::normalizeUrl($this->params['url']), + 'handler' => HandlerStack::create() + ]); + + $authService = Service::factory($httpClient); + $this->params['identityService'] = $authService; + $this->params['authUrl'] = $this->params['url']; + $client = new OpenStack($this->params); + + if (!$hasToken) { + try { + $token = $authService->generateToken($this->params); + $this->cacheToken($token, $cacheKey); + } catch (ConnectException $e) { + throw new StorageAuthException('Failed to connect to keystone, verify the keystone url', $e); + } catch (ClientException $e) { + $statusCode = $e->getResponse()->getStatusCode(); + if ($statusCode === 404) { + throw new StorageAuthException('Keystone not found, verify the keystone url', $e); + } else if ($statusCode === 412) { + throw new StorageAuthException('Precondition failed, verify the keystone url', $e); + } else if ($statusCode === 401) { + throw new StorageAuthException('Authentication failed, verify the username, password and possibly tenant', $e); + } else { + throw new StorageAuthException('Unknown error', $e); + } + } catch (RequestException $e) { + throw new StorageAuthException('Connection reset while connecting to keystone, verify the keystone url', $e); + } + } + + return $client; + } + + /** + * @return \OpenStack\ObjectStore\v1\Models\Container + * @throws StorageAuthException + * @throws StorageNotAvailableException + */ + public function getContainer() { + if (is_null($this->container)) { + $this->container = $this->createContainer(); + } + + return $this->container; + } + + /** + * @return \OpenStack\ObjectStore\v1\Models\Container + * @throws StorageAuthException + * @throws StorageNotAvailableException + */ + private function createContainer() { + $client = $this->getClient(); + $objectStoreService = $client->objectStoreV1(); + + $autoCreate = isset($this->params['autocreate']) && $this->params['autocreate'] === true; + try { + $container = $objectStoreService->getContainer($this->params['container']); + if ($autoCreate) { + $container->getMetadata(); + } + return $container; + } catch (BadResponseError $ex) { + // if the container does not exist and autocreate is true try to create the container on the fly + if ($ex->getResponse()->getStatusCode() === 404 && $autoCreate) { + return $objectStoreService->createContainer([ + 'name' => $this->params['container'] + ]); + } else { + throw new StorageNotAvailableException('Invalid response while trying to get container info', StorageNotAvailableException::STATUS_ERROR, $e); + } + } catch (ConnectException $e) { + /** @var RequestInterface $request */ + $request = $e->getRequest(); + $host = $request->getUri()->getHost() . ':' . $request->getUri()->getPort(); + \OC::$server->getLogger()->error("Can't connect to object storage server at $host"); + throw new StorageNotAvailableException("Can't connect to object storage server at $host", StorageNotAvailableException::STATUS_ERROR, $e); + } + } +} diff --git a/lib/private/Files/Storage/DAV.php b/lib/private/Files/Storage/DAV.php index f9c6175308c..1496fda5140 100644 --- a/lib/private/Files/Storage/DAV.php +++ b/lib/private/Files/Storage/DAV.php @@ -35,7 +35,7 @@ namespace OC\Files\Storage; use Exception; use GuzzleHttp\Exception\RequestException; -use GuzzleHttp\Message\ResponseInterface; +use Psr\Http\Message\ResponseInterface; use Icewind\Streams\CallbackWrapper; use OC\Files\Filesystem; use Icewind\Streams\IteratorDirectory; @@ -344,7 +344,7 @@ class DAV extends Common { 'auth' => [$this->user, $this->password], 'stream' => true ]); - } catch (RequestException $e) { + } catch (\GuzzleHttp\Exception\ClientException $e) { if ($e->getResponse() instanceof ResponseInterface && $e->getResponse()->getStatusCode() === 404) { return false; diff --git a/lib/private/Http/Client/Client.php b/lib/private/Http/Client/Client.php index 4e6843d7b9f..0387fcabfaf 100644 --- a/lib/private/Http/Client/Client.php +++ b/lib/private/Http/Client/Client.php @@ -25,10 +25,13 @@ declare(strict_types=1); namespace OC\Http\Client; use GuzzleHttp\Client as GuzzleClient; +use GuzzleHttp\HandlerStack; +use GuzzleHttp\Middleware; use OCP\Http\Client\IClient; use OCP\Http\Client\IResponse; use OCP\ICertificateManager; use OCP\IConfig; +use Psr\Http\Message\RequestInterface; /** * Class Client @@ -43,17 +46,23 @@ class Client implements IClient { /** @var ICertificateManager */ private $certificateManager; private $configured = false; + /** @var HandlerStack */ + private $stack; /** * @param IConfig $config * @param ICertificateManager $certificateManager * @param GuzzleClient $client */ - public function __construct(IConfig $config, - ICertificateManager $certificateManager, - GuzzleClient $client) { + public function __construct( + IConfig $config, + ICertificateManager $certificateManager, + GuzzleClient $client, + HandlerStack $stack + ) { $this->config = $config; $this->client = $client; + $this->stack = $stack; $this->certificateManager = $certificateManager; } @@ -65,25 +74,37 @@ class Client implements IClient { return; } $this->configured = true; - // Either use user bundle or the system bundle if nothing is specified + + $this->stack->push(Middleware::mapRequest(function (RequestInterface $request) { + return $request + ->withHeader('User-Agent', 'Nextcloud Server Crawler'); + })); + } + + private function getRequestOptions() { + $options = [ + 'verify' => $this->getCertBundle(), + ]; + $proxyUri = $this->getProxyUri(); + if ($proxyUri !== '') { + $options['proxy'] = $proxyUri; + } + return $options; + } + + private function getCertBundle() { if ($this->certificateManager->listCertificates() !== []) { - $this->client->setDefaultOption('verify', $this->certificateManager->getAbsoluteBundlePath()); + return $this->certificateManager->getAbsoluteBundlePath(); } else { // If the instance is not yet setup we need to use the static path as // $this->certificateManager->getAbsoluteBundlePath() tries to instantiiate // a view if ($this->config->getSystemValue('installed', false)) { - $this->client->setDefaultOption('verify', $this->certificateManager->getAbsoluteBundlePath(null)); + return $this->certificateManager->getAbsoluteBundlePath(null); } else { - $this->client->setDefaultOption('verify', \OC::$SERVERROOT . '/resources/config/ca-bundle.crt'); + return \OC::$SERVERROOT . '/resources/config/ca-bundle.crt'; } } - - $this->client->setDefaultOption('headers/User-Agent', 'Nextcloud Server Crawler'); - $proxyUri = $this->getProxyUri(); - if ($proxyUri !== '') { - $this->client->setDefaultOption('proxy', $proxyUri); - } } /** @@ -137,7 +158,7 @@ class Client implements IClient { */ public function get(string $uri, array $options = []): IResponse { $this->setDefaultOptions(); - $response = $this->client->get($uri, $options); + $response = $this->client->request('get', $uri, array_merge($options, $this->getRequestOptions())); $isStream = isset($options['stream']) && $options['stream']; return new Response($response, $isStream); } @@ -168,7 +189,7 @@ class Client implements IClient { */ public function head(string $uri, array $options = []): IResponse { $this->setDefaultOptions(); - $response = $this->client->head($uri, $options); + $response = $this->client->request('head', $uri, array_merge($options, $this->getRequestOptions())); return new Response($response); } @@ -203,7 +224,11 @@ class Client implements IClient { */ public function post(string $uri, array $options = []): IResponse { $this->setDefaultOptions(); - $response = $this->client->post($uri, $options); + if (isset($options['body']) && is_array($options['body'])) { + $options['form_params'] = $options['body']; + unset($options['body']); + } + $response = $this->client->request('post', $uri, array_merge($options, $this->getRequestOptions())); return new Response($response); } @@ -238,7 +263,7 @@ class Client implements IClient { */ public function put(string $uri, array $options = []): IResponse { $this->setDefaultOptions(); - $response = $this->client->put($uri, $options); + $response = $this->client->request('put', $uri, array_merge($options, $this->getRequestOptions())); return new Response($response); } @@ -273,7 +298,7 @@ class Client implements IClient { */ public function delete(string $uri, array $options = []): IResponse { $this->setDefaultOptions(); - $response = $this->client->delete($uri, $options); + $response = $this->client->request('delete', $uri, array_merge($options, $this->getRequestOptions())); return new Response($response); } @@ -309,7 +334,7 @@ class Client implements IClient { */ public function options(string $uri, array $options = []): IResponse { $this->setDefaultOptions(); - $response = $this->client->options($uri, $options); + $response = $this->client->request('options', $uri, array_merge($options, $this->getRequestOptions())); return new Response($response); } } diff --git a/lib/private/Http/Client/ClientService.php b/lib/private/Http/Client/ClientService.php index 1df54010a2d..fa8544f07a5 100644 --- a/lib/private/Http/Client/ClientService.php +++ b/lib/private/Http/Client/ClientService.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace OC\Http\Client; use GuzzleHttp\Client as GuzzleClient; +use GuzzleHttp\HandlerStack; use OCP\Http\Client\IClient; use OCP\Http\Client\IClientService; use OCP\ICertificateManager; @@ -54,6 +55,6 @@ class ClientService implements IClientService { * @return Client */ public function newClient(): IClient { - return new Client($this->config, $this->certificateManager, new GuzzleClient()); + return new Client($this->config, $this->certificateManager, new GuzzleClient(), HandlerStack::create()); } } diff --git a/lib/private/Http/Client/Response.php b/lib/private/Http/Client/Response.php index 0ce6cc98e0d..73c14c2926d 100644 --- a/lib/private/Http/Client/Response.php +++ b/lib/private/Http/Client/Response.php @@ -25,7 +25,7 @@ declare(strict_types=1); namespace OC\Http\Client; use OCP\Http\Client\IResponse; -use GuzzleHttp\Message\ResponseInterface as GuzzleResponse; +use Psr\Http\Message\ResponseInterface; /** * Class Response @@ -33,7 +33,7 @@ use GuzzleHttp\Message\ResponseInterface as GuzzleResponse; * @package OC\Http */ class Response implements IResponse { - /** @var GuzzleResponse */ + /** @var ResponseInterface */ private $response; /** @@ -42,10 +42,10 @@ class Response implements IResponse { private $stream; /** - * @param GuzzleResponse $response + * @param ResponseInterface $response * @param bool $stream */ - public function __construct(GuzzleResponse $response, $stream = false) { + public function __construct(ResponseInterface $response, $stream = false) { $this->response = $response; $this->stream = $stream; } @@ -71,7 +71,7 @@ class Response implements IResponse { * @return string */ public function getHeader(string $key): string { - return $this->response->getHeader($key); + return $this->response->getHeader($key)[0]; } /** diff --git a/lib/private/Installer.php b/lib/private/Installer.php index ad2dcb60f20..8a8ece82077 100644 --- a/lib/private/Installer.php +++ b/lib/private/Installer.php @@ -36,17 +36,12 @@ namespace OC; use Doctrine\DBAL\Exception\TableExistsException; -use OC\App\AppManager; use OC\App\AppStore\Bundles\Bundle; use OC\App\AppStore\Fetcher\AppFetcher; -use OC\App\CodeChecker\CodeChecker; -use OC\App\CodeChecker\EmptyCheck; -use OC\App\CodeChecker\PrivateCheck; use OC\Archive\TAR; use OC_App; use OC_DB; use OC_Helper; -use OCP\App\IAppManager; use OCP\Http\Client\IClientService; use OCP\IConfig; use OCP\ILogger; @@ -117,7 +112,7 @@ class Installer { ); } - $version = \OCP\Util::getVersion(); + $version = implode('.', \OCP\Util::getVersion()); if (!\OC_App::isAppCompatible($version, $info)) { throw new \Exception( // TODO $l diff --git a/lib/private/IntegrityCheck/Checker.php b/lib/private/IntegrityCheck/Checker.php index 771ac891ab4..44544b6770e 100644 --- a/lib/private/IntegrityCheck/Checker.php +++ b/lib/private/IntegrityCheck/Checker.php @@ -1,4 +1,5 @@ <?php +declare(strict_types=1); /** * @copyright Copyright (c) 2016, ownCloud, Inc. * @@ -97,9 +98,9 @@ class Checker { * * @return bool */ - public function isCodeCheckEnforced() { + public function isCodeCheckEnforced(): bool { $notSignedChannels = [ '', 'git']; - if (in_array($this->environmentHelper->getChannel(), $notSignedChannels, true)) { + if (\in_array($this->environmentHelper->getChannel(), $notSignedChannels, true)) { return false; } @@ -108,10 +109,9 @@ class Checker { * applicable for very specific scenarios and we should not advertise it * too prominent. So please do not add it to config.sample.php. */ + $isIntegrityCheckDisabled = false; if ($this->config !== null) { $isIntegrityCheckDisabled = $this->config->getSystemValue('integrity.check.disabled', false); - } else { - $isIntegrityCheckDisabled = false; } if ($isIntegrityCheckDisabled === true) { return false; @@ -128,7 +128,7 @@ class Checker { * @return \RecursiveIteratorIterator * @throws \Exception */ - private function getFolderIterator($folderToIterate, $root = '') { + private function getFolderIterator(string $folderToIterate, string $root = ''): \RecursiveIteratorIterator { $dirItr = new \RecursiveDirectoryIterator( $folderToIterate, \RecursiveDirectoryIterator::SKIP_DOTS @@ -156,12 +156,12 @@ class Checker { * @return array Array of hashes. */ private function generateHashes(\RecursiveIteratorIterator $iterator, - $path) { + string $path): array { $hashes = []; $copiedWebserverSettingFiles = false; $tmpFolder = ''; - $baseDirectoryLength = strlen($path); + $baseDirectoryLength = \strlen($path); foreach($iterator as $filename => $data) { /** @var \DirectoryIterator $data */ if($data->isDir()) { @@ -220,7 +220,7 @@ class Checker { if($filename === $this->environmentHelper->getServerRoot() . '/.htaccess') { $fileContent = file_get_contents($tmpFolder . '/.htaccess'); $explodedArray = explode('#### DO NOT CHANGE ANYTHING ABOVE THIS LINE ####', $fileContent); - if(count($explodedArray) === 2) { + if(\count($explodedArray) === 2) { $hashes[$relativeFileName] = hash('sha512', $explodedArray[0]); continue; } @@ -238,11 +238,11 @@ class Checker { * @param array $hashes * @param X509 $certificate * @param RSA $privateKey - * @return string + * @return array */ private function createSignatureData(array $hashes, X509 $certificate, - RSA $privateKey) { + RSA $privateKey): array { ksort($hashes); $privateKey->setSignatureMode(RSA::SIGNATURE_PSS); @@ -328,13 +328,18 @@ class Checker { * @throws InvalidSignatureException * @throws \Exception */ - private function verify($signaturePath, $basePath, $certificateCN) { + private function verify(string $signaturePath, string $basePath, string $certificateCN): array { if(!$this->isCodeCheckEnforced()) { return []; } - $signatureData = json_decode($this->fileAccessHelper->file_get_contents($signaturePath), true); - if(!is_array($signatureData)) { + $content = $this->fileAccessHelper->file_get_contents($signaturePath); + $signatureData = null; + + if (\is_string($content)) { + $signatureData = json_decode($content, true); + } + if(!\is_array($signatureData)) { throw new InvalidSignatureException('Signature data not found.'); } @@ -422,7 +427,7 @@ class Checker { * * @return bool */ - public function hasPassedCheck() { + public function hasPassedCheck(): bool { $results = $this->getResults(); if(empty($results)) { return true; @@ -434,9 +439,9 @@ class Checker { /** * @return array */ - public function getResults() { + public function getResults(): array { $cachedResults = $this->cache->get(self::CACHE_KEY); - if(!is_null($cachedResults)) { + if(!\is_null($cachedResults)) { return json_decode($cachedResults, true); } @@ -452,7 +457,7 @@ class Checker { * @param string $scope * @param array $result */ - private function storeResults($scope, array $result) { + private function storeResults(string $scope, array $result) { $resultArray = $this->getResults(); unset($resultArray[$scope]); if(!empty($result)) { @@ -505,7 +510,7 @@ class Checker { * @param string $path Optional path. If none is given it will be guessed. * @return array */ - public function verifyAppSignature($appId, $path = '') { + public function verifyAppSignature(string $appId, string $path = ''): array { try { if($path === '') { $path = $this->appLocator->getAppPath($appId); @@ -518,7 +523,7 @@ class Checker { } catch (\Exception $e) { $result = [ 'EXCEPTION' => [ - 'class' => get_class($e), + 'class' => \get_class($e), 'message' => $e->getMessage(), ], ]; @@ -558,7 +563,7 @@ class Checker { * * @return array */ - public function verifyCoreSignature() { + public function verifyCoreSignature(): array { try { $result = $this->verify( $this->environmentHelper->getServerRoot() . '/core/signature.json', @@ -568,7 +573,7 @@ class Checker { } catch (\Exception $e) { $result = [ 'EXCEPTION' => [ - 'class' => get_class($e), + 'class' => \get_class($e), 'message' => $e->getMessage(), ], ]; diff --git a/lib/private/IntegrityCheck/Helpers/AppLocator.php b/lib/private/IntegrityCheck/Helpers/AppLocator.php index c8d4e1b9b27..9ec5361d9d5 100644 --- a/lib/private/IntegrityCheck/Helpers/AppLocator.php +++ b/lib/private/IntegrityCheck/Helpers/AppLocator.php @@ -1,4 +1,5 @@ <?php +declare(strict_types=1); /** * @copyright Copyright (c) 2016, ownCloud, Inc. * @@ -37,7 +38,7 @@ class AppLocator { * @return string * @throws \Exception If the app cannot be found */ - public function getAppPath($appId) { + public function getAppPath(string $appId): string { $path = \OC_App::getAppPath($appId); if($path === false) { @@ -51,7 +52,7 @@ class AppLocator { * * @return array */ - public function getAllApps() { + public function getAllApps(): array { return \OC_App::getAllApps(); } } diff --git a/lib/private/IntegrityCheck/Helpers/EnvironmentHelper.php b/lib/private/IntegrityCheck/Helpers/EnvironmentHelper.php index c5e91997130..b69af591bc2 100644 --- a/lib/private/IntegrityCheck/Helpers/EnvironmentHelper.php +++ b/lib/private/IntegrityCheck/Helpers/EnvironmentHelper.php @@ -1,4 +1,5 @@ <?php +declare(strict_types=1); /** * @copyright Copyright (c) 2016, ownCloud, Inc. * @@ -34,7 +35,7 @@ class EnvironmentHelper { * * @return string */ - public function getServerRoot() { + public function getServerRoot(): string { return rtrim(\OC::$SERVERROOT, '/'); } @@ -43,7 +44,7 @@ class EnvironmentHelper { * * @return string */ - public function getChannel() { + public function getChannel(): string { return \OC_Util::getChannel(); } } diff --git a/lib/private/IntegrityCheck/Helpers/FileAccessHelper.php b/lib/private/IntegrityCheck/Helpers/FileAccessHelper.php index ef8e8b41b3f..e73b84b73c4 100644 --- a/lib/private/IntegrityCheck/Helpers/FileAccessHelper.php +++ b/lib/private/IntegrityCheck/Helpers/FileAccessHelper.php @@ -1,4 +1,5 @@ <?php +declare(strict_types=1); /** * @copyright Copyright (c) 2016, ownCloud, Inc. * @@ -36,7 +37,7 @@ class FileAccessHelper { * @param string $filename * @return string|false */ - public function file_get_contents($filename) { + public function file_get_contents(string $filename) { return file_get_contents($filename); } @@ -46,7 +47,7 @@ class FileAccessHelper { * @param string $filename * @return bool */ - public function file_exists($filename) { + public function file_exists(string $filename): bool { return file_exists($filename); } @@ -58,9 +59,9 @@ class FileAccessHelper { * @return int * @throws \Exception */ - public function file_put_contents($filename, $data) { + public function file_put_contents(string $filename, string $data): int { $bytesWritten = @file_put_contents($filename, $data); - if ($bytesWritten === false || $bytesWritten !== strlen($data)){ + if ($bytesWritten === false || $bytesWritten !== \strlen($data)){ throw new \Exception('Failed to write into ' . $filename); } return $bytesWritten; @@ -70,7 +71,7 @@ class FileAccessHelper { * @param string $path * @return bool */ - public function is_writable($path) { + public function is_writable(string $path): bool { return is_writable($path); } @@ -78,7 +79,7 @@ class FileAccessHelper { * @param string $path * @throws \Exception */ - public function assertDirectoryExists($path) { + public function assertDirectoryExists(string $path) { if (!is_dir($path)) { throw new \Exception('Directory ' . $path . ' does not exist.'); } diff --git a/lib/private/IntegrityCheck/Iterator/ExcludeFileByNameFilterIterator.php b/lib/private/IntegrityCheck/Iterator/ExcludeFileByNameFilterIterator.php index 4801d7bb748..e0ad6a550e5 100644 --- a/lib/private/IntegrityCheck/Iterator/ExcludeFileByNameFilterIterator.php +++ b/lib/private/IntegrityCheck/Iterator/ExcludeFileByNameFilterIterator.php @@ -1,4 +1,5 @@ <?php +declare(strict_types=1); /** * @copyright Copyright (c) 2016, ownCloud, Inc. * @@ -52,7 +53,7 @@ class ExcludeFileByNameFilterIterator extends \RecursiveFilterIterator { return true; } - return !in_array( + return !\in_array( $this->current()->getFilename(), $this->excludedFilenames, true diff --git a/lib/private/IntegrityCheck/Iterator/ExcludeFoldersByPathFilterIterator.php b/lib/private/IntegrityCheck/Iterator/ExcludeFoldersByPathFilterIterator.php index 31dd05ef312..56524abe6a0 100644 --- a/lib/private/IntegrityCheck/Iterator/ExcludeFoldersByPathFilterIterator.php +++ b/lib/private/IntegrityCheck/Iterator/ExcludeFoldersByPathFilterIterator.php @@ -1,4 +1,5 @@ <?php +declare(strict_types=1); /** * @copyright Copyright (c) 2016, ownCloud, Inc. * @@ -24,7 +25,7 @@ namespace OC\IntegrityCheck\Iterator; class ExcludeFoldersByPathFilterIterator extends \RecursiveFilterIterator { - private $excludedFolders = []; + private $excludedFolders; public function __construct(\RecursiveIterator $iterator, $root = '') { parent::__construct($iterator); @@ -59,7 +60,7 @@ class ExcludeFoldersByPathFilterIterator extends \RecursiveFilterIterator { * @return bool */ public function accept() { - return !in_array( + return !\in_array( $this->current()->getPathName(), $this->excludedFolders, true diff --git a/lib/private/L10N/L10N.php b/lib/private/L10N/L10N.php index e9e720a3766..a9b1b7377aa 100644 --- a/lib/private/L10N/L10N.php +++ b/lib/private/L10N/L10N.php @@ -1,4 +1,5 @@ <?php +declare(strict_types=1); /** * @copyright Copyright (c) 2016, ownCloud, Inc. * @@ -60,7 +61,6 @@ class L10N implements IL10N { $this->app = $app; $this->lang = $lang; - $this->translations = []; foreach ($files as $languageFile) { $this->load($languageFile); } @@ -71,20 +71,24 @@ class L10N implements IL10N { * * @return string language */ - public function getLanguageCode() { + public function getLanguageCode(): string { return $this->lang; } /** * Translating * @param string $text The text we need a translation for - * @param array $parameters default:array() Parameters for sprintf + * @param array|string $parameters default:array() Parameters for sprintf * @return string Translation or the same text * * Returns the translation. If no translation is found, $text will be * returned. */ - public function t($text, $parameters = array()) { + public function t(string $text, $parameters = []): string { + if (!\is_array($parameters)) { + $parameters = [$parameters]; + } + return (string) new L10NString($this, $text, $parameters); } @@ -103,17 +107,17 @@ class L10N implements IL10N { * provided by the po file. * */ - public function n($text_singular, $text_plural, $count, $parameters = array()) { + public function n(string $text_singular, string $text_plural, int $count, array $parameters = []): string { $identifier = "_${text_singular}_::_${text_plural}_"; if (isset($this->translations[$identifier])) { return (string) new L10NString($this, $identifier, $parameters, $count); - } else { - if ($count === 1) { - return (string) new L10NString($this, $text_singular, $parameters, $count); - } else { - return (string) new L10NString($this, $text_plural, $parameters, $count); - } } + + if ($count === 1) { + return (string) new L10NString($this, $text_singular, $parameters, $count); + } + + return (string) new L10NString($this, $text_plural, $parameters, $count); } /** @@ -138,7 +142,7 @@ class L10N implements IL10N { * - firstday: Returns the first day of the week (0 sunday - 6 saturday) * - jsdate: Returns the short JS date format */ - public function l($type, $data = null, $options = array()) { + public function l(string $type, $data = null, array $options = []) { // Use the language of the instance $locale = $this->getLanguageCode(); if ($locale === 'sr@latin') { @@ -155,14 +159,15 @@ class L10N implements IL10N { $value = new \DateTime(); if ($data instanceof \DateTime) { $value = $data; - } else if (is_string($data) && !is_numeric($data)) { + } else if (\is_string($data) && !is_numeric($data)) { $data = strtotime($data); $value->setTimestamp($data); } else if ($data !== null) { + $data = (int)$data; $value->setTimestamp($data); } - $options = array_merge(array('width' => 'long'), $options); + $options = array_merge(['width' => 'long'], $options); $width = $options['width']; switch ($type) { case 'date': @@ -184,7 +189,7 @@ class L10N implements IL10N { * Called by \OC_L10N_String * @return array */ - public function getTranslations() { + public function getTranslations(): array { return $this->translations; } @@ -192,10 +197,10 @@ class L10N implements IL10N { * Returnsed function accepts the argument $n * * Called by \OC_L10N_String - * @return string the plural form function + * @return \Closure the plural form function */ - public function getPluralFormFunction() { - if (is_null($this->pluralFormFunction)) { + public function getPluralFormFunction(): \Closure { + if (\is_null($this->pluralFormFunction)) { $lang = $this->getLanguageCode(); $this->pluralFormFunction = function($n) use ($lang) { return PluralizationRules::get($n, $lang); @@ -206,12 +211,12 @@ class L10N implements IL10N { } /** - * @param $translationFile + * @param string $translationFile * @return bool */ - protected function load($translationFile) { + protected function load(string $translationFile): bool { $json = json_decode(file_get_contents($translationFile), true); - if (!is_array($json)) { + if (!\is_array($json)) { $jsonError = json_last_error(); \OC::$server->getLogger()->warning("Failed to load $translationFile - json error code: $jsonError", ['app' => 'l10n']); return false; diff --git a/lib/private/NavigationManager.php b/lib/private/NavigationManager.php index 31d147a3b80..279c899c5fa 100644 --- a/lib/private/NavigationManager.php +++ b/lib/private/NavigationManager.php @@ -104,26 +104,61 @@ class NavigationManager implements INavigationManager { } /** - * returns all the added Menu entries - * @param string $type - * @return array an array of the added entries + * Get a list of navigation entries + * + * @param string $type type of the navigation entries + * @return array */ - public function getAll($type = 'link') { + public function getAll(string $type = 'link'): array { $this->init(); foreach ($this->closureEntries as $c) { $this->add($c()); } $this->closureEntries = array(); - if ($type === 'all') { - return $this->entries; + $result = $this->entries; + if ($type !== 'all') { + $result = array_filter($this->entries, function($entry) use ($type) { + return $entry['type'] === $type; + }); } - return array_filter($this->entries, function($entry) use ($type) { - return $entry['type'] === $type; + return $this->proceedNavigation($result); + } + + /** + * Sort navigation entries by order, name and set active flag + * + * @param array $list + * @return array + */ + private function proceedNavigation(array $list): array { + usort($list, function($a, $b) { + if (isset($a['order']) && isset($b['order'])) { + return ($a['order'] < $b['order']) ? -1 : 1; + } else if (isset($a['order']) || isset($b['order'])) { + return isset($a['order']) ? -1 : 1; + } else { + return ($a['name'] < $b['name']) ? -1 : 1; + } }); + + $activeApp = $this->getActiveEntry(); + if ($activeApp !== null) { + foreach ($list as $index => &$navEntry) { + if ($navEntry['id'] == $activeApp) { + $navEntry['active'] = true; + } else { + $navEntry['active'] = false; + } + } + unset($navEntry); + } + + return $list; } + /** * removes all the entries */ diff --git a/lib/private/Repair.php b/lib/private/Repair.php index d787a1c802b..a257ef061e7 100644 --- a/lib/private/Repair.php +++ b/lib/private/Repair.php @@ -30,8 +30,6 @@ namespace OC; -use OC\App\AppStore\Bundles\BundleFetcher; -use OC\Files\AppData\Factory; use OC\Repair\CleanTags; use OC\Repair\ClearFrontendCaches; use OC\Repair\Collation; diff --git a/lib/private/Repair/Collation.php b/lib/private/Repair/Collation.php index 2642985371b..f2cc9373176 100644 --- a/lib/private/Repair/Collation.php +++ b/lib/private/Repair/Collation.php @@ -6,6 +6,7 @@ * @author Morris Jobke <hey@morrisjobke.de> * @author Robin Appelman <robin@icewind.nl> * @author Thomas Müller <thomas.mueller@tmit.eu> + * @author Robin Müller <robin.mueller@1und1.de> * * @license AGPL-3.0 * @@ -124,7 +125,7 @@ class Collation implements IRepairStep { " FROM INFORMATION_SCHEMA . COLUMNS" . " WHERE TABLE_SCHEMA = ?" . " AND (COLLATION_NAME <> '" . $characterSet . "_bin' OR CHARACTER_SET_NAME <> '" . $characterSet . "')" . - " AND TABLE_NAME LIKE \"*PREFIX*%\"", + " AND TABLE_NAME LIKE '*PREFIX*%'", array($dbName) ); $rows = $statement->fetchAll(); @@ -139,7 +140,7 @@ class Collation implements IRepairStep { " FROM INFORMATION_SCHEMA . TABLES" . " WHERE TABLE_SCHEMA = ?" . " AND TABLE_COLLATION <> '" . $characterSet . "_bin'" . - " AND TABLE_NAME LIKE \"*PREFIX*%\"", + " AND TABLE_NAME LIKE '*PREFIX*%'", [$dbName] ); $rows = $statement->fetchAll(); diff --git a/lib/private/Server.php b/lib/private/Server.php index 228f0ab5f97..d586bab15b9 100644 --- a/lib/private/Server.php +++ b/lib/private/Server.php @@ -814,7 +814,7 @@ class Server extends ServerContainer implements IServerContainer { 'cookies' => $_COOKIE, 'method' => (isset($_SERVER) && isset($_SERVER['REQUEST_METHOD'])) ? $_SERVER['REQUEST_METHOD'] - : null, + : '', 'urlParams' => $urlParams, ], $this->getSecureRandom(), diff --git a/lib/private/Share/Share.php b/lib/private/Share/Share.php index 1798969ca53..e6056679c1c 100644 --- a/lib/private/Share/Share.php +++ b/lib/private/Share/Share.php @@ -39,12 +39,7 @@ namespace OC\Share; -use OC\Files\Filesystem; use OCP\DB\QueryBuilder\IQueryBuilder; -use OCP\ILogger; -use OCP\IUserManager; -use OCP\IUserSession; -use OCP\IDBConnection; use OCP\IConfig; use OCP\Util; diff --git a/lib/private/Share20/DefaultShareProvider.php b/lib/private/Share20/DefaultShareProvider.php index b9ab7a46873..3c56b24707c 100644 --- a/lib/private/Share20/DefaultShareProvider.php +++ b/lib/private/Share20/DefaultShareProvider.php @@ -30,7 +30,6 @@ namespace OC\Share20; use OC\Files\Cache\Cache; -use OCP\Files\File; use OCP\Files\Folder; use OCP\Share\IShareProvider; use OC\Share20\Exception\InvalidShare; diff --git a/lib/private/SystemTag/ManagerFactory.php b/lib/private/SystemTag/ManagerFactory.php index 12af2523f47..839a819a04a 100644 --- a/lib/private/SystemTag/ManagerFactory.php +++ b/lib/private/SystemTag/ManagerFactory.php @@ -1,4 +1,5 @@ <?php +declare(strict_types=1); /** * @copyright Copyright (c) 2016, ownCloud, Inc. * @@ -57,7 +58,7 @@ class ManagerFactory implements ISystemTagManagerFactory { * @return ISystemTagManager * @since 9.0.0 */ - public function getManager() { + public function getManager(): ISystemTagManager { return new SystemTagManager( $this->serverContainer->getDatabaseConnection(), $this->serverContainer->getGroupManager(), @@ -72,7 +73,7 @@ class ManagerFactory implements ISystemTagManagerFactory { * @return ISystemTagObjectMapper * @since 9.0.0 */ - public function getObjectMapper() { + public function getObjectMapper(): ISystemTagObjectMapper { return new SystemTagObjectMapper( $this->serverContainer->getDatabaseConnection(), $this->getManager(), diff --git a/lib/private/SystemTag/SystemTag.php b/lib/private/SystemTag/SystemTag.php index 15eb15efd9e..3b0cf23c9a8 100644 --- a/lib/private/SystemTag/SystemTag.php +++ b/lib/private/SystemTag/SystemTag.php @@ -1,4 +1,5 @@ <?php +declare(strict_types=1); /** * @copyright Copyright (c) 2016, ownCloud, Inc. * @@ -55,7 +56,7 @@ class SystemTag implements ISystemTag { * @param bool $userVisible whether the tag is user visible * @param bool $userAssignable whether the tag is user assignable */ - public function __construct($id, $name, $userVisible, $userAssignable) { + public function __construct(string $id, string $name, bool $userVisible, bool $userAssignable) { $this->id = $id; $this->name = $name; $this->userVisible = $userVisible; @@ -65,28 +66,28 @@ class SystemTag implements ISystemTag { /** * {@inheritdoc} */ - public function getId() { + public function getId(): string { return $this->id; } /** * {@inheritdoc} */ - public function getName() { + public function getName(): string { return $this->name; } /** * {@inheritdoc} */ - public function isUserVisible() { + public function isUserVisible(): bool { return $this->userVisible; } /** * {@inheritdoc} */ - public function isUserAssignable() { + public function isUserAssignable(): bool { return $this->userAssignable; } } diff --git a/lib/private/SystemTag/SystemTagManager.php b/lib/private/SystemTag/SystemTagManager.php index 642ce515801..055b744e5c3 100644 --- a/lib/private/SystemTag/SystemTagManager.php +++ b/lib/private/SystemTag/SystemTagManager.php @@ -1,4 +1,5 @@ <?php +declare(strict_types=1); /** * @copyright Copyright (c) 2016, ownCloud, Inc. * @@ -65,6 +66,7 @@ class SystemTagManager implements ISystemTagManager { * Constructor. * * @param IDBConnection $connection database connection + * @param IGroupManager $groupManager * @param EventDispatcherInterface $dispatcher */ public function __construct( @@ -87,8 +89,8 @@ class SystemTagManager implements ISystemTagManager { /** * {@inheritdoc} */ - public function getTagsByIds($tagIds) { - if (!is_array($tagIds)) { + public function getTagsByIds($tagIds): array { + if (!\is_array($tagIds)) { $tagIds = [$tagIds]; } @@ -117,7 +119,7 @@ class SystemTagManager implements ISystemTagManager { $result->closeCursor(); - if (count($tags) !== count($tagIds)) { + if (\count($tags) !== \count($tagIds)) { throw new TagNotFoundException( 'Tag id(s) not found', 0, null, array_diff($tagIds, array_keys($tags)) ); @@ -129,14 +131,14 @@ class SystemTagManager implements ISystemTagManager { /** * {@inheritdoc} */ - public function getAllTags($visibilityFilter = null, $nameSearchPattern = null) { + public function getAllTags($visibilityFilter = null, $nameSearchPattern = null): array { $tags = []; $query = $this->connection->getQueryBuilder(); $query->select('*') ->from(self::TAG_TABLE); - if (!is_null($visibilityFilter)) { + if (!\is_null($visibilityFilter)) { $query->andWhere($query->expr()->eq('visibility', $query->createNamedParameter((int)$visibilityFilter))); } @@ -167,14 +169,11 @@ class SystemTagManager implements ISystemTagManager { /** * {@inheritdoc} */ - public function getTag($tagName, $userVisible, $userAssignable) { - $userVisible = (int)$userVisible; - $userAssignable = (int)$userAssignable; - + public function getTag(string $tagName, bool $userVisible, bool $userAssignable): ISystemTag { $result = $this->selectTagQuery ->setParameter('name', $tagName) - ->setParameter('visibility', $userVisible) - ->setParameter('editable', $userAssignable) + ->setParameter('visibility', $userVisible ? 1 : 0) + ->setParameter('editable', $userAssignable ? 1 : 0) ->execute(); $row = $result->fetch(); @@ -191,16 +190,13 @@ class SystemTagManager implements ISystemTagManager { /** * {@inheritdoc} */ - public function createTag($tagName, $userVisible, $userAssignable) { - $userVisible = (int)$userVisible; - $userAssignable = (int)$userAssignable; - + public function createTag(string $tagName, bool $userVisible, bool $userAssignable): ISystemTag { $query = $this->connection->getQueryBuilder(); $query->insert(self::TAG_TABLE) ->values([ 'name' => $query->createNamedParameter($tagName), - 'visibility' => $query->createNamedParameter($userVisible), - 'editable' => $query->createNamedParameter($userAssignable), + 'visibility' => $query->createNamedParameter($userVisible ? 1 : 0), + 'editable' => $query->createNamedParameter($userAssignable ? 1 : 0), ]); try { @@ -216,10 +212,10 @@ class SystemTagManager implements ISystemTagManager { $tagId = $query->getLastInsertId(); $tag = new SystemTag( - (int)$tagId, + (string)$tagId, $tagName, - (bool)$userVisible, - (bool)$userAssignable + $userVisible, + $userAssignable ); $this->dispatcher->dispatch(ManagerEvent::EVENT_CREATE, new ManagerEvent( @@ -232,10 +228,7 @@ class SystemTagManager implements ISystemTagManager { /** * {@inheritdoc} */ - public function updateTag($tagId, $tagName, $userVisible, $userAssignable) { - $userVisible = (int)$userVisible; - $userAssignable = (int)$userAssignable; - + public function updateTag(string $tagId, string $tagName, bool $userVisible, bool $userAssignable) { try { $tags = $this->getTagsByIds($tagId); } catch (TagNotFoundException $e) { @@ -246,10 +239,10 @@ class SystemTagManager implements ISystemTagManager { $beforeUpdate = array_shift($tags); $afterUpdate = new SystemTag( - (int) $tagId, + $tagId, $tagName, - (bool) $userVisible, - (bool) $userAssignable + $userVisible, + $userAssignable ); $query = $this->connection->getQueryBuilder(); @@ -259,8 +252,8 @@ class SystemTagManager implements ISystemTagManager { ->set('editable', $query->createParameter('editable')) ->where($query->expr()->eq('id', $query->createParameter('tagid'))) ->setParameter('name', $tagName) - ->setParameter('visibility', $userVisible) - ->setParameter('editable', $userAssignable) + ->setParameter('visibility', $userVisible ? 1 : 0) + ->setParameter('editable', $userAssignable ? 1 : 0) ->setParameter('tagid', $tagId); try { @@ -286,7 +279,7 @@ class SystemTagManager implements ISystemTagManager { * {@inheritdoc} */ public function deleteTags($tagIds) { - if (!is_array($tagIds)) { + if (!\is_array($tagIds)) { $tagIds = [$tagIds]; } @@ -337,7 +330,7 @@ class SystemTagManager implements ISystemTagManager { /** * {@inheritdoc} */ - public function canUserAssignTag(ISystemTag $tag, IUser $user) { + public function canUserAssignTag(ISystemTag $tag, IUser $user): bool { // early check to avoid unneeded group lookups if ($tag->isUserAssignable() && $tag->isUserVisible()) { return true; @@ -365,7 +358,7 @@ class SystemTagManager implements ISystemTagManager { /** * {@inheritdoc} */ - public function canUserSeeTag(ISystemTag $tag, IUser $user) { + public function canUserSeeTag(ISystemTag $tag, IUser $user): bool { if ($tag->isUserVisible()) { return true; } @@ -378,13 +371,13 @@ class SystemTagManager implements ISystemTagManager { } private function createSystemTagFromRow($row) { - return new SystemTag((int)$row['id'], $row['name'], (bool)$row['visibility'], (bool)$row['editable']); + return new SystemTag((string)$row['id'], $row['name'], (bool)$row['visibility'], (bool)$row['editable']); } /** * {@inheritdoc} */ - public function setTagGroups(ISystemTag $tag, $groupIds) { + public function setTagGroups(ISystemTag $tag, array $groupIds) { // delete relationships first $this->connection->beginTransaction(); try { @@ -418,7 +411,7 @@ class SystemTagManager implements ISystemTagManager { /** * {@inheritdoc} */ - public function getTagGroups(ISystemTag $tag) { + public function getTagGroups(ISystemTag $tag): array { $groupIds = []; $query = $this->connection->getQueryBuilder(); $query->select('gid') diff --git a/lib/private/SystemTag/SystemTagObjectMapper.php b/lib/private/SystemTag/SystemTagObjectMapper.php index 75bf37c652c..8ecc46b4357 100644 --- a/lib/private/SystemTag/SystemTagObjectMapper.php +++ b/lib/private/SystemTag/SystemTagObjectMapper.php @@ -1,4 +1,5 @@ <?php +declare(strict_types=1); /** * @copyright Copyright (c) 2016, ownCloud, Inc. * @@ -63,8 +64,8 @@ class SystemTagObjectMapper implements ISystemTagObjectMapper { /** * {@inheritdoc} */ - public function getTagIdsForObjects($objIds, $objectType) { - if (!is_array($objIds)) { + public function getTagIdsForObjects($objIds, string $objectType): array { + if (!\is_array($objIds)) { $objIds = [$objIds]; } else if (empty($objIds)) { return []; @@ -99,8 +100,8 @@ class SystemTagObjectMapper implements ISystemTagObjectMapper { /** * {@inheritdoc} */ - public function getObjectIdsForTags($tagIds, $objectType, $limit = 0, $offset = '') { - if (!is_array($tagIds)) { + public function getObjectIdsForTags($tagIds, string $objectType, int $limit = 0, string $offset = ''): array { + if (!\is_array($tagIds)) { $tagIds = [$tagIds]; } @@ -113,7 +114,7 @@ class SystemTagObjectMapper implements ISystemTagObjectMapper { ->andWhere($query->expr()->eq('objecttype', $query->createNamedParameter($objectType))); if ($limit) { - if (count($tagIds) !== 1) { + if (\count($tagIds) !== 1) { throw new \InvalidArgumentException('Limit is only allowed with a single tag'); } @@ -138,8 +139,8 @@ class SystemTagObjectMapper implements ISystemTagObjectMapper { /** * {@inheritdoc} */ - public function assignTags($objId, $objectType, $tagIds) { - if (!is_array($tagIds)) { + public function assignTags(string $objId, string $objectType, $tagIds) { + if (!\is_array($tagIds)) { $tagIds = [$tagIds]; } @@ -173,8 +174,8 @@ class SystemTagObjectMapper implements ISystemTagObjectMapper { /** * {@inheritdoc} */ - public function unassignTags($objId, $objectType, $tagIds) { - if (!is_array($tagIds)) { + public function unassignTags(string $objId, string $objectType, $tagIds) { + if (!\is_array($tagIds)) { $tagIds = [$tagIds]; } @@ -201,10 +202,10 @@ class SystemTagObjectMapper implements ISystemTagObjectMapper { /** * {@inheritdoc} */ - public function haveTag($objIds, $objectType, $tagId, $all = true) { + public function haveTag($objIds, string $objectType, string $tagId, bool $all = true): bool { $this->assertTagsExist([$tagId]); - if (!is_array($objIds)) { + if (!\is_array($objIds)) { $objIds = [$objIds]; } @@ -232,10 +233,10 @@ class SystemTagObjectMapper implements ISystemTagObjectMapper { $result->closeCursor(); if ($all) { - return ((int)$row[0] === count($objIds)); - } else { - return (bool) $row; + return ((int)$row[0] === \count($objIds)); } + + return (bool) $row; } /** @@ -247,7 +248,7 @@ class SystemTagObjectMapper implements ISystemTagObjectMapper { */ private function assertTagsExist($tagIds) { $tags = $this->tagManager->getTagsByIds($tagIds); - if (count($tags) !== count($tagIds)) { + if (\count($tags) !== \count($tagIds)) { // at least one tag missing, bail out $foundTagIds = array_map( function(ISystemTag $tag) { diff --git a/lib/private/TemplateLayout.php b/lib/private/TemplateLayout.php index d37a8bbabbe..8cc235bf818 100644 --- a/lib/private/TemplateLayout.php +++ b/lib/private/TemplateLayout.php @@ -80,9 +80,9 @@ class TemplateLayout extends \OC_Template { // Add navigation entry $this->assign( 'application', ''); $this->assign( 'appid', $appId ); - $navigation = \OC_App::getNavigation(); + $navigation = \OC::$server->getNavigationManager()->getAll(); $this->assign( 'navigation', $navigation); - $settingsNavigation = \OC_App::getSettingsNavigation(); + $settingsNavigation = \OC::$server->getNavigationManager()->getAll('settings'); $this->assign( 'settingsnavigation', $settingsNavigation); foreach($navigation as $entry) { if ($entry['active']) { diff --git a/lib/private/Updater.php b/lib/private/Updater.php index 43096e7c1f8..c70113e1c7d 100644 --- a/lib/private/Updater.php +++ b/lib/private/Updater.php @@ -250,7 +250,7 @@ class Updater extends BasicEmitter { $this->upgradeAppStoreApps(\OC::$server->getAppManager()->getInstalledApps()); // install new shipped apps on upgrade - OC_App::loadApps('authentication'); + OC_App::loadApps(['authentication']); $errors = Installer::installShippedApps(true); foreach ($errors as $appId => $exception) { /** @var \Exception $exception */ @@ -346,7 +346,7 @@ class Updater extends BasicEmitter { if(!isset($stacks[$type])) { $stacks[$type] = array(); } - if (\OC_App::isType($appId, $type)) { + if (\OC_App::isType($appId, [$type])) { $stacks[$type][] = $appId; $priorityType = true; break; @@ -385,7 +385,7 @@ class Updater extends BasicEmitter { private function checkAppsRequirements() { $isCoreUpgrade = $this->isCodeUpgrade(); $apps = OC_App::getEnabledApps(); - $version = Util::getVersion(); + $version = implode('.', Util::getVersion()); $disabledApps = []; $appManager = \OC::$server->getAppManager(); foreach ($apps as $app) { diff --git a/lib/private/User/Session.php b/lib/private/User/Session.php index c2b58c37cdb..4ac8888cee1 100644 --- a/lib/private/User/Session.php +++ b/lib/private/User/Session.php @@ -55,7 +55,6 @@ use OCP\ILogger; use OCP\IRequest; use OCP\ISession; use OCP\IUser; -use OCP\IUserManager; use OCP\IUserSession; use OCP\Lockdown\ILockdownManager; use OCP\Security\ISecureRandom; diff --git a/lib/private/legacy/app.php b/lib/private/legacy/app.php index b19d63f560e..16e57d43ebc 100644 --- a/lib/private/legacy/app.php +++ b/lib/private/legacy/app.php @@ -1,4 +1,5 @@ <?php +declare(strict_types=1); /** * @copyright Copyright (c) 2016, ownCloud, Inc. * @copyright Copyright (c) 2016, Lukas Reschke <lukas@statuscode.ch> @@ -62,21 +63,21 @@ use OCP\App\ManagerEvent; * upgrading and removing apps. */ class OC_App { - static private $adminForms = array(); - static private $personalForms = array(); - static private $appTypes = array(); - static private $loadedApps = array(); - static private $altLogin = array(); + static private $adminForms = []; + static private $personalForms = []; + static private $appTypes = []; + static private $loadedApps = []; + static private $altLogin = []; static private $alreadyRegistered = []; const officialApp = 200; /** * clean the appId * - * @param string|boolean $app AppId that needs to be cleaned + * @param string $app AppId that needs to be cleaned * @return string */ - public static function cleanAppId($app) { + public static function cleanAppId(string $app): string { return str_replace(array('\0', '/', '\\', '..'), '', $app); } @@ -86,23 +87,23 @@ class OC_App { * @param string $app * @return bool */ - public static function isAppLoaded($app) { + public static function isAppLoaded(string $app): bool { return in_array($app, self::$loadedApps, true); } /** * loads all apps * - * @param string[] | string | null $types + * @param string[] $types * @return bool * * This function walks through the ownCloud directory and loads all apps * it can find. A directory contains an app if the file /appinfo/info.xml * exists. * - * if $types is set, only apps of those types will be loaded + * if $types is set to non-empty array, only apps of those types will be loaded */ - public static function loadApps($types = null) { + public static function loadApps(array $types = []): bool { if (\OC::$server->getSystemConfig()->getValue('maintenance', false)) { return false; } @@ -120,7 +121,7 @@ class OC_App { // prevent app.php from printing output ob_start(); foreach ($apps as $app) { - if ((is_null($types) or self::isType($app, $types)) && !in_array($app, self::$loadedApps)) { + if (($types === [] or self::isType($app, $types)) && !in_array($app, self::$loadedApps)) { self::loadApp($app); } } @@ -133,8 +134,9 @@ class OC_App { * load a single app * * @param string $app + * @throws Exception */ - public static function loadApp($app) { + public static function loadApp(string $app) { self::$loadedApps[] = $app; $appPath = self::getAppPath($app); if($appPath === false) { @@ -146,13 +148,21 @@ class OC_App { if (is_file($appPath . '/appinfo/app.php')) { \OC::$server->getEventLogger()->start('load_app_' . $app, 'Load app: ' . $app); - self::requireAppFile($app); + try { + self::requireAppFile($app); + } catch (Error $ex) { + \OC::$server->getLogger()->logException($ex); + if (!\OC::$server->getAppManager()->isShipped($app)) { + // Only disable apps which are not shipped + self::disable($app); + } + } if (self::isType($app, array('authentication'))) { // since authentication apps affect the "is app enabled for group" check, // the enabled apps cache needs to be cleared to make sure that the // next time getEnableApps() is called it will also include apps that were // enabled for groups - self::$enabledAppsCache = array(); + self::$enabledAppsCache = []; } \OC::$server->getEventLogger()->end('load_app_' . $app); } @@ -218,7 +228,7 @@ class OC_App { * @param string $app * @param string $path */ - public static function registerAutoloading($app, $path) { + public static function registerAutoloading(string $app, string $path) { $key = $app . '-' . $path; if(isset(self::$alreadyRegistered[$key])) { return; @@ -248,31 +258,21 @@ class OC_App { * Load app.php from the given app * * @param string $app app name + * @throws Error */ - private static function requireAppFile($app) { - try { - // encapsulated here to avoid variable scope conflicts - require_once $app . '/appinfo/app.php'; - } catch (Error $ex) { - \OC::$server->getLogger()->logException($ex); - if (!\OC::$server->getAppManager()->isShipped($app)) { - // Only disable apps which are not shipped - self::disable($app); - } - } + private static function requireAppFile(string $app) { + // encapsulated here to avoid variable scope conflicts + require_once $app . '/appinfo/app.php'; } /** * check if an app is of a specific type * * @param string $app - * @param string|array $types + * @param array $types * @return bool */ - public static function isType($app, $types) { - if (is_string($types)) { - $types = array($types); - } + public static function isType(string $app, array $types): bool { $appTypes = self::getAppTypes($app); foreach ($types as $type) { if (array_search($type, $appTypes) !== false) { @@ -288,7 +288,7 @@ class OC_App { * @param string $app * @return array */ - private static function getAppTypes($app) { + private static function getAppTypes(string $app): array { //load the cache if (count(self::$appTypes) == 0) { self::$appTypes = \OC::$server->getAppConfig()->getValues(false, 'types'); @@ -296,16 +296,17 @@ class OC_App { if (isset(self::$appTypes[$app])) { return explode(',', self::$appTypes[$app]); - } else { - return array(); } + + return []; } /** * read app types from info.xml and cache them in the database */ - public static function setAppTypes($app) { - $appData = self::getAppInfo($app); + public static function setAppTypes(string $app) { + $appManager = \OC::$server->getAppManager(); + $appData = $appManager->getAppInfo($app); if(!is_array($appData)) { return; } @@ -317,12 +318,13 @@ class OC_App { $appData['types'] = []; } - \OC::$server->getConfig()->setAppValue($app, 'types', $appTypes); + $config = \OC::$server->getConfig(); + $config->setAppValue($app, 'types', $appTypes); - if (\OC::$server->getAppManager()->hasProtectedAppType($appData['types'])) { - $enabled = \OC::$server->getConfig()->getAppValue($app, 'enabled', 'yes'); + if ($appManager->hasProtectedAppType($appData['types'])) { + $enabled = $config->getAppValue($app, 'enabled', 'yes'); if ($enabled !== 'yes' && $enabled !== 'no') { - \OC::$server->getConfig()->setAppValue($app, 'enabled', 'yes'); + $config->setAppValue($app, 'enabled', 'yes'); } } } @@ -330,7 +332,7 @@ class OC_App { /** * get all enabled apps */ - protected static $enabledAppsCache = array(); + protected static $enabledAppsCache = []; /** * Returns apps enabled for the current user. @@ -340,9 +342,9 @@ class OC_App { * currently logged in one * @return string[] */ - public static function getEnabledApps($forceRefresh = false, $all = false) { + public static function getEnabledApps(bool $forceRefresh = false, bool $all = false): array { if (!\OC::$server->getSystemConfig()->getValue('installed', false)) { - return array(); + return []; } // in incognito mode or when logged out, $user will be false, // which is also the case during an upgrade @@ -375,7 +377,7 @@ class OC_App { * * This function checks whether or not an app is enabled. */ - public static function isEnabled($app) { + public static function isEnabled(string $app): bool { return \OC::$server->getAppManager()->isEnabledForUser($app); } @@ -389,8 +391,8 @@ class OC_App { * * This function set an app as enabled in appconfig. */ - public function enable($appId, - $groups = null) { + public function enable(string $appId, + array $groups = []) { self::$enabledAppsCache = []; // flush // Check if app is already downloaded @@ -404,7 +406,7 @@ class OC_App { $installer->installApp($appId); $appManager = \OC::$server->getAppManager(); - if (!is_null($groups)) { + if ($groups !== []) { $groupManager = \OC::$server->getGroupManager(); $groupsList = []; foreach ($groups as $group) { @@ -425,9 +427,9 @@ class OC_App { * @param string $app app * @throws Exception */ - public static function disable($app) { + public static function disable(string $app) { // flush - self::$enabledAppsCache = array(); + self::$enabledAppsCache = []; // run uninstall steps $appData = OC_App::getAppInfo($app); @@ -443,31 +445,6 @@ class OC_App { $appManager->disableApp($app); } - // This is private as well. It simply works, so don't ask for more details - private static function proceedNavigation($list) { - usort($list, function($a, $b) { - if (isset($a['order']) && isset($b['order'])) { - return ($a['order'] < $b['order']) ? -1 : 1; - } else if (isset($a['order']) || isset($b['order'])) { - return isset($a['order']) ? -1 : 1; - } else { - return ($a['name'] < $b['name']) ? -1 : 1; - } - }); - - $activeApp = OC::$server->getNavigationManager()->getActiveEntry(); - foreach ($list as $index => &$navEntry) { - if ($navEntry['id'] == $activeApp) { - $navEntry['active'] = true; - } else { - $navEntry['active'] = false; - } - } - unset($navEntry); - - return $list; - } - /** * Get the path where to install apps * @@ -495,18 +472,18 @@ class OC_App { * @param string $appId * @return false|string */ - public static function findAppInDirectories($appId) { + public static function findAppInDirectories(string $appId) { $sanitizedAppId = self::cleanAppId($appId); if($sanitizedAppId !== $appId) { return false; } - static $app_dir = array(); + static $app_dir = []; if (isset($app_dir[$appId])) { return $app_dir[$appId]; } - $possibleApps = array(); + $possibleApps = []; foreach (OC::$APPSROOTS as $dir) { if (file_exists($dir['path'] . '/' . $appId)) { $possibleApps[] = $dir; @@ -520,7 +497,7 @@ class OC_App { $app_dir[$appId] = $dir; return $dir; } else { - $versionToLoad = array(); + $versionToLoad = []; foreach ($possibleApps as $possibleApp) { $version = self::getAppVersionByPath($possibleApp['path']); if (empty($versionToLoad) || version_compare($version, $versionToLoad['version'], '>')) { @@ -543,7 +520,7 @@ class OC_App { * @param string $appId * @return string|false */ - public static function getAppPath($appId) { + public static function getAppPath(string $appId) { if ($appId === null || trim($appId) === '') { return false; } @@ -561,7 +538,7 @@ class OC_App { * @param string $appId * @return string|false */ - public static function getAppWebPath($appId) { + public static function getAppWebPath(string $appId) { if (($dir = self::findAppInDirectories($appId)) != false) { return OC::$WEBROOT . $dir['url'] . '/' . $appId; } @@ -576,7 +553,7 @@ class OC_App { * @return string * @deprecated 14.0.0 use \OC::$server->getAppManager()->getAppVersion() */ - public static function getAppVersion($appId, $useCache = true) { + public static function getAppVersion(string $appId, bool $useCache = true): string { return \OC::$server->getAppManager()->getAppVersion($appId, $useCache); } @@ -586,7 +563,7 @@ class OC_App { * @param string $path * @return string */ - public static function getAppVersionByPath($path) { + public static function getAppVersionByPath(string $path): string { $infoFile = $path . '/appinfo/info.xml'; $appData = \OC::$server->getAppManager()->getAppInfo($infoFile, true); return isset($appData['version']) ? $appData['version'] : ''; @@ -603,7 +580,7 @@ class OC_App { * @note all data is read from info.xml, not just pre-defined fields * @deprecated 14.0.0 use \OC::$server->getAppManager()->getAppInfo() */ - public static function getAppInfo($appId, $path = false, $lang = null) { + public static function getAppInfo(string $appId, bool $path = false, string $lang = null) { return \OC::$server->getAppManager()->getAppInfo($appId, $path, $lang); } @@ -611,28 +588,28 @@ class OC_App { * Returns the navigation * * @return array + * @deprecated 14.0.0 use \OC::$server->getNavigationManager()->getAll() * * This function returns an array containing all entries added. The * entries are sorted by the key 'order' ascending. Additional to the keys * given for each app the following keys exist: * - active: boolean, signals if the user is on this navigation entry */ - public static function getNavigation() { - $entries = OC::$server->getNavigationManager()->getAll(); - return self::proceedNavigation($entries); + public static function getNavigation(): array { + return OC::$server->getNavigationManager()->getAll(); } /** * Returns the Settings Navigation * * @return string[] + * @deprecated 14.0.0 use \OC::$server->getNavigationManager()->getAll('settings') * * This function returns an array containing all settings pages added. The * entries are sorted by the key 'order' ascending. */ - public static function getSettingsNavigation() { - $entries = OC::$server->getNavigationManager()->getAll('settings'); - return self::proceedNavigation($entries); + public static function getSettingsNavigation(): array { + return OC::$server->getNavigationManager()->getAll('settings'); } /** @@ -640,7 +617,7 @@ class OC_App { * * @return string */ - public static function getCurrentApp() { + public static function getCurrentApp(): string { $request = \OC::$server->getRequest(); $script = substr($request->getScriptName(), strlen(OC::$WEBROOT) + 1); $topFolder = substr($script, 0, strpos($script, '/') ?: 0); @@ -652,7 +629,7 @@ class OC_App { } if ($topFolder == 'apps') { $length = strlen($topFolder); - return substr($script, $length + 1, strpos($script, '/', $length + 1) - $length - 1); + return substr($script, $length + 1, strpos($script, '/', $length + 1) - $length - 1) ?: ''; } else { return $topFolder; } @@ -662,8 +639,8 @@ class OC_App { * @param string $type * @return array */ - public static function getForms($type) { - $forms = array(); + public static function getForms(string $type): array { + $forms = []; switch ($type) { case 'admin': $source = self::$adminForms; @@ -672,7 +649,7 @@ class OC_App { $source = self::$personalForms; break; default: - return array(); + return []; } foreach ($source as $form) { $forms[] = include $form; @@ -686,7 +663,7 @@ class OC_App { * @param string $app * @param string $page */ - public static function registerAdmin($app, $page) { + public static function registerAdmin(string $app, string $page) { self::$adminForms[] = $app . '/' . $page . '.php'; } @@ -695,7 +672,7 @@ class OC_App { * @param string $app * @param string $page */ - public static function registerPersonal($app, $page) { + public static function registerPersonal(string $app, string $page) { self::$personalForms[] = $app . '/' . $page . '.php'; } @@ -709,7 +686,7 @@ class OC_App { /** * @return array */ - public static function getAlternativeLogIns() { + public static function getAlternativeLogIns(): array { return self::$altLogin; } @@ -719,9 +696,9 @@ class OC_App { * @return array an array of app names (string IDs) * @todo: change the name of this method to getInstalledApps, which is more accurate */ - public static function getAllApps() { + public static function getAllApps(): array { - $apps = array(); + $apps = []; foreach (OC::$APPSROOTS as $apps_dir) { if (!is_readable($apps_dir['path'])) { @@ -751,13 +728,13 @@ class OC_App { * * @return array */ - public function listAllApps() { + public function listAllApps(): array { $installedApps = OC_App::getAllApps(); $appManager = \OC::$server->getAppManager(); //we don't want to show configuration for these $blacklist = $appManager->getAlwaysEnabledApps(); - $appList = array(); + $appList = []; $langCode = \OC::$server->getL10N('core')->getLanguageCode(); $urlGenerator = \OC::$server->getURLGenerator(); @@ -832,7 +809,7 @@ class OC_App { return $appList; } - public static function shouldUpgrade($app) { + public static function shouldUpgrade(string $app): bool { $versions = self::getAppVersions(); $currentVersion = OC_App::getAppVersion($app); if ($currentVersion && isset($versions[$app])) { @@ -852,7 +829,7 @@ class OC_App { * @param string $version2 version to take the number of parts from * @return string shortened $version1 */ - private static function adjustVersionParts($version1, $version2) { + private static function adjustVersionParts(string $version1, string $version2): string { $version1 = explode('.', $version1); $version2 = explode('.', $version2); // reduce $version1 to match the number of parts in $version2 @@ -882,7 +859,7 @@ class OC_App { * * @return boolean true if compatible, otherwise false */ - public static function isAppCompatible($ocVersion, $appInfo) { + public static function isAppCompatible(string $ocVersion, array $appInfo): bool { $requireMin = ''; $requireMax = ''; if (isset($appInfo['dependencies']['nextcloud']['@attributes']['min-version'])) { @@ -903,10 +880,6 @@ class OC_App { $requireMax = $appInfo['requiremax']; } - if (is_array($ocVersion)) { - $ocVersion = implode('.', $ocVersion); - } - if (!empty($requireMin) && version_compare(self::adjustVersionParts($ocVersion, $requireMin), $requireMin, '<') ) { @@ -942,7 +915,7 @@ class OC_App { * @param string $appId * @return bool */ - public static function updateApp($appId) { + public static function updateApp(string $appId): bool { $appPath = self::getAppPath($appId); if($appPath === false) { return false; @@ -1001,7 +974,7 @@ class OC_App { * @param string[] $steps * @throws \OC\NeedsUpdateException */ - public static function executeRepairSteps($appId, array $steps) { + public static function executeRepairSteps(string $appId, array $steps) { if (empty($steps)) { return; } @@ -1035,7 +1008,7 @@ class OC_App { * @param string $appId * @param string[] $steps */ - private static function setupLiveMigrations($appId, array $steps) { + private static function setupLiveMigrations(string $appId, array $steps) { $queue = \OC::$server->getJobList(); foreach ($steps as $step) { $queue->add('OC\Migration\BackgroundRepair', [ @@ -1048,7 +1021,7 @@ class OC_App { * @param string $appId * @return \OC\Files\View|false */ - public static function getStorage($appId) { + public static function getStorage(string $appId) { if (\OC::$server->getAppManager()->isEnabledForUser($appId)) { //sanity check if (\OC::$server->getUserSession()->isLoggedIn()) { $view = new \OC\Files\View('/' . OC_User::getUser()); @@ -1066,7 +1039,7 @@ class OC_App { } } - protected static function findBestL10NOption($options, $lang) { + protected static function findBestL10NOption(array $options, string $lang): string { $fallback = $similarLangFallback = $englishFallback = false; $lang = strtolower($lang); @@ -1118,7 +1091,7 @@ class OC_App { * @param string $lang * @return array improved app data */ - public static function parseAppInfo(array $data, $lang = null) { + public static function parseAppInfo(array $data, $lang = null): array { if ($lang && isset($data['name']) && is_array($data['name'])) { $data['name'] = self::findBestL10NOption($data['name'], $lang); @@ -1143,7 +1116,7 @@ class OC_App { * @param array $info * @throws \Exception */ - public static function checkAppDependencies($config, $l, $info) { + public static function checkAppDependencies(\OCP\IConfig $config, \OCP\IL10N $l, array $info) { $dependencyAnalyzer = new DependencyAnalyzer(new Platform($config), $l); $missing = $dependencyAnalyzer->analyze($info); if (!empty($missing)) { diff --git a/lib/private/legacy/files.php b/lib/private/legacy/files.php index 24324bca095..def9f82fab9 100644 --- a/lib/private/legacy/files.php +++ b/lib/private/legacy/files.php @@ -75,7 +75,9 @@ class OC_Files { private static function sendHeaders($filename, $name, array $rangeArray) { OC_Response::setContentDispositionHeader($name, 'attachment'); header('Content-Transfer-Encoding: binary', true); - OC_Response::disableCaching(); + header('Pragma: public');// enable caching in IE + header('Expires: 0'); + header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); $fileSize = \OC\Files\Filesystem::filesize($filename); $type = \OC::$server->getMimeTypeDetector()->getSecureMimeType(\OC\Files\Filesystem::getMimeType($filename)); if ($fileSize > -1) { diff --git a/lib/private/legacy/response.php b/lib/private/legacy/response.php index 975ff570485..1b0b01de972 100644 --- a/lib/private/legacy/response.php +++ b/lib/private/legacy/response.php @@ -55,7 +55,7 @@ class OC_Response { header('Cache-Control: max-age='.$cache_time.', must-revalidate'); } else { - self::setExpiresHeader(0); + header('Expires: 0'); header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); } } @@ -67,14 +67,6 @@ class OC_Response { } /** - * disable browser caching - * @see enableCaching with cache_time = 0 - */ - static public function disableCaching() { - self::enableCaching(0); - } - - /** * Set response status * @param int $status a HTTP status code, see also the STATUS constants */ |