Merge pull request #333 from nextcloud/sync-master

Sync master
This commit is contained in:
Lukas Reschke 2016-07-07 19:29:43 +02:00 committed by GitHub
commit 2a1a3957b6
158 changed files with 517 additions and 603 deletions

View File

@ -182,7 +182,8 @@ Jesús Macias <jmacias@solidgear.es> Jesus Macias <jmacias@full-on-net.com>
jknockaert <jasper@knockaert.nl> jknockaert <jasper@knockaert.nl>
Joan <aseques@gmail.com> Joan <aseques@gmail.com>
Joar Wandborg <git@wandborg.com> Joar Wandborg <git@wandborg.com>
Joas Schilling <nickvergessen@owncloud.com> Joas Schilling <nickvergessen@gmx.de> Joas Schilling <coding@schilljs.com> Joas Schilling <nickvergessen@gmx.de>
Joas Schilling <coding@schilljs.com> Joas Schilling <nickvergessen@owncloud.com>
joel hansson <joel.hansson@gmail.com> joel hansson <joel.hansson@gmail.com>
Johan Björk <johanimon@gmail.com> Johan Björk <johanimon@gmail.com>
Johannes Twittmann <github.com@deryo.de> Johannes Twittmann <github.com@deryo.de>

View File

@ -1079,22 +1079,27 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
'lastmodified' => time(), 'lastmodified' => time(),
]; ];
foreach($this->subscriptionPropertyMap as $xmlName=>$dbName) { $propertiesBoolean = ['striptodos', 'stripalarms', 'stripattachments'];
if (isset($properties[$xmlName])) {
$values[$dbName] = $properties[$xmlName]; foreach($this->subscriptionPropertyMap as $xmlName=>$dbName) {
$fieldNames[] = $dbName; if (array_key_exists($xmlName, $properties)) {
$values[$dbName] = $properties[$xmlName];
if (in_array($dbName, $propertiesBoolean)) {
$values[$dbName] = true;
}
} }
} }
$valuesToInsert = array();
$query = $this->db->getQueryBuilder(); $query = $this->db->getQueryBuilder();
foreach (array_keys($values) as $name) {
$valuesToInsert[$name] = $query->createNamedParameter($values[$name]);
}
$query->insert('calendarsubscriptions') $query->insert('calendarsubscriptions')
->values([ ->values($valuesToInsert)
'principaluri' => $query->createNamedParameter($values['principaluri']),
'uri' => $query->createNamedParameter($values['uri']),
'source' => $query->createNamedParameter($values['source']),
'lastmodified' => $query->createNamedParameter($values['lastmodified']),
])
->execute(); ->execute();
return $this->db->lastInsertId('*PREFIX*calendarsubscriptions'); return $this->db->lastInsertId('*PREFIX*calendarsubscriptions');

View File

