summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorArthur Schiwon <blizzz@arthur-schiwon.de>2018-06-26 17:25:37 +0200
committerMorris Jobke <hey@morrisjobke.de>2018-06-29 09:11:04 +0200
commit25d9c3e52921b107383e5d05f3649178bd7cd1cf (patch)
tree837fb580784174aa14a1d412056b1e9bf4f61772 /lib
parent4ed8ee1c1e8ada0e5d26f6e014896accc89d4d6a (diff)
downloadnextcloud-server-25d9c3e52921b107383e5d05f3649178bd7cd1cf.tar.gz
nextcloud-server-25d9c3e52921b107383e5d05f3649178bd7cd1cf.zip
adjust backend and gui to update and changelog server
Signed-off-by: Arthur Schiwon <blizzz@arthur-schiwon.de>
Diffstat (limited to 'lib')
-rw-r--r--lib/composer/composer/autoload_classmap.php4
-rw-r--r--lib/composer/composer/autoload_static.php4
-rw-r--r--lib/private/L10N/Factory.php32
-rw-r--r--lib/private/Updater/ChangesCheck.php157
-rw-r--r--lib/private/Updater/ChangesMapper.php57
-rw-r--r--lib/private/Updater/ChangesResult.php61
-rw-r--r--lib/private/Updater/VersionCheck.php9
-rw-r--r--lib/public/L10N/IFactory.php10
8 files changed, 328 insertions, 6 deletions
diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php
index b416d6e77bd..a3d4564e3f9 100644
--- a/lib/composer/composer/autoload_classmap.php
+++ b/lib/composer/composer/autoload_classmap.php
@@ -595,6 +595,7 @@ return array(
'OC\\Core\\Migrations\\Version14000Date20180516101403' => $baseDir . '/core/Migrations/Version14000Date20180516101403.php',
'OC\\Core\\Migrations\\Version14000Date20180518120534' => $baseDir . '/core/Migrations/Version14000Date20180518120534.php',
'OC\\Core\\Migrations\\Version14000Date20180522074438' => $baseDir . '/core/Migrations/Version14000Date20180522074438.php',
+ 'OC\\Core\\Migrations\\Version14000Date20180626223656' => $baseDir . '/core/Migrations/Version14000Date20180626223656.php',
'OC\\DB\\Adapter' => $baseDir . '/lib/private/DB/Adapter.php',
'OC\\DB\\AdapterMySQL' => $baseDir . '/lib/private/DB/AdapterMySQL.php',
'OC\\DB\\AdapterOCI8' => $baseDir . '/lib/private/DB/AdapterOCI8.php',
@@ -1003,6 +1004,9 @@ return array(
'OC\\Template\\TemplateFileLocator' => $baseDir . '/lib/private/Template/TemplateFileLocator.php',
'OC\\URLGenerator' => $baseDir . '/lib/private/URLGenerator.php',
'OC\\Updater' => $baseDir . '/lib/private/Updater.php',
+ 'OC\\Updater\\ChangesCheck' => $baseDir . '/lib/private/Updater/ChangesCheck.php',
+ 'OC\\Updater\\ChangesMapper' => $baseDir . '/lib/private/Updater/ChangesMapper.php',
+ 'OC\\Updater\\ChangesResult' => $baseDir . '/lib/private/Updater/ChangesResult.php',
'OC\\Updater\\VersionCheck' => $baseDir . '/lib/private/Updater/VersionCheck.php',
'OC\\User\\Backend' => $baseDir . '/lib/private/User/Backend.php',
'OC\\User\\Database' => $baseDir . '/lib/private/User/Database.php',
diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php
index 2ada951e03e..e0b158f90f8 100644
--- a/lib/composer/composer/autoload_static.php
+++ b/lib/composer/composer/autoload_static.php
@@ -625,6 +625,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\Core\\Migrations\\Version14000Date20180516101403' => __DIR__ . '/../../..' . '/core/Migrations/Version14000Date20180516101403.php',
'OC\\Core\\Migrations\\Version14000Date20180518120534' => __DIR__ . '/../../..' . '/core/Migrations/Version14000Date20180518120534.php',
'OC\\Core\\Migrations\\Version14000Date20180522074438' => __DIR__ . '/../../..' . '/core/Migrations/Version14000Date20180522074438.php',
+ 'OC\\Core\\Migrations\\Version14000Date20180626223656' => __DIR__ . '/../../..' . '/core/Migrations/Version14000Date20180626223656.php',
'OC\\DB\\Adapter' => __DIR__ . '/../../..' . '/lib/private/DB/Adapter.php',
'OC\\DB\\AdapterMySQL' => __DIR__ . '/../../..' . '/lib/private/DB/AdapterMySQL.php',
'OC\\DB\\AdapterOCI8' => __DIR__ . '/../../..' . '/lib/private/DB/AdapterOCI8.php',
@@ -1033,6 +1034,9 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\Template\\TemplateFileLocator' => __DIR__ . '/../../..' . '/lib/private/Template/TemplateFileLocator.php',
'OC\\URLGenerator' => __DIR__ . '/../../..' . '/lib/private/URLGenerator.php',
'OC\\Updater' => __DIR__ . '/../../..' . '/lib/private/Updater.php',
+ 'OC\\Updater\\ChangesCheck' => __DIR__ . '/../../..' . '/lib/private/Updater/ChangesCheck.php',
+ 'OC\\Updater\\ChangesMapper' => __DIR__ . '/../../..' . '/lib/private/Updater/ChangesMapper.php',
+ 'OC\\Updater\\ChangesResult' => __DIR__ . '/../../..' . '/lib/private/Updater/ChangesResult.php',
'OC\\Updater\\VersionCheck' => __DIR__ . '/../../..' . '/lib/private/Updater/VersionCheck.php',
'OC\\User\\Backend' => __DIR__ . '/../../..' . '/lib/private/User/Backend.php',
'OC\\User\\Database' => __DIR__ . '/../../..' . '/lib/private/User/Database.php',
diff --git a/lib/private/L10N/Factory.php b/lib/private/L10N/Factory.php
index 8c8735836bb..79495f5ff88 100644
--- a/lib/private/L10N/Factory.php
+++ b/lib/private/L10N/Factory.php
@@ -32,6 +32,7 @@ namespace OC\L10N;
use OCP\IConfig;
use OCP\IRequest;
+use OCP\IUser;
use OCP\IUserSession;
use OCP\L10N\IFactory;
@@ -321,6 +322,37 @@ class Factory implements IFactory {
return array_search($lang, $languages) !== false;
}
+ public function iterateLanguage(bool $reset = false): string {
+ static $i = 0;
+ if($reset) {
+ $i = 0;
+ }
+ switch($i) {
+ /** @noinspection PhpMissingBreakStatementInspection */
+ case 0:
+ $i++;
+ $forcedLang = $this->config->getSystemValue('force_language', false);
+ if(is_string($forcedLang)) {
+ return $forcedLang;
+ }
+ /** @noinspection PhpMissingBreakStatementInspection */
+ case 1:
+ $i++;
+ $user = $this->userSession->getUser();
+ if($user instanceof IUser) {
+ $userLang = $this->config->getUserValue($user->getUID(), 'core', 'lang', null);
+ if(is_string($userLang)) {
+ return $userLang;
+ }
+ }
+ case 2:
+ $i++;
+ return $this->config->getSystemValue('default_language', 'en');
+ default:
+ return 'en';
+ }
+ }
+
/**
* @param string $locale
* @return bool
diff --git a/lib/private/Updater/ChangesCheck.php b/lib/private/Updater/ChangesCheck.php
new file mode 100644
index 00000000000..095f63db879
--- /dev/null
+++ b/lib/private/Updater/ChangesCheck.php
@@ -0,0 +1,157 @@
+<?php
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2018 Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @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\Updater;
+
+use OCP\AppFramework\Db\DoesNotExistException;
+use OCP\Http\Client\IClientService;
+use OCP\Http\Client\IResponse;
+use OCP\ILogger;
+
+class ChangesCheck {
+ /** @var IClientService */
+ protected $clientService;
+ /** @var ChangesMapper */
+ private $mapper;
+ /** @var ILogger */
+ private $logger;
+
+ const RESPONSE_NO_CONTENT = 0;
+ const RESPONSE_USE_CACHE = 1;
+ const RESPONSE_HAS_CONTENT = 2;
+
+ public function __construct(IClientService $clientService, ChangesMapper $mapper, ILogger $logger) {
+ $this->clientService = $clientService;
+ $this->mapper = $mapper;
+ $this->logger = $logger;
+ }
+
+ /**
+ * @throws \Exception
+ */
+ public function check(string $uri, string $version): array {
+ try {
+ $version = $this->normalizeVersion($version);
+ $changesInfo = $this->mapper->getChanges($version);
+ if($changesInfo->getLastCheck() + 1800 > time()) {
+ return json_decode($changesInfo->getData(), true);
+ }
+ } catch (DoesNotExistException $e) {
+ $changesInfo = new ChangesResult();
+ }
+
+ $response = $this->queryChangesServer($uri, $changesInfo);
+
+ switch($this->evaluateResponse($response)) {
+ case self::RESPONSE_NO_CONTENT:
+ return [];
+ case self::RESPONSE_USE_CACHE:
+ return json_decode($changesInfo->getData(), true);
+ case self::RESPONSE_HAS_CONTENT:
+ default:
+ $data = $this->extractData($response->getBody());
+ $changesInfo->setData(json_encode($data));
+ $changesInfo->setEtag($response->getHeader('Etag'));
+ $this->cacheResult($changesInfo, $version);
+
+ return $data;
+ }
+ }
+
+ protected function evaluateResponse(IResponse $response): int {
+ if($response->getStatusCode() === 304) {
+ return self::RESPONSE_USE_CACHE;
+ } else if($response->getStatusCode() === 404) {
+ return self::RESPONSE_NO_CONTENT;
+ } else if($response->getStatusCode() === 200) {
+ return self::RESPONSE_HAS_CONTENT;
+ }
+ $this->logger->debug('Unexpected return code {code} from changelog server', [
+ 'app' => 'core',
+ 'code' => $response->getStatusCode(),
+ ]);
+ return self::RESPONSE_NO_CONTENT;
+ }
+
+ protected function cacheResult(ChangesResult $entry, string $version) {
+ if($entry->getVersion() === $version) {
+ $this->mapper->update($entry);
+ } else {
+ $entry->setVersion($version);
+ $this->mapper->insert($entry);
+ }
+ }
+
+ /**
+ * @throws \Exception
+ */
+ protected function queryChangesServer(string $uri, ChangesResult $entry): IResponse {
+ $headers = [];
+ if($entry->getEtag() !== '') {
+ $headers['If-None-Match'] = [$entry->getEtag()];
+ }
+
+ $entry->setLastCheck(time());
+ $client = $this->clientService->newClient();
+ return $client->get($uri, [
+ 'headers' => $headers,
+ ]);
+ }
+
+ protected function extractData($body):array {
+ $data = [];
+ if ($body) {
+ $loadEntities = libxml_disable_entity_loader(true);
+ $xml = @simplexml_load_string($body);
+ libxml_disable_entity_loader($loadEntities);
+ if ($xml !== false) {
+ $data['changelogURL'] = (string)$xml->changelog['href'];
+ $data['whatsNew'] = [];
+ foreach($xml->whatsNew as $infoSet) {
+ $data['whatsNew'][(string)$infoSet['lang']] = [
+ 'regular' => (array)$infoSet->regular->item,
+ 'admin' => (array)$infoSet->admin->item,
+ ];
+ }
+ } else {
+ libxml_clear_errors();
+ }
+ }
+ return $data;
+ }
+
+ /**
+ * returns a x.y.z form of the provided version. Extra numbers will be
+ * omitted, missing ones added as zeros.
+ */
+ protected function normalizeVersion(string $version): string {
+ $versionNumbers = array_slice(explode('.', $version), 0, 3);
+ $versionNumbers[0] = $versionNumbers[0] ?: '0'; // deal with empty input
+ while(count($versionNumbers) < 3) {
+ // changelog server expects x.y.z, pad 0 if it is too short
+ $versionNumbers[] = 0;
+ }
+ return implode('.', $versionNumbers);
+ }
+}
diff --git a/lib/private/Updater/ChangesMapper.php b/lib/private/Updater/ChangesMapper.php
new file mode 100644
index 00000000000..d1548c415ca
--- /dev/null
+++ b/lib/private/Updater/ChangesMapper.php
@@ -0,0 +1,57 @@
+<?php
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2018 Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @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\Updater;
+
+use OCP\AppFramework\Db\DoesNotExistException;
+use OCP\AppFramework\Db\QBMapper;
+use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\IDBConnection;
+
+class ChangesMapper extends QBMapper {
+ const TABLE_NAME = 'whats_new';
+
+ public function __construct(IDBConnection $db) {
+ parent::__construct($db, self::TABLE_NAME);
+ }
+
+ /**
+ * @throws DoesNotExistException
+ */
+ public function getChanges(string $version): ChangesResult {
+ /* @var $qb IQueryBuilder */
+ $qb = $this->db->getQueryBuilder();
+ $result = $qb->select('*')
+ ->from(self::TABLE_NAME)
+ ->where($qb->expr()->eq('version', $qb->createNamedParameter($version)))
+ ->execute();
+
+ $data = $result->fetch();
+ $result->closeCursor();
+ if ($data === false) {
+ throw new DoesNotExistException('Changes info is not present');
+ }
+ return ChangesResult::fromRow($data);
+ }
+}
diff --git a/lib/private/Updater/ChangesResult.php b/lib/private/Updater/ChangesResult.php
new file mode 100644
index 00000000000..95a1af3910c
--- /dev/null
+++ b/lib/private/Updater/ChangesResult.php
@@ -0,0 +1,61 @@
+<?php
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2018 Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @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\Updater;
+
+use OCP\AppFramework\Db\Entity;
+
+/**
+ * Class ChangesResult
+ *
+ * @package OC\Updater
+ * @method string getVersion()=1
+ * @method void setVersion(string $version)
+ * @method string getEtag()
+ * @method void setEtag(string $etag)
+ * @method int getLastCheck()
+ * @method void setLastCheck(int $lastCheck)
+ * @method string getData()
+ * @method void setData(string $data)
+ */
+class ChangesResult extends Entity {
+ /** @var string */
+ protected $version = '';
+
+ /** @var string */
+ protected $etag = '';
+
+ /** @var int */
+ protected $lastCheck = 0;
+
+ /** @var string */
+ protected $data = '';
+
+ public function __construct() {
+ $this->addType('version', 'string');
+ $this->addType('etag', 'string');
+ $this->addType('lastCheck', 'int');
+ $this->addType('data', 'string');
+ }
+}
diff --git a/lib/private/Updater/VersionCheck.php b/lib/private/Updater/VersionCheck.php
index bc505211634..3cbd7061fe0 100644
--- a/lib/private/Updater/VersionCheck.php
+++ b/lib/private/Updater/VersionCheck.php
@@ -55,7 +55,7 @@ class VersionCheck {
*/
public function check() {
// Look up the cache - it is invalidated all 30 minutes
- if (false && ((int)$this->config->getAppValue('core', 'lastupdatedat') + 1800) > time()) {
+ if (((int)$this->config->getAppValue('core', 'lastupdatedat') + 1800) > time()) {
return json_decode($this->config->getAppValue('core', 'lastupdateResult'), true);
}
@@ -70,7 +70,7 @@ class VersionCheck {
$version = Util::getVersion();
$version['installed'] = $this->config->getAppValue('core', 'installedat');
$version['updated'] = $this->config->getAppValue('core', 'lastupdatedat');
- $version['updatechannel'] = 'stable'; //\OC_Util::getChannel();
+ $version['updatechannel'] = \OC_Util::getChannel();
$version['edition'] = '';
$version['build'] = \OC_Util::getBuild();
$version['php_major'] = PHP_MAJOR_VERSION;
@@ -97,10 +97,7 @@ class VersionCheck {
$tmp['versionstring'] = (string)$data->versionstring;
$tmp['url'] = (string)$data->url;
$tmp['web'] = (string)$data->web;
- $tmp['changelog'] = isset($data->changelog) ? (string)$data->changelog : '';
- // TODO: one's it is decided, use the proper field…
- $tmp['whatsNew'] = isset($data->whatsNew) ? ((array)$data->whatsNew)['item'] : null;
- $tmp['whatsNew'] = isset($data->whatsNew_admin) ? ((array)$data->whatsNew_admin)['item'] : (string)$data->whatsNew;
+ $tmp['changes'] = isset($data->changes) ? (string)$data->changes : '';
$tmp['autoupdater'] = (string)$data->autoupdater;
$tmp['eol'] = isset($data->eol) ? (string)$data->eol : '0';
} else {
diff --git a/lib/public/L10N/IFactory.php b/lib/public/L10N/IFactory.php
index 263ebe81d05..9c006073200 100644
--- a/lib/public/L10N/IFactory.php
+++ b/lib/public/L10N/IFactory.php
@@ -89,4 +89,14 @@ interface IFactory {
* @since 14.0.0
*/
public function createPluralFunction($string);
+
+ /**
+ * iterate through language settings (if provided) in this order:
+ * 1. returns the forced language or:
+ * 2. returns the user language or:
+ * 3. returns the system default language or:
+ * 4+∞. returns 'en'
+ * @since 14.0.0
+ */
+ public function iterateLanguage(bool $reset = false): string;
}