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>
Joan <aseques@gmail.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>
Johan Björk <johanimon@gmail.com>
Johannes Twittmann <github.com@deryo.de>

View File

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

View File

@ -333,15 +333,20 @@ EOD;
public function testSubscriptions() {
$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);
$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']);
$patch = new PropPatch([
'{DAV:}displayname' => 'Unit test',
'{http://apple.com/ns/ical/}calendar-color' => '#ac0606',
]);
$this->backend->updateSubscription($id, $patch);
$patch->commit();
@ -350,6 +355,7 @@ EOD;
$this->assertEquals(1, count($subscriptions));
$this->assertEquals($id, $subscriptions[0]['id']);
$this->assertEquals('Unit test', $subscriptions[0]['{DAV:}displayname']);
$this->assertEquals('#ac0606', $subscriptions[0]['{http://apple.com/ns/ical/}calendar-color']);
$this->backend->deleteSubscription($id);
$subscriptions = $this->backend->getSubscriptionsForUser(self::UNIT_TEST_USER);

View File

@ -217,6 +217,8 @@ class FederatedShareProvider implements IShareProvider {
$share->getPermissions(),
$token
);
try {
$sharedByFederatedId = $share->getSharedBy();
if ($this->userManager->userExists($sharedByFederatedId)) {
$sharedByFederatedId = $sharedByFederatedId . '@' . $this->addressHandler->generateRemoteURL();
@ -233,13 +235,15 @@ class FederatedShareProvider implements IShareProvider {
);
if ($send === false) {
$data = $this->getRawShare($shareId);
$share = $this->createShareObject($data);
$this->removeShareFromTable($share);
$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;
}
@ -526,13 +530,22 @@ class FederatedShareProvider implements IShareProvider {
* @param 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->delete('share')
->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())));
->where($qb->expr()->eq('id', $qb->createNamedParameter($shareId)));
$qb->execute();
$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();
}

View File

@ -217,10 +217,6 @@ class FederatedShareProviderTest extends \Test\TestCase {
'sharedBy@http://localhost/'
)->willReturn(false);
$this->rootFolder->expects($this->once())
->method('getUserFolder')
->with('shareOwner')
->will($this->returnSelf());
$this->rootFolder->method('getById')
->with('42')
->willReturn([$node]);
@ -244,6 +240,62 @@ class FederatedShareProviderTest extends \Test\TestCase {
$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() {
$share = $this->shareManager->newShare();

View File

@ -513,7 +513,7 @@
* Event handler for when the URL changed
*/
_onUrlChanged: function(e) {
if (e && e.dir) {
if (e && _.isString(e.dir)) {
this.changeDirectory(e.dir, false, true);
}
},
@ -1397,6 +1397,16 @@
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.
* @param targetDir directory to display
@ -1404,7 +1414,11 @@
* @param {string} [fileId] file id
*/
_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(),
baseDir = OC.basename(targetDir);
@ -1415,6 +1429,9 @@
this.setPageTitle();
}
if (targetDir.length > 0 && targetDir[0] !== '/') {
targetDir = '/' + targetDir;
}
this._currentDirectory = targetDir;
// legacy stuff

View File

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

View File

@ -98,15 +98,30 @@ class Backends extends Base {
$result = [
'name' => $data['name'],
'identifier' => $data['identifier'],
'configuration' => array_map(function (DefinitionParameter $parameter) {
return $parameter->getTypeName();
}, $data['configuration'])
'configuration' => $this->formatConfiguration($data['configuration'])
];
if ($backend instanceof Backend) {
$result['storage_class'] = $backend->getStorageClass();
$authBackends = $this->backendService->getAuthMechanismsByScheme(array_keys($backend->getAuthSchemes()));
$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;
}
/**
* @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;
$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;
},
@ -98,6 +134,11 @@
// root has special permissions
this.$el.find('#emptycontent').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 {
OCA.Files.FileList.prototype.updateEmptyContent.apply(this, arguments);
@ -249,6 +290,7 @@
type: share.share_type,
target: share.share_with,
stime: share.stime * 1000,
expiration: share.expiration,
};
if (self._sharedWithUser) {
file.shareOwner = share.displayname_owner;

View File

@ -22,6 +22,9 @@
<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>
</th>
<th class="hidden column-expiration">
<a class="columntitle"><span><?php p($l->t( 'Expiration date' )); ?></span></a>
</th>
</tr>
</thead>
<tbody id="fileList">

View File

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

View File

@ -38,6 +38,9 @@ describe('OCA.Sharing.FileList tests', function() {
'<th class="hidden column-mtime">' +
'<a class="columntitle" data-sort="mtime"><span class="sort-indicator"></span></a>' +
'</th>' +
'<th class="column-expiration">' +
'<a class="columntitle"><span>Expiration date</span></a>' +
'</th>' +
'</tr></thead>' +
'<tbody id="fileList"></tbody>' +
'<tfoot></tfoot>' +
@ -512,6 +515,9 @@ describe('OCA.Sharing.FileList tests', function() {
fileList.reload();
var expirationDateInADay = moment()
.add(1, 'days').format('YYYY-MM-DD HH:mm:ss');
/* jshint camelcase: false */
ocsResponse = {
ocs: {
@ -528,12 +534,28 @@ describe('OCA.Sharing.FileList tests', function() {
path: '/local path/local name.txt',
permissions: 1,
stime: 11111,
expiration: null,
share_type: OC.Share.SHARE_TYPE_LINK,
share_with: null,
token: 'abc',
mimetype: 'text/plain',
uid_owner: 'user1',
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)
);
// only renders the link share entry
// only renders the link share entries
var $rows = fileList.$el.find('tbody tr');
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-type')).toEqual('file');
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(
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');
// 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() {
/* jshint camelcase: false */
@ -613,7 +644,7 @@ describe('OCA.Sharing.FileList tests', function() {
// only renders the link share entry
var $rows = fileList.$el.find('tbody tr');
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-type')).toEqual('file');
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
$toDelete[$key] = $version['path'] . '.v' . $version['version'];
$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 {
$nextVersion = $version['version'] - $step;
$prevTimestamp = $version['version'];
@ -766,7 +766,7 @@ class Storage {
self::deleteVersion($versionsFileview, $path);
\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
\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.
@ -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));
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));
\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'];
$availableSpace += $version['size'];
next($allVersions);

View File

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

View File

@ -228,6 +228,10 @@ class User_LDAP extends BackendUtility implements \OCP\IUserBackend, \OCP\UserIn
return false;
}
$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);
return true;
} catch (\Exception $e) {

View File

@ -4,7 +4,7 @@
</button>
<a href="<?php p(link_to_docs('admin-ldap')); ?>"
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" />
<?php p($l->t('Help'));?>
</a>

View File

@ -10,7 +10,7 @@
</button>
<a href="<?php p(link_to_docs('admin-ldap')); ?>"
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" />
<span class="ldap_grey"><?php p($l->t('Help'));?></span>
</a>

View File

@ -26,6 +26,21 @@ Feature: sharing
Then the OCS status code should be "100"
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
Given user "user0" exists
And As an "user0"

View File

@ -32,7 +32,6 @@ use OC\AppFramework\Utility\TimeFactory;
use OC\Core\Controller\AvatarController;
use OC\Core\Controller\LoginController;
use OC\Core\Controller\LostController;
use OC\Core\Controller\OccController;
use OC\Core\Controller\TokenController;
use OC\Core\Controller\TwoFactorChallengeController;
use OC\Core\Controller\UserController;
@ -126,18 +125,6 @@ class Application extends App {
$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

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