2018-02-07 18:22:00 +01:00
|
|
|
<?php
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Tests for sharing files and directories
|
|
|
|
*
|
2018-03-14 17:23:17 +01:00
|
|
|
* This is a bit of a mess, but I think we probably want to automatically test
|
|
|
|
* this to make sure we don't expose more than desired.
|
|
|
|
*
|
2018-02-07 18:22:00 +01:00
|
|
|
* @link http://www.egroupware.org
|
|
|
|
* @author Nathan Gray
|
|
|
|
* @package
|
|
|
|
* @copyright (c) 2018 Nathan Gray
|
|
|
|
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
|
|
|
*/
|
|
|
|
|
|
|
|
namespace EGroupware\Api\Vfs;
|
|
|
|
|
|
|
|
use EGroupware\Api;
|
|
|
|
use EGroupware\Api\Vfs;
|
|
|
|
use EGroupware\Api\LoggedInTest as LoggedInTest;
|
|
|
|
|
|
|
|
|
|
|
|
class SharingTest extends LoggedInTest
|
|
|
|
{
|
|
|
|
|
2018-03-20 22:44:27 +01:00
|
|
|
// Keep track of shares to remove after
|
2018-02-07 18:22:00 +01:00
|
|
|
protected $shares = Array();
|
|
|
|
|
2018-03-20 22:44:27 +01:00
|
|
|
// Keep track of files to remove after
|
|
|
|
protected $files = Array();
|
|
|
|
|
2018-02-07 18:22:00 +01:00
|
|
|
public function setUp()
|
|
|
|
{
|
2018-03-21 16:44:42 +01:00
|
|
|
|
2018-02-07 18:22:00 +01:00
|
|
|
}
|
2018-03-21 16:44:42 +01:00
|
|
|
|
2018-02-07 18:22:00 +01:00
|
|
|
public function tearDown()
|
|
|
|
{
|
2018-03-20 22:44:27 +01:00
|
|
|
LoggedInTest::tearDownAfterClass();
|
2018-02-15 17:37:48 +01:00
|
|
|
LoggedInTest::setupBeforeClass();
|
2018-03-20 22:44:27 +01:00
|
|
|
|
2018-03-21 16:44:42 +01:00
|
|
|
// 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();
|
2018-02-20 23:32:37 +01:00
|
|
|
|
|
|
|
// Need to ask about mounts, or other tests fail
|
|
|
|
Vfs::mount();
|
|
|
|
|
2018-03-20 22:44:27 +01:00
|
|
|
// Remove any added files
|
|
|
|
foreach($this->files as $path)
|
|
|
|
{
|
|
|
|
//echo "Unlinking $path: " . (Vfs::unlink($path) ? 'success' : 'failed');
|
|
|
|
Vfs::unlink($path);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remove any added shares
|
2018-02-07 18:22:00 +01:00
|
|
|
foreach($this->shares as $share)
|
|
|
|
{
|
2018-03-20 22:44:27 +01:00
|
|
|
Sharing::delete($share);
|
2018-02-07 18:22:00 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-02-20 23:32:37 +01:00
|
|
|
/**
|
|
|
|
* Test to make sure a readonly link to home gives just readonly access,
|
|
|
|
* and just to user's home
|
|
|
|
*/
|
2018-03-21 16:44:42 +01:00
|
|
|
public function testHomeReadonly()
|
2018-02-20 23:32:37 +01:00
|
|
|
{
|
2018-03-21 16:44:42 +01:00
|
|
|
$dir = Vfs::get_home_dir().'/';
|
2018-02-20 23:32:37 +01:00
|
|
|
|
2018-02-21 23:03:45 +01:00
|
|
|
//var_dump(Vfs::find('/',array('maxdepth' => 1)));
|
2018-02-20 23:32:37 +01:00
|
|
|
$logged_in_files = array_map(
|
|
|
|
function($path) use ($dir) {return str_replace($dir, '/', $path);},
|
|
|
|
Vfs::find($dir)
|
|
|
|
);
|
|
|
|
$this->shareLink($dir, Sharing::READONLY);
|
|
|
|
|
|
|
|
$files = Vfs::find(Vfs::get_home_dir());
|
|
|
|
|
2018-02-21 23:03:45 +01:00
|
|
|
//var_dump(Vfs::find('/test_subdir',array('maxdepth' => 1)));
|
2018-02-20 23:32:37 +01:00
|
|
|
// Make sure files are the same
|
|
|
|
$this->assertEquals($logged_in_files, $files);
|
|
|
|
|
|
|
|
// Make sure all are readonly
|
|
|
|
foreach($files as $file)
|
|
|
|
{
|
|
|
|
$this->assertFalse(Vfs::is_writable($file));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Test to make sure a writable link to home gives write access, but just
|
|
|
|
* to user's home
|
|
|
|
*/
|
|
|
|
public function testHomeWritable()
|
|
|
|
{
|
2018-03-14 17:23:17 +01:00
|
|
|
$dir = Vfs::get_home_dir().'/';
|
|
|
|
|
|
|
|
if(!Vfs::is_writable($dir))
|
|
|
|
{
|
|
|
|
$this->markTestSkipped("Unable to write to '$dir' as expected");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add some things for us to find, and make sure the dir is actually writable
|
|
|
|
$file = $dir.'test_file.txt';
|
2018-03-20 22:44:27 +01:00
|
|
|
$this->files[] = $file;
|
|
|
|
$this->assertTrue(
|
|
|
|
file_put_contents(Vfs::PREFIX.$file, 'Test for ' . $this->getName() ."\n". Api\DateTime::to()) !== FALSE,
|
|
|
|
'Unable to write test file - check file permissions for CLI user'
|
|
|
|
);
|
2018-02-20 23:32:37 +01:00
|
|
|
|
|
|
|
$logged_in_files = array_map(
|
|
|
|
function($path) use ($dir) {return str_replace($dir, '/', $path);},
|
|
|
|
Vfs::find($dir)
|
|
|
|
);
|
2018-03-14 17:23:17 +01:00
|
|
|
|
2018-03-20 22:44:27 +01:00
|
|
|
// Make sure the file's there
|
|
|
|
$this->assertTrue(in_array('/test_file.txt', $logged_in_files), 'Test file did not get created');
|
|
|
|
|
|
|
|
// Now we go to the link...
|
|
|
|
$this->shareLink($dir, Sharing::WRITABLE, array('share_writable' => TRUE));
|
2018-03-14 17:23:17 +01:00
|
|
|
$files = Vfs::find(Vfs::get_home_dir());
|
2018-02-20 23:32:37 +01:00
|
|
|
|
|
|
|
// Make sure files are the same
|
|
|
|
$this->assertEquals($logged_in_files, $files);
|
|
|
|
|
|
|
|
// Make sure all are writable
|
|
|
|
foreach($files as $file)
|
|
|
|
{
|
2018-03-14 17:23:17 +01:00
|
|
|
// Root is not writable
|
|
|
|
if($file == '/') continue;
|
2018-03-20 22:44:27 +01:00
|
|
|
|
2018-02-20 23:32:37 +01:00
|
|
|
$this->assertTrue(Vfs::is_writable($file), $file . ' was not writable');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-07 18:22:00 +01:00
|
|
|
/**
|
|
|
|
* Test that readable shares are actually readable
|
|
|
|
*
|
|
|
|
* @param string $path
|
|
|
|
*/
|
2018-03-20 22:44:27 +01:00
|
|
|
public function createShare($path, $mode, $extra = array())
|
2018-02-07 18:22:00 +01:00
|
|
|
{
|
2018-02-20 23:32:37 +01:00
|
|
|
// 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));
|
|
|
|
}
|
2018-02-07 18:22:00 +01:00
|
|
|
|
2018-02-20 23:32:37 +01:00
|
|
|
// Create share
|
2018-03-20 22:44:27 +01:00
|
|
|
$this->shares[] = $share = Sharing::create($path, $mode, $name, $recipients, $extra);
|
2018-02-07 18:22:00 +01:00
|
|
|
|
|
|
|
return $share;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2018-02-20 23:32:37 +01:00
|
|
|
* Test that a share link can be made, and that only that path is available
|
2018-02-07 18:22:00 +01:00
|
|
|
*
|
|
|
|
* @param string $path
|
|
|
|
*/
|
2018-03-20 22:44:27 +01:00
|
|
|
public function shareLink($path, $mode, $extra = array())
|
2018-02-07 18:22:00 +01:00
|
|
|
{
|
2018-03-20 22:44:27 +01:00
|
|
|
//echo __METHOD__ . "('$path',$mode)\n";
|
2018-02-07 18:22:00 +01:00
|
|
|
// Setup - create path and share
|
2018-03-20 22:44:27 +01:00
|
|
|
$share = $this->createShare($path, $mode, $extra);
|
2018-02-07 18:22:00 +01:00
|
|
|
$link = Vfs\Sharing::share2link($share);
|
2018-03-20 22:44:27 +01:00
|
|
|
//echo __METHOD__ . " link: $link\n";
|
|
|
|
//echo __METHOD__ . " share: " . array2string($share)."\n";
|
2018-02-07 18:22:00 +01:00
|
|
|
|
2018-02-15 17:37:48 +01:00
|
|
|
// Setup for share to load
|
2018-02-07 18:22:00 +01:00
|
|
|
$_SERVER['REQUEST_URI'] = $link;
|
2018-02-15 17:37:48 +01:00
|
|
|
preg_match('|^https?://[^/]+(/.*)share.php/'.$share['share_token'].'$|', $path_info=$_SERVER['REQUEST_URI'], $matches);
|
|
|
|
$_SERVER['SCRIPT_NAME'] = $matches[1];
|
|
|
|
|
2018-03-21 16:44:42 +01:00
|
|
|
// Log out & clear cache
|
2018-02-15 17:37:48 +01:00
|
|
|
LoggedInTest::tearDownAfterClass();
|
2018-03-21 16:44:42 +01:00
|
|
|
Vfs::clearstatcache();
|
2018-02-07 18:22:00 +01:00
|
|
|
|
2018-02-15 17:37:48 +01:00
|
|
|
// If it's a directory, check to make sure it gives the filemanager UI
|
2018-02-07 18:22:00 +01:00
|
|
|
if(Vfs::is_dir($path))
|
|
|
|
{
|
|
|
|
$this->checkDirectoryLink($link, $share);
|
|
|
|
}
|
|
|
|
|
2018-02-15 17:37:48 +01:00
|
|
|
// Load share
|
|
|
|
$this->setup_info();
|
|
|
|
|
2018-02-20 23:32:37 +01:00
|
|
|
// Our path should be mounted to root
|
|
|
|
$this->assertTrue(Vfs::is_readable('/'));
|
2018-02-15 17:37:48 +01:00
|
|
|
|
2018-02-20 23:32:37 +01:00
|
|
|
// Check other paths
|
|
|
|
$this->assertFalse(Vfs::is_readable($path));
|
|
|
|
$this->assertFalse(Vfs::is_readable($path . '../'));
|
2018-02-07 18:22:00 +01:00
|
|
|
}
|
|
|
|
|
2018-02-15 17:37:48 +01:00
|
|
|
/**
|
|
|
|
* Test to make sure that a directory link leads to a limited filemanager
|
|
|
|
* interface (not a file or 404).
|
|
|
|
*
|
|
|
|
* @param type $link
|
|
|
|
* @param type $share
|
|
|
|
*/
|
2018-02-07 18:22:00 +01:00
|
|
|
public function checkDirectoryLink($link, $share)
|
|
|
|
{
|
2018-02-20 23:32:37 +01:00
|
|
|
// Set up curl
|
2018-02-07 18:22:00 +01:00
|
|
|
$curl = curl_init($link);
|
|
|
|
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
|
|
|
|
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
|
|
|
|
$html = curl_exec($curl);
|
|
|
|
curl_close($curl);
|
2018-02-20 23:32:37 +01:00
|
|
|
|
2018-03-14 17:23:17 +01:00
|
|
|
if(!$html)
|
|
|
|
{
|
|
|
|
// No response - could mean something is terribly wrong, or it could
|
|
|
|
// mean we're running on Travis with no webserver to answer the
|
|
|
|
// request
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-02-20 23:32:37 +01:00
|
|
|
// Parse & check for nextmatch
|
2018-02-07 18:22:00 +01:00
|
|
|
$dom = new \DOMDocument();
|
2018-02-20 23:32:37 +01:00
|
|
|
@$dom->loadHTML($html);
|
2018-02-07 18:22:00 +01:00
|
|
|
$xpath = new \DOMXPath($dom);
|
|
|
|
$form = $xpath->query ('//form')->item(0);
|
|
|
|
$data = json_decode($form->getAttribute('data-etemplate'));
|
|
|
|
|
|
|
|
$this->assertEquals('filemanager.index', $data->name);
|
2018-03-14 17:23:17 +01:00
|
|
|
|
|
|
|
// Make sure we start at root, not somewhere else like the token mounted
|
|
|
|
// as a sub-directory
|
2018-02-07 18:22:00 +01:00
|
|
|
$this->assertEquals('/', $data->data->content->nm->path);
|
|
|
|
|
|
|
|
unset($data->data->content->nm->actions);
|
|
|
|
//var_dump($data->data->content->nm);
|
|
|
|
}
|
|
|
|
protected function setup_info()
|
|
|
|
{
|
|
|
|
// Copied from share.php
|
|
|
|
$GLOBALS['egw_info'] = array(
|
|
|
|
'flags' => array(
|
|
|
|
'disable_Template_class' => true,
|
|
|
|
'noheader' => true,
|
|
|
|
'nonavbar' => 'always', // true would cause eTemplate to reset it to false for non-popups!
|
|
|
|
'currentapp' => 'filemanager',
|
|
|
|
'autocreate_session_callback' => 'EGroupware\\Api\\Vfs\\Sharing::create_session',
|
|
|
|
'no_exception_handler' => 'basic_auth', // we use a basic auth exception handler (sends exception message as basic auth realm)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
|
2018-02-21 23:03:45 +01:00
|
|
|
ob_start();
|
2018-02-15 17:37:48 +01:00
|
|
|
static::load_egw('anonymous','','',$GLOBALS['egw_info']);
|
2018-02-21 23:03:45 +01:00
|
|
|
ob_end_clean();
|
2018-02-07 18:22:00 +01:00
|
|
|
}
|
|
|
|
}
|