Преглед на файлове

Merge pull request #236 from nextcloud/master-sync-upstream

[Master] sync upstream
tags/v10.0RC1
Morris Jobke преди 7 години
родител
ревизия
b6397ef73a
променени са 42 файла, в които са добавени 387 реда и са изтрити 252 реда
  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 Целия файл

"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 Целия файл

"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 Целия файл

"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 Целия файл

"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 Целия файл



$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 Целия файл

* @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 Целия файл

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 Целия файл

$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 Целия файл

$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 Целия файл

$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 Целия файл

$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 Целия файл

"%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 Целия файл

"%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 Целия файл

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 Целия файл

$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 Целия файл

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 Целия файл

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 Целия файл

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 Целия файл

.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 Целия файл

$(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 Целия файл



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 Целия файл

"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 Целия файл

"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 Целия файл

<!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 Целия файл

<!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 Целия файл

<!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 Целия файл

* 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 Целия файл

} }
} }


/**
* 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 Целия файл

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 Целия файл

*/ */
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 Целия файл



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

+ 8
- 8
settings/css/settings.css Целия файл

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 Целия файл

* *
*/ */


(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 Целия файл

* *
*/ */


(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 Целия файл

/* 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 Целия файл

"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 Целия файл

"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 Целия файл

<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 Целия файл

$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 Целия файл

$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 Целия файл

$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 Целия файл

// 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…
Отказ
Запис