Browse Source

Merge remote-tracking branch 'upstream/master' into master-sync-upstream

tags/v10.0RC1
Lukas Reschke 8 years ago
parent
commit
6670d37658
42 changed files with 387 additions and 252 deletions
  1. 3
    0
      apps/comments/l10n/fi_FI.js
  2. 3
    0
      apps/comments/l10n/fi_FI.json
  3. 3
    0
      apps/comments/l10n/pl.js
  4. 3
    0
      apps/comments/l10n/pl.json
  5. 2
    2
      apps/federatedfilesharing/lib/FederatedShareProvider.php
  6. 18
    4
      apps/files/js/filelist.js
  7. 11
    0
      apps/files/tests/js/filelistSpec.js
  8. 4
    0
      apps/files_external/lib/AppInfo/Application.php
  9. 17
    5
      apps/files_sharing/lib/API/Share20OCS.php
  10. 67
    10
      apps/files_sharing/tests/API/Share20OCSTest.php
  11. 14
    2
      apps/files_sharing/tests/ApiTest.php
  12. 1
    0
      apps/systemtags/l10n/pl.js
  13. 1
    0
      apps/systemtags/l10n/pl.json
  14. 3
    3
      build/integration/features/sharing-v1.feature
  15. 3
    0
      core/Command/Encryption/DecryptAll.php
  16. 0
    8
      core/css/apps.css
  17. 0
    116
      core/css/fixes.css
  18. 0
    7
      core/css/multiselect.css
  19. 1
    9
      core/css/styles.css
  20. 5
    25
      core/js/js.js
  21. 1
    1
      core/js/sharedialoglinkshareview.js
  22. 7
    0
      core/l10n/pl.js
  23. 7
    0
      core/l10n/pl.json
  24. 1
    3
      core/templates/layout.base.php
  25. 1
    3
      core/templates/layout.guest.php
  26. 1
    3
      core/templates/layout.user.php
  27. 12
    3
      lib/private/IntegrityCheck/Checker.php
  28. 23
    0
      lib/private/Repair/RepairInvalidShares.php
  29. 1
    6
      lib/private/Share20/Manager.php
  30. 11
    2
      lib/private/User/Session.php
  31. 1
    0
      settings/Controller/AuthSettingsController.php
  32. 8
    8
      settings/css/settings.css
  33. 3
    3
      settings/js/authtoken.js
  34. 3
    3
      settings/js/authtoken_collection.js
  35. 16
    5
      settings/js/authtoken_view.js
  36. 2
    0
      settings/l10n/pl.js
  37. 2
    0
      settings/l10n/pl.json
  38. 10
    2
      settings/templates/personal.php
  39. 87
    0
      tests/lib/Repair/RepairInvalidSharesTest.php
  40. 0
    18
      tests/lib/Share20/ManagerTest.php
  41. 30
    0
      tests/lib/User/SessionTest.php
  42. 1
    1
      version.php

+ 3
- 0
apps/comments/l10n/fi_FI.js View File

"More comments..." : "Lisää kommentteja...", "More comments..." : "Lisää kommentteja...",
"Save" : "Tallenna", "Save" : "Tallenna",
"Allowed characters {count} of {max}" : "Sallittujen merkkien määrä {count}/{max}", "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", "{count} unread comments" : "{count} lukematonta kommenttia",
"Comment" : "Kommentti", "Comment" : "Kommentti",
"<strong>Comments</strong> for files <em>(always listed in stream)</em>" : "<strong>Kommentit</strong> tiedostoille <em>(aina listattu luettelossa)</em>", "<strong>Comments</strong> for files <em>(always listed in stream)</em>" : "<strong>Kommentit</strong> tiedostoille <em>(aina listattu luettelossa)</em>",

+ 3
- 0
apps/comments/l10n/fi_FI.json View File

"More comments..." : "Lisää kommentteja...", "More comments..." : "Lisää kommentteja...",
"Save" : "Tallenna", "Save" : "Tallenna",
"Allowed characters {count} of {max}" : "Sallittujen merkkien määrä {count}/{max}", "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", "{count} unread comments" : "{count} lukematonta kommenttia",
"Comment" : "Kommentti", "Comment" : "Kommentti",
"<strong>Comments</strong> for files <em>(always listed in stream)</em>" : "<strong>Kommentit</strong> tiedostoille <em>(aina listattu luettelossa)</em>", "<strong>Comments</strong> for files <em>(always listed in stream)</em>" : "<strong>Kommentit</strong> tiedostoille <em>(aina listattu luettelossa)</em>",

