File indexing completed on 2024-12-22 05:35:33
0001 <?php 0002 0003 /** 0004 * elFinder driver for local filesystem. 0005 * 0006 * @author Dmitry (dio) Levashov 0007 * @author Troex Nevelin 0008 **/ 0009 class elFinderVolumeLocalFileSystem extends elFinderVolumeDriver { 0010 0011 /** 0012 * Driver id 0013 * Must be started from letter and contains [a-z0-9] 0014 * Used as part of volume id 0015 * 0016 * @var string 0017 **/ 0018 protected $driverId = 'l'; 0019 0020 /** 0021 * Required to count total archive files size 0022 * 0023 * @var int 0024 **/ 0025 protected $archiveSize = 0; 0026 0027 /** 0028 * Constructor 0029 * Extend options with required fields 0030 * 0031 * @return void 0032 * @author Dmitry (dio) Levashov 0033 **/ 0034 public function __construct() { 0035 $this->options['alias'] = ''; // alias to replace root dir name 0036 $this->options['dirMode'] = 0755; // new dirs mode 0037 $this->options['fileMode'] = 0644; // new files mode 0038 $this->options['quarantine'] = '.quarantine'; // quarantine folder name - required to check archive (must be hidden) 0039 $this->options['maxArcFilesSize'] = 0; // max allowed archive files size (0 - no limit) 0040 } 0041 0042 /*********************************************************************/ 0043 /* INIT AND CONFIGURE */ 0044 /*********************************************************************/ 0045 0046 /** 0047 * Configure after successfull mount. 0048 * 0049 * @return void 0050 * @author Dmitry (dio) Levashov 0051 **/ 0052 protected function configure() { 0053 $this->aroot = realpath($this->root); 0054 $root = $this->stat($this->root); 0055 0056 if ($this->options['quarantine']) { 0057 $this->attributes[] = array( 0058 'pattern' => '~^'.preg_quote(DIRECTORY_SEPARATOR.$this->options['quarantine']).'$~', 0059 'read' => false, 0060 'write' => false, 0061 'locked' => true, 0062 'hidden' => true 0063 ); 0064 } 0065 0066 // chek thumbnails path 0067 if ($this->options['tmbPath']) { 0068 $this->options['tmbPath'] = strpos($this->options['tmbPath'], DIRECTORY_SEPARATOR) === false 0069 // tmb path set as dirname under root dir 0070 ? $this->root.DIRECTORY_SEPARATOR.$this->options['tmbPath'] 0071 // tmb path as full path 0072 : $this->_normpath($this->options['tmbPath']); 0073 } 0074 0075 parent::configure(); 0076 0077 // if no thumbnails url - try detect it 0078 if ($root['read'] && !$this->tmbURL && $this->URL) { 0079 if (strpos($this->tmbPath, $this->root) === 0) { 0080 $this->tmbURL = $this->URL.str_replace(DIRECTORY_SEPARATOR, '/', substr($this->tmbPath, strlen($this->root)+1)); 0081 if (preg_match("|[^/?&=]$|", $this->tmbURL)) { 0082 $this->tmbURL .= '/'; 0083 } 0084 } 0085 } 0086 0087 // check quarantine dir 0088 if (!empty($this->options['quarantine'])) { 0089 $this->quarantine = $this->root.DIRECTORY_SEPARATOR.$this->options['quarantine']; 0090 if ((!is_dir($this->quarantine) && !$this->_mkdir($this->root, $this->options['quarantine'])) || !is_writable($this->quarantine)) { 0091 $this->archivers['extract'] = array(); 0092 $this->disabled[] = 'extract'; 0093 } 0094 } else { 0095 $this->archivers['extract'] = array(); 0096 $this->disabled[] = 'extract'; 0097 } 0098 0099 } 0100 0101 /*********************************************************************/ 0102 /* FS API */ 0103 /*********************************************************************/ 0104 0105 /*********************** paths/urls *************************/ 0106 0107 /** 0108 * Return parent directory path 0109 * 0110 * @param string $path file path 0111 * @return string 0112 * @author Dmitry (dio) Levashov 0113 **/ 0114 protected function _dirname($path) { 0115 return dirname($path); 0116 } 0117 0118 /** 0119 * Return file name 0120 * 0121 * @param string $path file path 0122 * @return string 0123 * @author Dmitry (dio) Levashov 0124 **/ 0125 protected function _basename($path) { 0126 return basename($path); 0127 } 0128 0129 /** 0130 * Join dir name and file name and retur full path 0131 * 0132 * @param string $dir 0133 * @param string $name 0134 * @return string 0135 * @author Dmitry (dio) Levashov 0136 **/ 0137 protected function _joinPath($dir, $name) { 0138 return $dir.DIRECTORY_SEPARATOR.$name; 0139 } 0140 0141 /** 0142 * Return normalized path, this works the same as os.path.normpath() in Python 0143 * 0144 * @param string $path path 0145 * @return string 0146 * @author Troex Nevelin 0147 **/ 0148 protected function _normpath($path) { 0149 if (empty($path)) { 0150 return '.'; 0151 } 0152 0153 if (strpos($path, '/') === 0) { 0154 $initial_slashes = true; 0155 } else { 0156 $initial_slashes = false; 0157 } 0158 0159 if (($initial_slashes) 0160 && (strpos($path, '//') === 0) 0161 && (strpos($path, '///') === false)) { 0162 $initial_slashes = 2; 0163 } 0164 0165 $initial_slashes = (int) $initial_slashes; 0166 0167 $comps = explode('/', $path); 0168 $new_comps = array(); 0169 foreach ($comps as $comp) { 0170 if (in_array($comp, array('', '.'))) { 0171 continue; 0172 } 0173 0174 if (($comp != '..') 0175 || (!$initial_slashes && !$new_comps) 0176 || ($new_comps && (end($new_comps) == '..'))) { 0177 array_push($new_comps, $comp); 0178 } elseif ($new_comps) { 0179 array_pop($new_comps); 0180 } 0181 } 0182 $comps = $new_comps; 0183 $path = implode('/', $comps); 0184 if ($initial_slashes) { 0185 $path = str_repeat('/', $initial_slashes) . $path; 0186 } 0187 0188 return $path ? $path : '.'; 0189 } 0190 0191 /** 0192 * Return file path related to root dir 0193 * 0194 * @param string $path file path 0195 * @return string 0196 * @author Dmitry (dio) Levashov 0197 **/ 0198 protected function _relpath($path) { 0199 return $path == $this->root ? '' : substr($path, strlen($this->root)+1); 0200 } 0201 0202 /** 0203 * Convert path related to root dir into real path 0204 * 0205 * @param string $path file path 0206 * @return string 0207 * @author Dmitry (dio) Levashov 0208 **/ 0209 protected function _abspath($path) { 0210 return $path == DIRECTORY_SEPARATOR ? $this->root : $this->root.DIRECTORY_SEPARATOR.$path; 0211 } 0212 0213 /** 0214 * Return fake path started from root dir 0215 * 0216 * @param string $path file path 0217 * @return string 0218 * @author Dmitry (dio) Levashov 0219 **/ 0220 protected function _path($path) { 0221 return $this->rootName.($path == $this->root ? '' : $this->separator.$this->_relpath($path)); 0222 } 0223 0224 /** 0225 * Return true if $path is children of $parent 0226 * 0227 * @param string $path path to check 0228 * @param string $parent parent path 0229 * @return bool 0230 * @author Dmitry (dio) Levashov 0231 **/ 0232 protected function _inpath($path, $parent) { 0233 return $path == $parent || strpos($path, $parent.DIRECTORY_SEPARATOR) === 0; 0234 } 0235 0236 0237 0238 /***************** file stat ********************/ 0239 0240 /** 0241 * Return stat for given path. 0242 * Stat contains following fields: 0243 * - (int) size file size in b. required 0244 * - (int) ts file modification time in unix time. required 0245 * - (string) mime mimetype. required for folders, others - optionally 0246 * - (bool) read read permissions. required 0247 * - (bool) write write permissions. required 0248 * - (bool) locked is object locked. optionally 0249 * - (bool) hidden is object hidden. optionally 0250 * - (string) alias for symlinks - link target path relative to root path. optionally 0251 * - (string) target for symlinks - link target path. optionally 0252 * 0253 * If file does not exists - returns empty array or false. 0254 * 0255 * @param string $path file path 0256 * @return array|false 0257 * @author Dmitry (dio) Levashov 0258 **/ 0259 protected function _stat($path) { 0260 $stat = array(); 0261 0262 if (!file_exists($path)) { 0263 return $stat; 0264 } 0265 0266 if ($path != $this->root && is_link($path)) { 0267 if (($target = $this->readlink($path)) == false 0268 || $target == $path) { 0269 $stat['mime'] = 'symlink-broken'; 0270 $stat['read'] = false; 0271 $stat['write'] = false; 0272 $stat['size'] = 0; 0273 return $stat; 0274 } 0275 $stat['alias'] = $this->_path($target); 0276 $stat['target'] = $target; 0277 $path = $target; 0278 $lstat = lstat($path); 0279 $size = $lstat['size']; 0280 } else { 0281 $size = @filesize($path); 0282 } 0283 0284 $dir = is_dir($path); 0285 0286 $stat['mime'] = $dir ? 'directory' : $this->mimetype($path); 0287 $stat['ts'] = filemtime($path); 0288 $stat['read'] = is_readable($path); 0289 $stat['write'] = is_writable($path); 0290 if ($stat['read']) { 0291 $stat['size'] = $dir ? 0 : $size; 0292 } 0293 0294 return $stat; 0295 } 0296 0297 0298 /** 0299 * Return true if path is dir and has at least one childs directory 0300 * 0301 * @param string $path dir path 0302 * @return bool 0303 * @author Dmitry (dio) Levashov 0304 **/ 0305 protected function _subdirs($path) { 0306 0307 if (($dir = dir($path))) { 0308 $dir = dir($path); 0309 while (($entry = $dir->read()) !== false) { 0310 $p = $dir->path.DIRECTORY_SEPARATOR.$entry; 0311 if ($entry != '.' && $entry != '..' && is_dir($p) && !$this->attr($p, 'hidden')) { 0312 $dir->close(); 0313 return true; 0314 } 0315 } 0316 $dir->close(); 0317 } 0318 return false; 0319 } 0320 0321 /** 0322 * Return object width and height 0323 * Ususaly used for images, but can be realize for video etc... 0324 * 0325 * @param string $path file path 0326 * @param string $mime file mime type 0327 * @return string 0328 * @author Dmitry (dio) Levashov 0329 **/ 0330 protected function _dimensions($path, $mime) { 0331 clearstatcache(); 0332 return strpos($mime, 'image') === 0 && ($s = @getimagesize($path)) !== false 0333 ? $s[0].'x'.$s[1] 0334 : false; 0335 } 0336 /******************** file/dir content *********************/ 0337 0338 /** 0339 * Return symlink target file 0340 * 0341 * @param string $path link path 0342 * @return string 0343 * @author Dmitry (dio) Levashov 0344 **/ 0345 protected function readlink($path) { 0346 if (!($target = @readlink($path))) { 0347 return false; 0348 } 0349 0350 if (substr($target, 0, 1) != DIRECTORY_SEPARATOR) { 0351 $target = dirname($path).DIRECTORY_SEPARATOR.$target; 0352 } 0353 0354 $atarget = realpath($target); 0355 0356 if (!$atarget) { 0357 return false; 0358 } 0359 0360 $root = $this->root; 0361 $aroot = $this->aroot; 0362 0363 if ($this->_inpath($atarget, $this->aroot)) { 0364 return $this->_normpath($this->root.DIRECTORY_SEPARATOR.substr($atarget, strlen($this->aroot)+1)); 0365 } 0366 0367 return false; 0368 } 0369 0370 /** 0371 * Return files list in directory. 0372 * 0373 * @param string $path dir path 0374 * @return array 0375 * @author Dmitry (dio) Levashov 0376 **/ 0377 protected function _scandir($path) { 0378 $files = array(); 0379 0380 foreach (scandir($path) as $name) { 0381 if ($name != '.' && $name != '..') { 0382 $files[] = $path.DIRECTORY_SEPARATOR.$name; 0383 } 0384 } 0385 return $files; 0386 } 0387 0388 /** 0389 * Open file and return file pointer 0390 * 0391 * @param string $path file path 0392 * @param bool $write open file for writing 0393 * @return resource|false 0394 * @author Dmitry (dio) Levashov 0395 **/ 0396 protected function _fopen($path, $mode='rb') { 0397 return @fopen($path, 'r'); 0398 } 0399 0400 /** 0401 * Close opened file 0402 * 0403 * @param resource $fp file pointer 0404 * @return bool 0405 * @author Dmitry (dio) Levashov 0406 **/ 0407 protected function _fclose($fp, $path='') { 0408 return @fclose($fp); 0409 } 0410 0411 /******************** file/dir manipulations *************************/ 0412 0413 /** 0414 * Create dir and return created dir path or false on failed 0415 * 0416 * @param string $path parent dir path 0417 * @param string $name new directory name 0418 * @return string|bool 0419 * @author Dmitry (dio) Levashov 0420 **/ 0421 protected function _mkdir($path, $name) { 0422 $path = $path.DIRECTORY_SEPARATOR.$name; 0423 0424 if (@mkdir($path)) { 0425 @chmod($path, $this->options['dirMode']); 0426 return $path; 0427 } 0428 0429 return false; 0430 } 0431 0432 /** 0433 * Create file and return it's path or false on failed 0434 * 0435 * @param string $path parent dir path 0436 * @param string $name new file name 0437 * @return string|bool 0438 * @author Dmitry (dio) Levashov 0439 **/ 0440 protected function _mkfile($path, $name) { 0441 $path = $path.DIRECTORY_SEPARATOR.$name; 0442 0443 if (($fp = @fopen($path, 'w'))) { 0444 @fclose($fp); 0445 @chmod($path, $this->options['fileMode']); 0446 return $path; 0447 } 0448 return false; 0449 } 0450 0451 /** 0452 * Create symlink 0453 * 0454 * @param string $source file to link to 0455 * @param string $targetDir folder to create link in 0456 * @param string $name symlink name 0457 * @return bool 0458 * @author Dmitry (dio) Levashov 0459 **/ 0460 protected function _symlink($source, $targetDir, $name) { 0461 return @symlink($source, $targetDir.DIRECTORY_SEPARATOR.$name); 0462 } 0463 0464 /** 0465 * Copy file into another file 0466 * 0467 * @param string $source source file path 0468 * @param string $targetDir target directory path 0469 * @param string $name new file name 0470 * @return bool 0471 * @author Dmitry (dio) Levashov 0472 **/ 0473 protected function _copy($source, $targetDir, $name) { 0474 return copy($source, $targetDir.DIRECTORY_SEPARATOR.$name); 0475 } 0476 0477 /** 0478 * Move file into another parent dir. 0479 * Return new file path or false. 0480 * 0481 * @param string $source source file path 0482 * @param string $target target dir path 0483 * @param string $name file name 0484 * @return string|bool 0485 * @author Dmitry (dio) Levashov 0486 **/ 0487 protected function _move($source, $targetDir, $name) { 0488 $target = $targetDir.DIRECTORY_SEPARATOR.$name; 0489 return @rename($source, $target) ? $target : false; 0490 } 0491 0492 /** 0493 * Remove file 0494 * 0495 * @param string $path file path 0496 * @return bool 0497 * @author Dmitry (dio) Levashov 0498 **/ 0499 protected function _unlink($path) { 0500 return @unlink($path); 0501 } 0502 0503 /** 0504 * Remove dir 0505 * 0506 * @param string $path dir path 0507 * @return bool 0508 * @author Dmitry (dio) Levashov 0509 **/ 0510 protected function _rmdir($path) { 0511 return @rmdir($path); 0512 } 0513 0514 /** 0515 * Create new file and write into it from file pointer. 0516 * Return new file path or false on error. 0517 * 0518 * @param resource $fp file pointer 0519 * @param string $dir target dir path 0520 * @param string $name file name 0521 * @return bool|string 0522 * @author Dmitry (dio) Levashov 0523 **/ 0524 protected function _save($fp, $dir, $name, $mime, $w, $h) { 0525 $path = $dir.DIRECTORY_SEPARATOR.$name; 0526 0527 if (!($target = @fopen($path, 'wb'))) { 0528 return false; 0529 } 0530 0531 while (!feof($fp)) { 0532 fwrite($target, fread($fp, 8192)); 0533 } 0534 fclose($target); 0535 @chmod($path, $this->options['fileMode']); 0536 clearstatcache(); 0537 return $path; 0538 } 0539 0540 /** 0541 * Get file contents 0542 * 0543 * @param string $path file path 0544 * @return string|false 0545 * @author Dmitry (dio) Levashov 0546 **/ 0547 protected function _getContents($path) { 0548 return file_get_contents($path); 0549 } 0550 0551 /** 0552 * Write a string to a file 0553 * 0554 * @param string $path file path 0555 * @param string $content new file content 0556 * @return bool 0557 * @author Dmitry (dio) Levashov 0558 **/ 0559 protected function _filePutContents($path, $content) { 0560 if (@file_put_contents($path, $content, LOCK_EX) !== false) { 0561 clearstatcache(); 0562 return true; 0563 } 0564 return false; 0565 } 0566 0567 /** 0568 * Detect available archivers 0569 * 0570 * @return void 0571 **/ 0572 protected function _checkArchivers() { 0573 if (!function_exists('exec')) { 0574 $this->options['archivers'] = $this->options['archive'] = array(); 0575 return; 0576 } 0577 $arcs = array( 0578 'create' => array(), 0579 'extract' => array() 0580 ); 0581 0582 //exec('tar --version', $o, $ctar); 0583 $this->procExec('tar --version', $o, $ctar); 0584 0585 if ($ctar == 0) { 0586 $arcs['create']['application/x-tar'] = array('cmd' => 'tar', 'argc' => '-cf', 'ext' => 'tar'); 0587 $arcs['extract']['application/x-tar'] = array('cmd' => 'tar', 'argc' => '-xf', 'ext' => 'tar'); 0588 //$test = exec('gzip --version', $o, $c); 0589 unset($o); 0590 $test = $this->procExec('gzip --version', $o, $c); 0591 0592 if ($c == 0) { 0593 $arcs['create']['application/x-gzip'] = array('cmd' => 'tar', 'argc' => '-czf', 'ext' => 'tgz'); 0594 $arcs['extract']['application/x-gzip'] = array('cmd' => 'tar', 'argc' => '-xzf', 'ext' => 'tgz'); 0595 } 0596 unset($o); 0597 //$test = exec('bzip2 --version', $o, $c); 0598 $test = $this->procExec('bzip2 --version', $o, $c); 0599 if ($c == 0) { 0600 $arcs['create']['application/x-bzip2'] = array('cmd' => 'tar', 'argc' => '-cjf', 'ext' => 'tbz'); 0601 $arcs['extract']['application/x-bzip2'] = array('cmd' => 'tar', 'argc' => '-xjf', 'ext' => 'tbz'); 0602 } 0603 } 0604 unset($o); 0605 //exec('zip --version', $o, $c); 0606 $this->procExec('zip -v', $o, $c); 0607 if ($c == 0) { 0608 $arcs['create']['application/zip'] = array('cmd' => 'zip', 'argc' => '-r9', 'ext' => 'zip'); 0609 } 0610 unset($o); 0611 $this->procExec('unzip --help', $o, $c); 0612 if ($c == 0) { 0613 $arcs['extract']['application/zip'] = array('cmd' => 'unzip', 'argc' => '', 'ext' => 'zip'); 0614 } 0615 unset($o); 0616 //exec('rar --version', $o, $c); 0617 $this->procExec('rar --version', $o, $c); 0618 if ($c == 0 || $c == 7) { 0619 $arcs['create']['application/x-rar'] = array('cmd' => 'rar', 'argc' => 'a -inul', 'ext' => 'rar'); 0620 $arcs['extract']['application/x-rar'] = array('cmd' => 'rar', 'argc' => 'x -y', 'ext' => 'rar'); 0621 } else { 0622 unset($o); 0623 //$test = exec('unrar', $o, $c); 0624 $test = $this->procExec('unrar', $o, $c); 0625 if ($c==0 || $c == 7) { 0626 $arcs['extract']['application/x-rar'] = array('cmd' => 'unrar', 'argc' => 'x -y', 'ext' => 'rar'); 0627 } 0628 } 0629 unset($o); 0630 //exec('7za --help', $o, $c); 0631 $this->procExec('7za --help', $o, $c); 0632 if ($c == 0) { 0633 $arcs['create']['application/x-7z-compressed'] = array('cmd' => '7za', 'argc' => 'a', 'ext' => '7z'); 0634 $arcs['extract']['application/x-7z-compressed'] = array('cmd' => '7za', 'argc' => 'e -y', 'ext' => '7z'); 0635 0636 if (empty($arcs['create']['application/x-gzip'])) { 0637 $arcs['create']['application/x-gzip'] = array('cmd' => '7za', 'argc' => 'a -tgzip', 'ext' => 'tar.gz'); 0638 } 0639 if (empty($arcs['extract']['application/x-gzip'])) { 0640 $arcs['extract']['application/x-gzip'] = array('cmd' => '7za', 'argc' => 'e -tgzip -y', 'ext' => 'tar.gz'); 0641 } 0642 if (empty($arcs['create']['application/x-bzip2'])) { 0643 $arcs['create']['application/x-bzip2'] = array('cmd' => '7za', 'argc' => 'a -tbzip2', 'ext' => 'tar.bz'); 0644 } 0645 if (empty($arcs['extract']['application/x-bzip2'])) { 0646 $arcs['extract']['application/x-bzip2'] = array('cmd' => '7za', 'argc' => 'a -tbzip2 -y', 'ext' => 'tar.bz'); 0647 } 0648 if (empty($arcs['create']['application/zip'])) { 0649 $arcs['create']['application/zip'] = array('cmd' => '7za', 'argc' => 'a -tzip -l', 'ext' => 'zip'); 0650 } 0651 if (empty($arcs['extract']['application/zip'])) { 0652 $arcs['extract']['application/zip'] = array('cmd' => '7za', 'argc' => 'e -tzip -y', 'ext' => 'zip'); 0653 } 0654 if (empty($arcs['create']['application/x-tar'])) { 0655 $arcs['create']['application/x-tar'] = array('cmd' => '7za', 'argc' => 'a -ttar -l', 'ext' => 'tar'); 0656 } 0657 if (empty($arcs['extract']['application/x-tar'])) { 0658 $arcs['extract']['application/x-tar'] = array('cmd' => '7za', 'argc' => 'e -ttar -y', 'ext' => 'tar'); 0659 } 0660 } 0661 0662 $this->archivers = $arcs; 0663 } 0664 0665 /** 0666 * Unpack archive 0667 * 0668 * @param string $path archive path 0669 * @param array $arc archiver command and arguments (same as in $this->archivers) 0670 * @return void 0671 * @author Dmitry (dio) Levashov 0672 * @author Alexey Sukhotin 0673 **/ 0674 protected function _unpack($path, $arc) { 0675 $cwd = getcwd(); 0676 $dir = $this->_dirname($path); 0677 chdir($dir); 0678 $cmd = $arc['cmd'].' '.$arc['argc'].' '.escapeshellarg($this->_basename($path)); 0679 $this->procExec($cmd, $o, $c); 0680 chdir($cwd); 0681 } 0682 0683 /** 0684 * Recursive symlinks search 0685 * 0686 * @param string $path file/dir path 0687 * @return bool 0688 * @author Dmitry (dio) Levashov 0689 **/ 0690 protected function _findSymlinks($path) { 0691 if (is_link($path)) { 0692 return true; 0693 } 0694 0695 if (is_dir($path)) { 0696 foreach (scandir($path) as $name) { 0697 if ($name != '.' && $name != '..') { 0698 $p = $path.DIRECTORY_SEPARATOR.$name; 0699 if (is_link($p)) { 0700 return true; 0701 } 0702 if (is_dir($p) && $this->_findSymlinks($p)) { 0703 return true; 0704 } elseif (is_file($p)) { 0705 $this->archiveSize += filesize($p); 0706 } 0707 } 0708 } 0709 } else { 0710 $this->archiveSize += filesize($path); 0711 } 0712 0713 return false; 0714 } 0715 0716 /** 0717 * Extract files from archive 0718 * 0719 * @param string $path archive path 0720 * @param array $arc archiver command and arguments (same as in $this->archivers) 0721 * @return true 0722 * @author Dmitry (dio) Levashov, 0723 * @author Alexey Sukhotin 0724 **/ 0725 protected function _extract($path, $arc) { 0726 0727 if ($this->quarantine) { 0728 $dir = $this->quarantine.DIRECTORY_SEPARATOR.str_replace(' ', '_', microtime()).basename($path); 0729 $archive = $dir.DIRECTORY_SEPARATOR.basename($path); 0730 0731 if (!@mkdir($dir)) { 0732 return false; 0733 } 0734 0735 chmod($dir, 0777); 0736 0737 // copy in quarantine 0738 if (!copy($path, $archive)) { 0739 return false; 0740 } 0741 0742 // extract in quarantine 0743 $this->_unpack($archive, $arc); 0744 @unlink($archive); 0745 0746 // get files list 0747 $ls = array(); 0748 foreach (scandir($dir) as $i => $name) { 0749 if ($name != '.' && $name != '..') { 0750 $ls[] = $name; 0751 } 0752 } 0753 0754 // no files - extract error ? 0755 if (empty($ls)) { 0756 return false; 0757 } 0758 0759 $this->archiveSize = 0; 0760 0761 // find symlinks 0762 $symlinks = $this->_findSymlinks($dir); 0763 // remove arc copy 0764 $this->remove($dir); 0765 0766 if ($symlinks) { 0767 return $this->setError(elFinder::ERROR_ARC_SYMLINKS); 0768 } 0769 0770 // check max files size 0771 if ($this->options['maxArcFilesSize'] > 0 && $this->options['maxArcFilesSize'] < $this->archiveSize) { 0772 return $this->setError(elFinder::ERROR_ARC_MAXSIZE); 0773 } 0774 0775 0776 0777 // archive contains one item - extract in archive dir 0778 if (count($ls) == 1) { 0779 $this->_unpack($path, $arc); 0780 $result = dirname($path).DIRECTORY_SEPARATOR.$ls[0]; 0781 0782 0783 } else { 0784 // for several files - create new directory 0785 // create unique name for directory 0786 $name = basename($path); 0787 if (preg_match('/\.((tar\.(gz|bz|bz2|z|lzo))|cpio\.gz|ps\.gz|xcf\.(gz|bz2)|[a-z0-9]{1,4})$/i', $name, $m)) { 0788 $name = substr($name, 0, strlen($name)-strlen($m[0])); 0789 } 0790 $test = dirname($path).DIRECTORY_SEPARATOR.$name; 0791 if (file_exists($test) || is_link($test)) { 0792 $name = $this->uniqueName(dirname($path), $name, '-', false); 0793 } 0794 0795 $result = dirname($path).DIRECTORY_SEPARATOR.$name; 0796 $archive = $result.DIRECTORY_SEPARATOR.basename($path); 0797 0798 if (!$this->_mkdir(dirname($path), $name) || !copy($path, $archive)) { 0799 return false; 0800 } 0801 0802 $this->_unpack($archive, $arc); 0803 @unlink($archive); 0804 } 0805 0806 return file_exists($result) ? $result : false; 0807 } 0808 } 0809 0810 /** 0811 * Create archive and return its path 0812 * 0813 * @param string $dir target dir 0814 * @param array $files files names list 0815 * @param string $name archive name 0816 * @param array $arc archiver options 0817 * @return string|bool 0818 * @author Dmitry (dio) Levashov, 0819 * @author Alexey Sukhotin 0820 **/ 0821 protected function _archive($dir, $files, $name, $arc) { 0822 $cwd = getcwd(); 0823 chdir($dir); 0824 0825 $files = array_map('escapeshellarg', $files); 0826 0827 $cmd = $arc['cmd'].' '.$arc['argc'].' '.escapeshellarg($name).' '.implode(' ', $files); 0828 $this->procExec($cmd, $o, $c); 0829 chdir($cwd); 0830 0831 $path = $dir.DIRECTORY_SEPARATOR.$name; 0832 return file_exists($path) ? $path : false; 0833 } 0834 0835 } // END class