Files
DomFramework/file.php
2019-08-20 10:13:23 +00:00

979 lines
33 KiB
PHP

<?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
* @param string $directory Go in the provided 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;
}
// }}}
/** Change the group for a file/dir...
* @param string $filename The file/directory to change
* @param mixed $group The group name or group GID
* @throws If filename not exists, or the directory is not RW
*/
public function chgrp ($filename, $group)
// {{{
{
$this->debug (2, "chgrp ($filename, $group)");
$filename = $this->realpath ($filename);
$this->checkPathRW (dirname ($filename));
if (! file_exists ($filename))
throw new \Exception (sprintf (dgettext ("domframework",
"File '%s' to chmod doesn't exists"),
$filename), 404);
if (! is_writeable ($filename))
throw new \Exception (sprintf (dgettext ("domframework",
"File '%s' to chmod is not writeable"),
$filename), 500);
$rc = chgrp ($filename, $group);
$this->debug (1, "chgrp ($filename, $group) => $rc");
return $rc;
}
// }}}
/** Change the rights mode for a file/dir...
* @param string $filename The file/directory to change
* @param integer $mode The mode to use for the filename
* @throws If filename not exists, or the directory is not RW
*/
public function chmod ($filename, $mode)
// {{{
{
$this->debug (2, "chmod ($filename, $mode)");
$filename = $this->realpath ($filename);
$this->checkPathRW (dirname ($filename));
if (! file_exists ($filename))
throw new \Exception (sprintf (dgettext ("domframework",
"File '%s' to chmod doesn't exists"),
$filename), 404);
if (! is_writeable ($filename))
throw new \Exception (sprintf (dgettext ("domframework",
"File '%s' to chmod is not writeable"),
$filename), 500);
$rc = chmod ($filename, $mode);
$this->debug (1, "chmod ($filename, $mode) => $rc");
return $rc;
}
// }}}
/** Change the owner for a file/dir...
* @param string $filename The file/directory to change
* @param mixed $user The user name or user UID
* @throws If filename not exists, or the directory is not RW
*/
public function chown ($filename, $user)
// {{{
{
$this->debug (2, "chown ($filename, $user)");
if (posix_getuid () !== 0 &&
posix_getuid () !== $user &&
posix_getpwuid (posix_getuid()) !== $user)
throw new \Exception (sprintf (dgettext ("domframework",
"Only root user can change the file owner for '%s'"),
$filename), 500);
$filename = $this->realpath ($filename);
$this->checkPathRW (dirname ($filename));
if (! file_exists ($filename))
throw new \Exception (sprintf (dgettext ("domframework",
"File '%s' to chmod doesn't exists"),
$filename), 404);
if (! is_writeable ($filename))
throw new \Exception (sprintf (dgettext ("domframework",
"File '%s' to chmod is not writeable"),
$filename), 500);
$rc = chown ($filename, $user);
$this->debug (1, "chown ($filename, $user) => $rc");
return $rc;
}
// }}}
/** Chroot in the provided directory
* @param string $directory 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);
try
{
$this->checkPathRO (dirname ($filename));
}
catch (\Exception $e)
{
if ($e->getCode () !== 404)
throw new \Exception ($e->getMessage (), $e->getCode ());
}
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 string $data The data to write
* @param integer|null $flags The optional flags
* @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, $flags=0)
// {{{
{
$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, $flags);
$this->debug (1, "file_put_contents ($filename, \$data) => ".
"$contents bytes");
return $contents;
}
// }}}
/** Get the file modification time of a file
* @param string $filename Path to the file
* @return the time the file was last modified, or FALSE on failure. The
* time is returned as a Unix timestamp, which is suitable for the date()
* function.
* @throws If parent directory not exists, is not writeable
*/
public function filemtime ($filename)
// {{{
{
$this->debug (2, "filemtime ($filename)");
$filename = $this->realpath ($filename);
$this->checkPathRO (dirname ($filename));
return filemtime ($filename);
}
// }}}
/** Get the file size
* @param string $filename Path to the file
* @return the size of the file or FALSE on failure.
* @throws If parent directory not exists, is not writeable
*/
public function filesize ($filename)
// {{{
{
$this->debug (2, "filesize ($filename)");
$filename = $this->realpath ($filename);
$this->checkPathRO (dirname ($filename));
return filesize ($filename);
}
// }}}
/** Get the file info of the provided filename
* @param string $filename Path to the file
* @return the mimetype of the file
* @throws If parent directory not exists, is not writeable
*/
public function fileinfoMimeType ($filename)
// {{{
{
$this->debug (2, "filesize ($filename)");
$filename = $this->realpath ($filename);
$this->checkPathRO (dirname ($filename));
$finfo = new \finfo (FILEINFO_MIME_TYPE);
return $finfo->file ($filename);
}
// }}}
/** Return the current working directory
* @return string the current working directory */
public function getcwd ()
// {{{
{
$this->debug (1, "getcwd $this->cwd");
return $this->cwd;
}
// }}}
/** Find pathnames matching a pattern
* If there is some unreadable files, skip them quietly
* @param string $pattern The pattern to found
* @param integer|null $flags The additional flags
* @return array Return an array if there is an error
* @throws If parent directory not exists, or is not executable
* or if there is one file unreadable
*/
public function glob ($pattern, $flags=0)
// {{{
{
$this->debug (2, "glob ($pattern, $flags)");
$this->checkPathRO ($this->baseDir);
if (substr ($pattern, 0, 1) === "/")
$relative = 0;
else
$relative = 1;
$pattern = $this->realpath ($pattern);
$files = glob ($pattern, $flags);
if ($files === false)
// FIXME : In the exception : how found the file which is not readable ?
throw new \Exception ("Glob : can't read some files", 500);
foreach ($files as &$file)
{
if (strlen ($this->baseDir) > 1)
{
if ($relative == 1)
$file = substr ($file, strlen ($this->baseDir)+strlen ($this->cwd)+1);
else
$file = substr ($file, strlen ($this->baseDir));
}
else
{
if ($relative == 1)
$file = substr ($file, strlen ($this->cwd)+1);
}
}
return $files;
}
// }}}
/** 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;
}
// }}}
/** Tells whether a file exists and is executable
* @param string $filename The filename to test
* @return bool true if the $filename is a file exists and is writeable
* @throws If parent directory not exists, or is not executable
*/
public function is_executable ($filename)
// {{{
{
$this->debug (2, "is_executable ($filename)");
$filename = $this->realpath ($filename);
$this->checkPathRO (dirname ($filename));
if (file_exists ($filename) && is_executable ($filename))
return true;
return false;
}
// }}}
/** Tells whether a file exists and is readable
* @param string $filename The filename to test
* @return bool true if the $filename is a file exists and is readable
* @throws If parent directory not exists, or is not executable
*/
public function is_readable ($filename)
// {{{
{
$this->debug (2, "is_readable ($filename)");
$filename = $this->realpath ($filename);
$this->checkPathRO (dirname ($filename));
if (file_exists ($filename) && is_readable ($filename))
return true;
return false;
}
// }}}
/** Tells whether a file exists and is writeable
* @param string $filename The filename to test
* @return bool true if the $filename is a file exists and is writeable
* @throws If parent directory not exists, or is not executable
*/
public function is_writeable ($filename)
// {{{
{
$this->debug (2, "is_writeable ($filename)");
$filename = $this->realpath ($filename);
$this->checkPathRO (dirname ($filename));
if (file_exists ($filename) && is_writeable ($filename))
return true;
return false;
}
// }}}
/** Lock a file exclusively
* @param string $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));
if (! file_exists ($filename))
throw new \Exception (sprintf (dgettext ("domframework",
"File '%s' doesn't exists : could not be locked"),
$filename), 500);
if (! is_readable ($filename))
throw new \Exception (sprintf (dgettext ("domframework",
"File '%s' is not readable : could not be locked"),
$filename), 500);
$this->locks[$filename] = fopen ($filename, "rt");
return flock ($this->locks[$filename], LOCK_EX);
}
// }}}
/** Lock a file shared (allow multiple read)
* @param string $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));
if (! file_exists ($filename))
throw new \Exception (sprintf (dgettext ("domframework",
"File '%s' doesn't exists : could not be locked"),
$filename), 500);
if (! is_readable ($filename))
throw new \Exception (sprintf (dgettext ("domframework",
"File '%s' is not readable : could not be locked"),
$filename), 500);
$this->locks[$filename] = fopen ($filename, "rt");
return flock ($this->locks[$filename], LOCK_SH);
}
// }}}
/** Unlock a file previously locked
* @param string $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;
}
// }}}
/** Calculate the md5 sum of a file
* @param string $filename The file to hash
* @return the calulated hash
* @throws If the file doesn't exists
*/
public function md5_file ($filename)
// {{{
{
$this->debug (2, "md5_file ($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);
return md5_file ($filename);
}
// }}}
/** Create a new directory
* @param string $pathname The directory to create
* @param integer $mode The mode to create (0777 by default)
* @param boolean $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;
}
// }}}
/** Copy a file or a directory
* @param string $oldname The file to copy
* @param string $newname The new name of the file. It will be
* overwrited if it already exists
* @return bool
*/
public function copy ($oldname, $newname)
// {{{
{
$this->debug (2, "copy ($oldname, $newname)");
$oldname = $this->realpath ($oldname);
$newname = $this->realpath ($newname);
$this->checkPathRO (dirname ($oldname));
$this->checkPathRW (dirname ($newname));
if (is_dir ($oldname))
{
// Copy directory structure
if (! $this->file_exists ($newname))
$this->mkdir ($newname);
$files = $this->scandirNotSorted ($oldname);
foreach ($files as $file)
$this->copy ("$oldname/$file", "$newname/$file");
}
else
{
$rc = copy ($oldname, $newname);
}
$this->debug (1, "copy ($oldname, $newname) => $rc");
return $rc;
}
// }}}
/** Renames a file or directory
* @param string $oldname The file or directory to rename
* @param string $newname The new name of the file or directory. It will be
* overwrited if it already exists
* @return bool
*/
public function rename ($oldname, $newname)
// {{{
{
$this->debug (2, "rename ($oldname, $newname)");
$oldname = $this->realpath ($oldname);
$newname = $this->realpath ($newname);
$this->checkPathRO (dirname ($oldname));
$this->checkPathRW (dirname ($newname));
$rc = rename ($oldname, $newname);
$this->debug (1, "rename ($oldname, $newname) => $rc");
return $rc;
}
// }}}
/** Return a ini file converted to an array
* @param string $filename The filename of the ini file being parsed.
* @param boolean $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 boolean $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)
{
if (is_dir ("$tmpdirname/$file"))
{
$this->rmdir("$dirname/$file", $recursive);
}
else
{
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;
}
// }}}
/** Return the list of files and directories in the directory.
* Do not return the . and .. virtual dirs.
* The result is NOT 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 scandirNotSorted ($directory)
// {{{
{
$this->debug (2, "scandirNotSorted ($directory)");
$directory = $this->realpath ($directory);
$this->checkPathRO ($directory);
$res = array_values (array_diff (scandir ($directory, SCANDIR_SORT_NONE),
array('..', '.')));
return $res;
}
// }}}
/** Calculate the sha1 sum of a file
* @param string $filename The file to hash
* @return the calulated hash
* @throws If the file doesn't exists
*/
public function sha1_file ($filename)
// {{{
{
$this->debug (2, "sha1_file ($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);
return sha1_file ($filename);
}
// }}}
/** Create a new file or update the timestamp if the file exists
* @param string $filename the filename
* @param integer|null $time the timestamp to use (actual timestamp if not
* defined)
* @param integer|null $atime the access 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 string $path 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 string $path 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 integer $prio The message priority. Should be higher than
* $this->debug to save the message
* @param string $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;
}
// }}}
}