+ 3
- 0
apps/comments/l10n/pl.js View File

"More comments..." : "Więcej komentarzy...", "More comments..." : "Więcej komentarzy...",
"Save" : "Zapisz", "Save" : "Zapisz",
"Allowed characters {count} of {max}" : "Dozwolone znaki {count} z {max}", "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", "{count} unread comments" : "{count} nieprzeczytanych komentarzy",
"Comment" : "Komentarz", "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>", "<strong>Comments</strong> for files <em>(always listed in stream)</em>" : "<strong>Komentarze</strong> dla plików <em>(zawsze wypisane w strumieniu)</em>",

+ 3
- 0
apps/comments/l10n/pl.json View File

"More comments..." : "Więcej komentarzy...", "More comments..." : "Więcej komentarzy...",
"Save" : "Zapisz", "Save" : "Zapisz",
"Allowed characters {count} of {max}" : "Dozwolone znaki {count} z {max}", "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", "{count} unread comments" : "{count} nieprzeczytanych komentarzy",
"Comment" : "Komentarz", "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>", "<strong>Comments</strong> for files <em>(always listed in stream)</em>" : "<strong>Komentarze</strong> dla plików <em>(zawsze wypisane w strumieniu)</em>",

+ 2
- 2
apps/federatedfilesharing/lib/FederatedShareProvider.php View File



$isOwner = false; $isOwner = false;


$this->removeShareFromTable($share);

// if the local user is the owner we can send the unShare request directly... // if the local user is the owner we can send the unShare request directly...
if ($this->userManager->userExists($share->getShareOwner())) { if ($this->userManager->userExists($share->getShareOwner())) {
$this->notifications->sendRemoteUnShare($remote, $share->getId(), $share->getToken()); $this->notifications->sendRemoteUnShare($remote, $share->getId(), $share->getToken());
} }
$this->notifications->sendRevokeShare($remote, $remoteId, $share->getToken()); $this->notifications->sendRevokeShare($remote, $remoteId, $share->getToken());
} }

$this->removeShareFromTable($share);
} }


