Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/server.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/dav/lib/connector/sabre/principal.php18
-rw-r--r--apps/dav/lib/server.php17
-rw-r--r--apps/dav/tests/unit/connector/sabre/principal.php14
-rw-r--r--apps/encryption/lib/crypto/encryption.php74
-rw-r--r--apps/encryption/tests/lib/crypto/encryptionTest.php19
-rw-r--r--apps/files/command/deleteorphanedfiles.php30
-rw-r--r--apps/files/lib/backgroundjob/deleteorphaneditems.php41
-rw-r--r--apps/files_sharing/js/public.js3
-rw-r--r--apps/files_sharing/tests/js/publicAppSpec.js8
-rw-r--r--apps/files_versions/ajax/getVersions.php5
-rw-r--r--apps/files_versions/js/versioncollection.js3
-rw-r--r--apps/files_versions/lib/storage.php7
-rw-r--r--apps/updatenotification/controller/admincontroller.php4
-rw-r--r--apps/updatenotification/lib/resettokenbackgroundjob.php3
-rw-r--r--apps/updatenotification/tests/controller/AdminControllerTest.php4
-rw-r--r--core/templates/login.php4
-rw-r--r--core/vendor/davclient.js/lib/client.js8
-rw-r--r--lib/private/files/storage/wrapper/encryption.php4
-rw-r--r--lib/private/repair/repairinvalidshares.php24
-rw-r--r--lib/private/util.php1
20 files changed, 215 insertions, 76 deletions
diff --git a/apps/dav/lib/connector/sabre/principal.php b/apps/dav/lib/connector/sabre/principal.php
index 4f26390e3cc..a573124007d 100644
--- a/apps/dav/lib/connector/sabre/principal.php
+++ b/apps/dav/lib/connector/sabre/principal.php
@@ -49,6 +49,9 @@ class Principal implements BackendInterface {
/** @var string */
private $principalPrefix;
+ /** @var bool */
+ private $hasGroups;
+
/**
* @param IUserManager $userManager
* @param IGroupManager $groupManager
@@ -60,6 +63,7 @@ class Principal implements BackendInterface {
$this->userManager = $userManager;
$this->groupManager = $groupManager;
$this->principalPrefix = trim($principalPrefix, '/');
+ $this->hasGroups = ($principalPrefix === 'principals/users/');
}
/**
@@ -141,13 +145,15 @@ class Principal implements BackendInterface {
throw new Exception('Principal not found');
}
- $groups = $this->groupManager->getUserGroups($user);
- $groups = array_map(function($group) {
- /** @var IGroup $group */
- return $this->principalPrefix . '/' . $group->getGID();
- }, $groups);
+ if ($this->hasGroups) {
+ $groups = $this->groupManager->getUserGroups($user);
+ $groups = array_map(function($group) {
+ /** @var IGroup $group */
+ return 'principals/groups/' . $group->getGID();
+ }, $groups);
- return $groups;
+ return $groups;
+ }
}
return [];
}
diff --git a/apps/dav/lib/server.php b/apps/dav/lib/server.php
index 3bf8e155082..f5f1875a480 100644
--- a/apps/dav/lib/server.php
+++ b/apps/dav/lib/server.php
@@ -30,6 +30,10 @@ use OCA\DAV\Files\CustomPropertiesBackend;
use OCP\IRequest;
use OCP\SabrePluginEvent;
use Sabre\DAV\Auth\Plugin;
+use Sabre\DAV\IFile;
+use Sabre\HTTP\RequestInterface;
+use Sabre\HTTP\ResponseInterface;
+use Sabre\HTTP\Util;
class Server {
@@ -104,6 +108,19 @@ class Server {
$this->server->addPlugin(new \OCA\DAV\Connector\Sabre\FakeLockerPlugin());
}
+ // Serve all files with an Content-Disposition of type "attachment"
+ $this->server->on('beforeMethod', function (RequestInterface $requestInterface, ResponseInterface $responseInterface) {
+ if ($requestInterface->getMethod() === 'GET') {
+ $path = $requestInterface->getPath();
+ if ($this->server->tree->nodeExists($path)) {
+ $node = $this->server->tree->getNodeForPath($path);
+ if (($node instanceof IFile)) {
+ $responseInterface->addHeader('Content-Disposition', 'attachment');
+ }
+ }
+ }
+ });
+
// wait with registering these until auth is handled and the filesystem is setup
$this->server->on('beforeMethod', function () {
// custom properties plugin must be the last one
diff --git a/apps/dav/tests/unit/connector/sabre/principal.php b/apps/dav/tests/unit/connector/sabre/principal.php
index 07bfd5d263b..1747885240a 100644
--- a/apps/dav/tests/unit/connector/sabre/principal.php
+++ b/apps/dav/tests/unit/connector/sabre/principal.php
@@ -202,16 +202,26 @@ class Principal extends TestCase {
public function testGetGroupMembership() {
$fooUser = $this->getMockBuilder('\OC\User\User')
->disableOriginalConstructor()->getMock();
+ $group = $this->getMockBuilder('\OCP\IGroup')
+ ->disableOriginalConstructor()->getMock();
+ $group->expects($this->once())
+ ->method('getGID')
+ ->willReturn('group1');
$this->userManager
->expects($this->once())
->method('get')
->with('foo')
->willReturn($fooUser);
$this->groupManager
+ ->expects($this->once())
->method('getUserGroups')
- ->willReturn([]);
+ ->willReturn([
+ $group
+ ]);
- $expectedResponse = [];
+ $expectedResponse = [
+ 'principals/groups/group1'
+ ];
$response = $this->connector->getGroupMembership('principals/users/foo');
$this->assertSame($expectedResponse, $response);
}
diff --git a/apps/encryption/lib/crypto/encryption.php b/apps/encryption/lib/crypto/encryption.php
index a637f52a869..620bdd6ca9a 100644
--- a/apps/encryption/lib/crypto/encryption.php
+++ b/apps/encryption/lib/crypto/encryption.php
@@ -29,6 +29,7 @@ namespace OCA\Encryption\Crypto;
use OC\Encryption\Exceptions\DecryptionFailedException;
+use OC\Files\Cache\Scanner;
use OC\Files\View;
use OCA\Encryption\Exceptions\PublicKeyMissingException;
use OCA\Encryption\Session;
@@ -57,9 +58,6 @@ class Encryption implements IEncryptionModule {
private $path;
/** @var string */
- private $realPath;
-
- /** @var string */
private $user;
/** @var string */
@@ -107,6 +105,9 @@ class Encryption implements IEncryptionModule {
/** @var int Current version of the file */
private $version = 0;
+ /** @var array remember encryption signature version */
+ private static $rememberVersion = [];
+
/**
*
@@ -171,7 +172,6 @@ class Encryption implements IEncryptionModule {
*/
public function begin($path, $user, $mode, array $header, array $accessList) {
$this->path = $this->getPathToRealFile($path);
- $this->realPath = $path;
$this->accessList = $accessList;
$this->user = $user;
$this->isWriteOperation = false;
@@ -187,7 +187,10 @@ class Encryption implements IEncryptionModule {
$this->fileKey = $this->keyManager->getFileKey($this->path, $this->user);
}
- $this->version = (int)$this->keyManager->getVersion($this->realPath, new View());
+ // always use the version from the original file, also part files
+ // need to have a correct version number if they get moved over to the
+ // final location
+ $this->version = (int)$this->keyManager->getVersion($this->stripPartFileExtension($path), new View());
if (
$mode === 'w'
@@ -199,6 +202,13 @@ class Encryption implements IEncryptionModule {
if (empty($this->fileKey)) {
$this->fileKey = $this->crypt->generateFileKey();
}
+ } else {
+ // if we read a part file we need to increase the version by 1
+ // because the version number was also increased by writing
+ // the part file
+ if(Scanner::isPartialFile($path)) {
+ $this->version = $this->version + 1;
+ }
}
if ($this->isWriteOperation) {
@@ -230,15 +240,16 @@ class Encryption implements IEncryptionModule {
public function end($path, $position = 0) {
$result = '';
if ($this->isWriteOperation) {
- // Partial files do not increase the version
- if(\OC\Files\Cache\Scanner::isPartialFile($path)) {
- $version = $this->version;
- } else {
- $version = $this->version + 1;
+ $this->keyManager->setVersion($path, $this->version + 1, new View());
+ // in case of a part file we remember the new signature versions
+ // the version will be set later on update.
+ // This way we make sure that other apps listening to the pre-hooks
+ // still get the old version which should be the correct value for them
+ if (Scanner::isPartialFile($path)) {
+ self::$rememberVersion[$this->stripPartFileExtension($path)] = $this->version + 1;
}
- $this->keyManager->setVersion($this->path, $this->version+1, new View());
if (!empty($this->writeCache)) {
- $result = $this->crypt->symmetricEncryptFileContent($this->writeCache, $this->fileKey, $version, $position);
+ $result = $this->crypt->symmetricEncryptFileContent($this->writeCache, $this->fileKey, $this->version + 1, $position);
$this->writeCache = '';
}
$publicKeys = array();
@@ -319,13 +330,7 @@ class Encryption implements IEncryptionModule {
// Read the chunk from the start of $data
$chunk = substr($data, 0, $this->unencryptedBlockSizeSigned);
- // Partial files do not increase the version
- if(\OC\Files\Cache\Scanner::isPartialFile($this->path)) {
- $version = $this->version;
- } else {
- $version = $this->version + 1;
- }
- $encrypted .= $this->crypt->symmetricEncryptFileContent($chunk, $this->fileKey, $version, $position);
+ $encrypted .= $this->crypt->symmetricEncryptFileContent($chunk, $this->fileKey, $this->version + 1, $position);
// Remove the chunk we just processed from
// $data, leaving only unprocessed data in $data
@@ -368,11 +373,16 @@ class Encryption implements IEncryptionModule {
* @return boolean
*/
public function update($path, $uid, array $accessList) {
- $fileKey = $this->keyManager->getFileKey($path, $uid);
- if(empty($this->realPath)) {
- $this->realPath = $path;
+
+ if (empty($accessList)) {
+ if (isset(self::$rememberVersion[$path])) {
+ $this->keyManager->setVersion($path, self::$rememberVersion[$path], new View());
+ unset(self::$rememberVersion[$path]);
+ }
+ return;
}
- $version = $this->keyManager->getVersion($this->realPath, new View());
+
+ $fileKey = $this->keyManager->getFileKey($path, $uid);
if (!empty($fileKey)) {
@@ -393,8 +403,6 @@ class Encryption implements IEncryptionModule {
$this->keyManager->setAllFileKeys($path, $encryptedFileKey);
- $this->keyManager->setVersion($path, $version, new View());
-
} else {
$this->logger->debug('no file key found, we assume that the file "{file}" is not encrypted',
array('file' => $path, 'app' => 'encryption'));
@@ -520,4 +528,20 @@ class Encryption implements IEncryptionModule {
return $realPath;
}
+ /**
+ * remove .part file extension and the ocTransferId from the file to get the
+ * original file name
+ *
+ * @param string $path
+ * @return string
+ */
+ protected function stripPartFileExtension($path) {
+ if (pathinfo($path, PATHINFO_EXTENSION) === 'part') {
+ $pos = strrpos($path, '.', -6);
+ $path = substr($path, 0, $pos);
+ }
+
+ return $path;
+ }
+
}
diff --git a/apps/encryption/tests/lib/crypto/encryptionTest.php b/apps/encryption/tests/lib/crypto/encryptionTest.php
index ad943ab6e49..0ce1a2cb76a 100644
--- a/apps/encryption/tests/lib/crypto/encryptionTest.php
+++ b/apps/encryption/tests/lib/crypto/encryptionTest.php
@@ -298,6 +298,9 @@ class EncryptionTest extends TestCase {
return $publicKeys;
});
+ $this->keyManagerMock->expects($this->never())->method('getVersion');
+ $this->keyManagerMock->expects($this->never())->method('setVersion');
+
$this->assertSame($expected,
$this->instance->update('path', 'user1', ['users' => ['user1']])
);
@@ -311,6 +314,22 @@ class EncryptionTest extends TestCase {
);
}
+ public function testUpdateNoUsers() {
+
+ $this->invokePrivate($this->instance, 'rememberVersion', [['path' => 2]]);
+
+ $this->keyManagerMock->expects($this->never())->method('getFileKey');
+ $this->keyManagerMock->expects($this->never())->method('getPublicKey');
+ $this->keyManagerMock->expects($this->never())->method('addSystemKeys');
+ $this->keyManagerMock->expects($this->once())->method('setVersion')
+ ->willReturnCallback(function($path, $version, $view) {
+ $this->assertSame('path', $path);
+ $this->assertSame(2, $version);
+ $this->assertTrue($view instanceof \OC\Files\View);
+ });
+ $this->instance->update('path', 'user1', []);
+ }
+
/**
* by default the encryption module should encrypt regular files, files in
* files_versions and files in files_trashbin
diff --git a/apps/files/command/deleteorphanedfiles.php b/apps/files/command/deleteorphanedfiles.php
index d276e9a0993..f897c68fd8d 100644
--- a/apps/files/command/deleteorphanedfiles.php
+++ b/apps/files/command/deleteorphanedfiles.php
@@ -33,6 +33,8 @@ use Symfony\Component\Console\Output\OutputInterface;
*/
class DeleteOrphanedFiles extends Command {
+ const CHUNK_SIZE = 200;
+
/**
* @var IDBConnection
*/
@@ -50,13 +52,31 @@ class DeleteOrphanedFiles extends Command {
}
public function execute(InputInterface $input, OutputInterface $output) {
+ $deletedEntries = 0;
+
+ $query = $this->connection->getQueryBuilder();
+ $query->select('fc.fileid')
+ ->from('filecache', 'fc')
+ ->where($query->expr()->isNull('s.numeric_id'))
+ ->leftJoin('fc', 'storages', 's', $query->expr()->eq('fc.storage', 's.numeric_id'))
+ ->setMaxResults(self::CHUNK_SIZE);
+
+ $deleteQuery = $this->connection->getQueryBuilder();
+ $deleteQuery->delete('filecache')
+ ->where($deleteQuery->expr()->eq('fileid', $deleteQuery->createParameter('objectid')));
- $sql =
- 'DELETE FROM `*PREFIX*filecache` ' .
- 'WHERE NOT EXISTS ' .
- '(SELECT 1 FROM `*PREFIX*storages` WHERE `storage` = `numeric_id`)';
+ $deletedInLastChunk = self::CHUNK_SIZE;
+ while ($deletedInLastChunk === self::CHUNK_SIZE) {
+ $deletedInLastChunk = 0;
+ $result = $query->execute();
+ while ($row = $result->fetch()) {
+ $deletedInLastChunk++;
+ $deletedEntries += $deleteQuery->setParameter('objectid', (int) $row['fileid'])
+ ->execute();
+ }
+ $result->closeCursor();
+ }
- $deletedEntries = $this->connection->executeUpdate($sql);
$output->writeln("$deletedEntries orphaned file cache entries deleted");
}
diff --git a/apps/files/lib/backgroundjob/deleteorphaneditems.php b/apps/files/lib/backgroundjob/deleteorphaneditems.php
index cefa1d655de..773bb997e56 100644
--- a/apps/files/lib/backgroundjob/deleteorphaneditems.php
+++ b/apps/files/lib/backgroundjob/deleteorphaneditems.php
@@ -29,6 +29,8 @@ use OCP\DB\QueryBuilder\IQueryBuilder;
*/
class DeleteOrphanedItems extends TimedJob {
+ const CHUNK_SIZE = 200;
+
/** @var \OCP\IDBConnection */
protected $connection;
@@ -66,19 +68,38 @@ class DeleteOrphanedItems extends TimedJob {
/**
* Deleting orphaned system tag mappings
*
+ * @param string $table
+ * @param string $idCol
+ * @param string $typeCol
* @return int Number of deleted entries
*/
protected function cleanUp($table, $idCol, $typeCol) {
- $subQuery = $this->connection->getQueryBuilder();
- $subQuery->select($subQuery->expr()->literal('1'))
- ->from('filecache', 'f')
- ->where($subQuery->expr()->eq($idCol, 'f.fileid'));
+ $deletedEntries = 0;
$query = $this->connection->getQueryBuilder();
- $deletedEntries = $query->delete($table)
+ $query->select('t1.' . $idCol)
+ ->from($table, 't1')
->where($query->expr()->eq($typeCol, $query->expr()->literal('files')))
- ->andWhere($query->expr()->isNull($query->createFunction('(' . $subQuery->getSql() . ')')))
- ->execute();
+ ->andWhere($query->expr()->isNull('t2.fileid'))
+ ->leftJoin('t1', 'filecache', 't2', $query->expr()->eq($query->expr()->castColumn('t1.' . $idCol, IQueryBuilder::PARAM_INT), 't2.fileid'))
+ ->groupBy('t1.' . $idCol)
+ ->setMaxResults(self::CHUNK_SIZE);
+
+ $deleteQuery = $this->connection->getQueryBuilder();
+ $deleteQuery->delete($table)
+ ->where($deleteQuery->expr()->eq($idCol, $deleteQuery->createParameter('objectid')));
+
+ $deletedInLastChunk = self::CHUNK_SIZE;
+ while ($deletedInLastChunk === self::CHUNK_SIZE) {
+ $result = $query->execute();
+ $deletedInLastChunk = 0;
+ while ($row = $result->fetch()) {
+ $deletedInLastChunk++;
+ $deletedEntries += $deleteQuery->setParameter('objectid', (int) $row[$idCol])
+ ->execute();
+ }
+ $result->closeCursor();
+ }
return $deletedEntries;
}
@@ -111,8 +132,7 @@ class DeleteOrphanedItems extends TimedJob {
* @return int Number of deleted entries
*/
protected function cleanComments() {
- $qb = $this->connection->getQueryBuilder();
- $deletedEntries = $this->cleanUp('comments', $qb->expr()->castColumn('object_id', IQueryBuilder::PARAM_INT), 'object_type');
+ $deletedEntries = $this->cleanUp('comments', 'object_id', 'object_type');
$this->logger->debug("$deletedEntries orphaned comments deleted", ['app' => 'DeleteOrphanedItems']);
return $deletedEntries;
}
@@ -123,8 +143,7 @@ class DeleteOrphanedItems extends TimedJob {
* @return int Number of deleted entries
*/
protected function cleanCommentMarkers() {
- $qb = $this->connection->getQueryBuilder();
- $deletedEntries = $this->cleanUp('comments_read_markers', $qb->expr()->castColumn('object_id', IQueryBuilder::PARAM_INT), 'object_type');
+ $deletedEntries = $this->cleanUp('comments_read_markers', 'object_id', 'object_type');
$this->logger->debug("$deletedEntries orphaned comment read marks deleted", ['app' => 'DeleteOrphanedItems']);
return $deletedEntries;
}
diff --git a/apps/files_sharing/js/public.js b/apps/files_sharing/js/public.js
index bc609f04f79..da83044714e 100644
--- a/apps/files_sharing/js/public.js
+++ b/apps/files_sharing/js/public.js
@@ -154,9 +154,6 @@ OCA.Sharing.PublicApp = {
// TODO: move this to a separate PublicFileList class that extends OCA.Files.FileList (+ unit tests)
this.fileList.getDownloadUrl = function (filename, dir, isDir) {
var path = dir || this.getCurrentDirectory();
- if (filename && !_.isArray(filename) && !isDir) {
- return OC.getProtocol() + '://' + token + '@' + OC.getHost() + OC.getRootPath() + '/public.php/webdav' + OC.joinPaths(path, filename);
- }
if (_.isArray(filename)) {
filename = JSON.stringify(filename);
}
diff --git a/apps/files_sharing/tests/js/publicAppSpec.js b/apps/files_sharing/tests/js/publicAppSpec.js
index 8561836d77c..58565744882 100644
--- a/apps/files_sharing/tests/js/publicAppSpec.js
+++ b/apps/files_sharing/tests/js/publicAppSpec.js
@@ -102,12 +102,12 @@ describe('OCA.Sharing.PublicApp tests', function() {
it('returns correct download URL for single files', function() {
expect(fileList.getDownloadUrl('some file.txt'))
- .toEqual('https://sh4tok@example.com:9876/owncloud/public.php/webdav/subdir/some file.txt');
- expect(fileList.getDownloadUrl('some file.txt', '/another path/abc'))
- .toEqual('https://sh4tok@example.com:9876/owncloud/public.php/webdav/another path/abc/some file.txt');
+ .toEqual(OC.webroot + '/index.php/s/sh4tok/download?path=%2Fsubdir&files=some%20file.txt');
+ expect(fileList.getDownloadUrl('some file.txt', '/anotherpath/abc'))
+ .toEqual(OC.webroot + '/index.php/s/sh4tok/download?path=%2Fanotherpath%2Fabc&files=some%20file.txt');
fileList.changeDirectory('/');
expect(fileList.getDownloadUrl('some file.txt'))
- .toEqual('https://sh4tok@example.com:9876/owncloud/public.php/webdav/some file.txt');
+ .toEqual(OC.webroot + '/index.php/s/sh4tok/download?path=%2F&files=some%20file.txt');
});
it('returns correct download URL for multiple files', function() {
expect(fileList.getDownloadUrl(['a b c.txt', 'd e f.txt']))
diff --git a/apps/files_versions/ajax/getVersions.php b/apps/files_versions/ajax/getVersions.php
index 1953a55d13d..7d704c14618 100644
--- a/apps/files_versions/ajax/getVersions.php
+++ b/apps/files_versions/ajax/getVersions.php
@@ -41,6 +41,11 @@ if( $versions ) {
$versions = array_slice($versions, $start, $count);
+ // remove owner path from request to not disclose it to the recipient
+ foreach ($versions as $version) {
+ unset($version['path']);
+ }
+
\OCP\JSON::success(array('data' => array('versions' => $versions, 'endReached' => $endReached)));
} else {
diff --git a/apps/files_versions/js/versioncollection.js b/apps/files_versions/js/versioncollection.js
index 176f8e7529c..fdb12bae0a9 100644
--- a/apps/files_versions/js/versioncollection.js
+++ b/apps/files_versions/js/versioncollection.js
@@ -73,12 +73,13 @@
},
parse: function(result) {
+ var fullPath = this._fileInfo.getFullPath();
var results = _.map(result.data.versions, function(version) {
var revision = parseInt(version.version, 10);
return {
id: revision,
name: version.name,
- fullPath: version.path,
+ fullPath: fullPath,
timestamp: revision,
size: version.size
};
diff --git a/apps/files_versions/lib/storage.php b/apps/files_versions/lib/storage.php
index 0b121c344f9..d5e21959698 100644
--- a/apps/files_versions/lib/storage.php
+++ b/apps/files_versions/lib/storage.php
@@ -169,11 +169,8 @@ class Storage {
// Keep the "encrypted" value of the original file
$oldVersion = $files_view->getFileInfo($filename)->getEncryptedVersion();
- $qb = \OC::$server->getDatabaseConnection()->getQueryBuilder();
- $qb->update('filecache')
- ->set('encrypted', $qb->createNamedParameter($oldVersion))
- ->where($qb->expr()->eq('fileid', $qb->createNamedParameter($newFileInfo->getId())))
- ->execute();
+ $cache = $newFileInfo->getStorage()->getCache();
+ $cache->update($newFileInfo->getId(), ['encrypted' => $oldVersion, 'encryptedVersion' => $oldVersion]);
}
}
diff --git a/apps/updatenotification/controller/admincontroller.php b/apps/updatenotification/controller/admincontroller.php
index ec1cc45075c..505ea01edd9 100644
--- a/apps/updatenotification/controller/admincontroller.php
+++ b/apps/updatenotification/controller/admincontroller.php
@@ -77,8 +77,8 @@ class AdminController extends Controller {
$this->config->setAppValue('core', 'updater.secret.created', $this->timeFactory->getTime());
// Create a new token
- $newToken = $this->secureRandom->generate(32);
- $this->config->setSystemValue('updater.secret', $newToken);
+ $newToken = $this->secureRandom->generate(64);
+ $this->config->setSystemValue('updater.secret', password_hash($newToken, PASSWORD_DEFAULT));
return new DataResponse($newToken);
}
diff --git a/apps/updatenotification/lib/resettokenbackgroundjob.php b/apps/updatenotification/lib/resettokenbackgroundjob.php
index 0b737f681b6..61bd9fc0490 100644
--- a/apps/updatenotification/lib/resettokenbackgroundjob.php
+++ b/apps/updatenotification/lib/resettokenbackgroundjob.php
@@ -67,7 +67,8 @@ class ResetTokenBackgroundJob extends TimedJob {
* @param $argument
*/
protected function run($argument) {
- if($this->timeFactory->getTime() - $this->config->getAppValue('core', 'updater.secret.created', $this->timeFactory->getTime()) >= 86400) {
+ // Delete old tokens after 2 days
+ if($this->timeFactory->getTime() - $this->config->getAppValue('core', 'updater.secret.created', $this->timeFactory->getTime()) >= 172800) {
$this->config->deleteSystemValue('updater.secret');
}
}
diff --git a/apps/updatenotification/tests/controller/AdminControllerTest.php b/apps/updatenotification/tests/controller/AdminControllerTest.php
index 01801626000..5a0f9d21469 100644
--- a/apps/updatenotification/tests/controller/AdminControllerTest.php
+++ b/apps/updatenotification/tests/controller/AdminControllerTest.php
@@ -77,12 +77,12 @@ class AdminControllerTest extends TestCase {
$this->secureRandom
->expects($this->once())
->method('generate')
- ->with(32)
+ ->with(64)
->willReturn('MyGeneratedToken');
$this->config
->expects($this->once())
->method('setSystemValue')
- ->with('updater.secret', 'MyGeneratedToken');
+ ->with('updater.secret');
$this->timeFactory
->expects($this->once())
->method('getTime')
diff --git a/core/templates/login.php b/core/templates/login.php
index e87b871c67e..a12008295c4 100644
--- a/core/templates/login.php
+++ b/core/templates/login.php
@@ -67,7 +67,11 @@ script('core', [
<?php } ?>
<?php if ($_['rememberLoginAllowed'] === true) : ?>
<div class="remember-login-container">
+ <?php if ($_['rememberLoginState'] === 0) { ?>
<input type="checkbox" name="remember_login" value="1" id="remember_login" class="checkbox checkbox--white">
+ <?php } else { ?>
+ <input type="checkbox" name="remember_login" value="1" id="remember_login" class="checkbox checkbox--white" checked="checked">
+ <?php } ?>
<label for="remember_login"><?php p($l->t('Stay logged in')); ?></label>
</div>
<?php endif; ?>
diff --git a/core/vendor/davclient.js/lib/client.js b/core/vendor/davclient.js/lib/client.js
index 89c11516a38..d3d0a7062c0 100644
--- a/core/vendor/davclient.js/lib/client.js
+++ b/core/vendor/davclient.js/lib/client.js
@@ -172,7 +172,13 @@ dav.Client.prototype = {
for(ii in headers) {
xhr.setRequestHeader(ii, headers[ii]);
}
- xhr.send(body);
+
+ // Work around for edge
+ if (body === undefined) {
+ xhr.send();
+ } else {
+ xhr.send(body);
+ }
return new Promise(function(fulfill, reject) {
diff --git a/lib/private/files/storage/wrapper/encryption.php b/lib/private/files/storage/wrapper/encryption.php
index 14d3b15bbae..26905dfb388 100644
--- a/lib/private/files/storage/wrapper/encryption.php
+++ b/lib/private/files/storage/wrapper/encryption.php
@@ -260,6 +260,10 @@ class Encryption extends Wrapper {
$this->unencryptedSize[$target] = $this->unencryptedSize[$source];
}
$this->keyStorage->renameKeys($source, $target);
+ $module = $this->getEncryptionModule($path2);
+ if ($module) {
+ $module->update($target, $this->uid, []);
+ }
}
}
diff --git a/lib/private/repair/repairinvalidshares.php b/lib/private/repair/repairinvalidshares.php
index ee8b23906e5..beef5e37798 100644
--- a/lib/private/repair/repairinvalidshares.php
+++ b/lib/private/repair/repairinvalidshares.php
@@ -30,6 +30,8 @@ use OC\Hooks\BasicEmitter;
*/
class RepairInvalidShares extends BasicEmitter implements \OC\RepairStep {
+ const CHUNK_SIZE = 200;
+
/**
* @var \OCP\IConfig
*/
@@ -83,18 +85,24 @@ class RepairInvalidShares extends BasicEmitter implements \OC\RepairStep {
->where($query->expr()->isNotNull('s1.parent'))
->andWhere($query->expr()->isNull('s2.id'))
->leftJoin('s1', 'share', 's2', $query->expr()->eq('s1.parent', 's2.id'))
- ->groupBy('s1.parent');
+ ->groupBy('s1.parent')
+ ->setMaxResults(self::CHUNK_SIZE);
$deleteQuery = $this->connection->getQueryBuilder();
$deleteQuery->delete('share')
- ->where($query->expr()->eq('parent', $deleteQuery->createParameter('parent')));
-
- $result = $query->execute();
- while ($row = $result->fetch()) {
- $deletedEntries += $deleteQuery->setParameter('parent', (int) $row['parent'])
- ->execute();
+ ->where($deleteQuery->expr()->eq('parent', $deleteQuery->createParameter('parent')));
+
+ $deletedInLastChunk = self::CHUNK_SIZE;
+ while ($deletedInLastChunk === self::CHUNK_SIZE) {
+ $deletedInLastChunk = 0;
+ $result = $query->execute();
+ while ($row = $result->fetch()) {
+ $deletedInLastChunk++;
+ $deletedEntries += $deleteQuery->setParameter('parent', (int) $row['parent'])
+ ->execute();
+ }
+ $result->closeCursor();
}
- $result->closeCursor();
if ($deletedEntries) {
$this->emit('\OC\Repair', 'info', array('Removed ' . $deletedEntries . ' shares where the parent did not exist'));
diff --git a/lib/private/util.php b/lib/private/util.php
index 6e15d742bed..6ad668dedaa 100644
--- a/lib/private/util.php
+++ b/lib/private/util.php
@@ -969,6 +969,7 @@ class OC_Util {
$parameters['alt_login'] = OC_App::getAlternativeLogIns();
$parameters['rememberLoginAllowed'] = self::rememberLoginAllowed();
+ $parameters['rememberLoginState'] = isset($_POST['remember_login']) ? $_POST['remember_login'] : 0;
\OC_Hook::emit('OC_Util', 'pre_displayLoginPage', array('parameters' => $parameters));
OC_Template::printGuestPage("", "login", $parameters);
}