mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-12-27 00:58:55 +01:00
WIP on sharing prompt to ask about mounting new share
This commit is contained in:
parent
7c9e1c98ec
commit
5bf4d4866f
@ -334,7 +334,7 @@
|
|||||||
et2.load(data.name,data.url,data.data);
|
et2.load(data.name,data.url,data.data);
|
||||||
if (typeof data.response != 'undefined')
|
if (typeof data.response != 'undefined')
|
||||||
{
|
{
|
||||||
var json_request = egw(window).json();
|
var json_request = egw(window).json("");
|
||||||
json_request.handleResponse({response: data.response});
|
json_request.handleResponse({response: data.response});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -180,6 +180,14 @@ class Base
|
|||||||
}
|
}
|
||||||
unset(self::$fstab[$path], $GLOBALS['egw_info']['server']['vfs_fstab'][$path]);
|
unset(self::$fstab[$path], $GLOBALS['egw_info']['server']['vfs_fstab'][$path]);
|
||||||
Config::save_value('vfs_fstab', $GLOBALS['egw_info']['server']['vfs_fstab'],'phpgwapi');
|
Config::save_value('vfs_fstab', $GLOBALS['egw_info']['server']['vfs_fstab'],'phpgwapi');
|
||||||
|
|
||||||
|
unset($GLOBALS['egw_info']['user']['preferences']['common']['vfs_fstab'][$path]);
|
||||||
|
unset($_SESSION[Api\Session::EGW_INFO_CACHE]['user']['preferences']['common']['vfs_fstab'][$path]);
|
||||||
|
$prefs = new Api\Preferences();
|
||||||
|
$prefs->read_repository();
|
||||||
|
unset($prefs->user['common']['vfs_fstab'][$path]);
|
||||||
|
$prefs->save_repository();
|
||||||
|
|
||||||
// invalidate session cache
|
// invalidate session cache
|
||||||
if (method_exists($GLOBALS['egw'],'invalidate_session_cache')) // egw object in setup is limited
|
if (method_exists($GLOBALS['egw'],'invalidate_session_cache')) // egw object in setup is limited
|
||||||
{
|
{
|
||||||
|
@ -14,6 +14,7 @@ namespace EGroupware\Api\Vfs;
|
|||||||
|
|
||||||
use EGroupware\Api;
|
use EGroupware\Api;
|
||||||
use EGroupware\Api\Vfs;
|
use EGroupware\Api\Vfs;
|
||||||
|
use EGroupware\Filemanager\Sharing\HiddenUpload;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* VFS sharing for a folder, but always read-only. A /Upload directory is used to receive uploads without allowing any
|
* VFS sharing for a folder, but always read-only. A /Upload directory is used to receive uploads without allowing any
|
||||||
@ -187,7 +188,7 @@ class HiddenUploadSharing extends Sharing
|
|||||||
$GLOBALS['egw_info']['flags']['currentapp'] = 'filemanager';
|
$GLOBALS['egw_info']['flags']['currentapp'] = 'filemanager';
|
||||||
Api\Framework::includeCSS('filemanager', 'sharing');
|
Api\Framework::includeCSS('filemanager', 'sharing');
|
||||||
|
|
||||||
$ui = new UploadSharingUi();
|
$ui = new HiddenUpload();
|
||||||
$ui->index();
|
$ui->index();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,138 +205,3 @@ class HiddenUploadSharing extends Sharing
|
|||||||
static::setup_share(true, $this->share);
|
static::setup_share(true, $this->share);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (file_exists(__DIR__.'/../../../filemanager/inc/class.filemanager_ui.inc.php'))
|
|
||||||
{
|
|
||||||
require_once __DIR__.'/../../../filemanager/inc/class.filemanager_ui.inc.php';
|
|
||||||
|
|
||||||
class UploadSharingUi extends SharingUi
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get active view - override so it points to this class
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public static function get_view()
|
|
||||||
{
|
|
||||||
return array(new UploadSharingUi(), 'listview');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Filemanager listview
|
|
||||||
*
|
|
||||||
* Override to customize for sharing with a hidden upload directory.
|
|
||||||
* Everything not in the upload directory is readonly, but we make it look like you can upload.
|
|
||||||
* The upload directory is not shown.
|
|
||||||
*
|
|
||||||
* @param array $content
|
|
||||||
* @param string $msg
|
|
||||||
*/
|
|
||||||
function listview(array $content=null,$msg=null)
|
|
||||||
{
|
|
||||||
$this->etemplate = $this->etemplate ? $this->etemplate : new Api\Etemplate(static::LIST_TEMPLATE);
|
|
||||||
|
|
||||||
if (isset($GLOBALS['egw']->sharing) && $GLOBALS['egw']->sharing->has_hidden_upload())
|
|
||||||
{
|
|
||||||
// Tell client side that the path is actually writable
|
|
||||||
$content['initial_path_readonly'] = false;
|
|
||||||
|
|
||||||
// No new anything
|
|
||||||
$this->etemplate->disableElement('nm[new]');
|
|
||||||
$this->etemplate->setElementAttribute('nm[button][createdir]', 'readonly', true);
|
|
||||||
|
|
||||||
// Take over upload, change target and conflict strategy
|
|
||||||
$path = Vfs::concat(self::get_home_dir(), Sharing::HIDDEN_UPLOAD_DIR);
|
|
||||||
$target = str_replace('\\', '\\\\', __CLASS__);
|
|
||||||
$this->etemplate->setElementAttribute('nm[upload]', 'onFinishOne', "app.filemanager.upload(ev, 1, '$path', 'rename', '{$target}::ajax_action')");
|
|
||||||
}
|
|
||||||
|
|
||||||
return parent::listview($content, $msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deal with an uploaded file.
|
|
||||||
* Overridden from the parent to change the message and message type
|
|
||||||
*
|
|
||||||
* @param string $action Should be 'upload'
|
|
||||||
* @param $selected Array of file information
|
|
||||||
* @param string $dir Target directory
|
|
||||||
* @param $props
|
|
||||||
* @param string[] $arr Result
|
|
||||||
*
|
|
||||||
* @throws Api\Exception\AssertionFailed
|
|
||||||
*/
|
|
||||||
protected static function handle_upload_action(string $action, $selected, $dir, $props, &$arr)
|
|
||||||
{
|
|
||||||
Api\Translation::add_app('filemanager');
|
|
||||||
$vfs = Vfs::mount();
|
|
||||||
$GLOBALS['egw']->sharing->redo();
|
|
||||||
parent::handle_upload_action($action, $selected, $dir, $props, $arr);
|
|
||||||
$arr['msg'] .= "\n" . lang("The uploaded file is only visible to the person sharing these files with you, not to yourself or other people knowing this sharing link.");
|
|
||||||
$arr['type'] = 'notice';
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function is_hidden_upload_dir($directory)
|
|
||||||
{
|
|
||||||
if (!isset($GLOBALS['egw']->sharing)) return false;
|
|
||||||
// Just hide anything that is 'Upload' mounted where we expect, not just this share, to avoid exposing when
|
|
||||||
// more than one share is used
|
|
||||||
$mounts = Vfs::mount();
|
|
||||||
return Vfs::is_dir($directory) && '/'.Vfs::basename($directory) == Sharing::HIDDEN_UPLOAD_DIR && $mounts[$directory];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback to fetch the rows for the nextmatch widget
|
|
||||||
*
|
|
||||||
* @param array $query
|
|
||||||
* @param array &$rows
|
|
||||||
* @return int
|
|
||||||
*
|
|
||||||
* @throws Api\Json\Exception
|
|
||||||
*/
|
|
||||||
function get_rows(&$query, &$rows)
|
|
||||||
{
|
|
||||||
$hidden_upload = (isset($GLOBALS['egw']->sharing) && $GLOBALS['egw']->sharing->has_hidden_upload());
|
|
||||||
|
|
||||||
// Not allowed in hidden upload dir
|
|
||||||
$check_path = Sharing::HIDDEN_UPLOAD_DIR . (substr($query['path'], -1) == '/' ? '/' : '');
|
|
||||||
if(($length = strlen($check_path)) && (substr($query['path'], -$length) === $check_path))
|
|
||||||
{
|
|
||||||
// only redirect, if it would be to some other location, gives redirect-loop otherwise
|
|
||||||
if ($query['path'] != ($path = static::get_home_dir()))
|
|
||||||
{
|
|
||||||
// we will leave here, since we are not allowed, go back to root
|
|
||||||
// TODO: Give message about it, redirect to home dir
|
|
||||||
}
|
|
||||||
$rows = array();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get file list from parent
|
|
||||||
$total = parent::get_rows($query, $rows);
|
|
||||||
|
|
||||||
if(! $hidden_upload )
|
|
||||||
{
|
|
||||||
return $total;
|
|
||||||
}
|
|
||||||
|
|
||||||
// tell client-side that this directory is writeable - allows upload + button
|
|
||||||
$response = Api\Json\Response::get();
|
|
||||||
$response->call('app.filemanager.set_readonly', $query['path'], false);
|
|
||||||
|
|
||||||
// Hide the hidden upload directory, mark everything else as readonly
|
|
||||||
foreach($rows as $key => &$row)
|
|
||||||
{
|
|
||||||
if($this->is_hidden_upload_dir($row['path']))
|
|
||||||
{
|
|
||||||
unset($rows[$key]);
|
|
||||||
$total--;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$row['class'] .= 'noEdit noDelete ';
|
|
||||||
}
|
|
||||||
return $total;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -15,8 +15,9 @@ namespace EGroupware\Api\Vfs;
|
|||||||
|
|
||||||
use EGroupware\Api;
|
use EGroupware\Api;
|
||||||
use EGroupware\Api\Vfs;
|
use EGroupware\Api\Vfs;
|
||||||
use EGroupware\Collabora\Wopi;
|
use EGroupware\Filemanager\Sharing\AnonymousList;
|
||||||
use filemanager_ui;
|
use EGroupware\Filemanager\Sharing\Ui;
|
||||||
|
use EGroupware\Filemanager\Sharing\Ui as ShareUi;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* VFS sharing
|
* VFS sharing
|
||||||
@ -119,7 +120,7 @@ class Sharing extends \EGroupware\Api\Sharing
|
|||||||
// ToDo: handle there's already something there with that name (incl. maybe the same share!)
|
// ToDo: handle there's already something there with that name (incl. maybe the same share!)
|
||||||
|
|
||||||
Vfs::$is_root = true;
|
Vfs::$is_root = true;
|
||||||
if (!Vfs::mount(Vfs\Sharing\StreamWrapper::share2url($share), $share['share_root'], false, false, $clear_fstab))
|
if (!Vfs::mount(Vfs\Sharing\StreamWrapper::share2url($share), $share['share_root'], false, false, false))
|
||||||
{
|
{
|
||||||
sleep(1);
|
sleep(1);
|
||||||
return static::share_fail(
|
return static::share_fail(
|
||||||
@ -129,8 +130,7 @@ class Sharing extends \EGroupware\Api\Sharing
|
|||||||
}
|
}
|
||||||
Vfs::$is_root = false;
|
Vfs::$is_root = false;
|
||||||
|
|
||||||
Api\Framework::message(lang('Share has been mounted into you shares directory').': '.$share['share_root'], 'success');
|
// get_ui() will ask user if he wants the share permanently mounted
|
||||||
// ToDo: ask user if he want's the share permanently mounted
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -233,6 +233,38 @@ class Sharing extends \EGroupware\Api\Sharing
|
|||||||
*/
|
*/
|
||||||
public function get_ui()
|
public function get_ui()
|
||||||
{
|
{
|
||||||
|
// Ask about the share, if the user is not anonymous.
|
||||||
|
// * Link has already been opened in a new tab by this point *
|
||||||
|
if($GLOBALS['egw_info']['user']['account_lid'] !== 'anonymous' && $GLOBALS['egw_info']['user']['account_id'] !== $this->share['owner'])
|
||||||
|
{
|
||||||
|
// Check to see if this is already permanent mounted share
|
||||||
|
$mount_target = Vfs\Sharing\StreamWrapper::share2url($this->share);
|
||||||
|
if(($mounted = array_search($mount_target,$GLOBALS['egw_info']['user']['preferences']['common']['vfs_fstab'])))
|
||||||
|
{
|
||||||
|
Api\Json\Response::get()->apply('window.opener.egw.open_link',[
|
||||||
|
Api\Framework::link('/index.php',[
|
||||||
|
'menuaction' => 'filemanager.filemanager_ui.index',
|
||||||
|
'path' => $mounted
|
||||||
|
]),'filemanager',false,'filemanager'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// New share, ask about it
|
||||||
|
Api\Json\Response::get()->apply('window.opener.egw.open_link',[
|
||||||
|
Api\Framework::link('/index.php',[
|
||||||
|
'menuaction' => 'filemanager.EGroupware\\Filemanager\\Sharing\\Ui.share_received',
|
||||||
|
'token' => $this->share['share_token']
|
||||||
|
]),'filemanager','600x150','filemanager'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Api\Json\Response::get()->apply('window.close');
|
||||||
|
// Still need to load the list after though, since loading it processes what we just added
|
||||||
|
$ui = new \filemanager_ui();
|
||||||
|
return $ui->index();
|
||||||
|
}
|
||||||
|
|
||||||
// run full eTemplate2 UI for directories
|
// run full eTemplate2 UI for directories
|
||||||
$_GET['path'] = $this->share['share_root'];
|
$_GET['path'] = $this->share['share_root'];
|
||||||
$GLOBALS['egw_info']['user']['preferences']['filemanager']['nm_view'] = 'tile';
|
$GLOBALS['egw_info']['user']['preferences']['filemanager']['nm_view'] = 'tile';
|
||||||
@ -240,7 +272,7 @@ class Sharing extends \EGroupware\Api\Sharing
|
|||||||
$GLOBALS['egw_info']['flags']['js_link_registry'] = true;
|
$GLOBALS['egw_info']['flags']['js_link_registry'] = true;
|
||||||
$GLOBALS['egw_info']['flags']['currentapp'] = 'filemanager';
|
$GLOBALS['egw_info']['flags']['currentapp'] = 'filemanager';
|
||||||
Api\Framework::includeCSS('filemanager', 'sharing');
|
Api\Framework::includeCSS('filemanager', 'sharing');
|
||||||
$ui = new SharingUi();
|
$ui = new AnonymousList();
|
||||||
$ui->index();
|
$ui->index();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -547,133 +579,3 @@ class Sharing extends \EGroupware\Api\Sharing
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (file_exists(__DIR__.'/../../../filemanager/inc/class.filemanager_ui.inc.php'))
|
|
||||||
{
|
|
||||||
require_once __DIR__.'/../../../filemanager/inc/class.filemanager_ui.inc.php';
|
|
||||||
|
|
||||||
class SharingUi extends filemanager_ui
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*
|
|
||||||
* Reimplemented to load filemanager translations
|
|
||||||
*/
|
|
||||||
function __construct()
|
|
||||||
{
|
|
||||||
parent::__construct();
|
|
||||||
|
|
||||||
Api\Translation::add_app('filemanager');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get active view - override so it points to this class
|
|
||||||
*
|
|
||||||
* @return callable
|
|
||||||
*/
|
|
||||||
public static function get_view()
|
|
||||||
{
|
|
||||||
return array(new SharingUi(), 'listview');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Filemanager listview
|
|
||||||
*
|
|
||||||
* @param array $content
|
|
||||||
* @param string $msg
|
|
||||||
*/
|
|
||||||
function listview(array $content=null,$msg=null)
|
|
||||||
{
|
|
||||||
$this->etemplate = $this->etemplate ? $this->etemplate : new Api\Etemplate(static::LIST_TEMPLATE);
|
|
||||||
|
|
||||||
// Override and take over get_rows so we can customize
|
|
||||||
$content['nm']['get_rows'] = '.' . get_class($this) . '.get_rows';
|
|
||||||
|
|
||||||
return parent::listview($content, $msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the configured start directory for the current user
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
static function get_home_dir()
|
|
||||||
{
|
|
||||||
return $GLOBALS['egw']->sharing->get_root();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Context menu
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public static function get_actions()
|
|
||||||
{
|
|
||||||
$actions = parent::get_actions();
|
|
||||||
$group = 1;
|
|
||||||
// do not add edit setting action when we are in sharing
|
|
||||||
unset($actions['edit']);
|
|
||||||
if (Vfs::is_writable($GLOBALS['egw']->sharing->get_root()))
|
|
||||||
{
|
|
||||||
return $actions;
|
|
||||||
}
|
|
||||||
$actions+= array(
|
|
||||||
'egw_copy' => array(
|
|
||||||
'enabled' => false,
|
|
||||||
'group' => $group + 0.5,
|
|
||||||
'hideOnDisabled' => true
|
|
||||||
),
|
|
||||||
'egw_copy_add' => array(
|
|
||||||
'enabled' => false,
|
|
||||||
'group' => $group + 0.5,
|
|
||||||
'hideOnDisabled' => true
|
|
||||||
),
|
|
||||||
'paste' => array(
|
|
||||||
'enabled' => false,
|
|
||||||
'group' => $group + 0.5,
|
|
||||||
'hideOnDisabled' => true
|
|
||||||
),
|
|
||||||
);
|
|
||||||
return $actions;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function get_vfs_options($query)
|
|
||||||
{
|
|
||||||
$options = parent::get_vfs_options($query);
|
|
||||||
|
|
||||||
// Hide symlinks
|
|
||||||
// TODO: This hides everything, see Vfs::_check_add() line 648
|
|
||||||
//$options['type'] = '!l';
|
|
||||||
|
|
||||||
return $options;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback to fetch the rows for the nextmatch widget
|
|
||||||
*
|
|
||||||
* @param array $query
|
|
||||||
* @param array &$rows
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
function get_rows(&$query, &$rows)
|
|
||||||
{
|
|
||||||
// Check for navigating outside share, redirect back to share
|
|
||||||
if (!empty($query['path']) && (!Vfs::stat($query['path'],false) || !Vfs::is_dir($query['path']) || !Vfs::check_access($query['path'],Vfs::READABLE)))
|
|
||||||
{
|
|
||||||
// only redirect, if it would be to some other location, gives redirect-loop otherwise
|
|
||||||
if ($query['path'] != ($path = static::get_home_dir()))
|
|
||||||
{
|
|
||||||
// we will leave here, since we are not allowed, go back to root
|
|
||||||
// TODO: Give message about it, redirect to home dir
|
|
||||||
}
|
|
||||||
$rows = array();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get file list from parent
|
|
||||||
$total = parent::get_rows($query, $rows);
|
|
||||||
|
|
||||||
return $total;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -842,7 +842,17 @@ class filemanager_ui
|
|||||||
// feeding the links to dirs to Vfs::find() deletes the content of the dirs, not just the link!
|
// feeding the links to dirs to Vfs::find() deletes the content of the dirs, not just the link!
|
||||||
foreach($selected as $key => $path)
|
foreach($selected as $key => $path)
|
||||||
{
|
{
|
||||||
if (!Vfs::is_dir($path) || Vfs::is_link($path))
|
if (Vfs::is_dir($path) && $GLOBALS['egw_info']['user']['preferences']['common']['vfs_fstab'][$path])
|
||||||
|
{
|
||||||
|
// Trying to delete a share. Unmount.
|
||||||
|
$root = Vfs::$is_root;
|
||||||
|
Vfs::$is_root = true;
|
||||||
|
Vfs::umount($path);
|
||||||
|
Vfs::$is_root = $root;
|
||||||
|
++$dirs;
|
||||||
|
unset($selected[$key]);
|
||||||
|
}
|
||||||
|
else if (!Vfs::is_dir($path) || Vfs::is_link($path))
|
||||||
{
|
{
|
||||||
if (Vfs::unlink($path))
|
if (Vfs::unlink($path))
|
||||||
{
|
{
|
||||||
@ -1705,4 +1715,24 @@ class filemanager_ui
|
|||||||
}
|
}
|
||||||
return $mode;
|
return $mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User just got a new share. Ask the questions, let them customize
|
||||||
|
*
|
||||||
|
* @param array $content
|
||||||
|
*/
|
||||||
|
public function share_received($content = array())
|
||||||
|
{
|
||||||
|
// Deal with returning data & changes
|
||||||
|
|
||||||
|
// Read info for display
|
||||||
|
$content['mount_location'] = $content['share_path'];
|
||||||
|
$sel_options = array();
|
||||||
|
$readonlys = array();
|
||||||
|
$preserve = $content;
|
||||||
|
$template = new Api\Etemplate("api.file_share_received");
|
||||||
|
|
||||||
|
$template->exec(__CLASS__ . '::' . __METHOD__, $content, $sel_options, $readonlys, $preserve, 2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
144
filemanager/src/Sharing/AnonymousList.php
Normal file
144
filemanager/src/Sharing/AnonymousList.php
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* EGroupware - Filemanager - UI for sharing with anonymous user
|
||||||
|
*
|
||||||
|
* @link http://www.egroupware.org
|
||||||
|
* @package filemanager
|
||||||
|
* @author Nathan Gray
|
||||||
|
* @copyright (c) 2020 Nathan Gray
|
||||||
|
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||||
|
*/
|
||||||
|
namespace EGroupware\Filemanager\Sharing;
|
||||||
|
|
||||||
|
use \filemanager_ui;
|
||||||
|
use EGroupware\Api;
|
||||||
|
use EGroupware\Api\Vfs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the file list for an anonymous user.
|
||||||
|
* Logged in users may also end up here, but they will normally just use filemanager_ui
|
||||||
|
*/
|
||||||
|
class AnonymousList extends filemanager_ui
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* Reimplemented to load filemanager translations
|
||||||
|
*/
|
||||||
|
function __construct()
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
|
||||||
|
Api\Translation::add_app('filemanager');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get active view - override so it points to this class
|
||||||
|
*
|
||||||
|
* @return callable
|
||||||
|
*/
|
||||||
|
public static function get_view()
|
||||||
|
{
|
||||||
|
return array(new AnonymousList(), 'listview');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filemanager listview
|
||||||
|
*
|
||||||
|
* @param array $content
|
||||||
|
* @param string $msg
|
||||||
|
*/
|
||||||
|
function listview(array $content = null, $msg = null)
|
||||||
|
{
|
||||||
|
$this->etemplate = $this->etemplate ? $this->etemplate : new Api\Etemplate(static::LIST_TEMPLATE);
|
||||||
|
|
||||||
|
// Override and take over get_rows so we can customize
|
||||||
|
$content['nm']['get_rows'] = '.' . get_class($this) . '.get_rows';
|
||||||
|
|
||||||
|
return parent::listview($content, $msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the configured start directory for the current user
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
static function get_home_dir()
|
||||||
|
{
|
||||||
|
return $GLOBALS['egw']->sharing->get_root();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Context menu
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function get_actions()
|
||||||
|
{
|
||||||
|
$actions = parent::get_actions();
|
||||||
|
$group = 1;
|
||||||
|
// do not add edit setting action when we are in sharing
|
||||||
|
unset($actions['edit']);
|
||||||
|
if (Vfs::is_writable($GLOBALS['egw']->sharing->get_root()))
|
||||||
|
{
|
||||||
|
return $actions;
|
||||||
|
}
|
||||||
|
$actions += array(
|
||||||
|
'egw_copy' => array(
|
||||||
|
'enabled' => false,
|
||||||
|
'group' => $group + 0.5,
|
||||||
|
'hideOnDisabled' => true
|
||||||
|
),
|
||||||
|
'egw_copy_add' => array(
|
||||||
|
'enabled' => false,
|
||||||
|
'group' => $group + 0.5,
|
||||||
|
'hideOnDisabled' => true
|
||||||
|
),
|
||||||
|
'paste' => array(
|
||||||
|
'enabled' => false,
|
||||||
|
'group' => $group + 0.5,
|
||||||
|
'hideOnDisabled' => true
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return $actions;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function get_vfs_options($query)
|
||||||
|
{
|
||||||
|
$options = parent::get_vfs_options($query);
|
||||||
|
|
||||||
|
// Hide symlinks
|
||||||
|
// TODO: This hides everything, see Vfs::_check_add() line 648
|
||||||
|
//$options['type'] = '!l';
|
||||||
|
|
||||||
|
return $options;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback to fetch the rows for the nextmatch widget
|
||||||
|
*
|
||||||
|
* @param array $query
|
||||||
|
* @param array &$rows
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
function get_rows(&$query, &$rows)
|
||||||
|
{
|
||||||
|
// Check for navigating outside share, redirect back to share
|
||||||
|
if (!empty($query['path']) && (!Vfs::stat($query['path'], false) || !Vfs::is_dir($query['path']) || !Vfs::check_access($query['path'], Vfs::READABLE)))
|
||||||
|
{
|
||||||
|
// only redirect, if it would be to some other location, gives redirect-loop otherwise
|
||||||
|
if ($query['path'] != ($path = static::get_home_dir()))
|
||||||
|
{
|
||||||
|
// we will leave here, since we are not allowed, go back to root
|
||||||
|
// TODO: Give message about it, redirect to home dir
|
||||||
|
}
|
||||||
|
$rows = array();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get file list from parent
|
||||||
|
$total = parent::get_rows($query, $rows);
|
||||||
|
|
||||||
|
return $total;
|
||||||
|
}
|
||||||
|
}
|
139
filemanager/src/Sharing/HiddenUpload.php
Normal file
139
filemanager/src/Sharing/HiddenUpload.php
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
namespace EGroupware\Filemanager\Sharing;
|
||||||
|
|
||||||
|
|
||||||
|
use EGroupware\Api\Vfs;
|
||||||
|
use EGroupware\Api\Vfs\Sharing;
|
||||||
|
use EGroupware\Api\Vfs\UploadSharingUi;
|
||||||
|
|
||||||
|
class HiddenUpload extends AnonymousList
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get active view - override so it points to this class
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function get_view()
|
||||||
|
{
|
||||||
|
return array(new HiddenUpload(), 'listview');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filemanager listview
|
||||||
|
*
|
||||||
|
* Override to customize for sharing with a hidden upload directory.
|
||||||
|
* Everything not in the upload directory is readonly, but we make it look like you can upload.
|
||||||
|
* The upload directory is not shown.
|
||||||
|
*
|
||||||
|
* @param array $content
|
||||||
|
* @param string $msg
|
||||||
|
*/
|
||||||
|
function listview(array $content=null,$msg=null)
|
||||||
|
{
|
||||||
|
$this->etemplate = $this->etemplate ? $this->etemplate : new Api\Etemplate(static::LIST_TEMPLATE);
|
||||||
|
|
||||||
|
if (isset($GLOBALS['egw']->sharing) && $GLOBALS['egw']->sharing->has_hidden_upload())
|
||||||
|
{
|
||||||
|
// Tell client side that the path is actually writable
|
||||||
|
$content['initial_path_readonly'] = false;
|
||||||
|
|
||||||
|
// No new anything
|
||||||
|
$this->etemplate->disableElement('nm[new]');
|
||||||
|
$this->etemplate->setElementAttribute('nm[button][createdir]', 'readonly', true);
|
||||||
|
|
||||||
|
// Take over upload, change target and conflict strategy
|
||||||
|
$path = Vfs::concat(self::get_home_dir(), Sharing::HIDDEN_UPLOAD_DIR);
|
||||||
|
$target = str_replace('\\', '\\\\', __CLASS__);
|
||||||
|
$this->etemplate->setElementAttribute('nm[upload]', 'onFinishOne', "app.filemanager.upload(ev, 1, '$path', 'rename', '{$target}::ajax_action')");
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent::listview($content, $msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deal with an uploaded file.
|
||||||
|
* Overridden from the parent to change the message and message type
|
||||||
|
*
|
||||||
|
* @param string $action Should be 'upload'
|
||||||
|
* @param $selected Array of file information
|
||||||
|
* @param string $dir Target directory
|
||||||
|
* @param $props
|
||||||
|
* @param string[] $arr Result
|
||||||
|
*
|
||||||
|
* @throws Api\Exception\AssertionFailed
|
||||||
|
*/
|
||||||
|
protected static function handle_upload_action(string $action, $selected, $dir, $props, &$arr)
|
||||||
|
{
|
||||||
|
Api\Translation::add_app('filemanager');
|
||||||
|
$vfs = Vfs::mount();
|
||||||
|
$GLOBALS['egw']->sharing->redo();
|
||||||
|
parent::handle_upload_action($action, $selected, $dir, $props, $arr);
|
||||||
|
$arr['msg'] .= "\n" . lang("The uploaded file is only visible to the person sharing these files with you, not to yourself or other people knowing this sharing link.");
|
||||||
|
$arr['type'] = 'notice';
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function is_hidden_upload_dir($directory)
|
||||||
|
{
|
||||||
|
if (!isset($GLOBALS['egw']->sharing)) return false;
|
||||||
|
// Just hide anything that is 'Upload' mounted where we expect, not just this share, to avoid exposing when
|
||||||
|
// more than one share is used
|
||||||
|
$mounts = Vfs::mount();
|
||||||
|
return Vfs::is_dir($directory) && '/'.Vfs::basename($directory) == Sharing::HIDDEN_UPLOAD_DIR && $mounts[$directory];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback to fetch the rows for the nextmatch widget
|
||||||
|
*
|
||||||
|
* @param array $query
|
||||||
|
* @param array &$rows
|
||||||
|
* @return int
|
||||||
|
*
|
||||||
|
* @throws Api\Json\Exception
|
||||||
|
*/
|
||||||
|
function get_rows(&$query, &$rows)
|
||||||
|
{
|
||||||
|
$hidden_upload = (isset($GLOBALS['egw']->sharing) && $GLOBALS['egw']->sharing->has_hidden_upload());
|
||||||
|
|
||||||
|
// Not allowed in hidden upload dir
|
||||||
|
$check_path = Sharing::HIDDEN_UPLOAD_DIR . (substr($query['path'], -1) == '/' ? '/' : '');
|
||||||
|
if(($length = strlen($check_path)) && (substr($query['path'], -$length) === $check_path))
|
||||||
|
{
|
||||||
|
// only redirect, if it would be to some other location, gives redirect-loop otherwise
|
||||||
|
if ($query['path'] != ($path = static::get_home_dir()))
|
||||||
|
{
|
||||||
|
// we will leave here, since we are not allowed, go back to root
|
||||||
|
// TODO: Give message about it, redirect to home dir
|
||||||
|
}
|
||||||
|
$rows = array();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get file list from parent
|
||||||
|
$total = parent::get_rows($query, $rows);
|
||||||
|
|
||||||
|
if(! $hidden_upload )
|
||||||
|
{
|
||||||
|
return $total;
|
||||||
|
}
|
||||||
|
|
||||||
|
// tell client-side that this directory is writeable - allows upload + button
|
||||||
|
$response = Api\Json\Response::get();
|
||||||
|
$response->call('app.filemanager.set_readonly', $query['path'], false);
|
||||||
|
|
||||||
|
// Hide the hidden upload directory, mark everything else as readonly
|
||||||
|
foreach($rows as $key => &$row)
|
||||||
|
{
|
||||||
|
if($this->is_hidden_upload_dir($row['path']))
|
||||||
|
{
|
||||||
|
unset($rows[$key]);
|
||||||
|
$total--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$row['class'] .= 'noEdit noDelete ';
|
||||||
|
}
|
||||||
|
return $total;
|
||||||
|
}
|
||||||
|
}
|
105
filemanager/src/Sharing/Ui.php
Normal file
105
filemanager/src/Sharing/Ui.php
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* EGroupware - Filemanager - UI for sharing with regular users
|
||||||
|
*
|
||||||
|
* @link http://www.egroupware.org
|
||||||
|
* @package filemanager
|
||||||
|
* @author Nathan Gray
|
||||||
|
* @copyright (c) 2020 Nathan Gray
|
||||||
|
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace EGroupware\Filemanager\Sharing;
|
||||||
|
|
||||||
|
use EGroupware\Api;
|
||||||
|
use EGroupware\Api\Vfs\Sharing;
|
||||||
|
use EGroupware\Api\Etemplate;
|
||||||
|
use EGroupware\Api\Framework;
|
||||||
|
use EGroupware\Api\Link;
|
||||||
|
use EGroupware\Api\Vfs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User interface for dealing with filemanager shares
|
||||||
|
*/
|
||||||
|
class Ui
|
||||||
|
{
|
||||||
|
|
||||||
|
// These functions are allowed to be called from client
|
||||||
|
public $public_functions = Array(
|
||||||
|
'share_received' => true
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The user has been given a new share. Ask what they want to do with it.
|
||||||
|
*
|
||||||
|
* This allows changing the name / mountpoint, and if they want to only
|
||||||
|
* mount it temporarily.
|
||||||
|
*
|
||||||
|
* @param array $content
|
||||||
|
*/
|
||||||
|
public function share_received($content = array())
|
||||||
|
{
|
||||||
|
// Deal with response
|
||||||
|
$this->handle_share_received($content);
|
||||||
|
|
||||||
|
// Set up for display
|
||||||
|
$template = new Api\Etemplate('filemanager.file_share_received');
|
||||||
|
|
||||||
|
$token = $content['token'] ?: $_GET['token'];
|
||||||
|
|
||||||
|
$share = Sharing::so()->read(['share_token' => $token]);
|
||||||
|
|
||||||
|
// This should already have been done, but we want the correct share root
|
||||||
|
Sharing::setup_share(true,$share);
|
||||||
|
|
||||||
|
$content = $share;
|
||||||
|
$content['share_passwd'] = !!$content['share_passwd'];
|
||||||
|
unset($content['share_id']);
|
||||||
|
$content['mount_location'] = Vfs::basename($content['share_root']);
|
||||||
|
$content['permanent'] = true;
|
||||||
|
|
||||||
|
$sel_options = array();
|
||||||
|
$readonlys = array();
|
||||||
|
$preserve = $content;
|
||||||
|
$preserve['url'] = Vfs\Sharing\StreamWrapper::share2url($share);
|
||||||
|
|
||||||
|
$template->exec('filemanager.'.__CLASS__.'.'.__FUNCTION__, $content, $sel_options, $readonlys, $preserve);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User submitted the share_received dialog, update the share appropriately
|
||||||
|
*
|
||||||
|
* @param array $content
|
||||||
|
*/
|
||||||
|
protected function handle_share_received($content = array())
|
||||||
|
{
|
||||||
|
if(!$content) return;
|
||||||
|
|
||||||
|
// Set persistent
|
||||||
|
$persistent_mount = $content['permanent'] ? $GLOBALS['egw_info']['user']['account_id'] : false;
|
||||||
|
|
||||||
|
$new_mountpoint = Vfs::dirname($content['share_root']) . '/' . $content['mount_location'];
|
||||||
|
Vfs::$is_root = true;
|
||||||
|
Vfs::umount($content['share_root']);
|
||||||
|
if(Vfs::mount($content['url'], $new_mountpoint, false, $persistent_mount))
|
||||||
|
{
|
||||||
|
$content['share_root'] = $new_mountpoint;
|
||||||
|
}
|
||||||
|
Vfs::$is_root = false;
|
||||||
|
|
||||||
|
// also save for current session
|
||||||
|
$GLOBALS['egw_info']['user']['preferences']['common']['vfs_fstab'][$new_mountpoint] =
|
||||||
|
$_SESSION[Api\Session::EGW_INFO_CACHE]['user']['preferences']['common']['vfs_fstab'][$new_mountpoint] = $content['url'];
|
||||||
|
|
||||||
|
$GLOBALS['egw_info']['server']['vfs_fstab'] = Vfs::mount();
|
||||||
|
|
||||||
|
// Go to new share
|
||||||
|
Api\Json\Response::get()->apply('window.opener.egw.open_link',[
|
||||||
|
Api\Framework::link('/index.php',[
|
||||||
|
'menuaction' => "filemanager.filemanager_ui.index",
|
||||||
|
'path' => $content['share_root']
|
||||||
|
]), 'filemanager',false,'filemanager'
|
||||||
|
]);
|
||||||
|
Api\Framework::window_close();
|
||||||
|
}
|
||||||
|
}
|
32
filemanager/templates/default/file_share_received.xet
Normal file
32
filemanager/templates/default/file_share_received.xet
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE overlay PUBLIC "-//EGroupware GmbH//eTemplate 2//EN" "http://www.egroupware.org/etemplate2.dtd">
|
||||||
|
<!-- $Id$ -->
|
||||||
|
<overlay>
|
||||||
|
<template id="filemanager.file_share_received" template="" lang="" group="0" version="20.1">
|
||||||
|
<grid width="100%">
|
||||||
|
<columns>
|
||||||
|
<column width="20%"/>
|
||||||
|
<column/>
|
||||||
|
</columns>
|
||||||
|
<rows>
|
||||||
|
<row>
|
||||||
|
<label value="Location"/>
|
||||||
|
<description id="share_root" />
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<label value="Name"/>
|
||||||
|
<textbox id="mount_location"/>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<label value="Mount permanently" for="permanent"/>
|
||||||
|
<checkbox id="permanent"/>
|
||||||
|
</row>
|
||||||
|
<row class="dialogFooterToolbar">
|
||||||
|
<hbox>
|
||||||
|
<button label="Ok" id="ok" image="ok" background_image="1" align="center"/>
|
||||||
|
</hbox>
|
||||||
|
</row>
|
||||||
|
</rows>
|
||||||
|
</grid>
|
||||||
|
</template>
|
||||||
|
</overlay>
|
Loading…
Reference in New Issue
Block a user