/** /**

+ 18
- 4
apps/files/js/filelist.js View File

* @param filter * @param filter
*/ */
setFilter:function(filter) { setFilter:function(filter) {
var total = 0;
this._filter = filter; this._filter = filter;
this.fileSummary.setFilter(filter, this.files); this.fileSummary.setFilter(filter, this.files);
total = this.fileSummary.getTotal();
if (!this.$el.find('.mask').exists()) { if (!this.$el.find('.mask').exists()) {
this.hideIrrelevantUIWhenNoFilesMatch(); this.hideIrrelevantUIWhenNoFilesMatch();
} }
var that = this; var that = this;
var visibleCount = 0;
filter = filter.toLowerCase(); 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) { if ($e.data('file').toString().toLowerCase().indexOf(filter) === -1) {
$e.addClass('hidden'); $e.addClass('hidden');
} else { } else {
visibleCount++;
$e.removeClass('hidden'); $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() { hideIrrelevantUIWhenNoFilesMatch:function() {
if (this._filter && this.fileSummary.summary.totalDirs + this.fileSummary.summary.totalFiles === 0) { if (this._filter && this.fileSummary.summary.totalDirs + this.fileSummary.summary.totalFiles === 0) {

+ 11
- 0
apps/files/tests/js/filelistSpec.js View File

expect($summary.find('.info').text()).toEqual("1 folder and 3 files"); expect($summary.find('.info').text()).toEqual("1 folder and 3 files");
expect($nofilterresults.hasClass('hidden')).toEqual(true); 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() { it('hides the emptyfiles notice when using filter()', function() {
expect(fileList.files.length).toEqual(0); expect(fileList.files.length).toEqual(0);
expect(fileList.files).toEqual([]); expect(fileList.files).toEqual([]);

+ 4
- 0
apps/files_external/lib/AppInfo/Application.php View File

$backendService->registerBackendProvider($this); $backendService->registerBackendProvider($this);
$backendService->registerAuthMechanismProvider($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! // app developers: do NOT depend on this! it will disappear with oC 9.0!
\OC::$server->getEventDispatcher()->dispatch( \OC::$server->getEventDispatcher()->dispatch(
'OCA\\Files_External::loadAdditionalBackends' 'OCA\\Files_External::loadAdditionalBackends'

+ 17
- 5
apps/files_sharing/lib/API/Share20OCS.php View File

$share->setPermissions( $share->setPermissions(
\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_READ |
\OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_CREATE |
\OCP\Constants::PERMISSION_UPDATE
\OCP\Constants::PERMISSION_UPDATE |
\OCP\Constants::PERMISSION_DELETE
); );
} else { } else {
$share->setPermissions(\OCP\Constants::PERMISSION_READ); $share->setPermissions(\OCP\Constants::PERMISSION_READ);


$newPermissions = null; $newPermissions = null;
if ($publicUpload === 'true') { 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') { } else if ($publicUpload === 'false') {
$newPermissions = \OCP\Constants::PERMISSION_READ; $newPermissions = \OCP\Constants::PERMISSION_READ;
} }


if ($newPermissions !== null && if ($newPermissions !== null &&
$newPermissions !== \OCP\Constants::PERMISSION_READ && $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); $share->getNode()->unlock(ILockingProvider::LOCK_SHARED);
return new \OC_OCS_Result(null, 400, $this->l->t('Can\'t change permissions for public share links')); 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()) { if (!$this->shareManager->shareApiLinkAllowPublicUpload()) {
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED); $share->getNode()->unlock(ILockingProvider::LOCK_SHARED);
return new \OC_OCS_Result(null, 403, $this->l->t('Public upload disabled by the administrator')); return new \OC_OCS_Result(null, 403, $this->l->t('Public upload disabled by the administrator'));
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED); $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')); 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) { if ($newPermissions !== null) {

+ 67
- 10
apps/files_sharing/tests/API/Share20OCSTest.php View File

$this->callback(function (\OCP\Share\IShare $share) use ($path) { $this->callback(function (\OCP\Share\IShare $share) use ($path) {
return $share->getNode() === $path && return $share->getNode() === $path &&
$share->getShareType() === \OCP\Share::SHARE_TYPE_LINK && $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->getSharedBy() === 'currentUser' &&
$share->getPassword() === null && $share->getPassword() === null &&
$share->getExpirationDate() === null; $share->getExpirationDate() === null;
$date = new \DateTime('2000-01-01'); $date = new \DateTime('2000-01-01');
$date->setTime(0,0,0); $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->getPassword() === 'password' &&
$share->getExpirationDate() == $date; $share->getExpirationDate() == $date;
}) })
$this->assertEquals($expected->getData(), $result->getData()); $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() { public function testUpdateLinkShareInvalidDate() {
$ocs = $this->mockFormatShare(); $ocs = $this->mockFormatShare();


$this->assertEquals($expected->getData(), $result->getData()); $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(); $ocs = $this->mockFormatShare();


$folder = $this->getMock('\OCP\Files\Folder'); $folder = $this->getMock('\OCP\Files\Folder');


$this->request $this->request
->method('getParam') ->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('getShareById')->with('ocinternal:42')->willReturn($share);
$this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(false); $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(false);


$this->shareManager->expects($this->once())->method('updateShare')->with( $this->shareManager->expects($this->once())->method('updateShare')->with(
$this->callback(function (\OCP\Share\IShare $share) use ($date) { $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->getPassword() === 'password' &&
$share->getExpirationDate() === $date; $share->getExpirationDate() === $date;
}) })


$this->shareManager->expects($this->once())->method('updateShare')->with( $this->shareManager->expects($this->once())->method('updateShare')->with(
$this->callback(function (\OCP\Share\IShare $share) use ($date) { $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->getPassword() === 'password' &&
$share->getExpirationDate() === $date; $share->getExpirationDate() === $date;
}) })

+ 14
- 2
apps/files_sharing/tests/ApiTest.php View File

$this->assertTrue($result->succeeded()); $this->assertTrue($result->succeeded());


$data = $result->getData(); $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->assertEmpty($data['expiration']);
$this->assertTrue(is_string($data['token'])); $this->assertTrue(is_string($data['token']));


$this->assertTrue($result->succeeded()); $this->assertTrue($result->succeeded());


$share1 = $this->shareManager->getShareById($share1->getFullId()); $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 // cleanup
$this->shareManager->deleteShare($share1); $this->shareManager->deleteShare($share1);

+ 1
- 0
apps/systemtags/l10n/pl.js View File

"%1$s updated system tag %3$s to %2$s" : "%1$s zaktualizowany system etykiet%3$s do %2$s", "%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 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", "%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)", "%s (invisible)" : "%s (niewidoczny)",
"No files in here" : "Brak plików", "No files in here" : "Brak plików",
"No entries found in this folder" : "Brak wpisów w tym folderze", "No entries found in this folder" : "Brak wpisów w tym folderze",

+ 1
- 0
apps/systemtags/l10n/pl.json View File

"%1$s updated system tag %3$s to %2$s" : "%1$s zaktualizowany system etykiet%3$s do %2$s", "%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 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", "%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)", "%s (invisible)" : "%s (niewidoczny)",
"No files in here" : "Brak plików", "No files in here" : "Brak plików",
"No entries found in this folder" : "Brak wpisów w tym folderze", "No entries found in this folder" : "Brak wpisów w tym folderze",

+ 3
- 3
build/integration/features/sharing-v1.feature View File

And the HTTP status code should be "200" And the HTTP status code should be "200"
And Share fields of last share match with And Share fields of last share match with
| id | A_NUMBER | | id | A_NUMBER |
| permissions | 7 |
| permissions | 15 |
| expiration | +3 days | | expiration | +3 days |
| url | AN_URL | | url | AN_URL |
| token | A_TOKEN | | token | A_TOKEN |
| share_type | 3 | | share_type | 3 |
| file_source | A_NUMBER | | file_source | A_NUMBER |
| file_target | /FOLDER | | file_target | /FOLDER |
| permissions | 7 |
| permissions | 15 |
| stime | A_NUMBER | | stime | A_NUMBER |
| token | A_TOKEN | | token | A_TOKEN |
| storage | A_NUMBER | | storage | A_NUMBER |
| share_type | 3 | | share_type | 3 |
| file_source | A_NUMBER | | file_source | A_NUMBER |
| file_target | /FOLDER | | file_target | /FOLDER |
| permissions | 7 |
| permissions | 15 |
| stime | A_NUMBER | | stime | A_NUMBER |
| token | A_TOKEN | | token | A_TOKEN |
| storage | A_NUMBER | | storage | A_NUMBER |

+ 3
- 0
core/Command/Encryption/DecryptAll.php View File

$output->writeln(' aborted.'); $output->writeln(' aborted.');
$output->writeln('Server side encryption remains enabled'); $output->writeln('Server side encryption remains enabled');
$this->config->setAppValue('core', 'encryption_enabled', 'yes'); $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(); $this->resetSingleUserAndTrashbin();
} else { } else {

+ 0
- 8
core/css/apps.css View File

text-overflow: ellipsis; text-overflow: ellipsis;
overflow: hidden; overflow: hidden;
display: inline-block; display: inline-block;
width: 201px; /* fallback for IE8 */
width: calc(100% - 49px); width: calc(100% - 49px);
line-height: 44px; line-height: 44px;
float: left; float: left;
.edge #app-navigation .app-navigation-entry-menu:after { .edge #app-navigation .app-navigation-entry-menu:after {
border: 1px solid #eee; border: 1px solid #eee;
} }
.ie8 .bubble {
margin-top: 18px;
}
.ie8 .bubble:after {
display: none;
}
/* miraculous border arrow stuff */ /* miraculous border arrow stuff */
.bubble:after, .bubble:after,
#app-navigation .app-navigation-entry-menu:after { #app-navigation .app-navigation-entry-menu:after {
#app-navigation .app-navigation-entry-edit input { #app-navigation .app-navigation-entry-edit input {
border-bottom-right-radius: 0; border-bottom-right-radius: 0;
border-top-right-radius: 0; border-top-right-radius: 0;
width: 204px; /* fallback for IE8 */
width: calc(100% - 36px); width: calc(100% - 36px);
padding: 5px; padding: 5px;
margin-right: 0; margin-right: 0;

+ 0
- 116
core/css/fixes.css View File

height: 32px; 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. */ /* deactivate show password toggle for IE. Does not work for 8 and 9+ have their own implementation. */
.ie #show, .ie #show+label { .ie #show, .ie #show+label {
display: none; display: none;
visibility: hidden; 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;
}


+ 0
- 7
core/css/multiselect.css View File

padding: 5px; padding: 5px;
margin: -5px; margin: -5px;
} }

.ie8 div.multiselect span:first-child {
display:block;
position:relative;
width: 90%;
margin-right:-1px;
}

+ 1
- 9
core/css/styles.css View File

.emptycontent { .emptycontent {
color: #888; color: #888;
text-align: center; text-align: center;
margin-top: 100px; /* ie8 */
margin-top: 30vh; margin-top: 30vh;
width: 100%; width: 100%;
} }
-ms-user-select: none; -ms-user-select: none;
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 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;} #body-login .success { background:#d7fed7; border:1px solid #0f0; width: 35%; margin: 30px auto; padding:1em; text-align: center;}



+ 5
- 25
core/js/js.js View File

$(document).trigger(new $.Event('ajaxError'), xhr); $(document).trigger(new $.Event('ajaxError'), xhr);
}; };


// FIXME: also needs an IE8 way
if (xhr.addEventListener) { if (xhr.addEventListener) {
xhr.addEventListener('load', loadCallback); xhr.addEventListener('load', loadCallback);
xhr.addEventListener('error', errorCallback); xhr.addEventListener('error', errorCallback);
* This scales the image to the element's actual size, the URL is * This scales the image to the element's actual size, the URL is
* taken from the "background-image" CSS attribute. * taken from the "background-image" CSS attribute.
* *
* @deprecated IE8 isn't supported since 9.0
* @param {Object} $el image element * @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 * Returns whether this is IE
/** /**
* Returns whether this is IE8 * 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() { isIE8: function() {
return $('html').hasClass('ie8');
return false;
}, },


/** /**

+ 1
- 1
core/js/sharedialoglinkshareview.js View File



var permissions = OC.PERMISSION_READ; var permissions = OC.PERMISSION_READ;
if($checkbox.is(':checked')) { 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({ this.model.saveLinkShare({

+ 7
- 0
core/l10n/pl.js View File

"delete" : "usuń", "delete" : "usuń",
"access control" : "kontrola dostępu", "access control" : "kontrola dostępu",
"Could not unshare" : "Nie udało się usunąć udostępnienia", "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 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}", "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.", "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" : "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 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...", "Share with users…" : "Współdziel z użytkownikami...",
"Non-existing tag #{tag}" : "Znacznik #{tag} nie istnieje", "Non-existing tag #{tag}" : "Znacznik #{tag} nie istnieje",
"restricted" : "ograniczone", "restricted" : "ograniczone",
"invisible" : "niewidoczny", "invisible" : "niewidoczny",
"({scope})" : "({scope})",
"Delete" : "Usuń", "Delete" : "Usuń",
"Rename" : "Zmień nazwę", "Rename" : "Zmień nazwę",
"The object type is not specified." : "Nie określono typu obiektu.", "The object type is not specified." : "Nie określono typu obiektu.",
"Data folder" : "Katalog danych", "Data folder" : "Katalog danych",
"Configure the database" : "Skonfiguruj bazę danych", "Configure the database" : "Skonfiguruj bazę danych",
"Only %s is available." : "Dostępne jest wyłącznie %s.", "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ą.", "For more details check out the documentation." : "Aby uzyskać więcej informacji zapoznaj się z dokumentacją.",
"Database user" : "Użytkownik bazy danych", "Database user" : "Użytkownik bazy danych",
"Database password" : "Hasło do bazy danych", "Database password" : "Hasło do bazy danych",
"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:", "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", "Detailed logs" : "Szczegółowe logi",
"Update needed" : "Wymagana aktualizacja", "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>.", "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." "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."
}, },

+ 7
- 0
core/l10n/pl.json View File

"delete" : "usuń", "delete" : "usuń",
"access control" : "kontrola dostępu", "access control" : "kontrola dostępu",
"Could not unshare" : "Nie udało się usunąć udostępnienia", "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 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}", "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.", "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" : "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 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...", "Share with users…" : "Współdziel z użytkownikami...",
"Non-existing tag #{tag}" : "Znacznik #{tag} nie istnieje", "Non-existing tag #{tag}" : "Znacznik #{tag} nie istnieje",
"restricted" : "ograniczone", "restricted" : "ograniczone",
"invisible" : "niewidoczny", "invisible" : "niewidoczny",
"({scope})" : "({scope})",
"Delete" : "Usuń", "Delete" : "Usuń",
"Rename" : "Zmień nazwę", "Rename" : "Zmień nazwę",
"The object type is not specified." : "Nie określono typu obiektu.", "The object type is not specified." : "Nie określono typu obiektu.",
"Data folder" : "Katalog danych", "Data folder" : "Katalog danych",
"Configure the database" : "Skonfiguruj bazę danych", "Configure the database" : "Skonfiguruj bazę danych",
"Only %s is available." : "Dostępne jest wyłącznie %s.", "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ą.", "For more details check out the documentation." : "Aby uzyskać więcej informacji zapoznaj się z dokumentacją.",
"Database user" : "Użytkownik bazy danych", "Database user" : "Użytkownik bazy danych",
"Database password" : "Hasło do bazy danych", "Database password" : "Hasło do bazy danych",
"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:", "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", "Detailed logs" : "Szczegółowe logi",
"Update needed" : "Wymagana aktualizacja", "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>.", "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." "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);" },"pluralForm" :"nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"

+ 1
- 3
core/templates/layout.base.php View File

<!DOCTYPE html> <!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']); ?>"> <head data-requesttoken="<?php p($_['requesttoken']); ?>">
<meta charset="utf-8"> <meta charset="utf-8">
<title> <title>

+ 1
- 3
core/templates/layout.guest.php View File

<!DOCTYPE html> <!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']); ?>"> <head data-requesttoken="<?php p($_['requesttoken']); ?>">
<meta charset="utf-8"> <meta charset="utf-8">
<title> <title>

+ 1
- 3
core/templates/layout.user.php View File

<!DOCTYPE html> <!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']); ?>"> <head data-user="<?php p($_['user_uid']); ?>" data-user-displayname="<?php p($_['user_displayname']); ?>" data-requesttoken="<?php p($_['requesttoken']); ?>">
<meta charset="utf-8"> <meta charset="utf-8">
<title> <title>

+ 12
- 3
lib/private/IntegrityCheck/Checker.php View File

* applicable for very specific scenarios and we should not advertise it * applicable for very specific scenarios and we should not advertise it
* too prominent. So please do not add it to config.sample.php. * 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) { if($isIntegrityCheckDisabled === true) {
return false; return false;
} }
return json_decode($cachedResults, true); 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 [];
} }


/** /**
if(!empty($result)) { if(!empty($result)) {
$resultArray[$scope] = $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)); $this->cache->set(self::CACHE_KEY, json_encode($resultArray));
} }



+ 23
- 0
lib/private/Repair/RepairInvalidShares.php View File

} }
} }


/**
* 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 * Remove shares where the parent share does not exist anymore
*/ */
// this situation was only possible before 8.2 // this situation was only possible before 8.2
$this->removeExpirationDateFromNonLinkShares($out); $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); $this->removeSharesNonExistingParent($out);
} }

+ 1
- 6
lib/private/Share20/Manager.php View File

throw new \InvalidArgumentException('Link shares can\'t have reshare permissions'); 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 // Check if public upload is allowed
if (!$this->shareApiLinkAllowPublicUpload() && 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'); throw new \InvalidArgumentException('Public upload not allowed');
} }
} }

+ 11
- 2
lib/private/User/Session.php View File

*/ */
public function login($uid, $password) { public function login($uid, $password) {
$this->session->regenerateId(); $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 // When logging in with token, the password must be decrypted first before passing to login hook
try { try {
$token = $this->tokenProvider->getToken($password); $token = $this->tokenProvider->getToken($password);
* Invalidates the token if checks fail * Invalidates the token if checks fail
* *
* @param string $token * @param string $token
* @param string $user login name
* @return boolean * @return boolean
*/ */
private function validateToken($token) {
private function validateToken($token, $user = null) {
try { try {
$dbToken = $this->tokenProvider->getToken($token); $dbToken = $this->tokenProvider->getToken($token);
} catch (InvalidTokenException $ex) { } catch (InvalidTokenException $ex) {
return false; 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)) { if (!$this->checkTokenCredentials($dbToken, $token)) {
return false; return false;
} }

+ 1
- 0
settings/Controller/AuthSettingsController.php View File



return [ return [
'token' => $token, 'token' => $token,
'loginName' => $loginName,
'deviceToken' => $deviceToken 'deviceToken' => $deviceToken
]; ];
} }

+ 8
- 8
settings/css/settings.css View File

opacity: 0.6; opacity: 0.6;
} }


#new-app-login-name,
#new-app-password { #new-app-password {
width: 186px; width: 186px;
font-family: monospace; font-family: monospace;
background-color: lightyellow; background-color: lightyellow;
} }
.app-password-row {
display: table-row;
}
.app-password-label {
display: table-cell;
padding-right: 1em;
}


/* USERS */ /* USERS */
#newgroup-init a span { margin-left: 20px; } #newgroup-init a span { margin-left: 20px; }
width: 32px; width: 32px;
} }