@ -333,15 +333,20 @@ EOD;
public function testSubscriptions() { public function testSubscriptions() {
$id = $this->backend->createSubscription(self::UNIT_TEST_USER, 'Subscription', [ $id = $this->backend->createSubscription(self::UNIT_TEST_USER, 'Subscription', [
'{http://calendarserver.org/ns/}source' => new Href('test-source') '{http://calendarserver.org/ns/}source' => new Href('test-source'),
'{http://apple.com/ns/ical/}calendar-color' => '#1C4587',
'{http://calendarserver.org/ns/}subscribed-strip-todos' => ''
]); ]);
$subscriptions = $this->backend->getSubscriptionsForUser(self::UNIT_TEST_USER); $subscriptions = $this->backend->getSubscriptionsForUser(self::UNIT_TEST_USER);
$this->assertEquals(1, count($subscriptions)); $this->assertEquals(1, count($subscriptions));
$this->assertEquals('#1C4587', $subscriptions[0]['{http://apple.com/ns/ical/}calendar-color']);
$this->assertEquals(true, $subscriptions[0]['{http://calendarserver.org/ns/}subscribed-strip-todos']);
$this->assertEquals($id, $subscriptions[0]['id']); $this->assertEquals($id, $subscriptions[0]['id']);
$patch = new PropPatch([ $patch = new PropPatch([
'{DAV:}displayname' => 'Unit test', '{DAV:}displayname' => 'Unit test',
'{http://apple.com/ns/ical/}calendar-color' => '#ac0606',
]); ]);
$this->backend->updateSubscription($id, $patch); $this->backend->updateSubscription($id, $patch);
$patch->commit(); $patch->commit();
@ -350,6 +355,7 @@ EOD;
$this->assertEquals(1, count($subscriptions)); $this->assertEquals(1, count($subscriptions));
$this->assertEquals($id, $subscriptions[0]['id']); $this->assertEquals($id, $subscriptions[0]['id']);
$this->assertEquals('Unit test', $subscriptions[0]['{DAV:}displayname']); $this->assertEquals('Unit test', $subscriptions[0]['{DAV:}displayname']);
$this->assertEquals('#ac0606', $subscriptions[0]['{http://apple.com/ns/ical/}calendar-color']);
$this->backend->deleteSubscription($id); $this->backend->deleteSubscription($id);
$subscriptions = $this->backend->getSubscriptionsForUser(self::UNIT_TEST_USER); $subscriptions = $this->backend->getSubscriptionsForUser(self::UNIT_TEST_USER);

View File

@ -217,28 +217,32 @@ class FederatedShareProvider implements IShareProvider {
$share->getPermissions(), $share->getPermissions(),
$token $token
); );
$sharedByFederatedId = $share->getSharedBy();
if ($this->userManager->userExists($sharedByFederatedId)) {
$sharedByFederatedId = $sharedByFederatedId . '@' . $this->addressHandler->generateRemoteURL();
}
$send = $this->notifications->sendRemoteShare(
$token,
$share->getSharedWith(),
$share->getNode()->getName(),
$shareId,
$share->getShareOwner(),
$share->getShareOwner() . '@' . $this->addressHandler->generateRemoteURL(),
$share->getSharedBy(),
$sharedByFederatedId
);
if ($send === false) { try {
$data = $this->getRawShare($shareId); $sharedByFederatedId = $share->getSharedBy();
$share = $this->createShareObject($data); if ($this->userManager->userExists($sharedByFederatedId)) {
$this->removeShareFromTable($share); $sharedByFederatedId = $sharedByFederatedId . '@' . $this->addressHandler->generateRemoteURL();
$message_t = $this->l->t('Sharing %s failed, could not find %s, maybe the server is currently unreachable.', }
[$share->getNode()->getName(), $share->getSharedWith()]); $send = $this->notifications->sendRemoteShare(
throw new \Exception($message_t); $token,
$share->getSharedWith(),
$share->getNode()->getName(),
$shareId,
$share->getShareOwner(),
$share->getShareOwner() . '@' . $this->addressHandler->generateRemoteURL(),
$share->getSharedBy(),
$sharedByFederatedId
);
if ($send === false) {
$message_t = $this->l->t('Sharing %s failed, could not find %s, maybe the server is currently unreachable.',
[$share->getNode()->getName(), $share->getSharedWith()]);
throw new \Exception($message_t);
}
} catch (\Exception $e) {
$this->logger->error('Failed to notify remote server of federated share, removing share (' . $e->getMessage() . ')');
$this->removeShareFromTableById($shareId);
throw $e;
} }
return $shareId; return $shareId;
@ -526,13 +530,22 @@ class FederatedShareProvider implements IShareProvider {
* @param IShare $share * @param IShare $share
*/ */
public function removeShareFromTable(IShare $share) { public function removeShareFromTable(IShare $share) {
$this->removeShareFromTableById($share->getId());
}
/**
* remove share from table
*
* @param string $shareId
*/
private function removeShareFromTableById($shareId) {
$qb = $this->dbConnection->getQueryBuilder(); $qb = $this->dbConnection->getQueryBuilder();
$qb->delete('share') $qb->delete('share')
->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId()))); ->where($qb->expr()->eq('id', $qb->createNamedParameter($shareId)));
$qb->execute(); $qb->execute();
$qb->delete('federated_reshares') $qb->delete('federated_reshares')
->where($qb->expr()->eq('share_id', $qb->createNamedParameter($share->getId()))); ->where($qb->expr()->eq('share_id', $qb->createNamedParameter($shareId)));
$qb->execute(); $qb->execute();
} }

View File

