mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-11-25 17:33:49 +01:00
* Filemanager: enhance sharing to keep session of already logged in user, when he clicks on a share
This commit is contained in:
parent
95007f20d6
commit
e2aa6dce73
@ -5,7 +5,7 @@
|
|||||||
* @package etemplate
|
* @package etemplate
|
||||||
* @link http://www.egroupware.org
|
* @link http://www.egroupware.org
|
||||||
* @author Ralf Becker <rb@stylite.de>
|
* @author Ralf Becker <rb@stylite.de>
|
||||||
* @copyright (c) 2014 by Ralf Becker <rb@stylite.de>
|
* @copyright (c) 2014/15 by Ralf Becker <rb@stylite.de>
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -22,6 +22,12 @@ div#filemanager-index_buttons img, div#filemanager-index_favorite_wrapper,
|
|||||||
div.header_row_right, span.header_count, select#filemanager-index_filter, span.selectcols {
|
div.header_row_right, span.header_count, select#filemanager-index_filter, span.selectcols {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
|
div#filemanager-index_buttons img#filemanager-index_button\[change_view\] {
|
||||||
|
display: inline-block !important;
|
||||||
|
position: relative;
|
||||||
|
left: -230px;
|
||||||
|
top: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
div.filemanager_navigation label {
|
div.filemanager_navigation label {
|
||||||
/*right: 265px !important;*/
|
/*right: 265px !important;*/
|
||||||
|
@ -86,7 +86,8 @@ $GLOBALS['egw_info']['server']['versions']['header'] = '1.29';
|
|||||||
if(!isset($GLOBALS['egw_info']['flags']['noapi']) || !$GLOBALS['egw_info']['flags']['noapi'])
|
if(!isset($GLOBALS['egw_info']['flags']['noapi']) || !$GLOBALS['egw_info']['flags']['noapi'])
|
||||||
{
|
{
|
||||||
if (substr($_SERVER['SCRIPT_NAME'],-7) != 'dav.php' && // dont do it for webdav/groupdav, as we can not safely switch it off again
|
if (substr($_SERVER['SCRIPT_NAME'],-7) != 'dav.php' && // dont do it for webdav/groupdav, as we can not safely switch it off again
|
||||||
(!isset($_GET['menuaction']) || substr($_GET['menuaction'],-10) != '_hooks.log'))
|
(!isset($_GET['menuaction']) || substr($_GET['menuaction'],-10) != '_hooks.log') &&
|
||||||
|
substr($_SERVER['SCRIPT_NAME'],-10) != '/share.php')
|
||||||
{
|
{
|
||||||
ob_start(); // to prevent error messages to be send before our headers
|
ob_start(); // to prevent error messages to be send before our headers
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||||
* @package api
|
* @package api
|
||||||
* @author Ralf Becker <rb@stylite.de>
|
* @author Ralf Becker <rb@stylite.de>
|
||||||
* @copyright (c) 2014 by Ralf Becker <rb@stylite.de>
|
* @copyright (c) 2014/15 by Ralf Becker <rb@stylite.de>
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -94,9 +94,9 @@ class egw_sharing
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Init sharing by setting PHP_AUTH_USER from token in url
|
* Get token from url
|
||||||
*/
|
*/
|
||||||
public static function init()
|
public static function get_token()
|
||||||
{
|
{
|
||||||
// WebDAV has no concept of a query string and clients (including cadaver)
|
// WebDAV has no concept of a query string and clients (including cadaver)
|
||||||
// seem to pass '?' unencoded, so we need to extract the path info out
|
// seem to pass '?' unencoded, so we need to extract the path info out
|
||||||
@ -110,22 +110,45 @@ class egw_sharing
|
|||||||
$path_info = substr($path_info, strlen($_SERVER['SCRIPT_NAME']));
|
$path_info = substr($path_info, strlen($_SERVER['SCRIPT_NAME']));
|
||||||
list(, $token/*, $path*/) = preg_split('|[/?]|', $path_info, 3);
|
list(, $token/*, $path*/) = preg_split('|[/?]|', $path_info, 3);
|
||||||
|
|
||||||
$_SERVER['PHP_AUTH_USER'] = $token;
|
|
||||||
if (!isset($_SERVER['PHP_AUTH_PW'])) $_SERVER['PHP_AUTH_PW'] = '';
|
|
||||||
|
|
||||||
return $token;
|
return $token;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get root of share
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function get_root()
|
||||||
|
{
|
||||||
|
return $this->share['share_root'];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create sharing session
|
* Create sharing session
|
||||||
*
|
*
|
||||||
|
* @param boolean $keep_session =false false: create a new session, true: try mounting it into existing (already verified) session
|
||||||
* @return string with sessionid, does NOT return if no session created
|
* @return string with sessionid, does NOT return if no session created
|
||||||
*/
|
*/
|
||||||
public static function create_session()
|
public static function create_session($keep_session=false)
|
||||||
{
|
{
|
||||||
self::$db = $GLOBALS['egw']->db;
|
self::$db = $GLOBALS['egw']->db;
|
||||||
|
|
||||||
$token = $_SERVER['PHP_AUTH_USER'];
|
$token = self::get_token();
|
||||||
|
|
||||||
|
// are we called from header include, because session did not verify
|
||||||
|
// --> check if it verifys for our token
|
||||||
|
if ($token && !$keep_session)
|
||||||
|
{
|
||||||
|
$_SERVER['PHP_AUTH_USER'] = $token;
|
||||||
|
if (!isset($_SERVER['PHP_AUTH_PW'])) $_SERVER['PHP_AUTH_PW'] = '';
|
||||||
|
|
||||||
|
unset($GLOBALS['egw_info']['flags']['autocreate_session_callback']);
|
||||||
|
if ($GLOBALS['egw']->session->verify() && isset($GLOBALS['egw']->sharing) &&
|
||||||
|
$GLOBALS['egw']->sharing->share['share_token'] === $token)
|
||||||
|
{
|
||||||
|
return $GLOBALS['egw']->session->sessionid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (empty($token) || !($share = self::$db->select(self::TABLE, '*', array(
|
if (empty($token) || !($share = self::$db->select(self::TABLE, '*', array(
|
||||||
'share_token' => $token,
|
'share_token' => $token,
|
||||||
@ -156,6 +179,41 @@ class egw_sharing
|
|||||||
common::egw_exit();
|
common::egw_exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$share['resolve_url'] = egw_vfs::resolve_url($share['share_path']);
|
||||||
|
// if share not writable append ro=1 to mount url to make it readonly
|
||||||
|
if (!self::$db->from_bool($share['share_writable']))
|
||||||
|
{
|
||||||
|
$share['resolve_url'] .= (strpos($share['resolve_url'], '?') ? '&' : '?').'ro=1';
|
||||||
|
}
|
||||||
|
//_debug_array($share);
|
||||||
|
|
||||||
|
if ($keep_session) // add share to existing session
|
||||||
|
{
|
||||||
|
$share['share_root'] = '/'.$share['share_token'];
|
||||||
|
|
||||||
|
// if current user is not the share owner, we need to give him access to mounted share
|
||||||
|
if (egw_vfs::$user != $share['share_owner'])
|
||||||
|
{
|
||||||
|
// check if sharing user has owner rights for shared path
|
||||||
|
egw_vfs::$user = $share['share_owner'];
|
||||||
|
egw_vfs::clearstatcache();
|
||||||
|
if (egw_vfs::has_owner_rights($share['share_path']))
|
||||||
|
{
|
||||||
|
$rights = $share['share_writable'] && egw_vfs::is_writable($share['share_path']) ? 7 : 5;
|
||||||
|
egw_vfs::$user = $GLOBALS['egw']->session->account_id;
|
||||||
|
egw_vfs::eacl($share['share_root'], $rights, egw_vfs::$user, true); // true = session-only, not permanent
|
||||||
|
}
|
||||||
|
// if not, we must not use an eacl, as it grants recursive rights!
|
||||||
|
// (one could eg. create a writable share for / and use it to escalate his own rights)
|
||||||
|
// --> create a new session with propper rights (loosing current session)
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$keep_session = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!$keep_session) // do NOT change to else, as we might have set $keep_session=false!
|
||||||
|
{
|
||||||
// create session without checking auth: create(..., false, false)
|
// create session without checking auth: create(..., false, false)
|
||||||
if (!($sessionid = $GLOBALS['egw']->session->create('anonymous', '', 'text', false, false)))
|
if (!($sessionid = $GLOBALS['egw']->session->create('anonymous', '', 'text', false, false)))
|
||||||
{
|
{
|
||||||
@ -171,17 +229,14 @@ class egw_sharing
|
|||||||
'filemanager' => $GLOBALS['egw_info']['apps']['filemanager']
|
'filemanager' => $GLOBALS['egw_info']['apps']['filemanager']
|
||||||
);
|
);
|
||||||
|
|
||||||
$share['resolve_url'] = egw_vfs::resolve_url($share['share_path']);
|
$share['share_root'] = '/';
|
||||||
// if share not writable append ro=1 to mount url to make it readonly
|
// need to store new fstab and vfs_user in session to allow GET requests / downloads via WebDAV
|
||||||
if (!self::$db->from_bool($share['share_writable']))
|
$GLOBALS['egw_info']['user']['vfs_user'] = egw_vfs::$user = $share['share_owner'];
|
||||||
{
|
|
||||||
$share['resolve_url'] .= (strpos($share['resolve_url'], '?') ? '&' : '?').'ro=1';
|
|
||||||
}
|
}
|
||||||
//_debug_array($share);
|
|
||||||
|
|
||||||
// arrange vfs to only contain shared url and use share-owner as user
|
// mounting share
|
||||||
egw_vfs::$is_root = true;
|
egw_vfs::$is_root = true;
|
||||||
if (!egw_vfs::mount($share['resolve_url'], '/', false, false, true))
|
if (!egw_vfs::mount($share['resolve_url'], $share['share_root'], false, false, !$keep_session))
|
||||||
{
|
{
|
||||||
sleep(1);
|
sleep(1);
|
||||||
$status = '404 Not Found';
|
$status = '404 Not Found';
|
||||||
@ -191,9 +246,8 @@ class egw_sharing
|
|||||||
common::egw_exit();
|
common::egw_exit();
|
||||||
}
|
}
|
||||||
egw_vfs::$is_root = false;
|
egw_vfs::$is_root = false;
|
||||||
// need to store new fstab and vfs_user in session to allow GET requests / downloads via WebDAV
|
|
||||||
$GLOBALS['egw_info']['server']['vfs_fstab'] = egw_vfs::mount();
|
$GLOBALS['egw_info']['server']['vfs_fstab'] = egw_vfs::mount();
|
||||||
$GLOBALS['egw_info']['user']['vfs_user'] = egw_vfs::$user = $share['share_owner'];
|
|
||||||
egw_vfs::clearstatcache();
|
egw_vfs::clearstatcache();
|
||||||
|
|
||||||
// update accessed timestamp
|
// update accessed timestamp
|
||||||
@ -206,6 +260,15 @@ class egw_sharing
|
|||||||
// store sharing object in egw object and therefore in session
|
// store sharing object in egw object and therefore in session
|
||||||
$GLOBALS['egw']->sharing = new egw_sharing($share);
|
$GLOBALS['egw']->sharing = new egw_sharing($share);
|
||||||
|
|
||||||
|
// for an existing session we need to store modified egw and egw_info again in session
|
||||||
|
if ($keep_session)
|
||||||
|
{
|
||||||
|
$_SESSION[egw_session::EGW_INFO_CACHE] = $GLOBALS['egw_info'];
|
||||||
|
unset($_SESSION[egw_session::EGW_INFO_CACHE]['flags']); // dont save the flags, they change on each request
|
||||||
|
|
||||||
|
$_SESSION[egw_session::EGW_OBJECT_CACHE] = serialize($GLOBALS['egw']);
|
||||||
|
}
|
||||||
|
|
||||||
return $sessionid;
|
return $sessionid;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,25 +277,32 @@ class egw_sharing
|
|||||||
*/
|
*/
|
||||||
public function ServeRequest()
|
public function ServeRequest()
|
||||||
{
|
{
|
||||||
|
// sharing is for a different share, change to current share
|
||||||
|
if ($this->share['share_token'] !== self::get_token())
|
||||||
|
{
|
||||||
|
self::create_session($GLOBALS['egw']->session->session_flags === 'N');
|
||||||
|
|
||||||
|
return $GLOBALS['egw']->sharing->ServeRequest();
|
||||||
|
}
|
||||||
// use pure WebDAV for everything but GET requests to directories
|
// use pure WebDAV for everything but GET requests to directories
|
||||||
if (!egw_vfs::is_dir('/') || $_SERVER['REQUEST_METHOD'] != 'GET' ||
|
if (!egw_vfs::is_dir($this->share['share_root']) || $_SERVER['REQUEST_METHOD'] != 'GET' ||
|
||||||
// or unsupported browsers like ie < 10
|
// or unsupported browsers like ie < 10
|
||||||
html::$user_agent == 'msie' && html::$ua_version < 10.0 ||
|
html::$user_agent == 'msie' && html::$ua_version < 10.0 ||
|
||||||
// or if no filemanager installed (WebDAV has own autoindex)
|
// or if no filemanager installed (WebDAV has own autoindex)
|
||||||
!file_exists(__DIR__.'/../../filemanager/inc/class.filemanager_ui.inc.php'))
|
!file_exists(__DIR__.'/../../filemanager/inc/class.filemanager_ui.inc.php'))
|
||||||
{
|
{
|
||||||
// send a content-disposition header, so browser knows how to name downloaded file
|
// send a content-disposition header, so browser knows how to name downloaded file
|
||||||
if (!egw_vfs::is_dir($this->share['share_path']))
|
if (!egw_vfs::is_dir($this->share['share_root']))
|
||||||
{
|
{
|
||||||
html::content_disposition_header(egw_vfs::basename($this->share['share_path']), false);
|
html::content_disposition_header(egw_vfs::basename($this->share['share_path']), false);
|
||||||
}
|
}
|
||||||
//$GLOBALS['egw']->session->commit_session();
|
//$GLOBALS['egw']->session->commit_session();
|
||||||
$webdav_server = new vfs_webdav_server();
|
$webdav_server = new vfs_webdav_server();
|
||||||
$webdav_server->ServeRequest('/'.$this->share['share_token']);
|
$webdav_server->ServeRequest(egw_vfs::concat($this->share['share_root'], $this->share['share_token']));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// run full eTemplate2 UI for directories
|
// run full eTemplate2 UI for directories
|
||||||
$_GET['path'] = '/';
|
$_GET['path'] = $this->share['share_root'];
|
||||||
$_GET['cd'] = 'no';
|
$_GET['cd'] = 'no';
|
||||||
$GLOBALS['egw_info']['flags']['js_link_registry'] = true;
|
$GLOBALS['egw_info']['flags']['js_link_registry'] = true;
|
||||||
egw_framework::includeCSS('/filemanager/templates/default/sharing.css');
|
egw_framework::includeCSS('/filemanager/templates/default/sharing.css');
|
||||||
@ -557,7 +627,7 @@ if (file_exists(__DIR__.'/../../filemanager/inc/class.filemanager_ui.inc.php'))
|
|||||||
*/
|
*/
|
||||||
static function get_home_dir()
|
static function get_home_dir()
|
||||||
{
|
{
|
||||||
return '/';
|
return $GLOBALS['egw']->sharing->get_root();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -7,7 +7,7 @@
|
|||||||
* @package api
|
* @package api
|
||||||
* @subpackage vfs
|
* @subpackage vfs
|
||||||
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||||
* @copyright (c) 2008-14 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
* @copyright (c) 2008-15 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -927,6 +927,11 @@ class egw_vfs extends vfs_stream_wrapper
|
|||||||
return self::_call_on_backend('deny_script',array($path),true);
|
return self::_call_on_backend('deny_script',array($path),true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name of EACL array in session
|
||||||
|
*/
|
||||||
|
const SESSION_EACL = 'session-eacl';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set or delete extended acl for a given path and owner (or delete them if is_null($rights)
|
* Set or delete extended acl for a given path and owner (or delete them if is_null($rights)
|
||||||
*
|
*
|
||||||
@ -935,10 +940,21 @@ class egw_vfs extends vfs_stream_wrapper
|
|||||||
* @param string $url string with path
|
* @param string $url string with path
|
||||||
* @param int $rights =null rights to set, or null to delete the entry
|
* @param int $rights =null rights to set, or null to delete the entry
|
||||||
* @param int|boolean $owner =null owner for whom to set the rights, null for the current user, or false to delete all rights for $path
|
* @param int|boolean $owner =null owner for whom to set the rights, null for the current user, or false to delete all rights for $path
|
||||||
|
* @param boolean $session_only =false true: set eacl only for this session, does NO further checks currently!
|
||||||
* @return boolean true if acl is set/deleted, false on error
|
* @return boolean true if acl is set/deleted, false on error
|
||||||
*/
|
*/
|
||||||
static function eacl($url,$rights=null,$owner=null)
|
static function eacl($url,$rights=null,$owner=null,$session_only=false)
|
||||||
{
|
{
|
||||||
|
if ($session_only)
|
||||||
|
{
|
||||||
|
$session_eacls =& egw_cache::getSession(__CLASS__, self::SESSION_EACL);
|
||||||
|
$session_eacls[] = array(
|
||||||
|
'path' => $url[0] == '/' ? $url : egw_vfs::parse_url($url, PHP_URL_PATH),
|
||||||
|
'owner' => $owner ? $owner : egw_vfs::$user,
|
||||||
|
'rights' => $rights,
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return self::_call_on_backend('eacl',array($url,$rights,$owner));
|
return self::_call_on_backend('eacl',array($url,$rights,$owner));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -952,7 +968,31 @@ class egw_vfs extends vfs_stream_wrapper
|
|||||||
*/
|
*/
|
||||||
static function get_eacl($path)
|
static function get_eacl($path)
|
||||||
{
|
{
|
||||||
return self::_call_on_backend('get_eacl',array($path),true); // true = fail silent (no PHP Warning)
|
$eacls = self::_call_on_backend('get_eacl',array($path),true); // true = fail silent (no PHP Warning)
|
||||||
|
|
||||||
|
$session_eacls =& egw_cache::getSession(__CLASS__, self::SESSION_EACL);
|
||||||
|
if ($session_eacls)
|
||||||
|
{
|
||||||
|
// eacl is recursive, therefore we have to match all parent-dirs too
|
||||||
|
$paths = array($path);
|
||||||
|
while ($path && $path != '/')
|
||||||
|
{
|
||||||
|
$paths[] = $path = egw_vfs::dirname($path);
|
||||||
|
}
|
||||||
|
foreach((array)$session_eacls as $eacl)
|
||||||
|
{
|
||||||
|
if (in_array($eacl['path'], $paths))
|
||||||
|
{
|
||||||
|
$eacls[] = $eacl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// sort by length descending, to show precedence
|
||||||
|
usort($eacls, function($a, $b) {
|
||||||
|
return strlen($b['path']) - strlen($a['path']);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return $eacls;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -6,15 +6,12 @@
|
|||||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||||
* @package api
|
* @package api
|
||||||
* @author Ralf Becker <rb@stylite.de>
|
* @author Ralf Becker <rb@stylite.de>
|
||||||
* @copyright (c) 2014 by Ralf Becker <rb@stylite.de>
|
* @copyright (c) 2014/15 by Ralf Becker <rb@stylite.de>
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
require_once('./phpgwapi/inc/class.egw_sharing.inc.php');
|
require_once('./phpgwapi/inc/class.egw_sharing.inc.php');
|
||||||
|
|
||||||
// set PHP_AUTH_USER from token in URL, must be called before header include, to be able to verify session
|
|
||||||
egw_sharing::init();
|
|
||||||
|
|
||||||
$GLOBALS['egw_info'] = array(
|
$GLOBALS['egw_info'] = array(
|
||||||
'flags' => array(
|
'flags' => array(
|
||||||
'disable_Template_class' => true,
|
'disable_Template_class' => true,
|
||||||
@ -30,6 +27,6 @@ include('./header.inc.php');
|
|||||||
|
|
||||||
if (!$GLOBALS['egw']->sharing)
|
if (!$GLOBALS['egw']->sharing)
|
||||||
{
|
{
|
||||||
egw_sharing::create_session();
|
egw_sharing::create_session(true); // true = mount into existing session
|
||||||
}
|
}
|
||||||
$GLOBALS['egw']->sharing->ServeRequest();
|
$GLOBALS['egw']->sharing->ServeRequest();
|
||||||
|
Loading…
Reference in New Issue
Block a user