Downstream 2016-06-09

Merge branch 'master' of https://github.com/owncloud/core into downstream-160609
This commit is contained in:
Arthur Schiwon 2016-06-09 18:45:12 +02:00
commit a636e4ff28
No known key found for this signature in database
GPG Key ID: 7424F1874854DF23
102 changed files with 1216 additions and 276 deletions

View File

@ -56,9 +56,9 @@
RewriteRule ^\.well-known/carddav /remote.php/dav/ [R=301,L]
RewriteRule ^\.well-known/caldav /remote.php/dav/ [R=301,L]
RewriteRule ^remote/(.*) remote.php [QSA,L]
RewriteRule ^(build|tests|config|lib|3rdparty|templates)/.* - [R=404,L]
RewriteRule ^(?:build|tests|config|lib|3rdparty|templates)/.* - [R=404,L]
RewriteCond %{REQUEST_URI} !^/.well-known/acme-challenge/.*
RewriteRule ^(\.|autotest|occ|issue|indie|db_|console).* - [R=404,L]
RewriteRule ^(?:\.|autotest|occ|issue|indie|db_|console).* - [R=404,L]
</IfModule>
<IfModule mod_mime.c>
AddType image/svg+xml svg svgz

View File

@ -110,10 +110,10 @@ class Auth extends AbstractBasic {
$this->session->close();
return true;
} else {
\OC_Util::setUpFS(); //login hooks may need early access to the filesystem
\OC_Util::setupFS(); //login hooks may need early access to the filesystem
if($this->userSession->logClientIn($username, $password)) {
$this->userSession->createSessionToken($this->request, $this->userSession->getUser()->getUID(), $username, $password);
\OC_Util::setUpFS($this->userSession->getUser()->getUID());
\OC_Util::setupFS($this->userSession->getUser()->getUID());
$this->session->set(self::DAV_AUTHENTICATED, $this->userSession->getUser()->getUID());
$this->session->close();
return true;

View File

@ -196,6 +196,8 @@ class Directory extends \OCA\DAV\Connector\Sabre\Node
throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage());
} catch (\OCP\Files\InvalidPathException $ex) {
throw new InvalidPath($ex->getMessage());
} catch (ForbiddenException $e) {
throw new \Sabre\DAV\Exception\Forbidden();
}
}

View File

