diff --git a/api/src/Vfs/Sharing.php b/api/src/Vfs/Sharing.php index 1014d21424..5b99836c98 100644 --- a/api/src/Vfs/Sharing.php +++ b/api/src/Vfs/Sharing.php @@ -147,6 +147,12 @@ class Sharing extends \EGroupware\Api\Sharing $share['resolve_url'] .= (strpos($share['resolve_url'], '?') ? '&' : '?').'ro=1'; } $share['share_root'] = '/'; + if(!$GLOBALS['egw_info']['user']['account_lid'] || $GLOBALS['egw_info']['user']['account_lid'] == 'anonymous') + { + // Do not mount to root or it will be overwritten if they open another share + $share['share_root'] = '/' . Vfs::basename($share['share_path']); + } + // only allow filemanager app & collabora // In some cases, $GLOBALS['egw_info']['apps'] is not yet set at all. Set it to app => true, it will be used @@ -166,26 +172,28 @@ class Sharing extends \EGroupware\Api\Sharing // mounting share Vfs::$is_root = true; - if (!Vfs::mount($share['resolve_url'], $share['share_root'], false, false, true)) + if(!Vfs::mount($share['resolve_url'], $share['share_root'], false, false, true)) { sleep(1); return static::share_fail( '404 Not Found', - "Requested resource '/".htmlspecialchars($share['share_token'])."' does NOT exist!\n" + "Requested resource '/" . htmlspecialchars($share['share_token']) . "' does NOT exist!\n" ); } - /* ToDo: is this still needed and for what reason, as Vfs::mount() already supports session / non-persistent mounts - $session_fstab =& Api\Cache::getSession('api', 'fstab'); + /* + We want to hide any normal VFS folders from anonymous users, so we emptied the fstab (above) + and now add any other shares from this session + */ + $session_fstab = $_SESSION[Api\Session::EGW_INFO_CACHE]['server']['vfs_fstab']; if(!$session_fstab) { $session_fstab = array(); } - foreach($session_fstab as $mount => $info) + foreach($session_fstab as $path => $url) { - Vfs::mount($info['mount'], $mount, false, false); + Vfs::mount($url, $path, false, false); } - static::session_mount($share['share_root'], $share['resolve_url']);*/ Vfs::$is_root = false; Vfs::clearstatcache(); diff --git a/api/tests/Vfs/AnonymousSharingTest.php b/api/tests/Vfs/AnonymousSharingTest.php new file mode 100644 index 0000000000..2bdf4d0011 --- /dev/null +++ b/api/tests/Vfs/AnonymousSharingTest.php @@ -0,0 +1,151 @@ +files[] = $dir; + Vfs::mkdir($dir); + $this->files += $this->addFiles($dir); + + + // Create and use link + $this->getShareExtra($dir, Sharing::READONLY, $extra); + + $share = call_user_func([$this, $create], $dir, Sharing::READONLY, $extra); + $link = Vfs\Sharing::share2link($share); + + + return $link; + } + + /** + * Create a hidden upload share + * + * @param $path + * @param $mode + * @param array $extra + * @return array + * @throws \EGroupware\Api\Exception\AssertionFailed + */ + protected function createHiddenUploadShare($path, $mode, $extra = array()) + { + // Make sure the path is there + if(!Vfs::is_readable($path)) + { + $this->assertTrue( + Vfs::is_dir($path) ? Vfs::mkdir($path, 0750, true) : Vfs::touch($path), + "Share path $path does not exist" + ); + } + + // Create share + $this->shares[] = $share = TestHiddenSharing::create('', $path, $mode, $name, $recipients, $extra); + + return $share; + } + + /** + * Test a single anonymous user accessing two shares at the same time, in different browser windows + * + * @return void + * @see SharingACLTest::testShareNewSession() for a single share + * + */ + public function testTwoShares() + { + // TEST SETUP + // Create shares + $dir1 = Vfs::get_home_dir() . '/share1/'; + $link1 = $this->setupShare($dir1); + + $dir2 = Vfs::get_home_dir() . '/share2/'; + $link2 = $this->setupShare($dir2); + + // Add some files so we can tell the shares apart apart + $FIRST_CONTENT = "This is the first share\n"; + $SECOND_CONTENT = "This is the second share\n"; + $dir_1_files = $this->addFiles($dir1, $FIRST_CONTENT); + $dir_2_files = $this->addFiles($dir2, $SECOND_CONTENT); + $this->files += $dir_1_files; + $this->files += $dir_2_files; + + // Now log out + Vfs::clearstatcache(); + Vfs::init_static(); + Vfs\StreamWrapper::init_static(); + LoggedInTest::tearDownAfterClass(); + + + // ACTUAL TEST + $curl = curl_init(); + curl_setopt($curl, CURLOPT_COOKIEJAR, "/tmp/cookieFileName"); + curl_setopt($curl, CURLOPT_COOKIEFILE, "/tmp/cookieFileName"); + $this->checkShare($link1, $FIRST_CONTENT, $curl); + $this->checkShare($link2, $SECOND_CONTENT, $curl); + + // Check first file again + $this->checkShare($link1, $FIRST_CONTENT, $curl); + } + + protected function checkShare($link, $content, &$curl) + { + // Read the etemplate + $data = array(); + $form = $this->getShare($link, $data, false, $curl); + $this->assertNotNull($form, "Could not read the share link"); + $rows = $data['data']['content']['nm']['rows']; + + // Check content + $result = array_filter($rows, function ($v) + { + return $v['name'] == 'test_file.txt'; + }); + $this->assertIsArray($result, "Could not find test file"); + $result = array_pop($result); + + $content_url = preg_replace('/\/share.php(.+)/', $result['download_url'], $link); + + curl_setopt($curl, CURLOPT_URL, $content_url); + $fetched = curl_exec($curl); + + $this->assertEquals($content, $fetched, "Wrong file contents"); + } +} diff --git a/api/tests/Vfs/SharingBase.php b/api/tests/Vfs/SharingBase.php index 3fb8350bf2..cca2babe39 100644 --- a/api/tests/Vfs/SharingBase.php +++ b/api/tests/Vfs/SharingBase.php @@ -666,10 +666,18 @@ class SharingBase extends LoggedInTest * @param $data Data passed to the etemplate * @param $keep_session = true Keep the current session, or access with new session as anonymous */ - public function getShare($link, &$data, $keep_session = true) + public function getShare($link, &$data, $keep_session = true, &$_curl = null) { // Set up curl - $curl = curl_init($link); + if($_curl == null) + { + $curl = curl_init($link); + } + else + { + $curl = $_curl; + curl_setopt($curl, CURLOPT_URL, $link); + } curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true); @@ -681,7 +689,10 @@ class SharingBase extends LoggedInTest } curl_setopt($curl, CURLOPT_COOKIE, $cookie); $html = curl_exec($curl); - curl_close($curl); + if($_curl == null) + { + curl_close($curl); + } if(!$html) {