947 lines
25 KiB
PHP
Executable File
947 lines
25 KiB
PHP
Executable File
<?php
|
|
/**
|
|
* $Id: LocalFileImpl.php 547 2008-10-31 14:05:36Z spocke $
|
|
*
|
|
* @package MCFileManager.filesystems
|
|
* @author Moxiecode
|
|
* @copyright Copyright © 2005, Moxiecode Systems AB, All rights reserved.
|
|
*/
|
|
|
|
/**
|
|
* This is the local file system implementation of BaseFile.
|
|
*
|
|
* @package MCFileManager.filesystems
|
|
*/
|
|
class Moxiecode_LocalFileImpl extends Moxiecode_BaseFile {
|
|
// Private fields
|
|
var $_absPath = "";
|
|
var $_manager;
|
|
var $_config;
|
|
var $_type;
|
|
var $_events = true;
|
|
var $_statCache = array();
|
|
|
|
/**
|
|
* Creates a new absolute file.
|
|
*
|
|
* @param MCManager $manager MCManager reference.
|
|
* @param String $absolute_path Absolute path to local file.
|
|
* @param String $child_name Name of child file (Optional).
|
|
* @param String $type Optional file type.
|
|
*/
|
|
function Moxiecode_LocalFileImpl(&$manager, $absolute_path, $child_name = "", $type = MC_IS_FILE) {
|
|
$this->_manager =& $manager;
|
|
$this->_type = $type;
|
|
|
|
if ($child_name != "")
|
|
$this->_absPath = $this->_manager->removeTrailingSlash($absolute_path) . "/" . $child_name;
|
|
else
|
|
$this->_absPath = $absolute_path;
|
|
|
|
// Force it absolute
|
|
if (strpos($this->_absPath, '..') !== false)
|
|
$this->_absPath = $this->_manager->toUnixPath(realpath($this->_absPath));
|
|
}
|
|
|
|
/**
|
|
* Set a bool regarding events triggering.
|
|
*
|
|
* @param Bool $trigger Trigger or not to trigger.
|
|
*/
|
|
function setTriggerEvents($trigger) {
|
|
$this->_events = $trigger;
|
|
}
|
|
|
|
/**
|
|
* Returns bool if events are to be triggered or not.
|
|
*
|
|
* @return Bool bool for triggering events or not.
|
|
*/
|
|
function getTriggerEvents() {
|
|
return $this->_events;
|
|
}
|
|
|
|
/**
|
|
* Returns the parent files absolute path.
|
|
*
|
|
* @return String parent files absolute path.
|
|
*/
|
|
function getParent() {
|
|
$pathAr = explode("/", $this->_absPath);
|
|
|
|
array_pop($pathAr);
|
|
$path = implode("/", $pathAr);
|
|
|
|
// TODO: Check this
|
|
return ($path == "") ? null : $path;
|
|
}
|
|
|
|
/**
|
|
* Returns the parent files File instance.
|
|
*
|
|
* @return File parent files File instance or false if there is no more parents.
|
|
*/
|
|
function &getParentFile() {
|
|
$file = new Moxiecode_LocalFileImpl($this->_manager, $this->getParent());
|
|
return $file;
|
|
}
|
|
|
|
/**
|
|
* Returns the file name of a file.
|
|
*
|
|
* @return string File name of file.
|
|
*/
|
|
function getName() {
|
|
return basename($this->_manager->toOSPath($this->_absPath));
|
|
}
|
|
|
|
/**
|
|
* Returns the absolute path of the file.
|
|
*
|
|
* @return String absolute path of the file.
|
|
*/
|
|
function getAbsolutePath() {
|
|
return $this->_absPath;
|
|
}
|
|
|
|
/**
|
|
* Imports a local file to the file system, for example when users upload files.
|
|
*
|
|
* @param String $local_absolute_path Absolute path to local file to import.
|
|
*/
|
|
function importFile($local_absolute_path = "") {
|
|
$this->_clearCache();
|
|
|
|
// Add action
|
|
if ($this->_events) {
|
|
if ($this->isFile()) {
|
|
$this->_manager->dispatchEvent("onBeforeFileAction", array(ADD_ACTION, &$this));
|
|
$this->_manager->dispatchEvent("onFileAction", array(ADD_ACTION, &$this));
|
|
} else {
|
|
$this->_manager->dispatchEvent("onBeforeFileAction", array(MKDIR_ACTION, &$this));
|
|
$this->_manager->dispatchEvent("onFileAction", array(MKDIR_ACTION, &$this));
|
|
}
|
|
}
|
|
|
|
// Chmod the file
|
|
if (($mask = $this->_getConfigValue("filesystem.local.file_mask", false)) !== false)
|
|
@chmod($this->_manager->toOSPath($this->_absPath), intval($mask, 8));
|
|
|
|
// Chown the file
|
|
if (($owner = $this->_getConfigValue("filesystem.local.file_owner", false)) !== false)
|
|
$this->_chown($this->_manager->toOSPath($this->_absPath), $owner);
|
|
}
|
|
|
|
/**
|
|
* Returns true if the file exists.
|
|
*
|
|
* @return boolean true if the file exists.
|
|
*/
|
|
function exists() {
|
|
if (isset($this->_statCache['exists']))
|
|
return $this->_statCache['exists'];
|
|
|
|
// Returns false if safe mode is on and the user/group is not the same as apache
|
|
return ($this->_statCache['exists'] = file_exists($this->_manager->toOSPath($this->_absPath)));
|
|
}
|
|
|
|
/**
|
|
* Returns true if the file is a directory.
|
|
*
|
|
* @return boolean true if the file is a directory.
|
|
*/
|
|
function isDirectory() {
|
|
if (!$this->exists())
|
|
return $this->_type == MC_IS_DIRECTORY;
|
|
|
|
if (isset($this->_statCache['is_dir']))
|
|
return $this->_statCache['is_dir'];
|
|
|
|
return ($this->_statCache['is_dir'] = is_dir($this->_manager->toOSPath($this->_absPath)));
|
|
}
|
|
|
|
/**
|
|
* Returns true if the file is a file.
|
|
*
|
|
* @return boolean true if the file is a file.
|
|
*/
|
|
function isFile() {
|
|
if (!$this->exists())
|
|
return $this->_type == MC_IS_FILE;
|
|
|
|
if (isset($this->_statCache['is_file']))
|
|
return $this->_statCache['is_file'];
|
|
|
|
return ($this->_statCache['is_file'] = is_file($this->_manager->toOSPath($this->_absPath)));
|
|
}
|
|
|
|
/**
|
|
* Returns last modification date in ms as an long.
|
|
*
|
|
* @return long last modification date in ms as an long.
|
|
*/
|
|
function getLastModified() {
|
|
if (!isset($this->_statCache['stat']))
|
|
$this->_statCache['stat'] = @stat($this->_manager->toOSPath($this->_absPath));
|
|
|
|
return $this->_statCache['stat'][9];
|
|
}
|
|
|
|
/**
|
|
* Returns creation date in ms as an long.
|
|
*
|
|
* @return long creation date in ms as an long.
|
|
*/
|
|
function getCreationDate() {
|
|
if (!isset($this->_statCache['stat']))
|
|
$this->_statCache['stat'] = @stat($this->_manager->toOSPath($this->_absPath));
|
|
|
|
return $this->_statCache['stat'][10];
|
|
}
|
|
|
|
/**
|
|
* Returns true if the files is readable.
|
|
*
|
|
* @return boolean true if the files is readable.
|
|
*/
|
|
function canRead() {
|
|
if (isset($this->_statCache['is_readable']))
|
|
return $this->_statCache['is_readable'];
|
|
|
|
return ($this->_statCache['is_readable'] = is_readable($this->_manager->toOSPath($this->_absPath)));
|
|
}
|
|
|
|
/**
|
|
* Returns true if the files is writable.
|
|
*
|
|
* @return boolean true if the files is writable.
|
|
*/
|
|
function canWrite() {
|
|
// Check parent
|
|
if (!$this->exists()) {
|
|
$file =& $this->getParentFile();
|
|
|
|
if ($this->getAbsolutePath() == $file->getAbsolutePath())
|
|
return false;
|
|
|
|
return $file->canWrite();
|
|
}
|
|
|
|
if (isset($this->_statCache['is_writeable']))
|
|
return $this->_statCache['is_writeable'];
|
|
|
|
// Is windows
|
|
if (DIRECTORY_SEPARATOR == "\\") {
|
|
$path = $this->_manager->toOSPath($this->_absPath);
|
|
|
|
if (is_file($path)) {
|
|
$fp = @fopen($path, 'ab');
|
|
|
|
if ($fp) {
|
|
fclose($fp);
|
|
return true;
|
|
}
|
|
} else if (is_dir($path)) {
|
|
$tmpnam = time() . md5(uniqid('iswritable'));
|
|
|
|
if (@touch($path . '\\' . $tmpnam)) {
|
|
unlink($path . '\\' . $tmpnam);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// Other OS:es
|
|
return ($this->_statCache['is_writeable'] = is_writeable($this->_manager->toOSPath($this->_absPath)));
|
|
}
|
|
|
|
/**
|
|
* Returns file size as an long.
|
|
*
|
|
* @return long file size as an long.
|
|
*/
|
|
function getLength() {
|
|
if (!isset($this->_statCache['stat']))
|
|
$this->_statCache['stat'] = @stat($this->_manager->toOSPath($this->_absPath));
|
|
|
|
return $this->_statCache['stat'][7];
|
|
}
|
|
|
|
/**
|
|
* Copies this file to the specified file instance.
|
|
*
|
|
* @param File $dest File to copy to.
|
|
* @return boolean true - success, false - failure
|
|
*/
|
|
function copyTo(&$dest) {
|
|
$this->_clearCache();
|
|
|
|
if ($dest->exists())
|
|
return false;
|
|
|
|
// Copy in to your self?
|
|
if (strpos($dest->getAbsolutePath(), $this->getAbsolutePath()) === 0)
|
|
return false;
|
|
|
|
// Different file system then import
|
|
if (getClassName($dest) != 'moxiecode_localfileimpl')
|
|
return $dest->importFile($this->getAbsolutePath());
|
|
|
|
$dest->_clearCache();
|
|
|
|
if ($this->isDirectory()) {
|
|
$handle_as_add_event = true;
|
|
$treeHandler = new _LocalCopyDirTreeHandler($this->_manager, $this, $dest, $handle_as_add_event);
|
|
|
|
$this->listTree($treeHandler);
|
|
|
|
return true;
|
|
} else {
|
|
if ($this->_events)
|
|
$this->_manager->dispatchEvent("onBeforeFileAction", array(COPY_ACTION, &$this, &$dest));
|
|
|
|
$status = $this->_absPath == $dest->_absPath || copy($this->_manager->toOSPath($this->_absPath), $this->_manager->toOSPath($dest->_absPath));
|
|
|
|
// Chmod the file
|
|
if (($mask = $dest->_getConfigValue("filesystem.local.file_mask", false)) !== false)
|
|
@chmod($this->_manager->toOSPath($dest->_absPath), intval($mask, 8));
|
|
|
|
// Chown the file
|
|
if (($owner = $dest->_getConfigValue("filesystem.local.file_owner", false)) !== false)
|
|
$this->_chown($this->_manager->toOSPath($dest->_absPath), $owner);
|
|
|
|
if ($status && $this->_events)
|
|
$this->_manager->dispatchEvent("onFileAction", array(COPY_ACTION, &$this, &$dest));
|
|
|
|
return $status;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Deletes the file.
|
|
*
|
|
* @param boolean $deep If this option is enabled files will be deleted recurive.
|
|
* @return boolean true - success, false - failure
|
|
*/
|
|
function delete($deep = false) {
|
|
if (!$this->exists())
|
|
return false;
|
|
|
|
$this->_clearCache();
|
|
|
|
if (is_dir($this->_manager->toOSPath($this->_absPath))) {
|
|
if ($this->_events)
|
|
$this->_manager->dispatchEvent("onBeforeFileAction", array(RMDIR_ACTION, &$this));
|
|
|
|
if ($deep) {
|
|
// Get all the files
|
|
$treeHandler = new _LocalDeleteDirTreeHandler($this->_manager, $this);
|
|
$this->listTree($treeHandler);
|
|
|
|
// Delete the files
|
|
$files = array_reverse($treeHandler->getFiles());
|
|
foreach ($files as $file)
|
|
$file->delete();
|
|
|
|
// Hmm, should be better
|
|
return true;
|
|
}
|
|
|
|
if (($status = rmdir($this->_manager->toOSPath($this->_absPath))) && ($this->_events))
|
|
$this->_manager->dispatchEvent("onFileAction", array(RMDIR_ACTION, &$this));
|
|
} else {
|
|
if ($this->_events)
|
|
$this->_manager->dispatchEvent("onBeforeFileAction", array(DELETE_ACTION, &$this));
|
|
|
|
if (($status = unlink($this->_manager->toOSPath($this->_absPath))) && ($this->_events))
|
|
$this->_manager->dispatchEvent("onFileAction", array(DELETE_ACTION, &$this));
|
|
}
|
|
|
|
return $status;
|
|
}
|
|
|
|
/**
|
|
* Returns an array of File instances.
|
|
*
|
|
* @return Array array of File instances.
|
|
*/
|
|
function &listFiles() {
|
|
$files = $this->listFilesFiltered(new Moxiecode_DummyFileFilter());
|
|
return $files;
|
|
}
|
|
|
|
/**
|
|
* Returns an array of BaseFile instances based on the specified filter instance.
|
|
*
|
|
* @param FileFilter &$filter FileFilter instance to filter files by.
|
|
* @return Array array of File instances based on the specified filter instance.
|
|
*/
|
|
function &listFilesFiltered(&$filter) {
|
|
$dir = $this->_absPath;
|
|
$files = array();
|
|
$dirs = array();
|
|
$fileArray = array();
|
|
$dirArray = array();
|
|
|
|
if ($fHnd = opendir($this->_manager->toOSPath($dir))) {
|
|
// Is there a trailing slash on the dir? Get rid of it
|
|
//if ($dir[sizeof($dir)] == "/")
|
|
// $dir = substr($dir, 0, sizeof($dir) -1);
|
|
|
|
while (false !== ($file = readdir($fHnd))) {
|
|
if ($file == "." || $file == "..")
|
|
continue;
|
|
|
|
// Returns false if safe mode is on and the user/group is not the same as apache
|
|
$path = $dir . "/" . $file;
|
|
if (file_exists($path)) {
|
|
// We are at root!
|
|
if ($dir == "/")
|
|
$dir = "";
|
|
|
|
if (is_file($path))
|
|
$fileArray[] = $file;
|
|
else
|
|
$dirArray[] = $file;
|
|
}
|
|
}
|
|
|
|
// Close handle
|
|
closedir($fHnd);
|
|
|
|
sort($dirArray);
|
|
sort($fileArray);
|
|
|
|
// Add dirs
|
|
foreach ($dirArray as $adir) {
|
|
$file = new Moxiecode_LocalFileImpl($this->_manager, $dir . "/" . $adir);
|
|
|
|
if ($filter->accept($file) < 0)
|
|
continue;
|
|
|
|
array_push($files, $file);
|
|
}
|
|
|
|
// Add files
|
|
foreach ($fileArray as $afile) {
|
|
$file = new Moxiecode_LocalFileImpl($this->_manager, $dir . "/" . $afile);
|
|
|
|
if ($filter->accept($file) < 0)
|
|
continue;
|
|
|
|
array_push($files, $file);
|
|
}
|
|
}
|
|
|
|
return $files;
|
|
}
|
|
|
|
/**
|
|
* Lists the file as an tree and calls the specified FileTreeHandler instance on each file.
|
|
*
|
|
* @param FileTreeHandler &$file_tree_handler FileTreeHandler to invoke on each file.
|
|
*/
|
|
function listTree(&$file_tree_handler) {
|
|
$this->_listTree($this, $file_tree_handler, new Moxiecode_DummyFileFilter(), 0);
|
|
}
|
|
|
|
/**
|
|
* Lists the file as an tree and calls the specified FileTreeHandler instance on each file
|
|
* if the file filter accepts the file.
|
|
*
|
|
* @param FileTreeHandler &$file_tree_handler FileTreeHandler to invoke on each file.
|
|
* @param FileTreeHandler &$file_filter FileFilter instance to filter files by.
|
|
*/
|
|
function listTreeFiltered(&$file_tree_handler, &$file_filter) {
|
|
$this->_listTree($this, $file_tree_handler, $file_filter, 0);
|
|
}
|
|
|
|
/**
|
|
* Creates a new directory.
|
|
*
|
|
* @return boolean true- success, false - failure
|
|
*/
|
|
function mkdir() {
|
|
$this->_clearCache();
|
|
|
|
if ($this->_events)
|
|
$this->_manager->dispatchEvent("onBeforeFileAction", array(MKDIR_ACTION, &$this));
|
|
|
|
$tpl = $this->_getConfigValue("filesystem.local.directory_template", false);
|
|
|
|
if ($tpl)
|
|
$status = copy($this->_manager->toAbsPath($tpl), $this->_manager->toOSPath($this->_absPath));
|
|
else
|
|
$status = mkdir($this->_manager->toOSPath($this->_absPath));
|
|
|
|
// Chmod the dir
|
|
if (($mask = $this->_getConfigValue("filesystem.local.directory_mask", false)) !== false)
|
|
@chmod($this->_manager->toOSPath($this->_absPath), intval($mask, 8));
|
|
|
|
// Chown the dir
|
|
if (($owner = $this->_getConfigValue("filesystem.local.directory_owner", false)) !== false)
|
|
$this->_chown($this->_manager->toOSPath($this->_absPath), $owner);
|
|
|
|
if ($status && $this->_events)
|
|
$this->_manager->dispatchEvent("onFileAction", array(MKDIR_ACTION, &$this));
|
|
|
|
return $status;
|
|
}
|
|
|
|
/**
|
|
* Renames/Moves this file to the specified file instance.
|
|
*
|
|
* @param File $dest File to rename/move to.
|
|
* @return boolean true- success, false - failure
|
|
*/
|
|
function renameTo(&$dest) {
|
|
$this->_clearCache();
|
|
|
|
// Already exists
|
|
if ($dest->exists())
|
|
return false;
|
|
|
|
if ($this->_events)
|
|
$this->_manager->dispatchEvent("onBeforeFileAction", array(RENAME_ACTION, &$this, &$dest));
|
|
|
|
if ($this->_absPath != $dest->_absPath)
|
|
$status = rename($this->_manager->toOSPath($this->_absPath), $this->_manager->toOSPath($dest->_absPath));
|
|
|
|
if ($status && $this->_events)
|
|
$this->_manager->dispatchEvent("onFileAction", array(RENAME_ACTION, &$this, &$dest));
|
|
|
|
$isFile = is_file($this->_manager->toOSPath($this->_absPath));
|
|
|
|
// Chmod the file/directory
|
|
if (($mask = $dest->_getConfigValue("filesystem.local." . ($isFile ? "file" : "directory") . "_mask", false)) !== false)
|
|
@chmod($this->_manager->toOSPath($dest->_absPath), intval($mask, 8));
|
|
|
|
// Chown the file/directory
|
|
if (($owner = $dest->_getConfigValue("filesystem.local." . ($isFile ? "file" : "directory") . "_owner", false)) !== false)
|
|
$this->_chown($this->_manager->toOSPath($dest->_absPath), $owner);
|
|
|
|
return $status;
|
|
}
|
|
|
|
/*
|
|
* Sets the last-modified time of the file or directory.
|
|
*
|
|
* @param String $datetime The new date/time to set the file, in timestamp format
|
|
* @return boolean true- success, false - failure
|
|
*/
|
|
function setLastModified($datetime) {
|
|
$this->_clearCache();
|
|
return touch($this->_manager->toOSPath($this->_absPath), $datetime);
|
|
}
|
|
|
|
/**
|
|
* Opens a file stream by the specified mode. The default mode is rb.
|
|
*
|
|
* @param String $mode Mode to open file by, r, rb, w, wb etc.
|
|
* @return FileStream File stream implementation for the file system.
|
|
*/
|
|
function &open($mode = 'rb') {
|
|
$this->_clearCache();
|
|
$stream = new Moxiecode_LocalFileStream($this, $mode);
|
|
|
|
return $stream;
|
|
}
|
|
|
|
// * * Private methods
|
|
|
|
function _clearCache() {
|
|
$this->_statCache = array();
|
|
}
|
|
|
|
/**
|
|
* Lists files recursive, and places the files in the specified array.
|
|
*/
|
|
function _listTree($file, &$file_tree_handler, &$file_filter, $level) {
|
|
$state = $file_tree_handler->CONTINUE;
|
|
|
|
if ($file_filter->accept($file)) {
|
|
$state = $file_tree_handler->handle($file, $level);
|
|
|
|
if ($state == $file_tree_handler->ABORT || $state == $file_tree_handler->ABORT_FOLDER)
|
|
return $state;
|
|
}
|
|
|
|
$files = $file->listFiles();
|
|
|
|
foreach ($files as $file) {
|
|
if ($file_filter->accept($file)) {
|
|
if ($file->isFile()) {
|
|
// This is some weird shit!
|
|
//if (!is_object($file_filter))
|
|
$state = $file_tree_handler->handle($file, $level);
|
|
} else {
|
|
$state = $this->_listTree($file, $file_tree_handler, $file_filter, ++$level);
|
|
--$level;
|
|
}
|
|
}
|
|
|
|
if ($state == $file_tree_handler->ABORT)
|
|
return $state;
|
|
}
|
|
|
|
return $file_tree_handler->CONTINUE;
|
|
}
|
|
|
|
/**
|
|
* Returns a merged name/value array of config elements.
|
|
*
|
|
* @return Array Merged name/value array of config elements.
|
|
*/
|
|
function getConfig() {
|
|
$globalConf = $this->_manager->getConfig();
|
|
|
|
// Not cached config
|
|
if (!$this->_config) {
|
|
$localConfig = array();
|
|
|
|
$this->_config = $globalConf;
|
|
|
|
// Get files up the tree
|
|
$accessFiles = array();
|
|
$file =& $this;
|
|
|
|
if ($file->isFile())
|
|
$file =& $file->getParentFile();
|
|
|
|
while ($file->exists() && $file->getAbsolutePath() != "/") {
|
|
$accessFile = new Moxiecode_LocalFileImpl($this->_manager, $file->getAbsolutePath(), $globalConf["filesystem.local.access_file_name"]);
|
|
if ($accessFile->exists())
|
|
$accessFiles[] = $accessFile;
|
|
|
|
// Is not a valid path break loop
|
|
if (!$this->_manager->verifyPath($file->getParent()))
|
|
break;
|
|
|
|
$file =& $file->getParentFile();
|
|
}
|
|
|
|
// Parse and merge
|
|
$allowoverrideKeys = array();
|
|
foreach ($this->_config as $key => $value) {
|
|
$keyChunks = explode('.', $key);
|
|
|
|
if ($keyChunks[count($keyChunks)-1] == "allow_override") {
|
|
foreach (explode(',', $value) as $keySuffix) {
|
|
$keyChunks[count($keyChunks)-1] = $keySuffix;
|
|
$allowoverrideKeys[] = implode('.', $keyChunks);
|
|
}
|
|
}
|
|
}
|
|
|
|
foreach (array_reverse($accessFiles) as $accessFile) {
|
|
$config = array();
|
|
|
|
// Parse ini file
|
|
if (($fp = fopen($this->_manager->toOSPath($accessFile->getAbsolutePath()), "r"))) {
|
|
while (!feof($fp)) {
|
|
$line = trim(fgets($fp));
|
|
|
|
// Skip comments
|
|
if (substr($line, 0, 1) == "#")
|
|
continue;
|
|
|
|
// Split rows
|
|
if (($pos = strpos($line, "=")) !== FALSE)
|
|
$config[substr($line, 0, $pos)] = substr($line, $pos+1);
|
|
}
|
|
|
|
fclose($fp);
|
|
}
|
|
|
|
// Handle local config values
|
|
$curDir = $this->isFile() ? $this->getParent() : $this->getAbsolutePath();
|
|
if ($accessFile->getParent() == $curDir) {
|
|
foreach ($config as $key => $value) {
|
|
if (substr($key, 0, 1) == '_')
|
|
$localConfig[substr($key, 1)] = $value;
|
|
}
|
|
}
|
|
|
|
// Parse allow keys and deny keys
|
|
$denyOverrideKeys = array();
|
|
foreach ($config as $key => $value) {
|
|
$keyChunks = explode('.', $key);
|
|
$lastChunk = $keyChunks[count($keyChunks)-1];
|
|
|
|
if ($lastChunk == "allow_override" || $lastChunk == "deny_override") {
|
|
foreach (explode(',', $value) as $keySuffix) {
|
|
$keyChunks[count($keyChunks)-1] = $keySuffix;
|
|
$allowDenyKey = implode('.', $keyChunks);
|
|
|
|
if (in_array($allowDenyKey, $allowoverrideKeys)) {
|
|
if ($lastChunk == "allow_override")
|
|
$allowoverrideKeys[] = $allowDenyKey;
|
|
else
|
|
$denyOverrideKeys[] = $allowDenyKey;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Remove the denied keys from the allow list
|
|
/* foreach ($denyOverrideKeys as $denyKey) {
|
|
for ($i=0; $i<count($allowoverrideKeys); $i++) {
|
|
if ($denyKey == $allowoverrideKeys[$i])
|
|
unset($allowoverrideKeys[$i]);
|
|
}
|
|
}*/
|
|
|
|
// Add all overriden values
|
|
foreach ($config as $key => $value) {
|
|
$validAllKey = false;
|
|
|
|
foreach ($allowoverrideKeys as $allowkey) {
|
|
if (strpos($allowkey, "*") > 0) {
|
|
$allowkey = str_replace("*", "", $allowkey);
|
|
// echo $allowkey . "," . $key . strpos($allowkey, $key) . "<br>";
|
|
if (strpos($key, $allowkey) === 0) {
|
|
$validAllKey = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ((in_array($key, $allowoverrideKeys) || $validAllKey) && !in_array($key, $denyOverrideKeys)) {
|
|
if (strpos($value, '${') !== false)
|
|
$value = str_replace('${configpath}', $accessFile->getParent(), $value);
|
|
|
|
$this->_config[$key] = $value;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Variable substitute the values
|
|
foreach ($this->_config as $key => $value) {
|
|
if (!is_array($value) && strpos($value, '${') !== false) {
|
|
if ($this->isFile())
|
|
$path = $this->getAbsolutePath();
|
|
else
|
|
$path = $this->getParent();
|
|
|
|
$value = str_replace('${path}', $path, $value);
|
|
$value = str_replace('${rootpath}', $this->_manager->toUnixPath($this->_manager->_rootPaths[0]), $value);
|
|
|
|
// Handle multiple rootpaths
|
|
for ($i=0; $i<count($this->_manager->_rootPaths); $i++)
|
|
$value = str_replace('${rootpath' . $i . '}', $this->_manager->toUnixPath($this->_manager->_rootPaths[$i]), $value);
|
|
|
|
$this->_config[$key] = $value;
|
|
}
|
|
}
|
|
|
|
// Force local config
|
|
foreach ($localConfig as $key => $value) {
|
|
//$this->_config[$key] = $value;
|
|
|
|
$validAllKey = false;
|
|
|
|
foreach ($allowoverrideKeys as $allowkey) {
|
|
if (strpos($allowkey, "*") > 0) {
|
|
$allowkey = str_replace("*", "", $allowkey);
|
|
// echo $allowkey . "," . $key . strpos($allowkey, $key) . "<br>";
|
|
if (strpos($key, $allowkey) === 0) {
|
|
$validAllKey = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ((in_array($key, $allowoverrideKeys) || $validAllKey) && !in_array($key, $denyOverrideKeys)) {
|
|
if (strpos($value, '${') !== false)
|
|
$value = str_replace('${configpath}', $accessFile->getParent(), $value);
|
|
|
|
$this->_config[$key] = $value;
|
|
}
|
|
}
|
|
|
|
/* foreach ($this->_config as $key => $value) {
|
|
if (in_array($key, $allowoverrideKeys)) {
|
|
// Seems to be a variable
|
|
if (strpos($value, '${') !== false) {
|
|
$matches = array();
|
|
preg_match_all('/\${(.*)}/i', $value, $matches);
|
|
var_dump($matches);
|
|
foreach ($matches as $match)
|
|
$this->_config[$key] = str_replace('${' . $match . '}', $this->_config[$match], $this->_config[$key]);
|
|
}
|
|
}
|
|
}*/
|
|
}
|
|
|
|
return $this->_config;
|
|
}
|
|
|
|
/**
|
|
* Returns a config value by the specified key.
|
|
*
|
|
* @param String key Key to return value by.
|
|
* @param String default_value Optional default value.
|
|
* @return String Value returned from config.
|
|
*/
|
|
function _getConfigValue($key, $default_value = "") {
|
|
$config = $this->getConfig();
|
|
|
|
if (isset($config[$key]))
|
|
return $config[$key] ? $config[$key] : $default_value;
|
|
else
|
|
return $default_value;
|
|
}
|
|
|
|
function _chown($path, $owner) {
|
|
if ($owner == "")
|
|
return;
|
|
|
|
$owner = explode(":", $owner);
|
|
|
|
// Only user
|
|
if (count($owner) == 1)
|
|
array_push($owner, "");
|
|
|
|
// Hmm
|
|
if (count($owner) != 2)
|
|
return;
|
|
|
|
// Set user
|
|
if ($owner[0] != "")
|
|
@chown($path, $owner[0]);
|
|
|
|
// Set group
|
|
if ($owner[1] != "")
|
|
@chgrp($path, $owner[1]);
|
|
}
|
|
|
|
function _cmpByName($file1, $file2) {
|
|
$al = strtolower($file1->getName());
|
|
$bl = strtolower($file2->getName());
|
|
|
|
if ($al == $bl)
|
|
return 0;
|
|
|
|
return $al > $bl ? 1 : -1;
|
|
}
|
|
}
|
|
|
|
class _LocalCopyDirTreeHandler extends Moxiecode_FileTreeHandler {
|
|
var $_fromFile;
|
|
var $_destFile;
|
|
var $_manager;
|
|
var $_handle_as_add_event;
|
|
|
|
function _LocalCopyDirTreeHandler(&$manager, $from_file, $dest_file, $handle_as_add_event) {
|
|
$this->_manager = $manager;
|
|
$this->_fromFile = $from_file;
|
|
$this->_destFile = $dest_file;
|
|
$this->_handle_as_add_event = $handle_as_add_event;
|
|
}
|
|
|
|
/**
|
|
* Handles a file instance while looping an tree of directories.
|
|
*
|
|
* @param File $file File object reference
|
|
* @param int $level Current level of tree parse
|
|
* @return int State of what to do next can be CONTINUE, ABORT or ABORTFOLDER.
|
|
*/
|
|
function handle($file, $level) {
|
|
$toPath = $this->_destFile->getAbsolutePath();
|
|
$toPath .= substr($file->getAbsolutePath(), strlen($this->_fromFile->getAbsolutePath()));
|
|
$toFile = $this->_manager->getFile($toPath);
|
|
|
|
//debug($file->getAbsolutePath() . "->" . $toPath);
|
|
|
|
// Do action
|
|
if ($file->isDirectory())
|
|
$toFile->mkdir();
|
|
else
|
|
$file->copyTo($toFile);
|
|
|
|
return $this->CONTINUE;
|
|
}
|
|
}
|
|
|
|
class _LocalDeleteDirTreeHandler extends Moxiecode_FileTreeHandler {
|
|
var $_manager;
|
|
var $_dir;
|
|
var $_files;
|
|
|
|
function _LocalDeleteDirTreeHandler(&$manager, $dir) {
|
|
$this->_manager = $manager;
|
|
$this->_dir = $dir;
|
|
$this->_files = array();
|
|
}
|
|
|
|
/**
|
|
* Returns all the files and dirs.
|
|
*
|
|
* @return Array All the files and dirs.
|
|
*/
|
|
function getFiles() {
|
|
return $this->_files;
|
|
}
|
|
|
|
/**
|
|
* Handles a file instance while looping an tree of directories.
|
|
*
|
|
* @param File $file File object reference
|
|
* @param int $level Current level of tree parse
|
|
* @return int State of what to do next can be CONTINUE, ABORT or ABORTFOLDER.
|
|
*/
|
|
function handle($file, $level) {
|
|
$this->_files[] = $file;
|
|
|
|
//$file->delete();
|
|
return $this->CONTINUE;
|
|
}
|
|
}
|
|
|
|
class Moxiecode_LocalFileStream extends Moxiecode_FileStream {
|
|
var $_fp;
|
|
var $_file;
|
|
|
|
function Moxiecode_LocalFileStream(&$file, $mode) {
|
|
$this->_file = $file;
|
|
$this->_fp = fopen($file->getAbsolutePath(), $mode);
|
|
}
|
|
|
|
function skip($bytes) {
|
|
$pos = ftell($this->_fp);
|
|
|
|
fseek($this->_fp, $bytes, SEEK_CUR);
|
|
|
|
return ftell($this->_fp) - $pos;
|
|
}
|
|
|
|
function read($len = 1024) {
|
|
return fread($this->_fp, $len);
|
|
}
|
|
|
|
function readToEnd() {
|
|
$data = "";
|
|
|
|
while (($chunk = $this->read(1024)) != null)
|
|
$data .= $chunk;
|
|
|
|
return $data;
|
|
}
|
|
|
|
function write($buff, $len = -1) {
|
|
if ($len == -1)
|
|
return fwrite($this->_fp, $buff);
|
|
|
|
return fwrite($this->_fp, $buff, $len);
|
|
}
|
|
|
|
function close() {
|
|
$this->_file->_clearCache();
|
|
@fclose($this->_fp);
|
|
$this->_fp = null;
|
|
}
|
|
}
|
|
|
|
?>
|