Merge pull request #8399 from owncloud/server-server-sharing
Add server<->server sharing
This commit is contained in:
commit
8d1cf79152
|
@ -49,8 +49,9 @@ $server->subscribeEvent('beforeMethod', function () use ($server, $objectTree) {
|
||||||
$rootInfo = $view->getFileInfo('');
|
$rootInfo = $view->getFileInfo('');
|
||||||
|
|
||||||
// Create ownCloud Dir
|
// Create ownCloud Dir
|
||||||
|
$mountManager = \OC\Files\Filesystem::getMountManager();
|
||||||
$rootDir = new OC_Connector_Sabre_Directory($view, $rootInfo);
|
$rootDir = new OC_Connector_Sabre_Directory($view, $rootInfo);
|
||||||
$objectTree->init($rootDir, $view);
|
$objectTree->init($rootDir, $view, $mountManager);
|
||||||
|
|
||||||
$server->addPlugin(new OC_Connector_Sabre_AbortedUploadDetectionPlugin($view));
|
$server->addPlugin(new OC_Connector_Sabre_AbortedUploadDetectionPlugin($view));
|
||||||
$server->addPlugin(new OC_Connector_Sabre_QuotaPlugin($view));
|
$server->addPlugin(new OC_Connector_Sabre_QuotaPlugin($view));
|
||||||
|
|
|
@ -41,6 +41,39 @@ class Proxy extends \OC_FileProxy {
|
||||||
private static $fopenMode = array(); // remember the fopen mode
|
private static $fopenMode = array(); // remember the fopen mode
|
||||||
private static $enableEncryption = false; // Enable encryption for the given path
|
private static $enableEncryption = false; // Enable encryption for the given path
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* check if path is excluded from encryption
|
||||||
|
*
|
||||||
|
* @param string $path relative to data/
|
||||||
|
* @param string $uid user
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
private function isExcludedPath($path, $uid) {
|
||||||
|
|
||||||
|
$view = new \OC\Files\View();
|
||||||
|
|
||||||
|
// files outside of the files-folder are excluded
|
||||||
|
if(strpos($path, '/' . $uid . '/files') !== 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$view->file_exists($path)) {
|
||||||
|
$path = dirname($path);
|
||||||
|
}
|
||||||
|
|
||||||
|
// we don't encrypt server-to-server shares
|
||||||
|
list($storage, ) = \OC\Files\Filesystem::resolvePath($path);
|
||||||
|
/**
|
||||||
|
* @var \OCP\Files\Storage $storage
|
||||||
|
*/
|
||||||
|
if ($storage->instanceOfStorage('OCA\Files_Sharing\External\Storage')) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if a file requires encryption
|
* Check if a file requires encryption
|
||||||
* @param string $path
|
* @param string $path
|
||||||
|
@ -50,7 +83,7 @@ class Proxy extends \OC_FileProxy {
|
||||||
* Tests if server side encryption is enabled, and if we should call the
|
* Tests if server side encryption is enabled, and if we should call the
|
||||||
* crypt stream wrapper for the given file
|
* crypt stream wrapper for the given file
|
||||||
*/
|
*/
|
||||||
private static function shouldEncrypt($path, $mode = 'w') {
|
private function shouldEncrypt($path, $mode = 'w') {
|
||||||
|
|
||||||
$userId = Helper::getUser($path);
|
$userId = Helper::getUser($path);
|
||||||
$session = new Session(new \OC\Files\View());
|
$session = new Session(new \OC\Files\View());
|
||||||
|
@ -59,7 +92,7 @@ class Proxy extends \OC_FileProxy {
|
||||||
if (
|
if (
|
||||||
$session->getInitialized() !== Session::INIT_SUCCESSFUL // encryption successful initialized
|
$session->getInitialized() !== Session::INIT_SUCCESSFUL // encryption successful initialized
|
||||||
|| Crypt::mode() !== 'server' // we are not in server-side-encryption mode
|
|| Crypt::mode() !== 'server' // we are not in server-side-encryption mode
|
||||||
|| strpos($path, '/' . $userId . '/files') !== 0 // path is not in files/
|
|| $this->isExcludedPath($path, $userId) // if path is excluded from encryption
|
||||||
|| substr($path, 0, 8) === 'crypt://' // we are already in crypt mode
|
|| substr($path, 0, 8) === 'crypt://' // we are already in crypt mode
|
||||||
) {
|
) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -85,7 +118,7 @@ class Proxy extends \OC_FileProxy {
|
||||||
*/
|
*/
|
||||||
public function preFile_put_contents($path, &$data) {
|
public function preFile_put_contents($path, &$data) {
|
||||||
|
|
||||||
if (self::shouldEncrypt($path)) {
|
if ($this->shouldEncrypt($path)) {
|
||||||
|
|
||||||
if (!is_resource($data)) {
|
if (!is_resource($data)) {
|
||||||
|
|
||||||
|
@ -219,7 +252,7 @@ class Proxy extends \OC_FileProxy {
|
||||||
public function preFopen($path, $mode) {
|
public function preFopen($path, $mode) {
|
||||||
|
|
||||||
self::$fopenMode[$path] = $mode;
|
self::$fopenMode[$path] = $mode;
|
||||||
self::$enableEncryption = self::shouldEncrypt($path, $mode);
|
self::$enableEncryption = $this->shouldEncrypt($path, $mode);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -100,6 +100,8 @@ class Session {
|
||||||
$privateKey = Crypt::decryptPrivateKey($encryptedKey, '');
|
$privateKey = Crypt::decryptPrivateKey($encryptedKey, '');
|
||||||
$this->setPublicSharePrivateKey($privateKey);
|
$this->setPublicSharePrivateKey($privateKey);
|
||||||
|
|
||||||
|
$this->setInitialized(\OCA\Encryption\Session::INIT_SUCCESSFUL);
|
||||||
|
|
||||||
\OC_FileProxy::$enabled = $proxyStatus;
|
\OC_FileProxy::$enabled = $proxyStatus;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -235,7 +235,8 @@ class Test_Encryption_Webdav extends \PHPUnit_Framework_TestCase {
|
||||||
$view = new \OC\Files\View($root);
|
$view = new \OC\Files\View($root);
|
||||||
$publicDir = new OC_Connector_Sabre_Directory($view, $view->getFileInfo(''));
|
$publicDir = new OC_Connector_Sabre_Directory($view, $view->getFileInfo(''));
|
||||||
$objectTree = new \OC\Connector\Sabre\ObjectTree();
|
$objectTree = new \OC\Connector\Sabre\ObjectTree();
|
||||||
$objectTree->init($publicDir, $view);
|
$mountManager = \OC\Files\Filesystem::getMountManager();
|
||||||
|
$objectTree->init($publicDir, $view, $mountManager);
|
||||||
|
|
||||||
// Fire up server
|
// Fire up server
|
||||||
$server = new \Sabre\DAV\Server($publicDir);
|
$server = new \Sabre\DAV\Server($publicDir);
|
||||||
|
|
|
@ -9,13 +9,13 @@
|
||||||
namespace OC\Files\Storage;
|
namespace OC\Files\Storage;
|
||||||
|
|
||||||
class DAV extends \OC\Files\Storage\Common {
|
class DAV extends \OC\Files\Storage\Common {
|
||||||
private $password;
|
protected $password;
|
||||||
private $user;
|
protected $user;
|
||||||
private $host;
|
protected $host;
|
||||||
private $secure;
|
protected $secure;
|
||||||
private $root;
|
protected $root;
|
||||||
private $certPath;
|
protected $certPath;
|
||||||
private $ready;
|
protected $ready;
|
||||||
/**
|
/**
|
||||||
* @var \Sabre\DAV\Client
|
* @var \Sabre\DAV\Client
|
||||||
*/
|
*/
|
||||||
|
@ -355,6 +355,9 @@ class DAV extends \OC\Files\Storage\Common {
|
||||||
* @param string $path
|
* @param string $path
|
||||||
*/
|
*/
|
||||||
public function cleanPath($path) {
|
public function cleanPath($path) {
|
||||||
|
if ($path === "") {
|
||||||
|
return $path;
|
||||||
|
}
|
||||||
$path = \OC\Files\Filesystem::normalizePath($path);
|
$path = \OC\Files\Filesystem::normalizePath($path);
|
||||||
// remove leading slash
|
// remove leading slash
|
||||||
return substr($path, 1);
|
return substr($path, 1);
|
||||||
|
@ -397,11 +400,27 @@ class DAV extends \OC\Files\Storage\Common {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function isUpdatable($path) {
|
||||||
|
return (bool)($this->getPermissions($path) & \OCP\PERMISSION_UPDATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isCreatable($path) {
|
||||||
|
return (bool)($this->getPermissions($path) & \OCP\PERMISSION_CREATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isSharable($path) {
|
||||||
|
return (bool)($this->getPermissions($path) & \OCP\PERMISSION_SHARE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isDeletable($path) {
|
||||||
|
return (bool)($this->getPermissions($path) & \OCP\PERMISSION_DELETE);
|
||||||
|
}
|
||||||
|
|
||||||
public function getPermissions($path) {
|
public function getPermissions($path) {
|
||||||
$this->init();
|
$this->init();
|
||||||
$response = $this->client->propfind($this->encodePath($path), array('{http://owncloud.org/ns}permissions'));
|
$response = $this->client->propfind($this->encodePath($path), array('{http://owncloud.org/ns}permissions'));
|
||||||
if (isset($response['{http://owncloud.org/ns}permissions'])) {
|
if (isset($response['{http://owncloud.org/ns}permissions'])) {
|
||||||
$permissions = 0;
|
$permissions = \OCP\PERMISSION_READ;
|
||||||
$permissionsString = $response['{http://owncloud.org/ns}permissions'];
|
$permissionsString = $response['{http://owncloud.org/ns}permissions'];
|
||||||
if (strpos($permissionsString, 'R') !== false) {
|
if (strpos($permissionsString, 'R') !== false) {
|
||||||
$permissions |= \OCP\PERMISSION_SHARE;
|
$permissions |= \OCP\PERMISSION_SHARE;
|
||||||
|
@ -416,8 +435,12 @@ class DAV extends \OC\Files\Storage\Common {
|
||||||
$permissions |= \OCP\PERMISSION_CREATE;
|
$permissions |= \OCP\PERMISSION_CREATE;
|
||||||
}
|
}
|
||||||
return $permissions;
|
return $permissions;
|
||||||
|
} else if ($this->is_dir($path)) {
|
||||||
|
return \OCP\PERMISSION_ALL;
|
||||||
|
} else if ($this->file_exists($path)) {
|
||||||
|
return \OCP\PERMISSION_ALL - \OCP\PERMISSION_CREATE;
|
||||||
} else {
|
} else {
|
||||||
return parent::getPermissions($path);
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
|
||||||
|
* This file is licensed under the Affero General Public License version 3 or
|
||||||
|
* later.
|
||||||
|
* See the COPYING-README file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
OCP\JSON::callCheck();
|
||||||
|
OCP\JSON::checkLoggedIn();
|
||||||
|
OCP\JSON::checkAppEnabled('files_sharing');
|
||||||
|
|
||||||
|
$l = OC_L10N::get('files_sharing');
|
||||||
|
|
||||||
|
// check if server admin allows to mount public links from other servers
|
||||||
|
// check if files_external is enabled
|
||||||
|
// FIXME file_external check no longer needed if we use the webdav implementation from core
|
||||||
|
if (OCA\Files_Sharing\Helper::isIncomingServer2serverShareEnabled() === false ||
|
||||||
|
\OC_App::isEnabled('files_external') === false) {
|
||||||
|
\OCP\JSON::error(array('data' => array('message' => $l->t('Server to server sharing is not enabled on this server'))));
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
$token = $_POST['token'];
|
||||||
|
$remote = $_POST['remote'];
|
||||||
|
$owner = $_POST['owner'];
|
||||||
|
$name = $_POST['name'];
|
||||||
|
$password = $_POST['password'];
|
||||||
|
|
||||||
|
$externalManager = new \OCA\Files_Sharing\External\Manager(
|
||||||
|
\OC::$server->getDatabaseConnection(),
|
||||||
|
\OC\Files\Filesystem::getMountManager(),
|
||||||
|
\OC\Files\Filesystem::getLoader(),
|
||||||
|
\OC::$server->getUserSession()
|
||||||
|
);
|
||||||
|
|
||||||
|
$name = OCP\Files::buildNotExistingFileName('/', $name);
|
||||||
|
|
||||||
|
$mount = $externalManager->addShare($remote, $token, $password, $name, $owner);
|
||||||
|
/**
|
||||||
|
* @var \OCA\Files_Sharing\External\Storage $storage
|
||||||
|
*/
|
||||||
|
$storage = $mount->getStorage();
|
||||||
|
$result = $storage->file_exists('');
|
||||||
|
if($result){
|
||||||
|
$storage->getScanner()->scanAll();
|
||||||
|
\OCP\JSON::success();
|
||||||
|
} else {
|
||||||
|
$externalManager->removeShare($mount->getMountPoint());
|
||||||
|
\OCP\JSON::error(array('data' => array('message' => $l->t("Couldn't add remote share"))));
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
|
||||||
|
* This file is licensed under the Affero General Public License version 3 or
|
||||||
|
* later.
|
||||||
|
* See the COPYING-README file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
OCP\JSON::checkAppEnabled('files_sharing');
|
||||||
|
|
||||||
|
if (!isset($_GET['t'])) {
|
||||||
|
\OC_Response::setStatus(400); //400 Bad Request
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$token = $_GET['t'];
|
||||||
|
|
||||||
|
$password = null;
|
||||||
|
if (isset($_POST['password'])) {
|
||||||
|
$password = $_POST['password'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$relativePath = null;
|
||||||
|
if (isset($_GET['dir'])) {
|
||||||
|
$relativePath = $_GET['dir'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = \OCA\Files_Sharing\Helper::setupFromToken($token, $relativePath, $password);
|
||||||
|
|
||||||
|
$linkItem = $data['linkItem'];
|
||||||
|
// Load the files
|
||||||
|
$path = $data['realPath'];
|
||||||
|
|
||||||
|
$isWritable = $linkItem['permissions'] & (\OCP\PERMISSION_UPDATE | \OCP\PERMISSION_CREATE);
|
||||||
|
if (!$isWritable) {
|
||||||
|
\OC\Files\Filesystem::addStorageWrapper('readonly', function ($mountPoint, $storage) {
|
||||||
|
return new \OCA\Files_Sharing\ReadOnlyWrapper(array('storage' => $storage));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
$rootInfo = \OC\Files\Filesystem::getFileInfo($path);
|
||||||
|
$rootView = new \OC\Files\View('');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \OCP\Files\FileInfo $dir
|
||||||
|
* @param \OC\Files\View $view
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
function getChildInfo($dir, $view) {
|
||||||
|
$children = $view->getDirectoryContent($dir->getPath());
|
||||||
|
$result = array();
|
||||||
|
foreach ($children as $child) {
|
||||||
|
$formated = \OCA\Files\Helper::formatFileInfo($child);
|
||||||
|
if ($child->getType() === 'dir') {
|
||||||
|
$formated['children'] = getChildInfo($child, $view);
|
||||||
|
}
|
||||||
|
$formated['mtime'] = $formated['mtime'] / 1000;
|
||||||
|
$result[] = $formated;
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = \OCA\Files\Helper::formatFileInfo($rootInfo);
|
||||||
|
$result['mtime'] = $result['mtime'] / 1000;
|
||||||
|
if ($rootInfo->getType() === 'dir') {
|
||||||
|
$result['children'] = getChildInfo($rootInfo, $rootView);
|
||||||
|
}
|
||||||
|
|
||||||
|
OCP\JSON::success(array('data' => $result));
|
|
@ -0,0 +1,29 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
|
||||||
|
* This file is licensed under the Affero General Public License version 3 or
|
||||||
|
* later.
|
||||||
|
* See the COPYING-README file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
OCP\JSON::checkAppEnabled('files_sharing');
|
||||||
|
|
||||||
|
$remote = $_GET['remote'];
|
||||||
|
|
||||||
|
function testUrl($url) {
|
||||||
|
try {
|
||||||
|
$result = file_get_contents($url);
|
||||||
|
$data = json_decode($result);
|
||||||
|
return is_object($data) and !empty($data->version);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (testUrl('https://' . $remote . '/status.php')) {
|
||||||
|
echo 'https';
|
||||||
|
} elseif (testUrl('http://' . $remote . '/status.php')) {
|
||||||
|
echo 'http';
|
||||||
|
} else {
|
||||||
|
echo 'false';
|
||||||
|
}
|
|
@ -11,10 +11,24 @@ OC::$CLASSPATH['OC\Files\Cache\Shared_Watcher'] = 'files_sharing/lib/watcher.php
|
||||||
OC::$CLASSPATH['OCA\Files\Share\Api'] = 'files_sharing/lib/api.php';
|
OC::$CLASSPATH['OCA\Files\Share\Api'] = 'files_sharing/lib/api.php';
|
||||||
OC::$CLASSPATH['OCA\Files\Share\Maintainer'] = 'files_sharing/lib/maintainer.php';
|
OC::$CLASSPATH['OCA\Files\Share\Maintainer'] = 'files_sharing/lib/maintainer.php';
|
||||||
OC::$CLASSPATH['OCA\Files\Share\Proxy'] = 'files_sharing/lib/proxy.php';
|
OC::$CLASSPATH['OCA\Files\Share\Proxy'] = 'files_sharing/lib/proxy.php';
|
||||||
|
|
||||||
|
\OCP\App::registerAdmin('files_sharing', 'settings-admin');
|
||||||
|
|
||||||
|
$externalManager = new \OCA\Files_Sharing\External\Manager(
|
||||||
|
\OC::$server->getDatabaseConnection(),
|
||||||
|
\OC\Files\Filesystem::getMountManager(),
|
||||||
|
\OC\Files\Filesystem::getLoader(),
|
||||||
|
\OC::$server->getUserSession()
|
||||||
|
);
|
||||||
|
$externalManager->setup();
|
||||||
|
|
||||||
OCP\Util::connectHook('OC_Filesystem', 'setup', '\OC\Files\Storage\Shared', 'setup');
|
OCP\Util::connectHook('OC_Filesystem', 'setup', '\OC\Files\Storage\Shared', 'setup');
|
||||||
OCP\Share::registerBackend('file', 'OC_Share_Backend_File');
|
OCP\Share::registerBackend('file', 'OC_Share_Backend_File');
|
||||||
OCP\Share::registerBackend('folder', 'OC_Share_Backend_Folder', 'file');
|
OCP\Share::registerBackend('folder', 'OC_Share_Backend_Folder', 'file');
|
||||||
|
|
||||||
OCP\Util::addScript('files_sharing', 'share');
|
OCP\Util::addScript('files_sharing', 'share');
|
||||||
|
OCP\Util::addScript('files_sharing', 'external');
|
||||||
|
|
||||||
\OC_Hook::connect('OC_Filesystem', 'post_write', '\OC\Files\Cache\Shared_Updater', 'writeHook');
|
\OC_Hook::connect('OC_Filesystem', 'post_write', '\OC\Files\Cache\Shared_Updater', 'writeHook');
|
||||||
\OC_Hook::connect('OC_Filesystem', 'post_delete', '\OC\Files\Cache\Shared_Updater', 'postDeleteHook');
|
\OC_Hook::connect('OC_Filesystem', 'post_delete', '\OC\Files\Cache\Shared_Updater', 'postDeleteHook');
|
||||||
\OC_Hook::connect('OC_Filesystem', 'delete', '\OC\Files\Cache\Shared_Updater', 'deleteHook');
|
\OC_Hook::connect('OC_Filesystem', 'delete', '\OC\Files\Cache\Shared_Updater', 'deleteHook');
|
||||||
|
|
|
@ -0,0 +1,95 @@
|
||||||
|
<?xml version="1.0" encoding="ISO-8859-1" ?>
|
||||||
|
<database>
|
||||||
|
<name>*dbname*</name>
|
||||||
|
<create>true</create>
|
||||||
|
<overwrite>false</overwrite>
|
||||||
|
<charset>utf8</charset>
|
||||||
|
<table>
|
||||||
|
<name>*dbprefix*share_external</name>
|
||||||
|
<declaration>
|
||||||
|
<field>
|
||||||
|
<name>id</name>
|
||||||
|
<type>integer</type>
|
||||||
|
<default>0</default>
|
||||||
|
<notnull>true</notnull>
|
||||||
|
<autoincrement>1</autoincrement>
|
||||||
|
<length>4</length>
|
||||||
|
</field>
|
||||||
|
<field>
|
||||||
|
<name>remote</name>
|
||||||
|
<type>text</type>
|
||||||
|
<notnull>true</notnull>
|
||||||
|
<length>512</length>
|
||||||
|
<comments>Url of the remove owncloud instance</comments>
|
||||||
|
</field>
|
||||||
|
<field>
|
||||||
|
<name>share_token</name>
|
||||||
|
<type>text</type>
|
||||||
|
<notnull>true</notnull>
|
||||||
|
<length>64</length>
|
||||||
|
<comments>Public share token</comments>
|
||||||
|
</field>
|
||||||
|
<field>
|
||||||
|
<name>password</name>
|
||||||
|
<type>text</type>
|
||||||
|
<notnull>true</notnull>
|
||||||
|
<length>64</length>
|
||||||
|
<comments>Optional password for the public share</comments>
|
||||||
|
</field>
|
||||||
|
<field>
|
||||||
|
<name>name</name>
|
||||||
|
<type>text</type>
|
||||||
|
<notnull>true</notnull>
|
||||||
|
<length>64</length>
|
||||||
|
<comments>Original name on the remote server</comments>
|
||||||
|
</field>
|
||||||
|
<field>
|
||||||
|
<name>owner</name>
|
||||||
|
<type>text</type>
|
||||||
|
<notnull>true</notnull>
|
||||||
|
<length>64</length>
|
||||||
|
<comments>User that owns the public share on the remote server</comments>
|
||||||
|
</field>
|
||||||
|
<field>
|
||||||
|
<name>user</name>
|
||||||
|
<type>text</type>
|
||||||
|
<notnull>true</notnull>
|
||||||
|
<length>64</length>
|
||||||
|
<comments>Local user which added the external share</comments>
|
||||||
|
</field>
|
||||||
|
<field>
|
||||||
|
<name>mountpoint</name>
|
||||||
|
<type>text</type>
|
||||||
|
<notnull>true</notnull>
|
||||||
|
<length>4000</length>
|
||||||
|
<comments>Full path where the share is mounted</comments>
|
||||||
|
</field>
|
||||||
|
<field>
|
||||||
|
<name>mountpoint_hash</name>
|
||||||
|
<type>text</type>
|
||||||
|
<notnull>true</notnull>
|
||||||
|
<length>32</length>
|
||||||
|
<comments>md5 hash of the mountpoint</comments>
|
||||||
|
</field>
|
||||||
|
<index>
|
||||||
|
<name>sh_external_user</name>
|
||||||
|
<field>
|
||||||
|
<name>user</name>
|
||||||
|
<sorting>ascending</sorting>
|
||||||
|
</field>
|
||||||
|
</index>
|
||||||
|
<index>
|
||||||
|
<name>sh_external_mp</name>
|
||||||
|
<unique>true</unique>
|
||||||
|
<field>
|
||||||
|
<name>user</name>
|
||||||
|
<sorting>ascending</sorting>
|
||||||
|
</field>
|
||||||
|
<field>
|
||||||
|
<name>mountpoint_hash</name>
|
||||||
|
<sorting>ascending</sorting>
|
||||||
|
</field>
|
||||||
|
</index>
|
||||||
|
</declaration>
|
||||||
|
</table>
|
||||||
|
</database>
|
|
@ -5,6 +5,10 @@ $this->create('core_ajax_public_preview', '/publicpreview')->action(
|
||||||
require_once __DIR__ . '/../ajax/publicpreview.php';
|
require_once __DIR__ . '/../ajax/publicpreview.php';
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$this->create('sharing_external_shareinfo', '/shareinfo')->actionInclude('files_sharing/ajax/shareinfo.php');
|
||||||
|
$this->create('sharing_external_add', '/external')->actionInclude('files_sharing/ajax/external.php');
|
||||||
|
$this->create('sharing_external_test_remote', '/testremote')->actionInclude('files_sharing/ajax/testremote.php');
|
||||||
|
|
||||||
// OCS API
|
// OCS API
|
||||||
|
|
||||||
//TODO: SET: mail notification, waiting for PR #4689 to be accepted
|
//TODO: SET: mail notification, waiting for PR #4689 to be accepted
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
0.5
|
0.5.2
|
||||||
|
|
|
@ -87,3 +87,38 @@ thead {
|
||||||
width: 300px;
|
width: 300px;
|
||||||
max-width: 90%;
|
max-width: 90%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.header-right {
|
||||||
|
transition: opacity 500ms ease 0s;
|
||||||
|
-moz-transition: opacity 500ms ease 0s;
|
||||||
|
-ms-transition: opacity 500ms ease 0s;
|
||||||
|
-o-transition: opacity 500ms ease 0s;
|
||||||
|
-webkit-transition: opacity 500ms ease 0s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-right:hover, .header-right.active {
|
||||||
|
opacity: 1;
|
||||||
|
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
|
||||||
|
filter: alpha(opacity=100);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* within #save */
|
||||||
|
#remote_address {
|
||||||
|
margin: 0;
|
||||||
|
height: 14px;
|
||||||
|
line-height: 16px;
|
||||||
|
padding: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#save button {
|
||||||
|
margin: 0 5px;
|
||||||
|
height: 28px;
|
||||||
|
padding-bottom: 4px;
|
||||||
|
line-height: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#save .save-form [type="submit"] {
|
||||||
|
margin: 0 5px;
|
||||||
|
height: 28px;
|
||||||
|
padding-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
|
||||||
|
*
|
||||||
|
* This file is licensed under the Affero General Public License version 3
|
||||||
|
* or later.
|
||||||
|
*
|
||||||
|
* See the COPYING-README file.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
(function () {
|
||||||
|
var getParameterByName = function (query, name) {
|
||||||
|
name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
|
||||||
|
var regex = new RegExp("[\\#&]" + name + "=([^&#]*)"),
|
||||||
|
results = regex.exec(query);
|
||||||
|
return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
|
||||||
|
};
|
||||||
|
|
||||||
|
var addExternalShare = function (remote, token, owner, name, password) {
|
||||||
|
return $.post(OC.generateUrl('apps/files_sharing/external'), {
|
||||||
|
remote: remote,
|
||||||
|
token: token,
|
||||||
|
owner: owner,
|
||||||
|
name: name,
|
||||||
|
password: password
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var showAddExternalDialog = function (remote, token, owner, name, passwordProtected) {
|
||||||
|
var remoteClean = (remote.substr(0, 8) === 'https://') ? remote.substr(8) : remote.substr(7);
|
||||||
|
var callback = function (add, password) {
|
||||||
|
password = password || '';
|
||||||
|
if (add) {
|
||||||
|
addExternalShare(remote, token, owner, name, password).then(function (result) {
|
||||||
|
if (result.status === 'error') {
|
||||||
|
OC.Notification.show(result.data.message);
|
||||||
|
} else {
|
||||||
|
FileList.reload();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (!passwordProtected) {
|
||||||
|
OC.dialogs.confirm(t('files_sharing', 'Add {name} from {owner}@{remote}', {name: name, owner: owner, remote: remoteClean})
|
||||||
|
, 'Add Share', callback, true);
|
||||||
|
} else {
|
||||||
|
OC.dialogs.prompt(t('files_sharing', 'Add {name} from {owner}@{remote}', {name: name, owner: owner, remote: remoteClean})
|
||||||
|
, 'Add Share', callback, true, 'Password', true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
OCA.Sharing.showAddExternalDialog = function (hash) {
|
||||||
|
var remote = getParameterByName(hash, 'remote');
|
||||||
|
var owner = getParameterByName(hash, 'owner');
|
||||||
|
var name = getParameterByName(hash, 'name');
|
||||||
|
var token = getParameterByName(hash, 'token');
|
||||||
|
var passwordProtected = parseInt(getParameterByName(hash, 'protected'), 10);
|
||||||
|
|
||||||
|
if (remote && token && owner && name) {
|
||||||
|
showAddExternalDialog(remote, token, owner, name, passwordProtected);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
|
$(document).ready(function () {
|
||||||
|
// FIXME: HACK: do not init when running unit tests, need a better way
|
||||||
|
if (!window.TESTING && OCA.Files) {// only run in the files app
|
||||||
|
var hash = location.hash;
|
||||||
|
location.hash = '';
|
||||||
|
OCA.Sharing.showAddExternalDialog(hash);
|
||||||
|
}
|
||||||
|
});
|
|
@ -148,6 +148,24 @@ OCA.Sharing.PublicApp = {
|
||||||
$(this).select();
|
$(this).select();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$('.save-form').submit(function (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
var remote = $(this).find('input[type="text"]').val();
|
||||||
|
var token = $('#sharingToken').val();
|
||||||
|
var owner = $('#save').data('owner');
|
||||||
|
var name = $('#save').data('name');
|
||||||
|
var isProtected = $('#save').data('protected') ? 1 : 0;
|
||||||
|
OCA.Sharing.PublicApp._saveToOwnCloud(remote, token, owner, name, isProtected);
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#save > button').click(function () {
|
||||||
|
$(this).hide();
|
||||||
|
$('.header-right').addClass('active');
|
||||||
|
$('.save-form').css('display', 'inline');
|
||||||
|
$('#remote_address').focus();
|
||||||
|
});
|
||||||
|
|
||||||
// legacy
|
// legacy
|
||||||
window.FileList = this.fileList;
|
window.FileList = this.fileList;
|
||||||
},
|
},
|
||||||
|
@ -163,6 +181,29 @@ OCA.Sharing.PublicApp = {
|
||||||
|
|
||||||
_onUrlChanged: function (params) {
|
_onUrlChanged: function (params) {
|
||||||
this.fileList.changeDirectory(params.path || params.dir, false, true);
|
this.fileList.changeDirectory(params.path || params.dir, false, true);
|
||||||
|
},
|
||||||
|
|
||||||
|
_saveToOwnCloud: function(remote, token, owner, name, isProtected) {
|
||||||
|
var location = window.location.protocol + '//' + window.location.host + OC.webroot;
|
||||||
|
|
||||||
|
var url = remote + '/index.php/apps/files#' + 'remote=' + encodeURIComponent(location) // our location is the remote for the other server
|
||||||
|
+ "&token=" + encodeURIComponent(token) + "&owner=" + encodeURIComponent(owner) + "&name=" + encodeURIComponent(name) + "&protected=" + isProtected;
|
||||||
|
|
||||||
|
|
||||||
|
if (remote.indexOf('://') > 0) {
|
||||||
|
OC.redirect(url);
|
||||||
|
} else {
|
||||||
|
// if no protocol is specified, we automatically detect it by testing https and http
|
||||||
|
// this check needs to happen on the server due to the Content Security Policy directive
|
||||||
|
$.get(OC.generateUrl('apps/files_sharing/testremote'), {remote: remote}).then(function (protocol) {
|
||||||
|
if (protocol !== 'http' && protocol !== 'https') {
|
||||||
|
OC.dialogs.alert(t('files_sharing', 'No ownCloud installation found at {remote}', {remote: remote}),
|
||||||
|
t('files_sharing', 'Invalid ownCloud url'));
|
||||||
|
} else {
|
||||||
|
OC.redirect(protocol + '://' + url);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
$(document).ready(function() {
|
||||||
|
|
||||||
|
$('#fileSharingSettings input').change(function() {
|
||||||
|
var value = 'no';
|
||||||
|
if (this.checked) {
|
||||||
|
value = 'yes';
|
||||||
|
}
|
||||||
|
OC.AppConfig.setValue('files_sharing', $(this).attr('name'), value);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
|
@ -38,6 +38,7 @@ class PublicAuth extends \Sabre\DAV\Auth\Backend\AbstractBasic {
|
||||||
*/
|
*/
|
||||||
protected function validateUserPass($username, $password) {
|
protected function validateUserPass($username, $password) {
|
||||||
$linkItem = \OCP\Share::getShareByToken($username, false);
|
$linkItem = \OCP\Share::getShareByToken($username, false);
|
||||||
|
\OC_User::setIncognitoMode(true);
|
||||||
$this->share = $linkItem;
|
$this->share = $linkItem;
|
||||||
if (!$linkItem) {
|
if (!$linkItem) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
|
||||||
|
* This file is licensed under the Affero General Public License version 3 or
|
||||||
|
* later.
|
||||||
|
* See the COPYING-README file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace OCA\Files_Sharing\External;
|
||||||
|
|
||||||
|
class Cache extends \OC\Files\Cache\Cache {
|
||||||
|
private $remote;
|
||||||
|
private $remoteUser;
|
||||||
|
private $storage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \OCA\Files_Sharing\External\Storage $storage
|
||||||
|
* @param string $remote
|
||||||
|
* @param string $remoteUser
|
||||||
|
*/
|
||||||
|
public function __construct($storage, $remote, $remoteUser) {
|
||||||
|
$this->storage = $storage;
|
||||||
|
list(, $remote) = explode('://', $remote, 2);
|
||||||
|
$this->remote = $remote;
|
||||||
|
$this->remoteUser = $remoteUser;
|
||||||
|
parent::__construct($storage);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get($file) {
|
||||||
|
$result = parent::get($file);
|
||||||
|
$result['displayname_owner'] = $this->remoteUser . '@' . $this->remote;
|
||||||
|
if (!$file || $file === '') {
|
||||||
|
$result['is_share_mount_point'] = true;
|
||||||
|
$mountPoint = rtrim($this->storage->getMountPoint());
|
||||||
|
$result['name'] = basename($mountPoint);
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFolderContentsById($id) {
|
||||||
|
$results = parent::getFolderContentsById($id);
|
||||||
|
foreach ($results as &$file) {
|
||||||
|
$file['displayname_owner'] = $this->remoteUser . '@' . $this->remote;
|
||||||
|
}
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,140 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
|
||||||
|
* This file is licensed under the Affero General Public License version 3 or
|
||||||
|
* later.
|
||||||
|
* See the COPYING-README file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace OCA\Files_Sharing\External;
|
||||||
|
|
||||||
|
use OC\Files\Filesystem;
|
||||||
|
|
||||||
|
class Manager {
|
||||||
|
const STORAGE = '\OCA\Files_Sharing\External\Storage';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \OCP\IDBConnection
|
||||||
|
*/
|
||||||
|
private $connection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \OC\Files\Mount\Manager
|
||||||
|
*/
|
||||||
|
private $mountManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \OC\Files\Storage\Loader
|
||||||
|
*/
|
||||||
|
private $storageLoader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \OC\User\Session
|
||||||
|
*/
|
||||||
|
private $userSession;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \OCP\IDBConnection $connection
|
||||||
|
* @param \OC\Files\Mount\Manager $mountManager
|
||||||
|
* @param \OC\User\Session $userSession
|
||||||
|
* @param \OC\Files\Storage\Loader $storageLoader
|
||||||
|
*/
|
||||||
|
public function __construct(\OCP\IDBConnection $connection, \OC\Files\Mount\Manager $mountManager,
|
||||||
|
\OC\Files\Storage\Loader $storageLoader, \OC\User\Session $userSession) {
|
||||||
|
$this->connection = $connection;
|
||||||
|
$this->mountManager = $mountManager;
|
||||||
|
$this->userSession = $userSession;
|
||||||
|
$this->storageLoader = $storageLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addShare($remote, $token, $password, $name, $owner) {
|
||||||
|
$user = $this->userSession->getUser();
|
||||||
|
if ($user) {
|
||||||
|
$query = $this->connection->prepare('INSERT INTO *PREFIX*share_external(`remote`, `share_token`, `password`,
|
||||||
|
`name`, `owner`, `user`, `mountpoint`, `mountpoint_hash`) VALUES(?, ?, ?, ?, ?, ?, ?, ?)');
|
||||||
|
$mountPoint = Filesystem::normalizePath('/' . $name);
|
||||||
|
$hash = md5($mountPoint);
|
||||||
|
$query->execute(array($remote, $token, $password, $name, $owner, $user->getUID(), $mountPoint, $hash));
|
||||||
|
|
||||||
|
$options = array(
|
||||||
|
'remote' => $remote,
|
||||||
|
'token' => $token,
|
||||||
|
'password' => $password,
|
||||||
|
'mountpoint' => $mountPoint,
|
||||||
|
'owner' => $owner
|
||||||
|
);
|
||||||
|
return $this->mountShare($options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setup() {
|
||||||
|
// don't setup server-to-server shares if the file_external app is disabled
|
||||||
|
// FIXME no longer needed if we use the webdav implementation from core
|
||||||
|
if (\OC_App::isEnabled('files_external') === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$user = $this->userSession->getUser();
|
||||||
|
if ($user) {
|
||||||
|
$query = $this->connection->prepare('SELECT `remote`, `share_token`, `password`, `mountpoint`, `owner`
|
||||||
|
FROM *PREFIX*share_external WHERE `user` = ?');
|
||||||
|
$query->execute(array($user->getUID()));
|
||||||
|
|
||||||
|
while ($row = $query->fetch()) {
|
||||||
|
$row['manager'] = $this;
|
||||||
|
$row['token'] = $row['share_token'];
|
||||||
|
$this->mountShare($row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function stripPath($path) {
|
||||||
|
$prefix = '/' . $this->userSession->getUser()->getUID() . '/files';
|
||||||
|
return rtrim(substr($path, strlen($prefix)), '/');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $data
|
||||||
|
* @return Mount
|
||||||
|
*/
|
||||||
|
protected function mountShare($data) {
|
||||||
|
$mountPoint = '/' . $this->userSession->getUser()->getUID() . '/files' . $data['mountpoint'];
|
||||||
|
$mount = new Mount(self::STORAGE, $mountPoint, $data, $this, $this->storageLoader);
|
||||||
|
$this->mountManager->addMount($mount);
|
||||||
|
return $mount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \OC\Files\Mount\Manager
|
||||||
|
*/
|
||||||
|
public function getMountManager() {
|
||||||
|
return $this->mountManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $source
|
||||||
|
* @param string $target
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function setMountPoint($source, $target) {
|
||||||
|
$user = $this->userSession->getUser();
|
||||||
|
$source = $this->stripPath($source);
|
||||||
|
$target = $this->stripPath($target);
|
||||||
|
$sourceHash = md5($source);
|
||||||
|
$targetHash = md5($target);
|
||||||
|
|
||||||
|
$query = $this->connection->prepare('UPDATE *PREFIX*share_external SET
|
||||||
|
`mountpoint` = ?, `mountpoint_hash` = ? WHERE `mountpoint_hash` = ? AND `user` = ?');
|
||||||
|
$result = (bool)$query->execute(array($target, $targetHash, $sourceHash, $user->getUID()));
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function removeShare($mountPoint) {
|
||||||
|
$user = $this->userSession->getUser();
|
||||||
|
$mountPoint = $this->stripPath($mountPoint);
|
||||||
|
$hash = md5($mountPoint);
|
||||||
|
$query = $this->connection->prepare('DELETE FROM *PREFIX*share_external WHERE `mountpoint_hash` = ? AND `user` = ?');
|
||||||
|
return (bool)$query->execute(array($hash, $user->getUID()));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
|
||||||
|
* This file is licensed under the Affero General Public License version 3 or
|
||||||
|
* later.
|
||||||
|
* See the COPYING-README file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace OCA\Files_Sharing\External;
|
||||||
|
|
||||||
|
use OC\Files\Mount\MoveableMount;
|
||||||
|
|
||||||
|
class Mount extends \OC\Files\Mount\Mount implements MoveableMount {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \OCA\Files_Sharing\External\Manager
|
||||||
|
*/
|
||||||
|
protected $manager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string|\OC\Files\Storage\Storage $storage
|
||||||
|
* @param string $mountpoint
|
||||||
|
* @param array $options
|
||||||
|
* @param \OCA\Files_Sharing\External\Manager $manager
|
||||||
|
* @param \OC\Files\Storage\Loader $loader
|
||||||
|
*/
|
||||||
|
public function __construct($storage, $mountpoint, $options, $manager, $loader = null) {
|
||||||
|
parent::__construct($storage, $mountpoint, $options, $loader);
|
||||||
|
$this->manager = $manager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Move the mount point to $target
|
||||||
|
*
|
||||||
|
* @param string $target the target mount point
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function moveMount($target) {
|
||||||
|
$result = $this->manager->setMountPoint($this->mountPoint, $target);
|
||||||
|
$this->setMountPoint($target);
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the mount points
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function removeMount() {
|
||||||
|
return $this->manager->removeShare($this->mountPoint);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
|
||||||
|
* This file is licensed under the Affero General Public License version 3 or
|
||||||
|
* later.
|
||||||
|
* See the COPYING-README file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace OCA\Files_Sharing\External;
|
||||||
|
|
||||||
|
class Scanner extends \OC\Files\Cache\Scanner {
|
||||||
|
/**
|
||||||
|
* @var \OCA\Files_Sharing\External\Storage
|
||||||
|
*/
|
||||||
|
protected $storage;
|
||||||
|
|
||||||
|
public function scan($path, $recursive = self::SCAN_RECURSIVE, $reuse = -1) {
|
||||||
|
$this->scanAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scanAll() {
|
||||||
|
$remote = $this->storage->getRemote();
|
||||||
|
$token = $this->storage->getToken();
|
||||||
|
$password = $this->storage->getPassword();
|
||||||
|
$url = $remote . '/index.php/apps/files_sharing/shareinfo?t=' . $token;
|
||||||
|
|
||||||
|
$ch = curl_init();
|
||||||
|
|
||||||
|
curl_setopt($ch, CURLOPT_URL, $url);
|
||||||
|
curl_setopt($ch, CURLOPT_POST, 1);
|
||||||
|
curl_setopt($ch, CURLOPT_POSTFIELDS,
|
||||||
|
http_build_query(array('password' => $password)));
|
||||||
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||||
|
|
||||||
|
$result = curl_exec($ch);
|
||||||
|
curl_close($ch);
|
||||||
|
|
||||||
|
$data = json_decode($result, true);
|
||||||
|
if ($data['status'] === 'success') {
|
||||||
|
$this->addResult($data['data'], '');
|
||||||
|
} else {
|
||||||
|
throw new \Exception('Error while scanning remote share');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function addResult($data, $path) {
|
||||||
|
$this->cache->put($path, $data);
|
||||||
|
if (isset($data['children'])) {
|
||||||
|
foreach ($data['children'] as $child) {
|
||||||
|
$this->addResult($child, ltrim($path . '/' . $child['name'], '/'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,103 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
|
||||||
|
* This file is licensed under the Affero General Public License version 3 or
|
||||||
|
* later.
|
||||||
|
* See the COPYING-README file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace OCA\Files_Sharing\External;
|
||||||
|
|
||||||
|
use OC\Files\Filesystem;
|
||||||
|
use OC\Files\Storage\DAV;
|
||||||
|
use OCA\Files_Sharing\ISharedStorage;
|
||||||
|
|
||||||
|
class Storage extends DAV implements ISharedStorage {
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $remoteUser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $remote;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $mountPoint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $token;
|
||||||
|
|
||||||
|
public function __construct($options) {
|
||||||
|
$this->remote = $options['remote'];
|
||||||
|
$this->remoteUser = $options['owner'];
|
||||||
|
list($protocol, $remote) = explode('://', $this->remote);
|
||||||
|
list($host, $root) = explode('/', $remote);
|
||||||
|
$secure = $protocol === 'https';
|
||||||
|
$root .= '/public.php/webdav';
|
||||||
|
$this->mountPoint = $options['mountpoint'];
|
||||||
|
$this->token = $options['token'];
|
||||||
|
parent::__construct(array(
|
||||||
|
'secure' => $secure,
|
||||||
|
'host' => $host,
|
||||||
|
'root' => $root,
|
||||||
|
'user' => $options['token'],
|
||||||
|
'password' => $options['password']
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRemoteUser() {
|
||||||
|
return $this->remoteUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRemote() {
|
||||||
|
return $this->remote;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMountPoint() {
|
||||||
|
return $this->mountPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getToken() {
|
||||||
|
return $this->token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPassword() {
|
||||||
|
return $this->password;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief get id of the mount point
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getId() {
|
||||||
|
return 'shared::' . md5($this->token . '@' . $this->remote);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCache($path = '', $storage = null) {
|
||||||
|
if (!$storage) {
|
||||||
|
$this->cache = new Cache($this, $this->remote, $this->remoteUser);
|
||||||
|
}
|
||||||
|
return $this->cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $path
|
||||||
|
* @param \OC\Files\Storage\Storage $storage
|
||||||
|
* @return \OCA\Files_Sharing\External\Scanner
|
||||||
|
*/
|
||||||
|
public function getScanner($path = '', $storage = null) {
|
||||||
|
if (!$storage) {
|
||||||
|
$storage = $this;
|
||||||
|
}
|
||||||
|
if (!isset($this->scanner)) {
|
||||||
|
$this->scanner = new Scanner($storage);
|
||||||
|
}
|
||||||
|
return $this->scanner;
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,7 +16,7 @@ class Helper {
|
||||||
public static function setupFromToken($token, $relativePath = null, $password = null) {
|
public static function setupFromToken($token, $relativePath = null, $password = null) {
|
||||||
\OC_User::setIncognitoMode(true);
|
\OC_User::setIncognitoMode(true);
|
||||||
|
|
||||||
$linkItem = \OCP\Share::getShareByToken($token);
|
$linkItem = \OCP\Share::getShareByToken($token, !$password);
|
||||||
if($linkItem === false || ($linkItem['item_type'] !== 'file' && $linkItem['item_type'] !== 'folder')) {
|
if($linkItem === false || ($linkItem['item_type'] !== 'file' && $linkItem['item_type'] !== 'folder')) {
|
||||||
\OC_Response::setStatus(404);
|
\OC_Response::setStatus(404);
|
||||||
\OC_Log::write('core-preview', 'Passed token parameter is not valid', \OC_Log::DEBUG);
|
\OC_Log::write('core-preview', 'Passed token parameter is not valid', \OC_Log::DEBUG);
|
||||||
|
@ -202,4 +202,24 @@ class Helper {
|
||||||
|
|
||||||
return $path;
|
return $path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* allow users from other ownCloud instances to mount public links share by this instance
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function isOutgoingServer2serverShareEnabled() {
|
||||||
|
$appConfig = \OC::$server->getAppConfig();
|
||||||
|
$result = $appConfig->getValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes');
|
||||||
|
return ($result === 'yes') ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* allow user to mount public links from onther ownClouds
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function isIncomingServer2serverShareEnabled() {
|
||||||
|
$appConfig = \OC::$server->getAppConfig();
|
||||||
|
$result = $appConfig->getValue('files_sharing', 'incoming_server2server_share_enabled', 'yes');
|
||||||
|
return ($result === 'yes') ? true : false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
|
||||||
|
* This file is licensed under the Affero General Public License version 3 or
|
||||||
|
* later.
|
||||||
|
* See the COPYING-README file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace OCA\Files_Sharing;
|
||||||
|
|
||||||
|
interface ISharedStorage{
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
|
||||||
|
* This file is licensed under the Affero General Public License version 3 or
|
||||||
|
* later.
|
||||||
|
* See the COPYING-README file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace OCA\Files_Sharing;
|
||||||
|
|
||||||
|
use OC\Files\Cache\Cache;
|
||||||
|
|
||||||
|
class ReadOnlyCache extends Cache {
|
||||||
|
public function get($path) {
|
||||||
|
$data = parent::get($path);
|
||||||
|
$data['permissions'] &= (\OCP\PERMISSION_READ | \OCP\PERMISSION_SHARE);
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFolderContents($path) {
|
||||||
|
$content = parent::getFolderContents($path);
|
||||||
|
foreach ($content as &$data) {
|
||||||
|
$data['permissions'] &= (\OCP\PERMISSION_READ | \OCP\PERMISSION_SHARE);
|
||||||
|
}
|
||||||
|
return $content;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
|
||||||
|
* This file is licensed under the Affero General Public License version 3 or
|
||||||
|
* later.
|
||||||
|
* See the COPYING-README file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace OCA\Files_Sharing;
|
||||||
|
|
||||||
|
use OC\Files\Storage\Wrapper\Wrapper;
|
||||||
|
|
||||||
|
class ReadOnlyWrapper extends Wrapper {
|
||||||
|
public function isUpdatable($path) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isCreatable($path) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isDeletable($path) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPermissions($path) {
|
||||||
|
return $this->storage->getPermissions($path) & (\OCP\PERMISSION_READ | \OCP\PERMISSION_SHARE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rename($path1, $path2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function touch($path, $mtime = null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function mkdir($path) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rmdir($path) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function unlink($path) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCache($path = '', $storage = null) {
|
||||||
|
if (!$storage) {
|
||||||
|
$storage = $this;
|
||||||
|
}
|
||||||
|
return new ReadOnlyCache($storage);
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,12 +23,13 @@
|
||||||
|
|
||||||
namespace OC\Files\Storage;
|
namespace OC\Files\Storage;
|
||||||
use OC\Files\Filesystem;
|
use OC\Files\Filesystem;
|
||||||
|
use OCA\Files_Sharing\ISharedStorage;
|
||||||
use OCA\Files_Sharing\SharedMount;
|
use OCA\Files_Sharing\SharedMount;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert target path to source path and pass the function call to the correct storage provider
|
* Convert target path to source path and pass the function call to the correct storage provider
|
||||||
*/
|
*/
|
||||||
class Shared extends \OC\Files\Storage\Common {
|
class Shared extends \OC\Files\Storage\Common implements ISharedStorage {
|
||||||
|
|
||||||
private $share; // the shared resource
|
private $share; // the shared resource
|
||||||
private $files = array();
|
private $files = array();
|
||||||
|
@ -488,16 +489,25 @@ class Shared extends \OC\Files\Storage\Common {
|
||||||
return $this->filemtime($path) > $time;
|
return $this->filemtime($path) > $time;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getCache($path = '') {
|
public function getCache($path = '', $storage = null) {
|
||||||
return new \OC\Files\Cache\Shared_Cache($this);
|
if (!$storage) {
|
||||||
|
$storage = $this;
|
||||||
|
}
|
||||||
|
return new \OC\Files\Cache\Shared_Cache($storage);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getScanner($path = '') {
|
public function getScanner($path = '', $storage = null) {
|
||||||
return new \OC\Files\Cache\Scanner($this);
|
if (!$storage) {
|
||||||
|
$storage = $this;
|
||||||
|
}
|
||||||
|
return new \OC\Files\Cache\Scanner($storage);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getWatcher($path = '') {
|
public function getWatcher($path = '', $storage = null) {
|
||||||
return new \OC\Files\Cache\Shared_Watcher($this);
|
if (!$storage) {
|
||||||
|
$storage = $this;
|
||||||
|
}
|
||||||
|
return new \OC\Files\Cache\Shared_Watcher($storage);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getOwner($path) {
|
public function getOwner($path) {
|
||||||
|
|
|
@ -128,6 +128,7 @@ if (isset($path)) {
|
||||||
$tmpl->assign('mimetype', \OC\Files\Filesystem::getMimeType($path));
|
$tmpl->assign('mimetype', \OC\Files\Filesystem::getMimeType($path));
|
||||||
$tmpl->assign('dirToken', $linkItem['token']);
|
$tmpl->assign('dirToken', $linkItem['token']);
|
||||||
$tmpl->assign('sharingToken', $token);
|
$tmpl->assign('sharingToken', $token);
|
||||||
|
$tmpl->assign('protected', isset($linkItem['share_with']) ? 'true' : 'false');
|
||||||
|
|
||||||
$urlLinkIdentifiers= (isset($token)?'&t='.$token:'')
|
$urlLinkIdentifiers= (isset($token)?'&t='.$token:'')
|
||||||
.(isset($_GET['dir'])?'&dir='.$_GET['dir']:'')
|
.(isset($_GET['dir'])?'&dir='.$_GET['dir']:'')
|
||||||
|
|
|
@ -6,6 +6,10 @@
|
||||||
* See the COPYING-README file.
|
* See the COPYING-README file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
if (OCA\Files_Sharing\Helper::isOutgoingServer2serverShareEnabled() === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// load needed apps
|
// load needed apps
|
||||||
$RUNTIME_APPTYPES = array('filesystem', 'authentication', 'logging');
|
$RUNTIME_APPTYPES = array('filesystem', 'authentication', 'logging');
|
||||||
|
|
||||||
|
@ -37,7 +41,15 @@ $server->addPlugin(new OC_Connector_Sabre_ExceptionLoggerPlugin('webdav'));
|
||||||
$server->subscribeEvent('beforeMethod', function () use ($server, $objectTree, $authBackend) {
|
$server->subscribeEvent('beforeMethod', function () use ($server, $objectTree, $authBackend) {
|
||||||
$share = $authBackend->getShare();
|
$share = $authBackend->getShare();
|
||||||
$owner = $share['uid_owner'];
|
$owner = $share['uid_owner'];
|
||||||
|
$isWritable = $share['permissions'] & (\OCP\PERMISSION_UPDATE | \OCP\PERMISSION_CREATE);
|
||||||
$fileId = $share['file_source'];
|
$fileId = $share['file_source'];
|
||||||
|
|
||||||
|
if (!$isWritable) {
|
||||||
|
\OC\Files\Filesystem::addStorageWrapper('readonly', function ($mountPoint, $storage) {
|
||||||
|
return new \OCA\Files_Sharing\ReadOnlyWrapper(array('storage' => $storage));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
OC_Util::setupFS($owner);
|
OC_Util::setupFS($owner);
|
||||||
$ownerView = \OC\Files\Filesystem::getView();
|
$ownerView = \OC\Files\Filesystem::getView();
|
||||||
$path = $ownerView->getPath($fileId);
|
$path = $ownerView->getPath($fileId);
|
||||||
|
@ -47,8 +59,13 @@ $server->subscribeEvent('beforeMethod', function () use ($server, $objectTree, $
|
||||||
$rootInfo = $view->getFileInfo('');
|
$rootInfo = $view->getFileInfo('');
|
||||||
|
|
||||||
// Create ownCloud Dir
|
// Create ownCloud Dir
|
||||||
$rootDir = new OC_Connector_Sabre_Directory($view, $rootInfo);
|
if ($rootInfo->getType() === 'dir') {
|
||||||
$objectTree->init($rootDir, $view);
|
$root = new OC_Connector_Sabre_Directory($view, $rootInfo);
|
||||||
|
} else {
|
||||||
|
$root = new OC_Connector_Sabre_File($view, $rootInfo);
|
||||||
|
}
|
||||||
|
$mountManager = \OC\Files\Filesystem::getMountManager();
|
||||||
|
$objectTree->init($root, $view, $mountManager);
|
||||||
|
|
||||||
$server->addPlugin(new OC_Connector_Sabre_AbortedUploadDetectionPlugin($view));
|
$server->addPlugin(new OC_Connector_Sabre_AbortedUploadDetectionPlugin($view));
|
||||||
$server->addPlugin(new OC_Connector_Sabre_QuotaPlugin($view));
|
$server->addPlugin(new OC_Connector_Sabre_QuotaPlugin($view));
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2011 Robin Appelman <icewind@owncloud.com>
|
||||||
|
* This file is licensed under the Affero General Public License version 3 or
|
||||||
|
* later.
|
||||||
|
* See the COPYING-README file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
\OC_Util::checkAdminUser();
|
||||||
|
|
||||||
|
\OCP\Util::addScript('files_sharing', 'settings-admin');
|
||||||
|
|
||||||
|
$tmpl = new OCP\Template('files_sharing', 'settings-admin');
|
||||||
|
$tmpl->assign('outgoingServer2serverShareEnabled', OCA\Files_Sharing\Helper::isOutgoingServer2serverShareEnabled());
|
||||||
|
$tmpl->assign('incomingServer2serverShareEnabled', OCA\Files_Sharing\Helper::isIncomingServer2serverShareEnabled());
|
||||||
|
|
||||||
|
return $tmpl->fetchPage();
|
|
@ -15,10 +15,19 @@
|
||||||
src="<?php print_unescaped(image_path('', 'logo-wide.svg')); ?>" alt="<?php p($theme->getName()); ?>" /></a>
|
src="<?php print_unescaped(image_path('', 'logo-wide.svg')); ?>" alt="<?php p($theme->getName()); ?>" /></a>
|
||||||
<div id="logo-claim" style="display:none;"><?php p($theme->getLogoClaim()); ?></div>
|
<div id="logo-claim" style="display:none;"><?php p($theme->getLogoClaim()); ?></div>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
|
<span id="details">
|
||||||
|
<span id="save" data-protected="<?php p($_['protected'])?>" data-owner="<?php p($_['displayName'])?>" data-name="<?php p($_['filename'])?>">
|
||||||
|
<button><?php p($l->t('Save to ownCloud')) ?></button>
|
||||||
|
<form class="save-form hidden" action="#">
|
||||||
|
<input type="text" id="remote_address" placeholder="<?php p($l->t('example.com/owncloud')) ?>"/>
|
||||||
|
<input type="submit" value="<?php p($l->t('Save')) ?>"/>
|
||||||
|
</form>
|
||||||
|
</span>
|
||||||
<a href="<?php p($_['downloadURL']); ?>" id="download" class="button">
|
<a href="<?php p($_['downloadURL']); ?>" id="download" class="button">
|
||||||
<img class="svg" alt="" src="<?php print_unescaped(OCP\image_path("core", "actions/download.svg")); ?>"/>
|
<img class="svg" alt="" src="<?php print_unescaped(OCP\image_path("core", "actions/download.svg")); ?>"/>
|
||||||
<?php p($l->t('Download'))?>
|
<?php p($l->t('Download'))?>
|
||||||
</a>
|
</a>
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div></header>
|
</div></header>
|
||||||
<div id="content">
|
<div id="content">
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
<div class="section" id="fileSharingSettings" >
|
||||||
|
|
||||||
|
<h2><?php p($l->t('File Sharing'));?></h2>
|
||||||
|
|
||||||
|
<input type="checkbox" name="outgoing_server2server_share_enabled" id="outgoingServer2serverShareEnabled"
|
||||||
|
value="1" <?php if ($_['outgoingServer2serverShareEnabled']) print_unescaped('checked="checked"'); ?> />
|
||||||
|
<label for="outgoingServer2serverShareEnabled"><?php p($l->t('Allow other instances to mount public links shared from this server'));?></label><br/>
|
||||||
|
|
||||||
|
<input type="checkbox" name="incoming_server2server_share_enabled" id="incomingServer2serverShareEnabled"
|
||||||
|
value="1" <?php if ($_['incomingServer2serverShareEnabled']) print_unescaped('checked="checked"'); ?> />
|
||||||
|
<label for="incomingServer2serverShareEnabled"><?php p($l->t('Allow users to mount public link shares'));?></label><br/>
|
||||||
|
|
||||||
|
</div>
|
|
@ -202,7 +202,8 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function getQuotaInfo() {
|
public function getQuotaInfo() {
|
||||||
$storageInfo = OC_Helper::getStorageInfo($this->path);
|
$path = \OC\Files\Filesystem::getView()->getRelativePath($this->info->getPath());
|
||||||
|
$storageInfo = OC_Helper::getStorageInfo($path);
|
||||||
return array(
|
return array(
|
||||||
$storageInfo['used'],
|
$storageInfo['used'],
|
||||||
$storageInfo['free']
|
$storageInfo['free']
|
||||||
|
|
|
@ -140,7 +140,7 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements \Sabre\
|
||||||
if (\OC_Util::encryptedFiles()) {
|
if (\OC_Util::encryptedFiles()) {
|
||||||
throw new \Sabre\DAV\Exception\ServiceUnavailable();
|
throw new \Sabre\DAV\Exception\ServiceUnavailable();
|
||||||
} else {
|
} else {
|
||||||
return $this->fileView->fopen($this->path, 'rb');
|
return $this->fileView->fopen(ltrim($this->path, '/'), 'rb');
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ namespace OC\Connector\Sabre;
|
||||||
|
|
||||||
use OC\Files\FileInfo;
|
use OC\Files\FileInfo;
|
||||||
use OC\Files\Filesystem;
|
use OC\Files\Filesystem;
|
||||||
|
use OC\Files\Mount\MoveableMount;
|
||||||
|
|
||||||
class ObjectTree extends \Sabre\DAV\ObjectTree {
|
class ObjectTree extends \Sabre\DAV\ObjectTree {
|
||||||
|
|
||||||
|
@ -18,6 +19,11 @@ class ObjectTree extends \Sabre\DAV\ObjectTree {
|
||||||
*/
|
*/
|
||||||
protected $fileView;
|
protected $fileView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \OC\Files\Mount\Manager
|
||||||
|
*/
|
||||||
|
protected $mountManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the object
|
* Creates the object
|
||||||
*
|
*
|
||||||
|
@ -29,10 +35,12 @@ class ObjectTree extends \Sabre\DAV\ObjectTree {
|
||||||
/**
|
/**
|
||||||
* @param \Sabre\DAV\ICollection $rootNode
|
* @param \Sabre\DAV\ICollection $rootNode
|
||||||
* @param \OC\Files\View $view
|
* @param \OC\Files\View $view
|
||||||
|
* @param \OC\Files\Mount\Manager $mountManager
|
||||||
*/
|
*/
|
||||||
public function init(\Sabre\DAV\ICollection $rootNode, \OC\Files\View $view) {
|
public function init(\Sabre\DAV\ICollection $rootNode, \OC\Files\View $view, \OC\Files\Mount\Manager $mountManager) {
|
||||||
$this->rootNode = $rootNode;
|
$this->rootNode = $rootNode;
|
||||||
$this->fileView = $view;
|
$this->fileView = $view;
|
||||||
|
$this->mountManager = $mountManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -115,14 +123,15 @@ class ObjectTree extends \Sabre\DAV\ObjectTree {
|
||||||
list($sourceDir,) = \Sabre\DAV\URLUtil::splitPath($sourcePath);
|
list($sourceDir,) = \Sabre\DAV\URLUtil::splitPath($sourcePath);
|
||||||
list($destinationDir,) = \Sabre\DAV\URLUtil::splitPath($destinationPath);
|
list($destinationDir,) = \Sabre\DAV\URLUtil::splitPath($destinationPath);
|
||||||
|
|
||||||
$isShareMountPoint = false;
|
$isMovableMount = false;
|
||||||
list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath( '/' . \OCP\User::getUser() . '/files/' . $sourcePath);
|
$sourceMount = $this->mountManager->find($this->fileView->getAbsolutePath($sourcePath));
|
||||||
if ($storage instanceof \OC\Files\Storage\Shared && !$internalPath) {
|
$internalPath = $sourceMount->getInternalPath($this->fileView->getAbsolutePath($sourcePath));
|
||||||
$isShareMountPoint = true;
|
if ($sourceMount instanceof MoveableMount && $internalPath === '') {
|
||||||
|
$isMovableMount = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check update privileges
|
// check update privileges
|
||||||
if (!$this->fileView->isUpdatable($sourcePath) && !$isShareMountPoint) {
|
if (!$this->fileView->isUpdatable($sourcePath) && !$isMovableMount) {
|
||||||
throw new \Sabre\DAV\Exception\Forbidden();
|
throw new \Sabre\DAV\Exception\Forbidden();
|
||||||
}
|
}
|
||||||
if ($sourceDir !== $destinationDir) {
|
if ($sourceDir !== $destinationDir) {
|
||||||
|
@ -132,7 +141,7 @@ class ObjectTree extends \Sabre\DAV\ObjectTree {
|
||||||
if (!$this->fileView->isUpdatable($destinationDir)) {
|
if (!$this->fileView->isUpdatable($destinationDir)) {
|
||||||
throw new \Sabre\DAV\Exception\Forbidden();
|
throw new \Sabre\DAV\Exception\Forbidden();
|
||||||
}
|
}
|
||||||
if (!$this->fileView->isDeletable($sourcePath)) {
|
if (!$this->fileView->isDeletable($sourcePath) && !$isMovableMount) {
|
||||||
throw new \Sabre\DAV\Exception\Forbidden();
|
throw new \Sabre\DAV\Exception\Forbidden();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,20 +22,20 @@ class Cache {
|
||||||
/**
|
/**
|
||||||
* @var array partial data for the cache
|
* @var array partial data for the cache
|
||||||
*/
|
*/
|
||||||
private $partial = array();
|
protected $partial = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
private $storageId;
|
protected $storageId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var Storage $storageCache
|
* @var Storage $storageCache
|
||||||
*/
|
*/
|
||||||
private $storageCache;
|
protected $storageCache;
|
||||||
|
|
||||||
private static $mimetypeIds = array();
|
protected static $mimetypeIds = array();
|
||||||
private static $mimetypes = array();
|
protected static $mimetypes = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param \OC\Files\Storage\Storage|string $storage
|
* @param \OC\Files\Storage\Storage|string $storage
|
||||||
|
|
|
@ -287,31 +287,43 @@ abstract class Common implements \OC\Files\Storage\Storage {
|
||||||
return $this->filemtime($path) > $time;
|
return $this->filemtime($path) > $time;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getCache($path = '') {
|
public function getCache($path = '', $storage = null) {
|
||||||
|
if (!$storage) {
|
||||||
|
$storage = $this;
|
||||||
|
}
|
||||||
if (!isset($this->cache)) {
|
if (!isset($this->cache)) {
|
||||||
$this->cache = new \OC\Files\Cache\Cache($this);
|
$this->cache = new \OC\Files\Cache\Cache($storage);
|
||||||
}
|
}
|
||||||
return $this->cache;
|
return $this->cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getScanner($path = '') {
|
public function getScanner($path = '', $storage = null) {
|
||||||
|
if (!$storage) {
|
||||||
|
$storage = $this;
|
||||||
|
}
|
||||||
if (!isset($this->scanner)) {
|
if (!isset($this->scanner)) {
|
||||||
$this->scanner = new \OC\Files\Cache\Scanner($this);
|
$this->scanner = new \OC\Files\Cache\Scanner($storage);
|
||||||
}
|
}
|
||||||
return $this->scanner;
|
return $this->scanner;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getWatcher($path = '') {
|
public function getWatcher($path = '', $storage = null) {
|
||||||
|
if (!$storage) {
|
||||||
|
$storage = $this;
|
||||||
|
}
|
||||||
if (!isset($this->watcher)) {
|
if (!isset($this->watcher)) {
|
||||||
$this->watcher = new \OC\Files\Cache\Watcher($this);
|
$this->watcher = new \OC\Files\Cache\Watcher($storage);
|
||||||
$this->watcher->setPolicy(\OC::$server->getConfig()->getSystemValue('filesystem_check_changes', Watcher::CHECK_ONCE));
|
$this->watcher->setPolicy(\OC::$server->getConfig()->getSystemValue('filesystem_check_changes', Watcher::CHECK_ONCE));
|
||||||
}
|
}
|
||||||
return $this->watcher;
|
return $this->watcher;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getStorageCache() {
|
public function getStorageCache($storage = null) {
|
||||||
|
if (!$storage) {
|
||||||
|
$storage = $this;
|
||||||
|
}
|
||||||
if (!isset($this->storageCache)) {
|
if (!isset($this->storageCache)) {
|
||||||
$this->storageCache = new \OC\Files\Cache\Storage($this);
|
$this->storageCache = new \OC\Files\Cache\Storage($storage);
|
||||||
}
|
}
|
||||||
return $this->storageCache;
|
return $this->storageCache;
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,9 +49,12 @@ class Home extends Local {
|
||||||
/**
|
/**
|
||||||
* @return \OC\Files\Cache\HomeCache
|
* @return \OC\Files\Cache\HomeCache
|
||||||
*/
|
*/
|
||||||
public function getCache($path = '') {
|
public function getCache($path = '', $storage = null) {
|
||||||
|
if (!$storage) {
|
||||||
|
$storage = $this;
|
||||||
|
}
|
||||||
if (!isset($this->cache)) {
|
if (!isset($this->cache)) {
|
||||||
$this->cache = new \OC\Files\Cache\HomeCache($this);
|
$this->cache = new \OC\Files\Cache\HomeCache($storage);
|
||||||
}
|
}
|
||||||
return $this->cache;
|
return $this->cache;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,17 +19,19 @@ interface Storage extends \OCP\Files\Storage {
|
||||||
* get a cache instance for the storage
|
* get a cache instance for the storage
|
||||||
*
|
*
|
||||||
* @param string $path
|
* @param string $path
|
||||||
|
* @param \OC\Files\Storage\Storage (optional) the storage to pass to the cache
|
||||||
* @return \OC\Files\Cache\Cache
|
* @return \OC\Files\Cache\Cache
|
||||||
*/
|
*/
|
||||||
public function getCache($path = '');
|
public function getCache($path = '', $storage = null);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get a scanner instance for the storage
|
* get a scanner instance for the storage
|
||||||
*
|
*
|
||||||
* @param string $path
|
* @param string $path
|
||||||
|
* @param \OC\Files\Storage\Storage (optional) the storage to pass to the scanner
|
||||||
* @return \OC\Files\Cache\Scanner
|
* @return \OC\Files\Cache\Scanner
|
||||||
*/
|
*/
|
||||||
public function getScanner($path = '');
|
public function getScanner($path = '', $storage = null);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -44,9 +46,10 @@ interface Storage extends \OCP\Files\Storage {
|
||||||
* get a watcher instance for the cache
|
* get a watcher instance for the cache
|
||||||
*
|
*
|
||||||
* @param string $path
|
* @param string $path
|
||||||
|
* @param \OC\Files\Storage\Storage (optional) the storage to pass to the watcher
|
||||||
* @return \OC\Files\Cache\Watcher
|
* @return \OC\Files\Cache\Watcher
|
||||||
*/
|
*/
|
||||||
public function getWatcher($path = '');
|
public function getWatcher($path = '', $storage = null);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return \OC\Files\Cache\Storage
|
* @return \OC\Files\Cache\Storage
|
||||||
|
|
|
@ -361,20 +361,28 @@ class Wrapper implements \OC\Files\Storage\Storage {
|
||||||
* get a cache instance for the storage
|
* get a cache instance for the storage
|
||||||
*
|
*
|
||||||
* @param string $path
|
* @param string $path
|
||||||
|
* @param \OC\Files\Storage\Storage (optional) the storage to pass to the cache
|
||||||
* @return \OC\Files\Cache\Cache
|
* @return \OC\Files\Cache\Cache
|
||||||
*/
|
*/
|
||||||
public function getCache($path = '') {
|
public function getCache($path = '', $storage = null) {
|
||||||
return $this->storage->getCache($path);
|
if (!$storage) {
|
||||||
|
$storage = $this;
|
||||||
|
}
|
||||||
|
return $this->storage->getCache($path, $storage);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get a scanner instance for the storage
|
* get a scanner instance for the storage
|
||||||
*
|
*
|
||||||
* @param string $path
|
* @param string $path
|
||||||
|
* @param \OC\Files\Storage\Storage (optional) the storage to pass to the scanner
|
||||||
* @return \OC\Files\Cache\Scanner
|
* @return \OC\Files\Cache\Scanner
|
||||||
*/
|
*/
|
||||||
public function getScanner($path = '') {
|
public function getScanner($path = '', $storage = null) {
|
||||||
return $this->storage->getScanner($path);
|
if (!$storage) {
|
||||||
|
$storage = $this;
|
||||||
|
}
|
||||||
|
return $this->storage->getScanner($path, $storage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -392,10 +400,14 @@ class Wrapper implements \OC\Files\Storage\Storage {
|
||||||
* get a watcher instance for the cache
|
* get a watcher instance for the cache
|
||||||
*
|
*
|
||||||
* @param string $path
|
* @param string $path
|
||||||
|
* @param \OC\Files\Storage\Storage (optional) the storage to pass to the watcher
|
||||||
* @return \OC\Files\Cache\Watcher
|
* @return \OC\Files\Cache\Watcher
|
||||||
*/
|
*/
|
||||||
public function getWatcher($path = '') {
|
public function getWatcher($path = '', $storage = null) {
|
||||||
return $this->storage->getWatcher($path);
|
if (!$storage) {
|
||||||
|
$storage = $this;
|
||||||
|
}
|
||||||
|
return $this->storage->getWatcher($path, $storage);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -417,6 +429,7 @@ class Wrapper implements \OC\Files\Storage\Storage {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true
|
* Returns true
|
||||||
|
*
|
||||||
* @return true
|
* @return true
|
||||||
*/
|
*/
|
||||||
public function test() {
|
public function test() {
|
||||||
|
@ -425,6 +438,7 @@ class Wrapper implements \OC\Files\Storage\Storage {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the wrapped storage's value for isLocal()
|
* Returns the wrapped storage's value for isLocal()
|
||||||
|
*
|
||||||
* @return bool wrapped storage's isLocal() value
|
* @return bool wrapped storage's isLocal() value
|
||||||
*/
|
*/
|
||||||
public function isLocal() {
|
public function isLocal() {
|
||||||
|
|
|
@ -161,7 +161,34 @@ class View {
|
||||||
return $this->basicOperation('mkdir', $path, array('create', 'write'));
|
return $this->basicOperation('mkdir', $path, array('create', 'write'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function removeMount($mount, $path){
|
||||||
|
if ($mount instanceof MoveableMount) {
|
||||||
|
\OC_Hook::emit(
|
||||||
|
Filesystem::CLASSNAME, "umount",
|
||||||
|
array(Filesystem::signal_param_path => $path)
|
||||||
|
);
|
||||||
|
$result = $mount->removeMount();
|
||||||
|
if ($result) {
|
||||||
|
\OC_Hook::emit(
|
||||||
|
Filesystem::CLASSNAME, "post_umount",
|
||||||
|
array(Filesystem::signal_param_path => $path)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
} else {
|
||||||
|
// do not allow deleting the storage's root / the mount point
|
||||||
|
// because for some storages it might delete the whole contents
|
||||||
|
// but isn't supposed to work that way
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function rmdir($path) {
|
public function rmdir($path) {
|
||||||
|
$absolutePath= $this->getAbsolutePath($path);
|
||||||
|
$mount = Filesystem::getMountManager()->find($absolutePath);
|
||||||
|
if ($mount->getInternalPath($absolutePath) === '') {
|
||||||
|
return $this->removeMount($mount, $path);
|
||||||
|
}
|
||||||
if ($this->is_dir($path)) {
|
if ($this->is_dir($path)) {
|
||||||
return $this->basicOperation('rmdir', $path, array('delete'));
|
return $this->basicOperation('rmdir', $path, array('delete'));
|
||||||
} else {
|
} else {
|
||||||
|
@ -360,25 +387,7 @@ class View {
|
||||||
$absolutePath = Filesystem::normalizePath($this->getAbsolutePath($path));
|
$absolutePath = Filesystem::normalizePath($this->getAbsolutePath($path));
|
||||||
$mount = Filesystem::getMountManager()->find($absolutePath . $postFix);
|
$mount = Filesystem::getMountManager()->find($absolutePath . $postFix);
|
||||||
if ($mount->getInternalPath($absolutePath) === '') {
|
if ($mount->getInternalPath($absolutePath) === '') {
|
||||||
if ($mount instanceof MoveableMount) {
|
return $this->removeMount($mount, $path);
|
||||||
\OC_Hook::emit(
|
|
||||||
Filesystem::CLASSNAME, "umount",
|
|
||||||
array(Filesystem::signal_param_path => $path)
|
|
||||||
);
|
|
||||||
$result = $mount->removeMount();
|
|
||||||
if ($result) {
|
|
||||||
\OC_Hook::emit(
|
|
||||||
Filesystem::CLASSNAME, "post_umount",
|
|
||||||
array(Filesystem::signal_param_path => $path)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return $result;
|
|
||||||
} else {
|
|
||||||
// do not allow deleting the storage's root / the mount point
|
|
||||||
// because for some storages it might delete the whole contents
|
|
||||||
// but isn't supposed to work that way
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return $this->basicOperation('unlink', $path, array('delete'));
|
return $this->basicOperation('unlink', $path, array('delete'));
|
||||||
}
|
}
|
||||||
|
@ -836,11 +845,10 @@ class View {
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
$path = Filesystem::normalizePath($this->fakeRoot . '/' . $path);
|
$path = Filesystem::normalizePath($this->fakeRoot . '/' . $path);
|
||||||
/**
|
|
||||||
* @var \OC\Files\Storage\Storage $storage
|
$mount = Filesystem::getMountManager()->find($path);
|
||||||
* @var string $internalPath
|
$storage = $mount->getStorage();
|
||||||
*/
|
$internalPath = $mount->getInternalPath($path);
|
||||||
list($storage, $internalPath) = Filesystem::resolvePath($path);
|
|
||||||
$data = null;
|
$data = null;
|
||||||
if ($storage) {
|
if ($storage) {
|
||||||
$cache = $storage->getCache($internalPath);
|
$cache = $storage->getCache($internalPath);
|
||||||
|
@ -888,6 +896,10 @@ class View {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($mount instanceof MoveableMount) {
|
||||||
|
$data['permissions'] |= \OCP\PERMISSION_DELETE | \OCP\PERMISSION_UPDATE;
|
||||||
|
}
|
||||||
|
|
||||||
$data = \OC_FileProxy::runPostProxies('getFileInfo', $path, $data);
|
$data = \OC_FileProxy::runPostProxies('getFileInfo', $path, $data);
|
||||||
|
|
||||||
return new FileInfo($path, $storage, $internalPath, $data);
|
return new FileInfo($path, $storage, $internalPath, $data);
|
||||||
|
|
|
@ -940,7 +940,7 @@ class OC_Helper {
|
||||||
// return storage info without adding mount points
|
// return storage info without adding mount points
|
||||||
$includeExtStorage = \OC_Config::getValue('quota_include_external_storage', false);
|
$includeExtStorage = \OC_Config::getValue('quota_include_external_storage', false);
|
||||||
|
|
||||||
if (is_null($rootInfo)) {
|
if (!$rootInfo) {
|
||||||
$rootInfo = \OC\Files\Filesystem::getFileInfo($path, false);
|
$rootInfo = \OC\Files\Filesystem::getFileInfo($path, false);
|
||||||
}
|
}
|
||||||
$used = $rootInfo->getSize();
|
$used = $rootInfo->getSize();
|
||||||
|
|
|
@ -508,9 +508,9 @@ class Share extends \OC\Share\Constants {
|
||||||
if ($itemType === 'folder') {
|
if ($itemType === 'folder') {
|
||||||
$path = '/' . $uidOwner . '/files' . \OC\Files\Filesystem::getPath($itemSource) . '/';
|
$path = '/' . $uidOwner . '/files' . \OC\Files\Filesystem::getPath($itemSource) . '/';
|
||||||
$mountManager = \OC\Files\Filesystem::getMountManager();
|
$mountManager = \OC\Files\Filesystem::getMountManager();
|
||||||
$mounts = $mountManager->getAll();
|
$mounts = $mountManager->findIn($path);
|
||||||
foreach ($mounts as $mountPoint => $mount) {
|
foreach ($mounts as $mount) {
|
||||||
if ($mount->getStorage() instanceof \OC\Files\Storage\Shared && strpos($mountPoint, $path) === 0) {
|
if ($mount->getStorage()->instanceOfStorage('\OCA\Files_Sharing\ISharedStorage')) {
|
||||||
$message = 'Sharing "' . $itemSourceName . '" failed, because it contains files shared with you!';
|
$message = 'Sharing "' . $itemSourceName . '" failed, because it contains files shared with you!';
|
||||||
\OC_Log::write('OCP\Share', $message, \OC_Log::ERROR);
|
\OC_Log::write('OCP\Share', $message, \OC_Log::ERROR);
|
||||||
throw new \Exception($message);
|
throw new \Exception($message);
|
||||||
|
|
|
@ -110,7 +110,8 @@ class ObjectTree extends PHPUnit_Framework_TestCase {
|
||||||
->will($this->returnValue(false));
|
->will($this->returnValue(false));
|
||||||
|
|
||||||
/** @var $objectTree \OC\Connector\Sabre\ObjectTree */
|
/** @var $objectTree \OC\Connector\Sabre\ObjectTree */
|
||||||
$objectTree->init($rootDir, $view);
|
$mountManager = \OC\Files\Filesystem::getMountManager();
|
||||||
|
$objectTree->init($rootDir, $view, $mountManager);
|
||||||
$objectTree->move($source, $dest);
|
$objectTree->move($source, $dest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue