: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
* @param string $name file name
* @internal param string $target target dir path
* @author Dmitry (dio) Levashov
protected function _move($source, $targetDir, $name)
$mtime = filemtime($source);
$target = $this->_joinPath($targetDir, $name);
if ($ret = rename($source, $target) ? $target : false) {
isset($this->options['keepTimestamp']['move']) && $mtime && touch($target, $mtime);
* @param string $path file path
* @author Dmitry (dio) Levashov
protected function _unlink($path)
return is_file($path) && unlink($path);
* @param string $path dir path
* @author Dmitry (dio) Levashov
protected function _rmdir($path)
* Create new file and write into it from file pointer.
* Return new file path or false on error.
* @param resource $fp file pointer
* @param string $dir target dir path
* @param string $name file name
* @param array $stat file stat (required by some virtual fs)
* @author Dmitry (dio) Levashov
protected function _save($fp, $dir, $name, $stat)
$path = $this->_joinPath($dir, $name);
$meta = stream_get_meta_data($fp);
$uri = isset($meta['uri']) ? $meta['uri'] : '';
if ($uri && !preg_match('#^[a-zA-Z0-9]+://#', $uri) && !is_link($uri)) {
$mtime = filemtime($uri);
$isCmdPaste = ($this->ARGS['cmd'] === 'paste');
$isCmdCopy = ($isCmdPaste && empty($this->ARGS['cut']));
if (($isCmdCopy || !rename($uri, $path)) && !copy($uri, $path)) {
// keep timestamp on upload
if ($mtime && $this->ARGS['cmd'] === 'upload') {
touch($path, isset($this->options['keepTimestamp']['upload']) ? $mtime : time());
if (file_put_contents($path, $fp, LOCK_EX) === false) {
chmod($path, $this->options['fileMode']);
* @param string $path file path
* @author Dmitry (dio) Levashov
protected function _getContents($path)
return file_get_contents($path);
* Write a string to a file
* @param string $path file path
* @param string $content new file content
* @author Dmitry (dio) Levashov
protected function _filePutContents($path, $content)
return (file_put_contents($path, $content, LOCK_EX) !== false);
* Detect available archivers
* @throws elFinderAbortException
protected function _checkArchivers()
$this->archivers = $this->getArchivers();
protected function _chmod($path, $mode)
$modeOct = is_string($mode) ? octdec($mode) : octdec(sprintf("%04o", $mode));
return chmod($path, $modeOct);
* Recursive symlinks search
* @param string $path file/dir path
* @author Dmitry (dio) Levashov
protected function _findSymlinks($path)
return self::localFindSymlinks($path);
* Extract files from archive
* @param string $path archive path
* @param array $arc archiver command and arguments (same as in $this->archivers)
* @return array|string|boolean
* @throws elFinderAbortException
* @author Dmitry (dio) Levashov,
* @author Alexey Sukhotin
protected function _extract($path, $arc)
$dir = $this->quarantine . DIRECTORY_SEPARATOR . md5(basename($path) . mt_rand());
$archive = (isset($arc['toSpec']) || $arc['cmd'] === 'phpfunction') ? '' : $dir . DIRECTORY_SEPARATOR . basename($path);
// insurance unexpected shutdown
register_shutdown_function(array($this, 'rmdirRecursive'), realpath($dir));
if (!is_readable($path) || ($archive && !copy($path, $archive))) {
$this->unpackArchive($path, $arc, $archive ? true : $dir);
return $this->setError($e->getMessage());
$ls = self::localScandir($dir);
// no files - extract error ?
// find symlinks and check extracted items
$checkRes = $this->checkExtractItems($dir);
if ($checkRes['symlinks']) {
self::localRmdirRecursive($dir);
return $this->setError(array_merge($this->error, array(elFinder::ERROR_ARC_SYMLINKS)));
$this->archiveSize = $checkRes['totalSize'];
if ($checkRes['rmNames']) {
foreach ($checkRes['rmNames'] as $name) {
$this->addError(elFinder::ERROR_SAVE, $name);
if ($this->options['maxArcFilesSize'] > 0 && $this->options['maxArcFilesSize'] < $this->archiveSize) {
return $this->setError(elFinder::ERROR_ARC_MAXSIZE);
$extractTo = $this->extractToNewdir; // 'auto', ture or false
// archive contains one item - extract in archive dir
$src = $dir . DIRECTORY_SEPARATOR . $ls[0];
if (($extractTo === 'auto' || !$extractTo) && count($ls) === 1 && is_file($src)) {
} else if ($extractTo === 'auto' || $extractTo) {
// for several files - create new directory
// create unique name for directory
$splits = elFinder::splitFileExtention(basename($path));
$test = dirname($path) . DIRECTORY_SEPARATOR . $name;
if (file_exists($test) || is_link($test)) {
$name = $this->uniqueName(dirname($path), $name, '-', false);
$result = dirname($path) . DIRECTORY_SEPARATOR . $name;
if (!rename($src, $result)) {
$dstDir = dirname($path);
$target = $dstDir . DIRECTORY_SEPARATOR . $name;
if (self::localMoveRecursive($dir . DIRECTORY_SEPARATOR . $name, $target, true, $this->options['copyJoin'])) {
is_dir($dir) && $this->delTree($dir);
return (is_array($result) || file_exists($result)) ? $result : false;
//TODO: Add return statement here
* Create archive and return its path
* @param string $dir target dir
* @param array $files files names list
* @param string $name archive name
* @param array $arc archiver options
* @throws elFinderAbortException
* @author Dmitry (dio) Levashov,
* @author Alexey Sukhotin
protected function _archive($dir, $files, $name, $arc)
return $this->makeArchive($dir, $files, $name, $arc);
/******************** Over write functions *************************/
* File path of local server side work file path
protected function getWorkFile($path)
* @param string $localpath path need convert encoding to server encoding
* @throws elFinderAbortException
protected function delTree($localpath)
return $this->rmdirRecursive($localpath);
* Return fileinfo based on filename
* For item ID based path file system
* Please override if needed on each drivers
* @param string $path file cache
* @return array|boolean false
protected function isNameExists($path)
$exists = file_exists($this->convEncIn($path));
return $exists ? $this->stat($path) : false;
/******************** Over write (Optimized) functions *************************/
* @param string $path dir path
* @param string $q search string
* @throws elFinderAbortException
* @author Dmitry (dio) Levashov
protected function doSearch($path, $q, $mimes)
if (!empty($this->doSearchCurrentQuery['matchMethod']) || $this->encoding || !class_exists('FilesystemIterator', false)) {
// has custom match method or non UTF-8, use elFinderVolumeDriver::doSearch()
return parent::doSearch($path, $q, $mimes);
$timeout = $this->options['searchTimeout'] ? $this->searchStart + $this->options['searchTimeout'] : 0;
if ($timeout && $timeout < time()) {
$this->setError(elFinder::ERROR_SEARCH_TIMEOUT, $this->path($this->encode($path)));
elFinder::extendTimeLimit($this->options['searchTimeout'] + 30);
$iterator = new RecursiveIteratorIterator(
new RecursiveCallbackFilterIterator(
new RecursiveDirectoryIterator($path,
FilesystemIterator::KEY_AS_PATHNAME |
FilesystemIterator::SKIP_DOTS |
((defined('RecursiveDirectoryIterator::FOLLOW_SYMLINKS') && $this->options['followSymLinks']) ?
RecursiveDirectoryIterator::FOLLOW_SYMLINKS : 0)
array($this, 'localFileSystemSearchIteratorFilter')
RecursiveIteratorIterator::SELF_FIRST,
RecursiveIteratorIterator::CATCH_GET_CHILD
foreach ($iterator as $key => $node) {
if ($timeout && ($this->error || $timeout < time())) {
!$this->error && $this->setError(elFinder::ERROR_SEARCH_TIMEOUT, $this->path($this->encode($node->getPath)));
if ($this->stripos($node->getFilename(), $q) !== false) {
if ($timeout && ($this->error || $timeout < time())) {
!$this->error && $this->setError(elFinder::ERROR_SEARCH_TIMEOUT, $this->path($this->encode(dirname($p))));
if (!$stat) { // invalid links
if (!empty($stat['hidden']) || !$this->mimeAccepted($stat['mime'], $mimes)) {
if ((!$mimes || $stat['mime'] !== 'directory')) {
$stat['path'] = $this->path($stat['hash']);
if ($this->URL && !isset($stat['url'])) {
$_path = str_replace(DIRECTORY_SEPARATOR, '/', substr($p, strlen($this->root) + 1));
$stat['url'] = $this->URL . str_replace('%2F', '/', rawurlencode($_path));
/******************** Original local functions ************************
public function localFileSystemSearchIteratorFilter($file, $key, $iterator)
/* @var FilesystemIterator $file */
/* @var RecursiveDirectoryIterator $iterator */
$name = $file->getFilename();
if ($this->doSearchCurrentQuery['excludes']) {
foreach ($this->doSearchCurrentQuery['excludes'] as $exclude) {
if ($this->stripos($name, $exclude) !== false) {
if ($iterator->hasChildren()) {
if ($this->options['searchExDirReg'] && preg_match($this->options['searchExDirReg'], $key)) {
return (bool)$this->attr($key, 'read', null, true);
return ($this->stripos($name, $this->doSearchCurrentQuery['q']) === false) ? false : true;
* Creates a symbolic link
* @param string $target The target
* @param string $link The link
* @return boolean ( result of symlink() )
protected function localFileSystemSymlink($target, $link)
if (function_exists('symlink') and is_callable('symlink')) {
$errlev = error_reporting();
error_reporting($errlev ^ E_WARNING);
if ($res = symlink(realpath($target), $link)) {
$res = is_readable($link);
error_reporting($errlev);