Merge branch 'master' into memcache-public

This commit is contained in:
Robin Appelman 2014-01-22 13:19:49 +01:00
commit 02aa44d055
56 changed files with 711 additions and 241 deletions

View File

@ -34,6 +34,7 @@ if (empty($_POST['dirToken'])) {
// resolve reshares
$rootLinkItem = OCP\Share::resolveReShare($linkItem);
OCP\JSON::checkUserExists($rootLinkItem['uid_owner']);
// Setup FS with owner
OC_Util::tearDownFS();
OC_Util::setupFS($rootLinkItem['uid_owner']);

View File

@ -27,6 +27,8 @@ var FileList={
Files.setupDragAndDrop();
}
FileList.updateFileSummary();
procesSelection();
$fileList.trigger(jQuery.Event("updated"));
},
createRow:function(type, name, iconurl, linktarget, size, lastModified, permissions) {
@ -300,7 +302,10 @@ var FileList={
},
remove:function(name){
var fileEl = FileList.findFileEl(name);
fileEl.find('td.filename').draggable('destroy');
if (fileEl.data('permissions') & OC.PERMISSION_DELETE) {
// file is only draggable when delete permissions are set
fileEl.find('td.filename').draggable('destroy');
}
fileEl.remove();
FileList.updateFileSummary();
if ( ! $('tr[data-file]').exists() ) {

View File

@ -612,11 +612,12 @@ function procesSelection() {
return el.type==='dir';
});
if (selectedFiles.length === 0 && selectedFolders.length === 0) {
$('#headerName>span.name').text(t('files','Name'));
$('#headerName span.name').text(t('files','Name'));
$('#headerSize').text(t('files','Size'));
$('#modified').text(t('files','Modified'));
$('table').removeClass('multiselect');
$('.selectedActions').hide();
$('#select_all').removeAttr('checked');
}
else {
$('.selectedActions').show();
@ -719,7 +720,7 @@ Files.lazyLoadPreview = function(path, mime, ready, width, height, etag) {
console.warn('Files.lazyLoadPreview(): missing etag argument');
}
if ( $('#publicUploadButtonMock').length ) {
if ( $('#public_upload').length ) {
urlSpec.t = $('#dirToken').val();
previewURL = OC.Router.generate('core_ajax_public_preview', urlSpec);
} else {

View File

@ -1,6 +1,10 @@
<div class="crumb <?php if(!count($_["breadcrumb"])) p('last');?>" data-dir=''>
<a href="<?php print_unescaped($_['baseURL']); ?>">
<img src="<?php print_unescaped(OCP\image_path('core', 'places/home.svg'));?>" class="svg" />
<?php if(isset($_['rootBreadCrumb'])):
echo $_['rootBreadCrumb'];
else:?>
<img src="<?php print_unescaped(OCP\image_path('core', 'places/home.svg'));?>" class="svg" />
<?php endif;?>
</a>
</div>
<?php for($i=0; $i<count($_["breadcrumb"]); $i++):

View File

@ -18,7 +18,7 @@ $totalsize = 0; ?>
data-size="<?php p($file['size']);?>"
data-etag="<?php p($file['etag']);?>"
data-permissions="<?php p($file['permissions']); ?>">
<?php if($file['isPreviewAvailable']): ?>
<?php if(isset($file['isPreviewAvailable']) and $file['isPreviewAvailable']): ?>
<td class="filename svg preview-icon"
<?php else: ?>
<td class="filename svg"

View File

@ -6,6 +6,7 @@ if (OC::$CLI) {
if (count($argv) === 2) {
$file = $argv[1];
list(, $user) = explode('/', $file);
OCP\JSON::checkUserExists($owner);
OC_Util::setupFS($user);
$view = new \OC\Files\View('');
/**

View File

@ -2,11 +2,15 @@
<info>
<id>files_encryption</id>
<name>Encryption</name>
<description>The new ownCloud 5 files encryption system. After the app was enabled you need to re-login to initialize your encryption keys.</description>
<description>The ownCloud files encryption system provides server side-encryption. After the app was enabled you need to re-login to initialize your encryption keys.</description>
<licence>AGPL</licence>
<author>Sam Tuke, Bjoern Schiessle, Florin Peter</author>
<require>4</require>
<shipped>true</shipped>
<documentation>
<user>http://doc.owncloud.org/server/6.0/user_manual/files/encryption.html</user>
<admin>http://doc.owncloud.org/server/6.0/admin_manual/configuration/configuration_encryption.html</admin>
</documentation>
<rememberlogin>false</rememberlogin>
<types>
<filesystem/>

View File

@ -255,8 +255,8 @@ class Proxy extends \OC_FileProxy {
// split the path parts
$pathParts = explode('/', $path);
// FIXME: handling for /userId/cache used by webdav for chunking. The cache chunks are NOT encrypted
if (isset($pathParts[2]) && $pathParts[2] === 'cache') {
// don't try to encrypt/decrypt cache chunks or files in the trash bin
if (isset($pathParts[2]) && ($pathParts[2] === 'cache' || $pathParts[2] === 'files_trashbin')) {
return $result;
}

View File

@ -155,7 +155,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
*/
function testSymmetricStreamEncryptShortFileContent() {
$filename = 'tmp-' . time() . '.test';
$filename = 'tmp-' . uniqid() . '.test';
$util = new Encryption\Util(new \OC_FilesystemView(), $this->userId);
@ -214,7 +214,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
function testSymmetricStreamEncryptLongFileContent() {
// Generate a a random filename
$filename = 'tmp-' . time() . '.test';
$filename = 'tmp-' . uniqid() . '.test';
$util = new Encryption\Util(new \OC_FilesystemView(), $this->userId);
@ -297,7 +297,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
*/
function testSymmetricStreamDecryptShortFileContent() {
$filename = 'tmp-' . time();
$filename = 'tmp-' . uniqid();
// Save long data as encrypted file using stream wrapper
$cryptedFile = file_put_contents('crypt:///'. $this->userId . '/files/' . $filename, $this->dataShort);
@ -327,7 +327,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
*/
function testSymmetricStreamDecryptLongFileContent() {
$filename = 'tmp-' . time();
$filename = 'tmp-' . uniqid();
// Save long data as encrypted file using stream wrapper
$cryptedFile = file_put_contents('crypt:///' . $this->userId . '/files/' . $filename, $this->dataLong);
@ -418,7 +418,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
*/
function testRenameFile() {
$filename = 'tmp-' . time();
$filename = 'tmp-' . uniqid();
// Save long data as encrypted file using stream wrapper
$cryptedFile = file_put_contents('crypt:///' . $this->userId . '/files/' . $filename, $this->dataLong);
@ -431,7 +431,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
$this->assertEquals($this->dataLong, $decrypt);
$newFilename = 'tmp-new-' . time();
$newFilename = 'tmp-new-' . uniqid();
$view = new \OC\Files\View('/' . $this->userId . '/files');
$view->rename($filename, $newFilename);
@ -449,7 +449,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
*/
function testMoveFileIntoFolder() {
$filename = 'tmp-' . time();
$filename = 'tmp-' . uniqid();
// Save long data as encrypted file using stream wrapper
$cryptedFile = file_put_contents('crypt:///' . $this->userId . '/files/' . $filename, $this->dataLong);
@ -462,8 +462,8 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
$this->assertEquals($this->dataLong, $decrypt);
$newFolder = '/newfolder' . time();
$newFilename = 'tmp-new-' . time();
$newFolder = '/newfolder' . uniqid();
$newFilename = 'tmp-new-' . uniqid();
$view = new \OC\Files\View('/' . $this->userId . '/files');
$view->mkdir($newFolder);
$view->rename($filename, $newFolder . '/' . $newFilename);
@ -484,8 +484,8 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
$view = new \OC\Files\View('/' . $this->userId . '/files');
$filename = '/tmp-' . time();
$folder = '/folder' . time();
$filename = '/tmp-' . uniqid();
$folder = '/folder' . uniqid();
$view->mkdir($folder);
@ -500,7 +500,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
$this->assertEquals($this->dataLong, $decrypt);
$newFolder = '/newfolder/subfolder' . time();
$newFolder = '/newfolder/subfolder' . uniqid();
$view->mkdir('/newfolder');
$view->rename($folder, $newFolder);
@ -519,7 +519,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
* @medium
*/
function testChangePassphrase() {
$filename = 'tmp-' . time();
$filename = 'tmp-' . uniqid();
// Save long data as encrypted file using stream wrapper
$cryptedFile = file_put_contents('crypt:///' . $this->userId . '/files/' . $filename, $this->dataLong);
@ -557,7 +557,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
*/
function testViewFilePutAndGetContents() {
$filename = '/tmp-' . time();
$filename = '/tmp-' . uniqid();
$view = new \OC\Files\View('/' . $this->userId . '/files');
// Save short data as encrypted file using stream wrapper
@ -590,7 +590,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
* @large
*/
function testTouchExistingFile() {
$filename = '/tmp-' . time();
$filename = '/tmp-' . uniqid();
$view = new \OC\Files\View('/' . $this->userId . '/files');
// Save short data as encrypted file using stream wrapper
@ -614,7 +614,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
* @medium
*/
function testTouchFile() {
$filename = '/tmp-' . time();
$filename = '/tmp-' . uniqid();
$view = new \OC\Files\View('/' . $this->userId . '/files');
$view->touch($filename);
@ -638,7 +638,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
* @medium
*/
function testFopenFile() {
$filename = '/tmp-' . time();
$filename = '/tmp-' . uniqid();
$view = new \OC\Files\View('/' . $this->userId . '/files');
// Save short data as encrypted file using stream wrapper

View File

@ -143,7 +143,7 @@ class Test_Encryption_Keymanager extends \PHPUnit_Framework_TestCase {
$key = $this->randomKey;
$file = 'unittest-' . time() . '.txt';
$file = 'unittest-' . uniqid() . '.txt';
$util = new Encryption\Util($this->view, $this->userId);
@ -196,7 +196,7 @@ class Test_Encryption_Keymanager extends \PHPUnit_Framework_TestCase {
function testRecursiveDelShareKeys() {
// generate filename
$filename = '/tmp-' . time() . '.txt';
$filename = '/tmp-' . uniqid() . '.txt';
// create folder structure
$this->view->mkdir('/'.Test_Encryption_Keymanager::TEST_USER.'/files/folder1');

View File

@ -80,7 +80,7 @@ class Test_Encryption_Proxy extends \PHPUnit_Framework_TestCase {
// init short data
$this->data = 'hats';
$this->filename = 'enc_proxy_tests-' . time() . '.txt';
$this->filename = 'enc_proxy_tests-' . uniqid() . '.txt';
}

View File

@ -99,7 +99,7 @@ class Test_Encryption_Stream extends \PHPUnit_Framework_TestCase {
}
function testStreamOptions() {
$filename = '/tmp-' . time();
$filename = '/tmp-' . uniqid();
$view = new \OC\Files\View('/' . $this->userId . '/files');
// Save short data as encrypted file using stream wrapper
@ -122,7 +122,7 @@ class Test_Encryption_Stream extends \PHPUnit_Framework_TestCase {
}
function testStreamSetBlocking() {
$filename = '/tmp-' . time();
$filename = '/tmp-' . uniqid();
$view = new \OC\Files\View('/' . $this->userId . '/files');
// Save short data as encrypted file using stream wrapper
@ -144,7 +144,7 @@ class Test_Encryption_Stream extends \PHPUnit_Framework_TestCase {
* @medium
*/
function testStreamSetTimeout() {
$filename = '/tmp-' . time();
$filename = '/tmp-' . uniqid();
$view = new \OC\Files\View('/' . $this->userId . '/files');
// Save short data as encrypted file using stream wrapper
@ -163,7 +163,7 @@ class Test_Encryption_Stream extends \PHPUnit_Framework_TestCase {
}
function testStreamSetWriteBuffer() {
$filename = '/tmp-' . time();
$filename = '/tmp-' . uniqid();
$view = new \OC\Files\View('/' . $this->userId . '/files');
// Save short data as encrypted file using stream wrapper
@ -187,9 +187,9 @@ class Test_Encryption_Stream extends \PHPUnit_Framework_TestCase {
*/
function testStreamFromLocalFile() {
$filename = '/' . $this->userId . '/files/' . 'tmp-' . time().'.txt';
$filename = '/' . $this->userId . '/files/' . 'tmp-' . uniqid().'.txt';
$tmpFilename = "/tmp/" . time() . ".txt";
$tmpFilename = "/tmp/" . uniqid() . ".txt";
// write an encrypted file
$cryptedFile = $this->view->file_put_contents($filename, $this->dataShort);

View File

@ -119,7 +119,7 @@ class Test_Encryption_Trashbin extends \PHPUnit_Framework_TestCase {
function testDeleteFile() {
// generate filename
$filename = 'tmp-' . time() . '.txt';
$filename = 'tmp-' . uniqid() . '.txt';
// save file with content
$cryptedFile = file_put_contents('crypt:///' .\Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1. '/files/'. $filename, $this->dataShort);
@ -223,7 +223,7 @@ class Test_Encryption_Trashbin extends \PHPUnit_Framework_TestCase {
function testPermanentDeleteFile() {
// generate filename
$filename = 'tmp-' . time() . '.txt';
$filename = 'tmp-' . uniqid() . '.txt';
// save file with content
$cryptedFile = file_put_contents('crypt:///' .$this->userId. '/files/' . $filename, $this->dataShort);

View File

@ -142,8 +142,8 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase {
self::loginHelper($this->userId);
$unencryptedFile = '/tmpUnencrypted-' . time() . '.txt';
$encryptedFile = '/tmpEncrypted-' . time() . '.txt';
$unencryptedFile = '/tmpUnencrypted-' . uniqid() . '.txt';
$encryptedFile = '/tmpEncrypted-' . uniqid() . '.txt';
// Disable encryption proxy to write a unencrypted file
$proxyStatus = \OC_FileProxy::$enabled;
@ -254,7 +254,7 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase {
\OC_User::setUserId(\Test_Encryption_Util::TEST_ENCRYPTION_UTIL_USER1);
$filename = '/tmp-' . time() . '.test';
$filename = '/tmp-' . uniqid() . '.test';
// Disable encryption proxy to prevent recursive calls
$proxyStatus = \OC_FileProxy::$enabled;
@ -282,7 +282,7 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase {
function testGetFileSize() {
\Test_Encryption_Util::loginHelper(\Test_Encryption_Util::TEST_ENCRYPTION_UTIL_USER1);
$filename = 'tmp-' . time();
$filename = 'tmp-' . uniqid();
$externalFilename = '/' . $this->userId . '/files/' . $filename;
// Test for 0 byte files
@ -318,7 +318,7 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase {
function testEncryptAll() {
$filename = "/encryptAll" . time() . ".txt";
$filename = "/encryptAll" . uniqid() . ".txt";
$util = new Encryption\Util($this->view, $this->userId);
// disable encryption to upload a unencrypted file
@ -350,7 +350,7 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase {
function testDecryptAll() {
$filename = "/decryptAll" . time() . ".txt";
$filename = "/decryptAll" . uniqid() . ".txt";
$util = new Encryption\Util($this->view, $this->userId);
$this->view->file_put_contents($this->userId . '/files/' . $filename, $this->dataShort);

View File

@ -113,7 +113,7 @@ class Test_Encryption_Webdav extends \PHPUnit_Framework_TestCase {
function testWebdavPUT() {
// generate filename
$filename = '/tmp-' . time() . '.txt';
$filename = '/tmp-' . uniqid() . '.txt';
// set server vars
$_SERVER['REQUEST_METHOD'] = 'OPTIONS';

View File

@ -23,9 +23,12 @@ $(document).ready(function() {
$(token).val(result.access_token);
$(token_secret).val(result.access_token_secret);
$(configured).val('true');
OC.MountConfig.saveStorage(tr);
$(tr).find('.configuration input').attr('disabled', 'disabled');
$(tr).find('.configuration').append('<span id="access" style="padding-left:0.5em;">'+t('files_external', 'Access granted')+'</span>');
OC.MountConfig.saveStorage(tr, function(status) {
if (status) {
$(tr).find('.configuration input').attr('disabled', 'disabled');
$(tr).find('.configuration').append('<span id="access" style="padding-left:0.5em;">'+t('files_external', 'Access granted')+'</span>');
}
});
} else {
OC.dialogs.alert(result.data.message, t('files_external', 'Error configuring Dropbox storage'));
}
@ -77,7 +80,6 @@ $(document).ready(function() {
var tr = $(this).parent().parent();
var app_key = $(this).parent().find('[data-parameter="app_key"]').val();
var app_secret = $(this).parent().find('[data-parameter="app_secret"]').val();
var statusSpan = $(tr).find('.status span');
if (app_key != '' && app_secret != '') {
var tr = $(this).parent().parent();
var configured = $(this).parent().find('[data-parameter="configured"]');
@ -88,10 +90,9 @@ $(document).ready(function() {
$(configured).val('false');
$(token).val(result.data.request_token);
$(token_secret).val(result.data.request_token_secret);
OC.MountConfig.saveStorage(tr);
statusSpan.removeClass();
statusSpan.addClass('waiting');
window.location = result.data.url;
OC.MountConfig.saveStorage(tr, function() {
window.location = result.data.url;
});
} else {
OC.dialogs.alert(result.data.message, t('files_external', 'Error configuring Dropbox storage'));
}

View File

@ -32,11 +32,14 @@ $(document).ready(function() {
if (result && result.status == 'success') {
$(token).val(result.data.token);
$(configured).val('true');
OC.MountConfig.saveStorage(tr);
$(tr).find('.configuration input').attr('disabled', 'disabled');
$(tr).find('.configuration').append($('<span/>')
.attr('id', 'access')
.text(t('files_external', 'Access granted')));
OC.MountConfig.saveStorage(tr, function(status) {
if (status) {
$(tr).find('.configuration input').attr('disabled', 'disabled');
$(tr).find('.configuration').append($('<span/>')
.attr('id', 'access')
.text(t('files_external', 'Access granted')));
}
});
} else {
OC.dialogs.alert(result.data.message,
t('files_external', 'Error configuring Google Drive storage')
@ -99,7 +102,6 @@ $(document).ready(function() {
var configured = $(this).parent().find('[data-parameter="configured"]');
var client_id = $(this).parent().find('[data-parameter="client_id"]').val();
var client_secret = $(this).parent().find('[data-parameter="client_secret"]').val();
var statusSpan = $(tr).find('.status span');
if (client_id != '' && client_secret != '') {
var token = $(this).parent().find('[data-parameter="token"]');
$.post(OC.filePath('files_external', 'ajax', 'google.php'),
@ -112,10 +114,9 @@ $(document).ready(function() {
if (result && result.status == 'success') {
$(configured).val('false');
$(token).val('false');
OC.MountConfig.saveStorage(tr);
statusSpan.removeClass();
statusSpan.addClass('waiting');
window.location = result.data.url;
OC.MountConfig.saveStorage(tr, function(status) {
window.location = result.data.url;
});
} else {
OC.dialogs.alert(result.data.message,
t('files_external', 'Error configuring Google Drive storage')

View File

@ -12,7 +12,7 @@ function updateStatus(statusEl, result){
}
OC.MountConfig={
saveStorage:function(tr) {
saveStorage:function(tr, callback) {
var mountPoint = $(tr).find('.mountPoint input').val();
if (mountPoint == '') {
return false;
@ -84,9 +84,15 @@ OC.MountConfig={
},
success: function(result) {
status = updateStatus(statusSpan, result);
if (callback) {
callback(status);
}
},
error: function(result){
status = updateStatus(statusSpan, result);
if (callback) {
callback(status);
}
}
});
});
@ -137,9 +143,15 @@ OC.MountConfig={
},
success: function(result) {
status = updateStatus(statusSpan, result);
if (callback) {
callback(status);
}
},
error: function(result){
status = updateStatus(statusSpan, result);
if (callback) {
callback(status);
}
}
});
}

View File

@ -224,7 +224,7 @@ class DAV extends \OC\Files\Storage\Common{
if (isset($response['{DAV:}quota-available-bytes'])) {
return (int)$response['{DAV:}quota-available-bytes'];
} else {
return 0;
return \OC\Files\SPACE_UNKNOWN;
}
} catch(\Exception $e) {
return \OC\Files\SPACE_UNKNOWN;

View File

@ -39,6 +39,7 @@ if(!isset($linkedItem['uid_owner']) || !isset($linkedItem['file_source'])) {
$rootLinkItem = OCP\Share::resolveReShare($linkedItem);
$userId = $rootLinkItem['uid_owner'];
OCP\JSON::checkUserExists($rootLinkItem['uid_owner']);
\OC_Util::setupFS($userId);
\OC\Files\Filesystem::initMountPoints($userId);
$view = new \OC\Files\View('/' . $userId . '/files');
@ -88,4 +89,4 @@ try{
} catch (\Exception $e) {
\OC_Response::setStatus(500);
\OC_Log::write('core', $e->getmessage(), \OC_Log::DEBUG);
}
}

View File

@ -44,6 +44,7 @@ if (version_compare($installedVersion, '0.3', '<')) {
$shareType = OCP\Share::SHARE_TYPE_USER;
$shareWith = $row['uid_shared_with'];
}
OCP\JSON::checkUserExists($row['uid_owner']);
OC_User::setUserId($row['uid_owner']);
//we need to setup the filesystem for the user, otherwise OC_FileSystem::getRoot will fail and break
OC_Util::setupFS($row['uid_owner']);

View File

@ -141,10 +141,13 @@ thead{
.directLink {
margin-bottom: 20px;
}
.directLink label {
font-weight: normal;
}
.directLink input {
margin-left: 10px;
width: 300px;
}
.directLink label {
font-weight: normal;
}
.directLink input {
margin-left: 10px;
width: 300px;
}
.public_actions {
padding: 4px;
}

View File

@ -59,7 +59,8 @@ $(document).ready(function() {
});
// Add Uploadprogress Wrapper to controls bar
$('#controls').append($('#additional_controls div#uploadprogresswrapper'));
$('#controls').append($('#controls .actions div#uploadprogresswrapper'));
$('#uploadprogresswrapper').addClass('public_actions');
// Cancel upload trigger
$('#cancel_upload_button').click(function() {

View File

@ -32,7 +32,7 @@ class Shared_Watcher extends Watcher {
* @param string $path
*/
public function checkUpdate($path) {
if ($path != '' && parent::checkUpdate($path)) {
if ($path != '' && parent::checkUpdate($path) === true) {
// since checkUpdate() has already updated the size of the subdirs,
// only apply the update to the owner's parent dirs

View File

@ -35,7 +35,7 @@ function determineIcon($file, $sharingRoot, $sharingToken) {
if (isset($_GET['t'])) {
$token = $_GET['t'];
$linkItem = OCP\Share::getShareByToken($token);
$linkItem = OCP\Share::getShareByToken($token, false);
if (is_array($linkItem) && isset($linkItem['uid_owner'])) {
// seems to be a valid share
$type = $linkItem['item_type'];
@ -43,10 +43,10 @@ if (isset($_GET['t'])) {
$shareOwner = $linkItem['uid_owner'];
$path = null;
$rootLinkItem = OCP\Share::resolveReShare($linkItem);
$fileOwner = $rootLinkItem['uid_owner'];
if (isset($fileOwner)) {
if (isset($rootLinkItem['uid_owner'])) {
OCP\JSON::checkUserExists($rootLinkItem['uid_owner']);
OC_Util::tearDownFS();
OC_Util::setupFS($fileOwner);
OC_Util::setupFS($rootLinkItem['uid_owner']);
$path = \OC\Files\Filesystem::getPath($linkItem['file_source']);
}
}
@ -111,6 +111,7 @@ if (isset($path)) {
}
}
$basePath = $path;
$rootName = basename($path);
if (isset($_GET['path']) && \OC\Files\Filesystem::isReadable($basePath . $_GET['path'])) {
$getPath = \OC\Files\Filesystem::normalizePath($_GET['path']);
$path .= $getPath;
@ -188,8 +189,8 @@ if (isset($path)) {
} else {
$i['extension'] = '';
}
$i['isPreviewAvailable'] = \OC::$server->getPreviewManager()->isMimeSupported($i['mimetype']);
}
$i['isPreviewAvailable'] = \OC::$server->getPreviewManager()->isMimeSupported($i['mimetype']);
$i['directory'] = $getPath;
$i['permissions'] = OCP\PERMISSION_READ;
$i['icon'] = determineIcon($i, $basePath, $token);
@ -216,6 +217,7 @@ if (isset($path)) {
$list->assign('sharingroot', $basePath);
$breadcrumbNav = new OCP\Template('files', 'part.breadcrumb', '');
$breadcrumbNav->assign('breadcrumb', $breadcrumb);
$breadcrumbNav->assign('rootBreadCrumb', $rootName);
$breadcrumbNav->assign('baseURL', OCP\Util::linkToPublic('files') . $urlLinkIdentifiers . '&path=');
$maxUploadFilesize=OCP\Util::maxUploadFilesize($path);
$fileHeader = (!isset($files) or count($files) > 0);

View File

@ -24,9 +24,10 @@
<?php if (!isset($_['folder']) || $_['allowZipDownload']): ?>
<a href="<?php p($_['downloadURL']); ?>" class="button" id="download"><img
class="svg" alt="Download" src="<?php print_unescaped(OCP\image_path("core", "actions/download.svg")); ?>"
/><span><?php p($l->t('Download'))?></span></a>
<a href="<?php p($_['downloadURL']); ?>" class="button" id="download">
<img class="svg" alt="Download" src="<?php print_unescaped(OCP\image_path("core", "actions/download.svg")); ?>" />
<span><?php p($l->t('Download'))?></span>
</a>
<?php endif; ?>
<?php if ($_['allowPublicUploadEnabled']):?>
@ -43,28 +44,17 @@
<?php endif;?>
<div id="data-upload-form" class="button" title="<?php p($l->t('Upload') . ' max. '.$_['uploadMaxHumanFilesize']) ?>">
<div id="data-upload-form" title="<?php p($l->t('Upload') . ' max. '.$_['uploadMaxHumanFilesize']) ?>">
<input id="file_upload_start" type="file" name="files[]" data-url="<?php print_unescaped(OCP\Util::linkTo('files', 'ajax/upload.php')); ?>" multiple>
<a href="#" id="publicUploadButtonMock" class="svg">
<a href="#" id="public_upload" class="button">
<img class="svg" alt="Upload" src="<?php print_unescaped(OCP\image_path("core", "actions/upload.svg")); ?>" />
<span><?php p($l->t('Upload'))?></span>
</a>
</div>
</div>
<div id="additional_controls" style="display:none">
<div id="uploadprogresswrapper">
<div id="uploadprogressbar"></div>
<input id="cancel_upload_button" type="button" class="stop" style="display:none"
value="<?php p($l->t('Cancel upload'));?>"
/>
</div>
<div>
<?php endif; ?>
</div>
</div></header>
<div id="content">

View File

@ -189,7 +189,7 @@ class Trashbin {
if ($rootView->is_dir($owner . '/files_versions/' . $ownerPath)) {
$size += self::calculateSize(new \OC\Files\View('/' . $owner . '/files_versions/' . $ownerPath));
if ($owner !== $user) {
$rootView->copy($owner . '/files_versions/' . $ownerPath, $owner . '/files_trashbin/versions/' . basename($ownerPath) . '.d' . $timestamp);
self::copy_recursive($owner . '/files_versions/' . $ownerPath, $owner . '/files_trashbin/versions/' . basename($ownerPath) . '.d' . $timestamp, $rootView);
}
$rootView->rename($owner . '/files_versions/' . $ownerPath, $user . '/files_trashbin/versions/' . $filename . '.d' . $timestamp);
} else if ($versions = \OCA\Files_Versions\Storage::getVersions($owner, $ownerPath)) {
@ -247,7 +247,7 @@ class Trashbin {
if ($rootView->is_dir($keyfile)) {
$size += self::calculateSize(new \OC\Files\View($keyfile));
if ($owner !== $user) {
$rootView->copy($keyfile, $owner . '/files_trashbin/keyfiles/' . basename($ownerPath) . '.d' . $timestamp);
self::copy_recursive($keyfile, $owner . '/files_trashbin/keyfiles/' . basename($ownerPath) . '.d' . $timestamp, $rootView);
}
$rootView->rename($keyfile, $user . '/files_trashbin/keyfiles/' . $filename . '.d' . $timestamp);
} else {
@ -265,7 +265,7 @@ class Trashbin {
if ($rootView->is_dir($sharekeys)) {
$size += self::calculateSize(new \OC\Files\View($sharekeys));
if ($owner !== $user) {
$rootView->copy($sharekeys, $owner . '/files_trashbin/share-keys/' . basename($ownerPath) . '.d' . $timestamp);
self::copy_recursive($sharekeys, $owner . '/files_trashbin/share-keys/' . basename($ownerPath) . '.d' . $timestamp, $rootView);
}
$rootView->rename($sharekeys, $user . '/files_trashbin/share-keys/' . $filename . '.d' . $timestamp);
} else {
@ -734,7 +734,7 @@ class Trashbin {
// calculate available space for trash bin
// subtract size of files and current trash bin size from quota
if ($softQuota) {
$rootInfo = $view->getFileInfo('/files/');
$rootInfo = $view->getFileInfo('/files/', false);
$free = $quota - $rootInfo['size']; // remaining free space for user
if ($free > 0) {
$availableSpace = ($free * self::DEFAULTMAXSIZE / 100) - $trashbinSize; // how much space can be used for versions

View File

@ -5,7 +5,8 @@ $source = $_GET['source'];
$start = $_GET['start'];
list ($uid, $filename) = OCA\Files_Versions\Storage::getUidAndFilename($source);
$count = 5; //show the newest revisions
if( ($versions = OCA\Files_Versions\Storage::getVersions($uid, $filename)) ) {
$versions = OCA\Files_Versions\Storage::getVersions($uid, $filename, $source);
if( $versions ) {
$endReached = false;
if (count($versions) <= $start+$count) {

View File

@ -12,18 +12,11 @@ if(!\OC_App::isEnabled('files_versions')){
}
$file = array_key_exists('file', $_GET) ? (string) urldecode($_GET['file']) : '';
$user = array_key_exists('user', $_GET) ? $_GET['user'] : '';
$maxX = array_key_exists('x', $_GET) ? (int) $_GET['x'] : 44;
$maxY = array_key_exists('y', $_GET) ? (int) $_GET['y'] : 44;
$version = array_key_exists('version', $_GET) ? $_GET['version'] : '';
$scalingUp = array_key_exists('scalingup', $_GET) ? (bool) $_GET['scalingup'] : true;
if($user === '') {
\OC_Response::setStatus(400); //400 Bad Request
\OC_Log::write('versions-preview', 'No user parameter was passed', \OC_Log::DEBUG);
exit;
}
if($file === '' && $version === '') {
\OC_Response::setStatus(400); //400 Bad Request
\OC_Log::write('versions-preview', 'No file parameter was passed', \OC_Log::DEBUG);
@ -36,7 +29,8 @@ if($maxX === 0 || $maxY === 0) {
exit;
}
try{
try {
list($user, $file) = \OCA\Files_Versions\Storage::getUidAndFilename($file);
$preview = new \OC\Preview($user, 'files_versions', $file.'.v'.$version);
$mimetype = \OC_Helper::getFileNameMimeType($file);
$preview->setMimetype($mimetype);

View File

@ -261,11 +261,12 @@ class Storage {
/**
* @brief get a list of all available versions of a file in descending chronological order
* @param $uid user id from the owner of the file
* @param $filename file to find versions of, relative to the user files dir
* @returns array
* @param string $uid user id from the owner of the file
* @param string $filename file to find versions of, relative to the user files dir
* @param string $userFullPath
* @returns array versions newest version first
*/
public static function getVersions($uid, $filename) {
public static function getVersions($uid, $filename, $userFullPath = '') {
$versions = array();
// fetch for old versions
$view = new \OC\Files\View('/' . $uid . '/' . self::VERSIONS_ROOT);
@ -286,7 +287,11 @@ class Storage {
$versions[$key]['cur'] = 0;
$versions[$key]['version'] = $version;
$versions[$key]['humanReadableTimestamp'] = self::getHumanReadableTimestamp($version);
$versions[$key]['preview'] = \OCP\Util::linkToRoute('core_ajax_versions_preview', array('file' => $filename, 'version' => $version, 'user' => $uid));
if (empty($userFullPath)) {
$versions[$key]['preview'] = '';
} else {
$versions[$key]['preview'] = \OCP\Util::linkToRoute('core_ajax_versions_preview', array('file' => $userFullPath, 'version' => $version));
}
$versions[$key]['path'] = $filename;
$versions[$key]['name'] = $versionedFile;
$versions[$key]['size'] = $file['size'];
@ -392,12 +397,13 @@ class Storage {
}
}
ksort($versions);
// newest version first
krsort($versions);
$result = array();
foreach ($versions as $key => $value) {
$size = $view->filesize($value['path']);
$size = $view->filesize(self::VERSIONS_ROOT.'/'.$value['path'].'.v'.$value['timestamp']);
$filename = $value['path'];
$result['all'][$key]['version'] = $value['timestamp'];
@ -412,6 +418,63 @@ class Storage {
return $result;
}
/**
* @brief get list of files we want to expire
* @param int $currentTime timestamp of current time
* @param array $versions list of versions
* @return array containing the list of to deleted versions and the size of them
*/
protected static function getExpireList($time, $versions) {
$size = 0;
$toDelete = array(); // versions we want to delete
$interval = 1;
$step = Storage::$max_versions_per_interval[$interval]['step'];
if (Storage::$max_versions_per_interval[$interval]['intervalEndsAfter'] == -1) {
$nextInterval = -1;
} else {
$nextInterval = $time - Storage::$max_versions_per_interval[$interval]['intervalEndsAfter'];
}
$firstVersion = reset($versions);
$firstKey = key($versions);
$prevTimestamp = $firstVersion['version'];
$nextVersion = $firstVersion['version'] - $step;
unset($versions[$firstKey]);
foreach ($versions as $key => $version) {
$newInterval = true;
while ($newInterval) {
if ($nextInterval == -1 || $prevTimestamp > $nextInterval) {
if ($version['version'] > $nextVersion) {
//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);
} else {
$nextVersion = $version['version'] - $step;
$prevTimestamp = $version['version'];
}
$newInterval = false; // version checked so we can move to the next one
} else { // time to move on to the next interval
$interval++;
$step = Storage::$max_versions_per_interval[$interval]['step'];
$nextVersion = $prevTimestamp - $step;
if (Storage::$max_versions_per_interval[$interval]['intervalEndsAfter'] == -1) {
$nextInterval = -1;
} else {
$nextInterval = $time - Storage::$max_versions_per_interval[$interval]['intervalEndsAfter'];
}
$newInterval = true; // we changed the interval -> check same version with new interval
}
}
}
return array($toDelete, $size);
}
/**
* @brief Erase a file's versions which exceed the set quota
*/
@ -445,7 +508,7 @@ class Storage {
// subtract size of files and current versions size from quota
if ($softQuota) {
$files_view = new \OC\Files\View('/'.$uid.'/files');
$rootInfo = $files_view->getFileInfo('/');
$rootInfo = $files_view->getFileInfo('/', false);
$free = $quota-$rootInfo['size']; // remaining free space for user
if ( $free > 0 ) {
$availableSpace = ($free * self::DEFAULTMAXSIZE / 100) - ($versionsSize + $offset); // how much space can be used for versions
@ -456,33 +519,35 @@ class Storage {
$availableSpace = $quota - $offset;
}
// with the probability of 0.1% we reduce the number of all versions not only for the current file
$random = rand(0, 1000);
if ($random == 0) {
$allFiles = true;
} else {
$allFiles = false;
}
$allVersions = Storage::getVersions($uid, $filename);
$versionsByFile[$filename] = $allVersions;
$sizeOfDeletedVersions = self::delOldVersions($versionsByFile, $allVersions, $versionsFileview);
$time = time();
list($toDelete, $sizeOfDeletedVersions) = self::getExpireList($time, $allVersions);
$availableSpace = $availableSpace + $sizeOfDeletedVersions;
$versionsSize = $versionsSize - $sizeOfDeletedVersions;
// if still not enough free space we rearrange the versions from all files
if ($availableSpace <= 0 || $allFiles) {
if ($availableSpace <= 0) {
$result = Storage::getAllVersions($uid);
$versionsByFile = $result['by_file'];
$allVersions = $result['all'];
$sizeOfDeletedVersions = self::delOldVersions($versionsByFile, $allVersions, $versionsFileview);
foreach ($result['by_file'] as $versions) {
list($toDeleteNew, $size) = self::getExpireList($time, $versions);
$toDelete = array_merge($toDelete, $toDeleteNew);
$sizeOfDeletedVersions += $size;
}
$availableSpace = $availableSpace + $sizeOfDeletedVersions;
$versionsSize = $versionsSize - $sizeOfDeletedVersions;
}
foreach($toDelete as $key => $path) {
\OC_Hook::emit('\OCP\Versions', 'delete', array('path' => $path));
$versionsFileview->unlink($path);
unset($allVersions[$key]); // update array with the versions we keep
\OCP\Util::writeLog('files_versions', "Expire: " . $path, \OCP\Util::DEBUG);
}
// Check if enough space is available after versions are rearranged.
// If not we delete the oldest versions until we meet the size limit for versions,
// but always keep the two latest versions
@ -492,6 +557,7 @@ class Storage {
$version = current($allVersions);
$versionsFileview->unlink($version['path'].'.v'.$version['version']);
\OC_Hook::emit('\OCP\Versions', 'delete', array('path' => $version['path'].'.v'.$version['version']));
\OCP\Util::writeLog('files_versions', 'running out of space! Delete oldest version: ' . $version['path'].'.v'.$version['version'] , \OCP\Util::DEBUG);
$versionsSize -= $version['size'];
$availableSpace += $version['size'];
next($allVersions);
@ -504,69 +570,6 @@ class Storage {
return false;
}
/**
* @brief delete old version from a given list of versions
*
* @param array $versionsByFile list of versions ordered by files
* @param array $allVversions all versions accross multiple files
* @param $versionsFileview OC\Files\View on data/user/files_versions
* @return size of releted versions
*/
private static function delOldVersions($versionsByFile, &$allVersions, $versionsFileview) {
$time = time();
$size = 0;
// delete old versions for every given file
foreach ($versionsByFile as $versions) {
$versions = array_reverse($versions); // newest version first
$interval = 1;
$step = Storage::$max_versions_per_interval[$interval]['step'];
if (Storage::$max_versions_per_interval[$interval]['intervalEndsAfter'] == -1) {
$nextInterval = -1;
} else {
$nextInterval = $time - Storage::$max_versions_per_interval[$interval]['intervalEndsAfter'];
}
$firstVersion = reset($versions);
$firstKey = key($versions);
$prevTimestamp = $firstVersion['version'];
$nextVersion = $firstVersion['version'] - $step;
unset($versions[$firstKey]);
foreach ($versions as $key => $version) {
$newInterval = true;
while ($newInterval) {
if ($nextInterval == -1 || $version['version'] >= $nextInterval) {
if ($version['version'] > $nextVersion) {
//distance between two version too small, delete version
$versionsFileview->unlink($version['path'] . '.v' . $version['version']);
\OC_Hook::emit('\OCP\Versions', 'delete', array('path' => $version['path'] . '.v' . $version['version']));
$size += $version['size'];
unset($allVersions[$key]); // update array with all versions
} else {
$nextVersion = $version['version'] - $step;
}
$newInterval = false; // version checked so we can move to the next one
} else { // time to move on to the next interval
$interval++;
$step = Storage::$max_versions_per_interval[$interval]['step'];
$nextVersion = $prevTimestamp - $step;
if (Storage::$max_versions_per_interval[$interval]['intervalEndsAfter'] == -1) {
$nextInterval = -1;
} else {
$nextInterval = $time - Storage::$max_versions_per_interval[$interval]['intervalEndsAfter'];
}
$newInterval = true; // we changed the interval -> check same version with new interval
}
}
$prevTimestamp = $version['version'];
}
}
return $size;
}
/**
* @brief create recursively missing directories
* @param string $filename $path to a file

View File

@ -0,0 +1,188 @@
<?php
/**
* ownCloud
*
* @author Bjoern Schiessle
* @copyright 2014 Bjoern Schiessle <schiessle@owncloud.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library 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 along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*/
require_once __DIR__ . '/../lib/versions.php';
/**
* Class Test_Files_versions
* @brief this class provide basic files versions test
*/
class Test_Files_Versioning extends \PHPUnit_Framework_TestCase {
/**
* @medium
* @brief test expire logic
* @dataProvider versionsProvider
*/
function testGetExpireList($versions, $sizeOfAllDeletedFiles) {
// last interval enda at 2592000
$startTime = 5000000;
$testClass = new VersionStorageToTest();
list($deleted, $size) = $testClass->callProtectedGetExpireList($startTime, $versions);
// we should have deleted 16 files each of the size 1
$this->assertEquals($sizeOfAllDeletedFiles, $size);
// the deleted array should only contain versions which should be deleted
foreach($deleted as $key => $path) {
unset($versions[$key]);
$this->assertEquals("delete", substr($path, 0, strlen("delete")));
}
// the versions array should only contain versions which should be kept
foreach ($versions as $version) {
$this->assertEquals("keep", $version['path']);
}
}
public function versionsProvider() {
return array(
// first set of versions uniformly distributed versions
array(
array(
// first slice (10sec) keep one version every 2 seconds
array("version" => 4999999, "path" => "keep", "size" => 1),
array("version" => 4999998, "path" => "delete", "size" => 1),
array("version" => 4999997, "path" => "keep", "size" => 1),
array("version" => 4999995, "path" => "keep", "size" => 1),
array("version" => 4999994, "path" => "delete", "size" => 1),
//next slice (60sec) starts at 4999990 keep one version every 10 secons
array("version" => 4999988, "path" => "keep", "size" => 1),
array("version" => 4999978, "path" => "keep", "size" => 1),
array("version" => 4999975, "path" => "delete", "size" => 1),
array("version" => 4999972, "path" => "delete", "size" => 1),
array("version" => 4999967, "path" => "keep", "size" => 1),
array("version" => 4999958, "path" => "delete", "size" => 1),
array("version" => 4999957, "path" => "keep", "size" => 1),
//next slice (3600sec) start at 4999940 keep one version every 60 seconds
array("version" => 4999900, "path" => "keep", "size" => 1),
array("version" => 4999841, "path" => "delete", "size" => 1),
array("version" => 4999840, "path" => "keep", "size" => 1),
array("version" => 4999780, "path" => "keep", "size" => 1),
array("version" => 4996401, "path" => "keep", "size" => 1),
// next slice (86400sec) start at 4996400 keep one version every 3600 seconds
array("version" => 4996350, "path" => "delete", "size" => 1),
array("version" => 4992800, "path" => "keep", "size" => 1),
array("version" => 4989800, "path" => "delete", "size" => 1),
array("version" => 4989700, "path" => "delete", "size" => 1),
array("version" => 4989200, "path" => "keep", "size" => 1),
// next slice (2592000sec) start at 4913600 keep one version every 86400 seconds
array("version" => 4913600, "path" => "keep", "size" => 1),
array("version" => 4852800, "path" => "delete", "size" => 1),
array("version" => 4827201, "path" => "delete", "size" => 1),
array("version" => 4827200, "path" => "keep", "size" => 1),
array("version" => 4777201, "path" => "delete", "size" => 1),
array("version" => 4777501, "path" => "delete", "size" => 1),
array("version" => 4740000, "path" => "keep", "size" => 1),
// final slice starts at 2408000 keep one version every 604800 secons
array("version" => 2408000, "path" => "keep", "size" => 1),
array("version" => 1803201, "path" => "delete", "size" => 1),
array("version" => 1803200, "path" => "keep", "size" => 1),
array("version" => 1800199, "path" => "delete", "size" => 1),
array("version" => 1800100, "path" => "delete", "size" => 1),
array("version" => 1198300, "path" => "keep", "size" => 1),
),
16 // size of all deleted files (every file has the size 1)
),
// second set of versions, here we have only really old versions
array(
array(
// first slice (10sec) keep one version every 2 seconds
// next slice (60sec) starts at 4999990 keep one version every 10 secons
// next slice (3600sec) start at 4999940 keep one version every 60 seconds
// next slice (86400sec) start at 4996400 keep one version every 3600 seconds
array("version" => 4996400, "path" => "keep", "size" => 1),
array("version" => 4996350, "path" => "delete", "size" => 1),
array("version" => 4996350, "path" => "delete", "size" => 1),
array("version" => 4992800, "path" => "keep", "size" => 1),
array("version" => 4989800, "path" => "delete", "size" => 1),
array("version" => 4989700, "path" => "delete", "size" => 1),
array("version" => 4989200, "path" => "keep", "size" => 1),
// next slice (2592000sec) start at 4913600 keep one version every 86400 seconds
array("version" => 4913600, "path" => "keep", "size" => 1),
array("version" => 4852800, "path" => "delete", "size" => 1),
array("version" => 4827201, "path" => "delete", "size" => 1),
array("version" => 4827200, "path" => "keep", "size" => 1),
array("version" => 4777201, "path" => "delete", "size" => 1),
array("version" => 4777501, "path" => "delete", "size" => 1),
array("version" => 4740000, "path" => "keep", "size" => 1),
// final slice starts at 2408000 keep one version every 604800 secons
array("version" => 2408000, "path" => "keep", "size" => 1),
array("version" => 1803201, "path" => "delete", "size" => 1),
array("version" => 1803200, "path" => "keep", "size" => 1),
array("version" => 1800199, "path" => "delete", "size" => 1),
array("version" => 1800100, "path" => "delete", "size" => 1),
array("version" => 1198300, "path" => "keep", "size" => 1),
),
11 // size of all deleted files (every file has the size 1)
),
// third set of versions, with some gaps inbetween
array(
array(
// first slice (10sec) keep one version every 2 seconds
array("version" => 4999999, "path" => "keep", "size" => 1),
array("version" => 4999998, "path" => "delete", "size" => 1),
array("version" => 4999997, "path" => "keep", "size" => 1),
array("version" => 4999995, "path" => "keep", "size" => 1),
array("version" => 4999994, "path" => "delete", "size" => 1),
//next slice (60sec) starts at 4999990 keep one version every 10 secons
array("version" => 4999988, "path" => "keep", "size" => 1),
array("version" => 4999978, "path" => "keep", "size" => 1),
//next slice (3600sec) start at 4999940 keep one version every 60 seconds
// next slice (86400sec) start at 4996400 keep one version every 3600 seconds
array("version" => 4989200, "path" => "keep", "size" => 1),
// next slice (2592000sec) start at 4913600 keep one version every 86400 seconds
array("version" => 4913600, "path" => "keep", "size" => 1),
array("version" => 4852800, "path" => "delete", "size" => 1),
array("version" => 4827201, "path" => "delete", "size" => 1),
array("version" => 4827200, "path" => "keep", "size" => 1),
array("version" => 4777201, "path" => "delete", "size" => 1),
array("version" => 4777501, "path" => "delete", "size" => 1),
array("version" => 4740000, "path" => "keep", "size" => 1),
// final slice starts at 2408000 keep one version every 604800 secons
array("version" => 2408000, "path" => "keep", "size" => 1),
array("version" => 1803201, "path" => "delete", "size" => 1),
array("version" => 1803200, "path" => "keep", "size" => 1),
array("version" => 1800199, "path" => "delete", "size" => 1),
array("version" => 1800100, "path" => "delete", "size" => 1),
array("version" => 1198300, "path" => "keep", "size" => 1),
),
9 // size of all deleted files (every file has the size 1)
),
);
}
}
// extend the original class to make it possible to test protected methods
class VersionStorageToTest extends \OCA\Files_Versions\Storage {
public function callProtectedGetExpireList($time, $versions) {
return self::getExpireList($time, $versions);
}
}

View File

@ -48,18 +48,25 @@ class Helper {
static public function getServerConfigurationPrefixes($activeConfigurations = false) {
$referenceConfigkey = 'ldap_configuration_active';
$query = '
$sql = '
SELECT DISTINCT `configkey`
FROM `*PREFIX*appconfig`
WHERE `appid` = \'user_ldap\'
AND `configkey` LIKE ?
';
if($activeConfigurations) {
$query .= ' AND `configvalue` = \'1\'';
}
$query = \OCP\DB::prepare($query);
$serverConfigs = $query->execute(array('%'.$referenceConfigkey))->fetchAll();
if($activeConfigurations) {
if (\OC_Config::getValue( 'dbtype', 'sqlite' ) === 'oci') {
//FIXME oracle hack: need to explicitly cast CLOB to CHAR for comparison
$sql .= ' AND to_char(`configvalue`)=\'1\'';
} else {
$sql .= ' AND `configvalue` = \'1\'';
}
}
$stmt = \OCP\DB::prepare($sql);
$serverConfigs = $stmt->execute(array('%'.$referenceConfigkey))->fetchAll();
$prefixes = array();
foreach($serverConfigs as $serverConfig) {

View File

@ -416,6 +416,9 @@ var OC={
throw e;
});
}
if(!SVGSupport()) {
replaceSVG();
}
}).show();
}, 'html');
}

View File

@ -57,6 +57,9 @@ class OC {
* web path in 'url'
*/
public static $APPSROOTS = array();
public static $configDir;
/*
* requested app
*/
@ -100,6 +103,13 @@ class OC {
get_include_path()
);
if(defined('PHPUNIT_RUN') and PHPUNIT_RUN and is_dir(OC::$SERVERROOT . '/tests/config/')) {
self::$configDir = OC::$SERVERROOT . '/tests/config/';
} else {
self::$configDir = OC::$SERVERROOT . '/config/';
}
OC_Config::$object = new \OC\Config(self::$configDir);
OC::$SUBURI = str_replace("\\", "/", substr(realpath($_SERVER["SCRIPT_FILENAME"]), strlen(OC::$SERVERROOT)));
$scriptName = OC_Request::scriptName();
if (substr($scriptName, -1) == '/') {
@ -175,8 +185,8 @@ class OC {
}
public static function checkConfig() {
if (file_exists(OC::$SERVERROOT . "/config/config.php")
and !is_writable(OC::$SERVERROOT . "/config/config.php")
if (file_exists(self::$configDir . "/config.php")
and !is_writable(self::$configDir . "/config.php")
) {
$defaults = new OC_Defaults();
if (self::$CLI) {

View File

@ -555,6 +555,10 @@ class OC_App{
}elseif($child->getName()=='description') {
$xml=(string)$child->asXML();
$data[$child->getName()]=substr($xml, 13, -14);//script <description> tags
}elseif($child->getName()=='documentation') {
foreach($child as $subchild) {
$data["documentation"][$subchild->getName()] = (string)$subchild;
}
}else{
$data[$child->getName()]=(string)$child;
}

View File

@ -50,7 +50,7 @@ class Config {
protected $debugMode;
/**
* @param $configDir path to the config dir, needs to end with '/'
* @param string $configDir path to the config dir, needs to end with '/'
*/
public function __construct($configDir) {
$this->configDir = $configDir;

View File

@ -83,7 +83,7 @@ class OC_Files {
if ($basename) {
$name = $basename . '.zip';
} else {
$name = 'owncloud.zip';
$name = 'download.zip';
}
set_time_limit($executionTime);

View File

@ -40,7 +40,7 @@ class Watcher {
* check $path for updates
*
* @param string $path
* @return boolean true if path was updated, false otherwise
* @return boolean | array true if path was updated, otherwise the cached data is returned
*/
public function checkUpdate($path) {
$cachedEntry = $this->cache->get($path);
@ -56,7 +56,7 @@ class Watcher {
$this->cache->correctFolderSize($path);
return true;
}
return false;
return $cachedEntry;
}
/**

View File

@ -95,7 +95,7 @@ class Quota extends Wrapper {
public function fopen($path, $mode) {
$source = $this->storage->fopen($path, $mode);
$free = $this->free_space('');
if ($free >= 0 && $mode !== 'r') {
if ($source && $free >= 0 && $mode !== 'r' && $mode !== 'rb') {
return \OC\Files\Stream\Quota::wrap($source, $free);
} else {
return $source;

View File

@ -801,6 +801,7 @@ class View {
* @var string $internalPath
*/
list($storage, $internalPath) = Filesystem::resolvePath($path);
$data = null;
if ($storage) {
$cache = $storage->getCache($internalPath);
$permissionsCache = $storage->getPermissionsCache($internalPath);
@ -811,10 +812,12 @@ class View {
$scanner->scan($internalPath, Cache\Scanner::SCAN_SHALLOW);
} else {
$watcher = $storage->getWatcher($internalPath);
$watcher->checkUpdate($internalPath);
$data = $watcher->checkUpdate($internalPath);
}
$data = $cache->get($internalPath);
if (!is_array($data)) {
$data = $cache->get($internalPath);
}
if ($data and $data['fileid']) {
if ($includeMountPoints and $data['mimetype'] === 'httpd/unix-directory') {

View File

@ -407,6 +407,9 @@ class OC_Installer{
include OC_App::getAppPath($app)."/appinfo/install.php";
}
$info=OC_App::getAppInfo($app);
if (is_null($info)) {
return false;
}
OC_Appconfig::setValue($app, 'installed_version', OC_App::getAppVersion($app));
//set remote/public handelers

View File

@ -64,6 +64,20 @@ class OC_JSON{
}
}
/**
* Check is a given user exists - send json error msg if not
* @param string $user
*/
public static function checkUserExists($user) {
if (!OCP\User::userExists($user)) {
$l = OC_L10N::get('lib');
OCP\JSON::error(array('data' => array('message' => $l->t('Unknown user'))));
exit;
}
}
/**
* Check if the user is a subadmin, send json error msg if not
*/

View File

@ -38,7 +38,6 @@
* This class is responsible for reading and writing config.php, the very basic
* configuration file of ownCloud.
*/
OC_Config::$object = new \OC\Config(OC::$SERVERROOT.'/config/');
class OC_Config {
/**

View File

@ -22,7 +22,7 @@ class CSSResourceLocator extends ResourceLocator {
$app = substr($style, 0, strpos($style, '/'));
$style = substr($style, strpos($style, '/')+1);
$app_path = \OC_App::getAppPath($app);
$app_url = \OC_App::getAppWebPath($app);
$app_url = $this->webroot . '/index.php/apps/' . $app;
if ($this->appendIfExist($app_path, $style.$this->form_factor.'.css', $app_url)
|| $this->appendIfExist($app_path, $style.'.css', $app_url)
) {

View File

@ -51,6 +51,10 @@ class OC_Util {
self::$rootMounted = true;
}
if ($user != '' && !OCP\User::userExists($user)) {
return false;
}
//if we aren't logged in, there is no use to set up the filesystem
if( $user != "" ) {
\OC\Files\Filesystem::addStorageWrapper(function($mountPoint, $storage){
@ -312,7 +316,7 @@ class OC_Util {
.'" target="_blank">giving the webserver write access to the root directory</a>.';
// Check if config folder is writable.
if(!is_writable(OC::$SERVERROOT."/config/") or !is_readable(OC::$SERVERROOT."/config/")) {
if(!is_writable(OC::$configDir) or !is_readable(OC::$configDir)) {
$errors[] = array(
'error' => "Can't write into config directory",
'hint' => 'This can usually be fixed by '
@ -892,6 +896,11 @@ class OC_Util {
return false;
}
// in case the connection is via proxy return true to avoid connecting to owncloud.org
if(OC_Config::getValue('proxy', '') != '') {
return true;
}
// try to connect to owncloud.org to see if http connections to the internet are possible.
$connected = @fsockopen("www.owncloud.org", 80);
if ($connected) {

View File

@ -167,7 +167,7 @@ class JSON {
* @return string json formatted string if not admin user.
*/
public static function checkAdminUser() {
return(\OC_JSON::checkAdminUser());
\OC_JSON::checkAdminUser();
}
/**
@ -177,4 +177,12 @@ class JSON {
public static function encode($data) {
return(\OC_JSON::encode($data));
}
/**
* Check is a given user exists - send json error msg if not
* @param string $user
*/
public static function checkUserExists($user) {
\OC_JSON::checkUserExists($user);
}
}

View File

@ -347,20 +347,29 @@ class Share {
}
/**
* Get the item shared by a token
* @param string token
* @return Item
* Based on the given token the share information will be returned - password protected shares will be verified
* @param string $token
* @return array | bool false will be returned in case the token is unknown or unauthorized
*/
public static function getShareByToken($token) {
public static function getShareByToken($token, $checkPasswordProtection = true) {
$query = \OC_DB::prepare('SELECT * FROM `*PREFIX*share` WHERE `token` = ?', 1);
$result = $query->execute(array($token));
if (\OC_DB::isError($result)) {
\OC_Log::write('OCP\Share', \OC_DB::getErrorMessage($result) . ', token=' . $token, \OC_Log::ERROR);
}
$row = $result->fetchRow();
if ($row === false) {
return false;
}
if (is_array($row) and self::expireItem($row)) {
return false;
}
// password protected shares need to be authenticated
if ($checkPasswordProtection && !\OCP\Share::checkPasswordProtectedShare($row)) {
return false;
}
return $row;
}
@ -655,7 +664,15 @@ class Share {
* @return Returns true on success or false on failure
*/
public static function unshareAll($itemType, $itemSource) {
if ($shares = self::getItemShared($itemType, $itemSource)) {
// Get all of the owners of shares of this item.
$query = \OC_DB::prepare( 'SELECT `uid_owner` from `*PREFIX*share` WHERE `item_type`=? AND `item_source`=?' );
$result = $query->execute(array($itemType, $itemSource));
$shares = array();
// Add each owner's shares to the array of all shares for this item.
while ($row = $result->fetchRow()) {
$shares = array_merge($shares, self::getItems($itemType, $itemSource, null, null, $row['uid_owner']));
}
if (!empty($shares)) {
// Pass all the vars we have for now, they may be useful
$hookParams = array(
'itemType' => $itemType,
@ -1880,6 +1897,34 @@ class Share {
}
}
/**
* In case a password protected link is not yet authenticated this function will return false
*
* @param array $linkItem
* @return bool
*/
public static function checkPasswordProtectedShare(array $linkItem) {
if (!isset($linkItem['share_with'])) {
return true;
}
if (!isset($linkItem['share_type'])) {
return true;
}
if (!isset($linkItem['id'])) {
return true;
}
if ($linkItem['share_type'] != \OCP\Share::SHARE_TYPE_LINK) {
return true;
}
if ( \OC::$session->exists('public_link_authenticated')
&& \OC::$session->get('public_link_authenticated') === $linkItem['id'] ) {
return true;
}
return false;
}
}
/**

View File

@ -131,6 +131,12 @@ span.version { margin-left:1em; margin-right:1em; color:#555; }
.appslink { text-decoration: underline; }
.score { color:#666; font-weight:bold; font-size:0.8em; }
.appinfo .documentation {
margin-top: 1em;
margin-bottom: 1em;
}
/* LOG */
#log { white-space:normal; }
#lessLog { display:none; }

View File

@ -37,6 +37,30 @@ OC.Settings.Apps = OC.Settings.Apps || {
}
page.find('span.licence').text(appLicense);
var userDocumentation = false;
var adminDocumentation = false;
if (typeof(app.documentation) !== 'undefined') {
if (typeof(app.documentation.user) !== 'undefined') {
userDocumentation = true;
page.find('span.userDocumentation').html("<a id='userDocumentation' href='" + app.documentation.user + "'>" + t('settings', 'User Documentation') + "</a>");
page.find('p.documentation').show();
}
if (typeof(app.documentation.admin) !== 'undefined') {
adminDocumentation = true;
page.find('span.adminDocumentation').html("<a id='adminDocumentation' href='" + app.documentation.admin + "'>" + t('settings', 'Admin Documentation') + "</a>");
page.find('p.documentation').show();
}
if(userDocumentation && adminDocumentation) {
page.find('span.userDocumentation').after(', ');
}
}
if (typeof(app.website) !== 'undefined') {
page.find('p.website').show();
page.find('a#websitelink').attr('href', app.website);
}
if (app.update !== false) {
page.find('input.update').show();
page.find('input.update').data('appid', app.id);
@ -51,8 +75,8 @@ OC.Settings.Apps = OC.Settings.Apps || {
page.find('input.enable').data('active', app.active);
if (app.internal === false) {
page.find('span.score').show();
page.find('p.appslink').show();
page.find('a').attr('href', 'http://apps.owncloud.com/content/show.php?content=' + app.id);
page.find('p.appstore').show();
page.find('a#appstorelink').attr('href', 'http://apps.owncloud.com/content/show.php?content=' + app.id);
page.find('small.externalapp').hide();
} else {
page.find('p.appslink').hide();
@ -110,7 +134,7 @@ OC.Settings.Apps = OC.Settings.Apps || {
element.val(t('settings','Disable'));
}
},'json')
.fail(function() {
.fail(function() {
OC.Settings.Apps.showErrorMessage(t('settings', 'Error while enabling app'));
appitem.data('errormsg', t('settings', 'Error while enabling app'));
appitem.data('active',false);

View File

@ -44,7 +44,7 @@ var UserList = {
// Provide user with option to undo
$('#notification').data('deleteuser', true);
OC.Notification.showHtml(t('users', 'deleted') + ' ' + escapeHTML(uid) + '<span class="undo">' + t('users', 'undo') + '</span>');
OC.Notification.showHtml(t('settings', 'deleted') + ' ' + escapeHTML(uid) + '<span class="undo">' + t('settings', 'undo') + '</span>');
},
/**

View File

@ -34,9 +34,16 @@
class="version"></span><small class="externalapp" style="visibility:hidden;"></small></h3>
<span class="score"></span>
<p class="description"></p>
<p class="documentation hidden">
<?php p($l->t("Documentation:"));?>
<span class="userDocumentation appslink"></span>
<span class="adminDocumentation appslink"></span>
</p>
<img src="" class="preview hidden" />
<p class="appslink hidden"><a href="#" target="_blank"><?php
<p class="appslink appstore hidden"><a id="appstorelink" href="#" target="_blank"><?php
p($l->t('See application page at apps.owncloud.com'));?></a></p>
<p class="appslink website hidden"><a id="websitelink" href="#" target="_blank"><?php
p($l->t('See application website'));?></a></p>
<p class="license hidden"><?php
print_unescaped($l->t('<span class="licence"></span>-licensed by <span class="author"></span>'));?></p>
<input class="enable hidden" type="submit" />

View File

@ -21,6 +21,7 @@
<autoincrement>1</autoincrement>
<unsigned>true</unsigned>
<length>4</length>
<comments>This is the id</comments>
</field>
<field>

View File

@ -8,16 +8,17 @@
require_once __DIR__.'/../lib/base.php';
OC_App::enable('files_sharing');
OC_App::enable('files_encryption');
OC_App::enable('user_ldap');
OC_App::enable('calendar');
OC_App::enable('contacts');
OC_App::enable('apptemplateadvanced');
OC_App::enable('appframework');
#OC_App::enable('files_archive');
#OC_App::enable('mozilla_sync');
#OC_App::enable('news');
#OC_App::enable('provisioning_api');
#OC_App::enable('user_external');
function enableApp($app) {
try {
OC_App::enable($app);
} catch (Exception $e) {
echo $e;
}
}
enableApp('files_sharing');
enableApp('files_encryption');
//enableApp('files_external');
enableApp('user_ldap');
enableApp('files_versions');

View File

@ -169,8 +169,9 @@ class Cache extends \PHPUnit_Framework_TestCase {
$this->assertEquals(916, $this->cache->calculateFolderSize($file1));
// direct cache entry retrieval returns the original values
$this->assertEquals(1025, $this->cache->get($file1)['size']);
$this->assertEquals(916, $this->cache->get($file1)['unencrypted_size']);
$entry = $this->cache->get($file1);
$this->assertEquals(1025, $entry['size']);
$this->assertEquals(916, $entry['unencrypted_size']);
$this->cache->remove($file2);
$this->cache->remove($file3);

View File

@ -59,6 +59,20 @@ class Quota extends \Test\Files\Storage\Storage {
$this->assertEquals('foobarqwe', $instance->file_get_contents('foo'));
}
public function testReturnFalseWhenFopenFailed(){
$failStorage = $this->getMock(
'\OC\Files\Storage\Local',
array('fopen'),
array(array('datadir' => $this->tmpDir)));
$failStorage->expects($this->any())
->method('fopen')
->will($this->returnValue(false));
$instance = new \OC\Files\Storage\Wrapper\Quota(array('storage' => $failStorage, 'quota' => 1000));
$this->assertFalse($instance->fopen('failedfopen', 'r'));
}
public function testReturnRegularStreamOnRead(){
$instance = $this->getLimitedStorage(9);
@ -71,6 +85,11 @@ class Quota extends \Test\Files\Storage\Storage {
$meta = stream_get_meta_data($stream);
$this->assertEquals('plainfile', $meta['wrapper_type']);
fclose($stream);
$stream = $instance->fopen('foo', 'rb');
$meta = stream_get_meta_data($stream);
$this->assertEquals('plainfile', $meta['wrapper_type']);
fclose($stream);
}
public function testReturnQuotaStreamOnWrite(){

View File

@ -25,6 +25,8 @@ class Test_Share extends PHPUnit_Framework_TestCase {
protected $userBackend;
protected $user1;
protected $user2;
protected $user3;
protected $user4;
protected $groupBackend;
protected $group1;
protected $group2;
@ -149,6 +151,26 @@ class Test_Share extends PHPUnit_Framework_TestCase {
);
}
protected function shareUserTestFileWithUser($sharer, $receiver) {
OC_User::setUserId($sharer);
$this->assertTrue(
OCP\Share::shareItem('test', 'test.txt', OCP\Share::SHARE_TYPE_USER, $receiver, OCP\PERMISSION_READ | OCP\PERMISSION_SHARE),
'Failed asserting that ' . $sharer . ' successfully shared text.txt with ' . $receiver . '.'
);
$this->assertContains(
'test.txt',
OCP\Share::getItemShared('test', 'test.txt', Test_Share_Backend::FORMAT_SOURCE),
'Failed asserting that test.txt is a shared file of ' . $sharer . '.'
);
OC_User::setUserId($receiver);
$this->assertContains(
'test.txt',
OCP\Share::getItemSharedWith('test', 'test.txt', Test_Share_Backend::FORMAT_SOURCE),
'Failed asserting that ' . $receiver . ' has access to test.txt after initial sharing.'
);
}
public function testShareWithUser() {
// Invalid shares
$message = 'Sharing test.txt failed, because the user '.$this->user1.' is the item owner';
@ -585,25 +607,95 @@ class Test_Share extends PHPUnit_Framework_TestCase {
}
public function testUnshareAll() {
$this->shareUserOneTestFileWithUserTwo();
$this->shareUserTestFileWithUser($this->user1, $this->user2);
$this->shareUserTestFileWithUser($this->user2, $this->user3);
$this->shareUserTestFileWithUser($this->user3, $this->user4);
$this->shareUserOneTestFileWithGroupOne();
OC_User::setUserId($this->user1);
$this->assertEquals(
array('test.txt', 'test.txt'),
OCP\Share::getItemsShared('test', 'test.txt'),
'Failed asserting that the test.txt file is shared exactly two times.'
'Failed asserting that the test.txt file is shared exactly two times by user1.'
);
OC_User::setUserId($this->user2);
$this->assertEquals(
array('test.txt'),
OCP\Share::getItemsShared('test', 'test.txt'),
'Failed asserting that the test.txt file is shared exactly once by user2.'
);
OC_User::setUserId($this->user3);
$this->assertEquals(
array('test.txt'),
OCP\Share::getItemsShared('test', 'test.txt'),
'Failed asserting that the test.txt file is shared exactly once by user3.'
);
$this->assertTrue(
OCP\Share::unshareAll('test', 'test.txt'),
'Failed asserting that user 1 successfully unshared all shares of the test.txt share.'
'Failed asserting that user 3 successfully unshared all shares of the test.txt share.'
);
$this->assertEquals(
array(),
OCP\Share::getItemsShared('test'),
'Failed asserting that both shares of the test.txt file have been removed.'
'Failed asserting that the share of the test.txt file by user 3 has been removed.'
);
OC_User::setUserId($this->user1);
$this->assertEquals(
array(),
OCP\Share::getItemsShared('test'),
'Failed asserting that both shares of the test.txt file by user 1 have been removed.'
);
OC_User::setUserId($this->user2);
$this->assertEquals(
array(),
OCP\Share::getItemsShared('test'),
'Failed asserting that the share of the test.txt file by user 2 has been removed.'
);
}
/**
* @dataProvider checkPasswordProtectedShareDataProvider
* @param $expected
* @param $item
*/
public function testCheckPasswordProtectedShare($expected, $item) {
\OC::$session->set('public_link_authenticated', 100);
$result = \OCP\Share::checkPasswordProtectedShare($item);
$this->assertEquals($expected, $result);
}
function checkPasswordProtectedShareDataProvider() {
return array(
array(true, array()),
array(true, array('share_with' => null)),
array(true, array('share_with' => '')),
array(true, array('share_with' => '1234567890', 'share_type' => '1')),
array(true, array('share_with' => '1234567890', 'share_type' => 1)),
array(true, array('share_with' => '1234567890', 'share_type' => '3', 'id' => 100)),
array(true, array('share_with' => '1234567890', 'share_type' => 3, 'id' => 100)),
array(false, array('share_with' => '1234567890', 'share_type' => '3', 'id' => 101)),
array(false, array('share_with' => '1234567890', 'share_type' => 3, 'id' => 101)),
);
/*
if (!isset($linkItem['share_with'])) {
return true;
}
if ($linkItem['share_type'] != \OCP\Share::SHARE_TYPE_LINK) {
return true;
}
if ( \OC::$session->exists('public_link_authenticated')
&& \OC::$session->get('public_link_authenticated') === $linkItem['id'] ) {
return true;
}
* */
}
}