.ie8 #newgroup-form .icon-add {
height: 30px;
}

.isgroup .groupname { .isgroup .groupname {
width: 85%; width: 85%;
display: block; display: block;
width: 32px; 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 */ /* used to highlight a user row in red */
#userlist tr.row-warning { #userlist tr.row-warning {
background-color: #FDD; background-color: #FDD;

+ 3
- 3
settings/js/authtoken.js View File

* *
*/ */


(function(OC, Backbone) {
(function(OC) {
'use strict'; 'use strict';


OC.Settings = OC.Settings || {}; OC.Settings = OC.Settings || {};


var AuthToken = Backbone.Model.extend({
var AuthToken = OC.Backbone.Model.extend({
}); });


OC.Settings.AuthToken = AuthToken; OC.Settings.AuthToken = AuthToken;


})(OC, Backbone);
})(OC);

+ 3
- 3
settings/js/authtoken_collection.js View File

* *
*/ */


(function(OC, Backbone) {
(function(OC) {
'use strict'; 'use strict';


OC.Settings = OC.Settings || {}; OC.Settings = OC.Settings || {};


var AuthTokenCollection = Backbone.Collection.extend({
var AuthTokenCollection = OC.Backbone.Collection.extend({


model: OC.Settings.AuthToken, model: OC.Settings.AuthToken,




OC.Settings.AuthTokenCollection = AuthTokenCollection; OC.Settings.AuthTokenCollection = AuthTokenCollection;


})(OC, Backbone);
})(OC);

+ 16
- 5
settings/js/authtoken_view.js View File

/* global Backbone, Handlebars, moment */
/* global Handlebars, moment */


/** /**
* @author Christoph Wurst <christoph@owncloud.com> * @author Christoph Wurst <christoph@owncloud.com>
* *
*/ */


(function(OC, _, Backbone, $, Handlebars, moment) {
(function(OC, _, $, Handlebars, moment) {
'use strict'; 'use strict';


OC.Settings = OC.Settings || {}; OC.Settings = OC.Settings || {};
+ '<td><a class="icon-delete has-tooltip" title="' + t('core', 'Disconnect') + '"></a></td>' + '<td><a class="icon-delete has-tooltip" title="' + t('core', 'Disconnect') + '"></a></td>'
+ '<tr>'; + '<tr>';


var SubView = Backbone.View.extend({
var SubView = OC.Backbone.View.extend({
collection: null, collection: null,


/** /**
} }
}); });


var AuthTokenView = Backbone.View.extend({
var AuthTokenView = OC.Backbone.View.extend({
collection: null, collection: null,


_views: [], _views: [],


_result: undefined, _result: undefined,


_newAppLoginName: undefined,

_newAppPassword: undefined, _newAppPassword: undefined,


_hideAppPasswordBtn: undefined, _hideAppPasswordBtn: undefined,
this._addAppPasswordBtn.click(_.bind(this._addAppPassword, this)); this._addAppPasswordBtn.click(_.bind(this._addAppPassword, this));


this._result = $('#app-password-result'); 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 = $('#new-app-password');
this._newAppPassword.on('focus', _.bind(this._onNewTokenFocus, this)); this._newAppPassword.on('focus', _.bind(this._onNewTokenFocus, this));
this._hideAppPasswordBtn = $('#app-password-hide'); this._hideAppPasswordBtn = $('#app-password-hide');
$.when(creatingToken).done(function(resp) { $.when(creatingToken).done(function(resp) {
_this.collection.add(resp.deviceToken); _this.collection.add(resp.deviceToken);
_this.render(); _this.render();
_this._newAppLoginName.val(resp.loginName);
_this._newAppPassword.val(resp.token); _this._newAppPassword.val(resp.token);
_this._toggleFormResult(false); _this._toggleFormResult(false);
_this._newAppPassword.select(); _this._newAppPassword.select();
}); });
}, },


_onNewTokenLoginNameFocus: function() {
this._newAppLoginName.select();
},

_onNewTokenFocus: function() { _onNewTokenFocus: function() {
this._newAppPassword.select(); this._newAppPassword.select();
}, },


var destroyingToken = token.destroy(); var destroyingToken = token.destroy();


$row.find('.icon-delete').tooltip('hide');

var _this = this; var _this = this;
$.when(destroyingToken).fail(function() { $.when(destroyingToken).fail(function() {
OC.Notification.showTemporary(t('core', 'Error while deleting the token')); OC.Notification.showTemporary(t('core', 'Error while deleting the token'));


OC.Settings.AuthTokenView = AuthTokenView; OC.Settings.AuthTokenView = AuthTokenView;


})(OC, _, Backbone, $, Handlebars, moment);
})(OC, _, $, Handlebars, moment);

+ 2
- 0
settings/l10n/pl.js View File

"Email saved" : "E-mail zapisany", "Email saved" : "E-mail zapisany",
"Your full name has been changed." : "Twoja pełna nazwa została zmieniona.", "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", "Unable to change full name" : "Nie można zmienić pełnej nazwy",
"Redis" : "Redis",
"Security & setup warnings" : "Ostrzeżenia bezpieczeństwa i konfiguracji", "Security & setup warnings" : "Ostrzeżenia bezpieczeństwa i konfiguracji",
"Sharing" : "Udostępnianie", "Sharing" : "Udostępnianie",
"Server-side encryption" : "Szyfrowanie po stronie serwera", "Server-side encryption" : "Szyfrowanie po stronie serwera",
"Migration in progress. Please wait until the migration is finished" : "Trwa migracja. Proszę poczekać, aż migracja dobiegnie końca.", "Migration in progress. Please wait until the migration is finished" : "Trwa migracja. Proszę poczekać, aż migracja dobiegnie końca.",
"Migration started …" : "Migracja rozpoczęta...", "Migration started …" : "Migracja rozpoczęta...",
"Sending..." : "Wysyłam...", "Sending..." : "Wysyłam...",
"Experimental" : "Eksperymentalny",
"All" : "Wszystkie", "All" : "Wszystkie",
"No apps found for your version" : "Nie znaleziono aplikacji dla twojej wersji", "No apps found for your version" : "Nie znaleziono aplikacji dla twojej wersji",
"Update to %s" : "Uaktualnij do %s", "Update to %s" : "Uaktualnij do %s",

+ 2
- 0
settings/l10n/pl.json View File

"Email saved" : "E-mail zapisany", "Email saved" : "E-mail zapisany",
"Your full name has been changed." : "Twoja pełna nazwa została zmieniona.", "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", "Unable to change full name" : "Nie można zmienić pełnej nazwy",
"Redis" : "Redis",
"Security & setup warnings" : "Ostrzeżenia bezpieczeństwa i konfiguracji", "Security & setup warnings" : "Ostrzeżenia bezpieczeństwa i konfiguracji",
"Sharing" : "Udostępnianie", "Sharing" : "Udostępnianie",
"Server-side encryption" : "Szyfrowanie po stronie serwera", "Server-side encryption" : "Szyfrowanie po stronie serwera",
"Migration in progress. Please wait until the migration is finished" : "Trwa migracja. Proszę poczekać, aż migracja dobiegnie końca.", "Migration in progress. Please wait until the migration is finished" : "Trwa migracja. Proszę poczekać, aż migracja dobiegnie końca.",
"Migration started …" : "Migracja rozpoczęta...", "Migration started …" : "Migracja rozpoczęta...",
"Sending..." : "Wysyłam...", "Sending..." : "Wysyłam...",
"Experimental" : "Eksperymentalny",
"All" : "Wszystkie", "All" : "Wszystkie",
"No apps found for your version" : "Nie znaleziono aplikacji dla twojej wersji", "No apps found for your version" : "Nie znaleziono aplikacji dla twojej wersji",
"Update to %s" : "Uaktualnij do %s", "Update to %s" : "Uaktualnij do %s",

+ 10
- 2
settings/templates/personal.php View File

<button id="add-app-password" class="button"><?php p($l->t('Create new app password')); ?></button> <button id="add-app-password" class="button"><?php p($l->t('Create new app password')); ?></button>
</div> </div>
<div id="app-password-result" class="hidden"> <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>
</div> </div>



+ 87
- 0
tests/lib/Repair/RepairInvalidSharesTest.php View File

$this->assertNotNull($linkShare['expiration'], 'valid link share expiration date still there'); $this->assertNotNull($linkShare['expiration'], 'valid link share expiration date still there');
} }


/**
* 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 * Test remove shares where the parent share does not exist anymore
*/ */

+ 0
- 18
tests/lib/Share20/ManagerTest.php View File

$this->invokePrivate($this->manager, 'linkCreateChecks', [$share]); $this->invokePrivate($this->manager, 'linkCreateChecks', [$share]);
} }


/**
* @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 * @expectedException Exception
* @expectedExceptionMessage Public upload not allowed * @expectedExceptionMessage Public upload not allowed

+ 30
- 0
tests/lib/User/SessionTest.php View File

$userSession->login('foo', 'bar'); $userSession->login('foo', 'bar');
} }


/**
* 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 * @expectedException \OC\Authentication\Exceptions\PasswordLoginForbiddenException
*/ */

+ 1
- 1
version.php View File

// We only can count up. The 4. digit is only for the internal patchlevel to trigger DB upgrades // 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 // between betas, final and RCs. This is _not_ the public version number. Reset minor/patchlevel
// when updating major/minor version number. // when updating major/minor version number.
$OC_Version = array(9, 1, 0, 9);
$OC_Version = array(9, 1, 0, 10);


// The human readable string // The human readable string
$OC_VersionString = '9.1.0 beta 2'; $OC_VersionString = '9.1.0 beta 2';

Loading…
Cancel
Save