From 0fb4176067bbb30673134fb0a2897089ac03a330 Mon Sep 17 00:00:00 2001 From: nathangray Date: Wed, 8 Apr 2020 11:38:57 -0600 Subject: [PATCH] Fix sharing a single file gave 404 Added test to check that this works for a single file --- api/src/Sharing.php | 27 +++++++++++++-------- api/tests/Vfs/SharingBase.php | 45 +++++++++++++++++++++++++++++++++++ api/tests/Vfs/SharingTest.php | 38 +++++++++++++++++++++++++++++ 3 files changed, 100 insertions(+), 10 deletions(-) diff --git a/api/src/Sharing.php b/api/src/Sharing.php index 4ee0c7ac32..f2f6b7ba4a 100644 --- a/api/src/Sharing.php +++ b/api/src/Sharing.php @@ -95,16 +95,16 @@ class Sharing */ public static function get_token() { - // 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 - // of the request URI ourselves - // if request URI contains a full url, remove schema and domain + // 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 + // of the request URI ourselves + // if request URI contains a full url, remove schema and domain $matches = null; - if (preg_match('|^https?://[^/]+(/.*)$|', $path_info=$_SERVER['REQUEST_URI'], $matches)) - { - $path_info = $matches[1]; - } - $path_info = substr($path_info, strlen($_SERVER['SCRIPT_NAME'])); + if (preg_match('|^https?://[^/]+(/.*)$|', $path_info=$_SERVER['REQUEST_URI'], $matches)) + { + $path_info = $matches[1]; + } + $path_info = substr($path_info, strlen($_SERVER['SCRIPT_NAME'])); list(, $token/*, $path*/) = preg_split('|[/?]|', $path_info, 3); list($token) = explode(':', $token); @@ -521,8 +521,15 @@ class Sharing Header\Content::disposition(Vfs::basename($this->share['share_path']), false); } $GLOBALS['egw']->session->commit_session(); + + // 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']); + Vfs::mount($this->share['resolve_url'], '/', false, false, true); + Vfs::clearstatcache(); + $webdav_server = new Vfs\WebDAV(); - $webdav_server->ServeRequest(Vfs::concat($this->share['share_root'], $this->share['share_token'])); + $webdav_server->ServeRequest(Vfs::concat('/', $this->share['share_token'])); return; } return $this->get_ui(); diff --git a/api/tests/Vfs/SharingBase.php b/api/tests/Vfs/SharingBase.php index ad7e71a9fb..be5d6ca5a0 100644 --- a/api/tests/Vfs/SharingBase.php +++ b/api/tests/Vfs/SharingBase.php @@ -494,6 +494,11 @@ class SharingBase extends LoggedInTest { $this->checkDirectoryLink($link, $share); } + else + { + // If it's a file, check to make sure we get the file + $this->checkSharedFile($link, $path); + } // Load share $this->setup_info(); @@ -564,6 +569,46 @@ class SharingBase extends LoggedInTest unset($data->data->content->nm->actions); //var_dump($data->data->content->nm); } + + /** + * Check that we actually find the file we shared at the target link + * + * @param $link Share URL + * @param $file Vfs path to file + */ + public function checkSharedFile($link, $mimetype) + { + stream_context_set_default( + array( + 'http' => array( + 'method' => 'HEAD' + ) + ) + ); + $headers = get_headers($link); + $this->assertEquals('200', substr($headers[0], 9, 3), 'Did not find the file, got ' . $headers[0]); + + $indexed_headers = array(); + foreach($headers as &$header) + { + list($key, $value) = explode(': ', $header); + if(is_string($indexed_headers[$key])) + { + $indexed_headers[$key] = array($indexed_headers[$key]); + } + if(is_array($indexed_headers[$key])) + { + $indexed_headers[$key][] = $value; + } + else + { + $indexed_headers[$key] = $value; + } + } + + $this->assertStringContainsString($mimetype, $indexed_headers['Content-Type'], 'Wrong file type'); + } + protected function setup_info() { // Copied from share.php diff --git a/api/tests/Vfs/SharingTest.php b/api/tests/Vfs/SharingTest.php index 8c2287e1de..7f024aa05a 100644 --- a/api/tests/Vfs/SharingTest.php +++ b/api/tests/Vfs/SharingTest.php @@ -19,6 +19,7 @@ namespace EGroupware\Api\Vfs; require_once __DIR__ . '/SharingBase.php'; +use EGroupware\Api\LoggedInTest as LoggedInTest; use EGroupware\Api\Vfs; @@ -260,4 +261,41 @@ class SharingTest extends SharingBase $this->assertEquals($file, $created_share['share_path']); } + + /** + * Test that a share of a single file gives the file (uses WebDAV) + */ + public function testSingleFile() + { + $dir = Vfs::get_home_dir().'/'; + + // Plain text file + $file = $dir.'test_file.txt'; + $content = 'Testing that sharing a single (non-editable) file gives us the file.'; + $this->assertTrue( + file_put_contents(Vfs::PREFIX.$file, $content) !== FALSE, + 'Unable to write test file "' . Vfs::PREFIX . $file .'" - check file permissions for CLI user' + ); + $this->files[] = $file; + + $mimetype = Vfs::mime_content_type($file); + + // Create and use link + $extra = array(); + $this->getShareExtra($file, Sharing::READONLY, $extra); + + $share = $this->createShare($file, Sharing::READONLY, $extra); + $link = Vfs\Sharing::share2link($share); + + // Re-init, since they look at user, fstab, etc. + // Also, further tests that access the filesystem fail if we don't + Vfs::clearstatcache(); + Vfs::init_static(); + Vfs\StreamWrapper::init_static(); + + // Log out & clear cache + LoggedInTest::tearDownAfterClass(); + + $this->checkSharedFile($link, $mimetype); + } }