From 1ffde3b69207948c66b9f5d93624b8b60cfa68d2 Mon Sep 17 00:00:00 2001 From: nathangray Date: Thu, 11 Mar 2021 17:00:16 -0700 Subject: [PATCH] Change global sharing variable to be a list of shares in use, indexed by token. This should resolve the issues with multiple shares being accessed in the same session. --- api/lang/egw_en.lang | 1 + api/src/Sharing.php | 19 ++++++--- api/src/Storage/History.php | 14 ++++++- api/src/Vfs/Sharing.php | 47 ++++++++++++++++++----- filemanager/lang/egw_en.lang | 1 + filemanager/src/Sharing/AnonymousList.php | 7 ++-- filemanager/src/Sharing/HiddenUpload.php | 8 ++-- filemanager/src/Sharing/Ui.php | 5 ++- share.php | 4 +- 9 files changed, 80 insertions(+), 26 deletions(-) diff --git a/api/lang/egw_en.lang b/api/lang/egw_en.lang index 296650711c..0cfd2cdad4 100644 --- a/api/lang/egw_en.lang +++ b/api/lang/egw_en.lang @@ -1381,6 +1381,7 @@ the mail server returned common en The mail server returned there already is a system-user with this name. user's should not have the same name as a systemuser common en There already is a system user with this name. Please, select another name. they will be sub-folders in users home (%1 attribute). common en They will be sub-folders in users home (%1 attribute). this feature is only available in epl version. common en This feature is only available in EPL version. +this is your own share. to test it, use an anonymous / incognito window.
%1 common en This is your own share. To test it, use an anonymous / incognito window.
%1 this name has been used already common en This name has been used already! this text gets displayed if the input-field is empty and has no focus (blur) common en Text gets displayed if the input field is empty and has no focus (blur) this will reset toolbar preferences for all users and set them to configured default prefs. common en This will reset toolbar preferences for all users and set them to configured default prefs. diff --git a/api/src/Sharing.php b/api/src/Sharing.php index 320d51cdde..be5287aae4 100644 --- a/api/src/Sharing.php +++ b/api/src/Sharing.php @@ -198,7 +198,7 @@ class Sharing unset($GLOBALS['egw_info']['flags']['autocreate_session_callback']); if (isset($GLOBALS['egw']->session) && $GLOBALS['egw']->session->verify() - && isset($GLOBALS['egw']->sharing) && $GLOBALS['egw']->sharing->share['share_token'] === $token) + && isset($GLOBALS['egw']->sharing) && array_key_exists($token, $GLOBALS['egw']->sharing)) { return $GLOBALS['egw']->session->sessionid; } @@ -277,11 +277,15 @@ class Sharing ), __LINE__, __FILE__); // store sharing object in egw object and therefore in session - $GLOBALS['egw']->sharing = static::factory($share); + if(!isset($GLOBALS['egw']->sharing)) + { + $GLOBALS['egw']->sharing = Array(); + } + $GLOBALS['egw']->sharing[$share['share_token']] = static::factory($share); // we have a session we want to keep, but share owner is different from current user and we need filemanager UI, or no session // --> create a new anon session - if ($keep_session === false && $GLOBALS['egw']->sharing->need_session() || is_null($keep_session)) + if ($keep_session === false && $GLOBALS['egw']->sharing[$share['share_token']]->need_session() || is_null($keep_session)) { $sessionid = static::create_new_session(); @@ -513,7 +517,7 @@ class Sharing self::create_session($GLOBALS['egw']->session->session_flags === 'N' && $GLOBALS['egw_info']['user']['account_lid'] !== 'anonymous'); - return $GLOBALS['egw']->sharing->ServeRequest(); + return $GLOBALS['egw']->sharing[static::get_token()]->ServeRequest(); } /* No extended ACL for readonly shares, disable eacl by setting session cache @@ -526,7 +530,6 @@ class Sharing }*/ if($this->use_collabora()) { - unset($GLOBALS['egw']->sharing); $ui = new \EGroupware\Collabora\Ui(); return $ui->editor($this->share['share_path']); } @@ -543,6 +546,12 @@ class Sharing // WebDAV always looks at the original request for a single file so make sure the file is found at the root Vfs::$is_root = true; unset($GLOBALS['egw_info']['server']['vfs_fstab']); + + // Make SURE resolve_url is set, otherwise webdav will give full access to / + if(!$this->share['resolve_url']) + { + $this->share['resolve_url'] = Vfs::resolve_url($this->share['share_path'], true, true, true, true); + } Vfs::mount($this->share['resolve_url'], '/', false, false, true); Vfs::clearstatcache(); diff --git a/api/src/Storage/History.php b/api/src/Storage/History.php index ce1cebd041..c297d44568 100644 --- a/api/src/Storage/History.php +++ b/api/src/Storage/History.php @@ -125,6 +125,11 @@ class History { if ($new_value != $old_value) { + $share_with = ''; + foreach(isset($GLOBALS['egw']->sharing) ? $GLOBALS['egw']->sharing : [] as $token => $share_obj) + { + $share_with .= $share_obj->get_share_with(); + } $this->db->insert(self::TABLE,array( 'history_record_id' => $record_id, 'history_appname' => $this->appname, @@ -134,7 +139,7 @@ class History 'history_old_value' => $old_value, 'history_timestamp' => time(), 'sessionid' => $GLOBALS['egw']->session->sessionid_access_log, - 'share_email' => isset($GLOBALS['egw']->sharing) ? $GLOBALS['egw']->sharing->get_share_with() : '', + 'share_email' => $share_with, ),false,__LINE__,__FILE__); } } @@ -146,6 +151,11 @@ class History { if ($new_value != $old_value) { + $share_with = ''; + foreach(isset($GLOBALS['egw']->sharing) ? $GLOBALS['egw']->sharing : [] as $token => $share_obj) + { + $share_with .= $share_obj->get_share_with(); + } $GLOBALS['egw']->db->insert(self::TABLE,array( 'history_record_id' => $id, 'history_appname' => $appname, @@ -155,7 +165,7 @@ class History 'history_old_value' => $old_value, 'history_timestamp' => time(), 'sessionid' => $GLOBALS['egw']->session->sessionid_access_log, - 'share_email' => isset($GLOBALS['egw']->sharing) ? $GLOBALS['egw']->sharing->get_share_with() : '', + 'share_email' => $share_with, ),false,__LINE__,__FILE__); } } diff --git a/api/src/Vfs/Sharing.php b/api/src/Vfs/Sharing.php index 09c83a2525..411e334184 100644 --- a/api/src/Vfs/Sharing.php +++ b/api/src/Vfs/Sharing.php @@ -14,6 +14,7 @@ namespace EGroupware\Api\Vfs; use EGroupware\Api; +use EGroupware\Api\Json\Response; use EGroupware\Api\Vfs; use EGroupware\Filemanager\Sharing\AnonymousList; use EGroupware\Filemanager\Sharing\Ui; @@ -233,15 +234,39 @@ class Sharing extends \EGroupware\Api\Sharing */ 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']) + + // User testing their own share? + if($GLOBALS['egw_info']['user']['account_id'] == $this->share['share_owner']) + { + Api\Framework::message(lang( + "This is your own share. To test it, use an anonymous / incognito window.\n%1", + '' . $this->share['share_root'] . '' + ),'info'); + } + + + // Opened within EGroupware. Ask about the share, if the user is not anonymous. + if($GLOBALS['egw_info']['user']['account_lid'] !== 'anonymous' && $GLOBALS['egw_info']['user']['account_id'] != $this->share['share_owner']) { // Check to see if this is already permanent mounted share $mount_target = Vfs\Sharing\StreamWrapper::share2url($this->share); + + // Logged in user opening someone else's share, but they've opened the URL in its own tab + if (!Response::isJSONResponse()) + { + Api\Framework::message(lang( + "Share mounted. To test it, use an anonymous / incognito window.\n%1", + '' . $this->share['share_root'] . '' + ),'info'); + Api\Framework::redirect(Api\Framework::link('/index.php',[ + 'menuaction' => 'filemanager.EGroupware\\Filemanager\\Sharing\\Ui.share_received', + 'token' => $this->share['share_token'] + ])); + } if(($mounted = array_search($mount_target,$GLOBALS['egw_info']['user']['preferences']['common']['vfs_fstab']))) { - Api\Json\Response::get()->apply('window.opener.egw.open_link',[ + Response::get()->apply('window.opener.egw.open_link',[ Api\Framework::link('/index.php',[ 'menuaction' => 'filemanager.filemanager_ui.index', 'path' => $mounted @@ -251,7 +276,7 @@ class Sharing extends \EGroupware\Api\Sharing else { // New share, ask about it - Api\Json\Response::get()->apply('window.opener.egw.open_link',[ + 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'] @@ -259,7 +284,7 @@ class Sharing extends \EGroupware\Api\Sharing ]); } - Api\Json\Response::get()->apply('window.close'); + 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(); @@ -403,12 +428,14 @@ class Sharing extends \EGroupware\Api\Sharing if (($exists = ($stat = Vfs::stat($path)) && Vfs::check_access($path, Vfs::READABLE, $stat))) { - // Make sure we get the correct path if sharing from a share - if(isset($GLOBALS['egw']->sharing) && $exists) + // Not sure why stat puts a / on the end of files, but remove it + if(substr($stat['url'],-1) == '/' && !Vfs::is_dir($stat['url'])) + { + $stat['url'] = substr($stat['url'],0,strlen($stat['url'])-1); + } + // Make sure we get the correct path if sharing from a share + if(isset($GLOBALS['egw']->sharing) && array_key_exists(static::get_token(), $GLOBALS['egw']->sharing) && $exists) { - /* Why not use $stat['url'] - $resolved_stat = Vfs::parse_url($stat['url']); - $path = 'vfs://default'. $resolved_stat['path'];*/ $path = $stat['url']; } } diff --git a/filemanager/lang/egw_en.lang b/filemanager/lang/egw_en.lang index 19b73bc5a8..e00c9addd3 100644 --- a/filemanager/lang/egw_en.lang +++ b/filemanager/lang/egw_en.lang @@ -259,6 +259,7 @@ setting for document merge saved. filemanager en Setting for document merge save share files filemanager en Share files share link copied into clipboard filemanager en Share link copied into clipboard shared files filemanager en Shared files +share mounted at %1.
please close this tab. filemanager en Share mounted at %1.
Please close this tab. shared with filemanager en Shared with show filemanager en Show show hidden files filemanager en Show hidden files diff --git a/filemanager/src/Sharing/AnonymousList.php b/filemanager/src/Sharing/AnonymousList.php index c952be401e..21426af858 100644 --- a/filemanager/src/Sharing/AnonymousList.php +++ b/filemanager/src/Sharing/AnonymousList.php @@ -65,9 +65,9 @@ class AnonymousList extends filemanager_ui */ static function get_home_dir() { - if(isset($GLOBALS['egw']->sharing)) + if(isset($GLOBALS['egw']->sharing) && array_key_exists(Vfs\Sharing::get_token(), $GLOBALS['egw']->sharing)) { - return $GLOBALS['egw']->sharing->get_root(); + return $GLOBALS['egw']->sharing[Vfs\Sharing::get_token()]->get_root(); } return '/'; } @@ -83,7 +83,8 @@ class AnonymousList extends filemanager_ui $group = 1; // do not add edit setting action when we are in sharing unset($actions['edit']); - if (isset($GLOBALS['egw']->sharing) && Vfs::is_writable($GLOBALS['egw']->sharing->get_root())) + if (isset($GLOBALS['egw']->sharing) && array_key_exists(Vfs\Sharing::get_token(), $GLOBALS['egw']->sharing) && + Vfs::is_writable($GLOBALS['egw']->sharing[Vfs\Sharing::get_token()]->get_root())) { return $actions; } diff --git a/filemanager/src/Sharing/HiddenUpload.php b/filemanager/src/Sharing/HiddenUpload.php index a92ee2dacb..e0ae041b13 100644 --- a/filemanager/src/Sharing/HiddenUpload.php +++ b/filemanager/src/Sharing/HiddenUpload.php @@ -37,7 +37,8 @@ class HiddenUpload extends AnonymousList { $this->etemplate = $this->etemplate ? $this->etemplate : new Etemplate(static::LIST_TEMPLATE); - if (isset($GLOBALS['egw']->sharing) && $GLOBALS['egw']->sharing->has_hidden_upload()) + if (isset($GLOBALS['egw']->sharing) && array_key_exists(Vfs\Sharing::get_token(), $GLOBALS['egw']->sharing) && + $GLOBALS['egw']->sharing[Vfs\Sharing::get_token()]->has_hidden_upload()) { // Tell client side that the path is actually writable $content['initial_path_readonly'] = false; @@ -71,7 +72,7 @@ class HiddenUpload extends AnonymousList { Translation::add_app('filemanager'); $vfs = Vfs::mount(); - $GLOBALS['egw']->sharing->redo(); + $GLOBALS['egw']->sharing[Sharing::get_token()]->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'; @@ -97,7 +98,8 @@ class HiddenUpload extends AnonymousList */ function get_rows(&$query, &$rows) { - $hidden_upload = (isset($GLOBALS['egw']->sharing) && $GLOBALS['egw']->sharing->has_hidden_upload()); + $hidden_upload = (isset($GLOBALS['egw']->sharing) && array_key_exists(Vfs\Sharing::get_token(), $GLOBALS['egw']->sharing) && + $GLOBALS['egw']->sharing[Sharing::get_token()]->has_hidden_upload()); // Not allowed in hidden upload dir $check_path = Sharing::HIDDEN_UPLOAD_DIR . (substr($query['path'], -1) == '/' ? '/' : ''); diff --git a/filemanager/src/Sharing/Ui.php b/filemanager/src/Sharing/Ui.php index d5572269e9..e601d2c608 100644 --- a/filemanager/src/Sharing/Ui.php +++ b/filemanager/src/Sharing/Ui.php @@ -63,7 +63,7 @@ class Ui $preserve = $content; $preserve['url'] = Vfs\Sharing\StreamWrapper::share2url($share); - $template->exec('filemanager.'.__CLASS__.'.'.__FUNCTION__, $content, $sel_options, $readonlys, $preserve); + $template->exec('filemanager.'.__CLASS__.'.'.__FUNCTION__, $content, $sel_options, $readonlys, $preserve,2); } /** @@ -100,6 +100,9 @@ class Ui 'path' => $content['share_root'] ]), 'filemanager',false,'filemanager' ]); + // This should only be seen if they pasted the link into a new tab since we can't close the tab in that case + Framework::message(lang("Share mounted at %1.
Please close this tab.", $content['share_root']),"info"); + Api\Framework::window_close(); } } \ No newline at end of file diff --git a/share.php b/share.php index 8ac5d2c04a..aaf4dd70f8 100644 --- a/share.php +++ b/share.php @@ -27,8 +27,8 @@ $GLOBALS['egw_info'] = array( include('./header.inc.php'); -if (!isset($GLOBALS['egw']->sharing) || \EGroupware\Api\Sharing::get_token() !== $GLOBALS['egw']->sharing->get_token()) +if (!isset($GLOBALS['egw']->sharing) || !array_key_exists(Sharing::get_token(), $GLOBALS['egw']->sharing)) { Sharing::create_session(true); // true = mount into existing session } -$GLOBALS['egw']->sharing->ServeRequest(); +$GLOBALS['egw']->sharing[Sharing::get_token()]->ServeRequest();