@ -217,10 +217,6 @@ class FederatedShareProviderTest extends \Test\TestCase {
'sharedBy@http://localhost/' 'sharedBy@http://localhost/'
)->willReturn(false); )->willReturn(false);
$this->rootFolder->expects($this->once())
->method('getUserFolder')
->with('shareOwner')
->will($this->returnSelf());
$this->rootFolder->method('getById') $this->rootFolder->method('getById')
->with('42') ->with('42')
->willReturn([$node]); ->willReturn([$node]);
@ -244,6 +240,62 @@ class FederatedShareProviderTest extends \Test\TestCase {
$this->assertFalse($data); $this->assertFalse($data);
} }
public function testCreateException() {
$share = $this->shareManager->newShare();
$node = $this->getMock('\OCP\Files\File');
$node->method('getId')->willReturn(42);
$node->method('getName')->willReturn('myFile');
$share->setSharedWith('user@server.com')
->setSharedBy('sharedBy')
->setShareOwner('shareOwner')
->setPermissions(19)
->setNode($node);
$this->tokenHandler->method('generateToken')->willReturn('token');
$this->addressHandler->expects($this->any())->method('generateRemoteURL')
->willReturn('http://localhost/');
$this->addressHandler->expects($this->any())->method('splitUserRemote')
->willReturn(['user', 'server.com']);
$this->notifications->expects($this->once())
->method('sendRemoteShare')
->with(
$this->equalTo('token'),
$this->equalTo('user@server.com'),
$this->equalTo('myFile'),
$this->anything(),
'shareOwner',
'shareOwner@http://localhost/',
'sharedBy',
'sharedBy@http://localhost/'
)->willThrowException(new \Exception('dummy'));
$this->rootFolder->method('getById')
->with('42')
->willReturn([$node]);
try {
$share = $this->provider->create($share);
$this->fail();
} catch (\Exception $e) {
$this->assertEquals('dummy', $e->getMessage());
}
$qb = $this->connection->getQueryBuilder();
$stmt = $qb->select('*')
->from('share')
->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
->execute();
$data = $stmt->fetch();
$stmt->closeCursor();
$this->assertFalse($data);
}
public function testCreateShareWithSelf() { public function testCreateShareWithSelf() {
$share = $this->shareManager->newShare(); $share = $this->shareManager->newShare();

View File

@ -513,7 +513,7 @@
* Event handler for when the URL changed * Event handler for when the URL changed
*/ */
_onUrlChanged: function(e) { _onUrlChanged: function(e) {
if (e && e.dir) { if (e && _.isString(e.dir)) {
this.changeDirectory(e.dir, false, true); this.changeDirectory(e.dir, false, true);
} }
}, },
@ -1397,6 +1397,16 @@
return OC.linkTo('files', 'index.php')+"?dir="+ encodeURIComponent(dir).replace(/%2F/g, '/'); return OC.linkTo('files', 'index.php')+"?dir="+ encodeURIComponent(dir).replace(/%2F/g, '/');
}, },
_isValidPath: function(path) {
var sections = path.split('/');
for (var i = 0; i < sections.length; i++) {
if (sections[i] === '..') {
return false;
}
}
return true;
},
/** /**
* Sets the current directory name and updates the breadcrumb. * Sets the current directory name and updates the breadcrumb.
* @param targetDir directory to display * @param targetDir directory to display
@ -1404,7 +1414,11 @@
* @param {string} [fileId] file id * @param {string} [fileId] file id
*/ */
_setCurrentDir: function(targetDir, changeUrl, fileId) { _setCurrentDir: function(targetDir, changeUrl, fileId) {
targetDir = targetDir.replace(/\\/g, '/').replace(/\/\.\.\//g, '/'); targetDir = targetDir.replace(/\\/g, '/');
if (!this._isValidPath(targetDir)) {
targetDir = '/';
changeUrl = true;
}
var previousDir = this.getCurrentDirectory(), var previousDir = this.getCurrentDirectory(),
baseDir = OC.basename(targetDir); baseDir = OC.basename(targetDir);
@ -1415,6 +1429,9 @@
this.setPageTitle(); this.setPageTitle();
} }
if (targetDir.length > 0 && targetDir[0] !== '/') {
targetDir = '/' + targetDir;
}
this._currentDirectory = targetDir; this._currentDirectory = targetDir;
// legacy stuff // legacy stuff

View File

@ -1334,13 +1334,32 @@ describe('OCA.Files.FileList tests', function() {
fileList.changeDirectory('/another\\subdir'); fileList.changeDirectory('/another\\subdir');
expect(fileList.getCurrentDirectory()).toEqual('/another/subdir'); expect(fileList.getCurrentDirectory()).toEqual('/another/subdir');
}); });
it('converts backslashes to slashes and removes traversals when calling changeDirectory()', function() { it('switches to root dir when current directory is invalid', function() {
fileList.changeDirectory('/another\\subdir/../foo\\../bar\\..\\file/..\\folder/../'); _.each([
expect(fileList.getCurrentDirectory()).toEqual('/another/subdir/foo/bar/file/folder/'); '..',
'/..',
'../',
'/../',
'/../abc',
'/abc/..',
'/abc/../',
'/../abc/',
'/another\\subdir/../foo\\../bar\\..\\file/..\\folder/../'
], function(path) {
fileList.changeDirectory(path);
expect(fileList.getCurrentDirectory()).toEqual('/');
});
}); });
it('does not convert folders with a ".." in the name', function() { it('allows paths with dotdot at the beginning or end', function() {
fileList.changeDirectory('/abc../def'); _.each([
expect(fileList.getCurrentDirectory()).toEqual('/abc../def'); '/..abc',
'/def..',
'/...',
'/abc../def'
], function(path) {
fileList.changeDirectory(path);
expect(fileList.getCurrentDirectory()).toEqual(path);
});
}); });
it('switches to root dir when current directory does not exist', function() { it('switches to root dir when current directory does not exist', function() {
fileList.changeDirectory('/unexist'); fileList.changeDirectory('/unexist');
@ -1404,6 +1423,12 @@ describe('OCA.Files.FileList tests', function() {
setDirSpy.restore(); setDirSpy.restore();
getFolderContentsStub.restore(); getFolderContentsStub.restore();
}); });
it('prepends a slash to directory if none was given', function() {
fileList.changeDirectory('');
expect(fileList.getCurrentDirectory()).toEqual('/');
fileList.changeDirectory('noslash');
expect(fileList.getCurrentDirectory()).toEqual('/noslash');
});
}); });
describe('breadcrumb events', function() { describe('breadcrumb events', function() {
var deferredList; var deferredList;

View File

@ -98,15 +98,30 @@ class Backends extends Base {
$result = [ $result = [
'name' => $data['name'], 'name' => $data['name'],
'identifier' => $data['identifier'], 'identifier' => $data['identifier'],
'configuration' => array_map(function (DefinitionParameter $parameter) { 'configuration' => $this->formatConfiguration($data['configuration'])
return $parameter->getTypeName();
}, $data['configuration'])
]; ];
if ($backend instanceof Backend) { if ($backend instanceof Backend) {
$result['storage_class'] = $backend->getStorageClass(); $result['storage_class'] = $backend->getStorageClass();
$authBackends = $this->backendService->getAuthMechanismsByScheme(array_keys($backend->getAuthSchemes())); $authBackends = $this->backendService->getAuthMechanismsByScheme(array_keys($backend->getAuthSchemes()));
$result['supported_authentication_backends'] = array_keys($authBackends); $result['supported_authentication_backends'] = array_keys($authBackends);
$authConfig = array_map(function (AuthMechanism $auth) {
return $this->serializeAuthBackend($auth)['configuration'];
}, $authBackends);
$result['authentication_configuration'] = array_combine(array_keys($authBackends), $authConfig);
} }
return $result; return $result;
} }
/**
* @param DefinitionParameter[] $parameters
* @return string[]
*/
private function formatConfiguration(array $parameters) {
$configuration = array_filter($parameters, function (DefinitionParameter $parameter) {
return $parameter->getType() !== DefinitionParameter::VALUE_HIDDEN;
});
return array_map(function (DefinitionParameter $parameter) {
return $parameter->getTypeName();
}, $configuration);
}
} }

View File

@ -79,6 +79,42 @@
var permission = parseInt($tr.attr('data-permissions')) | OC.PERMISSION_DELETE; var permission = parseInt($tr.attr('data-permissions')) | OC.PERMISSION_DELETE;
$tr.attr('data-permissions', permission); $tr.attr('data-permissions', permission);
} }
// add row with expiration date for link only shares - influenced by _createRow of filelist
if (this._linksOnly) {
var expirationTimestamp = 0;
if(fileData.shares[0].expiration !== null) {
expirationTimestamp = moment(fileData.shares[0].expiration).valueOf();
}
$tr.attr('data-expiration', expirationTimestamp);
// date column (1000 milliseconds to seconds, 60 seconds, 60 minutes, 24 hours)
// difference in days multiplied by 5 - brightest shade for expiry dates in more than 32 days (160/5)
var modifiedColor = Math.round((expirationTimestamp - (new Date()).getTime()) / 1000 / 60 / 60 / 24 * 5);
// ensure that the brightest color is still readable
if (modifiedColor >= 160) {
modifiedColor = 160;
}
if (expirationTimestamp > 0) {
formatted = OC.Util.formatDate(expirationTimestamp);
text = OC.Util.relativeModifiedDate(expirationTimestamp);
} else {
formatted = t('files_sharing', 'No expiration date set');
text = '';
modifiedColor = 160;
}
td = $('<td></td>').attr({"class": "date"});
td.append($('<span></span>').attr({
"class": "modified",
"title": formatted,
"style": 'color:rgb(' + modifiedColor + ',' + modifiedColor + ',' + modifiedColor + ')'
}).text(text)
.tooltip({placement: 'top'})
);
$tr.append(td);
}
return $tr; return $tr;
}, },
@ -98,6 +134,11 @@
// root has special permissions // root has special permissions
this.$el.find('#emptycontent').toggleClass('hidden', !this.isEmpty); this.$el.find('#emptycontent').toggleClass('hidden', !this.isEmpty);
this.$el.find('#filestable thead th').toggleClass('hidden', this.isEmpty); this.$el.find('#filestable thead th').toggleClass('hidden', this.isEmpty);
// hide expiration date header for non link only shares
if (!this._linksOnly) {
this.$el.find('th.column-expiration').addClass('hidden');
}
} }
else { else {
OCA.Files.FileList.prototype.updateEmptyContent.apply(this, arguments); OCA.Files.FileList.prototype.updateEmptyContent.apply(this, arguments);
@ -249,6 +290,7 @@
type: share.share_type, type: share.share_type,
target: share.share_with, target: share.share_with,
stime: share.stime * 1000, stime: share.stime * 1000,
expiration: share.expiration,
}; };
if (self._sharedWithUser) { if (self._sharedWithUser) {
file.shareOwner = share.displayname_owner; file.shareOwner = share.displayname_owner;

View File

@ -22,6 +22,9 @@
<th id="headerDate" class="hidden column-mtime"> <th id="headerDate" class="hidden column-mtime">
<a id="modified" class="columntitle" data-sort="mtime"><span><?php p($l->t( 'Share time' )); ?></span><span class="sort-indicator"></span></a> <a id="modified" class="columntitle" data-sort="mtime"><span><?php p($l->t( 'Share time' )); ?></span><span class="sort-indicator"></span></a>
</th> </th>
<th class="hidden column-expiration">
<a class="columntitle"><span><?php p($l->t( 'Expiration date' )); ?></span></a>
</th>
</tr> </tr>
</thead> </thead>
<tbody id="fileList"> <tbody id="fileList">

View File

@ -30,6 +30,9 @@ use OCP\Share\IShare;
use OCP\Share\IManager; use OCP\Share\IManager;
use OCP\Files\Mount\IMountPoint; use OCP\Files\Mount\IMountPoint;
/**
* @group DB
*/
class MountProviderTest extends \Test\TestCase { class MountProviderTest extends \Test\TestCase {
/** @var MountProvider */ /** @var MountProvider */

View File

@ -38,6 +38,9 @@ describe('OCA.Sharing.FileList tests', function() {
'<th class="hidden column-mtime">' + '<th class="hidden column-mtime">' +
'<a class="columntitle" data-sort="mtime"><span class="sort-indicator"></span></a>' + '<a class="columntitle" data-sort="mtime"><span class="sort-indicator"></span></a>' +
'</th>' + '</th>' +
'<th class="column-expiration">' +
'<a class="columntitle"><span>Expiration date</span></a>' +
'</th>' +
'</tr></thead>' + '</tr></thead>' +
'<tbody id="fileList"></tbody>' + '<tbody id="fileList"></tbody>' +
'<tfoot></tfoot>' + '<tfoot></tfoot>' +
@ -512,6 +515,9 @@ describe('OCA.Sharing.FileList tests', function() {
fileList.reload(); fileList.reload();
var expirationDateInADay = moment()
.add(1, 'days').format('YYYY-MM-DD HH:mm:ss');
/* jshint camelcase: false */ /* jshint camelcase: false */
ocsResponse = { ocsResponse = {
ocs: { ocs: {
@ -528,12 +534,28 @@ describe('OCA.Sharing.FileList tests', function() {
path: '/local path/local name.txt', path: '/local path/local name.txt',
permissions: 1, permissions: 1,
stime: 11111, stime: 11111,
expiration: null,
share_type: OC.Share.SHARE_TYPE_LINK, share_type: OC.Share.SHARE_TYPE_LINK,
share_with: null, share_with: null,
token: 'abc', token: 'abc',
mimetype: 'text/plain', mimetype: 'text/plain',
uid_owner: 'user1', uid_owner: 'user1',
displayname_owner: 'User One' displayname_owner: 'User One'
},{
id: 8,
item_type: 'file',
item_source: 50,
file_source: 50,
path: '/local path2/local name2.txt',
permissions: 1,
stime: 11112,
expiration: expirationDateInADay,
share_type: OC.Share.SHARE_TYPE_LINK,
share_with: null,
token: 'abcd',
mimetype: 'text/plain2',
uid_owner: 'user2',
displayname_owner: 'User One2'
}] }]
} }
}; };
@ -570,10 +592,10 @@ describe('OCA.Sharing.FileList tests', function() {
JSON.stringify(ocsResponse) JSON.stringify(ocsResponse)
); );
// only renders the link share entry // only renders the link share entries
var $rows = fileList.$el.find('tbody tr'); var $rows = fileList.$el.find('tbody tr');
var $tr = $rows.eq(0); var $tr = $rows.eq(0);
expect($rows.length).toEqual(1); expect($rows.length).toEqual(2);
expect($tr.attr('data-id')).toEqual('49'); expect($tr.attr('data-id')).toEqual('49');
expect($tr.attr('data-type')).toEqual('file'); expect($tr.attr('data-type')).toEqual('file');
expect($tr.attr('data-file')).toEqual('local name.txt'); expect($tr.attr('data-file')).toEqual('local name.txt');
@ -588,8 +610,17 @@ describe('OCA.Sharing.FileList tests', function() {
expect($tr.find('a.name').attr('href')).toEqual( expect($tr.find('a.name').attr('href')).toEqual(
OC.webroot + '/remote.php/webdav/local%20path/local%20name.txt' OC.webroot + '/remote.php/webdav/local%20path/local%20name.txt'
); );
expect($tr.attr('data-expiration')).toEqual('0');
expect($tr.find('td:last-child span').text()).toEqual('');
expect($tr.find('.nametext').text().trim()).toEqual('local name.txt'); expect($tr.find('.nametext').text().trim()).toEqual('local name.txt');
// change to next row
$tr = $rows.eq(1);
expect($tr.attr('data-id')).toEqual('50');
expect($tr.attr('data-file')).toEqual('local name2.txt');
expect($tr.attr('data-expiration')).not.toEqual('0');
expect($tr.find('td:last-child span').text()).toEqual('in a day');
}); });
it('does not show virtual token recipient as recipient when password was set', function() { it('does not show virtual token recipient as recipient when password was set', function() {
/* jshint camelcase: false */ /* jshint camelcase: false */
@ -613,7 +644,7 @@ describe('OCA.Sharing.FileList tests', function() {
// only renders the link share entry // only renders the link share entry
var $rows = fileList.$el.find('tbody tr'); var $rows = fileList.$el.find('tbody tr');
var $tr = $rows.eq(0); var $tr = $rows.eq(0);
expect($rows.length).toEqual(1); expect($rows.length).toEqual(2);
expect($tr.attr('data-id')).toEqual('49'); expect($tr.attr('data-id')).toEqual('49');
expect($tr.attr('data-type')).toEqual('file'); expect($tr.attr('data-type')).toEqual('file');
expect($tr.attr('data-file')).toEqual('local name.txt'); expect($tr.attr('data-file')).toEqual('local name.txt');

View File

@ -645,7 +645,7 @@ class Storage {
//distance between two version too small, mark to delete //distance between two version too small, mark to delete
$toDelete[$key] = $version['path'] . '.v' . $version['version']; $toDelete[$key] = $version['path'] . '.v' . $version['version'];
$size += $version['size']; $size += $version['size'];
\OCP\Util::writeLog('files_versions', 'Mark to expire '. $version['path'] .' next version should be ' . $nextVersion . " or smaller. (prevTimestamp: " . $prevTimestamp . "; step: " . $step, \OCP\Util::DEBUG); \OCP\Util::writeLog('files_versions', 'Mark to expire '. $version['path'] .' next version should be ' . $nextVersion . " or smaller. (prevTimestamp: " . $prevTimestamp . "; step: " . $step, \OCP\Util::INFO);
} else { } else {
$nextVersion = $version['version'] - $step; $nextVersion = $version['version'] - $step;
$prevTimestamp = $version['version']; $prevTimestamp = $version['version'];
@ -766,7 +766,7 @@ class Storage {
self::deleteVersion($versionsFileview, $path); self::deleteVersion($versionsFileview, $path);
\OC_Hook::emit('\OCP\Versions', 'delete', array('path' => $path, 'trigger' => self::DELETE_TRIGGER_QUOTA_EXCEEDED)); \OC_Hook::emit('\OCP\Versions', 'delete', array('path' => $path, 'trigger' => self::DELETE_TRIGGER_QUOTA_EXCEEDED));
unset($allVersions[$key]); // update array with the versions we keep unset($allVersions[$key]); // update array with the versions we keep
\OCP\Util::writeLog('files_versions', "Expire: " . $path, \OCP\Util::DEBUG); \OCP\Util::writeLog('files_versions', "Expire: " . $path, \OCP\Util::INFO);
} }
// Check if enough space is available after versions are rearranged. // Check if enough space is available after versions are rearranged.
@ -782,7 +782,7 @@ class Storage {
\OC_Hook::emit('\OCP\Versions', 'preDelete', array('path' => $version['path'].'.v'.$version['version'], 'trigger' => self::DELETE_TRIGGER_QUOTA_EXCEEDED)); \OC_Hook::emit('\OCP\Versions', 'preDelete', array('path' => $version['path'].'.v'.$version['version'], 'trigger' => self::DELETE_TRIGGER_QUOTA_EXCEEDED));
self::deleteVersion($versionsFileview, $version['path'] . '.v' . $version['version']); self::deleteVersion($versionsFileview, $version['path'] . '.v' . $version['version']);
\OC_Hook::emit('\OCP\Versions', 'delete', array('path' => $version['path'].'.v'.$version['version'], 'trigger' => self::DELETE_TRIGGER_QUOTA_EXCEEDED)); \OC_Hook::emit('\OCP\Versions', 'delete', array('path' => $version['path'].'.v'.$version['version'], 'trigger' => self::DELETE_TRIGGER_QUOTA_EXCEEDED));
\OCP\Util::writeLog('files_versions', 'running out of space! Delete oldest version: ' . $version['path'].'.v'.$version['version'] , \OCP\Util::DEBUG); \OCP\Util::writeLog('files_versions', 'running out of space! Delete oldest version: ' . $version['path'].'.v'.$version['version'] , \OCP\Util::INFO);
$versionsSize -= $version['size']; $versionsSize -= $version['size'];
$availableSpace += $version['size']; $availableSpace += $version['size'];
next($allVersions); next($allVersions);

View File

@ -25,6 +25,7 @@
namespace OCA\User_LDAP\User; namespace OCA\User_LDAP\User;
use OC\Cache\CappedMemoryCache;
use OCA\User_LDAP\LogWrapper; use OCA\User_LDAP\LogWrapper;
use OCA\User_LDAP\FilesystemHelper; use OCA\User_LDAP\FilesystemHelper;
use OCP\IAvatarManager; use OCP\IAvatarManager;
@ -62,14 +63,13 @@ class Manager {
protected $avatarManager; protected $avatarManager;
/** /**
* array['byDN'] \OCA\User_LDAP\User\User[] * @var CappedMemoryCache $usersByDN
* ['byUid'] \OCA\User_LDAP\User\User[]
* @var array $users
*/ */
protected $users = array( protected $usersByDN;
'byDN' => array(), /**
'byUid' => array(), * @var CappedMemoryCache $usersByUid
); */
protected $usersByUid;
/** /**
* @param IConfig $ocConfig * @param IConfig $ocConfig
@ -93,6 +93,8 @@ class Manager {
$this->image = $image; $this->image = $image;
$this->db = $db; $this->db = $db;
$this->userManager = $userManager; $this->userManager = $userManager;
$this->usersByDN = new CappedMemoryCache();
$this->usersByUid = new CappedMemoryCache();
} }
/** /**
@ -116,8 +118,8 @@ class Manager {
$user = new User($uid, $dn, $this->access, $this->ocConfig, $user = new User($uid, $dn, $this->access, $this->ocConfig,
$this->ocFilesystem, clone $this->image, $this->ocLog, $this->ocFilesystem, clone $this->image, $this->ocLog,
$this->avatarManager, $this->userManager); $this->avatarManager, $this->userManager);
$this->users['byDN'][$dn] = $user; $this->usersByDN[$dn] = $user;
$this->users['byUid'][$uid] = $user; $this->usersByUid[$uid] = $user;
return $user; return $user;
} }
@ -219,10 +221,10 @@ class Manager {
*/ */
public function get($id) { public function get($id) {
$this->checkAccess(); $this->checkAccess();
if(isset($this->users['byDN'][$id])) { if(isset($this->usersByDN[$id])) {
return $this->users['byDN'][$id]; return $this->usersByDN[$id];
} else if(isset($this->users['byUid'][$id])) { } else if(isset($this->usersByUid[$id])) {
return $this->users['byUid'][$id]; return $this->usersByUid[$id];
} }
if($this->access->stringResemblesDN($id) ) { if($this->access->stringResemblesDN($id) ) {

View File

@ -228,6 +228,10 @@ class User_LDAP extends BackendUtility implements \OCP\IUserBackend, \OCP\UserIn
return false; return false;
} }
$newDn = $this->access->getUserDnByUuid($uuid); $newDn = $this->access->getUserDnByUuid($uuid);
//check if renamed user is still valid by reapplying the ldap filter
if(!is_array($this->access->readAttribute($newDn, '', $this->access->connection->ldapUserFilter))) {
return false;
}
$this->access->getUserMapper()->setDNbyUUID($newDn, $uuid); $this->access->getUserMapper()->setDNbyUUID($newDn, $uuid);
return true; return true;
} catch (\Exception $e) { } catch (\Exception $e) {

View File

@ -4,7 +4,7 @@
</button> </button>
<a href="<?php p(link_to_docs('admin-ldap')); ?>" <a href="<?php p(link_to_docs('admin-ldap')); ?>"
target="_blank" rel="noreferrer"> target="_blank" rel="noreferrer">
<img src="<?php print_unescaped(image_path('', 'actions/info.png')); ?>" <img src="<?php print_unescaped(image_path('', 'actions/info.svg')); ?>"
style="height:1.75ex" /> style="height:1.75ex" />
<?php p($l->t('Help'));?> <?php p($l->t('Help'));?>
</a> </a>

View File

@ -10,7 +10,7 @@
</button> </button>
<a href="<?php p(link_to_docs('admin-ldap')); ?>" <a href="<?php p(link_to_docs('admin-ldap')); ?>"
target="_blank" rel="noreferrer"> target="_blank" rel="noreferrer">
<img src="<?php print_unescaped(image_path('', 'actions/info.png')); ?>" <img src="<?php print_unescaped(image_path('', 'actions/info.svg')); ?>"
style="height:1.75ex" /> style="height:1.75ex" />
<span class="ldap_grey"><?php p($l->t('Help'));?></span> <span class="ldap_grey"><?php p($l->t('Help'));?></span>
</a> </a>

View File

@ -26,6 +26,21 @@ Feature: sharing
Then the OCS status code should be "100" Then the OCS status code should be "100"
And the HTTP status code should be "200" And the HTTP status code should be "200"
Scenario: Creating a new share with user who already received a share through their group
Given As an "admin"
And user "user0" exists
And user "user1" exists
And group "sharing-group" exists
And user "user1" belongs to group "sharing-group"
And file "welcome.txt" of user "user0" is shared with group "sharing-group"
And As an "user0"
Then sending "POST" to "/apps/files_sharing/api/v1/shares" with
| path | welcome.txt |
| shareWith | user1 |
| shareType | 0 |
Then the OCS status code should be "100"
And the HTTP status code should be "200"
Scenario: Creating a new public share Scenario: Creating a new public share
Given user "user0" exists Given user "user0" exists
And As an "user0" And As an "user0"

View File

@ -32,7 +32,6 @@ use OC\AppFramework\Utility\TimeFactory;
use OC\Core\Controller\AvatarController; use OC\Core\Controller\AvatarController;
use OC\Core\Controller\LoginController; use OC\Core\Controller\LoginController;
use OC\Core\Controller\LostController; use OC\Core\Controller\LostController;
use OC\Core\Controller\OccController;
use OC\Core\Controller\TokenController; use OC\Core\Controller\TokenController;
use OC\Core\Controller\TwoFactorChallengeController; use OC\Core\Controller\TwoFactorChallengeController;
use OC\Core\Controller\UserController; use OC\Core\Controller\UserController;
@ -126,18 +125,6 @@ class Application extends App {
$c->query('SecureRandom') $c->query('SecureRandom')
); );
}); });
$container->registerService('OccController', function(SimpleContainer $c) {
return new OccController(
$c->query('AppName'),
$c->query('Request'),
$c->query('Config'),
new \OC\Console\Application(
$c->query('Config'),
$c->query('ServerContainer')->getEventDispatcher(),
$c->query('Request')
)
);
});
/** /**
* Core class wrappers * Core class wrappers

View File

@ -1,147 +0,0 @@
<?php
/**
* @author Victor Dubiniuk <dubiniuk@owncloud.com>
*
* @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 OC\Core\Controller;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\JSONResponse;
use OC\Console\Application;
use OCP\IConfig;
use OCP\IRequest;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\BufferedOutput;
class OccController extends Controller {
/** @var array */
private $allowedCommands = [
'app:disable',
'app:enable',
'app:getpath',
'app:list',
'check',
'config:list',
'maintenance:mode',
'status',
'upgrade'
];
/** @var IConfig */
private $config;
/** @var Application */
private $console;
/**
* OccController constructor.
*
* @param string $appName
* @param IRequest $request
* @param IConfig $config
* @param Application $console
*/
public function __construct($appName, IRequest $request,
IConfig $config, Application $console) {
parent::__construct($appName, $request);
$this->config = $config;
$this->console = $console;
}
/**
* @PublicPage
* @NoCSRFRequired
*
* Execute occ command
* Sample request
* POST http://domain.tld/index.php/occ/status',
* {
* 'params': {
* '--no-warnings':'1',
* '--output':'json'
* },
* 'token': 'someToken'
* }
*
* @param string $command
* @param string $token
* @param array $params
*
* @return JSONResponse
* @throws \Exception
*/
public function execute($command, $token, $params = []) {
try {
$this->validateRequest($command, $token);
$output = new BufferedOutput();
$formatter = $output->getFormatter();
$formatter->setDecorated(false);
$this->console->setAutoExit(false);
$this->console->loadCommands(new ArrayInput([]), $output);
$inputArray = array_merge(['command' => $command], $params);
$input = new ArrayInput($inputArray);
$exitCode = $this->console->run($input, $output);
$response = $output->fetch();
$json = [
'exitCode' => $exitCode,
'response' => $response
];
} catch (\UnexpectedValueException $e){
$json = [
'exitCode' => 126,
'response' => 'Not allowed',
'details' => $e->getMessage()
];
}
return new JSONResponse($json);
}
/**
* Check if command is allowed and has a valid security token
* @param $command
* @param $token
*/
protected function validateRequest($command, $token){
if (!in_array($this->request->getRemoteAddress(), ['::1', '127.0.0.1', 'localhost'])) {
throw new \UnexpectedValueException('Web executor is not allowed to run from a different host');
}
if (!in_array($command, $this->allowedCommands)) {
throw new \UnexpectedValueException(sprintf('Command "%s" is not allowed to run via web request', $command));
}
$coreToken = $this->config->getSystemValue('updater.secret', '');
if ($coreToken === '') {
throw new \UnexpectedValueException(
'updater.secret is undefined in config/config.php. Either browse the admin settings in your ownCloud and click "Open updater" or define a strong secret using <pre>php -r \'echo password_hash("MyStrongSecretDoUseYourOwn!", PASSWORD_DEFAULT)."\n";\'</pre> and set this in the config.php.'
);
}
if (!password_verify($token, $coreToken)) {
throw new \UnexpectedValueException(
'updater.secret does not match the provided token'
);
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 132 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 128 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 127 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 233 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 267 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 251 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 134 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 134 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 135 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 138 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 130 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 134 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 279 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 212 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 266 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 493 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 323 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 132 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 208 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 236 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 208 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 295 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 192 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 134 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 169 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 228 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 228 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 160 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 392 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 249 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 324 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 315 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 355 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 229 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 106 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 122 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 159 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 163 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 136 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 150 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 163 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 127 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 307 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 378 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 424 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 317 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 336 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 321 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 193 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 309 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 293 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 256 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 264 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 264 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 180 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 496 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 492 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 122 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 120 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 238 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 149 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 128 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 128 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 142 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 142 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 300 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 959 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 648 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 804 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 984 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 376 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 892 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 805 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 640 B

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