Merge branch 'master' into storagestatistics-reuse
This commit is contained in:
commit
753af3a3ff
41 changed files with 736 additions and 191 deletions
|
@ -4,7 +4,9 @@
|
|||
A personal cloud which runs on your own server.
|
||||
|
||||
### Build Status on [Jenkins CI](https://ci.owncloud.org/)
|
||||
Git master: [![Build Status](https://ci.owncloud.org/buildStatus/icon?job=ownCloud-Server%28master%29)](https://ci.owncloud.org/job/ownCloud-Server%28master%29/)
|
||||
Git master: [![Build Status](https://ci.owncloud.org/job/server-master-linux/badge/icon)](https://ci.owncloud.org/job/server-master-linux/)
|
||||
|
||||
Quality: [![Scrutinizer Quality Score](https://scrutinizer-ci.com/g/owncloud/core/badges/quality-score.png?s=ce2f5ded03d4ac628e9ee5c767243fa7412e644f)](https://scrutinizer-ci.com/g/owncloud/core/)
|
||||
|
||||
### Installation instructions
|
||||
http://doc.owncloud.org/server/5.0/developer_manual/app/gettingstarted.html
|
||||
|
|
|
@ -139,7 +139,8 @@ if (strpos($dir, '..') === false) {
|
|||
'originalname' => $files['tmp_name'][$i],
|
||||
'uploadMaxFilesize' => $maxUploadFileSize,
|
||||
'maxHumanFilesize' => $maxHumanFileSize,
|
||||
'permissions' => $meta['permissions'] & $allowedPermissions
|
||||
'permissions' => $meta['permissions'] & $allowedPermissions,
|
||||
'directory' => \OC\Files\Filesystem::normalizePath(stripslashes($dir)),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -166,7 +167,8 @@ if (strpos($dir, '..') === false) {
|
|||
'originalname' => $files['tmp_name'][$i],
|
||||
'uploadMaxFilesize' => $maxUploadFileSize,
|
||||
'maxHumanFilesize' => $maxHumanFileSize,
|
||||
'permissions' => $meta['permissions'] & $allowedPermissions
|
||||
'permissions' => $meta['permissions'] & $allowedPermissions,
|
||||
'directory' => \OC\Files\Filesystem::normalizePath(stripslashes($dir)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,7 +40,8 @@ window.FileList={
|
|||
}
|
||||
FileList.updateFileSummary();
|
||||
procesSelection();
|
||||
|
||||
|
||||
$(window).scrollTop(0);
|
||||
$fileList.trigger(jQuery.Event("updated"));
|
||||
},
|
||||
createRow:function(type, name, iconurl, linktarget, size, lastModified, permissions) {
|
||||
|
@ -407,7 +408,7 @@ window.FileList={
|
|||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
form.submit(function(event) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
|
@ -434,10 +435,9 @@ window.FileList={
|
|||
tr.attr('data-file', newname);
|
||||
var path = td.children('a.name').attr('href');
|
||||
td.children('a.name').attr('href', path.replace(encodeURIComponent(oldname), encodeURIComponent(newname)));
|
||||
var basename = newname;
|
||||
if (newname.indexOf('.') > 0 && tr.data('type') !== 'dir') {
|
||||
var basename=newname.substr(0,newname.lastIndexOf('.'));
|
||||
} else {
|
||||
var basename=newname;
|
||||
basename = newname.substr(0,newname.lastIndexOf('.'));
|
||||
}
|
||||
td.find('a.name span.nametext').text(basename);
|
||||
if (newname.indexOf('.') > 0 && tr.data('type') !== 'dir') {
|
||||
|
@ -481,7 +481,7 @@ window.FileList={
|
|||
var basename = newname;
|
||||
if (newname.indexOf('.') > 0 && tr.data('type') !== 'dir') {
|
||||
basename = newname.substr(0, newname.lastIndexOf('.'));
|
||||
}
|
||||
}
|
||||
td.find('a.name span.nametext').text(basename);
|
||||
if (newname.indexOf('.') > 0 && tr.data('type') !== 'dir') {
|
||||
if ( ! td.find('a.name span.extension').exists() ) {
|
||||
|
@ -543,10 +543,9 @@ window.FileList={
|
|||
td.children('a.name .span').text(newName);
|
||||
var path = td.children('a.name').attr('href');
|
||||
td.children('a.name').attr('href', path.replace(encodeURIComponent(oldName), encodeURIComponent(newName)));
|
||||
var basename = newName;
|
||||
if (newName.indexOf('.') > 0) {
|
||||
var basename = newName.substr(0, newName.lastIndexOf('.'));
|
||||
} else {
|
||||
var basename = newName;
|
||||
basename = newName.substr(0, newName.lastIndexOf('.'));
|
||||
}
|
||||
td.children('a.name').empty();
|
||||
var span = $('<span class="nametext"></span>');
|
||||
|
@ -886,7 +885,7 @@ $(document).ready(function() {
|
|||
*/
|
||||
file_upload_start.on('fileuploaddone', function(e, data) {
|
||||
OC.Upload.log('filelist handle fileuploaddone', e, data);
|
||||
|
||||
|
||||
var response;
|
||||
if (typeof data.result === 'string') {
|
||||
response = data.result;
|
||||
|
@ -923,8 +922,8 @@ $(document).ready(function() {
|
|||
data.context.find('td.filesize').text(humanFileSize(size));
|
||||
|
||||
} else {
|
||||
// only append new file if dragged onto current dir's crumb (last)
|
||||
if (data.context && data.context.hasClass('crumb') && !data.context.hasClass('last')) {
|
||||
// only append new file if uploaded into the current folder
|
||||
if (file.directory !== FileList.getCurrentDirectory()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -405,7 +405,7 @@ $(document).ready(function() {
|
|||
Files.resizeBreadcrumbs(width, true);
|
||||
|
||||
// display storage warnings
|
||||
setTimeout ( "Files.displayStorageWarnings()", 100 );
|
||||
setTimeout(Files.displayStorageWarnings, 100);
|
||||
OC.Notification.setDefault(Files.displayStorageWarnings);
|
||||
|
||||
// only possible at the moment if user is logged in
|
||||
|
|
|
@ -32,6 +32,8 @@ class Hooks {
|
|||
|
||||
// file for which we want to rename the keys after the rename operation was successful
|
||||
private static $renamedFiles = array();
|
||||
// file for which we want to delete the keys after the delete operation was successful
|
||||
private static $deleteFiles = array();
|
||||
|
||||
/**
|
||||
* @brief Startup encryption backend upon user login
|
||||
|
@ -78,8 +80,15 @@ class Hooks {
|
|||
|
||||
// Check if first-run file migration has already been performed
|
||||
$ready = false;
|
||||
if ($util->getMigrationStatus() === Util::MIGRATION_OPEN) {
|
||||
$migrationStatus = $util->getMigrationStatus();
|
||||
if ($migrationStatus === Util::MIGRATION_OPEN) {
|
||||
$ready = $util->beginMigration();
|
||||
} elseif ($migrationStatus === Util::MIGRATION_IN_PROGRESS) {
|
||||
// refuse login as long as the initial encryption is running
|
||||
while ($migrationStatus === Util::MIGRATION_IN_PROGRESS) {
|
||||
sleep(60);
|
||||
$migrationStatus = $util->getMigrationStatus();
|
||||
}
|
||||
}
|
||||
|
||||
// If migration not yet done
|
||||
|
@ -630,4 +639,66 @@ class Hooks {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief if the file was really deleted we remove the encryption keys
|
||||
* @param array $params
|
||||
* @return boolean
|
||||
*/
|
||||
public static function postDelete($params) {
|
||||
|
||||
if (!isset(self::$deleteFiles[$params[\OC\Files\Filesystem::signal_param_path]])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$deletedFile = self::$deleteFiles[$params[\OC\Files\Filesystem::signal_param_path]];
|
||||
$path = $deletedFile['path'];
|
||||
$user = $deletedFile['uid'];
|
||||
|
||||
// we don't need to remember the file any longer
|
||||
unset(self::$deleteFiles[$params[\OC\Files\Filesystem::signal_param_path]]);
|
||||
|
||||
$view = new \OC\Files\View('/');
|
||||
|
||||
// return if the file still exists and wasn't deleted correctly
|
||||
if ($view->file_exists('/' . $user . '/files/' . $path)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Disable encryption proxy to prevent recursive calls
|
||||
$proxyStatus = \OC_FileProxy::$enabled;
|
||||
\OC_FileProxy::$enabled = false;
|
||||
|
||||
// Delete keyfile & shareKey so it isn't orphaned
|
||||
if (!Keymanager::deleteFileKey($view, $path, $user)) {
|
||||
\OCP\Util::writeLog('Encryption library',
|
||||
'Keyfile or shareKey could not be deleted for file "' . $user.'/files/'.$path . '"', \OCP\Util::ERROR);
|
||||
}
|
||||
|
||||
Keymanager::delAllShareKeys($view, $user, $path);
|
||||
|
||||
\OC_FileProxy::$enabled = $proxyStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief remember the file which should be deleted and it's owner
|
||||
* @param array $params
|
||||
* @return boolean
|
||||
*/
|
||||
public static function preDelete($params) {
|
||||
$path = $params[\OC\Files\Filesystem::signal_param_path];
|
||||
|
||||
// skip this method if the trash bin is enabled or if we delete a file
|
||||
// outside of /data/user/files
|
||||
if (\OCP\App::isEnabled('files_trashbin')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$util = new Util(new \OC_FilesystemView('/'), \OCP\USER::getUser());
|
||||
list($owner, $ownerPath) = $util->getUidAndFilename($path);
|
||||
|
||||
self::$deleteFiles[$params[\OC\Files\Filesystem::signal_param_path]] = array(
|
||||
'uid' => $owner,
|
||||
'path' => $ownerPath);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -63,6 +63,8 @@ class Helper {
|
|||
|
||||
\OCP\Util::connectHook('OC_Filesystem', 'rename', 'OCA\Encryption\Hooks', 'preRename');
|
||||
\OCP\Util::connectHook('OC_Filesystem', 'post_rename', 'OCA\Encryption\Hooks', 'postRename');
|
||||
\OCP\Util::connectHook('OC_Filesystem', 'post_delete', 'OCA\Encryption\Hooks', 'postDelete');
|
||||
\OCP\Util::connectHook('OC_Filesystem', 'delete', 'OCA\Encryption\Hooks', 'preDelete');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -214,15 +214,24 @@ class Keymanager {
|
|||
*
|
||||
* @param \OC_FilesystemView $view
|
||||
* @param string $path path of the file the key belongs to
|
||||
* @param string $userId the user to whom the file belongs
|
||||
* @return bool Outcome of unlink operation
|
||||
* @note $path must be relative to data/user/files. e.g. mydoc.txt NOT
|
||||
* /data/admin/files/mydoc.txt
|
||||
*/
|
||||
public static function deleteFileKey(\OC_FilesystemView $view, $path) {
|
||||
public static function deleteFileKey($view, $path, $userId=null) {
|
||||
|
||||
$trimmed = ltrim($path, '/');
|
||||
|
||||
$userId = Helper::getUser($path);
|
||||
if ($trimmed === '') {
|
||||
\OCP\Util::writeLog('Encryption library',
|
||||
'Can\'t delete file-key empty path given!', \OCP\Util::ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($userId === null) {
|
||||
$userId = Helper::getUser($path);
|
||||
}
|
||||
$util = new Util($view, $userId);
|
||||
|
||||
if($util->isSystemWideMountPoint($path)) {
|
||||
|
@ -402,7 +411,15 @@ class Keymanager {
|
|||
* @param string $userId owner of the file
|
||||
* @param string $filePath path to the file, relative to the owners file dir
|
||||
*/
|
||||
public static function delAllShareKeys(\OC_FilesystemView $view, $userId, $filePath) {
|
||||
public static function delAllShareKeys($view, $userId, $filePath) {
|
||||
|
||||
$filePath = ltrim($filePath, '/');
|
||||
|
||||
if ($filePath === '') {
|
||||
\OCP\Util::writeLog('Encryption library',
|
||||
'Can\'t delete share-keys empty path given!', \OCP\Util::ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
$util = new util($view, $userId);
|
||||
|
||||
|
@ -413,17 +430,15 @@ class Keymanager {
|
|||
}
|
||||
|
||||
|
||||
if ($view->is_dir($userId . '/files/' . $filePath)) {
|
||||
if ($view->is_dir($baseDir . $filePath)) {
|
||||
$view->unlink($baseDir . $filePath);
|
||||
} else {
|
||||
$localKeyPath = $view->getLocalFile($baseDir . $filePath);
|
||||
$escapedPath = Helper::escapeGlobPattern($localKeyPath);
|
||||
$matches = glob($escapedPath . '*.shareKey');
|
||||
foreach ($matches as $ma) {
|
||||
$result = unlink($ma);
|
||||
if (!$result) {
|
||||
\OCP\Util::writeLog('Encryption library',
|
||||
'Keyfile or shareKey could not be deleted for file "' . $filePath . '"', \OCP\Util::ERROR);
|
||||
$parentDir = dirname($baseDir . $filePath);
|
||||
$filename = pathinfo($filePath, PATHINFO_BASENAME);
|
||||
foreach($view->getDirectoryContent($parentDir) as $content) {
|
||||
$path = $content['path'];
|
||||
if (self::getFilenameFromShareKey($content['name']) === $filename) {
|
||||
$view->unlink('/' . $userId . '/' . $path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -523,4 +538,20 @@ class Keymanager {
|
|||
return $targetPath;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief extract filename from share key name
|
||||
* @param string $shareKey (filename.userid.sharekey)
|
||||
* @return mixed filename or false
|
||||
*/
|
||||
protected static function getFilenameFromShareKey($shareKey) {
|
||||
$parts = explode('.', $shareKey);
|
||||
|
||||
$filename = false;
|
||||
if(count($parts) > 2) {
|
||||
$filename = implode('.', array_slice($parts, 0, count($parts)-2));
|
||||
}
|
||||
|
||||
return $filename;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -203,47 +203,6 @@ class Proxy extends \OC_FileProxy {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief When a file is deleted, remove its keyfile also
|
||||
*/
|
||||
public function preUnlink($path) {
|
||||
|
||||
$relPath = Helper::stripUserFilesPath($path);
|
||||
|
||||
// skip this method if the trash bin is enabled or if we delete a file
|
||||
// outside of /data/user/files
|
||||
if (\OCP\App::isEnabled('files_trashbin') || $relPath === false) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Disable encryption proxy to prevent recursive calls
|
||||
$proxyStatus = \OC_FileProxy::$enabled;
|
||||
\OC_FileProxy::$enabled = false;
|
||||
|
||||
$view = new \OC_FilesystemView('/');
|
||||
|
||||
$userId = \OCP\USER::getUser();
|
||||
|
||||
$util = new Util($view, $userId);
|
||||
|
||||
list($owner, $ownerPath) = $util->getUidAndFilename($relPath);
|
||||
|
||||
// Delete keyfile & shareKey so it isn't orphaned
|
||||
if (!Keymanager::deleteFileKey($view, $ownerPath)) {
|
||||
\OCP\Util::writeLog('Encryption library',
|
||||
'Keyfile or shareKey could not be deleted for file "' . $ownerPath . '"', \OCP\Util::ERROR);
|
||||
}
|
||||
|
||||
Keymanager::delAllShareKeys($view, $owner, $ownerPath);
|
||||
|
||||
\OC_FileProxy::$enabled = $proxyStatus;
|
||||
|
||||
// If we don't return true then file delete will fail; better
|
||||
// to leave orphaned keyfiles than to disallow file deletion
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
* @return bool
|
||||
|
|
|
@ -57,7 +57,7 @@ class Util {
|
|||
* @param $userId
|
||||
* @param bool $client
|
||||
*/
|
||||
public function __construct(\OC_FilesystemView $view, $userId, $client = false) {
|
||||
public function __construct($view, $userId, $client = false) {
|
||||
|
||||
$this->view = $view;
|
||||
$this->client = $client;
|
||||
|
|
271
apps/files_encryption/tests/hooks.php
Normal file
271
apps/files_encryption/tests/hooks.php
Normal file
|
@ -0,0 +1,271 @@
|
|||
<?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/base.php';
|
||||
require_once __DIR__ . '/../lib/crypt.php';
|
||||
require_once __DIR__ . '/../lib/keymanager.php';
|
||||
require_once __DIR__ . '/../lib/stream.php';
|
||||
require_once __DIR__ . '/../lib/util.php';
|
||||
require_once __DIR__ . '/../appinfo/app.php';
|
||||
require_once __DIR__ . '/util.php';
|
||||
|
||||
use OCA\Encryption;
|
||||
|
||||
/**
|
||||
* Class Test_Encryption_Hooks
|
||||
* @brief this class provide basic hook app tests
|
||||
*/
|
||||
class Test_Encryption_Hooks extends \PHPUnit_Framework_TestCase {
|
||||
|
||||
const TEST_ENCRYPTION_HOOKS_USER1 = "test-encryption-hooks-user1";
|
||||
const TEST_ENCRYPTION_HOOKS_USER2 = "test-encryption-hooks-user2";
|
||||
|
||||
/**
|
||||
* @var \OC_FilesystemView
|
||||
*/
|
||||
public $user1View; // view on /data/user1/files
|
||||
public $user2View; // view on /data/user2/files
|
||||
public $rootView; // view on /data/user
|
||||
public $data;
|
||||
public $filename;
|
||||
|
||||
public static function setUpBeforeClass() {
|
||||
// reset backend
|
||||
\OC_User::clearBackends();
|
||||
\OC_User::useBackend('database');
|
||||
|
||||
\OC_Hook::clear('OC_Filesystem');
|
||||
\OC_Hook::clear('OC_User');
|
||||
|
||||
// clear share hooks
|
||||
\OC_Hook::clear('OCP\\Share');
|
||||
\OC::registerShareHooks();
|
||||
\OCP\Util::connectHook('OC_Filesystem', 'setup', '\OC\Files\Storage\Shared', 'setup');
|
||||
|
||||
// Filesystem related hooks
|
||||
\OCA\Encryption\Helper::registerFilesystemHooks();
|
||||
|
||||
// Sharing related hooks
|
||||
\OCA\Encryption\Helper::registerShareHooks();
|
||||
|
||||
// clear and register proxies
|
||||
\OC_FileProxy::clearProxies();
|
||||
\OC_FileProxy::register(new OCA\Encryption\Proxy());
|
||||
|
||||
// create test user
|
||||
\Test_Encryption_Util::loginHelper(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1, true);
|
||||
\Test_Encryption_Util::loginHelper(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2, true);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
// set user id
|
||||
\Test_Encryption_Util::loginHelper(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1);
|
||||
\OC_User::setUserId(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1);
|
||||
|
||||
// init filesystem view
|
||||
$this->user1View = new \OC_FilesystemView('/'. \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1 . '/files');
|
||||
$this->user2View = new \OC_FilesystemView('/'. \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2 . '/files');
|
||||
$this->rootView = new \OC_FilesystemView('/');
|
||||
|
||||
// init short data
|
||||
$this->data = 'hats';
|
||||
$this->filename = 'enc_hooks_tests-' . uniqid() . '.txt';
|
||||
|
||||
}
|
||||
|
||||
public static function tearDownAfterClass() {
|
||||
// cleanup test user
|
||||
\OC_User::deleteUser(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1);
|
||||
\OC_User::deleteUser(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2);
|
||||
}
|
||||
|
||||
function testDeleteHooks() {
|
||||
|
||||
// remember files_trashbin state
|
||||
$stateFilesTrashbin = OC_App::isEnabled('files_trashbin');
|
||||
|
||||
// we want to tests with app files_trashbin disabled
|
||||
\OC_App::disable('files_trashbin');
|
||||
|
||||
// make sure that the trash bin is disabled
|
||||
$this->assertFalse(\OC_APP::isEnabled('files_trashbin'));
|
||||
|
||||
$this->user1View->file_put_contents($this->filename, $this->data);
|
||||
|
||||
// check if all keys are generated
|
||||
$this->assertTrue($this->rootView->file_exists(
|
||||
self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/share-keys/'
|
||||
. $this->filename . '.' . \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey'));
|
||||
$this->assertTrue($this->rootView->file_exists(
|
||||
self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/keyfiles/' . $this->filename . '.key'));
|
||||
|
||||
|
||||
\Test_Encryption_Util::logoutHelper();
|
||||
\Test_Encryption_Util::loginHelper(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2);
|
||||
\OC_User::setUserId(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2);
|
||||
|
||||
|
||||
$this->user2View->file_put_contents($this->filename, $this->data);
|
||||
|
||||
// check if all keys are generated
|
||||
$this->assertTrue($this->rootView->file_exists(
|
||||
self::TEST_ENCRYPTION_HOOKS_USER2 . '/files_encryption/share-keys/'
|
||||
. $this->filename . '.' . \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2 . '.shareKey'));
|
||||
$this->assertTrue($this->rootView->file_exists(
|
||||
self::TEST_ENCRYPTION_HOOKS_USER2 . '/files_encryption/keyfiles/' . $this->filename . '.key'));
|
||||
|
||||
|
||||
// create a dummy file that we can delete something outside of data/user/files
|
||||
// in this case no share or file keys should be deleted
|
||||
$this->rootView->file_put_contents(self::TEST_ENCRYPTION_HOOKS_USER2 . "/" . $this->filename, $this->data);
|
||||
|
||||
// delete dummy file outside of data/user/files
|
||||
$this->rootView->unlink(self::TEST_ENCRYPTION_HOOKS_USER2 . "/" . $this->filename);
|
||||
|
||||
// all keys should still exist
|
||||
$this->assertTrue($this->rootView->file_exists(
|
||||
self::TEST_ENCRYPTION_HOOKS_USER2 . '/files_encryption/share-keys/'
|
||||
. $this->filename . '.' . \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2 . '.shareKey'));
|
||||
$this->assertTrue($this->rootView->file_exists(
|
||||
self::TEST_ENCRYPTION_HOOKS_USER2 . '/files_encryption/keyfiles/' . $this->filename . '.key'));
|
||||
|
||||
|
||||
// delete the file in data/user/files
|
||||
// now the correspondig share and file keys from user2 should be deleted
|
||||
$this->user2View->unlink($this->filename);
|
||||
|
||||
// check if keys from user2 are really deleted
|
||||
$this->assertFalse($this->rootView->file_exists(
|
||||
self::TEST_ENCRYPTION_HOOKS_USER2 . '/files_encryption/share-keys/'
|
||||
. $this->filename . '.' . \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2 . '.shareKey'));
|
||||
$this->assertFalse($this->rootView->file_exists(
|
||||
self::TEST_ENCRYPTION_HOOKS_USER2 . '/files_encryption/keyfiles/' . $this->filename . '.key'));
|
||||
|
||||
// but user1 keys should still exist
|
||||
$this->assertTrue($this->rootView->file_exists(
|
||||
self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/share-keys/'
|
||||
. $this->filename . '.' . \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey'));
|
||||
$this->assertTrue($this->rootView->file_exists(
|
||||
self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/keyfiles/' . $this->filename . '.key'));
|
||||
|
||||
if ($stateFilesTrashbin) {
|
||||
OC_App::enable('files_trashbin');
|
||||
}
|
||||
else {
|
||||
OC_App::disable('files_trashbin');
|
||||
}
|
||||
}
|
||||
|
||||
function testDeleteHooksForSharedFiles() {
|
||||
|
||||
\Test_Encryption_Util::logoutHelper();
|
||||
\Test_Encryption_Util::loginHelper(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1);
|
||||
\OC_User::setUserId(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1);
|
||||
|
||||
// remember files_trashbin state
|
||||
$stateFilesTrashbin = OC_App::isEnabled('files_trashbin');
|
||||
|
||||
// we want to tests with app files_trashbin disabled
|
||||
\OC_App::disable('files_trashbin');
|
||||
|
||||
// make sure that the trash bin is disabled
|
||||
$this->assertFalse(\OC_APP::isEnabled('files_trashbin'));
|
||||
|
||||
$this->user1View->file_put_contents($this->filename, $this->data);
|
||||
|
||||
// check if all keys are generated
|
||||
$this->assertTrue($this->rootView->file_exists(
|
||||
self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/share-keys/'
|
||||
. $this->filename . '.' . \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey'));
|
||||
$this->assertTrue($this->rootView->file_exists(
|
||||
self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/keyfiles/' . $this->filename . '.key'));
|
||||
|
||||
// get the file info from previous created file
|
||||
$fileInfo = $this->user1View->getFileInfo($this->filename);
|
||||
|
||||
// check if we have a valid file info
|
||||
$this->assertTrue(is_array($fileInfo));
|
||||
|
||||
// share the file with user2
|
||||
\OCP\Share::shareItem('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_USER, self::TEST_ENCRYPTION_HOOKS_USER2, OCP\PERMISSION_ALL);
|
||||
|
||||
// check if new share key exists
|
||||
$this->assertTrue($this->rootView->file_exists(
|
||||
self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/share-keys/'
|
||||
. $this->filename . '.' . \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2 . '.shareKey'));
|
||||
|
||||
\Test_Encryption_Util::logoutHelper();
|
||||
\Test_Encryption_Util::loginHelper(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2);
|
||||
\OC_User::setUserId(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2);
|
||||
|
||||
// user2 has a local file with the same name
|
||||
$this->user2View->file_put_contents($this->filename, $this->data);
|
||||
|
||||
// check if all keys are generated
|
||||
$this->assertTrue($this->rootView->file_exists(
|
||||
self::TEST_ENCRYPTION_HOOKS_USER2 . '/files_encryption/share-keys/'
|
||||
. $this->filename . '.' . \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2 . '.shareKey'));
|
||||
$this->assertTrue($this->rootView->file_exists(
|
||||
self::TEST_ENCRYPTION_HOOKS_USER2 . '/files_encryption/keyfiles/' . $this->filename . '.key'));
|
||||
|
||||
// delete the Shared file from user1 in data/user2/files/Shared
|
||||
$this->user2View->unlink('/Shared/' . $this->filename);
|
||||
|
||||
// now keys from user1s home should be gone
|
||||
$this->assertFalse($this->rootView->file_exists(
|
||||
self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/share-keys/'
|
||||
. $this->filename . '.' . \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey'));
|
||||
$this->assertFalse($this->rootView->file_exists(
|
||||
self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/share-keys/'
|
||||
. $this->filename . '.' . \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2 . '.shareKey'));
|
||||
$this->assertFalse($this->rootView->file_exists(
|
||||
self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/keyfiles/' . $this->filename . '.key'));
|
||||
|
||||
// but user2 keys should still exist
|
||||
$this->assertTrue($this->rootView->file_exists(
|
||||
self::TEST_ENCRYPTION_HOOKS_USER2 . '/files_encryption/share-keys/'
|
||||
. $this->filename . '.' . \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2 . '.shareKey'));
|
||||
$this->assertTrue($this->rootView->file_exists(
|
||||
self::TEST_ENCRYPTION_HOOKS_USER2 . '/files_encryption/keyfiles/' . $this->filename . '.key'));
|
||||
|
||||
// cleanup
|
||||
|
||||
$this->user2View->unlink($this->filename);
|
||||
|
||||
\Test_Encryption_Util::logoutHelper();
|
||||
\Test_Encryption_Util::loginHelper(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1);
|
||||
\OC_User::setUserId(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1);
|
||||
|
||||
// unshare the file
|
||||
\OCP\Share::unshare('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_USER, self::TEST_ENCRYPTION_HOOKS_USER2);
|
||||
|
||||
$this->user1View->unlink($this->filename);
|
||||
|
||||
if ($stateFilesTrashbin) {
|
||||
OC_App::enable('files_trashbin');
|
||||
}
|
||||
else {
|
||||
OC_App::disable('files_trashbin');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -136,6 +136,17 @@ class Test_Encryption_Keymanager extends \PHPUnit_Framework_TestCase {
|
|||
$this->assertArrayHasKey('key', $sslInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* @small
|
||||
*/
|
||||
function testGetFilenameFromShareKey() {
|
||||
$this->assertEquals("file",
|
||||
\TestProtectedKeymanagerMethods::testGetFilenameFromShareKey("file.user.shareKey"));
|
||||
$this->assertEquals("file.name.with.dots",
|
||||
\TestProtectedKeymanagerMethods::testGetFilenameFromShareKey("file.name.with.dots.user.shareKey"));
|
||||
$this->assertFalse(\TestProtectedKeymanagerMethods::testGetFilenameFromShareKey("file.txt"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @medium
|
||||
*/
|
||||
|
@ -234,3 +245,12 @@ class Test_Encryption_Keymanager extends \PHPUnit_Framework_TestCase {
|
|||
\OC_FileProxy::$enabled = $proxyStatus;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* dummy class to access protected methods of \OCA\Encryption\Keymanager for testing
|
||||
*/
|
||||
class TestProtectedKeymanagerMethods extends \OCA\Encryption\Keymanager {
|
||||
public static function testGetFilenameFromShareKey($sharekey) {
|
||||
return self::getFilenameFromShareKey($sharekey);
|
||||
}
|
||||
}
|
|
@ -112,54 +112,4 @@ class Test_Encryption_Proxy extends \PHPUnit_Framework_TestCase {
|
|||
|
||||
}
|
||||
|
||||
function testPreUnlinkWithoutTrash() {
|
||||
|
||||
// remember files_trashbin state
|
||||
$stateFilesTrashbin = OC_App::isEnabled('files_trashbin');
|
||||
|
||||
// we want to tests with app files_trashbin enabled
|
||||
\OC_App::disable('files_trashbin');
|
||||
|
||||
$this->view->file_put_contents($this->filename, $this->data);
|
||||
|
||||
// create a dummy file that we can delete something outside of data/user/files
|
||||
$this->rootView->file_put_contents("dummy.txt", $this->data);
|
||||
|
||||
// check if all keys are generated
|
||||
$this->assertTrue($this->rootView->file_exists(
|
||||
'/files_encryption/share-keys/'
|
||||
. $this->filename . '.' . \Test_Encryption_Proxy::TEST_ENCRYPTION_PROXY_USER1 . '.shareKey'));
|
||||
$this->assertTrue($this->rootView->file_exists(
|
||||
'/files_encryption/keyfiles/' . $this->filename . '.key'));
|
||||
|
||||
|
||||
// delete dummy file outside of data/user/files
|
||||
$this->rootView->unlink("dummy.txt");
|
||||
|
||||
// all keys should still exist
|
||||
$this->assertTrue($this->rootView->file_exists(
|
||||
'/files_encryption/share-keys/'
|
||||
. $this->filename . '.' . \Test_Encryption_Proxy::TEST_ENCRYPTION_PROXY_USER1 . '.shareKey'));
|
||||
$this->assertTrue($this->rootView->file_exists(
|
||||
'/files_encryption/keyfiles/' . $this->filename . '.key'));
|
||||
|
||||
|
||||
// delete the file in data/user/files
|
||||
$this->view->unlink($this->filename);
|
||||
|
||||
// now also the keys should be gone
|
||||
$this->assertFalse($this->rootView->file_exists(
|
||||
'/files_encryption/share-keys/'
|
||||
. $this->filename . '.' . \Test_Encryption_Proxy::TEST_ENCRYPTION_PROXY_USER1 . '.shareKey'));
|
||||
$this->assertFalse($this->rootView->file_exists(
|
||||
'/files_encryption/keyfiles/' . $this->filename . '.key'));
|
||||
|
||||
if ($stateFilesTrashbin) {
|
||||
OC_App::enable('files_trashbin');
|
||||
}
|
||||
else {
|
||||
OC_App::disable('files_trashbin');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -194,8 +194,9 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
|
|||
. $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '.shareKey'));
|
||||
|
||||
// cleanup
|
||||
$this->view->unlink(
|
||||
'/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename);
|
||||
$this->view->chroot('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/');
|
||||
$this->view->unlink($this->filename);
|
||||
$this->view->chroot('/');
|
||||
|
||||
// check if share key not exists
|
||||
$this->assertFalse($this->view->file_exists(
|
||||
|
@ -265,8 +266,9 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
|
|||
. $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '.shareKey'));
|
||||
|
||||
// cleanup
|
||||
$this->view->unlink(
|
||||
'/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename);
|
||||
$this->view->chroot('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/');
|
||||
$this->view->unlink($this->filename);
|
||||
$this->view->chroot('/');
|
||||
|
||||
// check if share key not exists
|
||||
$this->assertFalse($this->view->file_exists(
|
||||
|
@ -352,7 +354,9 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
|
|||
. $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '.shareKey'));
|
||||
|
||||
// cleanup
|
||||
$this->view->unlink('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files' . $this->folder1);
|
||||
$this->view->chroot('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files');
|
||||
$this->view->unlink($this->folder1);
|
||||
$this->view->chroot('/');
|
||||
|
||||
// check if share key not exists
|
||||
$this->assertFalse($this->view->file_exists(
|
||||
|
@ -482,9 +486,9 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
|
|||
. $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '.shareKey'));
|
||||
|
||||
// cleanup
|
||||
$this->view->unlink(
|
||||
'/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files' . $this->folder1 . $this->subfolder
|
||||
. $this->subsubfolder . '/' . $this->filename);
|
||||
$this->view->chroot('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files');
|
||||
$this->view->unlink($this->folder1 . $this->subfolder . $this->subsubfolder . '/' . $this->filename);
|
||||
$this->view->chroot('/');
|
||||
|
||||
// check if share key not exists
|
||||
$this->assertFalse($this->view->file_exists(
|
||||
|
@ -559,7 +563,9 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
|
|||
. $this->filename . '.' . $publicShareKeyId . '.shareKey'));
|
||||
|
||||
// cleanup
|
||||
$this->view->unlink('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename);
|
||||
$this->view->chroot('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/');
|
||||
$this->view->unlink($this->filename);
|
||||
$this->view->chroot('/');
|
||||
|
||||
// check if share key not exists
|
||||
$this->assertFalse($this->view->file_exists(
|
||||
|
@ -636,7 +642,9 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
|
|||
. $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER4 . '.shareKey'));
|
||||
|
||||
// cleanup
|
||||
$this->view->unlink('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename);
|
||||
$this->view->chroot('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/');
|
||||
$this->view->unlink($this->filename);
|
||||
$this->view->chroot('/');
|
||||
|
||||
// check if share key not exists
|
||||
$this->assertFalse($this->view->file_exists(
|
||||
|
@ -731,8 +739,10 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
|
|||
. $this->filename . '.' . $recoveryKeyId . '.shareKey'));
|
||||
|
||||
// cleanup
|
||||
$this->view->unlink('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename);
|
||||
$this->view->unlink('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->folder1);
|
||||
$this->view->chroot('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/');
|
||||
$this->view->unlink($this->filename);
|
||||
$this->view->unlink($this->folder1);
|
||||
$this->view->chroot('/');
|
||||
|
||||
// check if share key for recovery not exists
|
||||
$this->assertFalse($this->view->file_exists(
|
||||
|
@ -828,8 +838,10 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
|
|||
$this->assertEquals($this->dataShort, $retrievedCryptedFile2);
|
||||
|
||||
// cleanup
|
||||
$this->view->unlink('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files/' . $this->folder1);
|
||||
$this->view->unlink('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files/' . $this->filename);
|
||||
$this->view->chroot('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files/');
|
||||
$this->view->unlink($this->folder1);
|
||||
$this->view->unlink($this->filename);
|
||||
$this->view->chroot('/');
|
||||
|
||||
// check if share key for user and recovery exists
|
||||
$this->assertFalse($this->view->file_exists(
|
||||
|
@ -930,7 +942,9 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
|
|||
. $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3 . '.shareKey'));
|
||||
|
||||
// cleanup
|
||||
$this->view->unlink('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename);
|
||||
$this->view->chroot('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/');
|
||||
$this->view->unlink($this->filename);
|
||||
$this->view->chroot('/');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -92,12 +92,11 @@ class Shared_Cache extends Cache {
|
|||
} else {
|
||||
$query = \OC_DB::prepare(
|
||||
'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`,'
|
||||
.' `size`, `mtime`, `encrypted`'
|
||||
.' `size`, `mtime`, `encrypted`, `unencrypted_size`'
|
||||
.' FROM `*PREFIX*filecache` WHERE `fileid` = ?');
|
||||
$result = $query->execute(array($file));
|
||||
$data = $result->fetchRow();
|
||||
$data['fileid'] = (int)$data['fileid'];
|
||||
$data['size'] = (int)$data['size'];
|
||||
$data['mtime'] = (int)$data['mtime'];
|
||||
$data['storage_mtime'] = (int)$data['storage_mtime'];
|
||||
$data['encrypted'] = (bool)$data['encrypted'];
|
||||
|
@ -106,6 +105,12 @@ class Shared_Cache extends Cache {
|
|||
if ($data['storage_mtime'] === 0) {
|
||||
$data['storage_mtime'] = $data['mtime'];
|
||||
}
|
||||
if ($data['encrypted'] or ($data['unencrypted_size'] > 0 and $data['mimetype'] === 'httpd/unix-directory')) {
|
||||
$data['encrypted_size'] = (int)$data['size'];
|
||||
$data['size'] = (int)$data['unencrypted_size'];
|
||||
} else {
|
||||
$data['size'] = (int)$data['size'];
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
return false;
|
||||
|
@ -259,17 +264,38 @@ class Shared_Cache extends Cache {
|
|||
* @return array
|
||||
*/
|
||||
public function searchByMime($mimetype) {
|
||||
|
||||
if (strpos($mimetype, '/')) {
|
||||
$where = '`mimetype` = ? AND ';
|
||||
} else {
|
||||
$where = '`mimepart` = ? AND ';
|
||||
$mimepart = null;
|
||||
if (strpos($mimetype, '/') === false) {
|
||||
$mimepart = $mimetype;
|
||||
$mimetype = null;
|
||||
}
|
||||
|
||||
$value = $this->getMimetypeId($mimetype);
|
||||
|
||||
return $this->searchWithWhere($where, $value);
|
||||
// note: searchWithWhere is currently broken as it doesn't
|
||||
// recurse into subdirs nor returns the correct
|
||||
// file paths, so using getFolderContents() for now
|
||||
|
||||
$result = array();
|
||||
$exploreDirs = array('');
|
||||
while (count($exploreDirs) > 0) {
|
||||
$dir = array_pop($exploreDirs);
|
||||
$files = $this->getFolderContents($dir);
|
||||
// no results?
|
||||
if (!$files) {
|
||||
continue;
|
||||
}
|
||||
foreach ($files as $file) {
|
||||
if ($file['mimetype'] === 'httpd/unix-directory') {
|
||||
$exploreDirs[] = ltrim($dir . '/' . $file['name'], '/');
|
||||
}
|
||||
else if (($mimepart && $file['mimepart'] === $mimepart) || ($mimetype && $file['mimetype'] === $mimetype)) {
|
||||
// usersPath not reliable
|
||||
//$file['path'] = $file['usersPath'];
|
||||
$file['path'] = ltrim($dir . '/' . $file['name'], '/');
|
||||
$result[] = $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -313,6 +339,12 @@ class Shared_Cache extends Cache {
|
|||
}
|
||||
$row['mimetype'] = $this->getMimetype($row['mimetype']);
|
||||
$row['mimepart'] = $this->getMimetype($row['mimepart']);
|
||||
if ($row['encrypted'] or ($row['unencrypted_size'] > 0 and $row['mimetype'] === 'httpd/unix-directory')) {
|
||||
$row['encrypted_size'] = $row['size'];
|
||||
$row['size'] = $row['unencrypted_size'];
|
||||
} else {
|
||||
$row['size'] = $row['size'];
|
||||
}
|
||||
$files[] = $row;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,10 +91,17 @@ class OC_Share_Backend_File implements OCP\Share_Backend_File_Dependent {
|
|||
$file['name'] = basename($item['file_target']);
|
||||
$file['mimetype'] = $item['mimetype'];
|
||||
$file['mimepart'] = $item['mimepart'];
|
||||
$file['size'] = $item['size'];
|
||||
$file['mtime'] = $item['mtime'];
|
||||
$file['encrypted'] = $item['encrypted'];
|
||||
$file['etag'] = $item['etag'];
|
||||
$storage = \OC\Files\Filesystem::getStorage('/');
|
||||
$cache = $storage->getCache();
|
||||
if ($item['encrypted'] or ($item['unencrypted_size'] > 0 and $cache->getMimetype($item['mimetype']) === 'httpd/unix-directory')) {
|
||||
$file['size'] = $item['unencrypted_size'];
|
||||
$file['encrypted_size'] = $item['size'];
|
||||
} else {
|
||||
$file['size'] = $item['size'];
|
||||
}
|
||||
$files[] = $file;
|
||||
}
|
||||
return $files;
|
||||
|
|
|
@ -143,18 +143,13 @@ if (isset($path)) {
|
|||
OCP\Util::addScript('files', 'jquery.iframe-transport');
|
||||
OCP\Util::addScript('files', 'jquery.fileupload');
|
||||
$maxUploadFilesize=OCP\Util::maxUploadFilesize($path);
|
||||
$freeSpace=OCP\Util::freeSpace($dir);
|
||||
$uploadLimit=OCP\Util::uploadLimit();
|
||||
$tmpl = new OCP\Template('files_sharing', 'public', 'base');
|
||||
$tmpl->assign('uidOwner', $shareOwner);
|
||||
$tmpl->assign('displayName', \OCP\User::getDisplayName($shareOwner));
|
||||
$tmpl->assign('filename', $file);
|
||||
$tmpl->assign('directory_path', $linkItem['file_target']);
|
||||
$tmpl->assign('mimetype', \OC\Files\Filesystem::getMimeType($path));
|
||||
$tmpl->assign('fileTarget', basename($linkItem['file_target']));
|
||||
$tmpl->assign('dirToken', $linkItem['token']);
|
||||
$tmpl->assign('sharingToken', $token);
|
||||
$tmpl->assign('disableSharing', true);
|
||||
$allowPublicUploadEnabled = (bool) ($linkItem['permissions'] & OCP\PERMISSION_CREATE);
|
||||
if (OC_Appconfig::getValue('core', 'shareapi_allow_public_upload', 'yes') === 'no') {
|
||||
$allowPublicUploadEnabled = false;
|
||||
|
@ -162,10 +157,6 @@ if (isset($path)) {
|
|||
if ($linkItem['item_type'] !== 'folder') {
|
||||
$allowPublicUploadEnabled = false;
|
||||
}
|
||||
$tmpl->assign('uploadMaxFilesize', $maxUploadFilesize);
|
||||
$tmpl->assign('uploadMaxHumanFilesize', OCP\Util::humanFileSize($maxUploadFilesize));
|
||||
$tmpl->assign('freeSpace', $freeSpace);
|
||||
$tmpl->assign('uploadLimit', $uploadLimit); // PHP upload limit
|
||||
|
||||
$urlLinkIdentifiers= (isset($token)?'&t='.$token:'')
|
||||
.(isset($_GET['dir'])?'&dir='.$_GET['dir']:'')
|
||||
|
@ -226,6 +217,9 @@ if (isset($path)) {
|
|||
$maxUploadFilesize=OCP\Util::maxUploadFilesize($path);
|
||||
$fileHeader = (!isset($files) or count($files) > 0);
|
||||
$emptyContent = ($allowPublicUploadEnabled and !$fileHeader);
|
||||
|
||||
$freeSpace=OCP\Util::freeSpace($path);
|
||||
$uploadLimit=OCP\Util::uploadLimit();
|
||||
$folder = new OCP\Template('files', 'index', '');
|
||||
$folder->assign('fileList', $list->fetchPage());
|
||||
$folder->assign('breadcrumb', $breadcrumbNav->fetchPage());
|
||||
|
@ -238,6 +232,8 @@ if (isset($path)) {
|
|||
$folder->assign('files', $files);
|
||||
$folder->assign('uploadMaxFilesize', $maxUploadFilesize);
|
||||
$folder->assign('uploadMaxHumanFilesize', OCP\Util::humanFileSize($maxUploadFilesize));
|
||||
$folder->assign('freeSpace', $freeSpace);
|
||||
$folder->assign('uploadLimit', $uploadLimit); // PHP upload limit
|
||||
$folder->assign('allowZipDownload', intval(OCP\Config::getSystemValue('allowZipDownload', true)));
|
||||
$folder->assign('usedSpacePercent', 0);
|
||||
$folder->assign('fileHeader', $fileHeader);
|
||||
|
|
134
apps/files_sharing/tests/cache.php
Normal file
134
apps/files_sharing/tests/cache.php
Normal file
|
@ -0,0 +1,134 @@
|
|||
<?php
|
||||
/**
|
||||
* ownCloud
|
||||
*
|
||||
* @author Vincent Petry
|
||||
* @copyright 2014 Vincent Petry <pvince81@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__ . '/base.php';
|
||||
|
||||
class Test_Files_Sharing_Cache extends Test_Files_Sharing_Base {
|
||||
|
||||
function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
self::loginHelper(self::TEST_FILES_SHARING_API_USER1);
|
||||
|
||||
// prepare user1's dir structure
|
||||
$textData = "dummy file data\n";
|
||||
$this->view->mkdir('container');
|
||||
$this->view->mkdir('container/shareddir');
|
||||
$this->view->mkdir('container/shareddir/subdir');
|
||||
$this->view->mkdir('container/shareddir/emptydir');
|
||||
|
||||
$textData = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||
$this->view->file_put_contents('container/not shared.txt', $textData);
|
||||
$this->view->file_put_contents('container/shared single file.txt', $textData);
|
||||
$this->view->file_put_contents('container/shareddir/bar.txt', $textData);
|
||||
$this->view->file_put_contents('container/shareddir/subdir/another.txt', $textData);
|
||||
$this->view->file_put_contents('container/shareddir/subdir/another too.txt', $textData);
|
||||
$this->view->file_put_contents('container/shareddir/subdir/not a text file.xml', '<xml></xml>');
|
||||
|
||||
list($this->ownerStorage, $internalPath) = $this->view->resolvePath('');
|
||||
$this->ownerCache = $this->ownerStorage->getCache();
|
||||
$this->ownerStorage->getScanner()->scan('');
|
||||
|
||||
// share "shareddir" with user2
|
||||
$fileinfo = $this->view->getFileInfo('container/shareddir');
|
||||
\OCP\Share::shareItem('folder', $fileinfo['fileid'], \OCP\Share::SHARE_TYPE_USER,
|
||||
self::TEST_FILES_SHARING_API_USER2, 31);
|
||||
|
||||
$fileinfo = $this->view->getFileInfo('container/shared single file.txt');
|
||||
\OCP\Share::shareItem('file', $fileinfo['fileid'], \OCP\Share::SHARE_TYPE_USER,
|
||||
self::TEST_FILES_SHARING_API_USER2, 31);
|
||||
|
||||
// login as user2
|
||||
self::loginHelper(self::TEST_FILES_SHARING_API_USER2);
|
||||
|
||||
// retrieve the shared storage
|
||||
$secondView = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER2);
|
||||
list($this->sharedStorage, $internalPath) = $secondView->resolvePath('files/Shared/shareddir');
|
||||
$this->sharedCache = $this->sharedStorage->getCache();
|
||||
}
|
||||
|
||||
function tearDown() {
|
||||
$this->sharedCache->clear();
|
||||
|
||||
self::loginHelper(self::TEST_FILES_SHARING_API_USER1);
|
||||
|
||||
$fileinfo = $this->view->getFileInfo('container/shareddir');
|
||||
\OCP\Share::unshare('folder', $fileinfo['fileid'], \OCP\Share::SHARE_TYPE_USER,
|
||||
self::TEST_FILES_SHARING_API_USER2);
|
||||
|
||||
$fileinfo = $this->view->getFileInfo('container/shared single file.txt');
|
||||
\OCP\Share::unshare('file', $fileinfo['fileid'], \OCP\Share::SHARE_TYPE_USER,
|
||||
self::TEST_FILES_SHARING_API_USER2);
|
||||
|
||||
$this->view->deleteAll('container');
|
||||
|
||||
$this->ownerCache->clear();
|
||||
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test searching by mime type
|
||||
*/
|
||||
function testSearchByMime() {
|
||||
$results = $this->sharedStorage->getCache()->searchByMime('text');
|
||||
$check = array(
|
||||
array(
|
||||
'name' => 'shared single file.txt',
|
||||
'path' => 'shared single file.txt'
|
||||
),
|
||||
array(
|
||||
'name' => 'bar.txt',
|
||||
'path' => 'shareddir/bar.txt'
|
||||
),
|
||||
array(
|
||||
'name' => 'another too.txt',
|
||||
'path' => 'shareddir/subdir/another too.txt'
|
||||
),
|
||||
array(
|
||||
'name' => 'another.txt',
|
||||
'path' => 'shareddir/subdir/another.txt'
|
||||
),
|
||||
);
|
||||
$this->verifyFiles($check, $results);
|
||||
|
||||
$results2 = $this->sharedStorage->getCache()->searchByMime('text/plain');
|
||||
|
||||
$this->verifyFiles($check, $results);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that all provided attributes exist in the files list,
|
||||
* only the values provided in $examples will be used to check against
|
||||
* the file list. The files order also needs to be the same.
|
||||
*
|
||||
* @param array $examples array of example files
|
||||
* @param array $files array of files
|
||||
*/
|
||||
private function verifyFiles($examples, $files) {
|
||||
$this->assertEquals(count($examples), count($files));
|
||||
foreach ($files as $i => $file) {
|
||||
foreach ($examples[$i] as $key => $value) {
|
||||
$this->assertEquals($value, $file[$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -14,4 +14,7 @@
|
|||
<types>
|
||||
<authentication/>
|
||||
</types>
|
||||
<documentation>
|
||||
<admin>http://doc.owncloud.org/server/6.0/go.php?to=admin-ldap</admin>
|
||||
</documentation>
|
||||
</info>
|
||||
|
|
|
@ -240,6 +240,7 @@ var LdapWizard = {
|
|||
LdapWizard.hideSpinner('#ldap_base');
|
||||
LdapWizard.showInfoBox('Please specify a Base DN');
|
||||
LdapWizard.showInfoBox('Could not determine Base DN');
|
||||
$('#ldap_base').prop('disabled', false);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
@ -729,7 +729,7 @@ class Access extends LDAPUtility {
|
|||
}
|
||||
} else {
|
||||
if(!is_null($limit)) {
|
||||
\OCP\Util::writeLog('user_ldap', 'Paged search failed :(', \OCP\Util::INFO);
|
||||
\OCP\Util::writeLog('user_ldap', 'Paged search was not available', \OCP\Util::INFO);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -145,9 +145,11 @@ interface ILDAPWrapper {
|
|||
* @param $baseDN The DN of the entry to read from
|
||||
* @param $filter An LDAP filter
|
||||
* @param $attr array of the attributes to read
|
||||
* @param $attrsonly optional, 1 if only attribute types shall be returned
|
||||
* @param $limit optional, limits the result entries
|
||||
* @return an LDAP search result resource, false on error
|
||||
*/
|
||||
public function search($link, $baseDN, $filter, $attr);
|
||||
public function search($link, $baseDN, $filter, $attr, $attrsonly = 0, $limit = 0);
|
||||
|
||||
/**
|
||||
* @brief Sets the value of the specified option to be $value
|
||||
|
|
|
@ -85,9 +85,9 @@ class LDAP implements ILDAPWrapper {
|
|||
return $this->invokeLDAPMethod('read', $link, $baseDN, $filter, $attr);
|
||||
}
|
||||
|
||||
public function search($link, $baseDN, $filter, $attr) {
|
||||
return $this->invokeLDAPMethod('search', $link, $baseDN,
|
||||
$filter, $attr);
|
||||
public function search($link, $baseDN, $filter, $attr, $attrsonly = 0, $limit = 0) {
|
||||
return $this->invokeLDAPMethod('search', $link, $baseDN, $filter,
|
||||
$attr, $attrsonly, $limit);
|
||||
}
|
||||
|
||||
public function setOption($link, $option, $value) {
|
||||
|
|
|
@ -567,6 +567,10 @@ class Wizard extends LDAPUtility {
|
|||
//get a result set > 0 on a proper base
|
||||
$rr = $this->ldap->search($cr, $base, 'objectClass=*', array('dn'), 0, 1);
|
||||
if(!$this->ldap->isResource($rr)) {
|
||||
$errorNo = $this->ldap->errno($cr);
|
||||
$errorMsg = $this->ldap->error($cr);
|
||||
\OCP\Util::writeLog('user_ldap', 'Wiz: Could not search base '.$base.
|
||||
' Error '.$errorNo.': '.$errorMsg, \OCP\Util::INFO);
|
||||
return false;
|
||||
}
|
||||
$entries = $this->ldap->countEntries($cr, $rr);
|
||||
|
@ -1010,6 +1014,7 @@ class Wizard extends LDAPUtility {
|
|||
$this->configuration->ldapPort);
|
||||
|
||||
$this->ldap->setOption($cr, LDAP_OPT_PROTOCOL_VERSION, 3);
|
||||
$this->ldap->setOption($cr, LDAP_OPT_REFERRALS, 0);
|
||||
$this->ldap->setOption($cr, LDAP_OPT_NETWORK_TIMEOUT, self::LDAP_NW_TIMEOUT);
|
||||
if($this->configuration->ldapTLS === 1) {
|
||||
$this->ldap->startTls($cr);
|
||||
|
|
|
@ -185,19 +185,23 @@ EOF
|
|||
cp $BASEDIR/tests/autoconfig-$1.php $BASEDIR/config/autoconfig.php
|
||||
|
||||
# trigger installation
|
||||
php -f index.php
|
||||
echo "INDEX"
|
||||
php -f index.php | grep -i -C9999 error && echo "Error during setup" && exit 101
|
||||
echo "END INDEX"
|
||||
|
||||
#test execution
|
||||
echo "Testing with $1 ..."
|
||||
cd tests
|
||||
rm -rf coverage-html-$1
|
||||
mkdir coverage-html-$1
|
||||
php -f enable_all.php
|
||||
php -f enable_all.php | grep -i -C9999 error && echo "Error during setup" && exit 101
|
||||
if [ -z "$NOCOVERAGE" ]; then
|
||||
$PHPUNIT --configuration phpunit-autotest.xml --log-junit autotest-results-$1.xml --coverage-clover autotest-clover-$1.xml --coverage-html coverage-html-$1 $2 $3
|
||||
RESULT=$?
|
||||
else
|
||||
echo "No coverage"
|
||||
$PHPUNIT --configuration phpunit-autotest.xml --log-junit autotest-results-$1.xml $2 $3
|
||||
RESULT=$?
|
||||
fi
|
||||
}
|
||||
|
||||
|
|
|
@ -120,8 +120,14 @@ $CONFIG = array(
|
|||
/* Password to use for sendmail mail, depends on mail_smtpauth if this is used */
|
||||
"mail_smtppassword" => "",
|
||||
|
||||
/* memcached hostname and port (Only used when xCache, APC and APCu are absent.) */
|
||||
"memcached_server" => array('localhost', 11211),
|
||||
/* memcached servers (Only used when xCache, APC and APCu are absent.) */
|
||||
"memcached_servers" => array(
|
||||
// hostname, port and optional weight. Also see:
|
||||
// http://www.php.net/manual/en/memcached.addservers.php
|
||||
// http://www.php.net/manual/en/memcached.addserver.php
|
||||
array('localhost', 11211),
|
||||
//array('other.host.local', 11211),
|
||||
),
|
||||
|
||||
/* How long should ownCloud keep deleted files in the trash bin, default value: 30 days */
|
||||
'trashbin_retention_obligation' => 30,
|
||||
|
|
|
@ -56,17 +56,18 @@ class Controller {
|
|||
}
|
||||
|
||||
public function loadAutoConfig($post) {
|
||||
$dbIsSet = isset($post['dbtype']);
|
||||
$directoryIsSet = isset($post['directory']);
|
||||
$adminAccountIsSet = isset($post['adminlogin']);
|
||||
|
||||
$autosetup_file = \OC::$SERVERROOT.'/config/autoconfig.php';
|
||||
if( file_exists( $autosetup_file )) {
|
||||
\OC_Log::write('core', 'Autoconfig file found, setting up owncloud...', \OC_Log::INFO);
|
||||
$AUTOCONFIG = array();
|
||||
include $autosetup_file;
|
||||
$post = array_merge ($post, $AUTOCONFIG);
|
||||
}
|
||||
|
||||
$dbIsSet = isset($post['dbtype']);
|
||||
$directoryIsSet = isset($post['directory']);
|
||||
$adminAccountIsSet = isset($post['adminlogin']);
|
||||
|
||||
if ($dbIsSet AND $directoryIsSet AND $adminAccountIsSet) {
|
||||
$post['install'] = 'true';
|
||||
if( file_exists( $autosetup_file )) {
|
||||
|
@ -90,7 +91,7 @@ class Controller {
|
|||
$databases['sqlite'] = 'SQLite';
|
||||
}
|
||||
if ($hasMySQL) {
|
||||
$databases['mysql'] = 'MySQL';
|
||||
$databases['mysql'] = 'MySQL/MariaDB';
|
||||
}
|
||||
if ($hasPostgreSQL) {
|
||||
$databases['pgsql'] = 'PostgreSQL';
|
||||
|
|
|
@ -72,11 +72,12 @@ class Detection {
|
|||
and function_exists('finfo_file') and $finfo = finfo_open(FILEINFO_MIME)
|
||||
) {
|
||||
$info = @strtolower(finfo_file($finfo, $path));
|
||||
finfo_close($finfo);
|
||||
if ($info) {
|
||||
$mimeType = substr($info, 0, strpos($info, ';'));
|
||||
return empty($mimeType) ? 'application/octet-stream' : $mimeType;
|
||||
}
|
||||
finfo_close($finfo);
|
||||
|
||||
}
|
||||
$isWrapped = (strpos($path, '://') !== false) and (substr($path, 0, 7) === 'file://');
|
||||
if (!$isWrapped and $mimeType === 'application/octet-stream' && function_exists("mime_content_type")) {
|
||||
|
|
|
@ -409,14 +409,14 @@ class OC_Image {
|
|||
|
||||
/**
|
||||
* @brief Loads an image from a local file.
|
||||
* @param $imageref The path to a local file.
|
||||
* @param $imagePath The path to a local file.
|
||||
* @returns An image resource or false on error
|
||||
*/
|
||||
public function loadFromFile($imagePath=false) {
|
||||
// exif_imagetype throws "read error!" if file is less than 12 byte
|
||||
if(!@is_file($imagePath) || !file_exists($imagePath) || filesize($imagePath) < 12 || !is_readable($imagePath)) {
|
||||
// Debug output disabled because this method is tried before loadFromBase64?
|
||||
OC_Log::write('core', 'OC_Image->loadFromFile, couldn\'t load: '.$imagePath, OC_Log::DEBUG);
|
||||
OC_Log::write('core', 'OC_Image->loadFromFile, couldn\'t load: ' . (string) urlencode($imagePath), OC_Log::DEBUG);
|
||||
return false;
|
||||
}
|
||||
$iType = exif_imagetype($imagePath);
|
||||
|
|
|
@ -132,10 +132,10 @@ class OC_L10N implements \OCP\IL10N {
|
|||
$i18ndir = self::findI18nDir($app);
|
||||
// Localization is in /l10n, Texts are in $i18ndir
|
||||
// (Just no need to define date/time format etc. twice)
|
||||
if((OC_Helper::issubdirectory($i18ndir.$lang.'.php', OC_App::getAppPath($app).'/l10n/')
|
||||
|| OC_Helper::issubdirectory($i18ndir.$lang.'.php', OC::$SERVERROOT.'/core/l10n/')
|
||||
if((OC_Helper::issubdirectory($i18ndir.$lang.'.php', OC::$SERVERROOT.'/core/l10n/')
|
||||
|| OC_Helper::issubdirectory($i18ndir.$lang.'.php', OC::$SERVERROOT.'/lib/l10n/')
|
||||
|| OC_Helper::issubdirectory($i18ndir.$lang.'.php', OC::$SERVERROOT.'/settings')
|
||||
|| OC_Helper::issubdirectory($i18ndir.$lang.'.php', OC_App::getAppPath($app).'/l10n/')
|
||||
)
|
||||
&& file_exists($i18ndir.$lang.'.php')) {
|
||||
// Include the file, save the data from $CONFIG
|
||||
|
|
|
@ -18,8 +18,16 @@ class Memcached extends Cache {
|
|||
parent::__construct($prefix);
|
||||
if (is_null(self::$cache)) {
|
||||
self::$cache = new \Memcached();
|
||||
list($host, $port) = \OC_Config::getValue('memcached_server', array('localhost', 11211));
|
||||
self::$cache->addServer($host, $port);
|
||||
$servers = \OC_Config::getValue('memcached_servers');
|
||||
if (!$servers) {
|
||||
$server = \OC_Config::getValue('memcached_server');
|
||||
if ($server) {
|
||||
$servers = array($server);
|
||||
} else {
|
||||
$servers = array(array('localhost', 11211));
|
||||
}
|
||||
}
|
||||
self::$cache->addServers($servers);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* See the COPYING-README file.
|
||||
*/
|
||||
//both, libreoffice backend and php fallback, need imagick
|
||||
if (extension_loaded('imagick')) {
|
||||
if (extension_loaded('imagick') && count(\Imagick::queryFormats("PDF")) === 1) {
|
||||
$isShellExecEnabled = \OC_Helper::is_function_enabled('shell_exec');
|
||||
|
||||
// LibreOffice preview is currently not supported on Windows
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
namespace OC\Preview;
|
||||
|
||||
if (extension_loaded('imagick')) {
|
||||
if (extension_loaded('imagick') && count(\Imagick::queryFormats("PDF")) === 1) {
|
||||
|
||||
class PDF extends Provider {
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
namespace OC\Preview;
|
||||
|
||||
if (extension_loaded('imagick')) {
|
||||
if (extension_loaded('imagick') && count(\Imagick::queryFormats("SVG")) === 1) {
|
||||
|
||||
class SVG extends Provider {
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ class Unknown extends Provider {
|
|||
|
||||
$svgPath = substr_replace($path, 'svg', -3);
|
||||
|
||||
if (extension_loaded('imagick') && file_exists($svgPath)) {
|
||||
if (extension_loaded('imagick') && file_exists($svgPath) && count(\Imagick::queryFormats("SVG")) === 1) {
|
||||
|
||||
// http://www.php.net/manual/de/imagick.setresolution.php#85284
|
||||
$svg = new \Imagick();
|
||||
|
|
|
@ -11,6 +11,7 @@ class OC_Request {
|
|||
const USER_AGENT_IE = '/MSIE/';
|
||||
// Android Chrome user agent: https://developers.google.com/chrome/mobile/docs/user-agent
|
||||
const USER_AGENT_ANDROID_MOBILE_CHROME = '#Android.*Chrome/[.0-9]*#';
|
||||
const USER_AGENT_FREEBOX = '#^Mozilla/5\.0$#';
|
||||
|
||||
/**
|
||||
* @brief Check overwrite condition
|
||||
|
|
|
@ -153,7 +153,11 @@ class OC_Response {
|
|||
* @param string $type disposition type, either 'attachment' or 'inline'
|
||||
*/
|
||||
static public function setContentDispositionHeader( $filename, $type = 'attachment' ) {
|
||||
if (OC_Request::isUserAgent(array(OC_Request::USER_AGENT_IE, OC_Request::USER_AGENT_ANDROID_MOBILE_CHROME))) {
|
||||
if (OC_Request::isUserAgent(array(
|
||||
OC_Request::USER_AGENT_IE,
|
||||
OC_Request::USER_AGENT_ANDROID_MOBILE_CHROME,
|
||||
OC_Request::USER_AGENT_FREEBOX
|
||||
))) {
|
||||
header( 'Content-Disposition: ' . rawurlencode($type) . '; filename="' . rawurlencode( $filename ) . '"' );
|
||||
} else {
|
||||
header( 'Content-Disposition: ' . rawurlencode($type) . '; filename*=UTF-8\'\'' . rawurlencode( $filename )
|
||||
|
|
|
@ -3,13 +3,13 @@
|
|||
namespace OC\Setup;
|
||||
|
||||
class MySQL extends AbstractDatabase {
|
||||
public $dbprettyname = 'MySQL';
|
||||
public $dbprettyname = 'MySQL/MariaDB';
|
||||
|
||||
public function setupDatabase($username) {
|
||||
//check if the database user has admin right
|
||||
$connection = @mysql_connect($this->dbhost, $this->dbuser, $this->dbpassword);
|
||||
if(!$connection) {
|
||||
throw new \DatabaseSetupException($this->trans->t('MySQL username and/or password not valid'),
|
||||
throw new \DatabaseSetupException($this->trans->t('MySQL/MariaDB username and/or password not valid'),
|
||||
$this->trans->t('You need to enter either an existing account or the administrator.'));
|
||||
}
|
||||
$oldUser=\OC_Config::getValue('dbuser', false);
|
||||
|
@ -82,14 +82,14 @@ class MySQL extends AbstractDatabase {
|
|||
$query = "CREATE USER '$name'@'localhost' IDENTIFIED BY '$password'";
|
||||
$result = mysql_query($query, $connection);
|
||||
if (!$result) {
|
||||
throw new \DatabaseSetupException($this->trans->t("MySQL user '%s'@'localhost' exists already.", array($name)),
|
||||
$this->trans->t("Drop this user from MySQL", array($name)));
|
||||
throw new \DatabaseSetupException($this->trans->t("MySQL/MariaDB user '%s'@'localhost' exists already.", array($name)),
|
||||
$this->trans->t("Drop this user from MySQL/MariaDB", array($name)));
|
||||
}
|
||||
$query = "CREATE USER '$name'@'%' IDENTIFIED BY '$password'";
|
||||
$result = mysql_query($query, $connection);
|
||||
if (!$result) {
|
||||
throw new \DatabaseSetupException($this->trans->t("MySQL user '%s'@'%%' already exists", array($name)),
|
||||
$this->trans->t("Drop this user from MySQL."));
|
||||
throw new \DatabaseSetupException($this->trans->t("MySQL/MariaDB user '%s'@'%%' already exists", array($name)),
|
||||
$this->trans->t("Drop this user from MySQL/MariaDB."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1152,7 +1152,7 @@ class Share {
|
|||
$select = '`*PREFIX*share`.`id`, `item_type`, `item_source`, `*PREFIX*share`.`parent`, `uid_owner`, '
|
||||
.'`share_type`, `share_with`, `file_source`, `path`, `file_target`, '
|
||||
.'`permissions`, `expiration`, `storage`, `*PREFIX*filecache`.`parent` as `file_parent`, '
|
||||
.'`name`, `mtime`, `mimetype`, `mimepart`, `size`, `encrypted`, `etag`, `mail_send`';
|
||||
.'`name`, `mtime`, `mimetype`, `mimepart`, `size`, `unencrypted_size`, `encrypted`, `etag`, `mail_send`';
|
||||
} else {
|
||||
$select = '`*PREFIX*share`.`id`, `item_type`, `item_source`, `item_target`,
|
||||
`*PREFIX*share`.`parent`, `share_type`, `share_with`, `uid_owner`,
|
||||
|
|
|
@ -158,7 +158,7 @@ $(document).ready(function(){
|
|||
if(typeof timeout !== 'undefined'){
|
||||
clearTimeout(timeout);
|
||||
}
|
||||
timeout = setTimeout('changeDisplayName()',1000);
|
||||
timeout = setTimeout(changeDisplayName, 1000);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -173,7 +173,7 @@ $(document).ready(function(){
|
|||
if(typeof timeout !== 'undefined'){
|
||||
clearTimeout(timeout);
|
||||
}
|
||||
timeout = setTimeout('changeEmailAddress()',1000);
|
||||
timeout = setTimeout(changeEmailAddress, 1000);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -9,9 +9,11 @@
|
|||
|
||||
|
||||
<ul id="leftcontent" class="applist">
|
||||
<?php if(OC_Config::getValue('appstoreenabled', true) === true): ?>
|
||||
<li>
|
||||
<a class="app-external" target="_blank" href="http://owncloud.org/dev"><?php p($l->t('Add your App'));?> …</a>
|
||||
</li>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php foreach($_['apps'] as $app):?>
|
||||
<li <?php if($app['active']) print_unescaped('class="active"')?> data-id="<?php p($app['id']) ?>"
|
||||
|
@ -24,9 +26,11 @@
|
|||
</li>
|
||||
<?php endforeach;?>
|
||||
|
||||
<?php if(OC_Config::getValue('appstoreenabled', true) === true): ?>
|
||||
<li>
|
||||
<a class="app-external" target="_blank" href="http://apps.owncloud.com"><?php p($l->t('More Apps'));?> …</a>
|
||||
</li>
|
||||
<?php endif; ?>
|
||||
</ul>
|
||||
<div id="rightcontent">
|
||||
<div class="appinfo">
|
||||
|
|
|
@ -118,6 +118,21 @@ class Test_Request extends PHPUnit_Framework_TestCase {
|
|||
),
|
||||
true
|
||||
),
|
||||
array(
|
||||
'Mozilla/5.0 (X11; Linux i686; rv:24.0) Gecko/20100101 Firefox/24.0',
|
||||
OC_Request::USER_AGENT_FREEBOX,
|
||||
false
|
||||
),
|
||||
array(
|
||||
'Mozilla/5.0',
|
||||
OC_Request::USER_AGENT_FREEBOX,
|
||||
true
|
||||
),
|
||||
array(
|
||||
'Fake Mozilla/5.0',
|
||||
OC_Request::USER_AGENT_FREEBOX,
|
||||
false
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue