file : all the management of the files, with integrated filesystem checks, and virtual chroot support

git-svn-id: https://svn.fournier38.fr/svn/ProgSVN/trunk@2694 bf3deb0d-5f1a-0410-827f-c0cc1f45334c
This commit is contained in:
2016-04-14 11:48:58 +00:00
parent 263730d53e
commit 2509155cc2
2 changed files with 1001 additions and 0 deletions

441
Tests/fileTest.php Normal file
View File

@@ -0,0 +1,441 @@
<?php
/** DomFramework
@package domframework
@author Dominique Fournier <dominique@fournier38.fr> */
/** Test the domframework file part */
class test_file extends PHPUnit_Framework_TestCase
{
public function testinit ()
{
exec ("rm -rf /tmp/testDFFileDir");
}
public function testRealPath01 ()
{
$file = new file ();
$res = $file->realpath ("/tmp");
$this->assertSame($res, "/tmp");
}
public function testRealPath02 ()
{
$file = new file ();
$res = $file->realpath ("////tmp");
$this->assertSame($res, "/tmp");
}
public function testRealPath03 ()
{
$file = new file ();
$res = $file->realpath ("////tmp////");
$this->assertSame($res, "/tmp");
}
public function testRealPath04 ()
{
$file = new file ();
$res = $file->realpath (".////tmp////");
$this->assertSame($res, "./tmp");
}
public function testRealPath05 ()
{
$file = new file ();
$res = $file->realpath ("../../../../../tmp/file");
$this->assertSame($res, "/tmp/file");
}
public function testRealPath06 ()
{
$file = new file ();
$res = $file->realpath ("../../../../../tmp/file/../../../..");
$this->assertSame($res, "/");
}
public function testRealPath07 ()
{
$file = new file ();
$res = $file->realpath (".././././../tmp/file/../././..");
$this->assertSame($res, "/");
}
public function testRealPath11 ()
{
$file = new file ();
$file->chroot ("/tmp");
$res = $file->realpath ("/tmp2");
$this->assertSame($res, "/tmp/tmp2");
}
public function testRealPath12 ()
{
$file = new file ();
$file->chroot ("/tmp");
$res = $file->realpath ("////tmp2");
$this->assertSame($res, "/tmp/tmp2");
}
public function testRealPath13 ()
{
$file = new file ();
$file->chroot ("/tmp");
$res = $file->realpath ("////tmp2////");
$this->assertSame($res, "/tmp/tmp2");
}
public function testRealPath14 ()
{
$file = new file ();
$file->chroot ("/tmp");
$res = $file->realpath (".////tmp2////");
$this->assertSame($res, "/tmp/tmp2");
}
public function testRealPath15 ()
{
$file = new file ();
$file->chroot ("/tmp");
$res = $file->realpath ("../../../../../tmp2/file");
$this->assertSame($res, "/tmp/tmp2/file");
}
public function testRealPath16 ()
{
$file = new file ();
$file->chroot ("/tmp");
$res = $file->realpath ("../../../../../tmp2/file/../../../..");
$this->assertSame($res, "/tmp");
}
public function testRealPath17 ()
{
$file = new file ();
$file->chroot ("/tmp");
$res = $file->realpath (".././././../tmp2/file/../././..");
$this->assertSame($res, "/tmp");
}
public function testGetcwd1 ()
{
$file = new file ();
$res = $file->getcwd ();
$this->assertSame($res, ".");
}
public function testGetcwd2 ()
{
$file = new file ();
$file->chdir ("/tmp");
$res = $file->getcwd ();
$this->assertSame($res, "/tmp");
}
public function testGetcwd3 ()
{
$this->setExpectedException ("Exception", "Path '/NON EXISTS' not found");
$file = new file ();
$file->chdir ("/NON EXISTS");
$res = $file->getcwd ();
}
public function testGetcwd4 ()
{
$file = new file ();
$file->chdir ("/../../../tmp");
$res = $file->getcwd ();
$this->assertSame($res, "/tmp");
}
public function testGetcwd5 ()
{
$file = new file ();
$file->chdir ("../../../../../../tmp");
$res = $file->getcwd ();
$this->assertSame($res, "/tmp");
}
public function testGetcwd6 ()
{
$this->setExpectedException ("Exception", "Path './tmp' not found");
$file = new file ();
$file->chdir ("./tmp");
$res = $file->getcwd ();
}
public function testGetcwd7 ()
{
$this->setExpectedException ("Exception",
"Path '/tmp/NON EXISTS' not found");
$file = new file ();
$file->chdir ("/tmp/NON EXISTS");
$res = $file->getcwd ();
}
public function testGetcwd8 ()
{
$this->setExpectedException ("Exception",
"Parent Path '/NON EXISTS/' not found");
$file = new file ();
$file->chdir ("/NON EXISTS/tmp");
$res = $file->getcwd ();
}
public function testchroot1 ()
{
$this->setExpectedException ("Exception");
$file = new file ();
$res = $file->chroot ("non exists");
}
public function testchroot2 ()
{
$file = new file ();
$res = $file->chroot ("/tmp");
$this->assertSame($res, true);
}
// Without chroot
public function testMkdir1 ()
{
$file = new file ();
$res = $file->mkdir ("/tmp/testmkdir1-".time());
$this->assertSame($res, true);
}
// With chroot in tmp
public function testMkdir2 ()
{
$file = new file ();
$res = $file->chroot ("/tmp");
$res = $file->mkdir ("/testmkdir2-".time());
$this->assertSame($res, true);
}
// Without chroot and relative
public function testMkdir3 ()
{
$file = new file ();
$res = $file->mkdir ("/tmp/testmkdir3-".time());
$this->assertSame($res, true);
}
// With chroot in tmp and in relative
public function testMkdir4 ()
{
$file = new file ();
$res = $file->chroot ("/tmp");
$res = $file->mkdir ("testmkdir4-".time());
$this->assertSame($res, true);
}
// With chroot in tmp
public function testChdir1 ()
{
@rmdir ("/tmp/testDFFileDir");
$file = new file ();
$file->chroot ("/tmp");
$file->mkdir ("/testDFFileDir");
$file->chdir ("/testDFFileDir");
$res = $file->getcwd ();
$this->assertSame($res, "/testDFFileDir");
}
// With chroot in tmp
public function testChdir2 ()
{
@rmdir ("/tmp/testDFFileDir");
$file = new file ();
$file->chroot ("/tmp");
$file->mkdir ("/testDFFileDir");
$file->chroot ("/");
$file->chdir ("/testDFFileDir");
$res = $file->getcwd ();
$this->assertSame($res, "/testDFFileDir");
}
// With chroot in tmp
public function testChdir3 ()
{
$this->setExpectedException ("Exception",
"Path '/tmp/testDFFileDir/NON EXISTS' not found");
@rmdir ("/tmp/testDFFileDir");
$file = new file ();
$file->chroot ("/tmp");
$file->mkdir ("/testDFFileDir");
$file->chroot ("/testDFFileDir");
$file->chdir ("/NON EXISTS");
}
// With chroot in tmp
public function testChdir4 ()
{
$this->setExpectedException ("Exception",
"Parent Path '/tmp/tmp/' not found");
@rmdir ("/tmp/testDFFileDir");
$file = new file ();
$file->chroot ("/tmp");
$file->mkdir ("/testDFFileDir");
$file->chroot ("..");
$file->chdir ("/tmp/testDFFileDir");
}
public function testFile_get_contents1 ()
{
$this->setExpectedException ("Exception",
"File '/tmp/testDFFileDir' is not a file");
@rmdir ("/tmp/testDFFileDir");
$file = new file ();
$file->chroot ("/tmp");
$file->mkdir ("/testDFFileDir");
$res = $file->file_get_contents ("/testDFFileDir");
}
public function testFile_get_contents2 ()
{
@rmdir ("/tmp/testDFFileDir");
$file = new file ();
$file->chroot ("/tmp");
$file->mkdir ("/testDFFileDir");
$file->touch ("/testDFFileDir/toto");
$res = $file->file_get_contents ("/testDFFileDir/toto");
$this->assertSame($res, "");
}
public function testFile_put_contents1 ()
{
$file = new file ();
$file->chroot ("/tmp");
$file->file_put_contents ("/testDFFileDir/toto", "content");
$res = $file->file_get_contents ("/testDFFileDir/toto");
$this->assertSame($res, "content");
}
public function testFile_put_contents2 ()
{
$this->setExpectedException ("Exception",
"File '/tmp/testDFFileDir' is not a file");
$file = new file ();
$file->file_put_contents ("/tmp/testDFFileDir", "content");
}
public function testFile_put_contents3 ()
{
$file = new file ();
$file->chroot ("/tmp");
$res = $file->file_put_contents ("/testDFFileDir/toto", "content");
$this->assertSame($res, 7);
}
public function testscandir1 ()
{
$file = new file ();
$res = $file->scandir ("/tmp/testDFFileDir");
$this->assertSame ($res, array ("toto"));
}
public function testscandir2 ()
{
$file = new file ();
$file->chroot ("/tmp");
$res = $file->scandir ("/testDFFileDir");
$this->assertSame ($res, array ("toto"));
}
public function testscandir3 ()
{
$file = new file ();
$file->chroot ("/tmp");
$res = $file->scandir ("/testDFFileDir/");
$this->assertSame ($res, array ("toto"));
}
public function testrmdir1 ()
{
// Directory not empty and NOT recursive : return false
$file = new file ();
$res = $file->rmdir ("/tmp/testDFFileDir");
$this->assertSame ($res, false);
}
public function testrmdir2 ()
{
// Directory not empty and NOT recursive : return false
$file = new file ();
$file->chroot ("/tmp");
$res = $file->rmdir ("/testDFFileDir");
$this->assertSame ($res, false);
}
public function testrmdir3 ()
{
// Directory not empty and recursive : return true
$file = new file ();
$file->chroot ("/tmp");
$res = $file->rmdir ("/testDFFileDir", true);
$this->assertSame ($res, true);
}
public function testUnlink1 ()
{
@rmdir ("/tmp/testDFFileDir");
$file = new file ();
$file->chroot ("/tmp");
$file->mkdir ("/testDFFileDir");
$file->touch ("/testDFFileDir/toto");
$res = $file->unlink ("/testDFFileDir/toto");
$this->assertSame ($res, true);
}
public function testIsDir1 ()
{
$file = new file ();
$file->chroot ("/tmp");
$res = $file->is_dir ("//testDFFileDir");
$this->assertSame ($res, true);
}
public function testIsDir2 ()
{
$file = new file ();
$file->chroot ("/tmp");
$file->touch ("/testDFFileDir/toto");
$res = $file->is_dir ("//testDFFileDir/toto");
$this->assertSame ($res, false);
}
public function testIsFile1 ()
{
$file = new file ();
$file->chroot ("/tmp");
$file->touch ("/testDFFileDir/toto");
$res = $file->is_file ("/testDFFileDir/toto");
$this->assertSame ($res, true);
}
public function testIsFile2 ()
{
$file = new file ();
$file->chroot ("/tmp");
$file->touch ("/testDFFileDir/toto");
$res = $file->is_file ("//testDFFileDir");
$this->assertSame ($res, false);
}
public function testMkdir5 ()
{
$file = new file ();
$file->chroot ("/tmp");
// The parent doesn't exists and not recursive mode : exception
$this->expectException ();
$res = $file->mkdir ("/testDFFileDir/tptp/titi/poo");
}
public function testMkdir6 ()
{
$file = new file ();
$file->chroot ("/tmp");
$res = $file->mkdir ("/testDFFileDir/tptp/titi/poo", 0777, true);
$this->assertSame ($res, true);
}
}

560
file.php Normal file
View File

@@ -0,0 +1,560 @@
<?php
/** DomFramework
@package domframework
@author Dominique Fournier <dominique@fournier38.fr> */
/** The file method allow to manage files like PHP with a working chroot on all
* plateforms, and a right management compatible with database
* Don't follow links !
*
* To allow an external authorization test in plus of the filesystem check, you
* must extends the class and overload checkExternalPathRO and
* checkExternalPathRW.
*/
class file
{
/** The virtual current working directory */
private $cwd = ".";
/** The real directory used as root in virtual chroot */
private $baseDir = "/";
/** The lock stack */
private $locks = array ();
/** Activate the debug and define the minimum priority to save */
public $debug = 0;
/** Change the current working directory
* @return bool true if the directory is changed
* @throws If directory not exists, or the directory is not executable
*/
public function chdir ($directory)
{
$this->debug (2, "chdir ($directory)");
$tmpdirectory = $this->realpath ($directory);
$this->checkPathRO ($tmpdirectory);
if ($this->baseDir === "/")
$this->cwd = $tmpdirectory;
else
$this->cwd = substr ($tmpdirectory, strlen ($this->baseDir));
$this->debug (1, "chdir $directory -> $this->cwd");
return true;
}
/** Chroot in the provided directory
* @param $directory string The directory to chroot
* @return true if the chroot is done, false if there is a failure
* @throws If directory not exists, or the directory is not executable
*/
public function chroot ($directory)
{
// Use the checkPathRO (using the $this->baseDir) to not allow to go away of
// the chroot.
$this->debug (2, "chroot ($directory)");
$directory = $this->realpath ($directory);
$this->checkPathRO ($directory);
$this->baseDir = preg_replace ("#//+#", "/", $directory);
$this->cwd = "/";
$this->debug (1, "chroot $directory -> $this->baseDir");
return true;
}
/** Checks whether a file or directory exists
* @param string $filename The file or directory to verify
* @return bool true if the file exists, false otherwise
* @throws If parent directory not exists, or is not executable
*/
public function file_exists ($filename)
{
$this->debug (2, "file_exists ($filename)");
$filename = $this->realpath ($filename);
$this->checkPathRO (dirname ($filename));
if (file_exists ($filename) && ! is_link ($filename))
return true;
return false;
}
/** Get the file contents
* @param string $filename Name of the file to read
* @return string Content of the file
* @throws If parent directory not exists, is not readable, the file is not
* exists or is not readable
*/
public function file_get_contents ($filename)
{
$this->debug (2, "file_get_contents ($filename)");
$filename = $this->realpath ($filename);
$this->checkPathRO (dirname ($filename));
if (! is_file ($filename))
throw new \Exception (sprintf (dgettext ("domframework",
"File '%s' is not a file"),
$filename), 500);
if (! is_readable ($filename))
throw new \Exception (sprintf (dgettext ("domframework",
"File '%s' is not readable"),
$filename), 500);
$contents = file_get_contents ($filename);
$this->debug (1, "file_get_contents ($filename) => ".strlen ($contents).
" bytes");
return $contents;
}
/** Write a string to a file
* @param string $filename Path to the file where to write the data
* @param The data to write
* @return the length of the data stored
* @throws If parent directory not exists, is not writeable, or the file
* exists and is not writeable
*/
public function file_put_contents ($filename, $data)
{
$this->debug (2, "file_put_contents ($filename)");
$filename = $this->realpath ($filename);
$this->checkPathRW (dirname ($filename));
if (file_exists ($filename) && ! is_writeable ($filename))
throw new \Exception (sprintf (dgettext ("domframework",
"File '%s' is not writeable"),
$filename), 500);
if (file_exists ($filename) && ! is_file ($filename))
throw new \Exception (sprintf (dgettext ("domframework",
"File '%s' is not a file"),
$filename), 500);
$contents = file_put_contents ($filename, $data);
$this->debug (1, "file_put_contents ($filename, \$data) => ".
"$contents bytes");
return $contents;
}
/** Return the current working directory
* @return string the current working directory */
public function getcwd ()
{
$this->debug (1, "getcwd $this->cwd");
return $this->cwd;
}
/** Tells whether the given filename is a directory
* @param string $filename The filename to test
* @return bool true if the $filename is a directory and exists, false
* otherwise
* @throws If parent directory not exists, or is not executable
*/
public function is_dir ($filename)
{
$this->debug (2, "is_dir ($filename)");
$filename = $this->realpath ($filename);
$this->checkPathRO (dirname ($filename));
if (file_exists ($filename) && is_dir ($filename))
return true;
return false;
}
/** Tells whether the given filename is a valid file
* @param string $filename The filename to test
* @return bool true if the $filename is a file and exists, false otherwise
* @throws If parent directory not exists, or is not executable
*/
public function is_file ($filename)
{
$this->debug (2, "is_file ($filename)");
$filename = $this->realpath ($filename);
$this->checkPathRO (dirname ($filename));
if (file_exists ($filename) && is_file ($filename))
return true;
return false;
}
/** Lock a file exclusively
* @param $filename The file to lock
* @return bool true if the lock is acquired, false otherwise
* @throws If parent directory not exists, or is not writeable
*/
public function lockEX ($filename)
{
$this->debug (2, "lockEX ($filename)");
$filename = $this->realpath ($filename);
$this->checkPathRW (dirname ($filename));
$this->locks[$filename] = fopen ($filename, "rt");
return flock ($this->locks[$filename], LOCK_EX);
}
/** Lock a file shared (allow multiple read)
* @param $filename The file to lock
* @return bool true if the lock is acquired, false otherwise
* @throws If parent directory not exists, or is not writeable
*/
public function lockSH ($filename)
{
$this->debug (2, "lockSH ($filename)");
$filename = $this->realpath ($filename);
$this->checkPathRW (dirname ($filename));
$this->locks[$filename] = fopen ($filename, "rt");
return flock ($this->locks[$filename], LOCK_SH);
}
/** Unlock a file previously locked
* @param $filename The file to lock
* @return bool true if the lock is acquired, false otherwise
* @throws If parent directory not exists, or is not writeable
*/
public function lockUN ($filename)
{
$this->debug (2, "lockUN ($filename)");
$filename = $this->realpath ($filename);
$this->checkPathRW (dirname ($filename));
$res = true;
if (isset ($this->locks[$filename]))
{
$res = flock ($this->locks[$filename], LOCK_UN);
fclose ($this->locks[$filename]);
}
return $res;
}
/** Create a new directory
* @param $pathname The directory to create
* @param $mode The mode to create (0777 by default)
* @param $recursive (false by default)
* @return bool true if the directory is correctely created, false if the
* directory already exists
* @throws If parent directory not exists, is not writeable
*/
public function mkdir ($pathname, $mode = 0777, $recursive = false)
{
$this->debug (2, "mkdir ($pathname, $mode, $recursive)");
$pathname = $this->realpath ($pathname);
if ($recursive)
{
$parents = explode ("/", $pathname);
array_pop ($parents);
$parent = "";
foreach ($parents as $p)
{
$parent = $parent.$p."/";
if (! file_exists ($parent))
{
if (is_writeable (dirname ($parent)))
break;
throw new \Exception (sprintf ("Last Directory '%s' is readonly",
dirname ($parent)), 500);
}
}
if ($parent === dirname ($pathname) && ! is_writeable (dirname ($parent)))
{
throw new \Exception (sprintf ("Parent directory '%s' is readonly",
dirname ($parent)), 500);
}
}
else
{
$this->checkPathRW (dirname ($pathname));
}
if (file_exists ($pathname))
throw new \Exception (sprintf (dgettext ("domframework",
"Directory '%s' already exists"),
$pathname), 500);
$rc = mkdir ($pathname, $mode, $recursive);
$this->debug (1, "mkdir ($pathname, $mode, $recursive) => $rc");
return $rc;
}
/** Return a ini file converted to an array
* @param string $filename The filename of the ini file being parsed.
* @param bool $process_sections Process the sections
* @return array
*/
public function parse_ini_file ($filename, $process_sections = false)
{
$this->debug (2, "parse_ini_file ($filename, $process_sections)");
$filename = $this->realpath ($filename);
$this->checkPathRO (dirname ($filename));
if (! is_file ($filename))
throw new \Exception (sprintf (dgettext ("domframework",
"File '%s' is not a file"),
$filename), 500);
if (! is_readable ($filename))
throw new \Exception (sprintf (dgettext ("domframework",
"File '%s' is not readable"),
$filename), 500);
return parse_ini_file ($filename, $process_sections);
}
/** Return the canonical absolute path. Do not check if the directory exists,
* if there is links. Just calculate the realpath based on the chroot value
* @param string $path the path to analyze
* @return string the canonical absolute path
*/
public function realpath ($path)
{
$oriPath = $path;
$this->debug (2, "realpath ($oriPath)");
$path = preg_replace ("#//+#", "/", $path);
if (substr ($path, -1) === "/")
$path = substr ($path, 0, -1);
$parts = explode ("/", $path);
$current = $this->cwd;
$tmp = explode ("/", $current);
foreach ($parts as $part)
{
if ($part === "")
$tmp = array();
elseif ($part === ".")
continue;
elseif ($part === "..")
{
array_pop ($tmp);
continue;
}
else
array_push ($tmp, $part);
}
if (reset ($tmp) === ".")
{
array_shift ($tmp);
$path = $current."/".implode ("/", $tmp);
}
else
$path = "/".implode ("/", $tmp);
if ($this->baseDir !== "/")
$path = $this->baseDir.$path;
$path = preg_replace ("#//+#", "/", $path);
if ($path !== "/" && substr ($path, -1) === "/")
$path = substr ($path, 0, -1);
$this->debug (1, "realpath ($oriPath) => $path");
return $path;
}
/** Remove the provided directory
* If the recurse flag is true, remove the content too (files and
* directories)
* @param string $dirname The directory to remove
* @param bool $recursive Remove recursively
* @return bool true if all is removed, false otherwise
* @throws If parent directory not exists, is not writeable or the current
* dir is not writeable
*/
public function rmdir ($dirname, $recursive=false)
{
$this->debug (2, "rmdir ($dirname, $recursive)");
$tmpdirname = $this->realpath ($dirname);
$this->checkPathRW (dirname ($tmpdirname));
$this->checkPathRW ($tmpdirname);
if ($recursive === false)
return @rmdir ($tmpdirname);
$files = array_diff (scandir ($tmpdirname), array('.','..'));
foreach ($files as $file)
{
(is_dir ("$tmpdirname/$file")) ? $this->rmdir("$dirname/$file") :
unlink ("$tmpdirname/$file");
}
return rmdir ($tmpdirname);
}
/** Return the list of files and directories in the directory.
* Do not return the . and .. virtual dirs.
* The result is sorted
* @param string $directory The directory to read
* @return array the list of files and dirs
* @throws If directory not exists, or is not executable
*/
public function scandir ($directory)
{
$this->debug (2, "scandir ($directory)");
$directory = $this->realpath ($directory);
$this->checkPathRO ($directory);
$res = array_values (array_diff (scandir ($directory), array('..', '.')));
natsort ($res);
return $res;
}
/** Create a new file or update the timestamp if the file exists
* @param string $filename the filename
* @param int $time the timestamp to use (actual timestamp if not defined)
* @return bool true or false on failure
* @throws If parent directory not exists, is not writeable
*/
public function touch ($filename, $time = null, $atime = null)
{
$this->debug (2, "touch ($filename, $time, $atime)");
$filename = $this->realpath ($filename);
$this->checkPathRW (dirname ($filename));
if ($time === null)
$time = time ();
if ($atime === null)
$atime = time ();
$rc = touch ($filename, $time, $atime);
$this->debug (1, "touch ($filename, $time, $atime) => $rc");
return $rc;
}
/** Delete an existing file.
* @param string $filename The filename to remove
* @return bool true if the file si removed, false otherwise
* @throws If parent directory not exists, or is not executable
*/
public function unlink ($filename)
{
$this->debug (2, "unlink ($filename)");
$filename = $this->realpath ($filename);
$this->checkPathRW (dirname ($filename));
if (! file_exists ($filename) || ! is_writeable ($filename))
return false;
return unlink ($filename);
}
/** Check all the parents of the $directory if they are available, and
* executable. The path must exists.
* Must use the filesystem path (complete) and not the version in chroot.
* The last directoy must be executable and readable (no test for writeable)
* @param $path string The directory path to check
* @return true if the path is executable for all the parents and for the
* last directory
* @throws if there is a missing part, or a parent is not executable
*/
private function checkPathRO ($path)
{
$this->debug (2, "checkPathRO ($path)");
$path = preg_replace ("#//+#", "/", $path);
$parents = explode ("/", $path);
array_pop ($parents);
$parent = "";
foreach ($parents as $p)
{
$parent = $parent.$p."/";
if (! file_exists ($parent))
{
$this->debug (1,
"checkPathRO ($path) => Parent Path '$parent' not found");
throw new \Exception (sprintf (dgettext ("domframework",
"Parent Path '%s' not found"),
$parent), 404);
}
if (! is_executable ($parent))
{
$this->debug (1, "checkPathRO ($path) => ".
"Parent Directory '$parent' not executable");
throw new \Exception (sprintf (dgettext ("domframework",
"Parent Directory '%s' not executable"),
$parent), 500);
}
if ($this->checkExternalPathRO ($parent) !== true)
{
$this->debug (1, "checkPathRO ($path) => ".
"Parent Directory '$parent' not accessible by ".
"external check read-only");
throw new \Exception (sprintf (dgettext ("domframework",
"Parent Directory '%s' not accessible ".
"by external check read-only"),
$parent), 500);
}
}
if (! file_exists ($path))
{
$this->debug (1, "checkPathRO ($path) => Path '$path' not found");
throw new \Exception (sprintf (dgettext ("domframework",
"Path '%s' not found"),
$path), 404);
}
if (! is_dir ($path))
{
$this->debug (1, "checkPathRO ($path) => ".
"Path '$path' is not a directory");
throw new \Exception (sprintf (dgettext ("domframework",
"Path '%s' is not a directory"),
$path),
500);
}
if (! is_executable ($path))
{
$this->debug (1, "checkPathRO ($path) => ".
"Directory '$path' is not executable");
throw new \Exception (sprintf (dgettext ("domframework",
"Directory '%s' is not executable"),
$path), 500);
}
if (! is_readable ($path))
{
$this->debug (1, "checkPathRO ($path) => ".
"Directory '$path' is not readable");
throw new \Exception (sprintf (dgettext ("domframework",
"Directory '%s' is not readable"),
$path), 500);
}
return $this->checkExternalPathRO ($path);
}
/** Check all the parents of the $directory if they are available, and
* executable. The path must exists.
* Must use the filesystem path (complete) and not the version in chroot.
* The last directoy must be executable and readable and writeable
* @param $path string The directory path to check
* @return true if the path is executable for all the parents and for the
* last directory
* @throws if there is a missing part, or a parent is not executable
*/
private function checkPathRW ($path)
{
$this->debug (2, "checkPathRW ($path)");
$this->checkPathRO ($path);
if (! is_writeable ($path))
{
$this->debug (1, "checkPathRW ($path) => ".
"Directory '$path' is not writeable");
throw new \Exception (sprintf (dgettext ("domframework",
"Directory '%s' is not writeable"),
$path), 500);
}
if ($this->checkExternalPathRW ($path) !== true)
{
$this->debug (1, "checkPathRW ($path) => ".
"Directory '$path' not accessible by ".
"external check read-write");
throw new \Exception (sprintf (dgettext ("domframework",
"Directory '%s' not accessible ".
"by external check read-write"),
$path), 500);
}
return true;
}
/** Save a debug log
* @param $prio The message priority. Should be higher than $this->debug to
* save the message
* @param $message The message to save
* @return null;
*/
private function debug ($prio, $message)
{
if ($this->debug === false || $this->debug === 0)
return;
if ($prio <= $this->debug)
{
echo "[$prio] $message\n";
//file_put_contents ("/tmp/domframework.file.debug",
// date ("Y:m:d H:i:s")." [$prio] $message\n",
// FILE_APPEND);
}
}
/** External function allowed to be overloaded to test the RO access to a
* resource
* @param string $path The path to test in the filesystem
* @return boolean true if RO access, false if not
*/
public function checkExternalPathRO ($path)
{
return true;
}
/** External function allowed to be overloaded to test the RW access to a
* resource
* @param string $path The path to test in the filesystem
* @return boolean true if RW access, false if not
*/
public function checkExternalPathRW ($path)
{
return true;
}
}