@ -168,20 +168,19 @@ class FilesPlugin extends ServerPlugin {
*/
function checkMove($source, $destination) {
$sourceNode = $this->tree->getNodeForPath($source);
if ($sourceNode instanceof FutureFile) {
if (!$sourceNode instanceof Node) {
return;
}
list($sourceDir,) = \Sabre\HTTP\URLUtil::splitPath($source);
list($destinationDir,) = \Sabre\HTTP\URLUtil::splitPath($destination);
if ($sourceDir !== $destinationDir) {
$sourceFileInfo = $this->fileView->getFileInfo($source);
if ($sourceFileInfo === false) {
$sourceNodeFileInfo = $sourceNode->getFileInfo();
if (is_null($sourceNodeFileInfo)) {
throw new NotFound($source . ' does not exist');
}
if (!$sourceFileInfo->isDeletable()) {
if (!$sourceNodeFileInfo->isDeletable()) {
throw new Forbidden($source . " cannot be deleted");
}
}

View File

@ -347,4 +347,8 @@ abstract class Node implements \Sabre\DAV\INode {
public function changeLock($type) {
$this->fileView->changeLock($this->path, $type);
}
public function getFileInfo() {
return $this->info;
}
}

View File

@ -161,6 +161,8 @@ class ObjectTree extends \Sabre\DAV\Tree {
throw new \Sabre\DAV\Exception\NotFound('Storage ' . $path . ' is invalid');
} catch (LockedException $e) {
throw new \Sabre\DAV\Exception\Locked();
} catch (ForbiddenException $e) {
throw new \Sabre\DAV\Exception\Forbidden();
}
}

View File

@ -24,6 +24,7 @@
*/
namespace OCA\DAV\Tests\unit\Connector\Sabre;
use OCA\DAV\Connector\Sabre\FilesPlugin;
use OCP\Files\StorageNotAvailableException;
use Sabre\DAV\PropFind;
use Sabre\DAV\PropPatch;
@ -36,16 +37,16 @@ use Test\TestCase;
* See the COPYING-README file.
*/
class FilesPluginTest extends TestCase {
const GETETAG_PROPERTYNAME = \OCA\DAV\Connector\Sabre\FilesPlugin::GETETAG_PROPERTYNAME;
const FILEID_PROPERTYNAME = \OCA\DAV\Connector\Sabre\FilesPlugin::FILEID_PROPERTYNAME;
const INTERNAL_FILEID_PROPERTYNAME = \OCA\DAV\Connector\Sabre\FilesPlugin::INTERNAL_FILEID_PROPERTYNAME;
const SIZE_PROPERTYNAME = \OCA\DAV\Connector\Sabre\FilesPlugin::SIZE_PROPERTYNAME;
const PERMISSIONS_PROPERTYNAME = \OCA\DAV\Connector\Sabre\FilesPlugin::PERMISSIONS_PROPERTYNAME;
const LASTMODIFIED_PROPERTYNAME = \OCA\DAV\Connector\Sabre\FilesPlugin::LASTMODIFIED_PROPERTYNAME;
const DOWNLOADURL_PROPERTYNAME = \OCA\DAV\Connector\Sabre\FilesPlugin::DOWNLOADURL_PROPERTYNAME;
const OWNER_ID_PROPERTYNAME = \OCA\DAV\Connector\Sabre\FilesPlugin::OWNER_ID_PROPERTYNAME;
const OWNER_DISPLAY_NAME_PROPERTYNAME = \OCA\DAV\Connector\Sabre\FilesPlugin::OWNER_DISPLAY_NAME_PROPERTYNAME;
const DATA_FINGERPRINT_PROPERTYNAME = \OCA\DAV\Connector\Sabre\FilesPlugin::DATA_FINGERPRINT_PROPERTYNAME;
const GETETAG_PROPERTYNAME = FilesPlugin::GETETAG_PROPERTYNAME;
const FILEID_PROPERTYNAME = FilesPlugin::FILEID_PROPERTYNAME;
const INTERNAL_FILEID_PROPERTYNAME = FilesPlugin::INTERNAL_FILEID_PROPERTYNAME;
const SIZE_PROPERTYNAME = FilesPlugin::SIZE_PROPERTYNAME;
const PERMISSIONS_PROPERTYNAME = FilesPlugin::PERMISSIONS_PROPERTYNAME;
const LASTMODIFIED_PROPERTYNAME = FilesPlugin::LASTMODIFIED_PROPERTYNAME;
const DOWNLOADURL_PROPERTYNAME = FilesPlugin::DOWNLOADURL_PROPERTYNAME;
const OWNER_ID_PROPERTYNAME = FilesPlugin::OWNER_ID_PROPERTYNAME;
const OWNER_DISPLAY_NAME_PROPERTYNAME = FilesPlugin::OWNER_DISPLAY_NAME_PROPERTYNAME;
const DATA_FINGERPRINT_PROPERTYNAME = FilesPlugin::DATA_FINGERPRINT_PROPERTYNAME;
/**
* @var \Sabre\DAV\Server | \PHPUnit_Framework_MockObject_MockObject
@ -58,7 +59,7 @@ class FilesPluginTest extends TestCase {
private $tree;
/**
* @var \OCA\DAV\Connector\Sabre\FilesPlugin
* @var FilesPlugin
*/
private $plugin;
@ -84,11 +85,11 @@ class FilesPluginTest extends TestCase {
->disableOriginalConstructor()
->getMock();
$this->config = $this->getMock('\OCP\IConfig');
$this->config->method('getSystemValue')
$this->config->expects($this->any())->method('getSystemValue')
->with($this->equalTo('data-fingerprint'), $this->equalTo(''))
->willReturn('my_fingerprint');
$this->plugin = new \OCA\DAV\Connector\Sabre\FilesPlugin(
$this->plugin = new FilesPlugin(
$this->tree,
$this->view,
$this->config
@ -263,7 +264,7 @@ class FilesPluginTest extends TestCase {
}
public function testGetPublicPermissions() {
$this->plugin = new \OCA\DAV\Connector\Sabre\FilesPlugin(
$this->plugin = new FilesPlugin(
$this->tree,
$this->view,
$this->config,
@ -331,7 +332,7 @@ class FilesPluginTest extends TestCase {
$node = $this->getMockBuilder('\OCA\DAV\Connector\Sabre\Directory')
->disableOriginalConstructor()
->getMock();
$node->method('getPath')->willReturn('/');
$node->expects($this->any())->method('getPath')->willReturn('/');
$propFind = new PropFind(
'/',
@ -432,11 +433,16 @@ class FilesPluginTest extends TestCase {
->method('isDeletable')
->willReturn(false);
$this->view->expects($this->once())
$node = $this->getMockBuilder('\OCA\DAV\Connector\Sabre\Node')
->disableOriginalConstructor()
->getMock();
$node->expects($this->once())
->method('getFileInfo')
->with('FolderA/test.txt')
->willReturn($fileInfoFolderATestTXT);
$this->tree->expects($this->once())->method('getNodeForPath')
->willReturn($node);
$this->plugin->checkMove('FolderA/test.txt', 'test.txt');
}
@ -448,11 +454,16 @@ class FilesPluginTest extends TestCase {
->method('isDeletable')
->willReturn(true);
$this->view->expects($this->once())
$node = $this->getMockBuilder('\OCA\DAV\Connector\Sabre\Node')
->disableOriginalConstructor()
->getMock();
$node->expects($this->once())
->method('getFileInfo')
->with('FolderA/test.txt')
->willReturn($fileInfoFolderATestTXT);
$this->tree->expects($this->once())->method('getNodeForPath')
->willReturn($node);
$this->plugin->checkMove('FolderA/test.txt', 'test.txt');
}
@ -461,10 +472,15 @@ class FilesPluginTest extends TestCase {
* @expectedExceptionMessage FolderA/test.txt does not exist
*/
public function testMoveSrcNotExist() {
$this->view->expects($this->once())
$node = $this->getMockBuilder('\OCA\DAV\Connector\Sabre\Node')
->disableOriginalConstructor()
->getMock();
$node->expects($this->once())
->method('getFileInfo')
->with('FolderA/test.txt')
->willReturn(false);
->willReturn(null);
$this->tree->expects($this->once())->method('getNodeForPath')
->willReturn($node);
$this->plugin->checkMove('FolderA/test.txt', 'test.txt');
}

View File

@ -0,0 +1,59 @@
<?php
/**
* @author Joas Schilling <nickvergessen@owncloud.com>
* @author Robin Appelman <icewind@owncloud.com>
* @author Thomas Müller <thomas.mueller@tmit.eu>
*
* @copyright Copyright (c) 2016, ownCloud, Inc.
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
namespace OCA\DAV\Tests\unit\Connector\Sabre\RequestTest;
use OC\Connector\Sabre\Exception\FileLocked;
use OCP\AppFramework\Http;
use OCP\Lock\ILockingProvider;
/**
* Class DeleteTest
*
* @group DB
*
* @package OCA\DAV\Tests\unit\Connector\Sabre\RequestTest
*/
class DeleteTest extends RequestTest {
public function testBasicUpload() {
$user = $this->getUniqueID();
$view = $this->setupUser($user, 'pass');
$view->file_put_contents('foo.txt', 'asd');
$mount = $view->getMount('foo.txt');
$internalPath = $view->getAbsolutePath();
// create a ghost file
$mount->getStorage()->unlink($mount->getInternalPath($internalPath));
// cache entry still exists
$this->assertInstanceOf('\OCP\Files\FileInfo', $view->getFileInfo('foo.txt'));
$response = $this->request($view, $user, 'pass', 'DELETE', '/foo.txt');
$this->assertEquals(Http::STATUS_NO_CONTENT, $response->getStatus());
// no longer in the cache
$this->assertFalse($view->getFileInfo('foo.txt'));
}
}

View File

@ -0,0 +1,6 @@
OC.L10N.register(
"federatedfilesharing",
{
"Invalid Federated Cloud ID" : "معرّف السحابة المتحدة غير صالح"
},
"nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;");

View File

@ -0,0 +1,4 @@
{ "translations": {
"Invalid Federated Cloud ID" : "معرّف السحابة المتحدة غير صالح"
},"pluralForm" :"nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;"
}

View File

@ -2,6 +2,7 @@ OC.L10N.register(
"federatedfilesharing",
{
"Sharing %s failed, because this item is already shared with %s" : "Współdzielenie %s nie powiodło się, ponieważ element jest już współdzielony z %s",
"File is already shared with %s" : "Plik jest już współdzielony z %s",
"Sharing %s failed, could not find %s, maybe the server is currently unreachable." : "Współdzielenie %s nie powiodło się, nie można odnaleźć %s. Prawdopobnie serwer nie jest teraz osiągalny.",
"Accept" : "Akceptuj",
"Open documentation" : "Otwórz dokumentację",

View File

@ -1,5 +1,6 @@
{ "translations": {
"Sharing %s failed, because this item is already shared with %s" : "Współdzielenie %s nie powiodło się, ponieważ element jest już współdzielony z %s",
"File is already shared with %s" : "Plik jest już współdzielony z %s",
"Sharing %s failed, could not find %s, maybe the server is currently unreachable." : "Współdzielenie %s nie powiodło się, nie można odnaleźć %s. Prawdopobnie serwer nie jest teraz osiągalny.",
"Accept" : "Akceptuj",
"Open documentation" : "Otwórz dokumentację",

View File

@ -17,10 +17,13 @@
cursor: pointer;
}
#listOfTrustedServers li:hover {
cursor: pointer;
}
#listOfTrustedServers .status {
margin-right: 10px;
}
#listOfTrustedServers .icon {
cursor: pointer;
display: inline-block;
vertical-align: middle;
margin-left: 10px;
}

View File

@ -42,8 +42,9 @@ $(document).ready(function () {
$('ul#listOfTrustedServers').prepend(
$('<li>')
.attr('id', data.id)
.attr('class', 'icon-delete')
.html('<span class="status indeterminate"></span>' + data.url)
.html('<span class="status indeterminate"></span>' +
data.url +
'<span class="icon icon-delete"></span>')
);
OC.msg.finishedSuccess('#ocFederationAddServer .msg', data.message);
})
@ -56,10 +57,10 @@ $(document).ready(function () {
}
});
// remove trusted server from list
$( "#listOfTrustedServers" ).on('click', 'li', function() {
var id = $(this).attr('id');
var $this = $(this);
// remove trusted server from list
$( "#listOfTrustedServers" ).on('click', 'li > .icon-delete', function() {
var $this = $(this).parent();
id = $this.attr('id');
$.ajax({
url: OC.generateUrl('/apps/federation/trusted-servers/' + id),
type: 'DELETE',

View File

@ -23,7 +23,7 @@ style('federation', 'settings-admin')
</p>
<ul id="listOfTrustedServers">
<?php foreach($_['trustedServers'] as $trustedServer) { ?>
<li id="<?php p($trustedServer['id']); ?>" class="icon-delete">
<li id="<?php p($trustedServer['id']); ?>">
<?php if((int)$trustedServer['status'] === TrustedServers::STATUS_OK) { ?>
<span class="status success"></span>
<?php
@ -36,6 +36,7 @@ style('federation', 'settings-admin')
<span class="status error"></span>
<?php } ?>
<?php p($trustedServer['url']); ?>
<span class="icon icon-delete"></span>
</li>
<?php } ?>
</ul>

View File

@ -53,6 +53,9 @@
this.$showHiddenFiles = $('input#showhiddenfilesToggle');
var showHidden = $('#showHiddenFiles').val() === "1";
this.$showHiddenFiles.prop('checked', showHidden);
if ($('#fileNotFound').val() === "1") {
OC.Notification.showTemporary(t('files', 'File could not be found'));
}
this._filesConfig = new OC.Backbone.Model({
showhidden: showHidden

View File

@ -32,6 +32,8 @@ OC.L10N.register(
"Could not get result from server." : "Kunne ikke hente resultat fra server.",
"Uploading..." : "Uploader...",
"..." : "...",
"Any moment now..." : "Når som helst...",
"Soon..." : "Snart...",
"File upload is in progress. Leaving the page now will cancel the upload." : "Fil upload kører. Hvis du forlader siden nu, vil uploadet blive annuleret.",
"Actions" : "Handlinger",
"Download" : "Download",
@ -47,6 +49,8 @@ OC.L10N.register(
"This directory is unavailable, please check the logs or contact the administrator" : "Denne mappe er utilgængelig, tjek venligst loggene eller kontakt administratoren",
"Could not move \"{file}\", target exists" : "Kunne ikke flytte \"{file}\" - der findes allerede en fil med dette navn",
"Could not move \"{file}\"" : "Kunne ikke flytte \"{file}\"",
"{newName} already exists" : "{newName} eksistere allerede",
"Error deleting file \"{fileName}\"." : "Fejl under sletning af filen \"{fileName}\"",
"No entries in this folder match '{filter}'" : "Der er ingen poster i denne mappe, der matcher '{filter}'",
"Name" : "Navn",
"Size" : "Størrelse",
@ -68,6 +72,7 @@ OC.L10N.register(
"_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
"Favorited" : "Gjort til foretrukken",
"Favorite" : "Foretrukken",
"Local link" : "Lokalt link",
"Folder" : "Mappe",
"New folder" : "Ny Mappe",
"{newname} already exists" : "{newname} eksistere allerede",
@ -97,6 +102,7 @@ OC.L10N.register(
"Save" : "Gem",
"Missing permissions to edit from here." : "Rettighed mangler til at redigere på dette sted",
"Settings" : "Indstillinger",
"Show hidden files" : "Vis skjulte filer",
"WebDAV" : "WebDAV",
"No files in here" : "Her er ingen filer",
"Upload some content or sync with your devices!" : "Overfør indhold eller synkronisér med dine enheder!",

View File

@ -30,6 +30,8 @@
"Could not get result from server." : "Kunne ikke hente resultat fra server.",
"Uploading..." : "Uploader...",
"..." : "...",
"Any moment now..." : "Når som helst...",
"Soon..." : "Snart...",
"File upload is in progress. Leaving the page now will cancel the upload." : "Fil upload kører. Hvis du forlader siden nu, vil uploadet blive annuleret.",
"Actions" : "Handlinger",
"Download" : "Download",
@ -45,6 +47,8 @@
"This directory is unavailable, please check the logs or contact the administrator" : "Denne mappe er utilgængelig, tjek venligst loggene eller kontakt administratoren",
"Could not move \"{file}\", target exists" : "Kunne ikke flytte \"{file}\" - der findes allerede en fil med dette navn",
"Could not move \"{file}\"" : "Kunne ikke flytte \"{file}\"",
"{newName} already exists" : "{newName} eksistere allerede",
"Error deleting file \"{fileName}\"." : "Fejl under sletning af filen \"{fileName}\"",
"No entries in this folder match '{filter}'" : "Der er ingen poster i denne mappe, der matcher '{filter}'",
"Name" : "Navn",
"Size" : "Størrelse",
@ -66,6 +70,7 @@
"_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
"Favorited" : "Gjort til foretrukken",
"Favorite" : "Foretrukken",
"Local link" : "Lokalt link",
"Folder" : "Mappe",
"New folder" : "Ny Mappe",
"{newname} already exists" : "{newname} eksistere allerede",
@ -95,6 +100,7 @@
"Save" : "Gem",
"Missing permissions to edit from here." : "Rettighed mangler til at redigere på dette sted",
"Settings" : "Indstillinger",
"Show hidden files" : "Vis skjulte filer",
"WebDAV" : "WebDAV",
"No files in here" : "Her er ingen filer",
"Upload some content or sync with your devices!" : "Overfør indhold eller synkronisér med dine enheder!",

View File

@ -45,6 +45,7 @@ OC.L10N.register(
"Unable to determine date" : "Nie można ustalić daty",
"This operation is forbidden" : "Ta operacja jest niedozwolona",
"This directory is unavailable, please check the logs or contact the administrator" : "Ten folder jest niedostępny, proszę sprawdzić logi lub skontaktować się z administratorem.",
"Could not move \"{file}\", target exists" : "Nie można było przenieść „{file}” plik o takiej nazwie już istnieje",
"Could not move \"{file}\"" : "Nie można było przenieść \"{file}\"",
"Could not create file \"{file}\"" : "Nie można było utworzyć pliku \"{file}\"",
"Could not create file \"{file}\" because it already exists" : "Nie można było utworzyć pliku \"{file}\", ponieważ ten plik już istnieje.",

View File

@ -43,6 +43,7 @@
"Unable to determine date" : "Nie można ustalić daty",
"This operation is forbidden" : "Ta operacja jest niedozwolona",
"This directory is unavailable, please check the logs or contact the administrator" : "Ten folder jest niedostępny, proszę sprawdzić logi lub skontaktować się z administratorem.",
"Could not move \"{file}\", target exists" : "Nie można było przenieść „{file}” plik o takiej nazwie już istnieje",
"Could not move \"{file}\"" : "Nie można było przenieść \"{file}\"",
"Could not create file \"{file}\"" : "Nie można było utworzyć pliku \"{file}\"",
"Could not create file \"{file}\" because it already exists" : "Nie można było utworzyć pliku \"{file}\", ponieważ ten plik już istnieje.",

View File

@ -27,9 +27,9 @@ namespace OCA\Files\Controller;
use OC\AppFramework\Http\Request;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\ContentSecurityPolicy;
use OCP\AppFramework\Http\Response;
use OCP\AppFramework\Http\RedirectResponse;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\Files\NotFoundException;
use OCP\IConfig;
use OCP\IL10N;
use OCP\INavigationManager;
@ -37,7 +37,6 @@ use OCP\IRequest;
use OCP\IURLGenerator;
use OCP\IUserSession;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use OCP\AppFramework\Http\NotFoundResponse;
use OCP\Files\Folder;
use OCP\App\IAppManager;
@ -142,11 +141,15 @@ class ViewController extends Controller {
* @param string $view
* @param string $fileid
* @return TemplateResponse
* @throws \OCP\Files\NotFoundException
*/
public function index($dir = '', $view = '', $fileid = null) {
$fileNotFound = false;
if ($fileid !== null) {
return $this->showFile($fileid);
try {
return $this->showFile($fileid);
} catch (NotFoundException $e) {
$fileNotFound = true;
}
}
$nav = new \OCP\Template('files', 'appnavigation', '');
@ -245,6 +248,7 @@ class ViewController extends Controller {
$params['defaultFileSortingDirection'] = $this->config->getUserValue($user, 'files', 'file_sorting_direction', 'asc');
$showHidden = (bool) $this->config->getUserValue($this->userSession->getUser()->getUID(), 'files', 'show_hidden', false);
$params['showHiddenFiles'] = $showHidden ? 1 : 0;
$params['fileNotFound'] = $fileNotFound ? 1 : 0;
$params['appNavigation'] = $nav;
$params['appContents'] = $contentItems;
$this->navigationManager->setActiveEntry('files_index');
@ -265,40 +269,37 @@ class ViewController extends Controller {
* Redirects to the file list and highlight the given file id
*
* @param string $fileId file id to show
* @return Response redirect response or not found response
* @return RedirectResponse redirect response or not found response
* @throws \OCP\Files\NotFoundException
*
* @NoCSRFRequired
* @NoAdminRequired
*/
public function showFile($fileId) {
try {
$uid = $this->userSession->getUser()->getUID();
$baseFolder = $this->rootFolder->get($uid . '/files/');
$uid = $this->userSession->getUser()->getUID();
$baseFolder = $this->rootFolder->get($uid . '/files/');
$files = $baseFolder->getById($fileId);
$params = [];
if (empty($files) && $this->appManager->isEnabledForUser('files_trashbin')) {
$baseFolder = $this->rootFolder->get($uid . '/files_trashbin/files/');
$files = $baseFolder->getById($fileId);
$params = [];
if (empty($files) && $this->appManager->isEnabledForUser('files_trashbin')) {
$baseFolder = $this->rootFolder->get($uid . '/files_trashbin/files/');
$files = $baseFolder->getById($fileId);
$params['view'] = 'trashbin';
}
if (!empty($files)) {
$file = current($files);
if ($file instanceof Folder) {
// set the full path to enter the folder
$params['dir'] = $baseFolder->getRelativePath($file->getPath());
} else {
// set parent path as dir
$params['dir'] = $baseFolder->getRelativePath($file->getParent()->getPath());
// and scroll to the entry
$params['scrollto'] = $file->getName();
}
return new RedirectResponse($this->urlGenerator->linkToRoute('files.view.index', $params));
}
} catch (\OCP\Files\NotFoundException $e) {
return new NotFoundResponse();
$params['view'] = 'trashbin';
}
return new NotFoundResponse();
if (!empty($files)) {
$file = current($files);
if ($file instanceof Folder) {
// set the full path to enter the folder
$params['dir'] = $baseFolder->getRelativePath($file->getPath());
} else {
// set parent path as dir
$params['dir'] = $baseFolder->getRelativePath($file->getParent()->getPath());
// and scroll to the entry
$params['scrollto'] = $file->getName();
}
return new RedirectResponse($this->urlGenerator->linkToRoute('files.view.index', $params));
}
throw new \OCP\Files\NotFoundException();
}
}

View File

@ -14,6 +14,7 @@
<input type="hidden" name="usedSpacePercent" id="usedSpacePercent" value="<?php p($_['usedSpacePercent']); ?>" />
<input type="hidden" name="owner" id="owner" value="<?php p($_['owner']); ?>" />
<input type="hidden" name="ownerDisplayName" id="ownerDisplayName" value="<?php p($_['ownerDisplayName']); ?>" />
<input type="hidden" name="fileNotFound" id="fileNotFound" value="<?php p($_['fileNotFound']); ?>"" />
<?php if (!$_['isPublic']) :?>
<input type="hidden" name="mailNotificationEnabled" id="mailNotificationEnabled" value="<?php p($_['mailNotificationEnabled']) ?>" />
<input type="hidden" name="mailPublicNotificationEnabled" id="mailPublicNotificationEnabled" value="<?php p($_['mailPublicNotificationEnabled']) ?>" />

View File

@ -26,6 +26,7 @@ namespace OCA\Files\Tests\Controller;
use OCA\Files\Controller\ViewController;
use OCP\AppFramework\Http;
use OCP\Files\NotFoundException;
use OCP\IUser;
use OCP\Template;
use Test\TestCase;
@ -259,7 +260,8 @@ class ViewControllerTest extends TestCase {
'isPublic' => false,
'defaultFileSorting' => 'name',
'defaultFileSortingDirection' => 'asc',
'showHiddenFiles' => false,
'showHiddenFiles' => 0,
'fileNotFound' => 0,
'mailNotificationEnabled' => 'no',
'mailPublicNotificationEnabled' => 'no',
'allowShareWithLink' => 'yes',
@ -410,11 +412,14 @@ class ViewControllerTest extends TestCase {
->with(123)
->will($this->returnValue([]));
$expected = new Http\NotFoundResponse();
if ($useShowFile) {
$this->assertEquals($expected, $this->viewController->showFile(123));
$this->setExpectedException('OCP\Files\NotFoundException');
$this->viewController->showFile(123);
} else {
$this->assertEquals($expected, $this->viewController->index('/whatever', '', '123'));
$response = $this->viewController->index('MyDir', 'MyView', '123');
$this->assertInstanceOf('OCP\AppFramework\Http\TemplateResponse', $response);
$params = $response->getParams();
$this->assertEquals(1, $params['fileNotFound']);
}
}

View File

@ -299,7 +299,8 @@ StorageConfig.prototype = {
mountPoint: this.mountPoint,
backend: this.backend,
authMechanism: this.authMechanism,
backendOptions: this.backendOptions
backendOptions: this.backendOptions,
testOnly: true
};
if (this.id) {
data.id = this.id;
@ -326,6 +327,7 @@ StorageConfig.prototype = {
$.ajax({
type: 'GET',
url: OC.generateUrl(this._url + '/{id}', {id: this.id}),
data: {'testOnly': true},
success: options.success,
error: options.error
});
@ -908,6 +910,7 @@ MountConfigListView.prototype = _.extend({
$.ajax({
type: 'GET',
url: OC.generateUrl('apps/files_external/userglobalstorages'),
data: {'testOnly' : true},
contentType: 'application/json',
success: function(result) {
var onCompletion = jQuery.Deferred();

View File

@ -78,6 +78,7 @@ OCA.External.StatusManager = {
defObj = $.ajax({
type: 'GET',
url: OC.webroot + '/index.php/apps/files_external/' + ((mountData.type === 'personal') ? 'userstorages' : 'userglobalstorages') + '/' + mountData.id,
data: {'testOnly' : false},
success: function (response) {
if (response && response.status === 0) {
self.mountStatus[mountData.mount_point] = response;

View File

@ -2,6 +2,7 @@ OC.L10N.register(
"files_external",
{
"Fetching access tokens failed. Verify that your app key and secret are correct." : "Otrzymano błędne żądanie tokenów. Sprawdź, czy klucz aplikacji oraz klucz poufny są poprawne.",
"Please provide a valid app key and secret." : "Proszę podać prawidłowy klucz aplikacji i klucz sekretny.",
"Step 1 failed. Exception: %s" : "Krok 1 błędny. Błąd: %s",
"Step 2 failed. Exception: %s" : "Krok 2 błędny. Błąd: %s",
"External storage" : "Zewnętrzne zasoby dyskowe",

View File

@ -1,5 +1,6 @@
{ "translations": {
"Fetching access tokens failed. Verify that your app key and secret are correct." : "Otrzymano błędne żądanie tokenów. Sprawdź, czy klucz aplikacji oraz klucz poufny są poprawne.",
"Please provide a valid app key and secret." : "Proszę podać prawidłowy klucz aplikacji i klucz sekretny.",
"Step 1 failed. Exception: %s" : "Krok 1 błędny. Błąd: %s",
"Step 2 failed. Exception: %s" : "Krok 2 błędny. Błąd: %s",
"External storage" : "Zewnętrzne zasoby dyskowe",

View File

@ -7,13 +7,13 @@ OC.L10N.register(
"Step 1 failed. Exception: %s" : "Passo 1 falhou. Exceção: %s",
"Step 2 failed. Exception: %s" : "Passo 2 falhou. Exceção: %s",
"External storage" : "Armazenamento Externo",
"Dropbox App Configuration" : "Configuração da app Dropbox",
"Google Drive App Configuration" : "Configuração da app Google Drive",
"Dropbox App Configuration" : "Configuração da aplicação Dropbox",
"Google Drive App Configuration" : "Configuração da aplicação Google Drive",
"Personal" : "Pessoal",
"System" : "Sistema",
"Grant access" : "Conceder acesso",
"Error configuring OAuth1" : "Erro de configuração OAuth1",
"Error configuring OAuth2" : "Erro de configuração OAuth2",
"Error configuring OAuth1" : "Erro ao configurar OAuth1",
"Error configuring OAuth2" : "Erro ao configurar OAuth2",
"Generate keys" : "Gerar chaves",
"Error generating key pair" : "Erro ao gerar chave par",
"All users. Type to select user or group." : "Todos os utilizadores. Digite para selecionar o utilizador ou grupo.",
@ -27,14 +27,14 @@ OC.L10N.register(
"Couldn't get the list of external mount points: {type}" : "Não foi possível conseguir a lista de pontos de montagem externos: {type}",
"There was an error with message: " : "Houve um erro com a mensagem:",
"External mount error" : "Erro de montagem externa",
"external-storage" : "Armazenamento Externo",
"external-storage" : "armazenamento externo",
"Couldn't get the list of Windows network drive mount points: empty response from the server" : "Não foi possível conseguir a lista de pontos de montagem Windows na rede: resposta vazia do servidor",
"Some of the configured external mount points are not connected. Please click on the red row(s) for more information" : "Alguns dos pontos de montagem externos configurados não estão conectados. Por favor, clique na fila vermelha para mais informação",
"Please enter the credentials for the {mount} mount" : "Por favor, introduza as credenciais para {mount}",
"Username" : "Nome de utilizador",
"Password" : "Palavra-passe",
"Credentials saved" : "Credenciais guardadas",
"Credentials saving failed" : "Falha ao salvar credenciais",
"Credentials saving failed" : "Falha ao guardar as credenciais",
"Credentials required" : "Credenciais necessárias",
"Save" : "Guardar",
"Storage with id \"%i\" not found" : "Não foi encontrado o armazenamento com a id. \"%i\"",
@ -49,7 +49,7 @@ OC.L10N.register(
"Insufficient data: %s" : "Dados insuficientes: %s",
"%s" : "%s",
"Storage with id \"%i\" is not user editable" : "Armazenamento com id \"%i\" não é editável pelo utilizador",
"Access key" : "Código de acesso",
"Access key" : "Chave de acesso",
"Secret key" : "Código secreto",
"Builtin" : "Integrado",
"None" : "Nenhum",

View File

@ -5,13 +5,13 @@
"Step 1 failed. Exception: %s" : "Passo 1 falhou. Exceção: %s",
"Step 2 failed. Exception: %s" : "Passo 2 falhou. Exceção: %s",
"External storage" : "Armazenamento Externo",
"Dropbox App Configuration" : "Configuração da app Dropbox",
"Google Drive App Configuration" : "Configuração da app Google Drive",
"Dropbox App Configuration" : "Configuração da aplicação Dropbox",
"Google Drive App Configuration" : "Configuração da aplicação Google Drive",
"Personal" : "Pessoal",
"System" : "Sistema",
"Grant access" : "Conceder acesso",
"Error configuring OAuth1" : "Erro de configuração OAuth1",
"Error configuring OAuth2" : "Erro de configuração OAuth2",
"Error configuring OAuth1" : "Erro ao configurar OAuth1",
"Error configuring OAuth2" : "Erro ao configurar OAuth2",
"Generate keys" : "Gerar chaves",
"Error generating key pair" : "Erro ao gerar chave par",
"All users. Type to select user or group." : "Todos os utilizadores. Digite para selecionar o utilizador ou grupo.",
@ -25,14 +25,14 @@
"Couldn't get the list of external mount points: {type}" : "Não foi possível conseguir a lista de pontos de montagem externos: {type}",
"There was an error with message: " : "Houve um erro com a mensagem:",
"External mount error" : "Erro de montagem externa",
"external-storage" : "Armazenamento Externo",
"external-storage" : "armazenamento externo",
"Couldn't get the list of Windows network drive mount points: empty response from the server" : "Não foi possível conseguir a lista de pontos de montagem Windows na rede: resposta vazia do servidor",
"Some of the configured external mount points are not connected. Please click on the red row(s) for more information" : "Alguns dos pontos de montagem externos configurados não estão conectados. Por favor, clique na fila vermelha para mais informação",
"Please enter the credentials for the {mount} mount" : "Por favor, introduza as credenciais para {mount}",
"Username" : "Nome de utilizador",
"Password" : "Palavra-passe",
"Credentials saved" : "Credenciais guardadas",
"Credentials saving failed" : "Falha ao salvar credenciais",
"Credentials saving failed" : "Falha ao guardar as credenciais",
"Credentials required" : "Credenciais necessárias",
"Save" : "Guardar",
"Storage with id \"%i\" not found" : "Não foi encontrado o armazenamento com a id. \"%i\"",
@ -47,7 +47,7 @@
"Insufficient data: %s" : "Dados insuficientes: %s",
"%s" : "%s",
"Storage with id \"%i\" is not user editable" : "Armazenamento com id \"%i\" não é editável pelo utilizador",
"Access key" : "Código de acesso",
"Access key" : "Chave de acesso",
"Secret key" : "Código secreto",
"Builtin" : "Integrado",
"None" : "Nenhum",

View File

@ -139,7 +139,8 @@ class GlobalStoragesController extends StoragesController {
$mountOptions,
$applicableUsers,
$applicableGroups,
$priority
$priority,
$testOnly = true
) {
$storage = $this->createStorage(
$mountPoint,
@ -172,7 +173,7 @@ class GlobalStoragesController extends StoragesController {
);
}
$this->updateStorageStatus($storage);
$this->updateStorageStatus($storage, $testOnly);
return new DataResponse(
$storage,

View File

@ -238,7 +238,7 @@ abstract class StoragesController extends Controller {
*
* @param StorageConfig $storage storage configuration
*/
protected function updateStorageStatus(StorageConfig &$storage) {
protected function updateStorageStatus(StorageConfig &$storage, $testOnly = true) {
try {
$this->manipulateStorageConfig($storage);
@ -249,7 +249,8 @@ abstract class StoragesController extends Controller {
\OC_Mount_Config::getBackendStatus(
$backend->getStorageClass(),
$storage->getBackendOptions(),
false
false,
$testOnly
)
);
} catch (InsufficientDataForMeaningfulAnswerException $e) {
@ -293,11 +294,11 @@ abstract class StoragesController extends Controller {
*
* @return DataResponse
*/
public function show($id) {
public function show($id, $testOnly = true) {
try {
$storage = $this->service->getStorage($id);
$this->updateStorageStatus($storage);
$this->updateStorageStatus($storage, $testOnly);
} catch (NotFoundException $e) {
return new DataResponse(
[

View File

@ -111,11 +111,11 @@ class UserGlobalStoragesController extends StoragesController {
*
* @NoAdminRequired
*/
public function show($id) {
public function show($id, $testOnly = true) {
try {
$storage = $this->service->getStorage($id);
$this->updateStorageStatus($storage);
$this->updateStorageStatus($storage, $testOnly);
} catch (NotFoundException $e) {
return new DataResponse(
[
@ -146,7 +146,8 @@ class UserGlobalStoragesController extends StoragesController {
*/
public function update(
$id,
$backendOptions
$backendOptions,
$testOnly = true
) {
try {
$storage = $this->service->getStorage($id);
@ -171,7 +172,7 @@ class UserGlobalStoragesController extends StoragesController {
);
}
$this->updateStorageStatus($storage);
$this->updateStorageStatus($storage, $testOnly);
$this->sanitizeStorage($storage);
return new DataResponse(

View File

@ -101,8 +101,8 @@ class UserStoragesController extends StoragesController {
*
* {@inheritdoc}
*/
public function show($id) {
return parent::show($id);
public function show($id, $testOnly = true) {
return parent::show($id, $testOnly);
}
/**
@ -170,7 +170,8 @@ class UserStoragesController extends StoragesController {
$backend,
$authMechanism,
$backendOptions,
$mountOptions
$mountOptions,
$testOnly = true
) {
$storage = $this->createStorage(
$mountPoint,
@ -200,7 +201,7 @@ class UserStoragesController extends StoragesController {
);
}
$this->updateStorageStatus($storage);
$this->updateStorageStatus($storage, $testOnly);
return new DataResponse(
$storage,

View File

@ -97,6 +97,9 @@ class Google extends \OC\Files\Storage\Common {
private function getDriveFile($path) {
// Remove leading and trailing slashes
$path = trim($path, '/');
if ($path === '.') {
$path = '';
}
if (isset($this->driveFiles[$path])) {
return $this->driveFiles[$path];
} else if ($path === '') {
@ -138,7 +141,7 @@ class Google extends \OC\Files\Storage\Common {
if ($pos !== false) {
$pathWithoutExt = substr($path, 0, $pos);
$file = $this->getDriveFile($pathWithoutExt);
if ($file) {
if ($file && $this->isGoogleDocFile($file)) {
// Switch cached Google_Service_Drive_DriveFile to the correct index
unset($this->driveFiles[$pathWithoutExt]);
$this->driveFiles[$path] = $file;
@ -208,6 +211,17 @@ class Google extends \OC\Files\Storage\Common {
}
}
/**
* Returns whether the given drive file is a Google Doc file
*
* @param \Google_Service_Drive_DriveFile
*
* @return true if the file is a Google Doc file, false otherwise
*/
private function isGoogleDocFile($file) {
return $this->getGoogleDocExtension($file->getMimeType()) !== '';
}
public function mkdir($path) {
if (!$this->is_dir($path)) {
$parentFolder = $this->getDriveFile(dirname($path));
@ -312,7 +326,7 @@ class Google extends \OC\Files\Storage\Common {
$stat['size'] = 0;
} else {
// Check if this is a Google Doc
if ($this->getMimeType($path) !== $file->getMimeType()) {
if ($this->isGoogleDocFile($file)) {
// Return unknown file size
$stat['size'] = \OCP\Files\FileInfo::SPACE_UNKNOWN;
} else {

View File

@ -215,7 +215,7 @@ class OC_Mount_Config {
* @return int see self::STATUS_*
* @throws Exception
*/
public static function getBackendStatus($class, $options, $isPersonal) {
public static function getBackendStatus($class, $options, $isPersonal, $testOnly = true) {
if (self::$skipTest) {
return StorageNotAvailableException::STATUS_SUCCESS;
}
@ -228,7 +228,7 @@ class OC_Mount_Config {
$storage = new $class($options);
try {
$result = $storage->test($isPersonal);
$result = $storage->test($isPersonal, $testOnly);
$storage->setAvailability($result);
if ($result) {
return StorageNotAvailableException::STATUS_SUCCESS;

View File

@ -60,4 +60,13 @@ class GoogleTest extends \Test\Files\Storage\Storage {
parent::tearDown();
}
public function testSameNameAsFolderWithExtension() {
$this->assertTrue($this->instance->mkdir('testsamename'));
$this->assertEquals(13, $this->instance->file_put_contents('testsamename.txt', 'some contents'));
$this->assertEquals('some contents', $this->instance->file_get_contents('testsamename.txt'));
$this->assertTrue($this->instance->is_dir('testsamename'));
$this->assertTrue($this->instance->unlink('testsamename.txt'));
$this->assertTrue($this->instance->rmdir('testsamename'));
}
}

View File

@ -223,7 +223,8 @@ describe('OCA.External.Settings tests', function() {
applicableGroups: [],
mountOptions: {
'previews': true
}
},
testOnly: true
});
// TODO: respond and check data-id

View File

@ -21,6 +21,7 @@ OC.L10N.register(
"Remote share password" : "Hasło do zdalnego zasobu",
"Cancel" : "Anuluj",
"Add remote share" : "Dodaj zdalny zasób",
"No ownCloud installation (7 or higher) found at {remote}" : "Nie znaleziono instalacji ownCloud (w wersji 7 lub nowszej) na {remote}",
"Invalid ownCloud url" : "Błędny adres URL",
"Shared by" : "Udostępniane przez",
"Sharing" : "Udostępnianie",

View File

@ -19,6 +19,7 @@
"Remote share password" : "Hasło do zdalnego zasobu",
"Cancel" : "Anuluj",
"Add remote share" : "Dodaj zdalny zasób",
"No ownCloud installation (7 or higher) found at {remote}" : "Nie znaleziono instalacji ownCloud (w wersji 7 lub nowszej) na {remote}",
"Invalid ownCloud url" : "Błędny adres URL",
"Shared by" : "Udostępniane przez",
"Sharing" : "Udostępnianie",

View File

@ -81,7 +81,7 @@ class Cache extends CacheJail {
}
protected function formatCacheEntry($entry) {
$path = $entry['path'];
$path = isset($entry['path']) ? $entry['path'] : '';
$entry = parent::formatCacheEntry($entry);
$sharePermissions = $this->storage->getPermissions($path);
if (isset($entry['permissions'])) {

View File

@ -415,4 +415,22 @@ class Shared extends \OC\Files\Storage\Wrapper\Jail implements ISharedStorage {
return $this->sourceStorage;
}
public function file_get_contents($path) {
$info = [
'target' => $this->getMountPoint() . '/' . $path,
'source' => $this->getSourcePath($path),
];
\OCP\Util::emitHook('\OC\Files\Storage\Shared', 'file_get_contents', $info);
return parent::file_get_contents($path);
}
public function file_put_contents($path, $data) {
$info = [
'target' => $this->getMountPoint() . '/' . $path,
'source' => $this->getSourcePath($path),
];
\OCP\Util::emitHook('\OC\Files\Storage\Shared', 'file_put_contents', $info);
return parent::file_put_contents($path, $data);
}
}

View File

@ -7,20 +7,20 @@ OC.L10N.register(
"Please select tags to filter by" : "Veuillez sélectionner les étiquettes par lesquelles filtrer",
"No files found for the selected tags" : "Aucun fichier pour les étiquettes sélectionnées",
"<strong>System tags</strong> for a file have been modified" : "<strong>Les étiquettes systèmes</strong> pour un fichier ont été modifiées",
"You assigned system tag %3$s" : "Vous avez attribué l'étiquette système %3$s",
"You assigned system tag %3$s" : "Vous avez attribué l'étiquette collaborative %3$s",
"%1$s assigned system tag %3$s" : "%1$s a attribué l'étiquette système %3$s",
"You unassigned system tag %3$s" : "Vous avez retiré l'étiquette système %3$s",
"You unassigned system tag %3$s" : "Vous avez retiré l'étiquette collaborative %3$s",
"%1$s unassigned system tag %3$s" : "%1$s a retiré l'étiquette système %3$s",
"You created system tag %2$s" : "Vous avez créé l'étiquette système %2$s",
"You created system tag %2$s" : "Vous avez créé l'étiquette collaborative %2$s",
"%1$s created system tag %2$s" : "%1$s a créé l'étiquette système %2$s",
"You deleted system tag %2$s" : "Vous avez supprimé l'étiquette système %2$s",
"%1$s deleted system tag %2$s" : "%1$s a supprimé l'étiquette système %2$s",
"You updated system tag %3$s to %2$s" : "Vous avez renommé l'étiquette système %3$s en %2$s",
"%1$s updated system tag %3$s to %2$s" : "%1$s a renommé l'étiquette système %3$s en %2$s",
"You assigned system tag %3$s to %2$s" : "Vous avez attribué l'étiquette système %3$s à %2$s",
"%1$s assigned system tag %3$s to %2$s" : "%1$s a attribué l'étiquette système %3$s à %2$s",
"You unassigned system tag %3$s from %2$s" : "Vous avez retiré l'étiquette système %3$s de %2$s",
"%1$s unassigned system tag %3$s from %2$s" : "%1$s a retiré l'étiquette système %3$s à %2$s",
"You deleted system tag %2$s" : "Vous avez supprimé l'étiquette collaborative %2$s",
"%1$s deleted system tag %2$s" : "%1$s a supprimé l'étiquette collaborative %2$s",
"You updated system tag %3$s to %2$s" : "Vous avez renommé l'étiquette collaborative %3$s en %2$s",
"%1$s updated system tag %3$s to %2$s" : "%1$s a renommé l'étiquette collaborative %3$s en %2$s",
"You assigned system tag %3$s to %2$s" : "Vous avez attribué l'étiquette collaborative %3$s à %2$s",
"%1$s assigned system tag %3$s to %2$s" : "%1$s a attribué l'étiquette collaborative %3$s à %2$s",
"You unassigned system tag %3$s from %2$s" : "Vous avez retiré l'étiquette collaborative %3$s à %2$s",
"%1$s unassigned system tag %3$s from %2$s" : "%1$s a retiré l'étiquette collaborative %3$s à %2$s",
"%s (restricted)" : "%s (restreint)",
"%s (invisible)" : "%s (invisible)",
"No files in here" : "Aucun fichier",

View File

@ -5,20 +5,20 @@
"Please select tags to filter by" : "Veuillez sélectionner les étiquettes par lesquelles filtrer",
"No files found for the selected tags" : "Aucun fichier pour les étiquettes sélectionnées",
"<strong>System tags</strong> for a file have been modified" : "<strong>Les étiquettes systèmes</strong> pour un fichier ont été modifiées",
"You assigned system tag %3$s" : "Vous avez attribué l'étiquette système %3$s",
"You assigned system tag %3$s" : "Vous avez attribué l'étiquette collaborative %3$s",
"%1$s assigned system tag %3$s" : "%1$s a attribué l'étiquette système %3$s",
"You unassigned system tag %3$s" : "Vous avez retiré l'étiquette système %3$s",
"You unassigned system tag %3$s" : "Vous avez retiré l'étiquette collaborative %3$s",
"%1$s unassigned system tag %3$s" : "%1$s a retiré l'étiquette système %3$s",
"You created system tag %2$s" : "Vous avez créé l'étiquette système %2$s",
"You created system tag %2$s" : "Vous avez créé l'étiquette collaborative %2$s",
"%1$s created system tag %2$s" : "%1$s a créé l'étiquette système %2$s",
"You deleted system tag %2$s" : "Vous avez supprimé l'étiquette système %2$s",
"%1$s deleted system tag %2$s" : "%1$s a supprimé l'étiquette système %2$s",
"You updated system tag %3$s to %2$s" : "Vous avez renommé l'étiquette système %3$s en %2$s",
"%1$s updated system tag %3$s to %2$s" : "%1$s a renommé l'étiquette système %3$s en %2$s",
"You assigned system tag %3$s to %2$s" : "Vous avez attribué l'étiquette système %3$s à %2$s",
"%1$s assigned system tag %3$s to %2$s" : "%1$s a attribué l'étiquette système %3$s à %2$s",
"You unassigned system tag %3$s from %2$s" : "Vous avez retiré l'étiquette système %3$s de %2$s",
"%1$s unassigned system tag %3$s from %2$s" : "%1$s a retiré l'étiquette système %3$s à %2$s",
"You deleted system tag %2$s" : "Vous avez supprimé l'étiquette collaborative %2$s",
"%1$s deleted system tag %2$s" : "%1$s a supprimé l'étiquette collaborative %2$s",
"You updated system tag %3$s to %2$s" : "Vous avez renommé l'étiquette collaborative %3$s en %2$s",
"%1$s updated system tag %3$s to %2$s" : "%1$s a renommé l'étiquette collaborative %3$s en %2$s",
"You assigned system tag %3$s to %2$s" : "Vous avez attribué l'étiquette collaborative %3$s à %2$s",
"%1$s assigned system tag %3$s to %2$s" : "%1$s a attribué l'étiquette collaborative %3$s à %2$s",
"You unassigned system tag %3$s from %2$s" : "Vous avez retiré l'étiquette collaborative %3$s à %2$s",
"%1$s unassigned system tag %3$s from %2$s" : "%1$s a retiré l'étiquette collaborative %3$s à %2$s",
"%s (restricted)" : "%s (restreint)",
"%s (invisible)" : "%s (invisible)",
"No files in here" : "Aucun fichier",

View File

@ -3,6 +3,8 @@ OC.L10N.register(
{
"Tags" : "Etykiety",
"Tagged files" : "Otagowane pliki",
"Select tags to filter by" : "Wybierz tagi do filtru",
"Please select tags to filter by" : "Proszę wybrać tagi do filtrów",
"No files found for the selected tags" : "Nie znaleziono plików dla wybranych etykiet",
"<strong>System tags</strong> for a file have been modified" : "<strong>System etykiet</strong> dla pliku został zmieniony",
"%1$s assigned system tag %3$s" : "%1$s przypisywalny system etykiet%3$s",

View File

@ -1,6 +1,8 @@
{ "translations": {
"Tags" : "Etykiety",
"Tagged files" : "Otagowane pliki",
"Select tags to filter by" : "Wybierz tagi do filtru",
"Please select tags to filter by" : "Proszę wybrać tagi do filtrów",
"No files found for the selected tags" : "Nie znaleziono plików dla wybranych etykiet",
"<strong>System tags</strong> for a file have been modified" : "<strong>System etykiet</strong> dla pliku został zmieniony",
"%1$s assigned system tag %3$s" : "%1$s przypisywalny system etykiet%3$s",

View File

@ -1,8 +1,11 @@
OC.L10N.register(
"updatenotification",
{
"Update notifications" : "Powiadomienia o aktualizacji",
"{version} is available. Get more information on how to update." : "Wersja {version} jest dostępna. Dowiedz się jak zaktualizować.",
"Updated channel" : "Zaktualizowano kanał",
"ownCloud core" : "Rdzeń ownCloud",
"Update for %1$s to version %2$s is available." : "Jest dostępna aktualizacja dla %1$s do wersji %2$s",
"Updater" : "Aktualizator",
"A new version is available: %s" : "Dostępna jest nowa wersja: %s",
"Open updater" : "Otwórz aktualizator",

View File

@ -1,6 +1,9 @@
{ "translations": {
"Update notifications" : "Powiadomienia o aktualizacji",
"{version} is available. Get more information on how to update." : "Wersja {version} jest dostępna. Dowiedz się jak zaktualizować.",
"Updated channel" : "Zaktualizowano kanał",
"ownCloud core" : "Rdzeń ownCloud",
"Update for %1$s to version %2$s is available." : "Jest dostępna aktualizacja dla %1$s do wersji %2$s",
"Updater" : "Aktualizator",
"A new version is available: %s" : "Dostępna jest nowa wersja: %s",
"Open updater" : "Otwórz aktualizator",

View File

@ -54,7 +54,7 @@ else
fi
if ! [ -x "$PHPUNIT" ]; then
echo "phpunit executable not found, please install phpunit version >= 3.7" >&2
echo "phpunit executable not found, please install phpunit version >= 4.4" >&2
exit 3
fi

View File

@ -260,6 +260,17 @@ trait BasicStructure {
}
}
/**
* @Given User :user modifies text of :filename with text :text
* @param string $user
* @param string $filename
* @param string $text
*/
public function modifyTextOfFile($user, $filename, $text) {
self::removeFile("../../data/$user/files", "$filename");
file_put_contents("../../data/$user/files" . "$filename", "$text");
}
/**
* @BeforeSuite
*/

View File

@ -12,7 +12,7 @@ require __DIR__ . '/../../vendor/autoload.php';
*/
class FederationContext implements Context, SnippetAcceptingContext {
use Sharing;
use WebDav;
/**
* @Given /^User "([^"]*)" from server "(LOCAL|REMOTE)" shares "([^"]*)" with user "([^"]*)" from server "(LOCAL|REMOTE)"$/

View File

@ -120,6 +120,67 @@ Feature: federated
| share_with | user2 |
| share_with_displayname | user2 |
Scenario: Overwrite a federated shared file as recipient
Given Using server "REMOTE"
And user "user1" exists
And user "user2" exists
And Using server "LOCAL"
And user "user0" exists
And User "user0" from server "LOCAL" shares "/textfile0.txt" with user "user1" from server "REMOTE"
And User "user1" from server "REMOTE" accepts last pending share
And Using server "REMOTE"
And As an "user1"
And User "user1" modifies text of "/textfile0.txt" with text "BLABLABLA"
When User "user1" uploads file "../../data/user1/files/textfile0.txt" to "/textfile0 (2).txt"
And Downloading file "/textfile0 (2).txt" with range "bytes=0-8"
Then Downloaded content should be "BLABLABLA"
Scenario: Overwrite a federated shared folder as recipient
Given Using server "REMOTE"
And user "user1" exists
And user "user2" exists
And Using server "LOCAL"
And user "user0" exists
And User "user0" from server "LOCAL" shares "/PARENT" with user "user1" from server "REMOTE"
And User "user1" from server "REMOTE" accepts last pending share
And Using server "REMOTE"
And As an "user1"
And User "user1" modifies text of "/textfile0.txt" with text "BLABLABLA"
When User "user1" uploads file "../../data/user1/files/textfile0.txt" to "/PARENT (2)/textfile0.txt"
And Downloading file "/PARENT (2)/textfile0.txt" with range "bytes=0-8"
Then Downloaded content should be "BLABLABLA"
Scenario: Overwrite a federated shared file as recipient using old chunking
Given Using server "REMOTE"
And user "user1" exists
And user "user2" exists
And Using server "LOCAL"
And user "user0" exists
And User "user0" from server "LOCAL" shares "/textfile0.txt" with user "user1" from server "REMOTE"
And User "user1" from server "REMOTE" accepts last pending share
And Using server "REMOTE"
And As an "user1"
And user "user1" uploads chunk file "1" of "3" with "AAAAA" to "/textfile0 (2).txt"
And user "user1" uploads chunk file "2" of "3" with "BBBBB" to "/textfile0 (2).txt"
And user "user1" uploads chunk file "3" of "3" with "CCCCC" to "/textfile0 (2).txt"
When Downloading file "/textfile0 (2).txt" with range "bytes=0-4"
Then Downloaded content should be "AAAAA"
Scenario: Overwrite a federated shared folder as recipient using old chunking
Given Using server "REMOTE"
And user "user1" exists
And user "user2" exists
And Using server "LOCAL"
And user "user0" exists
And User "user0" from server "LOCAL" shares "/PARENT" with user "user1" from server "REMOTE"
And User "user1" from server "REMOTE" accepts last pending share
And Using server "REMOTE"
And As an "user1"
And user "user1" uploads chunk file "1" of "3" with "AAAAA" to "/PARENT (2)/textfile0.txt"
And user "user1" uploads chunk file "2" of "3" with "BBBBB" to "/PARENT (2)/textfile0.txt"
And user "user1" uploads chunk file "3" of "3" with "CCCCC" to "/PARENT (2)/textfile0.txt"
When Downloading file "/PARENT (2)/textfile0.txt" with range "bytes=3-13"
Then Downloaded content should be "AABBBBBCCCC"

View File

@ -120,7 +120,8 @@ class Application extends App {
$c->query('AppName'),
$c->query('Request'),
$c->query('UserManager'),
$c->query('OC\Authentication\Token\DefaultTokenProvider'),
$c->query('ServerContainer')->query('OC\Authentication\Token\IProvider'),
$c->query('TwoFactorAuthManager'),
$c->query('SecureRandom')
);
});

View File

@ -111,7 +111,8 @@ class DecryptAll extends Command {
$this->addArgument(
'user',
InputArgument::OPTIONAL,
'user for which you want to decrypt all files (optional)'
'user for which you want to decrypt all files (optional)',
''
);
}
@ -127,8 +128,15 @@ class DecryptAll extends Command {
return;
}
$uid = $input->getArgument('user');
if ($uid === '') {
$message = 'your ownCloud';
} else {
$message = "$uid's account";
}
$output->writeln("\n");
$output->writeln('You are about to start to decrypt all files stored in your ownCloud.');
$output->writeln("You are about to start to decrypt all files stored in $message.");
$output->writeln('It will depend on the encryption module and your setup if this is possible.');
$output->writeln('Depending on the number and size of your files this can take some time');
$output->writeln('Please make sure that no user access his files during this process!');
@ -140,6 +148,7 @@ class DecryptAll extends Command {
$result = $this->decryptAll->decryptAll($input, $output, $user);
if ($result === false) {
$output->writeln(' aborted.');
$output->writeln('Server side encryption remains enabled');
$this->config->setAppValue('core', 'encryption_enabled', 'yes');
}
$this->resetSingleUserAndTrashbin();

View File

@ -1,4 +1,5 @@
<?php
/**
* @author Christoph Wurst <christoph@owncloud.com>
*
@ -23,22 +24,27 @@ namespace OC\Core\Controller;
use OC\AppFramework\Http;
use OC\Authentication\Token\DefaultTokenProvider;
use OC\Authentication\Token\IProvider;
use OC\Authentication\Token\IToken;
use OC\User\Manager;
use OC\Authentication\TwoFactorAuth\Manager as TwoFactorAuthManager;
use OC\User\Manager as UserManager;
use OCA\User_LDAP\User\Manager;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\JSONResponse;
use OCP\AppFramework\Http\Response;
use OCP\IRequest;
use OCP\Security\ISecureRandom;
class TokenController extends Controller {
/** @var Manager */
/** @var UserManager */
private $userManager;
/** @var DefaultTokenProvider */
/** @var IProvider */
private $tokenProvider;
/** @var TwoFactorAuthManager */
private $twoFactorAuthManager;
/** @var ISecureRandom */
private $secureRandom;
@ -49,12 +55,12 @@ class TokenController extends Controller {
* @param DefaultTokenProvider $tokenProvider
* @param ISecureRandom $secureRandom
*/
public function __construct($appName, IRequest $request, Manager $userManager, DefaultTokenProvider $tokenProvider,
ISecureRandom $secureRandom) {
public function __construct($appName, IRequest $request, UserManager $userManager, IProvider $tokenProvider, TwoFactorAuthManager $twoFactorAuthManager, ISecureRandom $secureRandom) {
parent::__construct($appName, $request);
$this->userManager = $userManager;
$this->tokenProvider = $tokenProvider;
$this->secureRandom = $secureRandom;
$this->twoFactorAuthManager = $twoFactorAuthManager;
}
/**
@ -70,18 +76,26 @@ class TokenController extends Controller {
*/
public function generateToken($user, $password, $name = 'unknown client') {
if (is_null($user) || is_null($password)) {
$response = new Response();
$response = new JSONResponse();
$response->setStatus(Http::STATUS_UNPROCESSABLE_ENTITY);
return $response;
}
$loginResult = $this->userManager->checkPassword($user, $password);
if ($loginResult === false) {
$response = new Response();
$loginName = $user;
$user = $this->userManager->checkPassword($loginName, $password);
if ($user === false) {
$response = new JSONResponse();
$response->setStatus(Http::STATUS_UNAUTHORIZED);
return $response;
}
if ($this->twoFactorAuthManager->isTwoFactorAuthenticated($user)) {
$resp = new JSONResponse();
$resp->setStatus(Http::STATUS_UNAUTHORIZED);
return $resp;
}
$token = $this->secureRandom->generate(128);
$this->tokenProvider->generateToken($token, $loginResult->getUID(), $user, $password, $name, IToken::PERMANENT_TOKEN);
$this->tokenProvider->generateToken($token, $user->getUID(), $loginName, $password, $name, IToken::PERMANENT_TOKEN);
return [
'token' => $token,
];

View File

@ -61,6 +61,13 @@ class TwoFactorChallengeController extends Controller {
$this->urlGenerator = $urlGenerator;
}
/**
* @return string
*/
protected function getLogoutAttribute() {
return \OC_User::getLogoutAttribute();
}
/**
* @NoAdminRequired
* @NoCSRFRequired
@ -75,6 +82,7 @@ class TwoFactorChallengeController extends Controller {
$data = [
'providers' => $providers,
'redirect_url' => $redirect_url,
'logout_attribute' => $this->getLogoutAttribute(),
];
return new TemplateResponse($this->appName, 'twofactorselectchallenge', $data, 'guest');
}
@ -106,6 +114,7 @@ class TwoFactorChallengeController extends Controller {
$data = [
'error' => $error,
'provider' => $provider,
'logout_attribute' => $this->getLogoutAttribute(),
'template' => $tmpl->fetchPage(),
];
return new TemplateResponse($this->appName, 'twofactorshowchallenge', $data, 'guest');

View File

@ -82,6 +82,11 @@ class TwoFactorMiddleware extends Middleware {
return;
}
if ($controller instanceof \OC\Core\Controller\LoginController && $methodName === 'logout') {
// Don't block the logout page, to allow canceling the 2FA
return;
}
if ($this->userSession->isLoggedIn()) {
$user = $this->userSession->getUser();

View File

@ -38,6 +38,10 @@ body {
display: inline-block;
}
a.two-factor-cancel {
color: #fff;
}
.float-spinner {
height: 32px;
display: none;

View File

@ -47,7 +47,7 @@
padding: 0 5px;
}
.tooltip-inner {
max-width: 200px;
max-width: 350px;
padding: 3px 8px;
color: #ffffff;
text-align: center;

View File

@ -197,7 +197,7 @@
}
var afterCall = function(xhr) {
var messages = [];
if (xhr.status !== 403 && xhr.status !== 307 && xhr.status !== 301 && xhr.responseText === '') {
if (xhr.status !== 403 && xhr.status !== 307 && xhr.status !== 301 && xhr.responseText !== '') {
messages.push({
msg: t('core', 'Your data directory and your files are probably accessible from the Internet. The .htaccess file is not working. We strongly suggest that you configure your web server in a way that the data directory is no longer accessible or you move the data directory outside the web server document root.'),
type: OC.SetupChecks.MESSAGE_TYPE_ERROR
@ -208,7 +208,7 @@
$.ajax({
type: 'GET',
url: OC.linkTo('', oc_dataURL+'/.ocdata'),
url: OC.linkTo('', oc_dataURL+'/htaccesstest.txt?t=' + (new Date()).getTime()),
complete: afterCall
});
return deferred.promise();

View File

@ -103,7 +103,7 @@ describe('OC.SetupChecks tests', function() {
it('should return an error if data directory is not protected', function(done) {
var async = OC.SetupChecks.checkDataProtected();
suite.server.requests[0].respond(200);
suite.server.requests[0].respond(200, {'Content-Type': 'text/plain'}, 'file contents');
async.done(function( data, s, x ){
expect(data).toEqual([

View File

@ -295,6 +295,7 @@ OC.L10N.register(
"This means only administrators can use the instance." : "これは、管理者のみがインスタンスを利用できることを意味しています。",
"Contact your system administrator if this message persists or appeared unexpectedly." : "このメッセージが引き続きもしくは予期せず現れる場合は、システム管理者に問い合わせてください。",
"Thank you for your patience." : "しばらくお待ちください。",
"Two-step verification" : "2段階認証",
"You are accessing the server from an untrusted domain." : "信頼されていないドメインからサーバーにアクセスしています。",
"Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domains\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "管理者に問い合わせてください。このサーバーの管理者の場合は、\"trusted_domain\" の設定を config/config.php に設定してください。config/config.sample.php にサンプルの設定方法が記載してあります。",
"Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "環境により、下のボタンで信頼するドメインに追加する必要があるかもしれません。",

View File

@ -293,6 +293,7 @@
"This means only administrators can use the instance." : "これは、管理者のみがインスタンスを利用できることを意味しています。",
"Contact your system administrator if this message persists or appeared unexpectedly." : "このメッセージが引き続きもしくは予期せず現れる場合は、システム管理者に問い合わせてください。",
"Thank you for your patience." : "しばらくお待ちください。",
"Two-step verification" : "2段階認証",
"You are accessing the server from an untrusted domain." : "信頼されていないドメインからサーバーにアクセスしています。",
"Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domains\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "管理者に問い合わせてください。このサーバーの管理者の場合は、\"trusted_domain\" の設定を config/config.php に設定してください。config/config.sample.php にサンプルの設定方法が記載してあります。",
"Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "環境により、下のボタンで信頼するドメインに追加する必要があるかもしれません。",

View File

@ -18,4 +18,5 @@
</li>
<?php endforeach; ?>
</ul>
</fieldset>
</fieldset>
<a class="two-factor-cancel" <?php print_unescaped($_['logout_attribute']); ?>><?php p($l->t('Cancel login')) ?></a>

View File

@ -17,3 +17,4 @@ $template = $_['template'];
<span class="warning"><?php p($l->t('An error occured while verifying the token')); ?></span>
<?php endif; ?>
<?php print_unescaped($template); ?>
<a class="two-factor-cancel" <?php print_unescaped($_['logout_attribute']); ?>><?php p($l->t('Cancel login')) ?></a>

View File

@ -1,18 +1,46 @@
OC.L10N.register(
"lib",
{
"Cannot write into \"config\" directory!" : "الكتابة في مجلد \"config\" غير ممكنة!",
"This can usually be fixed by giving the webserver write access to the config directory" : "يمكن حل هذا عادة بإعطاء خادم الوب صلاحية الكتابة في مجلد config",
"See %s" : "أنظر %s",
"Sample configuration detected" : "تم اكتشاف إعدادات عيّنة",
"PHP %s or higher is required." : "إصدار PHP %s أو أحدث منه مطلوب.",
"PHP with a version lower than %s is required." : "PHP الإصدار %s أو أقل مطلوب.",
"%sbit or higher PHP required." : "مكتبات PHP ذات %s بت أو أعلى مطلوبة.",
"Following databases are supported: %s" : "قواعد البيانات التالية مدعومة: %s",
"The command line tool %s could not be found" : "لم يتم العثور على أداة سطر الأوامر %s",
"The library %s is not available." : "مكتبة %s غير متوفرة.",
"Unknown filetype" : "نوع الملف غير معروف",
"Invalid image" : "الصورة غير صالحة",
"today" : "اليوم",
"yesterday" : "يوم أمس",
"_%n day ago_::_%n days ago_" : ["قبل ساعات","قبل يوم","قبل يومين","قبل %n يوماً","قبل %n يوماً","قبل %n يوماً"],
"last month" : "الشهر الماضي",
"_%n month ago_::_%n months ago_" : ["قبل عدة أيام","قبل شهر","قبل شهرين","قبل %n شهراً","قبل %n شهراً","قبل %n شهراً"],
"last year" : "السنةالماضية",
"seconds ago" : "منذ ثواني",
"Empty filename is not allowed" : "لا يسمح بأسماء فارغة للملفات",
"4-byte characters are not supported in file names" : "المحارف ذات 4 بايت غير مسموح بها في أسماء الملفات",
"File name is a reserved word" : "اسم الملف كلمة محجوزة",
"File name contains at least one invalid character" : "اسم الملف به ، على الأقل ، حرف غير صالح",
"File name is too long" : "اسم الملف طويل جداً",
"App directory already exists" : "مجلد التطبيق موجود مسبقا",
"Can't create app folder. Please fix permissions. %s" : "لا يمكن إنشاء مجلد التطبيق. يرجى تعديل الصلاحيات. %s",
"Archive does not contain a directory named %s" : "الأرشيف لا يحتوي مجلداً اسمه %s",
"No source specified when installing app" : "لم يتم تحديد المصدر عن تثبيت البرنامج",
"No href specified when installing app from http" : "لم يتم تحديد href عند تثبيت التطبيق من http",
"No path specified when installing app from local file" : "لم يتم تحديد مسار عند تثبيت التطبيق من ملف محلّي",
"Archives of type %s are not supported" : "الأرشيفات من نوع %s غير مدعومة",
"Failed to open archive when installing app" : "فشل فتح الأرشيف أثناء تثبيت التطبيق",
"App does not provide an info.xml file" : "التطبيق لا يتوفر على ملف info.xml",
"App cannot be installed because appinfo file cannot be read." : "لا يمكن تثبيت التطبيق لأن ملف appinfo غير ممكنة قراءته.",
"Signature could not get checked. Please contact the app developer and check your admin screen." : "لم يتم التحقق من التوقيع. فضلاً اتصل بمطوّر التطبيق و تحقق من شاشة الإدارة في حسابك.",
"App can't be installed because of not allowed code in the App" : "لم يتم تثبيت التطبيق لوجود شفرة غير مسموح بها في التطبيق",
"App can't be installed because it is not compatible with this version of ownCloud" : "لم يتم تثبيت التطبيق لأنه غير متوافق مع هذا الإصدار من ownCloud",
"App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" : "لم يتم تثبيت التطبيق لأن به علامة <shipped>true</shipped> التي لايسمح بها في التطبيقات غير المشحونة",
"App can't be installed because the version in info.xml is not the same as the version reported from the app store" : "لم يتم تثبيت التطبيق لأن الإصدار في info.xml مختلف عن الإصدار المذكور في متجر التطبيقات",
"%s enter the database username and name." : "%s أدخِل اسم قاعدة البيانات واسم مستخدمها.",
"%s enter the database username." : "%s ادخل اسم المستخدم الخاص بقاعدة البيانات.",
"%s enter the database name." : "%s ادخل اسم فاعدة البيانات",
"%s you may not use dots in the database name" : "%s لا يسمح لك باستخدام نقطه (.) في اسم قاعدة البيانات",
@ -23,9 +51,20 @@ OC.L10N.register(
"You need to enter either an existing account or the administrator." : "انت بحاجة لكتابة اسم مستخدم موجود أو حساب المدير.",
"Offending command was: \"%s\", name: %s, password: %s" : "الأمر المخالف كان : \"%s\", اسم المستخدم : %s, كلمة المرور: %s",
"PostgreSQL username and/or password not valid" : "اسم المستخدم / أو كلمة المرور الخاصة بـPostgreSQL غير صحيحة",
"Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "نظام ماك الإصدار X غير مدعوم و %s لن يعمل بشكل صحيح على هذه المنصة. استخدمه على مسؤوليتك!",
"For the best results, please consider using a GNU/Linux server instead." : "فضلاً ضع في الاعتبار استخدام نظام GNU/Linux بدل الأنظمة الأخرى للحصول على أفضل النتائج.",
"Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "فضلاً إحذف إعداد open_basedir من ملف php.ini لديك أو حوّل إلى PHP إصدار 64 بت.",
"Set an admin username." : "اعداد اسم مستخدم للمدير",
"Set an admin password." : "اعداد كلمة مرور للمدير",
"Can't create or write into the data directory %s" : "لا يمكن الإنشاء أو الكتابة في مجلد البيانات %s",
"Invalid Federated Cloud ID" : "معرّف سحابة الاتحاد غير صالح",
"%s shared »%s« with you" : "%s شارك »%s« معك",
"%s via %s" : "%s عبر %s",
"Sharing %s failed, because the file does not exist" : "فشلت مشاركة %s فالملف غير موجود",
"You are not allowed to share %s" : "أنت غير مسموح لك أن تشارك %s",
"Sharing %s failed, because you can not share with yourself" : "فشلت مشاركة %s لأنك لايمكنك المشاركة مع نفسك",
"Sharing %s failed, because the user %s does not exist" : "فشلت مشاركة %s لأن المستخدم %s غير موجود",
"Share type %s is not valid for %s" : "مشاركة النوع %s غير صالحة لـ %s",
"Could not find category \"%s\"" : "تعذر العثور على المجلد \"%s\"",
"Apps" : "التطبيقات",
"A valid username must be provided" : "يجب ادخال اسم مستخدم صحيح",

View File

@ -1,16 +1,44 @@
{ "translations": {
"Cannot write into \"config\" directory!" : "الكتابة في مجلد \"config\" غير ممكنة!",
"This can usually be fixed by giving the webserver write access to the config directory" : "يمكن حل هذا عادة بإعطاء خادم الوب صلاحية الكتابة في مجلد config",
"See %s" : "أنظر %s",
"Sample configuration detected" : "تم اكتشاف إعدادات عيّنة",
"PHP %s or higher is required." : "إصدار PHP %s أو أحدث منه مطلوب.",
"PHP with a version lower than %s is required." : "PHP الإصدار %s أو أقل مطلوب.",
"%sbit or higher PHP required." : "مكتبات PHP ذات %s بت أو أعلى مطلوبة.",
"Following databases are supported: %s" : "قواعد البيانات التالية مدعومة: %s",
"The command line tool %s could not be found" : "لم يتم العثور على أداة سطر الأوامر %s",
"The library %s is not available." : "مكتبة %s غير متوفرة.",
"Unknown filetype" : "نوع الملف غير معروف",
"Invalid image" : "الصورة غير صالحة",
"today" : "اليوم",
"yesterday" : "يوم أمس",
"_%n day ago_::_%n days ago_" : ["قبل ساعات","قبل يوم","قبل يومين","قبل %n يوماً","قبل %n يوماً","قبل %n يوماً"],
"last month" : "الشهر الماضي",
"_%n month ago_::_%n months ago_" : ["قبل عدة أيام","قبل شهر","قبل شهرين","قبل %n شهراً","قبل %n شهراً","قبل %n شهراً"],
"last year" : "السنةالماضية",
"seconds ago" : "منذ ثواني",
"Empty filename is not allowed" : "لا يسمح بأسماء فارغة للملفات",
"4-byte characters are not supported in file names" : "المحارف ذات 4 بايت غير مسموح بها في أسماء الملفات",
"File name is a reserved word" : "اسم الملف كلمة محجوزة",
"File name contains at least one invalid character" : "اسم الملف به ، على الأقل ، حرف غير صالح",
"File name is too long" : "اسم الملف طويل جداً",
"App directory already exists" : "مجلد التطبيق موجود مسبقا",
"Can't create app folder. Please fix permissions. %s" : "لا يمكن إنشاء مجلد التطبيق. يرجى تعديل الصلاحيات. %s",
"Archive does not contain a directory named %s" : "الأرشيف لا يحتوي مجلداً اسمه %s",
"No source specified when installing app" : "لم يتم تحديد المصدر عن تثبيت البرنامج",
"No href specified when installing app from http" : "لم يتم تحديد href عند تثبيت التطبيق من http",
"No path specified when installing app from local file" : "لم يتم تحديد مسار عند تثبيت التطبيق من ملف محلّي",
"Archives of type %s are not supported" : "الأرشيفات من نوع %s غير مدعومة",
"Failed to open archive when installing app" : "فشل فتح الأرشيف أثناء تثبيت التطبيق",
"App does not provide an info.xml file" : "التطبيق لا يتوفر على ملف info.xml",
"App cannot be installed because appinfo file cannot be read." : "لا يمكن تثبيت التطبيق لأن ملف appinfo غير ممكنة قراءته.",
"Signature could not get checked. Please contact the app developer and check your admin screen." : "لم يتم التحقق من التوقيع. فضلاً اتصل بمطوّر التطبيق و تحقق من شاشة الإدارة في حسابك.",
"App can't be installed because of not allowed code in the App" : "لم يتم تثبيت التطبيق لوجود شفرة غير مسموح بها في التطبيق",
"App can't be installed because it is not compatible with this version of ownCloud" : "لم يتم تثبيت التطبيق لأنه غير متوافق مع هذا الإصدار من ownCloud",
"App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" : "لم يتم تثبيت التطبيق لأن به علامة <shipped>true</shipped> التي لايسمح بها في التطبيقات غير المشحونة",
"App can't be installed because the version in info.xml is not the same as the version reported from the app store" : "لم يتم تثبيت التطبيق لأن الإصدار في info.xml مختلف عن الإصدار المذكور في متجر التطبيقات",
"%s enter the database username and name." : "%s أدخِل اسم قاعدة البيانات واسم مستخدمها.",
"%s enter the database username." : "%s ادخل اسم المستخدم الخاص بقاعدة البيانات.",
"%s enter the database name." : "%s ادخل اسم فاعدة البيانات",
"%s you may not use dots in the database name" : "%s لا يسمح لك باستخدام نقطه (.) في اسم قاعدة البيانات",
@ -21,9 +49,20 @@
"You need to enter either an existing account or the administrator." : "انت بحاجة لكتابة اسم مستخدم موجود أو حساب المدير.",
"Offending command was: \"%s\", name: %s, password: %s" : "الأمر المخالف كان : \"%s\", اسم المستخدم : %s, كلمة المرور: %s",
"PostgreSQL username and/or password not valid" : "اسم المستخدم / أو كلمة المرور الخاصة بـPostgreSQL غير صحيحة",
"Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "نظام ماك الإصدار X غير مدعوم و %s لن يعمل بشكل صحيح على هذه المنصة. استخدمه على مسؤوليتك!",
"For the best results, please consider using a GNU/Linux server instead." : "فضلاً ضع في الاعتبار استخدام نظام GNU/Linux بدل الأنظمة الأخرى للحصول على أفضل النتائج.",
"Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "فضلاً إحذف إعداد open_basedir من ملف php.ini لديك أو حوّل إلى PHP إصدار 64 بت.",
"Set an admin username." : "اعداد اسم مستخدم للمدير",
"Set an admin password." : "اعداد كلمة مرور للمدير",
"Can't create or write into the data directory %s" : "لا يمكن الإنشاء أو الكتابة في مجلد البيانات %s",
"Invalid Federated Cloud ID" : "معرّف سحابة الاتحاد غير صالح",
"%s shared »%s« with you" : "%s شارك »%s« معك",
"%s via %s" : "%s عبر %s",
"Sharing %s failed, because the file does not exist" : "فشلت مشاركة %s فالملف غير موجود",
"You are not allowed to share %s" : "أنت غير مسموح لك أن تشارك %s",
"Sharing %s failed, because you can not share with yourself" : "فشلت مشاركة %s لأنك لايمكنك المشاركة مع نفسك",
"Sharing %s failed, because the user %s does not exist" : "فشلت مشاركة %s لأن المستخدم %s غير موجود",
"Share type %s is not valid for %s" : "مشاركة النوع %s غير صالحة لـ %s",
"Could not find category \"%s\"" : "تعذر العثور على المجلد \"%s\"",
"Apps" : "التطبيقات",
"A valid username must be provided" : "يجب ادخال اسم مستخدم صحيح",

View File

@ -29,6 +29,7 @@ OC.L10N.register(
"Module with id: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Modulul cu id-ul %s nu există. Activează-l în setările tale de aplicație sau contactează-ți administratorul.",
"Empty filename is not allowed" : "Nu este permis fișier fără nume",
"Dot files are not allowed" : "Fișierele care încep cu caracterul punct nu sunt permise",
"4-byte characters are not supported in file names" : "Caracterele stocate în 4 octeți nu sunt suportate în denumirile fișierelor",
"File name is a reserved word" : "Numele fișierului este un cuvânt rezervat",
"File name contains at least one invalid character" : "Numele fișierului conține măcar un caracter invalid",
"File name is too long" : "Numele fișierului este prea lung",
@ -36,6 +37,8 @@ OC.L10N.register(
"Can't create app folder. Please fix permissions. %s" : "Nu se poate crea directorul de aplicație. Repară permisiunile. %s",
"Archive does not contain a directory named %s" : "Arhiva nu conține vreun director cu numele %s",
"No source specified when installing app" : "Nu a fost specificată vreo sursă la instalarea aplicației",
"No href specified when installing app from http" : "Nu s-a specificat adresa la instalarea aplicației dintr-o sursă de pe Internet",
"No path specified when installing app from local file" : "Nu s-a specificat vreo cale la instalarea aplicației de pe un fișier local",
"Archives of type %s are not supported" : "Arhivele de tip %s nu sunt suportate",
"Failed to open archive when installing app" : "Deschiderea arhivei a eșuat în timpul instalării aplicației",
"App does not provide an info.xml file" : "Aplicația nu furnizează un fișier info.xml",
@ -51,10 +54,12 @@ OC.L10N.register(
"DB Error: \"%s\"" : "Eroare Bază de Date: \"%s\"",
"Offending command was: \"%s\"" : "Comanda cauză a fost: \"%s\"",
"PostgreSQL username and/or password not valid" : "Nume utilizator și/sau parolă PostgreSQL greșită",
"For the best results, please consider using a GNU/Linux server instead." : "Pentru cele mai bune rezultate, ia în calcul folosirea unui server care rulează un sistem de operare GNU/Linux.",
"Set an admin username." : "Setează un nume de administrator.",
"Set an admin password." : "Setează o parolă de administrator.",
"Invalid Federated Cloud ID" : "ID invalid cloud federalizat",
"%s shared »%s« with you" : "%s Partajat »%s« cu tine de",
"%s via %s" : "%s via %s",
"You are not allowed to share %s" : "Nu există permisiunea de partajare %s",
"Sharing %s failed, because this item is already shared with %s" : "Partajarea %s a eșuat deoarece acest element este deja partajat cu %s",
"Not allowed to create a federated share with the same user" : "Nu este permisă crearea unei partajări federalizate cu acelaşi utilizator",

View File

@ -27,6 +27,7 @@
"Module with id: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Modulul cu id-ul %s nu există. Activează-l în setările tale de aplicație sau contactează-ți administratorul.",
"Empty filename is not allowed" : "Nu este permis fișier fără nume",
"Dot files are not allowed" : "Fișierele care încep cu caracterul punct nu sunt permise",
"4-byte characters are not supported in file names" : "Caracterele stocate în 4 octeți nu sunt suportate în denumirile fișierelor",
"File name is a reserved word" : "Numele fișierului este un cuvânt rezervat",
"File name contains at least one invalid character" : "Numele fișierului conține măcar un caracter invalid",
"File name is too long" : "Numele fișierului este prea lung",
@ -34,6 +35,8 @@
"Can't create app folder. Please fix permissions. %s" : "Nu se poate crea directorul de aplicație. Repară permisiunile. %s",
"Archive does not contain a directory named %s" : "Arhiva nu conține vreun director cu numele %s",
"No source specified when installing app" : "Nu a fost specificată vreo sursă la instalarea aplicației",
"No href specified when installing app from http" : "Nu s-a specificat adresa la instalarea aplicației dintr-o sursă de pe Internet",
"No path specified when installing app from local file" : "Nu s-a specificat vreo cale la instalarea aplicației de pe un fișier local",
"Archives of type %s are not supported" : "Arhivele de tip %s nu sunt suportate",
"Failed to open archive when installing app" : "Deschiderea arhivei a eșuat în timpul instalării aplicației",
"App does not provide an info.xml file" : "Aplicația nu furnizează un fișier info.xml",
@ -49,10 +52,12 @@
"DB Error: \"%s\"" : "Eroare Bază de Date: \"%s\"",
"Offending command was: \"%s\"" : "Comanda cauză a fost: \"%s\"",
"PostgreSQL username and/or password not valid" : "Nume utilizator și/sau parolă PostgreSQL greșită",
"For the best results, please consider using a GNU/Linux server instead." : "Pentru cele mai bune rezultate, ia în calcul folosirea unui server care rulează un sistem de operare GNU/Linux.",
"Set an admin username." : "Setează un nume de administrator.",
"Set an admin password." : "Setează o parolă de administrator.",
"Invalid Federated Cloud ID" : "ID invalid cloud federalizat",
"%s shared »%s« with you" : "%s Partajat »%s« cu tine de",
"%s via %s" : "%s via %s",
"You are not allowed to share %s" : "Nu există permisiunea de partajare %s",
"Sharing %s failed, because this item is already shared with %s" : "Partajarea %s a eșuat deoarece acest element este deja partajat cu %s",
"Not allowed to create a federated share with the same user" : "Nu este permisă crearea unei partajări federalizate cu acelaşi utilizator",

View File

@ -154,7 +154,7 @@ class AllConfig implements \OCP\IConfig {
*
* @param string $appName the appName that we want to store the value under
* @param string $key the key of the value, under which will be saved
* @param string $value the value that should be stored
* @param string|float|int $value the value that should be stored
*/
public function setAppValue($appName, $key, $value) {
\OC::$server->getAppConfig()->setValue($appName, $key, $value);
@ -198,11 +198,16 @@ class AllConfig implements \OCP\IConfig {
* @param string $userId the userId of the user that we want to store the value under
* @param string $appName the appName that we want to store the value under
* @param string $key the key under which the value is being stored
* @param string $value the value that you want to store
* @param string|float|int $value the value that you want to store
* @param string $preCondition only update if the config value was previously the value passed as $preCondition
* @throws \OCP\PreConditionNotMetException if a precondition is specified and is not met
* @throws \UnexpectedValueException when trying to store an unexpected value
*/
public function setUserValue($userId, $appName, $key, $value, $preCondition = null) {
if (!is_int($value) && !is_float($value) && !is_string($value)) {
throw new \UnexpectedValueException('Only integers, floats and strings are allowed as value');
}
// TODO - FIXME
$this->fixDIInit();

View File

@ -143,7 +143,7 @@ class AppConfig implements IAppConfig {
*
* @param string $app app
* @param string $key key
* @param string $value value
* @param string|float|int $value value
* @return bool True if the value was inserted or updated, false if the value was the same
*/
public function setValue($app, $key, $value) {

View File

@ -26,13 +26,13 @@ namespace OC\AppFramework\Middleware\Security;
use OC\AppFramework\Middleware\Security\Exceptions\SecurityException;
use OC\AppFramework\Utility\ControllerMethodReflector;
use OC\User\Session;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\JSONResponse;
use OCP\IRequest;
use OCP\IUserSession;
use OCP\AppFramework\Http\Response;
use OCP\AppFramework\Middleware;
use OCP\IRequest;
/**
* This middleware sets the correct CORS headers on a response if the
@ -53,18 +53,18 @@ class CORSMiddleware extends Middleware {
private $reflector;
/**
* @var IUserSession
* @var Session
*/
private $session;
/**
* @param IRequest $request
* @param ControllerMethodReflector $reflector
* @param IUserSession $session
* @param Session $session
*/
public function __construct(IRequest $request,
ControllerMethodReflector $reflector,
IUserSession $session) {
Session $session) {
$this->request = $request;
$this->reflector = $reflector;
$this->session = $session;
@ -89,7 +89,7 @@ class CORSMiddleware extends Middleware {
$pass = $this->request->server['PHP_AUTH_PW'];
$this->session->logout();
if(!$this->session->login($user, $pass)) {
if(!$this->session->logClientIn($user, $pass)) {
throw new SecurityException('CORS requires basic auth', Http::STATUS_UNAUTHORIZED);
}
}

View File

@ -28,6 +28,7 @@ class DefaultTokenCleanupJob extends Job {
protected function run($argument) {
/* @var $provider DefaultTokenProvider */
// TODO: add OC\Authentication\Token\IProvider::invalidateOldTokens and query interface
$provider = OC::$server->query('OC\Authentication\Token\DefaultTokenProvider');
$provider->invalidateOldTokens();
}

View File

@ -80,7 +80,7 @@ class DecryptAll {
$this->input = $input;
$this->output = $output;
if (!empty($user) && $this->userManager->userExists($user) === false) {
if ($user !== '' && $this->userManager->userExists($user) === false) {
$this->output->writeln('User "' . $user . '" does not exist. Please check the username and try again');
return false;
}
@ -141,7 +141,7 @@ class DecryptAll {
$this->output->writeln("\n");
$userList = [];
if (empty($user)) {
if ($user === '') {
$fetchUsersProgress = new ProgressBar($this->output);
$fetchUsersProgress->setFormat(" %message% \n [%bar%]");

View File

@ -38,6 +38,7 @@ use OC\Files\Filesystem;
use OC\Hooks\BasicEmitter;
use OCP\Config;
use OCP\Files\Cache\IScanner;
use OCP\Files\ForbiddenException;
use OCP\Files\Storage\ILockingStorage;
use OCP\Lock\ILockingProvider;
@ -140,7 +141,11 @@ class Scanner extends BasicEmitter implements IScanner {
}
}
$data = $this->getData($file);
try {
$data = $this->getData($file);
} catch (ForbiddenException $e) {
return null;
}
if ($data) {

View File

@ -231,7 +231,10 @@ class Updater implements IUpdater {
$parentId = $this->cache->getParentId($internalPath);
$parent = dirname($internalPath);
if ($parentId != -1) {
$this->cache->update($parentId, array('storage_mtime' => $this->storage->filemtime($parent)));
$mtime = $this->storage->filemtime($parent);
if ($mtime !== false) {
$this->cache->update($parentId, array('storage_mtime' => $mtime));
}
}
}
}

View File

@ -643,6 +643,9 @@ abstract class Common implements Storage, ILockingStorage {
$data = [];
$data['mimetype'] = $this->getMimeType($path);
$data['mtime'] = $this->filemtime($path);
if ($data['mtime'] === false) {
$data['mtime'] = time();
}
if ($data['mimetype'] == 'httpd/unix-directory') {
$data['size'] = -1; //unknown
} else {

View File

@ -33,20 +33,31 @@
*/
namespace OC\Files\Storage;
use OCP\Files\ForbiddenException;
/**
* for local filestore, we only have to map the paths
*/
class Local extends \OC\Files\Storage\Common {
protected $datadir;
protected $dataDirLength;
protected $allowSymlinks = false;
protected $realDataDir;
public function __construct($arguments) {
if (!isset($arguments['datadir']) || !is_string($arguments['datadir'])) {
throw new \InvalidArgumentException('No data directory set for local storage');
}
$this->datadir = $arguments['datadir'];
$this->realDataDir = rtrim(realpath($this->datadir), '/') . '/';
if (substr($this->datadir, -1) !== '/') {
$this->datadir .= '/';
}
$this->dataDirLength = strlen($this->realDataDir);
}
public function __destruct() {
@ -157,7 +168,7 @@ class Local extends \OC\Files\Storage\Common {
public function filemtime($path) {
clearstatcache($this->getSourcePath($path));
return filemtime($this->getSourcePath($path));
return $this->file_exists($path) ? filemtime($this->getSourcePath($path)) : false;
}
public function touch($path, $mtime = null) {
@ -188,7 +199,7 @@ class Local extends \OC\Files\Storage\Common {
return '';
}
$handle = fopen($fileName,'rb');
$handle = fopen($fileName, 'rb');
$content = fread($handle, $fileSize);
fclose($handle);
return $content;
@ -337,10 +348,27 @@ class Local extends \OC\Files\Storage\Common {
*
* @param string $path
* @return string
* @throws ForbiddenException
*/
public function getSourcePath($path) {
$fullPath = $this->datadir . $path;
return $fullPath;
if ($this->allowSymlinks || $path === '') {
return $fullPath;
}
$pathToResolve = $fullPath;
$realPath = realpath($pathToResolve);
while ($realPath === false) { // for non existing files check the parent directory
$pathToResolve = dirname($pathToResolve);
$realPath = realpath($pathToResolve);
}
if ($realPath) {
$realPath = $realPath . '/';
}
if (substr($realPath, 0, $this->dataDirLength) === $this->realDataDir) {
return $fullPath;
} else {
throw new ForbiddenException("Following symlinks is not allowed ('$fullPath' -> '$realPath' not inside '{$this->realDataDir}')", false);
}
}
/**
@ -377,7 +405,7 @@ class Local extends \OC\Files\Storage\Common {
* @return bool
*/
public function copyFromStorage(\OCP\Files\Storage $sourceStorage, $sourceInternalPath, $targetInternalPath) {
if($sourceStorage->instanceOfStorage('\OC\Files\Storage\Local')){
if ($sourceStorage->instanceOfStorage('\OC\Files\Storage\Local')) {
/**
* @var \OC\Files\Storage\Local $sourceStorage
*/

View File

@ -160,7 +160,12 @@ class Scanner extends PublicEmitter {
if ($storage->instanceOfStorage('\OC\Files\Storage\Home') and
(!$storage->isCreatable('') or !$storage->isCreatable('files'))
) {
throw new ForbiddenException();
if ($storage->file_exists('') or $storage->getCache()->inCache('')) {
throw new ForbiddenException();
} else {// if the root exists in neither the cache nor the storage the user isn't setup yet
break;
}
}
$relativePath = $mount->getInternalPath($dir);
$scanner = $storage->getScanner();

View File

@ -337,10 +337,17 @@ class View {
return $this->removeMount($mount, $absolutePath);
}
if ($this->is_dir($path)) {
return $this->basicOperation('rmdir', $path, array('delete'));
$result = $this->basicOperation('rmdir', $path, array('delete'));
} else {
return false;
$result = false;
}
if (!$result && !$this->file_exists($path)) { //clear ghost files from the cache on delete
$storage = $mount->getStorage();
$internalPath = $mount->getInternalPath($absolutePath);
$storage->getUpdater()->remove($internalPath);
}
return $result;
}
/**
@ -429,7 +436,7 @@ class View {
/**
* @param string $path
* @param int $from
* @param int $from
* @param int $to
* @return bool|mixed
* @throws \OCP\Files\InvalidPathException
@ -441,18 +448,18 @@ class View {
$handle = $this->fopen($path, 'rb');
if ($handle) {
if (fseek($handle, $from) === 0) {
$chunkSize = 8192; // 8 kB chunks
$end = $to + 1;
while (!feof($handle) && ftell($handle) < $end) {
$len = $end-ftell($handle);
if ($len > $chunkSize) {
$len = $chunkSize;
$chunkSize = 8192; // 8 kB chunks
$end = $to + 1;
while (!feof($handle) && ftell($handle) < $end) {
$len = $end - ftell($handle);
if ($len > $chunkSize) {
$len = $chunkSize;
}
echo fread($handle, $len);
flush();
}
echo fread($handle, $len);
flush();
}
$size = ftell($handle) - $from;
return $size;
$size = ftell($handle) - $from;
return $size;
}
throw new \OCP\Files\UnseekableException('fseek error');
@ -679,7 +686,15 @@ class View {
if ($mount and $mount->getInternalPath($absolutePath) === '') {
return $this->removeMount($mount, $absolutePath);
}
return $this->basicOperation('unlink', $path, array('delete'));
$result = $this->basicOperation('unlink', $path, array('delete'));
if (!$result && !$this->file_exists($path)) { //clear ghost files from the cache on delete
$storage = $mount->getStorage();
$internalPath = $mount->getInternalPath($absolutePath);
$storage->getUpdater()->remove($internalPath);
return true;
} else {
return $result;
}
}
/**

View File

@ -60,6 +60,32 @@ class Log implements ILogger {
/** @var Normalizer */
private $normalizer;
protected $methodsWithSensitiveParameters = [
// Session/User
'login',
'checkPassword',
'updatePrivateKeyPassword',
'validateUserPass',
// TokenProvider
'getToken',
'isTokenPassword',
'getPassword',
'decryptPassword',
'logClientIn',
'generateToken',
'validateToken',
// TwoFactorAuth
'solveChallenge',
'verifyChallenge',
//ICrypto
'calculateHMAC',
'encrypt',
'decrypt',
];
/**
* @param string $logger The logger that should be used
* @param SystemConfig $config the system config object
@ -286,7 +312,7 @@ class Log implements ILogger {
'File' => $exception->getFile(),
'Line' => $exception->getLine(),
);
$exception['Trace'] = preg_replace('!(login|checkPassword|updatePrivateKeyPassword|validateUserPass)\(.*\)!', '$1(*** username and password replaced ***)', $exception['Trace']);
$exception['Trace'] = preg_replace('!(' . implode('|', $this->methodsWithSensitiveParameters) . ')\(.*\)!', '$1(*** sensitive parameters replaced ***)', $exception['Trace']);
$msg = isset($context['message']) ? $context['message'] : 'Exception';
$msg .= ': ' . json_encode($exception);
$this->error($msg, $context);

View File

@ -361,7 +361,14 @@ class Session implements IUserSession, Emitter {
// TODO: throw LoginException instead (https://github.com/owncloud/core/pull/24616)
return false;
}
return $this->login($user, $password);
if (!$this->login($user, $password) ) {
$users = $this->manager->getByEmail($user);
if (count($users) === 1) {
return $this->login($users[0]->getUID(), $password);
}
return false;
}
return true;
}
private function isTokenAuthEnforced() {
@ -376,7 +383,11 @@ class Session implements IUserSession, Emitter {
);
$user = $this->manager->get($username);
if (is_null($user)) {
return true;
$users = $this->manager->getByEmail($username);
if (count($users) !== 1) {
return true;
}
$user = $users[0];
}
// DI not possible due to cyclic dependencies :'-/
return OC::$server->getTwoFactorAuthManager()->isTwoFactorAuthenticated($user);
@ -385,7 +396,7 @@ class Session implements IUserSession, Emitter {
/**
* Check if the given 'password' is actually a device token
*
* @param type $password
* @param string $password
* @return boolean
*/
public function isTokenPassword($password) {
@ -470,11 +481,39 @@ class Session implements IUserSession, Emitter {
$name = isset($request->server['HTTP_USER_AGENT']) ? $request->server['HTTP_USER_AGENT'] : 'unknown browser';
try {
$sessionId = $this->session->getId();
$this->tokenProvider->generateToken($sessionId, $uid, $loginName, $password, $name);
$pwd = $this->getPassword($password);
$this->tokenProvider->generateToken($sessionId, $uid, $loginName, $pwd, $name);
return true;
} catch (SessionNotAvailableException $ex) {
// This can happen with OCC, where a memory session is used
// if a memory session is used, we shouldn't create a session token anyway
return false;
}
}
/**
* Checks if the given password is a token.
* If yes, the password is extracted from the token.
* If no, the same password is returned.
*
* @param string $password either the login password or a device token
* @return string|null the password or null if none was set in the token
*/
private function getPassword($password) {
if (is_null($password)) {
// This is surely no token ;-)
return null;
}
try {
$token = $this->tokenProvider->getToken($password);
try {
return $this->tokenProvider->getPassword($token, $password);
} catch (PasswordlessTokenException $ex) {
return null;
}
} catch (InvalidTokenException $ex) {
return $password;
}
return true;
}
/**

View File

@ -349,7 +349,7 @@ class OC_API {
if ($ocsApiRequest) {
// initialize the user's filesystem
\OC_Util::setUpFS(\OC_User::getUser());
\OC_Util::setupFS(\OC_User::getUser());
self::$isLoggedIn = true;
return OC_User::getUser();
@ -374,7 +374,7 @@ class OC_API {
self::$logoutRequired = true;
// initialize the user's filesystem
\OC_Util::setUpFS(\OC_User::getUser());
\OC_Util::setupFS(\OC_User::getUser());
self::$isLoggedIn = true;
return \OC_User::getUser();

View File

@ -206,7 +206,9 @@ class OC_Helper {
foreach ($files as $fileInfo) {
/** @var SplFileInfo $fileInfo */
if ($fileInfo->isDir()) {
if ($fileInfo->isLink()) {
unlink($fileInfo->getPathname());
} else if ($fileInfo->isDir()) {
rmdir($fileInfo->getRealPath());
} else {
unlink($fileInfo->getRealPath());

View File

@ -1128,19 +1128,8 @@ class OC_Util {
return $encoded;
}
/**
* Check if the .htaccess file is working
* @param \OCP\IConfig $config
* @return bool
* @throws Exception
* @throws \OC\HintException If the test file can't get written.
*/
public function isHtaccessWorking(\OCP\IConfig $config) {
if (\OC::$CLI || !$config->getSystemValue('check_for_working_htaccess', true)) {
return true;
}
public function createHtaccessTestFile(\OCP\IConfig $config) {
// php dev server does not support htaccess
if (php_sapi_name() === 'cli-server') {
return false;
@ -1148,7 +1137,7 @@ class OC_Util {
// testdata
$fileName = '/htaccesstest.txt';
$testContent = 'testcontent';
$testContent = 'This is used for testing whether htaccess is properly enabled to disallow access from the outside. This file can be safely removed.';
// creating a test file
$testFile = $config->getSystemValue('datadirectory', OC::$SERVERROOT . '/data') . '/' . $fileName;
@ -1164,6 +1153,28 @@ class OC_Util {
}
fwrite($fp, $testContent);
fclose($fp);
}
/**
* Check if the .htaccess file is working
* @param \OCP\IConfig $config
* @return bool
* @throws Exception
* @throws \OC\HintException If the test file can't get written.
*/
public function isHtaccessWorking(\OCP\IConfig $config) {
if (\OC::$CLI || !$config->getSystemValue('check_for_working_htaccess', true)) {
return true;
}
$testContent = $this->createHtaccessTestFile($config);
if ($testContent === false) {
return false;
}
$fileName = '/htaccesstest.txt';
$testFile = $config->getSystemValue('datadirectory', OC::$SERVERROOT . '/data') . '/' . $fileName;
// accessing the file via http
$url = \OC::$server->getURLGenerator()->getAbsoluteURL(OC::$WEBROOT . '/data' . $fileName);

View File

@ -88,7 +88,7 @@ interface IAppConfig {
* sets a value in the appconfig
* @param string $app app
* @param string $key key
* @param string $value value
* @param string|float|int $value value
* @deprecated 8.0.0 use method setAppValue of \OCP\IConfig
*
* Sets a value. If the key did not exist before it will be created.

View File

@ -104,7 +104,7 @@ interface IConfig {
* Writes a new app wide value
*
* @param string $appName the appName that we want to store the value under
* @param string $key the key of the value, under which will be saved
* @param string|float|int $key the key of the value, under which will be saved
* @param string $value the value that should be stored
* @return void
* @since 6.0.0
@ -149,6 +149,7 @@ interface IConfig {
* @param string $value the value that you want to store
* @param string $preCondition only update if the config value was previously the value passed as $preCondition
* @throws \OCP\PreConditionNotMetException if a precondition is specified and is not met
* @throws \UnexpectedValueException when trying to store an unexpected value
* @since 6.0.0 - parameter $precondition was added in 8.0.0
*/
public function setUserValue($userId, $appName, $key, $value, $preCondition = null);

View File

@ -267,3 +267,7 @@ if ($updaterAppPanel) {
$template->assign('forms', $formsAndMore);
$template->printPage();
$util = new \OC_Util();
$util->createHtaccessTestFile(\OC::$server->getConfig());

View File

@ -14,7 +14,7 @@ var UserList = {
availableGroups: [],
offset: 0,
usersToLoad: 10, //So many users will be loaded when user scrolls down
initialUsersToLoad: 250, //initial number of users to load
initialUsersToLoad: 50, //initial number of users to load
currentGid: '',
filter: '',

View File

@ -6,6 +6,7 @@ OC.L10N.register(
"Authentication error" : "Błąd uwierzytelniania",
"Please provide an admin recovery password, otherwise all user data will be lost" : "Podaj hasło odzyskiwania administratora, w przeciwnym razie wszystkie dane użytkownika zostaną utracone",
"Wrong admin recovery password. Please check the password and try again." : "Błędne hasło odzyskiwania. Sprawdź hasło i spróbuj ponownie.",
"Backend doesn't support password change, but the user's encryption key was successfully updated." : "Zaplecze nie obsługuje zmiany hasła, ale klucz szyfrowania użytkownika został pomyślnie zaktualizowany.",
"Unable to change password" : "Nie można zmienić hasła",
"Enabled" : "Włączone",
"Not enabled" : "Nie włączone",

View File

@ -4,6 +4,7 @@
"Authentication error" : "Błąd uwierzytelniania",
"Please provide an admin recovery password, otherwise all user data will be lost" : "Podaj hasło odzyskiwania administratora, w przeciwnym razie wszystkie dane użytkownika zostaną utracone",
"Wrong admin recovery password. Please check the password and try again." : "Błędne hasło odzyskiwania. Sprawdź hasło i spróbuj ponownie.",
"Backend doesn't support password change, but the user's encryption key was successfully updated." : "Zaplecze nie obsługuje zmiany hasła, ale klucz szyfrowania użytkownika został pomyślnie zaktualizowany.",
"Unable to change password" : "Nie można zmienić hasła",
"Enabled" : "Włączone",
"Not enabled" : "Nie włączone",

View File

@ -48,8 +48,16 @@ OC.L10N.register(
"Unable to add user to group %s" : "Nu s-a putut adăuga utilizatorul în grupul %s",
"Unable to remove user from group %s" : "Nu s-a putut elimina utilizatorul din grupul %s",
"Couldn't update app." : "Aplicaţia nu s-a putut actualiza.",
"Add trusted domain" : "Adaugă domeniu de încredere",
"Migration in progress. Please wait until the migration is finished" : "Migrare în progres. Așteaptă până când migrarea este finalizată",
"Migration started …" : "Migrarea a început...",
"Sending..." : "Se expediază...",
"Official" : "Oficial",
"Approved" : "Aprobat",
"Experimental" : "Experimental",
"All" : "Toate ",
"No apps found for your version" : "Nu au fost găsite aplicații pentru versiunea ta",
"The app will be downloaded from the app store" : "Aplicația va fi descărcată din magazin",
"Please wait...." : "Aşteptaţi vă rog....",
"Error while disabling app" : "Eroare în timpul dezactivării aplicației",
"Disable" : "Dezactivați",
@ -60,7 +68,9 @@ OC.L10N.register(
"Updated" : "Actualizat",
"Uninstalling ...." : "Dezinstalaza ....",
"Uninstall" : "Dezinstalați",
"Valid until {date}" : "Valabil până la {date}",
"Delete" : "Șterge",
"An error occurred: {message}" : "A apărut o eroare: {message}",
"Select a profile picture" : "Selectează o imagine de profil",
"Very weak password" : "Parolă foarte slabă",
"Weak password" : "Parolă slabă",
@ -68,13 +78,21 @@ OC.L10N.register(
"Good password" : "Parolă bună",
"Strong password" : "Parolă puternică",
"Groups" : "Grupuri",
"Unable to delete {objName}" : "Nu s-a putut șterge {objName}",
"deleted {groupName}" : "{groupName} s-a șters",
"undo" : "Anulează ultima acțiune",
"no group" : "niciun grup",
"never" : "niciodată",
"deleted {userName}" : "{userName} șters",
"add group" : "adăugaţi grupul",
"A valid username must be provided" : "Trebuie să furnizaţi un nume de utilizator valid",
"A valid password must be provided" : "Trebuie să furnizaţi o parolă validă",
"__language_name__" : "_language_name_",
"Unlimited" : "Nelimitată",
"Personal info" : "Informații personale",
"Sessions" : "Sesiuni",
"Devices" : "Dispozitive",
"Sync clients" : "Sincronizează clienții",
"None" : "Niciuna",
"Login" : "Autentificare",
"SSL" : "SSL",
@ -83,31 +101,75 @@ OC.L10N.register(
"Open documentation" : "Deschide documentația",
"Allow apps to use the Share API" : "Permite aplicațiilor să folosească API-ul de partajare",
"Allow public uploads" : "Permite încărcări publice",
"Enforce password protection" : "Impune protecția prin parolă",
"Set default expiration date" : "Setează data implicită de expirare",
"Allow users to send mail notification for shared files" : "Permite utilizatorilor sa expedieze notificări prin e-mail pentru dosarele comune",
"Expire after " : "Expiră după",
"days" : "zile",
"Enforce expiration date" : "Impune data de expirare",
"Allow resharing" : "Permite repartajarea",
"Allow sharing with groups" : "Permite partajarea cu grupuri",
"Exclude groups from sharing" : "Exclude grupuri de la partajare",
"Execute one task with each page loaded" : "Execută o sarcină la fiecare pagină încărcată",
"Enable server-side encryption" : "Activează criptarea pe server",
"Please read carefully before activating server-side encryption: " : "Citește cu atenție înainte să activezi criptarea pe server:",
"This is the final warning: Do you really want to enable encryption?" : "Aceasta este avertizarea finală: Chiar vrei să activezi criptarea?",
"Enable encryption" : "Activează criptarea",
"Select default encryption module:" : "Selectează modulul implicit de criptare:",
"Start migration" : "Pornește migrarea",
"Send mode" : "Modul de expediere",
"Encryption" : "Încriptare",
"From address" : "De la adresa",
"mail" : "poștă",
"Authentication method" : "Modul de autentificare",
"Authentication required" : "Autentificare necesară",
"Server address" : "Adresa server-ului",
"Port" : "Portul",
"Credentials" : "Detalii de autentificare",
"SMTP Username" : "Nume utilizator SMTP",
"SMTP Password" : "Parolă SMTP",
"Store credentials" : "Stochează datele de autentificare",
"Test email settings" : "Verifică setările de e-mail",
"Send email" : "Expediază mesajul",
"Download logfile" : "Descarcă fișierul cu loguri",
"More" : "Mai mult",
"Less" : "Mai puțin",
"The logfile is bigger than 100 MB. Downloading it may take some time!" : "Fișierul cu loguri este mai mare de 100 MB. Descărcarea acestuia ar putea dura ceva timp!",
"What to log" : "Ce să loghezi",
"SQLite is used as database. For larger installations we recommend to switch to a different database backend." : "SQLite e folosit ca o bază de date. Pentru instalări mari recomandăm folosirea unei alte baze de date.",
"Especially when using the desktop client for file syncing the use of SQLite is discouraged." : "În special atunci când este folosit clientul desktop pentru sincronizarea fișierelor, utilizarea SQLite este nerecomandată.",
"How to do backups" : "Cum să faci copii de rezervă",
"Advanced monitoring" : "Monitorizare avansată",
"Version" : "Versiunea",
"Developer documentation" : "Documentație pentru dezvoltatori",
"by %s" : "de %s",
"%s-licensed" : "%s-licențiat",
"Documentation:" : "Documentație:",
"User documentation" : "Documentație utilizator",
"Admin documentation" : "Documentație pentru administrare",
"Show description …" : "Arată descriere ...",
"Hide description …" : "Ascunde descriere ...",
"This app has an update available." : "Este disponibilă o actualizare pentru această aplicație.",
"Enable only for specific groups" : "Activează doar pentru grupuri specifice",
"Uninstall App" : "Dezinstalează aplicația",
"Enable experimental apps" : "Activează aplicațiile experimentale",
"SSL Root Certificates" : "Certificate SSL rădăcină",
"Common Name" : "Nume comun",
"Valid until" : "Valabil până la",
"Issued By" : "Emis de",
"Valid until %s" : "Valabil până la %s",
"Import root certificate" : "Importă certificat rădăcină",
"Cheers!" : "Noroc!",
"Administrator documentation" : "Documentație pentru administrare",
"Online documentation" : "Documentație online",
"Forum" : "Forum",
"Commercial support" : "Suport comercial",
"Profile picture" : "Imagine de profil",
"Upload new" : "Încarcă una nouă",
"Remove image" : "Înlătură imagine",
"png or jpg, max. 20 MB" : "png sau jpg, max. 20 MB",
"Cancel" : "Anulare",
"Full name" : "Nume complet",
"Email" : "Email",
"Your email address" : "Adresa ta de email",
"Password" : "Parolă",
@ -115,6 +177,8 @@ OC.L10N.register(
"Current password" : "Parola curentă",
"New password" : "Noua parolă",
"Change password" : "Schimbă parola",
"Most recent activity" : "Cea mai recentă activitate",
"You've linked these devices." : "Ai legat aceste dispozitive.",
"Name" : "Nume",
"Language" : "Limba",
"Help translate" : "Ajută la traducere",
@ -128,12 +192,16 @@ OC.L10N.register(
"Admin Recovery Password" : "Parolă de recuperare a Administratorului",
"Enter the recovery password in order to recover the users files during password change" : "Introdu parola de recuperare pentru a recupera fișierele utilizatorilor în timpul schimbării parolei",
"Group" : "Grup",
"Admins" : "Administratori",
"Default Quota" : "Cotă implicită",
"Other" : "Altele",
"Full Name" : "Nume complet",
"Group Admin for" : "Administrator de grup pentru",
"Quota" : "Cotă",
"Last Login" : "Ultima autentificare",
"change full name" : "schimbă numele complet",
"set new password" : "setează parolă nouă",
"change email address" : "schimbă adresa email",
"Default" : "Implicită"
},
"nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));");

View File

@ -46,8 +46,16 @@
"Unable to add user to group %s" : "Nu s-a putut adăuga utilizatorul în grupul %s",
"Unable to remove user from group %s" : "Nu s-a putut elimina utilizatorul din grupul %s",
"Couldn't update app." : "Aplicaţia nu s-a putut actualiza.",
"Add trusted domain" : "Adaugă domeniu de încredere",
"Migration in progress. Please wait until the migration is finished" : "Migrare în progres. Așteaptă până când migrarea este finalizată",
"Migration started …" : "Migrarea a început...",
"Sending..." : "Se expediază...",
"Official" : "Oficial",
"Approved" : "Aprobat",
"Experimental" : "Experimental",
"All" : "Toate ",
"No apps found for your version" : "Nu au fost găsite aplicații pentru versiunea ta",
"The app will be downloaded from the app store" : "Aplicația va fi descărcată din magazin",
"Please wait...." : "Aşteptaţi vă rog....",
"Error while disabling app" : "Eroare în timpul dezactivării aplicației",
"Disable" : "Dezactivați",
@ -58,7 +66,9 @@
"Updated" : "Actualizat",
"Uninstalling ...." : "Dezinstalaza ....",
"Uninstall" : "Dezinstalați",
"Valid until {date}" : "Valabil până la {date}",
"Delete" : "Șterge",
"An error occurred: {message}" : "A apărut o eroare: {message}",
"Select a profile picture" : "Selectează o imagine de profil",
"Very weak password" : "Parolă foarte slabă",
"Weak password" : "Parolă slabă",
@ -66,13 +76,21 @@
"Good password" : "Parolă bună",
"Strong password" : "Parolă puternică",
"Groups" : "Grupuri",
"Unable to delete {objName}" : "Nu s-a putut șterge {objName}",
"deleted {groupName}" : "{groupName} s-a șters",
"undo" : "Anulează ultima acțiune",
"no group" : "niciun grup",
"never" : "niciodată",
"deleted {userName}" : "{userName} șters",
"add group" : "adăugaţi grupul",
"A valid username must be provided" : "Trebuie să furnizaţi un nume de utilizator valid",
"A valid password must be provided" : "Trebuie să furnizaţi o parolă validă",
"__language_name__" : "_language_name_",
"Unlimited" : "Nelimitată",
"Personal info" : "Informații personale",
"Sessions" : "Sesiuni",
"Devices" : "Dispozitive",
"Sync clients" : "Sincronizează clienții",
"None" : "Niciuna",
"Login" : "Autentificare",
"SSL" : "SSL",
@ -81,31 +99,75 @@
"Open documentation" : "Deschide documentația",
"Allow apps to use the Share API" : "Permite aplicațiilor să folosească API-ul de partajare",
"Allow public uploads" : "Permite încărcări publice",
"Enforce password protection" : "Impune protecția prin parolă",
"Set default expiration date" : "Setează data implicită de expirare",
"Allow users to send mail notification for shared files" : "Permite utilizatorilor sa expedieze notificări prin e-mail pentru dosarele comune",
"Expire after " : "Expiră după",
"days" : "zile",
"Enforce expiration date" : "Impune data de expirare",
"Allow resharing" : "Permite repartajarea",
"Allow sharing with groups" : "Permite partajarea cu grupuri",
"Exclude groups from sharing" : "Exclude grupuri de la partajare",
"Execute one task with each page loaded" : "Execută o sarcină la fiecare pagină încărcată",
"Enable server-side encryption" : "Activează criptarea pe server",
"Please read carefully before activating server-side encryption: " : "Citește cu atenție înainte să activezi criptarea pe server:",
"This is the final warning: Do you really want to enable encryption?" : "Aceasta este avertizarea finală: Chiar vrei să activezi criptarea?",
"Enable encryption" : "Activează criptarea",
"Select default encryption module:" : "Selectează modulul implicit de criptare:",
"Start migration" : "Pornește migrarea",
"Send mode" : "Modul de expediere",
"Encryption" : "Încriptare",
"From address" : "De la adresa",
"mail" : "poștă",
"Authentication method" : "Modul de autentificare",
"Authentication required" : "Autentificare necesară",
"Server address" : "Adresa server-ului",
"Port" : "Portul",
"Credentials" : "Detalii de autentificare",
"SMTP Username" : "Nume utilizator SMTP",
"SMTP Password" : "Parolă SMTP",
"Store credentials" : "Stochează datele de autentificare",
"Test email settings" : "Verifică setările de e-mail",
"Send email" : "Expediază mesajul",
"Download logfile" : "Descarcă fișierul cu loguri",
"More" : "Mai mult",
"Less" : "Mai puțin",
"The logfile is bigger than 100 MB. Downloading it may take some time!" : "Fișierul cu loguri este mai mare de 100 MB. Descărcarea acestuia ar putea dura ceva timp!",
"What to log" : "Ce să loghezi",
"SQLite is used as database. For larger installations we recommend to switch to a different database backend." : "SQLite e folosit ca o bază de date. Pentru instalări mari recomandăm folosirea unei alte baze de date.",
"Especially when using the desktop client for file syncing the use of SQLite is discouraged." : "În special atunci când este folosit clientul desktop pentru sincronizarea fișierelor, utilizarea SQLite este nerecomandată.",
"How to do backups" : "Cum să faci copii de rezervă",
"Advanced monitoring" : "Monitorizare avansată",
"Version" : "Versiunea",
"Developer documentation" : "Documentație pentru dezvoltatori",
"by %s" : "de %s",
"%s-licensed" : "%s-licențiat",
"Documentation:" : "Documentație:",
"User documentation" : "Documentație utilizator",
"Admin documentation" : "Documentație pentru administrare",
"Show description …" : "Arată descriere ...",
"Hide description …" : "Ascunde descriere ...",
"This app has an update available." : "Este disponibilă o actualizare pentru această aplicație.",
"Enable only for specific groups" : "Activează doar pentru grupuri specifice",
"Uninstall App" : "Dezinstalează aplicația",
"Enable experimental apps" : "Activează aplicațiile experimentale",
"SSL Root Certificates" : "Certificate SSL rădăcină",
"Common Name" : "Nume comun",
"Valid until" : "Valabil până la",
"Issued By" : "Emis de",
"Valid until %s" : "Valabil până la %s",
"Import root certificate" : "Importă certificat rădăcină",
"Cheers!" : "Noroc!",
"Administrator documentation" : "Documentație pentru administrare",
"Online documentation" : "Documentație online",
"Forum" : "Forum",
"Commercial support" : "Suport comercial",
"Profile picture" : "Imagine de profil",
"Upload new" : "Încarcă una nouă",
"Remove image" : "Înlătură imagine",
"png or jpg, max. 20 MB" : "png sau jpg, max. 20 MB",
"Cancel" : "Anulare",
"Full name" : "Nume complet",
"Email" : "Email",
"Your email address" : "Adresa ta de email",
"Password" : "Parolă",
@ -113,6 +175,8 @@
"Current password" : "Parola curentă",
"New password" : "Noua parolă",
"Change password" : "Schimbă parola",
"Most recent activity" : "Cea mai recentă activitate",
"You've linked these devices." : "Ai legat aceste dispozitive.",
"Name" : "Nume",
"Language" : "Limba",
"Help translate" : "Ajută la traducere",
@ -126,12 +190,16 @@
"Admin Recovery Password" : "Parolă de recuperare a Administratorului",
"Enter the recovery password in order to recover the users files during password change" : "Introdu parola de recuperare pentru a recupera fișierele utilizatorilor în timpul schimbării parolei",
"Group" : "Grup",
"Admins" : "Administratori",
"Default Quota" : "Cotă implicită",
"Other" : "Altele",
"Full Name" : "Nume complet",
"Group Admin for" : "Administrator de grup pentru",
"Quota" : "Cotă",
"Last Login" : "Ultima autentificare",
"change full name" : "schimbă numele complet",
"set new password" : "setează parolă nouă",
"change email address" : "schimbă adresa email",
"Default" : "Implicită"
},"pluralForm" :"nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));"
}

View File

@ -23,8 +23,9 @@
namespace Tests\Core\Controller;
use OC\AppFramework\Http;
use OC\Authentication\Token\IToken;
use OC\Core\Controller\TokenController;
use OCP\AppFramework\Http\Response;
use OCP\AppFramework\Http\JSONResponse;
use Test\TestCase;
class TokenControllerTest extends TestCase {
@ -34,6 +35,7 @@ class TokenControllerTest extends TestCase {
private $request;
private $userManager;
private $tokenProvider;
private $twoFactorAuthManager;
private $secureRandom;
protected function setUp() {
@ -43,17 +45,17 @@ class TokenControllerTest extends TestCase {
$this->userManager = $this->getMockBuilder('\OC\User\Manager')
->disableOriginalConstructor()
->getMock();
$this->tokenProvider = $this->getMockBuilder('\OC\Authentication\Token\DefaultTokenProvider')
$this->tokenProvider = $this->getMock('\OC\Authentication\Token\IProvider');
$this->twoFactorAuthManager = $this->getMockBuilder('\OC\Authentication\TwoFactorAuth\Manager')
->disableOriginalConstructor()
->getMock();
$this->secureRandom = $this->getMock('\OCP\Security\ISecureRandom');
$this->tokenController = new TokenController('core', $this->request, $this->userManager, $this->tokenProvider,
$this->secureRandom);
$this->tokenController = new TokenController('core', $this->request, $this->userManager, $this->tokenProvider, $this->twoFactorAuthManager, $this->secureRandom);
}
public function testWithoutCredentials() {
$expected = new Response();
$expected = new JSONResponse();
$expected->setStatus(Http::STATUS_UNPROCESSABLE_ENTITY);
$actual = $this->tokenController->generateToken(null, null);
@ -66,7 +68,7 @@ class TokenControllerTest extends TestCase {
->method('checkPassword')
->with('john', 'passme')
->will($this->returnValue(false));
$expected = new Response();
$expected = new JSONResponse();
$expected->setStatus(Http::STATUS_UNAUTHORIZED);
$actual = $this->tokenController->generateToken('john', 'passme');
@ -83,13 +85,17 @@ class TokenControllerTest extends TestCase {
$user->expects($this->once())
->method('getUID')
->will($this->returnValue('john'));
$this->twoFactorAuthManager->expects($this->once())
->method('isTwoFactorAuthenticated')
->with($user)
->will($this->returnValue(false));
$this->secureRandom->expects($this->once())
->method('generate')
->with(128)
->will($this->returnValue('verysecurerandomtoken'));
$this->tokenProvider->expects($this->once())
->method('generateToken')
->with('verysecurerandomtoken', 'john', 'john', '123456', 'unknown client', \OC\Authentication\Token\IToken::PERMANENT_TOKEN);
->with('verysecurerandomtoken', 'john', 'john', '123456', 'unknown client', IToken::PERMANENT_TOKEN);
$expected = [
'token' => 'verysecurerandomtoken'
];
@ -99,4 +105,24 @@ class TokenControllerTest extends TestCase {
$this->assertEquals($expected, $actual);
}
public function testWithValidCredentialsBut2faEnabled() {
$user = $this->getMock('\OCP\IUser');
$this->userManager->expects($this->once())
->method('checkPassword')
->with('john', '123456')
->will($this->returnValue($user));
$this->twoFactorAuthManager->expects($this->once())
->method('isTwoFactorAuthenticated')
->with($user)
->will($this->returnValue(true));
$this->secureRandom->expects($this->never())
->method('generate');
$expected = new JSONResponse();
$expected->setStatus(Http::STATUS_UNAUTHORIZED);
$actual = $this->tokenController->generateToken('john', '123456');
$this->assertEquals($expected, $actual);
}
}

View File

@ -33,7 +33,7 @@ class TwoFactorChallengeControllerTest extends TestCase {
private $session;
private $urlGenerator;
/** TwoFactorChallengeController */
/** @var TwoFactorChallengeController|\PHPUnit_Framework_MockObject_MockObject */
private $controller;
protected function setUp() {
@ -47,9 +47,20 @@ class TwoFactorChallengeControllerTest extends TestCase {
$this->session = $this->getMock('\OCP\ISession');
$this->urlGenerator = $this->getMock('\OCP\IURLGenerator');
$this->controller = new TwoFactorChallengeController(
'core', $this->request, $this->twoFactorManager, $this->userSession, $this->session, $this->urlGenerator
);
$this->controller = $this->getMockBuilder('OC\Core\Controller\TwoFactorChallengeController')
->setConstructorArgs([
'core',
$this->request,
$this->twoFactorManager,
$this->userSession,
$this->session,
$this->urlGenerator,
])
->setMethods(['getLogoutAttribute'])
->getMock();
$this->controller->expects($this->any())
->method('getLogoutAttribute')
->willReturn('logoutAttribute');
}
public function testSelectChallenge() {
@ -70,6 +81,7 @@ class TwoFactorChallengeControllerTest extends TestCase {
$expected = new \OCP\AppFramework\Http\TemplateResponse('core', 'twofactorselectchallenge', [
'providers' => $providers,
'redirect_url' => '/some/url',
'logout_attribute' => 'logoutAttribute',
], 'guest');
$this->assertEquals($expected, $this->controller->selectChallenge('/some/url'));
@ -110,6 +122,7 @@ class TwoFactorChallengeControllerTest extends TestCase {
$expected = new \OCP\AppFramework\Http\TemplateResponse('core', 'twofactorshowchallenge', [
'error' => true,
'provider' => $provider,
'logout_attribute' => 'logoutAttribute',
'template' => '<html/>',
], 'guest');

View File

@ -123,6 +123,25 @@ class AllConfigTest extends \Test\TestCase {
$config->deleteUserValue('userPreCond', 'appPreCond', 'keyPreCond');
}
public function dataSetUserValueUnexpectedValue() {
return [
[true],
[false],
[null],
[new \stdClass()],
];
}
/**
* @dataProvider dataSetUserValueUnexpectedValue
* @param mixed $value
* @expectedException \UnexpectedValueException
*/
public function testSetUserValueUnexpectedValue($value) {
$config = $this->getConfig();
$config->setUserValue('userSetBool', 'appSetBool', 'keySetBool', $value);
}
/**
* @expectedException \OCP\PreConditionNotMetException
*/

View File

@ -16,7 +16,6 @@ use OC\AppFramework\Http\Request;
use OC\AppFramework\Middleware\Security\CORSMiddleware;
use OC\AppFramework\Utility\ControllerMethodReflector;
use OC\AppFramework\Middleware\Security\Exceptions\SecurityException;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\JSONResponse;
use OCP\AppFramework\Http\Response;
@ -29,7 +28,9 @@ class CORSMiddlewareTest extends \Test\TestCase {
protected function setUp() {
parent::setUp();
$this->reflector = new ControllerMethodReflector();
$this->session = $this->getMock('\OCP\IUserSession');
$this->session = $this->getMockBuilder('\OC\User\Session')
->disableOriginalConstructor()
->getMock();
}
/**
@ -127,7 +128,7 @@ class CORSMiddlewareTest extends \Test\TestCase {
$this->session->expects($this->never())
->method('logout');
$this->session->expects($this->never())
->method('login')
->method('logClientIn')
->with($this->equalTo('user'), $this->equalTo('pass'))
->will($this->returnValue(true));
$this->reflector->reflect($this, __FUNCTION__);
@ -150,7 +151,7 @@ class CORSMiddlewareTest extends \Test\TestCase {
$this->session->expects($this->once())
->method('logout');
$this->session->expects($this->once())
->method('login')
->method('logClientIn')
->with($this->equalTo('user'), $this->equalTo('pass'))
->will($this->returnValue(true));
$this->reflector->reflect($this, __FUNCTION__);
@ -175,7 +176,7 @@ class CORSMiddlewareTest extends \Test\TestCase {
$this->session->expects($this->once())
->method('logout');
$this->session->expects($this->once())
->method('login')
->method('logClientIn')
->with($this->equalTo('user'), $this->equalTo('pass'))
->will($this->returnValue(false));
$this->reflector->reflect($this, __FUNCTION__);

View File

@ -86,13 +86,25 @@ class DecryptAllTest extends TestCase {
$this->invokePrivate($this->instance, 'output', [$this->outputInterface]);
}
/**
* @dataProvider dataTrueFalse
* @param bool $prepareResult
*/
public function testDecryptAll($prepareResult, $user) {
public function dataDecryptAll() {
return [
[true, 'user1', true],
[false, 'user1', true],
[true, '0', true],
[false, '0', true],
[true, '', false],
];
}
if (!empty($user)) {
/**
* @dataProvider dataDecryptAll
* @param bool $prepareResult
* @param string $user
* @param bool $userExistsChecked
*/
public function testDecryptAll($prepareResult, $user, $userExistsChecked) {
if ($userExistsChecked) {
$this->userManager->expects($this->once())->method('userExists')->willReturn(true);
} else {
$this->userManager->expects($this->never())->method('userExists');
@ -125,15 +137,6 @@ class DecryptAllTest extends TestCase {
$instance->decryptAll($this->inputInterface, $this->outputInterface, $user);
}
public function dataTrueFalse() {
return [
[true, 'user1'],
[false, 'user1'],
[true, ''],
[true, null]
];
}
/**
* test decrypt all call with a user who doesn't exists
*/
@ -147,8 +150,16 @@ class DecryptAllTest extends TestCase {
);
}
public function dataTrueFalse() {
return [
[true],
[false],
];
}
/**
* @dataProvider dataTrueFalse
* @param bool $success
*/
public function testPrepareEncryptionModules($success) {

View File

@ -84,5 +84,36 @@ class LocalTest extends Storage {
public function testInvalidArgumentsNoArray() {
new \OC\Files\Storage\Local(null);
}
/**
* @expectedException \OCP\Files\ForbiddenException
*/
public function testDisallowSymlinksOutsideDatadir() {
$subDir1 = $this->tmpDir . 'sub1';
$subDir2 = $this->tmpDir . 'sub2';
$sym = $this->tmpDir . 'sub1/sym';
mkdir($subDir1);
mkdir($subDir2);
symlink($subDir2, $sym);
$storage = new \OC\Files\Storage\Local(['datadir' => $subDir1]);
$storage->file_put_contents('sym/foo', 'bar');
}
public function testDisallowSymlinksInsideDatadir() {
$subDir1 = $this->tmpDir . 'sub1';
$subDir2 = $this->tmpDir . 'sub1/sub2';
$sym = $this->tmpDir . 'sub1/sym';
mkdir($subDir1);
mkdir($subDir2);
symlink($subDir2, $sym);
$storage = new \OC\Files\Storage\Local(['datadir' => $subDir1]);
$storage->file_put_contents('sym/foo', 'bar');
}
}

View File

@ -2417,7 +2417,7 @@ class ViewTest extends \Test\TestCase {
$content = $view->getDirectoryContent('', $filter);
$files = array_map(function(FileInfo $info) {
$files = array_map(function (FileInfo $info) {
return $info->getName();
}, $content);
sort($files);
@ -2444,4 +2444,53 @@ class ViewTest extends \Test\TestCase {
$data = $view->getFileInfo('.');
$this->assertEquals('', $data->getChecksum());
}
public function testDeleteGhostFile() {
$storage = new Temporary(array());
$scanner = $storage->getScanner();
$cache = $storage->getCache();
$storage->file_put_contents('foo.txt', 'bar');
\OC\Files\Filesystem::mount($storage, array(), '/test/');
$scanner->scan('');
$storage->unlink('foo.txt');
$this->assertTrue($cache->inCache('foo.txt'));
$view = new \OC\Files\View('/test');
$rootInfo = $view->getFileInfo('');
$this->assertEquals(3, $rootInfo->getSize());
$view->unlink('foo.txt');
$newInfo = $view->getFileInfo('');
$this->assertFalse($cache->inCache('foo.txt'));
$this->assertNotEquals($rootInfo->getEtag(), $newInfo->getEtag());
$this->assertEquals(0, $newInfo->getSize());
}
public function testDeleteGhostFolder() {
$storage = new Temporary(array());
$scanner = $storage->getScanner();
$cache = $storage->getCache();
$storage->mkdir('foo');
$storage->file_put_contents('foo/foo.txt', 'bar');
\OC\Files\Filesystem::mount($storage, array(), '/test/');
$scanner->scan('');
$storage->rmdir('foo');
$this->assertTrue($cache->inCache('foo'));
$this->assertTrue($cache->inCache('foo/foo.txt'));
$view = new \OC\Files\View('/test');
$rootInfo = $view->getFileInfo('');
$this->assertEquals(3, $rootInfo->getSize());
$view->rmdir('foo');
$newInfo = $view->getFileInfo('');
$this->assertFalse($cache->inCache('foo'));
$this->assertFalse($cache->inCache('foo/foo.txt'));
$this->assertNotEquals($rootInfo->getEtag(), $newInfo->getEtag());
$this->assertEquals(0, $newInfo->getSize());
}
}

View File

@ -89,7 +89,7 @@ class LoggerTest extends TestCase {
foreach($logLines as $logLine) {
$this->assertNotContains($user, $logLine);
$this->assertNotContains($password, $logLine);
$this->assertContains('login(*** username and password replaced ***)', $logLine);
$this->assertContains('login(*** sensitive parameters replaced ***)', $logLine);
}
}
@ -104,7 +104,7 @@ class LoggerTest extends TestCase {
foreach($logLines as $logLine) {
$this->assertNotContains($user, $logLine);
$this->assertNotContains($password, $logLine);
$this->assertContains('checkPassword(*** username and password replaced ***)', $logLine);
$this->assertContains('checkPassword(*** sensitive parameters replaced ***)', $logLine);
}
}
@ -119,7 +119,7 @@ class LoggerTest extends TestCase {
foreach($logLines as $logLine) {
$this->assertNotContains($user, $logLine);
$this->assertNotContains($password, $logLine);
$this->assertContains('validateUserPass(*** username and password replaced ***)', $logLine);
$this->assertContains('validateUserPass(*** sensitive parameters replaced ***)', $logLine);
}
}
}

Some files were not shown because too many files have changed in this diff Show More