summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/base.php18
-rw-r--r--lib/composer/composer/autoload_classmap.php6
-rw-r--r--lib/composer/composer/autoload_static.php6
-rw-r--r--lib/private/App/AppStore/Fetcher/AppFetcher.php56
-rw-r--r--lib/private/App/AppStore/Fetcher/CategoryFetcher.php45
-rw-r--r--lib/private/App/AppStore/Fetcher/Fetcher.php92
-rw-r--r--lib/private/App/AppStore/Version/Version.php52
-rw-r--r--lib/private/App/AppStore/Version/VersionParser.php83
-rw-r--r--lib/private/App/DependencyAnalyzer.php9
-rw-r--r--lib/private/AppFramework/DependencyInjection/DIContainer.php1
-rw-r--r--lib/private/Archive/Archive.php21
-rw-r--r--lib/private/Authentication/Token/DefaultToken.php7
-rw-r--r--lib/private/Authentication/Token/DefaultTokenMapper.php17
-rw-r--r--lib/private/Authentication/Token/DefaultTokenProvider.php41
-rw-r--r--lib/private/Authentication/Token/IProvider.php13
-rw-r--r--lib/private/Authentication/Token/IToken.php2
-rw-r--r--lib/private/Authentication/TwoFactorAuth/Manager.php19
-rw-r--r--lib/private/DB/Connection.php6
-rw-r--r--lib/private/DB/QueryBuilder/QueryBuilder.php39
-rw-r--r--lib/private/Installer.php526
-rw-r--r--lib/private/OCSClient.php351
-rw-r--r--lib/private/Security/CSRF/TokenStorage/SessionStorage.php7
-rw-r--r--lib/private/Server.php43
-rw-r--r--lib/private/Setup/MySQL.php24
-rw-r--r--lib/private/Updater.php18
-rw-r--r--lib/private/User/Session.php81
-rw-r--r--lib/private/legacy/app.php245
-rw-r--r--lib/private/legacy/user.php5
-rw-r--r--lib/private/legacy/util.php1
-rw-r--r--lib/public/IRequest.php2
30 files changed, 887 insertions, 949 deletions
diff --git a/lib/base.php b/lib/base.php
index e7bedb69596..909a62040ee 100644
--- a/lib/base.php
+++ b/lib/base.php
@@ -377,6 +377,7 @@ class OC {
\OCP\Util::addScript('update');
\OCP\Util::addStyle('update');
+ /** @var \OCP\App\IAppManager $appManager */
$appManager = \OC::$server->getAppManager();
$tmpl = new OC_Template('', 'update.admin', 'guest');
@@ -385,8 +386,17 @@ class OC {
// get third party apps
$ocVersion = \OCP\Util::getVersion();
+ $incompatibleApps = $appManager->getIncompatibleApps($ocVersion);
+ foreach ($incompatibleApps as $appInfo) {
+ if ($appManager->isShipped($appInfo['id'])) {
+ $l = \OC::$server->getL10N('core');
+ $hint = $l->t('The files of the app "%$1s" (%$2s) were not replaced correctly.', [$appInfo['name'], $appInfo['id']]);
+ throw new \OC\HintException('The files of the app "' . $appInfo['name'] . '" (' . $appInfo['id'] . ') were not replaced correctly.', $hint);
+ }
+ }
+
$tmpl->assign('appsToUpgrade', $appManager->getAppsNeedingUpgrade($ocVersion));
- $tmpl->assign('incompatibleAppsList', $appManager->getIncompatibleApps($ocVersion));
+ $tmpl->assign('incompatibleAppsList', $incompatibleApps);
$tmpl->assign('productName', 'Nextcloud'); // for now
$tmpl->assign('oldTheme', $oldTheme);
$tmpl->printPage();
@@ -1035,6 +1045,12 @@ class OC {
if ($userSession->tryTokenLogin($request)) {
return true;
}
+ if (isset($_COOKIE['nc_username'])
+ && isset($_COOKIE['nc_token'])
+ && isset($_COOKIE['nc_session_id'])
+ && $userSession->loginWithCookie($_COOKIE['nc_username'], $_COOKIE['nc_token'], $_COOKIE['nc_session_id'])) {
+ return true;
+ }
if ($userSession->tryBasicAuthLogin($request, \OC::$server->getBruteForceThrottler())) {
return true;
}
diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php
index 532a6f39848..ddd531868d4 100644
--- a/lib/composer/composer/autoload_classmap.php
+++ b/lib/composer/composer/autoload_classmap.php
@@ -279,6 +279,11 @@ return array(
'OC\\AppFramework\\Utility\\TimeFactory' => $baseDir . '/lib/private/AppFramework/Utility/TimeFactory.php',
'OC\\AppHelper' => $baseDir . '/lib/private/AppHelper.php',
'OC\\App\\AppManager' => $baseDir . '/lib/private/App/AppManager.php',
+ 'OC\\App\\AppStore\\Fetcher\\AppFetcher' => $baseDir . '/lib/private/App/AppStore/Fetcher/AppFetcher.php',
+ 'OC\\App\\AppStore\\Fetcher\\CategoryFetcher' => $baseDir . '/lib/private/App/AppStore/Fetcher/CategoryFetcher.php',
+ 'OC\\App\\AppStore\\Fetcher\\Fetcher' => $baseDir . '/lib/private/App/AppStore/Fetcher/Fetcher.php',
+ 'OC\\App\\AppStore\\Version\\Version' => $baseDir . '/lib/private/App/AppStore/Version/Version.php',
+ 'OC\\App\\AppStore\\Version\\VersionParser' => $baseDir . '/lib/private/App/AppStore/Version/VersionParser.php',
'OC\\App\\CodeChecker\\AbstractCheck' => $baseDir . '/lib/private/App/CodeChecker/AbstractCheck.php',
'OC\\App\\CodeChecker\\CodeChecker' => $baseDir . '/lib/private/App/CodeChecker/CodeChecker.php',
'OC\\App\\CodeChecker\\DeprecationCheck' => $baseDir . '/lib/private/App/CodeChecker/DeprecationCheck.php',
@@ -602,7 +607,6 @@ return array(
'OC\\Notification\\Action' => $baseDir . '/lib/private/Notification/Action.php',
'OC\\Notification\\Manager' => $baseDir . '/lib/private/Notification/Manager.php',
'OC\\Notification\\Notification' => $baseDir . '/lib/private/Notification/Notification.php',
- 'OC\\OCSClient' => $baseDir . '/lib/private/OCSClient.php',
'OC\\OCS\\CoreCapabilities' => $baseDir . '/lib/private/OCS/CoreCapabilities.php',
'OC\\OCS\\Exception' => $baseDir . '/lib/private/OCS/Exception.php',
'OC\\OCS\\Person' => $baseDir . '/lib/private/OCS/Person.php',
diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php
index c0a3e9b50c6..99a3c3d540e 100644
--- a/lib/composer/composer/autoload_static.php
+++ b/lib/composer/composer/autoload_static.php
@@ -309,6 +309,11 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\AppFramework\\Utility\\TimeFactory' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Utility/TimeFactory.php',
'OC\\AppHelper' => __DIR__ . '/../../..' . '/lib/private/AppHelper.php',
'OC\\App\\AppManager' => __DIR__ . '/../../..' . '/lib/private/App/AppManager.php',
+ 'OC\\App\\AppStore\\Fetcher\\AppFetcher' => __DIR__ . '/../../..' . '/lib/private/App/AppStore/Fetcher/AppFetcher.php',
+ 'OC\\App\\AppStore\\Fetcher\\CategoryFetcher' => __DIR__ . '/../../..' . '/lib/private/App/AppStore/Fetcher/CategoryFetcher.php',
+ 'OC\\App\\AppStore\\Fetcher\\Fetcher' => __DIR__ . '/../../..' . '/lib/private/App/AppStore/Fetcher/Fetcher.php',
+ 'OC\\App\\AppStore\\Version\\Version' => __DIR__ . '/../../..' . '/lib/private/App/AppStore/Version/Version.php',
+ 'OC\\App\\AppStore\\Version\\VersionParser' => __DIR__ . '/../../..' . '/lib/private/App/AppStore/Version/VersionParser.php',
'OC\\App\\CodeChecker\\AbstractCheck' => __DIR__ . '/../../..' . '/lib/private/App/CodeChecker/AbstractCheck.php',
'OC\\App\\CodeChecker\\CodeChecker' => __DIR__ . '/../../..' . '/lib/private/App/CodeChecker/CodeChecker.php',
'OC\\App\\CodeChecker\\DeprecationCheck' => __DIR__ . '/../../..' . '/lib/private/App/CodeChecker/DeprecationCheck.php',
@@ -632,7 +637,6 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\Notification\\Action' => __DIR__ . '/../../..' . '/lib/private/Notification/Action.php',
'OC\\Notification\\Manager' => __DIR__ . '/../../..' . '/lib/private/Notification/Manager.php',
'OC\\Notification\\Notification' => __DIR__ . '/../../..' . '/lib/private/Notification/Notification.php',
- 'OC\\OCSClient' => __DIR__ . '/../../..' . '/lib/private/OCSClient.php',
'OC\\OCS\\CoreCapabilities' => __DIR__ . '/../../..' . '/lib/private/OCS/CoreCapabilities.php',
'OC\\OCS\\Exception' => __DIR__ . '/../../..' . '/lib/private/OCS/Exception.php',
'OC\\OCS\\Person' => __DIR__ . '/../../..' . '/lib/private/OCS/Person.php',
diff --git a/lib/private/App/AppStore/Fetcher/AppFetcher.php b/lib/private/App/AppStore/Fetcher/AppFetcher.php
new file mode 100644
index 00000000000..19e61d416a0
--- /dev/null
+++ b/lib/private/App/AppStore/Fetcher/AppFetcher.php
@@ -0,0 +1,56 @@
+<?php
+/**
+ * @copyright Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch>
+ *
+ * @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\App\AppStore\Fetcher;
+
+use OCP\AppFramework\Utility\ITimeFactory;
+use OCP\Files\IAppData;
+use OCP\Http\Client\IClientService;
+use OCP\IConfig;
+
+class AppFetcher extends Fetcher {
+ /**
+ * @param IAppData $appData
+ * @param IClientService $clientService
+ * @param ITimeFactory $timeFactory
+ * @param IConfig $config;
+ */
+ public function __construct(IAppData $appData,
+ IClientService $clientService,
+ ITimeFactory $timeFactory,
+ IConfig $config) {
+ parent::__construct(
+ $appData,
+ $clientService,
+ $timeFactory
+ );
+
+ $this->fileName = 'apps.json';
+
+ $versionArray = \OC_Util::getVersion();
+ $this->endpointUrl = sprintf(
+ 'https://apps.nextcloud.com/api/v1/platform/%d.%d.%d/apps.json',
+ $versionArray[0],
+ $versionArray[1],
+ $versionArray[2]
+ );
+ }
+}
diff --git a/lib/private/App/AppStore/Fetcher/CategoryFetcher.php b/lib/private/App/AppStore/Fetcher/CategoryFetcher.php
new file mode 100644
index 00000000000..74201ec3737
--- /dev/null
+++ b/lib/private/App/AppStore/Fetcher/CategoryFetcher.php
@@ -0,0 +1,45 @@
+<?php
+/**
+ * @copyright Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch>
+ *
+ * @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\App\AppStore\Fetcher;
+
+use OCP\AppFramework\Utility\ITimeFactory;
+use OCP\Files\IAppData;
+use OCP\Http\Client\IClientService;
+
+class CategoryFetcher extends Fetcher {
+ /**
+ * @param IAppData $appData
+ * @param IClientService $clientService
+ * @param ITimeFactory $timeFactory
+ */
+ public function __construct(IAppData $appData,
+ IClientService $clientService,
+ ITimeFactory $timeFactory) {
+ parent::__construct(
+ $appData,
+ $clientService,
+ $timeFactory
+ );
+ $this->fileName = 'categories.json';
+ $this->endpointUrl = 'https://apps.nextcloud.com/api/v1/categories.json';
+ }
+}
diff --git a/lib/private/App/AppStore/Fetcher/Fetcher.php b/lib/private/App/AppStore/Fetcher/Fetcher.php
new file mode 100644
index 00000000000..cffff9176e2
--- /dev/null
+++ b/lib/private/App/AppStore/Fetcher/Fetcher.php
@@ -0,0 +1,92 @@
+<?php
+/**
+ * @copyright Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch>
+ *
+ * @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\App\AppStore\Fetcher;
+
+use OCP\AppFramework\Utility\ITimeFactory;
+use OCP\Files\IAppData;
+use OCP\Files\NotFoundException;
+use OCP\Http\Client\IClientService;
+
+abstract class Fetcher {
+ const INVALIDATE_AFTER_SECONDS = 300;
+
+ /** @var IAppData */
+ private $appData;
+ /** @var IClientService */
+ private $clientService;
+ /** @var ITimeFactory */
+ private $timeFactory;
+ /** @var string */
+ protected $fileName;
+ /** @var string */
+ protected $endpointUrl;
+
+ /**
+ * @param IAppData $appData
+ * @param IClientService $clientService
+ * @param ITimeFactory $timeFactory
+ */
+ public function __construct(IAppData $appData,
+ IClientService $clientService,
+ ITimeFactory $timeFactory) {
+ $this->appData = $appData;
+ $this->clientService = $clientService;
+ $this->timeFactory = $timeFactory;
+ }
+
+ /**
+ * Returns the array with the categories on the appstore server
+ *
+ * @return array
+ */
+ public function get() {
+ $rootFolder = $this->appData->getFolder('/');
+
+ try {
+ // File does already exists
+ $file = $rootFolder->getFile($this->fileName);
+ $jsonBlob = json_decode($file->getContent(), true);
+ if(is_array($jsonBlob)) {
+ // If the timestamp is older than 300 seconds request the files new
+ if((int)$jsonBlob['timestamp'] > ($this->timeFactory->getTime() - self::INVALIDATE_AFTER_SECONDS)) {
+ return $jsonBlob['data'];
+ }
+ }
+ } catch (NotFoundException $e) {
+ // File does not already exists
+ $file = $rootFolder->newFile($this->fileName);
+ }
+
+ // Refresh the file content
+ $client = $this->clientService->newClient();
+ try {
+ $response = $client->get($this->endpointUrl);
+ $responseJson = [];
+ $responseJson['data'] = json_decode($response->getBody(), true);
+ $responseJson['timestamp'] = $this->timeFactory->getTime();
+ $file->putContent(json_encode($responseJson));
+ return json_decode($file->getContent(), true)['data'];
+ } catch (\Exception $e) {
+ return [];
+ }
+ }
+}
diff --git a/lib/private/App/AppStore/Version/Version.php b/lib/private/App/AppStore/Version/Version.php
new file mode 100644
index 00000000000..ca182ae078b
--- /dev/null
+++ b/lib/private/App/AppStore/Version/Version.php
@@ -0,0 +1,52 @@
+<?php
+/**
+ * @copyright Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch>
+ *
+ * @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\App\AppStore\Version;
+
+class Version {
+ /** @var string */
+ private $minVersion;
+ /** @var string */
+ private $maxVersion;
+
+ /**
+ * @param string $minVersion
+ * @param string $maxVersion
+ */
+ public function __construct($minVersion, $maxVersion) {
+ $this->minVersion = $minVersion;
+ $this->maxVersion = $maxVersion;
+ }
+
+ /**
+ * @return string
+ */
+ public function getMinimumVersion() {
+ return $this->minVersion;
+ }
+
+ /**
+ * @return string
+ */
+ public function getMaximumVersion() {
+ return $this->maxVersion;
+ }
+}
diff --git a/lib/private/App/AppStore/Version/VersionParser.php b/lib/private/App/AppStore/Version/VersionParser.php
new file mode 100644
index 00000000000..b548ef386d9
--- /dev/null
+++ b/lib/private/App/AppStore/Version/VersionParser.php
@@ -0,0 +1,83 @@
+<?php
+/**
+ * @copyright Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch>
+ *
+ * @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\App\AppStore\Version;
+
+/**
+ * Class VersionParser parses the versions as sent by the Nextcloud app store
+ *
+ * @package OC\App\AppStore
+ */
+class VersionParser {
+ /**
+ * @param string $versionString
+ * @return bool
+ */
+ private function isValidVersionString($versionString) {
+ return (bool)preg_match('/^[0-9.]+$/', $versionString);
+ }
+
+ /**
+ * Returns the version for a version string
+ *
+ * @param string $versionSpec
+ * @return Version
+ * @throws \Exception If the version cannot be parsed
+ */
+ public function getVersion($versionSpec) {
+ // * indicates that the version is compatible with all versions
+ if($versionSpec === '*') {
+ return new Version('', '');
+ }
+
+ // Count the amount of =, if it is one then it's either maximum or minimum
+ // version. If it is two then it is maximum and minimum.
+ $versionElements = explode(' ', $versionSpec);
+ $firstVersion = isset($versionElements[0]) ? $versionElements[0] : '';
+ $firstVersionNumber = substr($firstVersion, 2);
+ $secondVersion = isset($versionElements[1]) ? $versionElements[1] : '';
+ $secondVersionNumber = substr($secondVersion, 2);
+
+ switch(count($versionElements)) {
+ case 1:
+ if(!$this->isValidVersionString($firstVersionNumber)) {
+ break;
+ }
+ if(substr($firstVersion, 0, 1) === '>') {
+ return new Version($firstVersionNumber, '');
+ } else {
+ return new Version('', $firstVersionNumber);
+ }
+ case 2:
+ if(!$this->isValidVersionString($firstVersionNumber) || !$this->isValidVersionString($secondVersionNumber)) {
+ break;
+ }
+ return new Version($firstVersionNumber, $secondVersionNumber);
+ }
+
+ throw new \Exception(
+ sprintf(
+ 'Version cannot be parsed: %s',
+ $versionSpec
+ )
+ );
+ }
+}
diff --git a/lib/private/App/DependencyAnalyzer.php b/lib/private/App/DependencyAnalyzer.php
index 67268981e99..c24b25ff14d 100644
--- a/lib/private/App/DependencyAnalyzer.php
+++ b/lib/private/App/DependencyAnalyzer.php
@@ -1,6 +1,7 @@
<?php
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
+ * @copyright Copyright (c) 2016, Lukas Reschke <lukas@statuscode.ch>
*
* @author Bernhard Posselt <dev@bernhard-posselt.com>
* @author Joas Schilling <coding@schilljs.com>
@@ -294,7 +295,9 @@ class DependencyAnalyzer {
private function analyzeOC(array $dependencies, array $appInfo) {
$missing = [];
$minVersion = null;
- if (isset($dependencies['owncloud']['@attributes']['min-version'])) {
+ if (isset($dependencies['nextcloud']['@attributes']['min-version'])) {
+ $minVersion = $dependencies['nextcloud']['@attributes']['min-version'];
+ } elseif (isset($dependencies['owncloud']['@attributes']['min-version'])) {
$minVersion = $dependencies['owncloud']['@attributes']['min-version'];
} elseif (isset($appInfo['requiremin'])) {
$minVersion = $appInfo['requiremin'];
@@ -302,7 +305,9 @@ class DependencyAnalyzer {
$minVersion = $appInfo['require'];
}
$maxVersion = null;
- if (isset($dependencies['owncloud']['@attributes']['max-version'])) {
+ if (isset($dependencies['nextcloud']['@attributes']['max-version'])) {
+ $maxVersion = $dependencies['nextcloud']['@attributes']['max-version'];
+ } elseif (isset($dependencies['owncloud']['@attributes']['max-version'])) {
$maxVersion = $dependencies['owncloud']['@attributes']['max-version'];
} elseif (isset($appInfo['requiremax'])) {
$maxVersion = $appInfo['requiremax'];
diff --git a/lib/private/AppFramework/DependencyInjection/DIContainer.php b/lib/private/AppFramework/DependencyInjection/DIContainer.php
index a1e845f132e..e1516c47ed6 100644
--- a/lib/private/AppFramework/DependencyInjection/DIContainer.php
+++ b/lib/private/AppFramework/DependencyInjection/DIContainer.php
@@ -290,6 +290,7 @@ class DIContainer extends SimpleContainer implements IAppContainer {
$this->registerService('OCP\\IUserSession', function($c) {
return $this->getServer()->getUserSession();
});
+ $this->registerAlias(\OC\User\Session::class, \OCP\IUserSession::class);
$this->registerService('OCP\\ISession', function($c) {
return $this->getServer()->getSession();
diff --git a/lib/private/Archive/Archive.php b/lib/private/Archive/Archive.php
index da2c53f2aa1..fadc12d2a24 100644
--- a/lib/private/Archive/Archive.php
+++ b/lib/private/Archive/Archive.php
@@ -32,26 +32,7 @@
namespace OC\Archive;
-abstract class Archive{
- /**
- * Open any of the supported archive types
- *
- * @param string $path
- * @return Archive|void
- */
- public static function open($path) {
- $mime = \OC::$server->getMimeTypeDetector()->detect($path);
-
- switch($mime) {
- case 'application/zip':
- return new ZIP($path);
- case 'application/x-gzip':
- return new TAR($path);
- case 'application/x-bzip2':
- return new TAR($path);
- }
- }
-
+abstract class Archive {
/**
* @param $source
*/
diff --git a/lib/private/Authentication/Token/DefaultToken.php b/lib/private/Authentication/Token/DefaultToken.php
index 904df9baa28..faef2f73b33 100644
--- a/lib/private/Authentication/Token/DefaultToken.php
+++ b/lib/private/Authentication/Token/DefaultToken.php
@@ -35,6 +35,8 @@ use OCP\AppFramework\Db\Entity;
* @method string getToken()
* @method void setType(string $type)
* @method int getType()
+ * @method void setRemember(int $remember)
+ * @method int getRemember()
* @method void setLastActivity(int $lastActivity)
* @method int getLastActivity()
*/
@@ -73,6 +75,11 @@ class DefaultToken extends Entity implements IToken {
/**
* @var int
*/
+ protected $remember;
+
+ /**
+ * @var int
+ */
protected $lastActivity;
/**
diff --git a/lib/private/Authentication/Token/DefaultTokenMapper.php b/lib/private/Authentication/Token/DefaultTokenMapper.php
index 0ce26197ccf..752974ff240 100644
--- a/lib/private/Authentication/Token/DefaultTokenMapper.php
+++ b/lib/private/Authentication/Token/DefaultTokenMapper.php
@@ -40,24 +40,25 @@ class DefaultTokenMapper extends Mapper {
* @param string $token
*/
public function invalidate($token) {
+ /* @var $qb IQueryBuilder */
$qb = $this->db->getQueryBuilder();
$qb->delete('authtoken')
- ->andWhere($qb->expr()->eq('token', $qb->createParameter('token')))
+ ->where($qb->expr()->eq('token', $qb->createParameter('token')))
->setParameter('token', $token)
->execute();
}
/**
* @param int $olderThan
+ * @param int $remember
*/
- public function invalidateOld($olderThan) {
+ public function invalidateOld($olderThan, $remember = IToken::DO_NOT_REMEMBER) {
/* @var $qb IQueryBuilder */
$qb = $this->db->getQueryBuilder();
$qb->delete('authtoken')
- ->where($qb->expr()->lt('last_activity', $qb->createParameter('last_activity')))
- ->andWhere($qb->expr()->eq('type', $qb->createParameter('type')))
- ->setParameter('last_activity', $olderThan, IQueryBuilder::PARAM_INT)
- ->setParameter('type', IToken::TEMPORARY_TOKEN, IQueryBuilder::PARAM_INT)
+ ->where($qb->expr()->lt('last_activity', $qb->createNamedParameter($olderThan, IQueryBuilder::PARAM_INT)))
+ ->andWhere($qb->expr()->eq('type', $qb->createNamedParameter(IToken::TEMPORARY_TOKEN, IQueryBuilder::PARAM_INT)))
+ ->andWhere($qb->expr()->eq('remember', $qb->createNamedParameter($remember, IQueryBuilder::PARAM_INT)))
->execute();
}
@@ -71,7 +72,7 @@ class DefaultTokenMapper extends Mapper {
public function getToken($token) {
/* @var $qb IQueryBuilder */
$qb = $this->db->getQueryBuilder();
- $result = $qb->select('id', 'uid', 'login_name', 'password', 'name', 'type', 'token', 'last_activity', 'last_check')
+ $result = $qb->select('id', 'uid', 'login_name', 'password', 'name', 'type', 'remember', 'token', 'last_activity', 'last_check')
->from('authtoken')
->where($qb->expr()->eq('token', $qb->createParameter('token')))
->setParameter('token', $token)
@@ -97,7 +98,7 @@ class DefaultTokenMapper extends Mapper {
public function getTokenByUser(IUser $user) {
/* @var $qb IQueryBuilder */
$qb = $this->db->getQueryBuilder();
- $qb->select('id', 'uid', 'login_name', 'password', 'name', 'type', 'token', 'last_activity', 'last_check')
+ $qb->select('id', 'uid', 'login_name', 'password', 'name', 'type', 'remember', 'token', 'last_activity', 'last_check')
->from('authtoken')
->where($qb->expr()->eq('uid', $qb->createNamedParameter($user->getUID())))
->setMaxResults(1000);
diff --git a/lib/private/Authentication/Token/DefaultTokenProvider.php b/lib/private/Authentication/Token/DefaultTokenProvider.php
index b0fbeb9b47e..87f434c684c 100644
--- a/lib/private/Authentication/Token/DefaultTokenProvider.php
+++ b/lib/private/Authentication/Token/DefaultTokenProvider.php
@@ -1,6 +1,7 @@
<?php
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
+ * @copyright Copyright (c) 2016, Christoph Wurst <christoph@winzerhof-wurst.at>
*
* @author Christoph Wurst <christoph@owncloud.com>
*
@@ -56,7 +57,11 @@ class DefaultTokenProvider implements IProvider {
* @param ILogger $logger
* @param ITimeFactory $time
*/
- public function __construct(DefaultTokenMapper $mapper, ICrypto $crypto, IConfig $config, ILogger $logger, ITimeFactory $time) {
+ public function __construct(DefaultTokenMapper $mapper,
+ ICrypto $crypto,
+ IConfig $config,
+ ILogger $logger,
+ ITimeFactory $time) {
$this->mapper = $mapper;
$this->crypto = $crypto;
$this->config = $config;
@@ -73,9 +78,10 @@ class DefaultTokenProvider implements IProvider {
* @param string|null $password
* @param string $name
* @param int $type token type
+ * @param int $remember whether the session token should be used for remember-me
* @return IToken
*/
- public function generateToken($token, $uid, $loginName, $password, $name, $type = IToken::TEMPORARY_TOKEN) {
+ public function generateToken($token, $uid, $loginName, $password, $name, $type = IToken::TEMPORARY_TOKEN, $remember = IToken::DO_NOT_REMEMBER) {
$dbToken = new DefaultToken();
$dbToken->setUid($uid);
$dbToken->setLoginName($loginName);
@@ -85,6 +91,7 @@ class DefaultTokenProvider implements IProvider {
$dbToken->setName($name);
$dbToken->setToken($this->hashToken($token));
$dbToken->setType($type);
+ $dbToken->setRemember($remember);
$dbToken->setLastActivity($this->time->getTime());
$this->mapper->insert($dbToken);
@@ -96,6 +103,7 @@ class DefaultTokenProvider implements IProvider {
* Save the updated token
*
* @param IToken $token
+ * @throws InvalidTokenException
*/
public function updateToken(IToken $token) {
if (!($token instanceof DefaultToken)) {
@@ -152,6 +160,28 @@ class DefaultTokenProvider implements IProvider {
}
/**
+ * @param string $oldSessionId
+ * @param string $sessionId
+ * @throws InvalidTokenException
+ */
+ public function renewSessionToken($oldSessionId, $sessionId) {
+ $token = $this->getToken($oldSessionId);
+
+ $newToken = new DefaultToken();
+ $newToken->setUid($token->getUID());
+ $newToken->setLoginName($token->getLoginName());
+ if (!is_null($token->getPassword())) {
+ $password = $this->decryptPassword($token->getPassword(), $oldSessionId);
+ $newToken->setPassword($this->encryptPassword($password, $sessionId));
+ }
+ $newToken->setName($token->getName());
+ $newToken->setToken($this->hashToken($sessionId));
+ $newToken->setType(IToken::TEMPORARY_TOKEN);
+ $newToken->setLastActivity($this->time->getTime());
+ $this->mapper->insert($newToken);
+ }
+
+ /**
* @param IToken $savedToken
* @param string $tokenId session token
* @throws InvalidTokenException
@@ -207,8 +237,11 @@ class DefaultTokenProvider implements IProvider {
*/
public function invalidateOldTokens() {
$olderThan = $this->time->getTime() - (int) $this->config->getSystemValue('session_lifetime', 60 * 60 * 24);
- $this->logger->info('Invalidating tokens older than ' . date('c', $olderThan));
- $this->mapper->invalidateOld($olderThan);
+ $this->logger->info('Invalidating session tokens older than ' . date('c', $olderThan));
+ $this->mapper->invalidateOld($olderThan, IToken::DO_NOT_REMEMBER);
+ $rememberThreshold = $this->time->getTime() - (int) $this->config->getSystemValue('remember_login_cookie_lifetime', 60 * 60 * 24 * 15);
+ $this->logger->info('Invalidating remembered session tokens older than ' . date('c', $rememberThreshold));
+ $this->mapper->invalidateOld($rememberThreshold, IToken::REMEMBER);
}
/**
diff --git a/lib/private/Authentication/Token/IProvider.php b/lib/private/Authentication/Token/IProvider.php
index 65b515960ea..ce14a5880c5 100644
--- a/lib/private/Authentication/Token/IProvider.php
+++ b/lib/private/Authentication/Token/IProvider.php
@@ -28,6 +28,7 @@ use OCP\IUser;
interface IProvider {
+
/**
* Create and persist a new token
*
@@ -37,9 +38,10 @@ interface IProvider {
* @param string|null $password
* @param string $name
* @param int $type token type
+ * @param int $remember whether the session token should be used for remember-me
* @return IToken
*/
- public function generateToken($token, $uid, $loginName, $password, $name, $type = IToken::TEMPORARY_TOKEN);
+ public function generateToken($token, $uid, $loginName, $password, $name, $type = IToken::TEMPORARY_TOKEN, $remember = IToken::DO_NOT_REMEMBER);
/**
* Get a token by token id
@@ -51,6 +53,15 @@ interface IProvider {
public function getToken($tokenId) ;
/**
+ * Duplicate an existing session token
+ *
+ * @param string $oldSessionId
+ * @param string $sessionId
+ * @throws InvalidTokenException
+ */
+ public function renewSessionToken($oldSessionId, $sessionId);
+
+ /**
* Invalidate (delete) the given session token
*
* @param string $token
diff --git a/lib/private/Authentication/Token/IToken.php b/lib/private/Authentication/Token/IToken.php
index e1e78ca369a..14811dd3201 100644
--- a/lib/private/Authentication/Token/IToken.php
+++ b/lib/private/Authentication/Token/IToken.php
@@ -28,6 +28,8 @@ interface IToken extends JsonSerializable {
const TEMPORARY_TOKEN = 0;
const PERMANENT_TOKEN = 1;
+ const DO_NOT_REMEMBER = 0;
+ const REMEMBER = 1;
/**
* Get the token ID
diff --git a/lib/private/Authentication/TwoFactorAuth/Manager.php b/lib/private/Authentication/TwoFactorAuth/Manager.php
index 1bea7aa3478..d84ba4aee7e 100644
--- a/lib/private/Authentication/TwoFactorAuth/Manager.php
+++ b/lib/private/Authentication/TwoFactorAuth/Manager.php
@@ -37,6 +37,7 @@ class Manager {
const SESSION_UID_KEY = 'two_factor_auth_uid';
const BACKUP_CODES_APP_ID = 'twofactor_backupcodes';
const BACKUP_CODES_PROVIDER_ID = 'backup_codes';
+ const REMEMBER_LOGIN = 'two_factor_remember_login';
/** @var AppManager */
private $appManager;
@@ -114,6 +115,7 @@ class Manager {
* @param IUser $user
* @param bool $includeBackupApp
* @return IProvider[]
+ * @throws Exception
*/
public function getProviders(IUser $user, $includeBackupApp = false) {
$allApps = $this->appManager->getEnabledAppsForUser($user);
@@ -171,11 +173,16 @@ class Manager {
return false;
}
- $result = $provider->verifyChallenge($user, $challenge);
- if ($result) {
+ $passed = $provider->verifyChallenge($user, $challenge);
+ if ($passed) {
+ if ($this->session->get(self::REMEMBER_LOGIN) === true) {
+ // TODO: resolve cyclic dependency and use DI
+ \OC::$server->getUserSession()->createRememberMeToken($user);
+ }
$this->session->remove(self::SESSION_UID_KEY);
+ $this->session->remove(self::REMEMBER_LOGIN);
}
- return $result;
+ return $passed;
}
/**
@@ -202,12 +209,14 @@ class Manager {
}
/**
- * Prepare the 2FA login (set session value)
+ * Prepare the 2FA login
*
* @param IUser $user
+ * @param boolean $rememberMe
*/
- public function prepareTwoFactorLogin(IUser $user) {
+ public function prepareTwoFactorLogin(IUser $user, $rememberMe) {
$this->session->set(self::SESSION_UID_KEY, $user->getUID());
+ $this->session->set(self::REMEMBER_LOGIN, $rememberMe);
}
}
diff --git a/lib/private/DB/Connection.php b/lib/private/DB/Connection.php
index dfe2e86b617..497ff0c8a26 100644
--- a/lib/private/DB/Connection.php
+++ b/lib/private/DB/Connection.php
@@ -67,7 +67,11 @@ class Connection extends \Doctrine\DBAL\Connection implements IDBConnection {
* @return \OCP\DB\QueryBuilder\IQueryBuilder
*/
public function getQueryBuilder() {
- return new QueryBuilder($this);
+ return new QueryBuilder(
+ $this,
+ \OC::$server->getSystemConfig(),
+ \OC::$server->getLogger()
+ );
}
/**
diff --git a/lib/private/DB/QueryBuilder/QueryBuilder.php b/lib/private/DB/QueryBuilder/QueryBuilder.php
index eac77dd98fd..d5dd9cf0366 100644
--- a/lib/private/DB/QueryBuilder/QueryBuilder.php
+++ b/lib/private/DB/QueryBuilder/QueryBuilder.php
@@ -31,16 +31,24 @@ use OC\DB\QueryBuilder\ExpressionBuilder\ExpressionBuilder;
use OC\DB\QueryBuilder\ExpressionBuilder\MySqlExpressionBuilder;
use OC\DB\QueryBuilder\ExpressionBuilder\OCIExpressionBuilder;
use OC\DB\QueryBuilder\ExpressionBuilder\PgSqlExpressionBuilder;
+use OC\SystemConfig;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\DB\QueryBuilder\IQueryFunction;
use OCP\DB\QueryBuilder\IParameter;
use OCP\IDBConnection;
+use OCP\ILogger;
class QueryBuilder implements IQueryBuilder {
/** @var \OCP\IDBConnection */
private $connection;
+ /** @var SystemConfig */
+ private $systemConfig;
+
+ /** @var ILogger */
+ private $logger;
+
/** @var \Doctrine\DBAL\Query\QueryBuilder */
private $queryBuilder;
@@ -56,10 +64,14 @@ class QueryBuilder implements IQueryBuilder {
/**
* Initializes a new QueryBuilder.
*
- * @param \OCP\IDBConnection $connection
+ * @param IDBConnection $connection
+ * @param SystemConfig $systemConfig
+ * @param ILogger $logger
*/
- public function __construct(IDBConnection $connection) {
+ public function __construct(IDBConnection $connection, SystemConfig $systemConfig, ILogger $logger) {
$this->connection = $connection;
+ $this->systemConfig = $systemConfig;
+ $this->logger = $logger;
$this->queryBuilder = new \Doctrine\DBAL\Query\QueryBuilder($this->connection);
$this->helper = new QuoteHelper();
}
@@ -139,6 +151,29 @@ class QueryBuilder implements IQueryBuilder {
* @return \Doctrine\DBAL\Driver\Statement|int
*/
public function execute() {
+ if ($this->systemConfig->getValue('log_query', false)) {
+ $params = [];
+ foreach ($this->getParameters() as $placeholder => $value) {
+ if (is_array($value)) {
+ $params[] = $placeholder . ' => (\'' . implode('\', \'', $value) . '\')';
+ } else {
+ $params[] = $placeholder . ' => \'' . $value . '\'';
+ }
+ }
+ if (empty($params)) {
+ $this->logger->debug('DB QueryBuilder: \'{query}\'', [
+ 'query' => $this->getSQL(),
+ 'app' => 'core',
+ ]);
+ } else {
+ $this->logger->debug('DB QueryBuilder: \'{query}\' with parameters: {params}', [
+ 'query' => $this->getSQL(),
+ 'params' => implode(', ', $params),
+ 'app' => 'core',
+ ]);
+ }
+ }
+
return $this->queryBuilder->execute();
}
diff --git a/lib/private/Installer.php b/lib/private/Installer.php
index 009df790585..2366b762654 100644
--- a/lib/private/Installer.php
+++ b/lib/private/Installer.php
@@ -1,6 +1,7 @@
<?php
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
+ * @copyright Copyright (c) 2016, Lukas Reschke <lukas@statuscode.ch>
*
* @author Arthur Schiwon <blizzz@arthur-schiwon.de>
* @author Bart Visscher <bartv@thisnet.nl>
@@ -40,90 +41,64 @@
namespace OC;
+use OC\App\AppStore\Fetcher\AppFetcher;
use OC\App\CodeChecker\CodeChecker;
use OC\App\CodeChecker\EmptyCheck;
use OC\App\CodeChecker\PrivateCheck;
+use OC\Archive\Archive;
+use OC\Archive\TAR;
use OC_App;
use OC_DB;
use OC_Helper;
+use OCP\Http\Client\IClientService;
+use OCP\ILogger;
+use OCP\ITempManager;
+use phpseclib\File\X509;
/**
- * This class provides the functionality needed to install, update and remove plugins/apps
+ * This class provides the functionality needed to install, update and remove apps
*/
class Installer {
+ /** @var AppFetcher */
+ private $appFetcher;
+ /** @var IClientService */
+ private $clientService;
+ /** @var ITempManager */
+ private $tempManager;
+ /** @var ILogger */
+ private $logger;
/**
+ * @param AppFetcher $appFetcher
+ * @param IClientService $clientService
+ * @param ITempManager $tempManager
+ * @param ILogger $logger
+ */
+ public function __construct(AppFetcher $appFetcher,
+ IClientService $clientService,
+ ITempManager $tempManager,
+ ILogger $logger) {
+ $this->appFetcher = $appFetcher;
+ $this->clientService = $clientService;
+ $this->tempManager = $tempManager;
+ $this->logger = $logger;
+ }
+
+ /**
+ * Installs an app that is located in one of the app folders already
*
- * This function installs an app. All information needed are passed in the
- * associative array $data.
- * The following keys are required:
- * - source: string, can be "path" or "http"
- *
- * One of the following keys is required:
- * - path: path to the file containing the app
- * - href: link to the downloadable file containing the app
- *
- * The following keys are optional:
- * - pretend: boolean, if set true the system won't do anything
- * - noinstall: boolean, if true appinfo/install.php won't be loaded
- * - inactive: boolean, if set true the appconfig/app.sample.php won't be
- * renamed
- *
- * This function works as follows
- * -# fetching the file
- * -# unzipping it
- * -# check the code
- * -# installing the database at appinfo/database.xml
- * -# including appinfo/install.php
- * -# setting the installed version
- *
- * It is the task of oc_app_install to create the tables and do whatever is
- * needed to get the app working.
- *
- * Installs an app
- * @param array $data with all information
+ * @param string $appId App to install
* @throws \Exception
* @return integer
*/
- public static function installApp( $data = array()) {
- $l = \OC::$server->getL10N('lib');
-
- list($extractDir, $path) = self::downloadApp($data);
-
- $info = self::checkAppsIntegrity($data, $extractDir, $path);
- $appId = OC_App::cleanAppId($info['id']);
- $basedir = OC_App::getInstallPath().'/'.$appId;
- //check if the destination directory already exists
- if(is_dir($basedir)) {
- OC_Helper::rmdirr($extractDir);
- if($data['source']=='http') {
- unlink($path);
- }
- throw new \Exception($l->t("App directory already exists"));
- }
-
- if(!empty($data['pretent'])) {
- return false;
+ public function installApp($appId) {
+ $app = \OC_App::findAppInDirectories($appId);
+ if($app === false) {
+ throw new \Exception('App not found in any app directory');
}
- //copy the app to the correct place
- if(@!mkdir($basedir)) {
- OC_Helper::rmdirr($extractDir);
- if($data['source']=='http') {
- unlink($path);
- }
- throw new \Exception($l->t("Can't create app folder. Please fix permissions. %s", array($basedir)));
- }
-
- $extractDir .= '/' . $info['id'];
- if(!file_exists($extractDir)) {
- OC_Helper::rmdirr($basedir);
- throw new \Exception($l->t("Archive does not contain a directory named %s", $info['id']));
- }
- OC_Helper::copyr($extractDir, $basedir);
-
- //remove temporary files
- OC_Helper::rmdirr($extractDir);
+ $basedir = $app['path'].'/'.$appId;
+ $info = OC_App::getAppInfo($basedir.'/appinfo/info.xml', true);
//install the database
if(is_file($basedir.'/appinfo/database.xml')) {
@@ -168,259 +143,189 @@ class Installer {
*
* Checks whether or not an app is installed, i.e. registered in apps table.
*/
- public static function isInstalled( $app ) {
+ public static function isInstalled( $app ) {
return (\OC::$server->getConfig()->getAppValue($app, "installed_version", null) !== null);
}
/**
- * @brief Update an application
- * @param array $info
- * @param bool $isShipped
- * @throws \Exception
- * @return bool
- *
- * This function could work like described below, but currently it disables and then
- * enables the app again. This does result in an updated app.
- *
- *
- * This function installs an app. All information needed are passed in the
- * associative array $info.
- * The following keys are required:
- * - source: string, can be "path" or "http"
- *
- * One of the following keys is required:
- * - path: path to the file containing the app
- * - href: link to the downloadable file containing the app
- *
- * The following keys are optional:
- * - pretend: boolean, if set true the system won't do anything
- * - noupgrade: boolean, if true appinfo/upgrade.php won't be loaded
- *
- * This function works as follows
- * -# fetching the file
- * -# removing the old files
- * -# unzipping new file
- * -# including appinfo/upgrade.php
- * -# setting the installed version
- *
- * upgrade.php can determine the current installed version of the app using
- * "\OC::$server->getAppConfig()->getValue($appid, 'installed_version')"
- */
- public static function updateApp($info=array(), $isShipped=false) {
- list($extractDir, $path) = self::downloadApp($info);
- $info = self::checkAppsIntegrity($info, $extractDir, $path, $isShipped);
-
- $currentDir = OC_App::getAppPath($info['id']);
- $basedir = OC_App::getInstallPath();
- $basedir .= '/';
- $basedir .= $info['id'];
-
- if($currentDir !== false && is_writable($currentDir)) {
- $basedir = $currentDir;
- }
- if(is_dir($basedir)) {
- OC_Helper::rmdirr($basedir);
- }
-
- $appInExtractDir = $extractDir;
- if (substr($extractDir, -1) !== '/') {
- $appInExtractDir .= '/';
- }
-
- $appInExtractDir .= $info['id'];
- OC_Helper::copyr($appInExtractDir, $basedir);
- OC_Helper::rmdirr($extractDir);
-
- return OC_App::updateApp($info['id']);
- }
-
- /**
- * update an app by it's id
+ * Updates the specified app from the appstore
*
- * @param integer $ocsId
+ * @param string $appId
* @return bool
- * @throws \Exception
*/
- public static function updateAppByOCSId($ocsId) {
- $ocsClient = new OCSClient(
- \OC::$server->getHTTPClientService(),
- \OC::$server->getConfig(),
- \OC::$server->getLogger()
- );
- $appData = $ocsClient->getApplication($ocsId, \OCP\Util::getVersion());
- $download = $ocsClient->getApplicationDownload($ocsId, \OCP\Util::getVersion());
-
- if (isset($download['downloadlink']) && trim($download['downloadlink']) !== '') {
- $download['downloadlink'] = str_replace(' ', '%20', $download['downloadlink']);
- $info = array(
- 'source' => 'http',
- 'href' => $download['downloadlink'],
- 'appdata' => $appData
- );
- } else {
- throw new \Exception('Could not fetch app info!');
+ public function updateAppstoreApp($appId) {
+ if(self::isUpdateAvailable($appId, $this->appFetcher)) {
+ try {
+ $this->downloadApp($appId);
+ } catch (\Exception $e) {
+ $this->logger->error($e->getMessage(), ['app' => 'core']);
+ return false;
+ }
+ return OC_App::updateApp($appId);
}
- return self::updateApp($info);
+ return false;
}
/**
- * @param array $data
- * @return array
- * @throws \Exception
+ * Downloads an app and puts it into the app directory
+ *
+ * @param string $appId
+ *
+ * @throws \Exception If the installation was not successful
*/
- public static function downloadApp($data = array()) {
- $l = \OC::$server->getL10N('lib');
-
- if(!isset($data['source'])) {
- throw new \Exception($l->t("No source specified when installing app"));
- }
+ public function downloadApp($appId) {
+ $appId = strtolower($appId);
+
+ $apps = $this->appFetcher->get();
+ foreach($apps as $app) {
+ if($app['id'] === $appId) {
+ // Load the certificate
+ $certificate = new X509();
+ $certificate->loadCA(file_get_contents(__DIR__ . '/../../resources/codesigning/root.crt'));
+ $loadedCertificate = $certificate->loadX509($app['certificate']);
+
+ // Verify if the certificate has been revoked
+ $crl = new X509();
+ $crl->loadCA(file_get_contents(__DIR__ . '/../../resources/codesigning/root.crt'));
+ $crl->loadCRL(file_get_contents(__DIR__ . '/../../resources/codesigning/root.crl'));
+ if($crl->validateSignature() !== true) {
+ throw new \Exception('Could not validate CRL signature');
+ }
+ $csn = $loadedCertificate['tbsCertificate']['serialNumber']->toString();
+ $revoked = $crl->getRevoked($csn);
+ if ($revoked !== false) {
+ throw new \Exception(
+ sprintf(
+ 'Certificate "%s" has been revoked',
+ $csn
+ )
+ );
+ }
- //download the file if necessary
- if($data['source']=='http') {
- $pathInfo = pathinfo($data['href']);
- $extension = isset($pathInfo['extension']) ? '.' . $pathInfo['extension'] : '';
- $path = \OC::$server->getTempManager()->getTemporaryFile($extension);
- if(!isset($data['href'])) {
- throw new \Exception($l->t("No href specified when installing app from http"));
- }
- $client = \OC::$server->getHTTPClientService()->newClient();
- $client->get($data['href'], ['save_to' => $path]);
- } else {
- if(!isset($data['path'])) {
- throw new \Exception($l->t("No path specified when installing app from local file"));
- }
- $path=$data['path'];
- }
+ // Verify if the certificate has been issued by the Nextcloud Code Authority CA
+ if($certificate->validateSignature() !== true) {
+ throw new \Exception(
+ sprintf(
+ 'App with id %s has a certificate not issued by a trusted Code Signing Authority',
+ $appId
+ )
+ );
+ }
- //detect the archive type
- $mime = \OC::$server->getMimeTypeDetector()->detect($path);
- if ($mime !=='application/zip' && $mime !== 'application/x-gzip' && $mime !== 'application/x-bzip2') {
- throw new \Exception($l->t("Archives of type %s are not supported", array($mime)));
- }
+ // Verify if the certificate is issued for the requested app id
+ $certInfo = openssl_x509_parse($app['certificate']);
+ if(!isset($certInfo['subject']['CN'])) {
+ throw new \Exception(
+ sprintf(
+ 'App with id %s has a cert with no CN',
+ $appId
+ )
+ );
+ }
+ if($certInfo['subject']['CN'] !== $appId) {
+ throw new \Exception(
+ sprintf(
+ 'App with id %s has a cert issued to %s',
+ $appId,
+ $certInfo['subject']['CN']
+ )
+ );
+ }
- //extract the archive in a temporary folder
- $extractDir = \OC::$server->getTempManager()->getTemporaryFolder();
- OC_Helper::rmdirr($extractDir);
- mkdir($extractDir);
- if($archive=\OC\Archive\Archive::open($path)) {
- $archive->extract($extractDir);
- } else {
- OC_Helper::rmdirr($extractDir);
- if($data['source']=='http') {
- unlink($path);
- }
- throw new \Exception($l->t("Failed to open archive when installing app"));
- }
+ // Download the release
+ $tempFile = $this->tempManager->getTemporaryFile('.tar.gz');
+ $client = $this->clientService->newClient();
+ $client->get($app['releases'][0]['download'], ['save_to' => $tempFile]);
+
+ // Check if the signature actually matches the downloaded content
+ $certificate = openssl_get_publickey($app['certificate']);
+ $verified = (bool)openssl_verify(file_get_contents($tempFile), base64_decode($app['releases'][0]['signature']), $certificate, OPENSSL_ALGO_SHA512);
+ openssl_free_key($certificate);
+
+ if($verified === true) {
+ // Seems to match, let's proceed
+ $extractDir = $this->tempManager->getTemporaryFolder();
+ $archive = new TAR($tempFile);
+
+ if($archive) {
+ $archive->extract($extractDir);
+ $allFiles = scandir($extractDir);
+ $folders = array_diff($allFiles, ['.', '..']);
+ $folders = array_values($folders);
+
+ if(count($folders) > 1) {
+ throw new \Exception(
+ sprintf(
+ 'Extracted app %s has more than 1 folder',
+ $appId
+ )
+ );
+ }
- return array(
- $extractDir,
- $path
- );
- }
+ // Check if appinfo/info.xml has the same app ID as well
+ $loadEntities = libxml_disable_entity_loader(false);
+ $xml = simplexml_load_file($extractDir . '/' . $folders[0] . '/appinfo/info.xml');
+ libxml_disable_entity_loader($loadEntities);
+ if((string)$xml->id !== $appId) {
+ throw new \Exception(
+ sprintf(
+ 'App for id %s has a wrong app ID in info.xml: %s',
+ $appId,
+ (string)$xml->id
+ )
+ );
+ }
- /**
- * check an app's integrity
- * @param array $data
- * @param string $extractDir
- * @param string $path
- * @param bool $isShipped
- * @return array
- * @throws \Exception
- */
- public static function checkAppsIntegrity($data, $extractDir, $path, $isShipped = false) {
- $l = \OC::$server->getL10N('lib');
- //load the info.xml file of the app
- if(!is_file($extractDir.'/appinfo/info.xml')) {
- //try to find it in a subdir
- $dh=opendir($extractDir);
- if(is_resource($dh)) {
- while (($folder = readdir($dh)) !== false) {
- if($folder[0]!='.' and is_dir($extractDir.'/'.$folder)) {
- if(is_file($extractDir.'/'.$folder.'/appinfo/info.xml')) {
- $extractDir.='/'.$folder;
+ $baseDir = OC_App::getInstallPath() . '/' . $appId;
+ // Remove old app with the ID if existent
+ OC_Helper::rmdirr($baseDir);
+ // Move to app folder
+ if(@mkdir($baseDir)) {
+ $extractDir .= '/' . $folders[0];
+ OC_Helper::copyr($extractDir, $baseDir);
}
+ OC_Helper::copyr($extractDir, $baseDir);
+ OC_Helper::rmdirr($extractDir);
+ return;
+ } else {
+ throw new \Exception(
+ sprintf(
+ 'Could not extract app with ID %s to %s',
+ $appId,
+ $extractDir
+ )
+ );
}
- }
- }
- }
- if(!is_file($extractDir.'/appinfo/info.xml')) {
- OC_Helper::rmdirr($extractDir);
- if($data['source'] === 'http') {
- unlink($path);
- }
- throw new \Exception($l->t("App does not provide an info.xml file"));
- }
-
- $info = OC_App::getAppInfo($extractDir.'/appinfo/info.xml', true);
- if(!is_array($info)) {
- throw new \Exception($l->t('App cannot be installed because appinfo file cannot be read.'));
- }
-
- // We can't trust the parsed info.xml file as it may have been tampered
- // with by an attacker and thus we need to use the local data to check
- // whether the application needs to be signed.
- $appId = OC_App::cleanAppId($data['appdata']['id']);
- $appBelongingToId = OC_App::getInternalAppIdByOcs($appId);
- if(is_string($appBelongingToId)) {
- $previouslySigned = \OC::$server->getConfig()->getAppValue($appBelongingToId, 'signed', 'false');
- } else {
- $appBelongingToId = $info['id'];
- $previouslySigned = 'false';
- }
- if($data['appdata']['level'] === OC_App::officialApp || $previouslySigned === 'true') {
- \OC::$server->getConfig()->setAppValue($appBelongingToId, 'signed', 'true');
- $integrityResult = \OC::$server->getIntegrityCodeChecker()->verifyAppSignature(
- $appBelongingToId,
- $extractDir
- );
- if($integrityResult !== []) {
- $e = new \Exception(
- $l->t(
- 'Signature could not get checked. Please contact the app developer and check your admin screen.'
+ } else {
+ // Signature does not match
+ throw new \Exception(
+ sprintf(
+ 'App with id %s has invalid signature',
+ $appId
)
- );
- throw $e;
+ );
+ }
}
}
- // check the code for not allowed calls
- if(!$isShipped && !Installer::checkCode($extractDir)) {
- OC_Helper::rmdirr($extractDir);
- throw new \Exception($l->t("App can't be installed because of not allowed code in the App"));
- }
-
- // check if the app is compatible with this version of ownCloud
- if(!OC_App::isAppCompatible(\OCP\Util::getVersion(), $info)) {
- OC_Helper::rmdirr($extractDir);
- throw new \Exception($l->t("App can't be installed because it is not compatible with this version of the server"));
- }
-
- // check if shipped tag is set which is only allowed for apps that are shipped with ownCloud
- if(!$isShipped && isset($info['shipped']) && ($info['shipped']=='true')) {
- OC_Helper::rmdirr($extractDir);
- throw new \Exception($l->t("App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps"));
- }
-
- // check if the ocs version is the same as the version in info.xml/version
- $version = trim($info['version']);
-
- if(isset($data['appdata']['version']) && $version<>trim($data['appdata']['version'])) {
- OC_Helper::rmdirr($extractDir);
- throw new \Exception($l->t("App can't be installed because the version in info.xml is not the same as the version reported from the app store"));
- }
-
- return $info;
+ throw new \Exception(
+ sprintf(
+ 'Could not download app %s',
+ $appId
+ )
+ );
}
/**
* Check if an update for the app is available
- * @param string $app
- * @return string|false false or the version number of the update
*
- * The function will check if an update for a version is available
+ * @param string $appId
+ * @param AppFetcher $appFetcher
+ * @return string|false false or the version number of the update
*/
- public static function isUpdateAvailable( $app ) {
+ public static function isUpdateAvailable($appId,
+ AppFetcher $appFetcher) {
static $isInstanceReadyForUpdates = null;
if ($isInstanceReadyForUpdates === null) {
@@ -436,27 +341,20 @@ class Installer {
return false;
}
- $ocsid=\OC::$server->getAppConfig()->getValue( $app, 'ocsid', '');
-
- if($ocsid<>'') {
- $ocsClient = new OCSClient(
- \OC::$server->getHTTPClientService(),
- \OC::$server->getConfig(),
- \OC::$server->getLogger()
- );
- $ocsdata = $ocsClient->getApplication($ocsid, \OCP\Util::getVersion());
- $ocsversion= (string) $ocsdata['version'];
- $currentversion=OC_App::getAppVersion($app);
- if (version_compare($ocsversion, $currentversion, '>')) {
- return($ocsversion);
- }else{
- return false;
+ $apps = $appFetcher->get();
+ foreach($apps as $app) {
+ if($app['id'] === $appId) {
+ $currentVersion = OC_App::getAppVersion($appId);
+ $newestVersion = $app['releases'][0]['version'];
+ if (version_compare($newestVersion, $currentVersion, '>')) {
+ return $newestVersion;
+ } else {
+ return false;
+ }
}
-
- }else{
- return false;
}
+ return false;
}
/**
@@ -466,7 +364,7 @@ class Installer {
*
* The function will check if the app is already downloaded in the apps repository
*/
- public static function isDownloaded( $name ) {
+ public function isDownloaded($name) {
foreach(\OC::$APPSROOTS as $dir) {
$dirToTest = $dir['path'];
$dirToTest .= '/';
@@ -483,7 +381,7 @@ class Installer {
/**
* Removes an app
- * @param string $name name of the application to remove
+ * @param string $appId ID of the application to remove
* @return boolean
*
*
@@ -494,12 +392,10 @@ class Installer {
* The function will not delete preferences, tables and the configuration,
* this has to be done by the function oc_app_uninstall().
*/
- public static function removeApp($appId) {
-
- if(Installer::isDownloaded( $appId )) {
- $appDir=OC_App::getInstallPath() . '/' . $appId;
+ public function removeApp($appId) {
+ if($this->isDownloaded( $appId )) {
+ $appDir = OC_App::getInstallPath() . '/' . $appId;
OC_Helper::rmdirr($appDir);
-
return true;
}else{
\OCP\Util::writeLog('core', 'can\'t remove app '.$appId.'. It is not installed.', \OCP\Util::ERROR);
@@ -620,7 +516,7 @@ class Installer {
}
/**
- * @param $basedir
+ * @param string $script
*/
private static function includeAppScript($script) {
if ( file_exists($script) ){
diff --git a/lib/private/OCSClient.php b/lib/private/OCSClient.php
deleted file mode 100644
index 76c0b136c06..00000000000
--- a/lib/private/OCSClient.php
+++ /dev/null
@@ -1,351 +0,0 @@
-<?php
-/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Brice Maron <brice@bmaron.net>
- * @author Felix Moeller <mail@felixmoeller.de>
- * @author Frank Karlitschek <frank@karlitschek.de>
- * @author Jarrett <JetUni@users.noreply.github.com>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Kamil Domanski <kdomanski@kdemail.net>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Sam Tuke <mail@samtuke.com>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
- */
-
-namespace OC;
-
-use OCP\Http\Client\IClientService;
-use OCP\IConfig;
-use OCP\ILogger;
-
-/**
- * Class OCSClient is a class for communication with the ownCloud appstore
- *
- * @package OC
- */
-class OCSClient {
- /** @var IClientService */
- private $httpClientService;
- /** @var IConfig */
- private $config;
- /** @var ILogger */
- private $logger;
-
- /**
- * @param IClientService $httpClientService
- * @param IConfig $config
- * @param ILogger $logger
- */
- public function __construct(IClientService $httpClientService,
- IConfig $config,
- ILogger $logger) {
- $this->httpClientService = $httpClientService;
- $this->config = $config;
- $this->logger = $logger;
- }
-
- /**
- * Returns whether the AppStore is enabled (i.e. because the AppStore is disabled for EE)
- *
- * @return bool
- */
- public function isAppStoreEnabled() {
- return $this->config->getSystemValue('appstoreenabled', true) === true;
- }
-
- /**
- * Get the url of the OCS AppStore server.
- *
- * @return string of the AppStore server
- */
- private function getAppStoreUrl() {
- return $this->config->getSystemValue('appstoreurl', 'https://api.owncloud.com/v1');
- }
-
- /**
- * @param string $body
- * @param string $action
- * @return null|\SimpleXMLElement
- */
- private function loadData($body, $action) {
- $loadEntities = libxml_disable_entity_loader(true);
- $data = @simplexml_load_string($body);
- libxml_disable_entity_loader($loadEntities);
-
- if($data === false) {
- libxml_clear_errors();
- $this->logger->error(
- sprintf('Could not get %s, content was no valid XML', $action),
- [
- 'app' => 'core',
- ]
- );
- return null;
- }
-
- return $data;
- }
-
- /**
- * Get all the categories from the OCS server
- *
- * @param array $targetVersion The target ownCloud version
- * @return array|null an array of category ids or null
- * @note returns NULL if config value appstoreenabled is set to false
- * This function returns a list of all the application categories on the OCS server
- */
- public function getCategories(array $targetVersion) {
- if (!$this->isAppStoreEnabled()) {
- return null;
- }
-
- $client = $this->httpClientService->newClient();
- try {
- $response = $client->get(
- $this->getAppStoreUrl() . '/content/categories',
- [
- 'timeout' => 20,
- 'query' => [
- 'version' => implode('x', $targetVersion),
- ],
- ]
- );
- } catch(\Exception $e) {
- $this->logger->error(
- sprintf('Could not get categories: %s', $e->getMessage()),
- [
- 'app' => 'core',
- ]
- );
- return null;
- }
-
- $data = $this->loadData($response->getBody(), 'categories');
- if($data === null) {
- return null;
- }
-
- $tmp = $data->data;
- $cats = [];
-
- foreach ($tmp->category as $value) {
- $id = (int)$value->id;
- $name = (string)$value->name;
- $cats[$id] = $name;
- }
-
- return $cats;
- }
-
- /**
- * Get all the applications from the OCS server
- * @param array $categories
- * @param int $page
- * @param string $filter
- * @param array $targetVersion The target ownCloud version
- * @return array An array of application data
- */
- public function getApplications(array $categories, $page, $filter, array $targetVersion) {
- if (!$this->isAppStoreEnabled()) {
- return [];
- }
-
- $client = $this->httpClientService->newClient();
- try {
- $response = $client->get(
- $this->getAppStoreUrl() . '/content/data',
- [
- 'timeout' => 20,
- 'query' => [
- 'version' => implode('x', $targetVersion),
- 'filter' => $filter,
- 'categories' => implode('x', $categories),
- 'sortmode' => 'new',
- 'page' => $page,
- 'pagesize' => 100,
- 'approved' => $filter
- ],
- ]
- );
- } catch(\Exception $e) {
- $this->logger->error(
- sprintf('Could not get applications: %s', $e->getMessage()),
- [
- 'app' => 'core',
- ]
- );
- return [];
- }
-
- $data = $this->loadData($response->getBody(), 'applications');
- if($data === null) {
- return [];
- }
-
- $tmp = $data->data->content;
- $tmpCount = count($tmp);
-
- $apps = [];
- for ($i = 0; $i < $tmpCount; $i++) {
- $app = [];
- $app['id'] = (string)$tmp[$i]->id;
- $app['name'] = (string)$tmp[$i]->name;
- $app['label'] = (string)$tmp[$i]->label;
- $app['version'] = (string)$tmp[$i]->version;
- $app['type'] = (string)$tmp[$i]->typeid;
- $app['typename'] = (string)$tmp[$i]->typename;
- $app['personid'] = (string)$tmp[$i]->personid;
- $app['profilepage'] = (string)$tmp[$i]->profilepage;
- $app['license'] = (string)$tmp[$i]->license;
- $app['detailpage'] = (string)$tmp[$i]->detailpage;
- $app['preview'] = (string)$tmp[$i]->smallpreviewpic1;
- $app['preview-full'] = (string)$tmp[$i]->previewpic1;
- $app['changed'] = strtotime($tmp[$i]->changed);
- $app['description'] = (string)$tmp[$i]->description;
- $app['score'] = (string)$tmp[$i]->score;
- $app['downloads'] = (int)$tmp[$i]->downloads;
- $app['level'] = (int)$tmp[$i]->approved;
-
- $apps[] = $app;
- }
-
- return $apps;
- }
-
-
- /**
- * Get an the applications from the OCS server
- *
- * @param string $id
- * @param array $targetVersion The target ownCloud version
- * @return array|null an array of application data or null
- *
- * This function returns an applications from the OCS server
- */
- public function getApplication($id, array $targetVersion) {
- if (!$this->isAppStoreEnabled()) {
- return null;
- }
-
- $client = $this->httpClientService->newClient();
- try {
- $response = $client->get(
- $this->getAppStoreUrl() . '/content/data/' . urlencode($id),
- [
- 'timeout' => 20,
- 'query' => [
- 'version' => implode('x', $targetVersion),
- ],
- ]
- );
- } catch(\Exception $e) {
- $this->logger->error(
- sprintf('Could not get application: %s', $e->getMessage()),
- [
- 'app' => 'core',
- ]
- );
- return null;
- }
-
- $data = $this->loadData($response->getBody(), 'application');
- if($data === null) {
- return null;
- }
-
- $tmp = $data->data->content;
- if (is_null($tmp)) {
- \OCP\Util::writeLog('core', 'No update found at the ownCloud appstore for app ' . $id, \OCP\Util::DEBUG);
- return null;
- }
-
- $app = [];
- $app['id'] = (int)$id;
- $app['name'] = (string)$tmp->name;
- $app['version'] = (string)$tmp->version;
- $app['type'] = (string)$tmp->typeid;
- $app['label'] = (string)$tmp->label;
- $app['typename'] = (string)$tmp->typename;
- $app['personid'] = (string)$tmp->personid;
- $app['profilepage'] = (string)$tmp->profilepage;
- $app['detailpage'] = (string)$tmp->detailpage;
- $app['preview1'] = (string)$tmp->smallpreviewpic1;
- $app['preview2'] = (string)$tmp->smallpreviewpic2;
- $app['preview3'] = (string)$tmp->smallpreviewpic3;
- $app['changed'] = strtotime($tmp->changed);
- $app['description'] = (string)$tmp->description;
- $app['detailpage'] = (string)$tmp->detailpage;
- $app['score'] = (int)$tmp->score;
- $app['level'] = (int)$tmp->approved;
-
- return $app;
- }
-
- /**
- * Get the download url for an application from the OCS server
- * @param string $id
- * @param array $targetVersion The target ownCloud version
- * @return array|null an array of application data or null
- */
- public function getApplicationDownload($id, array $targetVersion) {
- if (!$this->isAppStoreEnabled()) {
- return null;
- }
- $url = $this->getAppStoreUrl() . '/content/download/' . urlencode($id) . '/1';
- $client = $this->httpClientService->newClient();
- try {
- $response = $client->get(
- $url,
- [
- 'timeout' => 20,
- 'query' => [
- 'version' => implode('x', $targetVersion),
- ],
- ]
- );
- } catch(\Exception $e) {
- $this->logger->error(
- sprintf('Could not get application download URL: %s', $e->getMessage()),
- [
- 'app' => 'core',
- ]
- );
- return null;
- }
-
- $data = $this->loadData($response->getBody(), 'application download URL');
- if($data === null) {
- return null;
- }
-
- $tmp = $data->data->content;
- $app = [];
- if (isset($tmp->downloadlink)) {
- $app['downloadlink'] = (string)$tmp->downloadlink;
- } else {
- $app['downloadlink'] = '';
- }
- return $app;
- }
-
-}
diff --git a/lib/private/Security/CSRF/TokenStorage/SessionStorage.php b/lib/private/Security/CSRF/TokenStorage/SessionStorage.php
index cf4cdfa5036..9d2e723a6d3 100644
--- a/lib/private/Security/CSRF/TokenStorage/SessionStorage.php
+++ b/lib/private/Security/CSRF/TokenStorage/SessionStorage.php
@@ -41,6 +41,13 @@ class SessionStorage {
}
/**
+ * @param ISession $session
+ */
+ public function setSession(ISession $session) {
+ $this->session = $session;
+ }
+
+ /**
* Returns the current token or throws an exception if none is found.
*
* @return string
diff --git a/lib/private/Server.php b/lib/private/Server.php
index 21ec311401d..dca50c15733 100644
--- a/lib/private/Server.php
+++ b/lib/private/Server.php
@@ -1,6 +1,7 @@
<?php
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
+ * @copyright Copyright (c) 2016, Lukas Reschke <lukas@statuscode.ch>
*
* @author Arthur Schiwon <blizzz@arthur-schiwon.de>
* @author Bart Visscher <bartv@thisnet.nl>
@@ -41,6 +42,8 @@
namespace OC;
use bantu\IniGetWrapper\IniGetWrapper;
+use OC\App\AppStore\Fetcher\AppFetcher;
+use OC\App\AppStore\Fetcher\CategoryFetcher;
use OC\AppFramework\Http\Request;
use OC\AppFramework\Db\Db;
use OC\AppFramework\Utility\TimeFactory;
@@ -242,7 +245,7 @@ class Server extends ServerContainer implements IServerContainer {
$defaultTokenProvider = null;
}
- $userSession = new \OC\User\Session($manager, $session, $timeFactory, $defaultTokenProvider, $c->getConfig());
+ $userSession = new \OC\User\Session($manager, $session, $timeFactory, $defaultTokenProvider, $c->getConfig(), $c->getSecureRandom());
$userSession->listen('\OC\User', 'preCreateUser', function ($uid, $password) {
\OC_Hook::emit('OC_User', 'pre_createUser', array('run' => true, 'uid' => $uid, 'password' => $password));
});
@@ -283,7 +286,7 @@ class Server extends ServerContainer implements IServerContainer {
return $userSession;
});
- $this->registerService('\OC\Authentication\TwoFactorAuth\Manager', function (Server $c) {
+ $this->registerService(\OC\Authentication\TwoFactorAuth\Manager::class, function (Server $c) {
return new \OC\Authentication\TwoFactorAuth\Manager($c->getAppManager(), $c->getSession(), $c->getConfig());
});
@@ -320,6 +323,21 @@ class Server extends ServerContainer implements IServerContainer {
$this->registerService('AppHelper', function ($c) {
return new \OC\AppHelper();
});
+ $this->registerService('AppFetcher', function ($c) {
+ return new AppFetcher(
+ $this->getAppDataDir('appstore'),
+ $this->getHTTPClientService(),
+ $this->query(TimeFactory::class),
+ $this->getConfig()
+ );
+ });
+ $this->registerService('CategoryFetcher', function ($c) {
+ return new CategoryFetcher(
+ $this->getAppDataDir('appstore'),
+ $this->getHTTPClientService(),
+ $this->query(TimeFactory::class)
+ );
+ });
$this->registerService('UserCache', function ($c) {
return new Cache\File();
});
@@ -580,13 +598,6 @@ class Server extends ServerContainer implements IServerContainer {
$c->getThemingDefaults()
);
});
- $this->registerService('OcsClient', function (Server $c) {
- return new OCSClient(
- $this->getHTTPClientService(),
- $this->getConfig(),
- $this->getLogger()
- );
- });
$this->registerService('LDAPProvider', function(Server $c) {
$config = $c->getConfig();
$factoryClass = $config->getSystemValue('ldapProviderFactory', null);
@@ -699,13 +710,15 @@ class Server extends ServerContainer implements IServerContainer {
});
$this->registerService('CsrfTokenManager', function (Server $c) {
$tokenGenerator = new CsrfTokenGenerator($c->getSecureRandom());
- $sessionStorage = new SessionStorage($c->getSession());
return new CsrfTokenManager(
$tokenGenerator,
- $sessionStorage
+ $c->query(SessionStorage::class)
);
});
+ $this->registerService(SessionStorage::class, function (Server $c) {
+ return new SessionStorage($c->getSession());
+ });
$this->registerService('ContentSecurityPolicyManager', function (Server $c) {
return new ContentSecurityPolicyManager();
});
@@ -934,6 +947,7 @@ class Server extends ServerContainer implements IServerContainer {
* @param \OCP\ISession $session
*/
public function setSession(\OCP\ISession $session) {
+ $this->query(SessionStorage::class)->setSession($session);
return $this->query('UserSession')->setSession($session);
}
@@ -1008,6 +1022,13 @@ class Server extends ServerContainer implements IServerContainer {
}
/**
+ * @return AppFetcher
+ */
+ public function getAppFetcher() {
+ return $this->query('AppFetcher');
+ }
+
+ /**
* Returns an ICache instance. Since 8.1.0 it returns a fake cache. Use
* getMemCacheFactory() instead.
*
diff --git a/lib/private/Setup/MySQL.php b/lib/private/Setup/MySQL.php
index c022616d8b3..d1399c8821c 100644
--- a/lib/private/Setup/MySQL.php
+++ b/lib/private/Setup/MySQL.php
@@ -87,14 +87,22 @@ class MySQL extends AbstractDatabase {
* @throws \OC\DatabaseSetupException
*/
private function createDBUser($connection) {
- $name = $this->dbUser;
- $password = $this->dbPassword;
- // we need to create 2 accounts, one for global use and one for local user. if we don't specify the local one,
- // the anonymous user would take precedence when there is one.
- $query = "CREATE USER '$name'@'localhost' IDENTIFIED BY '$password'";
- $connection->executeUpdate($query);
- $query = "CREATE USER '$name'@'%' IDENTIFIED BY '$password'";
- $connection->executeUpdate($query);
+ try{
+ $name = $this->dbUser;
+ $password = $this->dbPassword;
+ // we need to create 2 accounts, one for global use and one for local user. if we don't specify the local one,
+ // the anonymous user would take precedence when there is one.
+ $query = "CREATE USER '$name'@'localhost' IDENTIFIED BY '$password'";
+ $connection->executeUpdate($query);
+ $query = "CREATE USER '$name'@'%' IDENTIFIED BY '$password'";
+ $connection->executeUpdate($query);
+ }
+ catch (\Exception $ex){
+ $this->logger->error('Database User creation failed: {error}', [
+ 'app' => 'mysql.setup',
+ 'error' => $ex->getMessage()
+ ]);
+ }
}
/**
diff --git a/lib/private/Updater.php b/lib/private/Updater.php
index 646fc031a83..e7f7a944902 100644
--- a/lib/private/Updater.php
+++ b/lib/private/Updater.php
@@ -1,6 +1,7 @@
<?php
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
+ * @copyright Copyright (c) 2016, Lukas Reschke <lukas@statuscode.ch>
*
* @author Arthur Schiwon <blizzz@arthur-schiwon.de>
* @author Frank Karlitschek <frank@karlitschek.de>
@@ -381,6 +382,9 @@ class Updater extends BasicEmitter {
// check if the app is compatible with this version of ownCloud
$info = OC_App::getAppInfo($app);
if(!OC_App::isAppCompatible($version, $info)) {
+ if (OC_App::isShipped($app)) {
+ throw new \UnexpectedValueException('The files of the app "' . $app . '" were not correctly replaced before running the update');
+ }
OC_App::disable($app);
$this->emit('\OC\Updater', 'incompatibleAppDisabled', array($app));
}
@@ -426,11 +430,15 @@ class Updater extends BasicEmitter {
private function upgradeAppStoreApps(array $disabledApps) {
foreach($disabledApps as $app) {
try {
- if (Installer::isUpdateAvailable($app)) {
- $ocsId = \OC::$server->getConfig()->getAppValue($app, 'ocsid', '');
-
- $this->emit('\OC\Updater', 'upgradeAppStoreApp', array($app));
- Installer::updateAppByOCSId($ocsId);
+ $installer = new Installer(
+ \OC::$server->getAppFetcher(),
+ \OC::$server->getHTTPClientService(),
+ \OC::$server->getTempManager(),
+ $this->log
+ );
+ if (Installer::isUpdateAvailable($app, \OC::$server->getAppFetcher())) {
+ $this->emit('\OC\Updater', 'upgradeAppStoreApp', [$app]);
+ $installer->updateAppstoreApp($app);
}
} catch (\Exception $ex) {
$this->log->logException($ex, ['app' => 'core']);
diff --git a/lib/private/User/Session.php b/lib/private/User/Session.php
index a213ee48c2a..7215cbe4188 100644
--- a/lib/private/User/Session.php
+++ b/lib/private/User/Session.php
@@ -48,6 +48,7 @@ use OCP\ISession;
use OCP\IUser;
use OCP\IUserManager;
use OCP\IUserSession;
+use OCP\Security\ISecureRandom;
use OCP\Session\Exceptions\SessionNotAvailableException;
use OCP\Util;
@@ -89,23 +90,29 @@ class Session implements IUserSession, Emitter {
/** @var User $activeUser */
protected $activeUser;
+ /** @var ISecureRandom */
+ private $random;
+
/**
* @param IUserManager $manager
* @param ISession $session
* @param ITimeFactory $timeFacory
* @param IProvider $tokenProvider
* @param IConfig $config
+ * @param ISecureRandom $random
*/
public function __construct(IUserManager $manager,
ISession $session,
ITimeFactory $timeFacory,
$tokenProvider,
- IConfig $config) {
+ IConfig $config,
+ ISecureRandom $random) {
$this->manager = $manager;
$this->session = $session;
$this->timeFacory = $timeFacory;
$this->tokenProvider = $tokenProvider;
$this->config = $config;
+ $this->random = $random;
}
/**
@@ -526,9 +533,10 @@ class Session implements IUserSession, Emitter {
* @param string $uid user UID
* @param string $loginName login name
* @param string $password
+ * @param int $remember
* @return boolean
*/
- public function createSessionToken(IRequest $request, $uid, $loginName, $password = null) {
+ public function createSessionToken(IRequest $request, $uid, $loginName, $password = null, $remember = IToken::DO_NOT_REMEMBER) {
if (is_null($this->manager->get($uid))) {
// User does not exist
return false;
@@ -537,7 +545,7 @@ class Session implements IUserSession, Emitter {
try {
$sessionId = $this->session->getId();
$pwd = $this->getPassword($password);
- $this->tokenProvider->generateToken($sessionId, $uid, $loginName, $pwd, $name);
+ $this->tokenProvider->generateToken($sessionId, $uid, $loginName, $pwd, $name, IToken::TEMPORARY_TOKEN, IToken::REMEMBER);
return true;
} catch (SessionNotAvailableException $ex) {
// This can happen with OCC, where a memory session is used
@@ -680,9 +688,10 @@ class Session implements IUserSession, Emitter {
*
* @param string $uid the username
* @param string $currentToken
+ * @param string $oldSessionId
* @return bool
*/
- public function loginWithCookie($uid, $currentToken) {
+ public function loginWithCookie($uid, $currentToken, $oldSessionId) {
$this->session->regenerateId();
$this->manager->emit('\OC\User', 'preRememberedLogin', array($uid));
$user = $this->manager->get($uid);
@@ -692,15 +701,26 @@ class Session implements IUserSession, Emitter {
}
// get stored tokens
- $tokens = OC::$server->getConfig()->getUserKeys($uid, 'login_token');
+ $tokens = $this->config->getUserKeys($uid, 'login_token');
// test cookies token against stored tokens
if (!in_array($currentToken, $tokens, true)) {
return false;
}
// replace successfully used token with a new one
- OC::$server->getConfig()->deleteUserValue($uid, 'login_token', $currentToken);
- $newToken = OC::$server->getSecureRandom()->generate(32);
- OC::$server->getConfig()->setUserValue($uid, 'login_token', $newToken, time());
+ $this->config->deleteUserValue($uid, 'login_token', $currentToken);
+ $newToken = $this->random->generate(32);
+ $this->config->setUserValue($uid, 'login_token', $newToken, $this->timeFacory->getTime());
+
+ try {
+ $sessionId = $this->session->getId();
+ $this->tokenProvider->renewSessionToken($oldSessionId, $sessionId);
+ } catch (SessionNotAvailableException $ex) {
+ return false;
+ } catch (InvalidTokenException $ex) {
+ \OC::$server->getLogger()->warning('Renewing session token failed', ['app' => 'core']);
+ return false;
+ }
+
$this->setMagicInCookie($user->getUID(), $newToken);
//login
@@ -710,6 +730,15 @@ class Session implements IUserSession, Emitter {
}
/**
+ * @param IUser $user
+ */
+ public function createRememberMeToken(IUser $user) {
+ $token = $this->random->generate(32);
+ $this->config->setUserValue($user->getUID(), 'login_token', $token, $this->timeFacory->getTime());
+ $this->setMagicInCookie($user->getUID(), $token);
+ }
+
+ /**
* logout the user from the session
*/
public function logout() {
@@ -736,10 +765,19 @@ class Session implements IUserSession, Emitter {
*/
public function setMagicInCookie($username, $token) {
$secureCookie = OC::$server->getRequest()->getServerProtocol() === 'https';
- $expires = time() + OC::$server->getConfig()->getSystemValue('remember_login_cookie_lifetime', 60 * 60 * 24 * 15);
- setcookie('oc_username', $username, $expires, OC::$WEBROOT, '', $secureCookie, true);
- setcookie('oc_token', $token, $expires, OC::$WEBROOT, '', $secureCookie, true);
- setcookie('oc_remember_login', '1', $expires, OC::$WEBROOT, '', $secureCookie, true);
+ $webRoot = \OC::$WEBROOT;
+ if ($webRoot === '') {
+ $webRoot = '/';
+ }
+
+ $expires = $this->timeFacory->getTime() + $this->config->getSystemValue('remember_login_cookie_lifetime', 60 * 60 * 24 * 15);
+ setcookie('nc_username', $username, $expires, $webRoot, '', $secureCookie, true);
+ setcookie('nc_token', $token, $expires, $webRoot, '', $secureCookie, true);
+ try {
+ setcookie('nc_session_id', $this->session->getId(), $expires, $webRoot, '', $secureCookie, true);
+ } catch (SessionNotAvailableException $ex) {
+ // ignore
+ }
}
/**
@@ -749,17 +787,17 @@ class Session implements IUserSession, Emitter {
//TODO: DI for cookies and IRequest
$secureCookie = OC::$server->getRequest()->getServerProtocol() === 'https';
- unset($_COOKIE['oc_username']); //TODO: DI
- unset($_COOKIE['oc_token']);
- unset($_COOKIE['oc_remember_login']);
- setcookie('oc_username', '', time() - 3600, OC::$WEBROOT, '', $secureCookie, true);
- setcookie('oc_token', '', time() - 3600, OC::$WEBROOT, '', $secureCookie, true);
- setcookie('oc_remember_login', '', time() - 3600, OC::$WEBROOT, '', $secureCookie, true);
+ unset($_COOKIE['nc_username']); //TODO: DI
+ unset($_COOKIE['nc_token']);
+ unset($_COOKIE['nc_session_id']);
+ setcookie('nc_username', '', $this->timeFacory->getTime() - 3600, OC::$WEBROOT, '', $secureCookie, true);
+ setcookie('nc_token', '', $this->timeFacory->getTime() - 3600, OC::$WEBROOT, '', $secureCookie, true);
+ setcookie('nc_session_id', '', $this->timeFacory->getTime() - 3600, OC::$WEBROOT, '', $secureCookie, true);
// old cookies might be stored under /webroot/ instead of /webroot
// and Firefox doesn't like it!
- setcookie('oc_username', '', time() - 3600, OC::$WEBROOT . '/', '', $secureCookie, true);
- setcookie('oc_token', '', time() - 3600, OC::$WEBROOT . '/', '', $secureCookie, true);
- setcookie('oc_remember_login', '', time() - 3600, OC::$WEBROOT . '/', '', $secureCookie, true);
+ setcookie('nc_username', '', $this->timeFacory->getTime() - 3600, OC::$WEBROOT . '/', '', $secureCookie, true);
+ setcookie('nc_token', '', $this->timeFacory->getTime() - 3600, OC::$WEBROOT . '/', '', $secureCookie, true);
+ setcookie('nc_session_id', '', $this->timeFacory->getTime() - 3600, OC::$WEBROOT . '/', '', $secureCookie, true);
}
/**
@@ -779,4 +817,5 @@ class Session implements IUserSession, Emitter {
}
}
+
}
diff --git a/lib/private/legacy/app.php b/lib/private/legacy/app.php
index d25534aa822..a89a4650c5d 100644
--- a/lib/private/legacy/app.php
+++ b/lib/private/legacy/app.php
@@ -1,6 +1,7 @@
<?php
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
+ * @copyright Copyright (c) 2016, Lukas Reschke <lukas@statuscode.ch>
*
* @author Arthur Schiwon <blizzz@arthur-schiwon.de>
* @author Bart Visscher <bartv@thisnet.nl>
@@ -326,24 +327,44 @@ class OC_App {
/**
* enables an app
*
- * @param mixed $app app
+ * @param string $appId
* @param array $groups (optional) when set, only these groups will have access to the app
* @throws \Exception
* @return void
*
* This function set an app as enabled in appconfig.
*/
- public static function enable($app, $groups = null) {
+ public function enable($appId,
+ $groups = null) {
self::$enabledAppsCache = []; // flush
- if (!Installer::isInstalled($app)) {
- $app = self::installApp($app);
+ $l = \OC::$server->getL10N('core');
+ $config = \OC::$server->getConfig();
+
+ // Check if app is already downloaded
+ $installer = new Installer(
+ \OC::$server->getAppFetcher(),
+ \OC::$server->getHTTPClientService(),
+ \OC::$server->getTempManager(),
+ \OC::$server->getLogger()
+ );
+ $isDownloaded = $installer->isDownloaded($appId);
+
+ if(!$isDownloaded) {
+ $installer->downloadApp($appId);
+ }
+
+ if (!Installer::isInstalled($appId)) {
+ $appId = self::installApp(
+ $appId,
+ $config,
+ $l
+ );
+ $installer->installApp($appId);
} else {
// check for required dependencies
- $config = \OC::$server->getConfig();
- $l = \OC::$server->getL10N('core');
- $info = self::getAppInfo($app);
-
+ $info = self::getAppInfo($appId);
self::checkAppDependencies($config, $l, $info);
+ $installer->installApp($appId);
}
$appManager = \OC::$server->getAppManager();
@@ -356,42 +377,21 @@ class OC_App {
$groupsList[] = $groupManager->get($group);
}
}
- $appManager->enableAppForGroups($app, $groupsList);
+ $appManager->enableAppForGroups($appId, $groupsList);
} else {
- $appManager->enableApp($app);
+ $appManager->enableApp($appId);
}
- $info = self::getAppInfo($app);
+ $info = self::getAppInfo($appId);
if(isset($info['settings']) && is_array($info['settings'])) {
- $appPath = self::getAppPath($app);
- self::registerAutoloading($app, $appPath);
+ $appPath = self::getAppPath($appId);
+ self::registerAutoloading($appId, $appPath);
\OC::$server->getSettingsManager()->setupSettings($info['settings']);
}
}
/**
* @param string $app
- * @return int
- */
- private static function downloadApp($app) {
- $ocsClient = new OCSClient(
- \OC::$server->getHTTPClientService(),
- \OC::$server->getConfig(),
- \OC::$server->getLogger()
- );
- $appData = $ocsClient->getApplication($app, \OCP\Util::getVersion());
- $download = $ocsClient->getApplicationDownload($app, \OCP\Util::getVersion());
- if(isset($download['downloadlink']) and $download['downloadlink']!='') {
- // Replace spaces in download link without encoding entire URL
- $download['downloadlink'] = str_replace(' ', '%20', $download['downloadlink']);
- $info = array('source' => 'http', 'href' => $download['downloadlink'], 'appdata' => $appData);
- $app = Installer::installApp($info);
- }
- return $app;
- }
-
- /**
- * @param string $app
* @return bool
*/
public static function removeApp($app) {
@@ -399,7 +399,13 @@ class OC_App {
return false;
}
- return Installer::removeApp($app);
+ $installer = new Installer(
+ \OC::$server->getAppFetcher(),
+ \OC::$server->getHTTPClientService(),
+ \OC::$server->getTempManager(),
+ \OC::$server->getLogger()
+ );
+ return $installer->removeApp($app);
}
/**
@@ -409,11 +415,6 @@ class OC_App {
* @throws Exception
*/
public static function disable($app) {
- // Convert OCS ID to regular application identifier
- if(self::getInternalAppIdByOcs($app) !== false) {
- $app = self::getInternalAppIdByOcs($app);
- }
-
// flush
self::$enabledAppsCache = array();
@@ -554,7 +555,7 @@ class OC_App {
* @param string $appId
* @return false|string
*/
- protected static function findAppInDirectories($appId) {
+ public static function findAppInDirectories($appId) {
$sanitizedAppId = self::cleanAppId($appId);
if($sanitizedAppId !== $appId) {
return false;
@@ -613,18 +614,6 @@ class OC_App {
return false;
}
-
- /**
- * check if an app's directory is writable
- *
- * @param string $appId
- * @return bool
- */
- public static function isAppDirWritable($appId) {
- $path = self::getAppPath($appId);
- return ($path !== false) ? is_writable($path) : false;
- }
-
/**
* Get the path for the given app on the access
* If the app is defined in multiple directories, the first one is taken. (false if not found)
@@ -837,20 +826,11 @@ class OC_App {
/**
* List all apps, this is used in apps.php
*
- * @param bool $onlyLocal
- * @param bool $includeUpdateInfo Should we check whether there is an update
- * in the app store?
- * @param OCSClient $ocsClient
* @return array
*/
- public static function listAllApps($onlyLocal = false,
- $includeUpdateInfo = true,
- OCSClient $ocsClient) {
+ public function listAllApps() {
$installedApps = OC_App::getAllApps();
- //TODO which apps do we want to blacklist and how do we integrate
- // blacklisting with the multi apps folder feature?
-
//we don't want to show configuration for these
$blacklist = \OC::$server->getAppManager()->getAlwaysEnabledApps();
$appList = array();
@@ -893,8 +873,6 @@ class OC_App {
$info['removable'] = true;
}
- $info['update'] = ($includeUpdateInfo) ? Installer::isUpdateAvailable($app) : null;
-
$appPath = self::getAppPath($app);
if($appPath !== false) {
$appIcon = $appPath . '/img/' . $app . '.svg';
@@ -926,29 +904,8 @@ class OC_App {
$appList[] = $info;
}
}
- if ($onlyLocal) {
- $remoteApps = [];
- } else {
- $remoteApps = OC_App::getAppstoreApps('approved', null, $ocsClient);
- }
- if ($remoteApps) {
- // Remove duplicates
- foreach ($appList as $app) {
- foreach ($remoteApps AS $key => $remote) {
- if ($app['name'] === $remote['name'] ||
- (isset($app['ocsid']) &&
- $app['ocsid'] === $remote['id'])
- ) {
- unset($remoteApps[$key]);
- }
- }
- }
- $combinedApps = array_merge($appList, $remoteApps);
- } else {
- $combinedApps = $appList;
- }
- return $combinedApps;
+ return $appList;
}
/**
@@ -966,70 +923,6 @@ class OC_App {
return false;
}
- /**
- * Get a list of all apps on the appstore
- * @param string $filter
- * @param string|null $category
- * @param OCSClient $ocsClient
- * @return array|bool multi-dimensional array of apps.
- * Keys: id, name, type, typename, personid, license, detailpage, preview, changed, description
- */
- public static function getAppstoreApps($filter = 'approved',
- $category = null,
- OCSClient $ocsClient) {
- $categories = [$category];
-
- if (is_null($category)) {
- $categoryNames = $ocsClient->getCategories(\OCP\Util::getVersion());
- if (is_array($categoryNames)) {
- // Check that categories of apps were retrieved correctly
- if (!$categories = array_keys($categoryNames)) {
- return false;
- }
- } else {
- return false;
- }
- }
-
- $page = 0;
- $remoteApps = $ocsClient->getApplications($categories, $page, $filter, \OCP\Util::getVersion());
- $apps = [];
- $i = 0;
- $l = \OC::$server->getL10N('core');
- foreach ($remoteApps as $app) {
- $potentialCleanId = self::getInternalAppIdByOcs($app['id']);
- // enhance app info (for example the description)
- $apps[$i] = OC_App::parseAppInfo($app);
- $apps[$i]['author'] = $app['personid'];
- $apps[$i]['ocs_id'] = $app['id'];
- $apps[$i]['internal'] = 0;
- $apps[$i]['active'] = ($potentialCleanId !== false) ? self::isEnabled($potentialCleanId) : false;
- $apps[$i]['update'] = false;
- $apps[$i]['groups'] = false;
- $apps[$i]['score'] = $app['score'];
- $apps[$i]['removable'] = false;
- if ($app['label'] == 'recommended') {
- $apps[$i]['internallabel'] = (string)$l->t('Recommended');
- $apps[$i]['internalclass'] = 'recommendedapp';
- }
-
- // Apps from the appstore are always assumed to be compatible with the
- // the current release as the initial filtering is done on the appstore
- $apps[$i]['dependencies']['owncloud']['@attributes']['min-version'] = implode('.', \OCP\Util::getVersion());
- $apps[$i]['dependencies']['owncloud']['@attributes']['max-version'] = implode('.', \OCP\Util::getVersion());
-
- $i++;
- }
-
-
-
- if (empty($apps)) {
- return false;
- } else {
- return $apps;
- }
- }
-
public static function shouldUpgrade($app) {
$versions = self::getAppVersions();
$currentVersion = OC_App::getAppVersion($app);
@@ -1083,7 +976,9 @@ class OC_App {
public static function isAppCompatible($ocVersion, $appInfo) {
$requireMin = '';
$requireMax = '';
- if (isset($appInfo['dependencies']['owncloud']['@attributes']['min-version'])) {
+ if (isset($appInfo['dependencies']['nextcloud']['@attributes']['min-version'])) {
+ $requireMin = $appInfo['dependencies']['nextcloud']['@attributes']['min-version'];
+ } elseif (isset($appInfo['dependencies']['owncloud']['@attributes']['min-version'])) {
$requireMin = $appInfo['dependencies']['owncloud']['@attributes']['min-version'];
} else if (isset($appInfo['requiremin'])) {
$requireMin = $appInfo['requiremin'];
@@ -1091,7 +986,9 @@ class OC_App {
$requireMin = $appInfo['require'];
}
- if (isset($appInfo['dependencies']['owncloud']['@attributes']['max-version'])) {
+ if (isset($appInfo['dependencies']['nextcloud']['@attributes']['max-version'])) {
+ $requireMax = $appInfo['dependencies']['nextcloud']['@attributes']['max-version'];
+ } elseif (isset($appInfo['dependencies']['owncloud']['@attributes']['max-version'])) {
$requireMax = $appInfo['dependencies']['owncloud']['@attributes']['max-version'];
} else if (isset($appInfo['requiremax'])) {
$requireMax = $appInfo['requiremax'];
@@ -1132,46 +1029,16 @@ class OC_App {
/**
* @param string $app
+ * @param \OCP\IConfig $config
+ * @param \OCP\IL10N $l
* @return bool
+ *
* @throws Exception if app is not compatible with this version of ownCloud
* @throws Exception if no app-name was specified
*/
- public static function installApp($app) {
- $appName = $app; // $app will be overwritten, preserve name for error logging
- $l = \OC::$server->getL10N('core');
- $config = \OC::$server->getConfig();
- $ocsClient = new OCSClient(
- \OC::$server->getHTTPClientService(),
- $config,
- \OC::$server->getLogger()
- );
- $appData = $ocsClient->getApplication($app, \OCP\Util::getVersion());
-
- // check if app is a shipped app or not. OCS apps have an integer as id, shipped apps use a string
- if (!is_numeric($app)) {
- $shippedVersion = self::getAppVersion($app);
- if ($appData && version_compare($shippedVersion, $appData['version'], '<')) {
- $app = self::downloadApp($app);
- } else {
- $app = Installer::installShippedApp($app);
- }
- } else {
- // Maybe the app is already installed - compare the version in this
- // case and use the local already installed one.
- // FIXME: This is a horrible hack. I feel sad. The god of code cleanness may forgive me.
- $internalAppId = self::getInternalAppIdByOcs($app);
- if($internalAppId !== false) {
- if($appData && version_compare(\OC_App::getAppVersion($internalAppId), $appData['version'], '<')) {
- $app = self::downloadApp($app);
- } else {
- self::enable($internalAppId);
- $app = $internalAppId;
- }
- } else {
- $app = self::downloadApp($app);
- }
- }
-
+ public function installApp($app,
+ \OCP\IConfig $config,
+ \OCP\IL10N $l) {
if ($app !== false) {
// check if the app is compatible with this version of ownCloud
$info = self::getAppInfo($app);
diff --git a/lib/private/legacy/user.php b/lib/private/legacy/user.php
index af2382dbb86..ed0d14a1ab9 100644
--- a/lib/private/legacy/user.php
+++ b/lib/private/legacy/user.php
@@ -155,10 +155,11 @@ class OC_User {
* @deprecated use \OCP\IUserSession::loginWithCookie()
* @param string $uid The username of the user to log in
* @param string $token
+ * @param string $oldSessionId
* @return bool
*/
- public static function loginWithCookie($uid, $token) {
- return self::getUserSession()->loginWithCookie($uid, $token);
+ public static function loginWithCookie($uid, $token, $oldSessionId) {
+ return self::getUserSession()->loginWithCookie($uid, $token, $oldSessionId);
}
/**
diff --git a/lib/private/legacy/util.php b/lib/private/legacy/util.php
index e4c2caeafd7..5cd92eaa415 100644
--- a/lib/private/legacy/util.php
+++ b/lib/private/legacy/util.php
@@ -757,6 +757,7 @@ class OC_Util {
'simplexml_load_string' => 'SimpleXML',
'hash' => 'HASH Message Digest Framework',
'curl_init' => 'cURL',
+ 'openssl_verify' => 'OpenSSL',
],
'defined' => array(
'PDO::ATTR_DRIVER_NAME' => 'PDO'
diff --git a/lib/public/IRequest.php b/lib/public/IRequest.php
index 11242c481f0..b36a934b0c2 100644
--- a/lib/public/IRequest.php
+++ b/lib/public/IRequest.php
@@ -145,7 +145,7 @@ interface IRequest {
* Shortcut for getting cookie variables
*
* @param string $key the key that will be taken from the $_COOKIE array
- * @return string the value in the $_COOKIE element
+ * @return string|null the value in the $_COOKIE element
* @since 6.0.0
*/
public function getCookie($key);