git-svn-id: https://192.168.0.254/svn/Proyectos.Incam_MaquetaIntranet/trunk@5 dea6828b-3720-d243-8757-cae5f23734d0
1996 lines
56 KiB
PHP
1996 lines
56 KiB
PHP
<?php
|
|
|
|
// set locale to UTF8 to correct multibyte characters
|
|
setlocale(LC_ALL, 'en_US.UTF8');
|
|
|
|
interface elFinderILogger {
|
|
public function log($cmd, $ok, $context, $err='', $errorData = array());
|
|
}
|
|
|
|
class elFinder {
|
|
|
|
/**
|
|
* object options
|
|
*
|
|
* @var array
|
|
**/
|
|
protected $_options = array(
|
|
'root' => '', // path to root directory
|
|
'URL' => '', // root directory URL
|
|
'rootAlias' => 'Home', // display this instead of root directory name
|
|
'disabled' => array(), // list of not allowed commands
|
|
'dotFiles' => false, // display dot files
|
|
'dirSize' => true, // count total directories sizes
|
|
'fileMode' => 0666, // new files mode
|
|
'dirMode' => 0777, // new folders mode
|
|
'mimeDetect' => 'auto', // files mimetypes detection method (finfo, mime_content_type, linux (file -ib), bsd (file -Ib), internal (by extensions))
|
|
'uploadAllow' => array(), // mimetypes which allowed to upload
|
|
'uploadDeny' => array(), // mimetypes which not allowed to upload
|
|
'uploadOrder' => 'deny,allow', // order to proccess uploadAllow and uploadAllow options
|
|
'imgLib' => 'auto', // image manipulation library (imagick, mogrify, gd)
|
|
'tmbDir' => '.tmb', // directory name for image thumbnails. Set to "" to avoid thumbnails generation
|
|
'tmbCleanProb' => 1, // how frequiently clean thumbnails dir (0 - never, 200 - every init request)
|
|
'tmbAtOnce' => 5, // number of thumbnails to generate per request
|
|
'tmbSize' => 48, // images thumbnails size (px)
|
|
'tmbCrop' => true, // crop thumbnails (true - crop, false - scale image to fit thumbnail size)
|
|
'tmbBgColor' => '#ffffff', // thumbnail background color
|
|
'fileURL' => true, // display file URL in "get info"
|
|
'dateFormat' => 'j M Y H:i', // file modification date format
|
|
'logger' => null, // object logger
|
|
'aclObj' => null, // acl object (not implemented yet)
|
|
'aclRole' => 'user', // role for acl
|
|
'defaults' => array( // default permisions
|
|
'read' => true,
|
|
'write' => true,
|
|
'rm' => true
|
|
),
|
|
'perms' => array(), // individual folders/files permisions
|
|
'debug' => false, // send debug to client
|
|
'archiveMimes' => array(), // allowed archive's mimetypes to create. Leave empty for all available types.
|
|
'archivers' => array() // info about archivers to use. See example below. Leave empty for auto detect
|
|
// 'archivers' => array(
|
|
// 'create' => array(
|
|
// 'application/x-gzip' => array(
|
|
// 'cmd' => 'tar',
|
|
// 'argc' => '-czf',
|
|
// 'ext' => 'tar.gz'
|
|
// )
|
|
// ),
|
|
// 'extract' => array(
|
|
// 'application/x-gzip' => array(
|
|
// 'cmd' => 'tar',
|
|
// 'argc' => '-xzf',
|
|
// 'ext' => 'tar.gz'
|
|
// ),
|
|
// 'application/x-bzip2' => array(
|
|
// 'cmd' => 'tar',
|
|
// 'argc' => '-xjf',
|
|
// 'ext' => 'tar.bz'
|
|
// )
|
|
// )
|
|
// )
|
|
);
|
|
|
|
/**
|
|
* mapping $_GET['cmd]/$_POST['cmd] to class methods
|
|
*
|
|
* @var array
|
|
**/
|
|
protected $_commands = array(
|
|
'open' => '_open',
|
|
'reload' => '_reload',
|
|
'mkdir' => '_mkdir',
|
|
'mkfile' => '_mkfile',
|
|
'rename' => '_rename',
|
|
'upload' => '_upload',
|
|
'paste' => '_paste',
|
|
'rm' => '_rm',
|
|
'duplicate' => '_duplicate',
|
|
'read' => '_fread',
|
|
'edit' => '_edit',
|
|
'archive' => '_archive',
|
|
'extract' => '_extract',
|
|
'resize' => '_resize',
|
|
'tmb' => '_thumbnails',
|
|
'ping' => '_ping'
|
|
);
|
|
|
|
/**
|
|
* List of commands to log
|
|
*
|
|
* @var string
|
|
**/
|
|
public $_loggedCommands = array('mkdir', 'mkfile', 'rename', 'upload', 'paste', 'rm', 'duplicate', 'edit', 'resize');
|
|
|
|
/**
|
|
* Context to log command
|
|
*
|
|
* @var string
|
|
**/
|
|
protected $_logContext = array();
|
|
|
|
/**
|
|
* extensions/mimetypes for _mimetypeDetect = 'internal'
|
|
*
|
|
* @var array
|
|
**/
|
|
protected $_mimeTypes = array(
|
|
//applications
|
|
'ai' => 'application/postscript',
|
|
'eps' => 'application/postscript',
|
|
'exe' => 'application/octet-stream',
|
|
'doc' => 'application/vnd.ms-word',
|
|
'xls' => 'application/vnd.ms-excel',
|
|
'ppt' => 'application/vnd.ms-powerpoint',
|
|
'pps' => 'application/vnd.ms-powerpoint',
|
|
'pdf' => 'application/pdf',
|
|
'xml' => 'application/xml',
|
|
'odt' => 'application/vnd.oasis.opendocument.text',
|
|
'swf' => 'application/x-shockwave-flash',
|
|
// archives
|
|
'gz' => 'application/x-gzip',
|
|
'tgz' => 'application/x-gzip',
|
|
'bz' => 'application/x-bzip2',
|
|
'bz2' => 'application/x-bzip2',
|
|
'tbz' => 'application/x-bzip2',
|
|
'zip' => 'application/zip',
|
|
'rar' => 'application/x-rar',
|
|
'tar' => 'application/x-tar',
|
|
'7z' => 'application/x-7z-compressed',
|
|
// texts
|
|
'txt' => 'text/plain',
|
|
'php' => 'text/x-php',
|
|
'html' => 'text/html',
|
|
'htm' => 'text/html',
|
|
'js' => 'text/javascript',
|
|
'css' => 'text/css',
|
|
'rtf' => 'text/rtf',
|
|
'rtfd' => 'text/rtfd',
|
|
'py' => 'text/x-python',
|
|
'java' => 'text/x-java-source',
|
|
'rb' => 'text/x-ruby',
|
|
'sh' => 'text/x-shellscript',
|
|
'pl' => 'text/x-perl',
|
|
'sql' => 'text/x-sql',
|
|
// images
|
|
'bmp' => 'image/x-ms-bmp',
|
|
'jpg' => 'image/jpeg',
|
|
'jpeg' => 'image/jpeg',
|
|
'gif' => 'image/gif',
|
|
'png' => 'image/png',
|
|
'tif' => 'image/tiff',
|
|
'tiff' => 'image/tiff',
|
|
'tga' => 'image/x-targa',
|
|
'psd' => 'image/vnd.adobe.photoshop',
|
|
//audio
|
|
'mp3' => 'audio/mpeg',
|
|
'mid' => 'audio/midi',
|
|
'ogg' => 'audio/ogg',
|
|
'mp4a' => 'audio/mp4',
|
|
'wav' => 'audio/wav',
|
|
'wma' => 'audio/x-ms-wma',
|
|
// video
|
|
'avi' => 'video/x-msvideo',
|
|
'dv' => 'video/x-dv',
|
|
'mp4' => 'video/mp4',
|
|
'mpeg' => 'video/mpeg',
|
|
'mpg' => 'video/mpeg',
|
|
'mov' => 'video/quicktime',
|
|
'wm' => 'video/x-ms-wmv',
|
|
'flv' => 'video/x-flv',
|
|
'mkv' => 'video/x-matroska'
|
|
);
|
|
|
|
/**
|
|
* undocumented class variable
|
|
*
|
|
* @var string
|
|
**/
|
|
protected $_time = 0;
|
|
|
|
/**
|
|
* Additional data about error
|
|
*
|
|
* @var array
|
|
**/
|
|
protected $_errorData = array();
|
|
|
|
/**
|
|
* undocumented class variable
|
|
*
|
|
* @var string
|
|
**/
|
|
protected $_fakeRoot = '';
|
|
|
|
/**
|
|
* Command result to send to client
|
|
*
|
|
* @var array
|
|
**/
|
|
protected $_result = array();
|
|
|
|
/**
|
|
* undocumented class variable
|
|
*
|
|
* @var string
|
|
**/
|
|
protected $_today = 0;
|
|
|
|
/**
|
|
* undocumented class variable
|
|
*
|
|
* @var string
|
|
**/
|
|
protected $_yesterday = 0;
|
|
|
|
/**
|
|
* constructor
|
|
*
|
|
* @param array object options
|
|
* @return void
|
|
**/
|
|
public function __construct($options=array()) {
|
|
foreach ($this->_options as $k=>$v) {
|
|
if (isset($options[$k])) {
|
|
$this->_options[$k] = is_array($this->_options[$k])
|
|
? array_merge($this->_options[$k], $options[$k])
|
|
: $options[$k];
|
|
}
|
|
}
|
|
|
|
if (substr($this->_options['root'], -1) == DIRECTORY_SEPARATOR) {
|
|
$this->_options['root'] = substr($this->_options['root'], 0, -1);
|
|
}
|
|
|
|
$this->_time = $this->_options['debug'] ? $this->_utime() : 0;
|
|
|
|
$this->_fakeRoot = !$this->_options['rootAlias']
|
|
? $this->_options['root']
|
|
: dirname($this->_options['root']).DIRECTORY_SEPARATOR.$this->_options['rootAlias'];
|
|
|
|
if (!empty($this->_options['disabled'])) {
|
|
$no = array('open', 'reload', 'tmb', 'ping');
|
|
foreach ($this->_options['disabled'] as $k => $c) {
|
|
if (!isset($this->_commands[$c]) || in_array($c, $no)) {
|
|
unset($this->_options['disabled'][$k]);
|
|
} else {
|
|
unset($this->_commands[$c]);
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($this->_options['tmbDir']) {
|
|
$tmbDir = $this->_options['root'].DIRECTORY_SEPARATOR.$this->_options['tmbDir'];
|
|
$this->_options['tmbDir'] = is_dir($tmbDir) || @mkdir($tmbDir, $this->_options['dirMode']) ? $tmbDir : '';
|
|
}
|
|
if ($this->_options['tmbDir']) {
|
|
if (!in_array($this->_options['imgLib'], array('imagick', 'mogrify', 'gd'))) {
|
|
$this->_options['imgLib'] = $this->_getImgLib();
|
|
}
|
|
}
|
|
$this->_today = mktime(0,0,0, date('m'), date('d'), date('Y'));
|
|
$this->_yesterday = $this->_today-86400;
|
|
}
|
|
|
|
/**
|
|
* Proccess client request and output json
|
|
*
|
|
* @return void
|
|
**/
|
|
public function run() {
|
|
if (!function_exists('json_encode')) {
|
|
exit('{"error":"PHP JSON module not installed"}');
|
|
}
|
|
if (empty($this->_options['root']) || !is_dir($this->_options['root'])) {
|
|
exit(json_encode(array('error' => 'Invalid backend configuration')));
|
|
}
|
|
if (!$this->_isAllowed($this->_options['root'], 'read')) {
|
|
exit(json_encode(array('error' => 'Access denied')));
|
|
}
|
|
|
|
$cmd = '';
|
|
if (!empty($_POST['cmd'])) {
|
|
$cmd = trim($_POST['cmd']);
|
|
} elseif (!empty($_GET['cmd'])) {
|
|
$cmd = trim($_GET['cmd']);
|
|
}
|
|
if (!$cmd && $_SERVER["REQUEST_METHOD"] == 'POST') {
|
|
header("Content-Type: text/html");
|
|
$this->_result['error'] = 'Data exceeds the maximum allowed size';
|
|
exit(json_encode($this->_result));
|
|
}
|
|
|
|
if ($cmd && (empty($this->_commands[$cmd]) || !method_exists($this, $this->_commands[$cmd]))) {
|
|
exit(json_encode(array('error' => 'Unknown command')));
|
|
}
|
|
|
|
if (isset($_GET['init'])) {
|
|
|
|
$ts = $this->_utime();
|
|
$this->_result['disabled'] = array_values($this->_options['disabled']);
|
|
|
|
$this->_result['params'] = array(
|
|
'dotFiles' => $this->_options['dotFiles'],
|
|
'uplMaxSize' => ini_get('upload_max_filesize'),
|
|
'archives' => array(),
|
|
'extract' => array(),
|
|
'url' => $this->_options['fileURL'] ? $this->_options['URL'] : ''
|
|
);
|
|
if (isset($this->_commands['archive']) || isset($this->_commands['extract'])) {
|
|
$this->_checkArchivers();
|
|
if (isset($this->_commands['archive'])) {
|
|
$this->_result['params']['archives'] = $this->_options['archiveMimes'];
|
|
}
|
|
if (isset($this->_commands['extract'])) {
|
|
$this->_result['params']['extract'] = array_keys($this->_options['archivers']['extract']);
|
|
}
|
|
}
|
|
// clean thumbnails dir
|
|
if ($this->_options['tmbDir']) {
|
|
srand((double) microtime() * 1000000);
|
|
if (rand(1, 200) <= $this->_options['tmbCleanProb']) {
|
|
$ts2 = $this->_utime();
|
|
$ls = scandir($this->_options['tmbDir']);
|
|
for ($i=0, $s = count($ls); $i < $s; $i++) {
|
|
if ('.' != $ls[$i] && '..' != $ls[$i]) {
|
|
@unlink($this->_options['tmbDir'].DIRECTORY_SEPARATOR.$ls[$i]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
if ($this->_options['debug']) {
|
|
$this->_result['debug'] = array(
|
|
'time' => $this->_utime() - $this->_time,
|
|
'mimeDetect' => $this->_options['mimeDetect'],
|
|
'imgLib' => $this->_options['imgLib']
|
|
);
|
|
if ($this->_options['dirSize']) {
|
|
$this->_result['debug']['dirSize'] = true;
|
|
$this->_result['debug']['du'] = @$this->_options['du'];
|
|
}
|
|
}
|
|
|
|
if ($cmd) {
|
|
$this->{$this->_commands[$cmd]}();
|
|
} else {
|
|
$this->_open();
|
|
}
|
|
|
|
header("Content-Type: ".($cmd == 'upload' ? 'text/html' : 'application/json'));
|
|
header("Connection: close");
|
|
echo json_encode($this->_result);
|
|
|
|
if (!empty($this->_options['logger']) && in_array($cmd, $this->_loggedCommands)) {
|
|
$this->_options['logger']->log($cmd, empty($this->_result['error']), $this->_logContext, !empty($this->_result['error']) ? $this->_result['error'] : '', !empty($this->_result['errorData']) ? $this->_result['errorData'] : array());
|
|
}
|
|
exit();
|
|
}
|
|
|
|
|
|
/************************************************************/
|
|
/** elFinder commands **/
|
|
/************************************************************/
|
|
|
|
/**
|
|
* Return current dir content to client or output file content to browser
|
|
*
|
|
* @return void
|
|
**/
|
|
protected function _open()
|
|
{
|
|
if (isset($_GET['current'])) { // read file
|
|
if (empty($_GET['current'])
|
|
|| empty($_GET['target'])
|
|
|| false == ($dir = $this->_findDir(trim($_GET['current'])))
|
|
|| false == ($file = $this->_find(trim($_GET['target']), $dir))
|
|
|| is_dir($file)
|
|
) {
|
|
header('HTTP/1.x 404 Not Found');
|
|
exit('File not found');
|
|
}
|
|
if (!$this->_isAllowed($dir, 'read') || !$this->_isAllowed($file, 'read')) {
|
|
header('HTTP/1.x 403 Access Denied');
|
|
exit('Access denied');
|
|
}
|
|
|
|
if (filetype($file) == 'link') {
|
|
$file = $this->_readlink($file);
|
|
if (!$file || is_dir($file)) {
|
|
header('HTTP/1.x 404 Not Found');
|
|
exit('File not found');
|
|
}
|
|
if (!$this->_isAllowed(dirname($file), 'read') || !$this->_isAllowed($file, 'read')) {
|
|
header('HTTP/1.x 403 Access Denied');
|
|
exit('Access denied');
|
|
}
|
|
}
|
|
|
|
$mime = $this->_mimetype($file);
|
|
$parts = explode('/', $mime);
|
|
$disp = $parts[0] == 'image' || $parts[0] == 'text' ? 'inline' : 'attachments';
|
|
|
|
header("Content-Type: ".$mime);
|
|
header("Content-Disposition: ".$disp."; filename=".basename($file));
|
|
header("Content-Location: ".str_replace($this->_options['root'], '', $file));
|
|
header('Content-Transfer-Encoding: binary');
|
|
header("Content-Length: ".filesize($file));
|
|
header("Connection: close");
|
|
readfile($file);
|
|
exit();
|
|
|
|
} else { // enter directory
|
|
$path = $this->_options['root'];
|
|
if (!empty($_GET['target'])) {
|
|
if (false == ($p = $this->_findDir(trim($_GET['target'])))) {
|
|
if (!isset($_GET['init'])) {
|
|
$this->_result['error'] = 'Invalid parameters';
|
|
}
|
|
} elseif (!$this->_isAllowed($p, 'read')) {
|
|
if (!isset($_GET['init'])) {
|
|
$this->_result['error'] = 'Access denied';
|
|
}
|
|
} else {
|
|
$path = $p;
|
|
}
|
|
}
|
|
$this->_content($path, isset($_GET['tree']));
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Rename file/folder
|
|
*
|
|
* @return void
|
|
**/
|
|
protected function _rename()
|
|
{
|
|
if (empty($_GET['current'])
|
|
|| empty($_GET['target'])
|
|
|| false == ($dir = $this->_findDir(trim($_GET['current'])))
|
|
|| false == ($target = $this->_find(trim($_GET['target']), $dir))
|
|
) {
|
|
$this->_result['error'] = 'File not found';
|
|
} elseif (false == ($name = $this->_checkName($_GET['name'])) ) {
|
|
$this->_result['error'] = 'Invalid name';
|
|
} elseif (!$this->_isAllowed($dir, 'write')) {
|
|
$this->_result['error'] = 'Access denied';
|
|
} elseif (file_exists($dir.DIRECTORY_SEPARATOR.$name)) {
|
|
$this->_result['error'] = 'File or folder with the same name already exists';
|
|
} elseif (!rename($target, $dir.DIRECTORY_SEPARATOR.$name)) {
|
|
$this->_result['error'] = 'Unable to rename file';
|
|
} else {
|
|
$this->_rmTmb($target);
|
|
$this->_logContext['from'] = $target;
|
|
$this->_logContext['to'] = $dir.DIRECTORY_SEPARATOR.$name;
|
|
$this->_result['select'] = array($this->_hash($dir.DIRECTORY_SEPARATOR.$name));
|
|
$this->_content($dir, is_dir($dir.DIRECTORY_SEPARATOR.$name));
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Create new folder
|
|
*
|
|
* @return void
|
|
**/
|
|
protected function _mkdir()
|
|
{
|
|
if (empty($_GET['current']) || false == ($dir = $this->_findDir(trim($_GET['current'])))) {
|
|
return $this->_result['error'] = 'Invalid parameters';
|
|
}
|
|
$this->_logContext['dir'] = $dir.DIRECTORY_SEPARATOR.$_GET['name'];
|
|
if (!$this->_isAllowed($dir, 'write')) {
|
|
$this->_result['error'] = 'Access denied';
|
|
} elseif (false == ($name = $this->_checkName($_GET['name'])) ) {
|
|
$this->_result['error'] = 'Invalid name';
|
|
} elseif (file_exists($dir.DIRECTORY_SEPARATOR.$name)) {
|
|
$this->_result['error'] = 'File or folder with the same name already exists';
|
|
} elseif (!@mkdir($dir.DIRECTORY_SEPARATOR.$name, $this->_options['dirMode'])) {
|
|
$this->_result['error'] = 'Unable to create folder';
|
|
} else {
|
|
$this->_logContext['dir'] = $dir.DIRECTORY_SEPARATOR.$name;
|
|
$this->_result['select'] = array($this->_hash($dir.DIRECTORY_SEPARATOR.$name));
|
|
$this->_content($dir, true);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create new empty file
|
|
*
|
|
* @return void
|
|
**/
|
|
protected function _mkfile()
|
|
{
|
|
if (empty($_GET['current'])
|
|
|| false == ($dir = $this->_findDir(trim($_GET['current'])))) {
|
|
return $this->_result['error'] = 'Invalid parameters';
|
|
}
|
|
$this->_logContext['file'] = $dir.DIRECTORY_SEPARATOR.$_GET['name'];
|
|
if (!$this->_isAllowed($dir, 'write')) {
|
|
$this->_result['error'] = 'Access denied';
|
|
} elseif (false == ($name = $this->_checkName($_GET['name'])) ) {
|
|
$this->_result['error'] = 'Invalid name';
|
|
} elseif (file_exists($dir.DIRECTORY_SEPARATOR.$name)) {
|
|
$this->_result['error'] = 'File or folder with the same name already exists';
|
|
} else {
|
|
$f = $dir.DIRECTORY_SEPARATOR.$name;
|
|
$this->_logContext['file'] = $f;
|
|
if (false != ($fp = @fopen($f, 'wb'))) {
|
|
fwrite($fp, "");
|
|
fclose($fp);
|
|
$this->_result['select'] = array($this->_hash($dir.DIRECTORY_SEPARATOR.$name));
|
|
$this->_content($dir);
|
|
} else {
|
|
$this->_result['error'] = 'Unable to create file';
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Remove files/folders
|
|
*
|
|
* @return void
|
|
**/
|
|
protected function _rm()
|
|
{
|
|
if (empty($_GET['current'])
|
|
|| false == ($dir = $this->_findDir(trim($_GET['current'])))
|
|
|| (empty($_GET['targets']) || !is_array($_GET['targets']))) {
|
|
return $this->_result['error'] = 'Invalid parameters';
|
|
}
|
|
|
|
$this->_logContext['targets'] = array();
|
|
foreach ($_GET['targets'] as $hash) {
|
|
if (false != ($f = $this->_find($hash, $dir))) {
|
|
$this->_remove($f);
|
|
$this->_logContext['targets'][] = $f;
|
|
}
|
|
}
|
|
if (!empty($this->_result['errorData'])) {
|
|
$this->_result['error'] = 'Unable to remove file';
|
|
}
|
|
$this->_content($dir, true);
|
|
}
|
|
|
|
/**
|
|
* Upload files
|
|
*
|
|
* @return void
|
|
**/
|
|
protected function _upload()
|
|
{
|
|
|
|
if (empty($_POST['current'])
|
|
|| false == ($dir = $this->_findDir(trim($_POST['current'])))) {
|
|
return $this->_result['error'] = 'Invalid parameters';
|
|
}
|
|
if (!$this->_isAllowed($dir, 'write')) {
|
|
return $this->_result['error'] = 'Access denied';
|
|
}
|
|
if (empty($_FILES['upload']))
|
|
{
|
|
return $this->_result['error'] = 'No file to upload';
|
|
}
|
|
|
|
$this->_logContext['upload'] = array();
|
|
$this->_result['select'] = array();
|
|
$total = 0;
|
|
for ($i=0, $s = count($_FILES['upload']['name']); $i < $s; $i++) {
|
|
if (!empty($_FILES['upload']['name'][$i])) {
|
|
$total++;
|
|
$this->_logContext['upload'][] = $_FILES['upload']['name'][$i];
|
|
if ($_FILES['upload']['error'][$i] > 0) {
|
|
$error = 'Unable to upload file';
|
|
switch ($_FILES['upload']['error'][$i]) {
|
|
case UPLOAD_ERR_INI_SIZE:
|
|
case UPLOAD_ERR_FORM_SIZE:
|
|
$error = 'File exceeds the maximum allowed filesize';
|
|
break;
|
|
case UPLOAD_ERR_EXTENSION:
|
|
$error = 'Not allowed file type';
|
|
break;
|
|
}
|
|
$this->_errorData($_FILES['upload']['name'][$i], $error);
|
|
} elseif (false == ($name = $this->_checkName($_FILES['upload']['name'][$i]))) {
|
|
$this->_errorData($_FILES['upload']['name'][$i], 'Invalid name');
|
|
} elseif (!$this->_isUploadAllow($_FILES['upload']['name'][$i], $_FILES['upload']['tmp_name'][$i])) {
|
|
$this->_errorData($_FILES['upload']['name'][$i], 'Not allowed file type');
|
|
} else {
|
|
$name = $this->_checkName($_FILES['upload']['name'][$i]);
|
|
$file = $dir.DIRECTORY_SEPARATOR.$name;
|
|
if (!@move_uploaded_file($_FILES['upload']['tmp_name'][$i], $file)) {
|
|
$this->_errorData($_FILES['upload']['name'][$i], 'Unable to save uploaded file');
|
|
} else {
|
|
@chmod($file, $this->_options['fileMode']);
|
|
$this->_result['select'][] = $this->_hash($file);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
$errCnt = !empty($this->_result['errorData']) ? count($this->_result['errorData']) : 0;
|
|
|
|
if ($errCnt == $total) {
|
|
$this->_result['error'] = 'Unable to upload files';
|
|
} else {
|
|
if ($errCnt>0) {
|
|
$this->_result['error'] = 'Some files was not uploaded';
|
|
}
|
|
$this->_content($dir);
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* Copy/move files/folders
|
|
*
|
|
* @return void
|
|
**/
|
|
protected function _paste()
|
|
{
|
|
if (empty($_GET['current'])
|
|
|| false == ($current = $this->_findDir(trim($_GET['current'])))
|
|
|| empty($_GET['src'])
|
|
|| false == ($src = $this->_findDir(trim($_GET['src'])))
|
|
|| empty($_GET['dst'])
|
|
|| false == ($dst = $this->_findDir(trim($_GET['dst'])))
|
|
|| empty($_GET['targets']) || !is_array($_GET['targets'])
|
|
) {
|
|
return $this->_result['error'] = 'Invalid parameters';
|
|
}
|
|
$cut = !empty($_GET['cut']);
|
|
$this->_logContext['src'] = array();
|
|
$this->_logContext['dest'] = $dst;
|
|
$this->_logContext['cut'] = $cut;
|
|
|
|
|
|
if (!$this->_isAllowed($dst, 'write') || !$this->_isAllowed($src, 'read')) {
|
|
return $this->_result['error'] = 'Access denied';
|
|
}
|
|
|
|
foreach ($_GET['targets'] as $hash) {
|
|
if (false == ($f = $this->_find($hash, $src))) {
|
|
return $this->_result['error'] = 'File not found' && $this->_content($current, true);
|
|
}
|
|
$this->_logContext['src'][] = $f;
|
|
$_dst = $dst.DIRECTORY_SEPARATOR.basename($f);
|
|
|
|
if (0 === strpos($dst, $f)) {
|
|
return $this->_result['error'] = 'Unable to copy into itself' && $this->_content($current, true);
|
|
} elseif (file_exists($_dst)) {
|
|
return $this->_result['error'] = 'File or folder with the same name already exists' && $this->_content($current, true);
|
|
} elseif ($cut && !$this->_isAllowed($f, 'rm')) {
|
|
return $this->_result['error'] = 'Access denied' && $this->_content($current, true);
|
|
}
|
|
|
|
if ($cut) {
|
|
if (!@rename($f, $_dst)) {
|
|
return $this->_result['error'] = 'Unable to move files' && $this->_content($current, true);
|
|
} elseif (!is_dir($f)) {
|
|
$this->_rmTmb($f);
|
|
}
|
|
} elseif (!$this->_copy($f, $_dst)) {
|
|
return $this->_result['error'] = 'Unable to copy files' && $this->_content($current, true);
|
|
}
|
|
}
|
|
$this->_content($current, true);
|
|
}
|
|
|
|
/**
|
|
* Create file/folder copy with suffix - "copy"
|
|
*
|
|
* @return void
|
|
**/
|
|
protected function _duplicate()
|
|
{
|
|
if (empty($_GET['current'])
|
|
|| false == ($current = $this->_findDir(trim($_GET['current'])))
|
|
|| empty($_GET['target'])
|
|
|| false == ($target = $this->_find(trim($_GET['target']), $current))
|
|
) {
|
|
return $this->_result['error'] = 'Invalid parameters';
|
|
}
|
|
$this->_logContext['target'] = $target;
|
|
if (!$this->_isAllowed($current, 'write') || !$this->_isAllowed($target, 'read')) {
|
|
return $this->_result['error'] = 'Access denied';
|
|
}
|
|
$dup = $this->_uniqueName($target);
|
|
if (!$this->_copy($target, $dup)) {
|
|
return $this->_result['error'] = 'Unable to create file copy';
|
|
}
|
|
$this->_result['select'] = array($this->_hash($dup));
|
|
$this->_content($current, is_dir($target));
|
|
}
|
|
|
|
/**
|
|
* Resize image
|
|
*
|
|
* @return void
|
|
**/
|
|
protected function _resize()
|
|
{
|
|
if (empty($_GET['current'])
|
|
|| false == ($current = $this->_findDir(trim($_GET['current'])))
|
|
|| empty($_GET['target'])
|
|
|| false == ($target = $this->_find(trim($_GET['target']), $current))
|
|
|| empty($_GET['width']) || 0 >= ($width = intval($_GET['width']))
|
|
|| empty($_GET['height']) || 0 >= ($height = intval($_GET['height']))
|
|
) {
|
|
return $this->_result['error'] = 'Invalid parameters';
|
|
}
|
|
$this->_logContext = array(
|
|
'target' => $target,
|
|
'width' => $width,
|
|
'height' => $height
|
|
);
|
|
if (!$this->_isAllowed($target, 'write')) {
|
|
return $this->_result['error'] = 'Access denied';
|
|
}
|
|
if (0 !== strpos($this->_mimetype($target), 'image')) {
|
|
return $this->_result['error'] = 'File is not an image';
|
|
}
|
|
if (!$this->_resizeImg($target, $width, $height)) {
|
|
return $this->_result['error'] = 'Unable to resize image';
|
|
}
|
|
$this->_result['select'] = array($this->_hash($target));
|
|
$this->_content($current);
|
|
}
|
|
|
|
/**
|
|
* Create images thumbnails
|
|
*
|
|
* @return void
|
|
**/
|
|
protected function _thumbnails()
|
|
{
|
|
if (!empty($this->_options['tmbDir']) && !empty($_GET['current']) && false != ($current = $this->_findDir(trim($_GET['current'])))) {
|
|
$this->_result['current'] = $this->_hash($current);
|
|
$this->_result['images'] = array();
|
|
$ls = scandir($current);
|
|
$cnt = 0;
|
|
$max = $this->_options['tmbAtOnce'] > 0 ? intval($this->_options['tmbAtOnce']) : 5;
|
|
for ($i=0; $i < count($ls); $i++) {
|
|
if ($this->_isAccepted($ls[$i])) {
|
|
$path = $current.DIRECTORY_SEPARATOR.$ls[$i];
|
|
if (is_readable($path) && $this->_canCreateTmb($this->_mimetype($path))) {
|
|
$tmb = $this->_tmbPath($path);
|
|
if (!file_exists($tmb)) {
|
|
if ($cnt>=$max) {
|
|
return $this->_result['tmb'] = true;
|
|
} elseif ($this->_tmb($path, $tmb)) {
|
|
$this->_result['images'][$this->_hash($path)] = $this->_path2url($tmb);
|
|
$cnt++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Return file content to client
|
|
*
|
|
* @return void
|
|
**/
|
|
protected function _fread()
|
|
{
|
|
if (empty($_GET['current'])
|
|
|| false == ($current = $this->_findDir(trim($_GET['current'])))
|
|
|| empty($_GET['target'])
|
|
|| false == ($target = $this->_find(trim($_GET['target']), $current))
|
|
) {
|
|
return $this->_result['error'] = 'Invalid parameters';
|
|
}
|
|
if (!$this->_isAllowed($target, 'read')) {
|
|
return $this->_result['error'] = 'Access denied';
|
|
}
|
|
$this->_result['content'] = @file_get_contents($target);
|
|
}
|
|
|
|
/**
|
|
* Save data into text file.
|
|
*
|
|
* @return void
|
|
**/
|
|
protected function _edit()
|
|
{
|
|
if (empty($_POST['current'])
|
|
|| false == ($current = $this->_findDir(trim($_POST['current'])))
|
|
|| empty($_POST['target'])
|
|
|| false == ($target = $this->_find(trim($_POST['target']), $current))
|
|
|| !isset($_POST['content'])
|
|
) {
|
|
return $this->_result['error'] = 'Invalid parameters';
|
|
}
|
|
$this->_logContext['target'] = $target;
|
|
if (!$this->_isAllowed($target, 'write')) {
|
|
return $this->_result['error'] = 'Access denied';
|
|
}
|
|
if (false === file_put_contents($target, trim($_POST['content']))) {
|
|
return $this->_result['error'] = 'Unable to write to file';
|
|
}
|
|
$this->_result['target'] = $this->_info($target);
|
|
// $this->_result['select'] = array($this->_hash($target));
|
|
}
|
|
|
|
/**
|
|
* Create archive of selected type
|
|
*
|
|
* @return void
|
|
**/
|
|
protected function _archive()
|
|
{
|
|
$this->_checkArchivers();
|
|
if (empty($this->_options['archivers']['create'])
|
|
|| empty($_GET['type'])
|
|
|| empty($this->_options['archivers']['create'][$_GET['type']])
|
|
|| !in_array($_GET['type'], $this->_options['archiveMimes'])) {
|
|
return $this->_result['error'] = 'Invalid parameters';
|
|
}
|
|
|
|
if (empty($_GET['current'])
|
|
|| empty($_GET['targets'])
|
|
|| !is_array($_GET['targets'])
|
|
|| false == ($dir = $this->_findDir(trim($_GET['current'])))
|
|
|| !$this->_isAllowed($dir, 'write')
|
|
) {
|
|
return $this->_result['error'] = 'Invalid parameters';
|
|
}
|
|
|
|
$files = array();
|
|
$argc = '';
|
|
foreach ($_GET['targets'] as $hash) {
|
|
if (false == ($f = $this->_find($hash, $dir))) {
|
|
return $this->_result['error'] = 'File not found';
|
|
}
|
|
$files[] = $f;
|
|
$argc .= escapeshellarg(basename($f)).' ';
|
|
}
|
|
$arc = $this->_options['archivers']['create'][$_GET['type']];
|
|
$name = count($files) == 1 ? basename($files[0]) : $_GET['name'];
|
|
$name = basename($this->_uniqueName($name.'.'.$arc['ext'], ''));
|
|
|
|
$cwd = getcwd();
|
|
chdir($dir);
|
|
$cmd = $arc['cmd'].' '.$arc['argc'].' '.escapeshellarg($name).' '.$argc;
|
|
exec($cmd, $o, $c);
|
|
chdir($cwd);
|
|
if (file_exists($dir.DIRECTORY_SEPARATOR.$name)) {
|
|
$this->_content($dir);
|
|
$this->_result['select'] = array($this->_hash($dir.DIRECTORY_SEPARATOR.$name));
|
|
} else {
|
|
$this->_result['error'] = 'Unable to create archive';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Extract files from archive
|
|
*
|
|
* @return void
|
|
**/
|
|
protected function _extract()
|
|
{
|
|
if (empty($_GET['current'])
|
|
|| false == ($current = $this->_findDir(trim($_GET['current'])))
|
|
|| empty($_GET['target'])
|
|
|| false == ($file = $this->_find(trim($_GET['target']), $current))
|
|
|| !$this->_isAllowed($current, 'write')
|
|
) {
|
|
return $this->_result['error'] = 'Invalid parameters';
|
|
}
|
|
$this->_checkArchivers();
|
|
$mime = $this->_mimetype($file);
|
|
if (empty($this->_options['archivers']['extract'][$mime])) {
|
|
return $this->_result['error'] = 'Invalid parameters';
|
|
}
|
|
$cwd = getcwd();
|
|
$arc = $this->_options['archivers']['extract'][$mime];
|
|
$cmd = $arc['cmd'].' '.$arc['argc'].' '.escapeshellarg(basename($file));
|
|
chdir(dirname($file));
|
|
exec($cmd, $o, $c);
|
|
chdir($cwd);
|
|
if ($c == 0) {
|
|
$this->_content($current, true);
|
|
} else {
|
|
$this->_result['error'] = 'Unable to extract files from archive';
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Send header Connection: close. Required by safari to fix bug http://www.webmasterworld.com/macintosh_webmaster/3300569.htm
|
|
*
|
|
* @return void
|
|
**/
|
|
protected function _ping()
|
|
{
|
|
exit(header("Connection: close"));
|
|
}
|
|
/************************************************************/
|
|
/** "content" methods **/
|
|
/************************************************************/
|
|
/**
|
|
* Set current dir info, content and [dirs tree]
|
|
*
|
|
* @param string $path current dir path
|
|
* @param bool $tree set dirs tree?
|
|
* @return void
|
|
**/
|
|
protected function _content($path, $tree=false)
|
|
{
|
|
$this->_cwd($path);
|
|
$this->_cdc($path);
|
|
if ($tree) {
|
|
$this->_result['tree'] = $this->_tree($this->_options['root']);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set current dir info
|
|
*
|
|
* @param string $path current dir path
|
|
* @return void
|
|
**/
|
|
protected function _cwd($path)
|
|
{
|
|
$rel = $this->_options['rootAlias'] ? $this->_options['rootAlias'] : basename($this->_options['root']);
|
|
if ($path == $this->_options['root']) {
|
|
$name = $rel;
|
|
} else {
|
|
$name = basename($path);
|
|
$rel .= DIRECTORY_SEPARATOR.substr($path, strlen($this->_options['root'])+1);
|
|
}
|
|
$this->_result['cwd'] = array(
|
|
'hash' => $this->_hash($path),
|
|
'name' => $name,
|
|
'mime' => 'directory',
|
|
'rel' => $rel,
|
|
'size' => 0,
|
|
'date' => date($this->_options['dateFormat'], filemtime($path)),
|
|
'read' => true,
|
|
'write' => $this->_isAllowed($path, 'write'),
|
|
'rm' => $path == $this->_options['root'] ? false : $this->_isAllowed($path, 'rm')
|
|
);
|
|
}
|
|
|
|
|
|
/**
|
|
* Set current dir content
|
|
*
|
|
* @param string $path current dir path
|
|
* @return void
|
|
**/
|
|
protected function _cdc($path)
|
|
{
|
|
$dirs = $files = array();
|
|
$ls = scandir($path);
|
|
for ($i=0; $i < count($ls); $i++) {
|
|
if ($this->_isAccepted($ls[$i])) {
|
|
$info = $this->_info($path.DIRECTORY_SEPARATOR.$ls[$i]);
|
|
if ($info['mime'] == 'directory') {
|
|
$dirs[] = $info;
|
|
} else {
|
|
$files[] = $info;
|
|
}
|
|
}
|
|
}
|
|
$this->_result['cdc'] = array_merge($dirs, $files);
|
|
}
|
|
|
|
/**
|
|
* Return file/folder info
|
|
*
|
|
* @param string $path file path
|
|
* @return array
|
|
**/
|
|
protected function _info($path)
|
|
{
|
|
$type = filetype($path);
|
|
$stat = $type == 'link' ? lstat($path) : stat($path);
|
|
|
|
if ($stat['mtime'] > $this->_today) {
|
|
$d = 'Today '.date('H:i', $stat['mtime']);
|
|
} elseif ($stat['mtime'] > $this->_yesterday) {
|
|
$d = 'Yesterday '.date('H:i', $stat['mtime']);
|
|
} else {
|
|
$d = date($this->_options['dateFormat'], $stat['mtime']);
|
|
}
|
|
|
|
$info = array(
|
|
'name' => htmlspecialchars(basename($path)),
|
|
'hash' => $this->_hash($path),
|
|
'mime' => $type == 'dir' ? 'directory' : $this->_mimetype($path),
|
|
'date' => $d,
|
|
'size' => $type == 'dir' ? $this->_dirSize($path) : $stat['size'],
|
|
'read' => $this->_isAllowed($path, 'read'),
|
|
'write' => $this->_isAllowed($path, 'write'),
|
|
'rm' => $this->_isAllowed($path, 'rm'),
|
|
);
|
|
|
|
if ($type == 'link') {
|
|
if (false == ($lpath = $this->_readlink($path))) {
|
|
$info['mime'] = 'symlink-broken';
|
|
return $info;
|
|
}
|
|
if (is_dir($lpath)) {
|
|
$info['mime'] = 'directory';
|
|
} else {
|
|
$info['parent'] = $this->_hash(dirname($lpath));
|
|
$info['mime'] = $this->_mimetype($lpath);
|
|
}
|
|
$info['link'] = $this->_hash($lpath);
|
|
$info['linkTo'] = ($this->_options['rootAlias'] ? $this->_options['rootAlias'] : basename($this->_options['root'])).substr($lpath, strlen($this->_options['root']));
|
|
$info['read'] = $this->_isAllowed($lpath, 'read');
|
|
$info['write'] = $this->_isAllowed($lpath, 'write');
|
|
$info['rm'] = $this->_isAllowed($lpath, 'rm');
|
|
} else {
|
|
$lpath = '';
|
|
}
|
|
|
|
if ($info['mime'] != 'directory') {
|
|
if ($this->_options['fileURL'] && $info['read']) {
|
|
$info['url'] = $this->_path2url($lpath ? $lpath : $path);
|
|
}
|
|
|
|
if (0 === ($p = strpos($info['mime'], 'image'))) {
|
|
if (false != ($s = getimagesize($path))) {
|
|
$info['dim'] = $s[0].'x'.$s[1];
|
|
}
|
|
if ($info['read']) {
|
|
$info['resize'] = isset($info['dim']) && $this->_canCreateTmb($info['mime']);
|
|
$tmb = $this->_tmbPath($path);
|
|
|
|
if (file_exists($tmb)) {
|
|
$info['tmb'] = $this->_path2url($tmb);
|
|
} elseif ($info['resize']) {
|
|
$this->_result['tmb'] = true;
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
return $info;
|
|
}
|
|
|
|
/**
|
|
* Return directory tree (multidimensional array)
|
|
*
|
|
* @param string $path directory path
|
|
* @return array
|
|
**/
|
|
protected function _tree($path)
|
|
{
|
|
$dir = array(
|
|
'hash' => $this->_hash($path),
|
|
'name' => $path == $this->_options['root'] && $this->_options['rootAlias'] ? $this->_options['rootAlias'] : basename($path),
|
|
'read' => $this->_isAllowed($path, 'read'),
|
|
'write' => $this->_isAllowed($path, 'write'),
|
|
'dirs' => array()
|
|
);
|
|
|
|
if ($dir['read'] && (false != ($ls = scandir($path)))) {
|
|
for ($i=0; $i < count($ls); $i++) {
|
|
$p = $path.DIRECTORY_SEPARATOR.$ls[$i];
|
|
if ($this->_isAccepted($ls[$i]) && is_dir($p) && !is_link($p)) {
|
|
$dir['dirs'][] = $this->_tree($p);
|
|
}
|
|
}
|
|
}
|
|
return $dir;
|
|
}
|
|
|
|
/************************************************************/
|
|
/** fs methods **/
|
|
/************************************************************/
|
|
|
|
/**
|
|
* Return name for duplicated file/folder or new archive
|
|
*
|
|
* @param string $f file/folder name
|
|
* @param string $suffix file name suffix
|
|
* @return string
|
|
**/
|
|
protected function _uniqueName($f, $suffix=' copy')
|
|
{
|
|
$dir = dirname($f);
|
|
$name = basename($f);
|
|
$ext = '';
|
|
|
|
if (!is_dir($f)) {
|
|
if (preg_match('/\.(tar\.gz|tar\.bz|tar\.bz2|[a-z0-9]{1,4})$/i', $name, $m)) {
|
|
$ext = '.'.$m[1];
|
|
$name = substr($name, 0, strlen($name)-strlen($m[0]));
|
|
}
|
|
}
|
|
|
|
if (preg_match('/('.$suffix.')(\d*)$/i', $name, $m)) {
|
|
$i = (int)$m[2];
|
|
$name = substr($name, 0, strlen($name)-strlen($m[2]));
|
|
} else {
|
|
$name .= $suffix;
|
|
$i = 0;
|
|
$n = $dir.DIRECTORY_SEPARATOR.$name.$ext;
|
|
if (!file_exists($n)) {
|
|
return $n;
|
|
}
|
|
}
|
|
|
|
while ($i++ <= 10000) {
|
|
$n = $dir.DIRECTORY_SEPARATOR.$name.$i.$ext;
|
|
if (!file_exists($n)) {
|
|
return $n;
|
|
}
|
|
}
|
|
return $dir.DIRECTORY_SEPARATOR.$name.md5($f).$ext;
|
|
}
|
|
|
|
/**
|
|
* Remove file or folder (recursively)
|
|
*
|
|
* @param string $path fole/folder path
|
|
* @return void
|
|
**/
|
|
protected function _remove($path)
|
|
{
|
|
if (!$this->_isAllowed($path, 'rm')) {
|
|
return $this->_errorData($path, 'Access denied');
|
|
}
|
|
if (!is_dir($path)) {
|
|
if (!@unlink($path)) {
|
|
$this->_errorData($path, 'Unable to remove file');
|
|
} else {
|
|
$this->_rmTmb($path);
|
|
}
|
|
} else {
|
|
$ls = scandir($path);
|
|
for ($i=0; $i < count($ls); $i++) {
|
|
if ('.' != $ls[$i] && '..' != $ls[$i]) {
|
|
$this->_remove($path.DIRECTORY_SEPARATOR.$ls[$i]);
|
|
}
|
|
}
|
|
if (!@rmdir($path)) {
|
|
return $this->_errorData($path, 'Unable to remove file');
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Copy file/folder (recursively)
|
|
*
|
|
* @param string $src file/folder to copy
|
|
* @param string $trg destination name
|
|
* @return bool
|
|
**/
|
|
protected function _copy($src, $trg)
|
|
{
|
|
if (!$this->_isAllowed($src, 'read')) {
|
|
return $this->_errorData($src, 'Access denied');
|
|
}
|
|
|
|
$dir = dirname($trg);
|
|
|
|
if (!$this->_isAllowed($dir, 'write')) {
|
|
return $this->_errorData($dir, 'Access denied');
|
|
}
|
|
if (file_exists($trg)) {
|
|
return $this->_errorData($src, 'File or folder with the same name already exists');
|
|
}
|
|
|
|
if (!is_dir($src)) {
|
|
if (!@copy($src, $trg)) {
|
|
return $this->_errorData($src, 'Unable to copy files');
|
|
}
|
|
@chmod($trg, $this->_options['fileMode']);
|
|
} else {
|
|
|
|
if (!@mkdir($trg, $this->_options['dirMode'])) {
|
|
return $this->_errorData($src, 'Unable to copy files');
|
|
}
|
|
|
|
$ls = scandir($src);
|
|
for ($i=0; $i < count($ls); $i++) {
|
|
if ('.' != $ls[$i] && '..' != $ls[$i]) {
|
|
$_src = $src.DIRECTORY_SEPARATOR.$ls[$i];
|
|
$_trg = $trg.DIRECTORY_SEPARATOR.$ls[$i];
|
|
if (is_dir($_src)) {
|
|
if (!$this->_copy($_src, $_trg)) {
|
|
return $this->_errorData($_src, 'Unable to copy files');
|
|
}
|
|
} else {
|
|
if (!@copy($_src, $_trg)) {
|
|
return $this->_errorData($_src, 'Unable to copy files');
|
|
}
|
|
@chmod($_trg, $this->_options['fileMode']);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Check new file name for invalid simbols. Return name if valid
|
|
*
|
|
* @return string $n file name
|
|
* @return string
|
|
**/
|
|
protected function _checkName($n)
|
|
{
|
|
$n = strip_tags(trim($n));
|
|
if (!$this->_options['dotFiles'] && '.' == substr($n, 0, 1)) {
|
|
return false;
|
|
}
|
|
return preg_match('|^[^\\/\<\>:]+$|', $n) ? $n : false;
|
|
}
|
|
|
|
/**
|
|
* Find folder by hash in required folder and subfolders
|
|
*
|
|
* @param string $hash folder hash
|
|
* @param string $path folder path to search in
|
|
* @return string
|
|
**/
|
|
protected function _findDir($hash, $path='')
|
|
{
|
|
if (!$path) {
|
|
$path = $this->_options['root'];
|
|
if ($this->_hash($path) == $hash) {
|
|
return $path;
|
|
}
|
|
}
|
|
|
|
if (false != ($ls = scandir($path))) {
|
|
for ($i=0; $i < count($ls); $i++) {
|
|
$p = $path.DIRECTORY_SEPARATOR.$ls[$i];
|
|
if (is_link($p))
|
|
{
|
|
$link = $this->_readlink($p);
|
|
//$this->_result['debug']['findDir_'.$p] = 'link to '.$link;
|
|
}
|
|
if ($this->_isAccepted($ls[$i]) && is_dir($p) && (!is_link($p))) {
|
|
if ($this->_hash($p) == $hash || false != ($p = $this->_findDir($hash, $p))) {
|
|
return $p;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Find file/folder by hash in required folder
|
|
*
|
|
* @param string $hash file/folder hash
|
|
* @param string $path folder path to search in
|
|
**/
|
|
protected function _find($hash, $path)
|
|
{
|
|
if (false != ($ls = scandir($path))) {
|
|
for ($i=0; $i < count($ls); $i++) {
|
|
if ($this->_isAccepted($ls[$i])) {
|
|
$p = $path.DIRECTORY_SEPARATOR.$ls[$i];
|
|
if ($this->_hash($p) == $hash) {
|
|
return $p;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Return path of file on which link point to, if exists in root directory
|
|
*
|
|
* @param string $path symlink path
|
|
* @return string
|
|
**/
|
|
protected function _readlink($path)
|
|
{
|
|
$target = readlink($path);
|
|
if ('/' != substr($target, 0, 1)) {
|
|
$target = dirname($path).DIRECTORY_SEPARATOR.$target;
|
|
}
|
|
$target = $this->_normpath($target);
|
|
$root = $this->_normpath($this->_options['root']);
|
|
return $target && file_exists($target) && 0 === strpos($target, $root) ? $target : false;
|
|
}
|
|
|
|
/**
|
|
* Count total directory size if this allowed in options
|
|
*
|
|
* @param string $path directory path
|
|
* @return int
|
|
**/
|
|
protected function _dirSize($path)
|
|
{
|
|
$size = 0;
|
|
if (!$this->_options['dirSize'] || !$this->_isAllowed($path, 'read')) {
|
|
return filesize($path);
|
|
}
|
|
if (!isset($this->_options['du'])) {
|
|
$this->_options['du'] = function_exists('exec')
|
|
? exec('du -h '.escapeshellarg(__FILE__), $o, $s) > 0 && $s == 0
|
|
: false;
|
|
}
|
|
if ($this->_options['du']) {
|
|
$size = intval(exec('du -k '.escapeshellarg($path)))*1024;
|
|
} else {
|
|
$ls = scandir($path);
|
|
for ($i=0; $i < count($ls); $i++) {
|
|
if ($this->_isAccepted($ls[$i])) {
|
|
$p = $path.DIRECTORY_SEPARATOR.$ls[$i];
|
|
$size += filetype($p) == 'dir' && $this->_isAllowed($p, 'read') ? $this->_dirSize($p) : filesize($p);
|
|
}
|
|
}
|
|
}
|
|
return $size;
|
|
}
|
|
|
|
/**
|
|
* Return file mimetype
|
|
*
|
|
* @param string $path file path
|
|
* @return string
|
|
**/
|
|
protected function _mimetype($path)
|
|
{
|
|
if (empty($this->_options['mimeDetect']) || $this->_options['mimeDetect'] == 'auto') {
|
|
$this->_options['mimeDetect'] = $this->_getMimeDetect();
|
|
}
|
|
|
|
switch ($this->_options['mimeDetect']) {
|
|
case 'finfo':
|
|
if (empty($this->_finfo)) {
|
|
$this->_finfo = finfo_open(FILEINFO_MIME);
|
|
}
|
|
$type = @finfo_file($this->_finfo, $path);
|
|
break;
|
|
case 'php':
|
|
$type = mime_content_type($path);
|
|
break;
|
|
case 'linux':
|
|
$type = exec('file -ib '.escapeshellarg($path));
|
|
break;
|
|
case 'bsd':
|
|
$type = exec('file -Ib '.escapeshellarg($path));
|
|
break;
|
|
default:
|
|
$pinfo = pathinfo($path);
|
|
$ext = isset($pinfo['extension']) ? strtolower($pinfo['extension']) : '';
|
|
$type = isset($this->_mimeTypes[$ext]) ? $this->_mimeTypes[$ext] : 'unknown;';
|
|
}
|
|
$type = explode(';', $type);
|
|
|
|
if ($this->_options['mimeDetect'] != 'internal' && $type[0] == 'application/octet-stream') {
|
|
$pinfo = pathinfo($path);
|
|
$ext = isset($pinfo['extension']) ? strtolower($pinfo['extension']) : '';
|
|
if (!empty($ext) && !empty($this->_mimeTypes[$ext])) {
|
|
$type[0] = $this->_mimeTypes[$ext];
|
|
}
|
|
}
|
|
|
|
return $type[0];
|
|
}
|
|
|
|
/************************************************************/
|
|
/** image manipulation **/
|
|
/************************************************************/
|
|
|
|
/**
|
|
* Create image thumbnail
|
|
*
|
|
* @param string $img image file
|
|
* @param string $tmb thumbnail name
|
|
* @return bool
|
|
**/
|
|
protected function _tmb($img, $tmb)
|
|
{
|
|
if (false == ($s = getimagesize($img))) {
|
|
return false;
|
|
}
|
|
$tmbSize = $this->_options['tmbSize'];
|
|
|
|
if ($this->_options['tmbCrop'] == false) {
|
|
|
|
/* Calculating image scale width and height */
|
|
$xscale = $s[0] / $tmbSize;
|
|
$yscale = $s[1] / $tmbSize;
|
|
|
|
if ($yscale > $xscale) {
|
|
$newwidth = round($s[0] * (1 / $yscale));
|
|
$newheight = round($s[1] * (1 / $yscale));
|
|
} else {
|
|
$newwidth = round($s[0] * (1 / $xscale));
|
|
$newheight = round($s[1] * (1 / $xscale));
|
|
}
|
|
|
|
/* Keeping original dimensions if image fitting into thumbnail without scale */
|
|
if ($s[0] <= $tmbSize && $s[1] <= $tmbSize) {
|
|
$newwidth = $s[0];
|
|
$newheight = $s[1];
|
|
}
|
|
|
|
/* Calculating coordinates for aligning thumbnail */
|
|
$align_y = ceil(($tmbSize - $newheight) / 2);
|
|
$align_x = ceil(($tmbSize - $newwidth) / 2);
|
|
}
|
|
|
|
|
|
|
|
switch ($this->_options['imgLib']) {
|
|
case 'imagick':
|
|
try {
|
|
$_img = new imagick($img);
|
|
} catch (Exception $e) {
|
|
return false;
|
|
}
|
|
|
|
$_img->contrastImage(1);
|
|
|
|
if ($this->_options['tmbCrop'] == false) {
|
|
$img1 = new Imagick();
|
|
$img1->newImage($tmbSize, $tmbSize, new ImagickPixel($this->_options['tmbBgColor']));
|
|
$img1->setImageFormat('png');
|
|
$_img->resizeImage($newwidth, $newheight, NULL, true);
|
|
$img1->compositeImage( $_img, imagick::COMPOSITE_OVER, $align_x, $align_y );
|
|
return $img1->writeImage($tmb);
|
|
} else {
|
|
return $_img->cropThumbnailImage($tmbSize, $tmbSize) && $_img->writeImage($tmb);
|
|
}
|
|
break;
|
|
|
|
case 'mogrify':
|
|
if (@copy($img, $tmb)) {
|
|
list($x, $y, $size) = $this->_cropPos($s[0], $s[1]);
|
|
// exec('mogrify -crop '.$size.'x'.$size.'+'.$x.'+'.$y.' -scale '.$tmbSize.'x'.$tmbSize.'! '.escapeshellarg($tmb), $o, $c);
|
|
|
|
$mogrifyArgs = 'mogrify -resize ' . $tmbSize . 'x' . $tmbSize;
|
|
|
|
if ($this->_options['tmbCrop'] == false) {
|
|
$mogrifyArgs .= ' -gravity center -background "' . $this->_options['tmbBgColor'] . '" -extent ' . $tmbSize . 'x' . $tmbSize;
|
|
}
|
|
|
|
if ($this->_options['tmbCrop'] == false) {
|
|
$mogrifyArgs .= ' ' . escapeshellarg($tmb);
|
|
}
|
|
|
|
exec($mogrifyArgs, $o, $c);
|
|
|
|
if (file_exists($tmb)) {
|
|
return true;
|
|
} elseif ($c == 0) {
|
|
// find tmb for psd and animated gif
|
|
$mime = $this->_mimetype($img);
|
|
if ($mime == 'image/vnd.adobe.photoshop' || $mime = 'image/gif') {
|
|
$pinfo = pathinfo($tmb);
|
|
$test = $pinfo['dirname'].DIRECTORY_SEPARATOR.$pinfo['filename'].'-0.'.$pinfo['extension'];
|
|
if (file_exists($test)) {
|
|
return rename($test, $tmb);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 'gd':
|
|
if ($s['mime'] == 'image/jpeg') {
|
|
$_img = imagecreatefromjpeg($img);
|
|
} elseif ($s['mime'] == 'image/png') {
|
|
$_img = imagecreatefrompng($img);
|
|
} elseif ($s['mime'] == 'image/gif') {
|
|
$_img = imagecreatefromgif($img);
|
|
}
|
|
if (!$_img || false == ($_tmb = imagecreatetruecolor($tmbSize, $tmbSize))) {
|
|
return false;
|
|
}
|
|
|
|
if ($this->_options['tmbCrop'] == false) {
|
|
|
|
list($r,$g,$b) = sscanf($this->_options['tmbBgColor'], "#%02x%02x%02x");
|
|
|
|
imagefill($_tmb, 0, 0, imagecolorallocate($_tmb, $r, $g, $b));
|
|
|
|
if (!imagecopyresampled($_tmb, $_img, $align_x, $align_y, 0, 0, $newwidth, $newheight, $s[0], $s[1])) {
|
|
return false;
|
|
}
|
|
|
|
} else {
|
|
list($x, $y, $size) = $this->_cropPos($s[0], $s[1]);
|
|
if (!imagecopyresampled($_tmb, $_img, 0, 0, $x, $y, $tmbSize, $tmbSize, $size, $size)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
$r = imagepng($_tmb, $tmb, 7);
|
|
imagedestroy($_img);
|
|
imagedestroy($_tmb);
|
|
return $r;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Remove image thumbnail
|
|
*
|
|
* @param string $img image file
|
|
* @return void
|
|
**/
|
|
protected function _rmTmb($img)
|
|
{
|
|
if ($this->_options['tmbDir'] && false != ($tmb = $this->_tmbPath($img)) && file_exists($tmb)) {
|
|
@unlink($tmb);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Return x/y coord for crop image thumbnail
|
|
*
|
|
* @param int $w image width
|
|
* @param int $h image height
|
|
* @return array
|
|
**/
|
|
protected function _cropPos($w, $h)
|
|
{
|
|
$x = $y = 0;
|
|
$size = min($w, $h);
|
|
if ($w > $h) {
|
|
$x = ceil(($w - $h)/2);
|
|
} else {
|
|
$y = ceil(($h - $w)/2);
|
|
}
|
|
return array($x, $y, $size);
|
|
}
|
|
|
|
/**
|
|
* Resize image
|
|
*
|
|
* @param string $img image path
|
|
* @param int $w image width
|
|
* @param int $h image height
|
|
* @return bool
|
|
**/
|
|
protected function _resizeImg($img, $w, $h)
|
|
{
|
|
if (false == ($s = getimagesize($img))) {
|
|
return false;
|
|
}
|
|
|
|
switch ($this->_options['imgLib']) {
|
|
case 'imagick':
|
|
if (false != ($_img = new imagick($img))) {
|
|
return $_img->cropThumbnailImage($w, $h) && $_img->writeImage($img);
|
|
}
|
|
break;
|
|
case 'mogrify':
|
|
exec('mogrify -scale '.$w.'x'.$h.'! '.escapeshellarg($img), $o, $c);
|
|
return 0 == $c;
|
|
break;
|
|
case 'gd':
|
|
if ($s['mime'] == 'image/jpeg') {
|
|
$_img = imagecreatefromjpeg($img);
|
|
} elseif ($s['mime'] = 'image/png') {
|
|
$_img = imagecreatefrompng($img);
|
|
} elseif ($s['mime'] = 'image/gif') {
|
|
$_img = imagecreatefromgif($img);
|
|
}
|
|
if (!$_img || false == ($_out = imagecreatetruecolor($w, $h))) {
|
|
return false;
|
|
}
|
|
if (!imagecopyresampled($_out, $_img, 0, 0, 0, 0, $w, $h, $s[0], $s[1])) {
|
|
return false;
|
|
}
|
|
if ($s['mime'] == 'image/jpeg') {
|
|
$r = imagejpeg($_out, $img, 100);
|
|
} else if ($s['mime'] = 'image/png') {
|
|
$r = imagepng($_out, $img, 7);
|
|
} else {
|
|
$r = imagegif($_out, $img, 7);
|
|
}
|
|
imagedestroy($_img);
|
|
imagedestroy($_out);
|
|
return $r;
|
|
break;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
/**
|
|
* Return true if we can create thumbnail for file with this mimetype
|
|
*
|
|
* @param string $mime file mimetype
|
|
* @return bool
|
|
**/
|
|
protected function _canCreateTmb($mime)
|
|
{
|
|
if ($this->_options['tmbDir'] && $this->_options['imgLib'] && 0 === strpos($mime, 'image')) {
|
|
if ('gd' == $this->_options['imgLib']) {
|
|
return $mime == 'image/jpeg' || $mime == 'image/png' || $mime == 'image/gif';
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Return image thumbnail path. For thumbnail return itself
|
|
*
|
|
* @param string $path image path
|
|
* @return string
|
|
**/
|
|
protected function _tmbPath($path)
|
|
{
|
|
$tmb = '';
|
|
if ($this->_options['tmbDir']) {
|
|
$tmb = dirname($path) != $this->_options['tmbDir']
|
|
? $this->_options['tmbDir'].DIRECTORY_SEPARATOR.$this->_hash($path).'.png'
|
|
: $path;
|
|
}
|
|
return $tmb;
|
|
}
|
|
|
|
/************************************************************/
|
|
/** access control **/
|
|
/************************************************************/
|
|
|
|
/**
|
|
* Return true if file's mimetype is allowed for upload
|
|
*
|
|
* @param string $name file name
|
|
* @param string $tmpName uploaded file tmp name
|
|
* @return bool
|
|
**/
|
|
protected function _isUploadAllow($name, $tmpName)
|
|
{
|
|
$allow = false;
|
|
$deny = false;
|
|
$mime = $this->_mimetype($this->_options['mimeDetect'] != 'internal' ? $tmpName : $name);
|
|
|
|
if (in_array('all', $this->_options['uploadAllow'])) {
|
|
$allow = true;
|
|
} else {
|
|
foreach ($this->_options['uploadAllow'] as $type) {
|
|
if (0 === strpos($mime, $type)) {
|
|
$allow = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (in_array('all', $this->_options['uploadDeny'])) {
|
|
$deny = true;
|
|
} else {
|
|
foreach ($this->_options['uploadDeny'] as $type) {
|
|
if (0 === strpos($mime, $type)) {
|
|
$deny = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
$this->_result['debug']['_isUploadAllow'][$name] = $mime;
|
|
|
|
if (0 === strpos($this->_options['uploadOrder'], 'allow')) { // ,deny
|
|
if ($deny == true) {
|
|
return false;
|
|
} elseif ($allow == true) {
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
} else { // deny,allow
|
|
if ($allow == true) {
|
|
return true;
|
|
} elseif ($deny == true) {
|
|
return false;
|
|
} else {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Return true if file name is not . or ..
|
|
* If file name begins with . return value according to $this->_options['dotFiles']
|
|
*
|
|
* @param string $file file name
|
|
* @return bool
|
|
**/
|
|
protected function _isAccepted($file)
|
|
{
|
|
if ('.' == $file || '..' == $file) {
|
|
return false;
|
|
}
|
|
if (!$this->_options['dotFiles'] && '.' == substr($file, 0, 1)) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Return true if requeired action allowed to file/folder
|
|
*
|
|
* @param string $path file/folder path
|
|
* @param string $action action name (read/write/rm)
|
|
* @return void
|
|
**/
|
|
protected function _isAllowed($path, $action) {
|
|
|
|
switch ($action) {
|
|
case 'read':
|
|
if (!is_readable($path)) {
|
|
return false;
|
|
}
|
|
break;
|
|
case 'write':
|
|
if (!is_writable($path)) {
|
|
return false;
|
|
}
|
|
break;
|
|
case 'rm':
|
|
if (!is_writable(dirname($path))) {
|
|
return false;
|
|
}
|
|
break;
|
|
}
|
|
|
|
// if ($this->_options['aclObj']) {
|
|
//
|
|
// }
|
|
$path = substr($path, strlen($this->_options['root'])+1);
|
|
// echo "$path\n";
|
|
foreach ($this->_options['perms'] as $regex => $rules) {
|
|
|
|
if (preg_match($regex, $path)) {
|
|
if (isset($rules[$action])) {
|
|
return $rules[$action];
|
|
}
|
|
}
|
|
}
|
|
return isset($this->_options['defaults'][$action]) ? $this->_options['defaults'][$action] : false;
|
|
}
|
|
|
|
/************************************************************/
|
|
/** utilites **/
|
|
/************************************************************/
|
|
|
|
/**
|
|
* Return image manipalation library name
|
|
*
|
|
* @return string
|
|
**/
|
|
protected function _getImgLib()
|
|
{
|
|
if (extension_loaded('imagick')) {
|
|
return 'imagick';
|
|
} elseif (function_exists('exec')) {
|
|
exec('mogrify --version', $o, $c);
|
|
if ($c == 0) {
|
|
return 'mogrify';
|
|
}
|
|
}
|
|
return function_exists('gd_info') ? 'gd' : '';
|
|
}
|
|
|
|
/**
|
|
* Return list of available archivers
|
|
*
|
|
* @return array
|
|
**/
|
|
protected function _checkArchivers()
|
|
{
|
|
if (!function_exists('exec')) {
|
|
$this->_options['archivers'] = $this->_options['archive'] = array();
|
|
return;
|
|
}
|
|
$arcs = array(
|
|
'create' => array(),
|
|
'extract' => array()
|
|
);
|
|
|
|
exec('tar --version', $o, $ctar);
|
|
if ($ctar == 0) {
|
|
$arcs['create']['application/x-tar'] = array('cmd' => 'tar', 'argc' => '-cf', 'ext' => 'tar');
|
|
$arcs['extract']['application/x-tar'] = array('cmd' => 'tar', 'argc' => '-xf', 'ext' => 'tar');
|
|
$test = exec('gzip --version', $o, $c);
|
|
if ($c == 0) {
|
|
$arcs['create']['application/x-gzip'] = array('cmd' => 'tar', 'argc' => '-czf', 'ext' => 'tgz');
|
|
$arcs['extract']['application/x-gzip'] = array('cmd' => 'tar', 'argc' => '-xzf', 'ext' => 'tgz');
|
|
}
|
|
$test = exec('bzip2 --version', $o, $c);
|
|
if ($c == 0) {
|
|
$arcs['create']['application/x-bzip2'] = array('cmd' => 'tar', 'argc' => '-cjf', 'ext' => 'tbz');
|
|
$arcs['extract']['application/x-bzip2'] = array('cmd' => 'tar', 'argc' => '-xjf', 'ext' => 'tbz');
|
|
}
|
|
}
|
|
|
|
exec('zip --version', $o, $c);
|
|
if ($c == 0) {
|
|
$arcs['create']['application/zip'] = array('cmd' => 'zip', 'argc' => '-r9', 'ext' => 'zip');
|
|
}
|
|
|
|
exec('unzip --help', $o, $c);
|
|
if ($c == 0) {
|
|
$arcs['extract']['application/zip'] = array('cmd' => 'unzip', 'argc' => '', 'ext' => 'zip');
|
|
}
|
|
|
|
exec('rar --version', $o, $c);
|
|
if ($c == 0 || $c == 7) {
|
|
$arcs['create']['application/x-rar'] = array('cmd' => 'rar', 'argc' => 'a -inul', 'ext' => 'rar');
|
|
$arcs['extract']['application/x-rar'] = array('cmd' => 'rar', 'argc' => 'x -y', 'ext' => 'rar');
|
|
} else {
|
|
$test = exec('unrar', $o, $c);
|
|
if ($c==0 || $c == 7) {
|
|
$arcs['extract']['application/x-rar'] = array('cmd' => 'unrar', 'argc' => 'x -y', 'ext' => 'rar');
|
|
}
|
|
}
|
|
|
|
exec('7za --help', $o, $c);
|
|
if ($c == 0) {
|
|
$arcs['create']['application/x-7z-compressed'] = array('cmd' => '7za', 'argc' => 'a', 'ext' => '7z');
|
|
$arcs['extract']['application/x-7z-compressed'] = array('cmd' => '7za', 'argc' => 'e -y', 'ext' => '7z');
|
|
|
|
if (empty($arcs['create']['application/x-gzip'])) {
|
|
$arcs['create']['application/x-gzip'] = array('cmd' => '7za', 'argc' => 'a -tgzip', 'ext' => 'tar.gz');
|
|
}
|
|
if (empty($arcs['extract']['application/x-gzip'])) {
|
|
$arcs['extract']['application/x-gzip'] = array('cmd' => '7za', 'argc' => 'e -tgzip -y', 'ext' => 'tar.gz');
|
|
}
|
|
if (empty($arcs['create']['application/x-bzip2'])) {
|
|
$arcs['create']['application/x-bzip2'] = array('cmd' => '7za', 'argc' => 'a -tbzip2', 'ext' => 'tar.bz');
|
|
}
|
|
if (empty($arcs['extract']['application/x-bzip2'])) {
|
|
$arcs['extract']['application/x-bzip2'] = array('cmd' => '7za', 'argc' => 'a -tbzip2 -y', 'ext' => 'tar.bz');
|
|
}
|
|
if (empty($arcs['create']['application/zip'])) {
|
|
$arcs['create']['application/zip'] = array('cmd' => '7za', 'argc' => 'a -tzip -l', 'ext' => 'zip');
|
|
}
|
|
if (empty($arcs['extract']['application/zip'])) {
|
|
$arcs['extract']['application/zip'] = array('cmd' => '7za', 'argc' => 'e -tzip -y', 'ext' => 'zip');
|
|
}
|
|
if (empty($arcs['create']['application/x-tar'])) {
|
|
$arcs['create']['application/x-tar'] = array('cmd' => '7za', 'argc' => 'a -ttar -l', 'ext' => 'tar');
|
|
}
|
|
if (empty($arcs['extract']['application/x-tar'])) {
|
|
$arcs['extract']['application/x-tar'] = array('cmd' => '7za', 'argc' => 'e -ttar -y', 'ext' => 'tar');
|
|
}
|
|
}
|
|
|
|
$this->_options['archivers'] = $arcs;
|
|
foreach ($this->_options['archiveMimes'] as $k=>$mime) {
|
|
if (!isset($this->_options['archivers']['create'][$mime])) {
|
|
unset($this->_options['archiveMimes'][$k]);
|
|
}
|
|
}
|
|
if (empty($this->_options['archiveMimes'])) {
|
|
$this->_options['archiveMimes'] = array_keys($this->_options['archivers']['create']);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Return mimetype detect method name
|
|
*
|
|
* @return string
|
|
**/
|
|
protected function _getMimeDetect()
|
|
{
|
|
if (class_exists('finfo')) {
|
|
return 'finfo';
|
|
} elseif (function_exists('mime_content_type') && (mime_content_type(__FILE__) == 'text/x-php' || mime_content_type(__FILE__) == 'text/x-c++')) {
|
|
return 'mime_content_type';
|
|
} elseif (function_exists('exec')) {
|
|
$type = exec('file -ib '.escapeshellarg(__FILE__));
|
|
if (0 === strpos($type, 'text/x-php') || 0 === strpos($type, 'text/x-c++'))
|
|
{
|
|
return 'linux';
|
|
}
|
|
$type = exec('file -Ib '.escapeshellarg(__FILE__));
|
|
if (0 === strpos($type, 'text/x-php') || 0 === strpos($type, 'text/x-c++'))
|
|
{
|
|
return 'bsd';
|
|
}
|
|
}
|
|
return 'internal';
|
|
}
|
|
|
|
|
|
/**
|
|
* Return file path hash
|
|
*
|
|
* @param string $path
|
|
* @return string
|
|
**/
|
|
protected function _hash($path)
|
|
{
|
|
return md5($path);
|
|
}
|
|
|
|
/**
|
|
* Return file URL
|
|
*
|
|
* @param string $path
|
|
* @return string
|
|
**/
|
|
protected function _path2url($path)
|
|
{
|
|
$dir = substr(dirname($path), strlen($this->_options['root'])+1);
|
|
$file = rawurlencode(basename($path));
|
|
return $this->_options['URL'].($dir ? str_replace(DIRECTORY_SEPARATOR, '/', $dir).'/' : '').$file;
|
|
}
|
|
|
|
/**
|
|
* Return normalized path, this works the same as os.path.normpath() in Python
|
|
*
|
|
* @param string $path path
|
|
* @return string
|
|
**/
|
|
protected function _normpath($path)
|
|
{
|
|
if (empty($path))
|
|
return '.';
|
|
|
|
if (strpos($path, '/') === 0)
|
|
$initial_slashes = true;
|
|
else
|
|
$initial_slashes = false;
|
|
if (
|
|
($initial_slashes) &&
|
|
(strpos($path, '//') === 0) &&
|
|
(strpos($path, '///') === false)
|
|
)
|
|
$initial_slashes = 2;
|
|
$initial_slashes = (int) $initial_slashes;
|
|
|
|
$comps = explode('/', $path);
|
|
$new_comps = array();
|
|
foreach ($comps as $comp)
|
|
{
|
|
if (in_array($comp, array('', '.')))
|
|
continue;
|
|
if (
|
|
($comp != '..') ||
|
|
(!$initial_slashes && !$new_comps) ||
|
|
($new_comps && (end($new_comps) == '..'))
|
|
)
|
|
array_push($new_comps, $comp);
|
|
elseif ($new_comps)
|
|
array_pop($new_comps);
|
|
}
|
|
$comps = $new_comps;
|
|
$path = implode('/', $comps);
|
|
if ($initial_slashes)
|
|
$path = str_repeat('/', $initial_slashes) . $path;
|
|
if ($path)
|
|
return $path;
|
|
else
|
|
return '.';
|
|
}
|
|
|
|
/**
|
|
* Pack error message in $this->_result['errorData']
|
|
*
|
|
* @param string $path path to file
|
|
* @param string $msg error message
|
|
* @return bool always false
|
|
**/
|
|
protected function _errorData($path, $msg)
|
|
{
|
|
$path = preg_replace('|^'.preg_quote($this->_options['root']).'|', $this->_fakeRoot, $path);
|
|
if (!isset($this->_result['errorData'])) {
|
|
$this->_result['errorData'] = array();
|
|
}
|
|
$this->_result['errorData'][$path] = $msg;
|
|
return false;
|
|
}
|
|
|
|
protected function _utime()
|
|
{
|
|
$time = explode(" ", microtime());
|
|
return (double)$time[1] + (double)$time[0];
|
|
}
|
|
|
|
}
|