* @license BSD */ namespace Domframework; /** 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 boolean 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; } /** Get the file contents in an array (like 'file' function, but can not * have the same name as the class...) * @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 fileArray($filename) { $this->debug(2, "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); } $contents = file($filename); $this->debug(1, "file ($filename) => " . count($contents) . " rows"); return $contents; } /** 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|integer $data The data to write * @param integer|null $flags The optional flags * @return integer 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 integer|boolean 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 integer|boolean 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 string 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]); unset($this->locks[$filename]); } return $res; } /** Calculate the md5 sum of a file * @param string $filename The file to hash * @return string 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 string 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 boolean 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; } }