aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMorris Jobke <hey@morrisjobke.de>2016-06-28 09:02:03 +0200
committerGitHub <noreply@github.com>2016-06-28 09:02:03 +0200
commitb6397ef73a765be807efe363703f27013fd50d7a (patch)
tree31fedc1887b2b3b50e720f1e006f9693cd671cff
parent300f0965ae6528b370662ee39346bf6660aeaa5c (diff)
parent6670d3765881a1a7579bd96a523a90c2a52aec4a (diff)
downloadnextcloud-server-b6397ef73a765be807efe363703f27013fd50d7a.tar.gz
nextcloud-server-b6397ef73a765be807efe363703f27013fd50d7a.zip
Merge pull request #236 from nextcloud/master-sync-upstream
[Master] sync upstream
-rw-r--r--apps/comments/l10n/fi_FI.js3
-rw-r--r--apps/comments/l10n/fi_FI.json3
-rw-r--r--apps/comments/l10n/pl.js3
-rw-r--r--apps/comments/l10n/pl.json3
-rw-r--r--apps/federatedfilesharing/lib/FederatedShareProvider.php4
-rw-r--r--apps/files/js/filelist.js22
-rw-r--r--apps/files/tests/js/filelistSpec.js11
-rw-r--r--apps/files_external/lib/AppInfo/Application.php4
-rw-r--r--apps/files_sharing/lib/API/Share20OCS.php22
-rw-r--r--apps/files_sharing/tests/API/Share20OCSTest.php77
-rw-r--r--apps/files_sharing/tests/ApiTest.php16
-rw-r--r--apps/systemtags/l10n/pl.js1
-rw-r--r--apps/systemtags/l10n/pl.json1
-rw-r--r--build/integration/features/sharing-v1.feature6
-rw-r--r--core/Command/Encryption/DecryptAll.php3
-rw-r--r--core/css/apps.css8
-rw-r--r--core/css/fixes.css116
-rw-r--r--core/css/multiselect.css7
-rw-r--r--core/css/styles.css10
-rw-r--r--core/js/js.js30
-rw-r--r--core/js/sharedialoglinkshareview.js2
-rw-r--r--core/l10n/pl.js7
-rw-r--r--core/l10n/pl.json7
-rw-r--r--core/templates/layout.base.php4
-rw-r--r--core/templates/layout.guest.php4
-rw-r--r--core/templates/layout.user.php4
-rw-r--r--lib/private/IntegrityCheck/Checker.php15
-rw-r--r--lib/private/Repair/RepairInvalidShares.php23
-rw-r--r--lib/private/Share20/Manager.php7
-rw-r--r--lib/private/User/Session.php13
-rw-r--r--settings/Controller/AuthSettingsController.php1
-rw-r--r--settings/css/settings.css16
-rw-r--r--settings/js/authtoken.js6
-rw-r--r--settings/js/authtoken_collection.js6
-rw-r--r--settings/js/authtoken_view.js21
-rw-r--r--settings/l10n/pl.js2
-rw-r--r--settings/l10n/pl.json2
-rw-r--r--settings/templates/personal.php12
-rw-r--r--tests/lib/Repair/RepairInvalidSharesTest.php87
-rw-r--r--tests/lib/Share20/ManagerTest.php18
-rw-r--r--tests/lib/User/SessionTest.php30
-rw-r--r--version.php2
42 files changed, 387 insertions, 252 deletions
diff --git a/apps/comments/l10n/fi_FI.js b/apps/comments/l10n/fi_FI.js
index 7b4de946763..b541b9987fe 100644
--- a/apps/comments/l10n/fi_FI.js
+++ b/apps/comments/l10n/fi_FI.js
@@ -12,6 +12,9 @@ OC.L10N.register(
"More comments..." : "Lisää kommentteja...",
"Save" : "Tallenna",
"Allowed characters {count} of {max}" : "Sallittujen merkkien määrä {count}/{max}",
+ "Error occurred while retrieving comment with id {id}" : "Virhe noutaessa kommenttia tunnisteella {id}",
+ "Error occurred while updating comment with id {id}" : "Virhe päivittäessä kommenttia tunnisteella {id}",
+ "Error occurred while posting comment" : "Virhe kommenttia lähettäessä",
"{count} unread comments" : "{count} lukematonta kommenttia",
"Comment" : "Kommentti",
"<strong>Comments</strong> for files <em>(always listed in stream)</em>" : "<strong>Kommentit</strong> tiedostoille <em>(aina listattu luettelossa)</em>",
diff --git a/apps/comments/l10n/fi_FI.json b/apps/comments/l10n/fi_FI.json
index 5e9bcc74402..b5be601d905 100644
--- a/apps/comments/l10n/fi_FI.json
+++ b/apps/comments/l10n/fi_FI.json
@@ -10,6 +10,9 @@
"More comments..." : "Lisää kommentteja...",
"Save" : "Tallenna",
"Allowed characters {count} of {max}" : "Sallittujen merkkien määrä {count}/{max}",
+ "Error occurred while retrieving comment with id {id}" : "Virhe noutaessa kommenttia tunnisteella {id}",
+ "Error occurred while updating comment with id {id}" : "Virhe päivittäessä kommenttia tunnisteella {id}",
+ "Error occurred while posting comment" : "Virhe kommenttia lähettäessä",
"{count} unread comments" : "{count} lukematonta kommenttia",
"Comment" : "Kommentti",
"<strong>Comments</strong> for files <em>(always listed in stream)</em>" : "<strong>Kommentit</strong> tiedostoille <em>(aina listattu luettelossa)</em>",
diff --git a/apps/comments/l10n/pl.js b/apps/comments/l10n/pl.js
index d4a492e1da2..b8df4dea02b 100644
--- a/apps/comments/l10n/pl.js
+++ b/apps/comments/l10n/pl.js
@@ -12,6 +12,9 @@ OC.L10N.register(
"More comments..." : "Więcej komentarzy...",
"Save" : "Zapisz",
"Allowed characters {count} of {max}" : "Dozwolone znaki {count} z {max}",
+ "Error occurred while retrieving comment with id {id}" : "W trakcie otrzymywania komentarza o identyfikatorze {id} wystąpił błąd.",
+ "Error occurred while updating comment with id {id}" : "W trakcie aktualizacji komentarza o identyfikatorze {id} wystąpił błąd.",
+ "Error occurred while posting comment" : "Podczas wysyłania komentarza wystąpił błąd",
"{count} unread comments" : "{count} nieprzeczytanych komentarzy",
"Comment" : "Komentarz",
"<strong>Comments</strong> for files <em>(always listed in stream)</em>" : "<strong>Komentarze</strong> dla plików <em>(zawsze wypisane w strumieniu)</em>",
diff --git a/apps/comments/l10n/pl.json b/apps/comments/l10n/pl.json
index 78e9f0ff210..47e4b101f98 100644
--- a/apps/comments/l10n/pl.json
+++ b/apps/comments/l10n/pl.json
@@ -10,6 +10,9 @@
"More comments..." : "Więcej komentarzy...",
"Save" : "Zapisz",
"Allowed characters {count} of {max}" : "Dozwolone znaki {count} z {max}",
+ "Error occurred while retrieving comment with id {id}" : "W trakcie otrzymywania komentarza o identyfikatorze {id} wystąpił błąd.",
+ "Error occurred while updating comment with id {id}" : "W trakcie aktualizacji komentarza o identyfikatorze {id} wystąpił błąd.",
+ "Error occurred while posting comment" : "Podczas wysyłania komentarza wystąpił błąd",
"{count} unread comments" : "{count} nieprzeczytanych komentarzy",
"Comment" : "Komentarz",
"<strong>Comments</strong> for files <em>(always listed in stream)</em>" : "<strong>Komentarze</strong> dla plików <em>(zawsze wypisane w strumieniu)</em>",
diff --git a/apps/federatedfilesharing/lib/FederatedShareProvider.php b/apps/federatedfilesharing/lib/FederatedShareProvider.php
index 6f9b6644eed..40e2e8a472f 100644
--- a/apps/federatedfilesharing/lib/FederatedShareProvider.php
+++ b/apps/federatedfilesharing/lib/FederatedShareProvider.php
@@ -473,6 +473,8 @@ class FederatedShareProvider implements IShareProvider {
$isOwner = false;
+ $this->removeShareFromTable($share);
+
// if the local user is the owner we can send the unShare request directly...
if ($this->userManager->userExists($share->getShareOwner())) {
$this->notifications->sendRemoteUnShare($remote, $share->getId(), $share->getToken());
@@ -494,8 +496,6 @@ class FederatedShareProvider implements IShareProvider {
}
$this->notifications->sendRevokeShare($remote, $remoteId, $share->getToken());
}
-
- $this->removeShareFromTable($share);
}
/**
diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js
index 3ab5032599c..e483882fcc5 100644
--- a/apps/files/js/filelist.js
+++ b/apps/files/js/filelist.js
@@ -2351,22 +2351,36 @@
* @param filter
*/
setFilter:function(filter) {
+ var total = 0;
this._filter = filter;
this.fileSummary.setFilter(filter, this.files);
+ total = this.fileSummary.getTotal();
if (!this.$el.find('.mask').exists()) {
this.hideIrrelevantUIWhenNoFilesMatch();
}
var that = this;
+ var visibleCount = 0;
filter = filter.toLowerCase();
- this.$fileList.find('tr').each(function(i,e) {
- var $e = $(e);
+
+ function filterRows(tr) {
+ var $e = $(tr);
if ($e.data('file').toString().toLowerCase().indexOf(filter) === -1) {
$e.addClass('hidden');
} else {
+ visibleCount++;
$e.removeClass('hidden');
}
- });
- that.$container.trigger('scroll');
+ }
+
+ var $trs = this.$fileList.find('tr');
+ do {
+ _.each($trs, filterRows);
+ if (visibleCount < total) {
+ $trs = this._nextPage(false);
+ }
+ } while (visibleCount < total);
+
+ this.$container.trigger('scroll');
},
hideIrrelevantUIWhenNoFilesMatch:function() {
if (this._filter && this.fileSummary.summary.totalDirs + this.fileSummary.summary.totalFiles === 0) {
diff --git a/apps/files/tests/js/filelistSpec.js b/apps/files/tests/js/filelistSpec.js
index 44f271d8084..ae4b75f7771 100644
--- a/apps/files/tests/js/filelistSpec.js
+++ b/apps/files/tests/js/filelistSpec.js
@@ -989,6 +989,17 @@ describe('OCA.Files.FileList tests', function() {
expect($summary.find('.info').text()).toEqual("1 folder and 3 files");
expect($nofilterresults.hasClass('hidden')).toEqual(true);
});
+ it('filters the list of non-rendered rows using filter()', function() {
+ var $summary = $('#filestable .summary');
+ var $nofilterresults = fileList.$el.find(".nofilterresults");
+ fileList.setFiles(generateFiles(0, 64));
+
+ fileList.setFilter('63');
+ expect($('#fileList tr:not(.hidden)').length).toEqual(1);
+ expect($summary.hasClass('hidden')).toEqual(false);
+ expect($summary.find('.info').text()).toEqual("0 folders and 1 file matches '63'");
+ expect($nofilterresults.hasClass('hidden')).toEqual(true);
+ });
it('hides the emptyfiles notice when using filter()', function() {
expect(fileList.files.length).toEqual(0);
expect(fileList.files).toEqual([]);
diff --git a/apps/files_external/lib/AppInfo/Application.php b/apps/files_external/lib/AppInfo/Application.php
index cbbcbe9c319..0ee4e9b3d5c 100644
--- a/apps/files_external/lib/AppInfo/Application.php
+++ b/apps/files_external/lib/AppInfo/Application.php
@@ -52,6 +52,10 @@ class Application extends App implements IBackendProvider, IAuthMechanismProvide
$backendService->registerBackendProvider($this);
$backendService->registerAuthMechanismProvider($this);
+ // force-load auth mechanisms since some will register hooks
+ // TODO: obsolete these and use the TokenProvider to get the user's password from the session
+ $this->getAuthMechanisms();
+
// app developers: do NOT depend on this! it will disappear with oC 9.0!
\OC::$server->getEventDispatcher()->dispatch(
'OCA\\Files_External::loadAdditionalBackends'
diff --git a/apps/files_sharing/lib/API/Share20OCS.php b/apps/files_sharing/lib/API/Share20OCS.php
index 3d6a715be99..436b8d15ac8 100644
--- a/apps/files_sharing/lib/API/Share20OCS.php
+++ b/apps/files_sharing/lib/API/Share20OCS.php
@@ -354,7 +354,8 @@ class Share20OCS {
$share->setPermissions(
\OCP\Constants::PERMISSION_READ |
\OCP\Constants::PERMISSION_CREATE |
- \OCP\Constants::PERMISSION_UPDATE
+ \OCP\Constants::PERMISSION_UPDATE |
+ \OCP\Constants::PERMISSION_DELETE
);
} else {
$share->setPermissions(\OCP\Constants::PERMISSION_READ);
@@ -591,7 +592,7 @@ class Share20OCS {
$newPermissions = null;
if ($publicUpload === 'true') {
- $newPermissions = \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE;
+ $newPermissions = \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE;
} else if ($publicUpload === 'false') {
$newPermissions = \OCP\Constants::PERMISSION_READ;
}
@@ -602,13 +603,21 @@ class Share20OCS {
if ($newPermissions !== null &&
$newPermissions !== \OCP\Constants::PERMISSION_READ &&
- $newPermissions !== (\OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE) &&
- $newPermissions !== (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE)) {
+ // legacy
+ $newPermissions !== (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE) &&
+ // correct
+ $newPermissions !== (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE)
+ ) {
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED);
return new \OC_OCS_Result(null, 400, $this->l->t('Can\'t change permissions for public share links'));
}
- if ($newPermissions === (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE)) {
+ if (
+ // legacy
+ $newPermissions === (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE) ||
+ // correct
+ $newPermissions === (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE)
+ ) {
if (!$this->shareManager->shareApiLinkAllowPublicUpload()) {
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED);
return new \OC_OCS_Result(null, 403, $this->l->t('Public upload disabled by the administrator'));
@@ -618,6 +627,9 @@ class Share20OCS {
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED);
return new \OC_OCS_Result(null, 400, $this->l->t('Public upload is only possible for publicly shared folders'));
}
+
+ // normalize to correct public upload permissions
+ $newPermissions = \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE;
}
if ($newPermissions !== null) {
diff --git a/apps/files_sharing/tests/API/Share20OCSTest.php b/apps/files_sharing/tests/API/Share20OCSTest.php
index b760a0f47a0..6435c992f25 100644
--- a/apps/files_sharing/tests/API/Share20OCSTest.php
+++ b/apps/files_sharing/tests/API/Share20OCSTest.php
@@ -1035,7 +1035,7 @@ class Share20OCSTest extends \Test\TestCase {
$this->callback(function (\OCP\Share\IShare $share) use ($path) {
return $share->getNode() === $path &&
$share->getShareType() === \OCP\Share::SHARE_TYPE_LINK &&
- $share->getPermissions() === \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_DELETE &&
+ $share->getPermissions() === (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE) &&
$share->getSharedBy() === 'currentUser' &&
$share->getPassword() === null &&
$share->getExpirationDate() === null;
@@ -1366,7 +1366,7 @@ class Share20OCSTest extends \Test\TestCase {
$date = new \DateTime('2000-01-01');
$date->setTime(0,0,0);
- return $share->getPermissions() === \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE && \OCP\Constants::PERMISSION_DELETE &&
+ return $share->getPermissions() === (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE) &&
$share->getPassword() === 'password' &&
$share->getExpirationDate() == $date;
})
@@ -1379,6 +1379,44 @@ class Share20OCSTest extends \Test\TestCase {
$this->assertEquals($expected->getData(), $result->getData());
}
+ /**
+ * @dataProvider publicUploadParamsProvider
+ */
+ public function testUpdateLinkShareEnablePublicUpload($params) {
+ $ocs = $this->mockFormatShare();
+
+ $folder = $this->getMock('\OCP\Files\Folder');
+
+ $share = \OC::$server->getShareManager()->newShare();
+ $share->setPermissions(\OCP\Constants::PERMISSION_ALL)
+ ->setSharedBy($this->currentUser->getUID())
+ ->setShareType(\OCP\Share::SHARE_TYPE_LINK)
+ ->setPassword('password')
+ ->setNode($folder);
+
+ $this->request
+ ->method('getParam')
+ ->will($this->returnValueMap($params));
+
+ $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
+ $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
+ $this->shareManager->method('getSharedWith')->willReturn([]);
+
+ $this->shareManager->expects($this->once())->method('updateShare')->with(
+ $this->callback(function (\OCP\Share\IShare $share) {
+ return $share->getPermissions() === (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE) &&
+ $share->getPassword() === 'password' &&
+ $share->getExpirationDate() === null;
+ })
+ )->will($this->returnArgument(0));
+
+ $expected = new \OC_OCS_Result(null);
+ $result = $ocs->updateShare(42);
+
+ $this->assertEquals($expected->getMeta(), $result->getMeta());
+ $this->assertEquals($expected->getData(), $result->getData());
+ }
+
public function testUpdateLinkShareInvalidDate() {
$ocs = $this->mockFormatShare();
@@ -1408,7 +1446,30 @@ class Share20OCSTest extends \Test\TestCase {
$this->assertEquals($expected->getData(), $result->getData());
}
- public function testUpdateLinkSharePublicUploadNotAllowed() {
+ public function publicUploadParamsProvider() {
+ return [
+ [[
+ ['publicUpload', null, 'true'],
+ ['expireDate', '', null],
+ ['password', '', 'password'],
+ ]], [[
+ // legacy had no delete
+ ['permissions', null, \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE],
+ ['expireDate', '', null],
+ ['password', '', 'password'],
+ ]], [[
+ // correct
+ ['permissions', null, \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE],
+ ['expireDate', '', null],
+ ['password', '', 'password'],
+ ]],
+ ];
+ }
+
+ /**
+ * @dataProvider publicUploadParamsProvider
+ */
+ public function testUpdateLinkSharePublicUploadNotAllowed($params) {
$ocs = $this->mockFormatShare();
$folder = $this->getMock('\OCP\Files\Folder');
@@ -1421,11 +1482,7 @@ class Share20OCSTest extends \Test\TestCase {
$this->request
->method('getParam')
- ->will($this->returnValueMap([
- ['publicUpload', null, 'true'],
- ['expireDate', '', null],
- ['password', '', 'password'],
- ]));
+ ->will($this->returnValueMap($params));
$this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
$this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(false);
@@ -1585,7 +1642,7 @@ class Share20OCSTest extends \Test\TestCase {
$this->shareManager->expects($this->once())->method('updateShare')->with(
$this->callback(function (\OCP\Share\IShare $share) use ($date) {
- return $share->getPermissions() === \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_DELETE &&
+ return $share->getPermissions() === (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE) &&
$share->getPassword() === 'password' &&
$share->getExpirationDate() === $date;
})
@@ -1625,7 +1682,7 @@ class Share20OCSTest extends \Test\TestCase {
$this->shareManager->expects($this->once())->method('updateShare')->with(
$this->callback(function (\OCP\Share\IShare $share) use ($date) {
- return $share->getPermissions() === \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_DELETE &&
+ return $share->getPermissions() === (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE) &&
$share->getPassword() === 'password' &&
$share->getExpirationDate() === $date;
})
diff --git a/apps/files_sharing/tests/ApiTest.php b/apps/files_sharing/tests/ApiTest.php
index 058b0c4758c..40c9085353c 100644
--- a/apps/files_sharing/tests/ApiTest.php
+++ b/apps/files_sharing/tests/ApiTest.php
@@ -257,7 +257,13 @@ class ApiTest extends TestCase {
$this->assertTrue($result->succeeded());
$data = $result->getData();
- $this->assertEquals(7, $data['permissions']);
+ $this->assertEquals(
+ \OCP\Constants::PERMISSION_READ |
+ \OCP\Constants::PERMISSION_CREATE |
+ \OCP\Constants::PERMISSION_UPDATE |
+ \OCP\Constants::PERMISSION_DELETE,
+ $data['permissions']
+ );
$this->assertEmpty($data['expiration']);
$this->assertTrue(is_string($data['token']));
@@ -1081,7 +1087,13 @@ class ApiTest extends TestCase {
$this->assertTrue($result->succeeded());
$share1 = $this->shareManager->getShareById($share1->getFullId());
- $this->assertEquals(7, $share1->getPermissions());
+ $this->assertEquals(
+ \OCP\Constants::PERMISSION_READ |
+ \OCP\Constants::PERMISSION_CREATE |
+ \OCP\Constants::PERMISSION_UPDATE |
+ \OCP\Constants::PERMISSION_DELETE,
+ $share1->getPermissions()
+ );
// cleanup
$this->shareManager->deleteShare($share1);
diff --git a/apps/systemtags/l10n/pl.js b/apps/systemtags/l10n/pl.js
index f5e4775d540..fca05665ec8 100644
--- a/apps/systemtags/l10n/pl.js
+++ b/apps/systemtags/l10n/pl.js
@@ -14,6 +14,7 @@ OC.L10N.register(
"%1$s updated system tag %3$s to %2$s" : "%1$s zaktualizowany system etykiet%3$s do %2$s",
"%1$s assigned system tag %3$s to %2$s" : "%1$s przypisywalny system etykiet%3$s do %2$s",
"%1$s unassigned system tag %3$s from %2$s" : "%1$s nieprzypisany system etykiet %3$s z %2$s",
+ "%s (restricted)" : "%s (ograniczone)",
"%s (invisible)" : "%s (niewidoczny)",
"No files in here" : "Brak plików",
"No entries found in this folder" : "Brak wpisów w tym folderze",
diff --git a/apps/systemtags/l10n/pl.json b/apps/systemtags/l10n/pl.json
index 6cb103ed4a5..97ae0230be4 100644
--- a/apps/systemtags/l10n/pl.json
+++ b/apps/systemtags/l10n/pl.json
@@ -12,6 +12,7 @@
"%1$s updated system tag %3$s to %2$s" : "%1$s zaktualizowany system etykiet%3$s do %2$s",
"%1$s assigned system tag %3$s to %2$s" : "%1$s przypisywalny system etykiet%3$s do %2$s",
"%1$s unassigned system tag %3$s from %2$s" : "%1$s nieprzypisany system etykiet %3$s z %2$s",
+ "%s (restricted)" : "%s (ograniczone)",
"%s (invisible)" : "%s (niewidoczny)",
"No files in here" : "Brak plików",
"No entries found in this folder" : "Brak wpisów w tym folderze",
diff --git a/build/integration/features/sharing-v1.feature b/build/integration/features/sharing-v1.feature
index 79dc1326f3c..3878e741f60 100644
--- a/build/integration/features/sharing-v1.feature
+++ b/build/integration/features/sharing-v1.feature
@@ -61,7 +61,7 @@ Feature: sharing
And the HTTP status code should be "200"
And Share fields of last share match with
| id | A_NUMBER |
- | permissions | 7 |
+ | permissions | 15 |
| expiration | +3 days |
| url | AN_URL |
| token | A_TOKEN |
@@ -159,7 +159,7 @@ Feature: sharing
| share_type | 3 |
| file_source | A_NUMBER |
| file_target | /FOLDER |
- | permissions | 7 |
+ | permissions | 15 |
| stime | A_NUMBER |
| token | A_TOKEN |
| storage | A_NUMBER |
@@ -189,7 +189,7 @@ Feature: sharing
| share_type | 3 |
| file_source | A_NUMBER |
| file_target | /FOLDER |
- | permissions | 7 |
+ | permissions | 15 |
| stime | A_NUMBER |
| token | A_TOKEN |
| storage | A_NUMBER |
diff --git a/core/Command/Encryption/DecryptAll.php b/core/Command/Encryption/DecryptAll.php
index 83c6c1dc168..cda7853b8b4 100644
--- a/core/Command/Encryption/DecryptAll.php
+++ b/core/Command/Encryption/DecryptAll.php
@@ -150,6 +150,9 @@ class DecryptAll extends Command {
$output->writeln(' aborted.');
$output->writeln('Server side encryption remains enabled');
$this->config->setAppValue('core', 'encryption_enabled', 'yes');
+ } else if ($uid !== '') {
+ $output->writeln('Server side encryption remains enabled');
+ $this->config->setAppValue('core', 'encryption_enabled', 'yes');
}
$this->resetSingleUserAndTrashbin();
} else {
diff --git a/core/css/apps.css b/core/css/apps.css
index e8b33ecba65..3ffa7d87098 100644
--- a/core/css/apps.css
+++ b/core/css/apps.css
@@ -162,7 +162,6 @@
text-overflow: ellipsis;
overflow: hidden;
display: inline-block;
- width: 201px; /* fallback for IE8 */
width: calc(100% - 49px);
line-height: 44px;
float: left;
@@ -309,12 +308,6 @@
.edge #app-navigation .app-navigation-entry-menu:after {
border: 1px solid #eee;
}
-.ie8 .bubble {
- margin-top: 18px;
-}
-.ie8 .bubble:after {
- display: none;
-}
/* miraculous border arrow stuff */
.bubble:after,
#app-navigation .app-navigation-entry-menu:after {
@@ -392,7 +385,6 @@
#app-navigation .app-navigation-entry-edit input {
border-bottom-right-radius: 0;
border-top-right-radius: 0;
- width: 204px; /* fallback for IE8 */
width: calc(100% - 36px);
padding: 5px;
margin-right: 0;
diff --git a/core/css/fixes.css b/core/css/fixes.css
index b660cd47aa8..3cb89c6599f 100644
--- a/core/css/fixes.css
+++ b/core/css/fixes.css
@@ -10,125 +10,9 @@ select {
height: 32px;
}
-/* reset typeface for IE8 because OpenSans renders too small */
-.ie8 body {
- font-family: Frutiger, Calibri, 'Myriad Pro', Myriad, Arial, sans-serif;
-}
-
-.lte8 .icon-delete { background-image: url('../img/actions/delete.png'); }
-.lte8 .icon-delete:hover, .icon-delete:focus {
- background-image: url('../img/actions/delete-hover.png');
-}
-
-.ie8 .icon-checkmark {
- background-image: url('../img/actions/checkmark.png');
-}
-
-.ie8 .icon-close {
- background-image: url('../img/actions/close.png');
-}
-
-.lte9 .icon-triangle-e {
- background-image: url('../img/actions/triangle-e.png');
-}
-.lte9 .icon-triangle-n {
- background-image: url('../img/actions/triangle-n.png');
-}
-.lte9 .icon-triangle-s {
- background-image: url('../img/actions/triangle-s.png');
-}
-.lte9 .icon-settings,
-.lte9 .settings-button {
- background-image: url('../img/actions/settings.png');
-}
-
-.lte9 input[type="submit"], .lte9 input[type="button"],
-.lte9 button, .lte9 .button,
-.lte9 #quota, .lte9 select, .lte9 .pager li a {
- background-color: #f1f1f1;
-}
-
-/* IE8 needs PNG image for header logo */
-.ie8 #header .logo {
- background-image: url(../img/logo-icon-175px.png);
-}
-
-/* IE8 needs background to be set to same color to make transparency look good. */
-.lte9 #body-login form input[type="text"] {
- border: 1px solid lightgrey; /* use border to add 1px line between input fields */
- background-color: white; /* don't change background on hover */
-}
-.lte9 #body-login form input[type="password"] {
- /* leave out top border for 1px line between input fields*/
- border-left: 1px solid lightgrey;
- border-right: 1px solid lightgrey;
- border-bottom: 1px solid lightgrey;
- background-color: white; /* don't change background on hover */
-}
-.ie8 #body-login input[type="submit"] {
- padding: 10px 5px;
- margin-top: 3px;
-}
-/* for whatever unexplained reason */
-.ie8 #password {
- width: 271px !important;
- min-width: auto !important;
-}
-
-/* disable opacity of info text on gradient
- since we cannot set a good backround color to use the filter&background hack as with the input labels */
-.lte9 #body-login p.info {
- filter: initial;
-}
-
/* deactivate show password toggle for IE. Does not work for 8 and 9+ have their own implementation. */
.ie #show, .ie #show+label {
display: none;
visibility: hidden;
}
-/* fix installation screen rendering issue for IE8+9 */
-.lte9 #body-login {
- min-height: 100%;
- height: auto !important;
-}
-
-/* oc-dialog only uses box shadow which is not supported by ie8 */
-.ie8 .oc-dialog {
- border: 1px solid #888888;
-}
-
-/* IE8 doesn't support transparent background - let's emulate black with an opacity of .3 on a dark blue background*/
-.ie8 fieldset .warning, .ie8 #body-login .error {
- background-color: #1B314D;
-}
-
-/* IE8 isn't able to display transparent background. So it is specified using a gradient */
-.ie8 #nojavascript {
- filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,startColorstr='#4c320000', endColorstr='#4c320000');
-}
-
-/* fix background of navigation popup in IE8 */
-.ie8 #navigation,
-.ie8 #expanddiv {
- background-color: #111;
-}
-
-/* needed else IE8 will randomly hide the borders... */
-.ie8 table th#headerDate, table td.date,
-.ie8 table th.column-last, table td.column-last {
- position: static;
-}
-
-.ie8 #controls {
- background-color: white;
-}
-
-.ie8 #content-wrapper {
- overflow-y: auto;
-}
-
-.ie8 #app-navigation .app-navigation-entry-edit input {
- line-height: 38px;
-}
-
diff --git a/core/css/multiselect.css b/core/css/multiselect.css
index a4b03319156..ef56044fd05 100644
--- a/core/css/multiselect.css
+++ b/core/css/multiselect.css
@@ -111,10 +111,3 @@ ul.multiselectoptions > li.creator > input {
padding: 5px;
margin: -5px;
}
-
-.ie8 div.multiselect span:first-child {
- display:block;
- position:relative;
- width: 90%;
- margin-right:-1px;
-}
diff --git a/core/css/styles.css b/core/css/styles.css
index d46e9700e87..c1bd76acbcf 100644
--- a/core/css/styles.css
+++ b/core/css/styles.css
@@ -189,7 +189,6 @@ a.two-factor-cancel {
.emptycontent {
color: #888;
text-align: center;
- margin-top: 100px; /* ie8 */
margin-top: 30vh;
width: 100%;
}
@@ -418,14 +417,7 @@ label.infield {
-ms-user-select: none;
user-select: none;
}
-html.ie8 #body-login form input[type="checkbox"]+label {
- margin-left: -28px;
- margin-top: -3px;
- vertical-align: auto;
-}
-html.ie8 #body-login form input[type="checkbox"] {
- margin-top: 5px;
-}
+
#body-login form .errors { background:#fed7d7; border:1px solid #f00; list-style-indent:inside; margin:0 0 2em; padding:1em; }
#body-login .success { background:#d7fed7; border:1px solid #0f0; width: 35%; margin: 30px auto; padding:1em; text-align: center;}
diff --git a/core/js/js.js b/core/js/js.js
index 1c49d38f950..7f98668dcb2 100644
--- a/core/js/js.js
+++ b/core/js/js.js
@@ -788,7 +788,6 @@ var OC={
$(document).trigger(new $.Event('ajaxError'), xhr);
};
- // FIXME: also needs an IE8 way
if (xhr.addEventListener) {
xhr.addEventListener('load', loadCallback);
xhr.addEventListener('error', errorCallback);
@@ -1857,30 +1856,10 @@ OC.Util = {
* This scales the image to the element's actual size, the URL is
* taken from the "background-image" CSS attribute.
*
+ * @deprecated IE8 isn't supported since 9.0
* @param {Object} $el image element
*/
- scaleFixForIE8: function($el) {
- if (!this.isIE8()) {
- return;
- }
- var self = this;
- $($el).each(function() {
- var url = $(this).css('background-image');
- var r = url.match(/url\(['"]?([^'")]*)['"]?\)/);
- if (!r) {
- return;
- }
- url = r[1];
- url = self.replaceSVGIcon(url);
- // TODO: escape
- url = url.replace(/'/g, '%27');
- $(this).css({
- 'filter': 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + url + '\', sizingMethod=\'scale\')',
- 'background-image': ''
- });
- });
- return $el;
- },
+ scaleFixForIE8: function($el) {},
/**
* Returns whether this is IE
@@ -1894,10 +1873,11 @@ OC.Util = {
/**
* Returns whether this is IE8
*
- * @return {bool} true if this is IE8, false otherwise
+ * @deprecated IE8 isn't supported since 9.0
+ * @return {bool} false (IE8 isn't supported anymore)
*/
isIE8: function() {
- return $('html').hasClass('ie8');
+ return false;
},
/**
diff --git a/core/js/sharedialoglinkshareview.js b/core/js/sharedialoglinkshareview.js
index 512da81da08..ff83b40e0a0 100644
--- a/core/js/sharedialoglinkshareview.js
+++ b/core/js/sharedialoglinkshareview.js
@@ -215,7 +215,7 @@
var permissions = OC.PERMISSION_READ;
if($checkbox.is(':checked')) {
- permissions = OC.PERMISSION_UPDATE | OC.PERMISSION_CREATE | OC.PERMISSION_READ;
+ permissions = OC.PERMISSION_UPDATE | OC.PERMISSION_CREATE | OC.PERMISSION_READ | OC.PERMISSION_DELETE;
}
this.model.saveLinkShare({
diff --git a/core/l10n/pl.js b/core/l10n/pl.js
index 787904ed794..50a9b458cf1 100644
--- a/core/l10n/pl.js
+++ b/core/l10n/pl.js
@@ -166,9 +166,13 @@ OC.L10N.register(
"delete" : "usuń",
"access control" : "kontrola dostępu",
"Could not unshare" : "Nie udało się usunąć udostępnienia",
+ "Share details could not be loaded for this item." : "Szczegóły udziału nie mogły zostać wczytane dla tego obiektu.",
"No users or groups found for {search}" : "Nie znaleziono użytkowników lub grup dla {search}",
"No users found for {search}" : "Nie znaleziono użytkowników dla {search}",
"An error occurred. Please try again" : "Wystąpił błąd. Proszę spróbować ponownie.",
+ "{sharee} (group)" : "{sharee} (grupa)",
+ "{sharee} (at {server})" : "{sharee} (na {server})",
+ "{sharee} (remote)" : "{sharee} (zdalny)",
"Share" : "Udostępnij",
"Share with people on other ownClouds using the syntax username@example.com/owncloud" : "Współdziel z użytkownikami innych chmur ownCloud używając wzorca uzytkownik@example.com/owncloud",
"Share with users…" : "Współdziel z użytkownikami...",
@@ -181,6 +185,7 @@ OC.L10N.register(
"Non-existing tag #{tag}" : "Znacznik #{tag} nie istnieje",
"restricted" : "ograniczone",
"invisible" : "niewidoczny",
+ "({scope})" : "({scope})",
"Delete" : "Usuń",
"Rename" : "Zmień nazwę",
"The object type is not specified." : "Nie określono typu obiektu.",
@@ -237,6 +242,7 @@ OC.L10N.register(
"Data folder" : "Katalog danych",
"Configure the database" : "Skonfiguruj bazę danych",
"Only %s is available." : "Dostępne jest wyłącznie %s.",
+ "Install and activate additional PHP modules to choose other database types." : "Zainstaluj lub aktywuj dodatkowe moduły PHP, aby uzyskać możliwość wyboru innych typów baz danych.",
"For more details check out the documentation." : "Aby uzyskać więcej informacji zapoznaj się z dokumentacją.",
"Database user" : "Użytkownik bazy danych",
"Database password" : "Hasło do bazy danych",
@@ -289,6 +295,7 @@ OC.L10N.register(
"To avoid timeouts with larger installations, you can instead run the following command from your installation directory:" : "Aby uniknąć timeout-ów przy większych instalacjach, możesz zamiast tego uruchomić następującą komendę w katalogu Twojej instalacji:",
"Detailed logs" : "Szczegółowe logi",
"Update needed" : "Wymagana aktualizacja",
+ "Please use the command line updater because you have a big instance." : "Ze względu na rozmiar Twojej instalacji użyj programu do aktualizacji z linii poleceń.",
"For help, see the <a target=\"_blank\" rel=\"noreferrer\" href=\"%s\">documentation</a>." : "Aby uzyskać pomoc, zajrzyj do <a target=\"_blank\" rel=\"noreferrer\" href=\"%s\">dokumentacji</a>.",
"This page will refresh itself when the %s instance is available again." : "Strona odświeży się gdy instancja %s będzie ponownie dostępna."
},
diff --git a/core/l10n/pl.json b/core/l10n/pl.json
index aed5fd35c6d..96391c796d9 100644
--- a/core/l10n/pl.json
+++ b/core/l10n/pl.json
@@ -164,9 +164,13 @@
"delete" : "usuń",
"access control" : "kontrola dostępu",
"Could not unshare" : "Nie udało się usunąć udostępnienia",
+ "Share details could not be loaded for this item." : "Szczegóły udziału nie mogły zostać wczytane dla tego obiektu.",
"No users or groups found for {search}" : "Nie znaleziono użytkowników lub grup dla {search}",
"No users found for {search}" : "Nie znaleziono użytkowników dla {search}",
"An error occurred. Please try again" : "Wystąpił błąd. Proszę spróbować ponownie.",
+ "{sharee} (group)" : "{sharee} (grupa)",
+ "{sharee} (at {server})" : "{sharee} (na {server})",
+ "{sharee} (remote)" : "{sharee} (zdalny)",
"Share" : "Udostępnij",
"Share with people on other ownClouds using the syntax username@example.com/owncloud" : "Współdziel z użytkownikami innych chmur ownCloud używając wzorca uzytkownik@example.com/owncloud",
"Share with users…" : "Współdziel z użytkownikami...",
@@ -179,6 +183,7 @@
"Non-existing tag #{tag}" : "Znacznik #{tag} nie istnieje",
"restricted" : "ograniczone",
"invisible" : "niewidoczny",
+ "({scope})" : "({scope})",
"Delete" : "Usuń",
"Rename" : "Zmień nazwę",
"The object type is not specified." : "Nie określono typu obiektu.",
@@ -235,6 +240,7 @@
"Data folder" : "Katalog danych",
"Configure the database" : "Skonfiguruj bazę danych",
"Only %s is available." : "Dostępne jest wyłącznie %s.",
+ "Install and activate additional PHP modules to choose other database types." : "Zainstaluj lub aktywuj dodatkowe moduły PHP, aby uzyskać możliwość wyboru innych typów baz danych.",
"For more details check out the documentation." : "Aby uzyskać więcej informacji zapoznaj się z dokumentacją.",
"Database user" : "Użytkownik bazy danych",
"Database password" : "Hasło do bazy danych",
@@ -287,6 +293,7 @@
"To avoid timeouts with larger installations, you can instead run the following command from your installation directory:" : "Aby uniknąć timeout-ów przy większych instalacjach, możesz zamiast tego uruchomić następującą komendę w katalogu Twojej instalacji:",
"Detailed logs" : "Szczegółowe logi",
"Update needed" : "Wymagana aktualizacja",
+ "Please use the command line updater because you have a big instance." : "Ze względu na rozmiar Twojej instalacji użyj programu do aktualizacji z linii poleceń.",
"For help, see the <a target=\"_blank\" rel=\"noreferrer\" href=\"%s\">documentation</a>." : "Aby uzyskać pomoc, zajrzyj do <a target=\"_blank\" rel=\"noreferrer\" href=\"%s\">dokumentacji</a>.",
"This page will refresh itself when the %s instance is available again." : "Strona odświeży się gdy instancja %s będzie ponownie dostępna."
},"pluralForm" :"nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"
diff --git a/core/templates/layout.base.php b/core/templates/layout.base.php
index 29c2ca6696d..7301ae690cc 100644
--- a/core/templates/layout.base.php
+++ b/core/templates/layout.base.php
@@ -1,7 +1,5 @@
<!DOCTYPE html>
-<!--[if lte IE 8]><html class="ng-csp ie ie8 lte9 lte8" data-placeholder-focus="false" lang="<?php p($_['language']); ?>" ><![endif]-->
-<!--[if IE 9]><html class="ng-csp ie ie9 lte9" data-placeholder-focus="false" lang="<?php p($_['language']); ?>" ><![endif]-->
-<!--[if (gt IE 9)|!(IE)]><!--><html class="ng-csp" data-placeholder-focus="false" lang="<?php p($_['language']); ?>" ><!--<![endif]-->
+<html class="ng-csp" data-placeholder-focus="false" lang="<?php p($_['language']); ?>" >
<head data-requesttoken="<?php p($_['requesttoken']); ?>">
<meta charset="utf-8">
<title>
diff --git a/core/templates/layout.guest.php b/core/templates/layout.guest.php
index 3f9c47f9aa6..985e95294ad 100644
--- a/core/templates/layout.guest.php
+++ b/core/templates/layout.guest.php
@@ -1,7 +1,5 @@
<!DOCTYPE html>
-<!--[if lte IE 8]><html class="ng-csp ie ie8 lte9 lte8" data-placeholder-focus="false" lang="<?php p($_['language']); ?>" ><![endif]-->
-<!--[if IE 9]><html class="ng-csp ie ie9 lte9" data-placeholder-focus="false" lang="<?php p($_['language']); ?>" ><![endif]-->
-<!--[if (gt IE 9)|!(IE)]><!--><html class="ng-csp" data-placeholder-focus="false" lang="<?php p($_['language']); ?>" ><!--<![endif]-->
+<html class="ng-csp" data-placeholder-focus="false" lang="<?php p($_['language']); ?>" >
<head data-requesttoken="<?php p($_['requesttoken']); ?>">
<meta charset="utf-8">
<title>
diff --git a/core/templates/layout.user.php b/core/templates/layout.user.php
index d762bd9897a..d42a392f40f 100644
--- a/core/templates/layout.user.php
+++ b/core/templates/layout.user.php
@@ -1,7 +1,5 @@
<!DOCTYPE html>
-<!--[if lte IE 8]><html class="ng-csp ie ie8 lte9 lte8" data-placeholder-focus="false" lang="<?php p($_['language']); ?>" ><![endif]-->
-<!--[if IE 9]><html class="ng-csp ie ie9 lte9" data-placeholder-focus="false" lang="<?php p($_['language']); ?>" ><![endif]-->
-<!--[if (gt IE 9)|!(IE)]><!--><html class="ng-csp" data-placeholder-focus="false" lang="<?php p($_['language']); ?>" ><!--<![endif]-->
+<html class="ng-csp" data-placeholder-focus="false" lang="<?php p($_['language']); ?>" >
<head data-user="<?php p($_['user_uid']); ?>" data-user-displayname="<?php p($_['user_displayname']); ?>" data-requesttoken="<?php p($_['requesttoken']); ?>">
<meta charset="utf-8">
<title>
diff --git a/lib/private/IntegrityCheck/Checker.php b/lib/private/IntegrityCheck/Checker.php
index ab68f752206..57127f280c4 100644
--- a/lib/private/IntegrityCheck/Checker.php
+++ b/lib/private/IntegrityCheck/Checker.php
@@ -108,7 +108,11 @@ class Checker {
* applicable for very specific scenarios and we should not advertise it
* too prominent. So please do not add it to config.sample.php.
*/
- $isIntegrityCheckDisabled = $this->config->getSystemValue('integrity.check.disabled', false);
+ if ($this->config !== null) {
+ $isIntegrityCheckDisabled = $this->config->getSystemValue('integrity.check.disabled', false);
+ } else {
+ $isIntegrityCheckDisabled = false;
+ }
if($isIntegrityCheckDisabled === true) {
return false;
}
@@ -401,7 +405,10 @@ class Checker {
return json_decode($cachedResults, true);
}
- return json_decode($this->config->getAppValue('core', self::CACHE_KEY, '{}'), true);
+ if ($this->config !== null) {
+ return json_decode($this->config->getAppValue('core', self::CACHE_KEY, '{}'), true);
+ }
+ return [];
}
/**
@@ -416,7 +423,9 @@ class Checker {
if(!empty($result)) {
$resultArray[$scope] = $result;
}
- $this->config->setAppValue('core', self::CACHE_KEY, json_encode($resultArray));
+ if ($this->config !== null) {
+ $this->config->setAppValue('core', self::CACHE_KEY, json_encode($resultArray));
+ }
$this->cache->set(self::CACHE_KEY, json_encode($resultArray));
}
diff --git a/lib/private/Repair/RepairInvalidShares.php b/lib/private/Repair/RepairInvalidShares.php
index 30f67a1f394..728632486d0 100644
--- a/lib/private/Repair/RepairInvalidShares.php
+++ b/lib/private/Repair/RepairInvalidShares.php
@@ -72,6 +72,25 @@ class RepairInvalidShares implements IRepairStep {
}
/**
+ * In the past link shares with public upload enabled were missing the delete permission.
+ */
+ private function addShareLinkDeletePermission(IOutput $out) {
+ $oldPerms = \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE;
+ $newPerms = \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE;
+ $builder = $this->connection->getQueryBuilder();
+ $builder
+ ->update('share')
+ ->set('permissions', $builder->expr()->literal($newPerms))
+ ->where($builder->expr()->eq('share_type', $builder->expr()->literal(\OC\Share\Constants::SHARE_TYPE_LINK)))
+ ->andWhere($builder->expr()->eq('permissions', $builder->expr()->literal($oldPerms)));
+
+ $updatedEntries = $builder->execute();
+ if ($updatedEntries > 0) {
+ $out->info('Fixed link share permissions for ' . $updatedEntries . ' shares');
+ }
+ }
+
+ /**
* Remove shares where the parent share does not exist anymore
*/
private function removeSharesNonExistingParent(IOutput $out) {
@@ -113,6 +132,10 @@ class RepairInvalidShares implements IRepairStep {
// this situation was only possible before 8.2
$this->removeExpirationDateFromNonLinkShares($out);
}
+ if (version_compare($ocVersionFromBeforeUpdate, '9.1.0.9', '<')) {
+ // this situation was only possible before 9.1
+ $this->addShareLinkDeletePermission($out);
+ }
$this->removeSharesNonExistingParent($out);
}
diff --git a/lib/private/Share20/Manager.php b/lib/private/Share20/Manager.php
index 478643e939b..9383255bc73 100644
--- a/lib/private/Share20/Manager.php
+++ b/lib/private/Share20/Manager.php
@@ -452,14 +452,9 @@ class Manager implements IManager {
throw new \InvalidArgumentException('Link shares can\'t have reshare permissions');
}
- // We don't allow deletion on link shares
- if ($share->getPermissions() & \OCP\Constants::PERMISSION_DELETE) {
- throw new \InvalidArgumentException('Link shares can\'t have delete permissions');
- }
-
// Check if public upload is allowed
if (!$this->shareApiLinkAllowPublicUpload() &&
- ($share->getPermissions() & (\OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE))) {
+ ($share->getPermissions() & (\OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE))) {
throw new \InvalidArgumentException('Public upload not allowed');
}
}
diff --git a/lib/private/User/Session.php b/lib/private/User/Session.php
index 2b65f31af28..6219a89e5b3 100644
--- a/lib/private/User/Session.php
+++ b/lib/private/User/Session.php
@@ -280,7 +280,7 @@ class Session implements IUserSession, Emitter {
*/
public function login($uid, $password) {
$this->session->regenerateId();
- if ($this->validateToken($password)) {
+ if ($this->validateToken($password, $uid)) {
// When logging in with token, the password must be decrypted first before passing to login hook
try {
$token = $this->tokenProvider->getToken($password);
@@ -584,15 +584,24 @@ class Session implements IUserSession, Emitter {
* Invalidates the token if checks fail
*
* @param string $token
+ * @param string $user login name
* @return boolean
*/
- private function validateToken($token) {
+ private function validateToken($token, $user = null) {
try {
$dbToken = $this->tokenProvider->getToken($token);
} catch (InvalidTokenException $ex) {
return false;
}
+ // Check if login names match
+ if (!is_null($user) && $dbToken->getLoginName() !== $user) {
+ // TODO: this makes it imposssible to use different login names on browser and client
+ // e.g. login by e-mail 'user@example.com' on browser for generating the token will not
+ // allow to use the client token with the login name 'user'.
+ return false;
+ }
+
if (!$this->checkTokenCredentials($dbToken, $token)) {
return false;
}
diff --git a/settings/Controller/AuthSettingsController.php b/settings/Controller/AuthSettingsController.php
index fba663b034d..db2db6e5bfc 100644
--- a/settings/Controller/AuthSettingsController.php
+++ b/settings/Controller/AuthSettingsController.php
@@ -118,6 +118,7 @@ class AuthSettingsController extends Controller {
return [
'token' => $token,
+ 'loginName' => $loginName,
'deviceToken' => $deviceToken
];
}
diff --git a/settings/css/settings.css b/settings/css/settings.css
index c4854ecec32..0af53cebf31 100644
--- a/settings/css/settings.css
+++ b/settings/css/settings.css
@@ -131,11 +131,19 @@ table.nostyle td { padding: 0.2em 0; }
opacity: 0.6;
}
+#new-app-login-name,
#new-app-password {
width: 186px;
font-family: monospace;
background-color: lightyellow;
}
+.app-password-row {
+ display: table-row;
+}
+.app-password-label {
+ display: table-cell;
+ padding-right: 1em;
+}
/* USERS */
#newgroup-init a span { margin-left: 20px; }
@@ -161,10 +169,6 @@ table.nostyle td { padding: 0.2em 0; }
width: 32px;
}
-.ie8 #newgroup-form .icon-add {
- height: 30px;
-}
-
.isgroup .groupname {
width: 85%;
display: block;
@@ -281,10 +285,6 @@ input.userFilter {width: 200px;}
width: 32px;
}
-
-.ie8 table.hascontrols{border-collapse:collapse;width: 100%;}
-.ie8 table.hascontrols tbody tr{border-collapse:collapse;border: 1px solid #ddd !important;}
-
/* used to highlight a user row in red */
#userlist tr.row-warning {
background-color: #FDD;
diff --git a/settings/js/authtoken.js b/settings/js/authtoken.js
index 215192d7163..1d958a4d675 100644
--- a/settings/js/authtoken.js
+++ b/settings/js/authtoken.js
@@ -20,14 +20,14 @@
*
*/
-(function(OC, Backbone) {
+(function(OC) {
'use strict';
OC.Settings = OC.Settings || {};
- var AuthToken = Backbone.Model.extend({
+ var AuthToken = OC.Backbone.Model.extend({
});
OC.Settings.AuthToken = AuthToken;
-})(OC, Backbone);
+})(OC);
diff --git a/settings/js/authtoken_collection.js b/settings/js/authtoken_collection.js
index a78e053995f..ab7f7d5804a 100644
--- a/settings/js/authtoken_collection.js
+++ b/settings/js/authtoken_collection.js
@@ -20,12 +20,12 @@
*
*/
-(function(OC, Backbone) {
+(function(OC) {
'use strict';
OC.Settings = OC.Settings || {};
- var AuthTokenCollection = Backbone.Collection.extend({
+ var AuthTokenCollection = OC.Backbone.Collection.extend({
model: OC.Settings.AuthToken,
@@ -49,4 +49,4 @@
OC.Settings.AuthTokenCollection = AuthTokenCollection;
-})(OC, Backbone);
+})(OC);
diff --git a/settings/js/authtoken_view.js b/settings/js/authtoken_view.js
index da5861689a0..01fc1b2ea34 100644
--- a/settings/js/authtoken_view.js
+++ b/settings/js/authtoken_view.js
@@ -1,4 +1,4 @@
-/* global Backbone, Handlebars, moment */
+/* global Handlebars, moment */
/**
* @author Christoph Wurst <christoph@owncloud.com>
@@ -20,7 +20,7 @@
*
*/
-(function(OC, _, Backbone, $, Handlebars, moment) {
+(function(OC, _, $, Handlebars, moment) {
'use strict';
OC.Settings = OC.Settings || {};
@@ -32,7 +32,7 @@
+ '<td><a class="icon-delete has-tooltip" title="' + t('core', 'Disconnect') + '"></a></td>'
+ '<tr>';
- var SubView = Backbone.View.extend({
+ var SubView = OC.Backbone.View.extend({
collection: null,
/**
@@ -94,7 +94,7 @@
}
});
- var AuthTokenView = Backbone.View.extend({
+ var AuthTokenView = OC.Backbone.View.extend({
collection: null,
_views: [],
@@ -107,6 +107,8 @@
_result: undefined,
+ _newAppLoginName: undefined,
+
_newAppPassword: undefined,
_hideAppPasswordBtn: undefined,
@@ -136,6 +138,8 @@
this._addAppPasswordBtn.click(_.bind(this._addAppPassword, this));
this._result = $('#app-password-result');
+ this._newAppLoginName = $('#new-app-login-name');
+ this._newAppLoginName.on('focus', _.bind(this._onNewTokenLoginNameFocus, this));
this._newAppPassword = $('#new-app-password');
this._newAppPassword.on('focus', _.bind(this._onNewTokenFocus, this));
this._hideAppPasswordBtn = $('#app-password-hide');
@@ -181,6 +185,7 @@
$.when(creatingToken).done(function(resp) {
_this.collection.add(resp.deviceToken);
_this.render();
+ _this._newAppLoginName.val(resp.loginName);
_this._newAppPassword.val(resp.token);
_this._toggleFormResult(false);
_this._newAppPassword.select();
@@ -194,6 +199,10 @@
});
},
+ _onNewTokenLoginNameFocus: function() {
+ this._newAppLoginName.select();
+ },
+
_onNewTokenFocus: function() {
this._newAppPassword.select();
},
@@ -220,6 +229,8 @@
var destroyingToken = token.destroy();
+ $row.find('.icon-delete').tooltip('hide');
+
var _this = this;
$.when(destroyingToken).fail(function() {
OC.Notification.showTemporary(t('core', 'Error while deleting the token'));
@@ -237,4 +248,4 @@
OC.Settings.AuthTokenView = AuthTokenView;
-})(OC, _, Backbone, $, Handlebars, moment);
+})(OC, _, $, Handlebars, moment);
diff --git a/settings/l10n/pl.js b/settings/l10n/pl.js
index 0d68b384931..903b374e0af 100644
--- a/settings/l10n/pl.js
+++ b/settings/l10n/pl.js
@@ -28,6 +28,7 @@ OC.L10N.register(
"Email saved" : "E-mail zapisany",
"Your full name has been changed." : "Twoja pełna nazwa została zmieniona.",
"Unable to change full name" : "Nie można zmienić pełnej nazwy",
+ "Redis" : "Redis",
"Security & setup warnings" : "Ostrzeżenia bezpieczeństwa i konfiguracji",
"Sharing" : "Udostępnianie",
"Server-side encryption" : "Szyfrowanie po stronie serwera",
@@ -48,6 +49,7 @@ OC.L10N.register(
"Migration in progress. Please wait until the migration is finished" : "Trwa migracja. Proszę poczekać, aż migracja dobiegnie końca.",
"Migration started …" : "Migracja rozpoczęta...",
"Sending..." : "Wysyłam...",
+ "Experimental" : "Eksperymentalny",
"All" : "Wszystkie",
"No apps found for your version" : "Nie znaleziono aplikacji dla twojej wersji",
"Update to %s" : "Uaktualnij do %s",
diff --git a/settings/l10n/pl.json b/settings/l10n/pl.json
index bdae17d4eef..f1c1994dd1d 100644
--- a/settings/l10n/pl.json
+++ b/settings/l10n/pl.json
@@ -26,6 +26,7 @@
"Email saved" : "E-mail zapisany",
"Your full name has been changed." : "Twoja pełna nazwa została zmieniona.",
"Unable to change full name" : "Nie można zmienić pełnej nazwy",
+ "Redis" : "Redis",
"Security & setup warnings" : "Ostrzeżenia bezpieczeństwa i konfiguracji",
"Sharing" : "Udostępnianie",
"Server-side encryption" : "Szyfrowanie po stronie serwera",
@@ -46,6 +47,7 @@
"Migration in progress. Please wait until the migration is finished" : "Trwa migracja. Proszę poczekać, aż migracja dobiegnie końca.",
"Migration started …" : "Migracja rozpoczęta...",
"Sending..." : "Wysyłam...",
+ "Experimental" : "Eksperymentalny",
"All" : "Wszystkie",
"No apps found for your version" : "Nie znaleziono aplikacji dla twojej wersji",
"Update to %s" : "Uaktualnij do %s",
diff --git a/settings/templates/personal.php b/settings/templates/personal.php
index 716570cad84..bcc803938ba 100644
--- a/settings/templates/personal.php
+++ b/settings/templates/personal.php
@@ -201,8 +201,16 @@ if($_['passwordChangeSupported']) {
<button id="add-app-password" class="button"><?php p($l->t('Create new app password')); ?></button>
</div>
<div id="app-password-result" class="hidden">
- <input id="new-app-password" type="text" readonly="readonly"/>
- <button id="app-password-hide" class="button"><?php p($l->t('Done')); ?></button>
+ <span><?php p($l->t('Use the credentials below to configure your app or device.')); ?></span>
+ <div class="app-password-row">
+ <span class="app-password-label"><?php p($l->t('Username')); ?></span>
+ <input id="new-app-login-name" type="text" readonly="readonly"/>
+ </div>
+ <div class="app-password-row">
+ <span class="app-password-label"><?php p($l->t('Password')); ?></span>
+ <input id="new-app-password" type="text" readonly="readonly"/>
+ <button id="app-password-hide" class="button"><?php p($l->t('Done')); ?></button>
+ </div>
</div>
</div>
diff --git a/tests/lib/Repair/RepairInvalidSharesTest.php b/tests/lib/Repair/RepairInvalidSharesTest.php
index a1e871bcc80..1ac42e53bf6 100644
--- a/tests/lib/Repair/RepairInvalidSharesTest.php
+++ b/tests/lib/Repair/RepairInvalidSharesTest.php
@@ -124,6 +124,93 @@ class RepairInvalidSharesTest extends TestCase {
}
/**
+ * Test remove expiration date for non-link shares
+ */
+ public function testAddShareLinkDeletePermission() {
+ $oldPerms = \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE;
+ $newPerms = \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE;
+
+ // share with old permissions
+ $qb = $this->connection->getQueryBuilder();
+ $qb->insert('share')
+ ->values([
+ 'share_type' => $qb->expr()->literal(Constants::SHARE_TYPE_LINK),
+ 'uid_owner' => $qb->expr()->literal('user1'),
+ 'item_type' => $qb->expr()->literal('folder'),
+ 'item_source' => $qb->expr()->literal(123),
+ 'item_target' => $qb->expr()->literal('/123'),
+ 'file_source' => $qb->expr()->literal(123),
+ 'file_target' => $qb->expr()->literal('/test'),
+ 'permissions' => $qb->expr()->literal($oldPerms),
+ 'stime' => $qb->expr()->literal(time()),
+ ])
+ ->execute();
+
+ $bogusShareId = $this->getLastShareId();
+
+ // share with read-only permissions
+ $qb = $this->connection->getQueryBuilder();
+ $qb->insert('share')
+ ->values([
+ 'share_type' => $qb->expr()->literal(Constants::SHARE_TYPE_LINK),
+ 'uid_owner' => $qb->expr()->literal('user1'),
+ 'item_type' => $qb->expr()->literal('folder'),
+ 'item_source' => $qb->expr()->literal(123),
+ 'item_target' => $qb->expr()->literal('/123'),
+ 'file_source' => $qb->expr()->literal(123),
+ 'file_target' => $qb->expr()->literal('/test'),
+ 'permissions' => $qb->expr()->literal(\OCP\Constants::PERMISSION_READ),
+ 'stime' => $qb->expr()->literal(time()),
+ ])
+ ->execute();
+
+ $keepThisShareId = $this->getLastShareId();
+
+ // user share to keep
+ $qb = $this->connection->getQueryBuilder();
+ $qb->insert('share')
+ ->values([
+ 'share_type' => $qb->expr()->literal(Constants::SHARE_TYPE_USER),
+ 'share_with' => $qb->expr()->literal('recipientuser1'),
+ 'uid_owner' => $qb->expr()->literal('user1'),
+ 'item_type' => $qb->expr()->literal('folder'),
+ 'item_source' => $qb->expr()->literal(123),
+ 'item_target' => $qb->expr()->literal('/123'),
+ 'file_source' => $qb->expr()->literal(123),
+ 'file_target' => $qb->expr()->literal('/test'),
+ 'permissions' => $qb->expr()->literal(3),
+ 'stime' => $qb->expr()->literal(time()),
+ ])
+ ->execute();
+
+ $keepThisShareId2 = $this->getLastShareId();
+
+ /** @var IOutput | \PHPUnit_Framework_MockObject_MockObject $outputMock */
+ $outputMock = $this->getMockBuilder('\OCP\Migration\IOutput')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->repair->run($outputMock);
+
+ $results = $this->connection->getQueryBuilder()
+ ->select('*')
+ ->from('share')
+ ->orderBy('permissions', 'ASC')
+ ->execute()
+ ->fetchAll();
+
+ $this->assertCount(3, $results);
+
+ $untouchedShare = $results[0];
+ $untouchedShare2 = $results[1];
+ $updatedShare = $results[2];
+ $this->assertEquals($keepThisShareId, $untouchedShare['id'], 'sanity check');
+ $this->assertEquals($keepThisShareId2, $untouchedShare2['id'], 'sanity check');
+ $this->assertEquals($bogusShareId, $updatedShare['id'], 'sanity check');
+ $this->assertEquals($newPerms, $updatedShare['permissions'], 'delete permission was added');
+ }
+
+ /**
* Test remove shares where the parent share does not exist anymore
*/
public function testSharesNonExistingParent() {
diff --git a/tests/lib/Share20/ManagerTest.php b/tests/lib/Share20/ManagerTest.php
index 5f7579474aa..689e47d8c52 100644
--- a/tests/lib/Share20/ManagerTest.php
+++ b/tests/lib/Share20/ManagerTest.php
@@ -1329,24 +1329,6 @@ class ManagerTest extends \Test\TestCase {
/**
* @expectedException Exception
- * @expectedExceptionMessage Link shares can't have delete permissions
- */
- public function testLinkCreateChecksDeletePermissions() {
- $share = $this->manager->newShare();
-
- $share->setPermissions(\OCP\Constants::PERMISSION_DELETE);
-
- $this->config
- ->method('getAppValue')
- ->will($this->returnValueMap([
- ['core', 'shareapi_allow_links', 'yes', 'yes'],
- ]));
-
- $this->invokePrivate($this->manager, 'linkCreateChecks', [$share]);
- }
-
- /**
- * @expectedException Exception
* @expectedExceptionMessage Public upload not allowed
*/
public function testLinkCreateChecksNoPublicUpload() {
diff --git a/tests/lib/User/SessionTest.php b/tests/lib/User/SessionTest.php
index eef4c7ff5ea..447c6142f34 100644
--- a/tests/lib/User/SessionTest.php
+++ b/tests/lib/User/SessionTest.php
@@ -315,6 +315,36 @@ class SessionTest extends \Test\TestCase {
}
/**
+ * When using a device token, the loginname must match the one that was used
+ * when generating the token on the browser.
+ */
+ public function testLoginWithDifferentTokenLoginName() {
+ $session = $this->getMock('\OC\Session\Memory', array(), array(''));
+ $manager = $this->getMock('\OC\User\Manager');
+ $backend = $this->getMock('\Test\Util\User\Dummy');
+ $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config);
+ $username = 'user123';
+ $token = new \OC\Authentication\Token\DefaultToken();
+ $token->setLoginName($username);
+
+ $session->expects($this->never())
+ ->method('set');
+ $session->expects($this->once())
+ ->method('regenerateId');
+ $this->tokenProvider->expects($this->once())
+ ->method('getToken')
+ ->with('bar')
+ ->will($this->returnValue($token));
+
+ $manager->expects($this->once())
+ ->method('checkPassword')
+ ->with('foo', 'bar')
+ ->will($this->returnValue(false));
+
+ $userSession->login('foo', 'bar');
+ }
+
+ /**
* @expectedException \OC\Authentication\Exceptions\PasswordLoginForbiddenException
*/
public function testLogClientInNoTokenPasswordWith2fa() {
diff --git a/version.php b/version.php
index 3015d976e53..b439ffbbdad 100644
--- a/version.php
+++ b/version.php
@@ -25,7 +25,7 @@
// We only can count up. The 4. digit is only for the internal patchlevel to trigger DB upgrades
// between betas, final and RCs. This is _not_ the public version number. Reset minor/patchlevel
// when updating major/minor version number.
-$OC_Version = array(9, 1, 0, 9);
+$OC_Version = array(9, 1, 0, 10);
// The human readable string
$OC_VersionString = '9.1.0 beta 2';