: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
* Check and filter the extracted items
* @param string $path target local path
* @param array $checks types to check default: ['symlink', 'name', 'writable', 'mime']
* @return array ['symlinks' => [], 'names' => [], 'writables' => [], 'mimes' => [], 'rmNames' => [], 'totalSize' => 0]
* @throws elFinderAbortException
protected function checkExtractItems($path, $checks = null)
if (is_null($checks) || !is_array($checks)) {
$checks = array('symlink', 'name', 'writable', 'mime');
$chkSymlink = in_array('symlink', $checks);
$chkName = in_array('name', $checks);
$chkWritable = in_array('writable', $checks);
$chkMime = in_array('mime', $checks);
$files = self::localScandir($path);
$files = array(basename($path));
foreach ($files as $name) {
$p = $path . DIRECTORY_SEPARATOR . $name;
$utf8Name = elFinder::$instance->utf8Encode($name);
if ($name !== $utf8Name) {
$_utf8 = @iconv($this->encoding, 'utf-8//IGNORE', $name);
if (@iconv('utf-8', $this->encoding.'//IGNORE', $_utf8) === $name) {
$_name = $this->convEncIn($utf8Name, true);
if (!$fsSame && rename($p, $path . DIRECTORY_SEPARATOR . $_name)) {
$p = $path . DIRECTORY_SEPARATOR . $name;
// Perhaps a symbolic link to open_basedir restricted location
self::localRmdirRecursive($p);
$res['rmNames'][] = $utf8Name;
if ($chkSymlink && is_link($p)) {
self::localRmdirRecursive($p);
$res['rmNames'][] = $utf8Name;
if ($chkName && !$this->nameAccepted($name, $isDir)) {
self::localRmdirRecursive($p);
$res['rmNames'][] = $utf8Name;
if ($chkWritable && !$this->attr($p, 'write', null, $isDir)) {
self::localRmdirRecursive($p);
$res['writables'][] = $p;
$res['rmNames'][] = $utf8Name;
$cRes = $this->checkExtractItems($p, $checks);
foreach ($cRes as $k => $v) {
$res[$k] = array_merge($res[$k], $cRes[$k]);
if ($chkMime && ($mimeByName = elFinderVolumeDriver::mimetypeInternalDetect($name)) && !$this->allowPutMime($mimeByName)) {
self::localRmdirRecursive($p);
$res['rmNames'][] = $utf8Name;
$res['totalSize'] += (int)sprintf('%u', filesize($p));
$res['rmNames'] = array_unique($res['rmNames']);
* Return files of target directory that is dotfiles excludes.
* @param string $dir target directory path
protected static function localScandir($dir)
// PHP function scandir() is not work well in specific environment. I dont know why.
// ref. https://github.com/Studio-42/elFinder/issues/1248
if ($dh = opendir($dir)) {
while (false !== ($file = readdir($dh))) {
if ($file !== '.' && $file !== '..') {
throw new Exception('Can not open local directory.');
* Remove directory recursive on local file system
* @param string $dir Target dirctory path
* @throws elFinderAbortException
protected static function localRmdirRecursive($dir)
if (is_callable('exec')) {
if (substr(PHP_OS, 0, 3) === 'WIN') {
if (!is_link($dir) && is_dir($dir)) {
exec('rd /S /Q ' . escapeshellarg($dir), $o, $r);
exec('del /F /Q ' . escapeshellarg($dir), $o, $r);
exec('rm -rf ' . escapeshellarg($dir), $o, $r);
if (!is_link($dir) && is_dir($dir)) {
if ($handle = opendir($dir)) {
while (false !== ($file = readdir($handle))) {
if ($file === '.' || $file === '..') {
elFinder::extendTimeLimit(30);
$path = $dir . DIRECTORY_SEPARATOR . $file;
if (!is_link($dir) && is_dir($path)) {
self::localRmdirRecursive($path);
* Move item recursive on local file system
* @throws elFinderAbortException
protected static function localMoveRecursive($src, $target, $overWrite = true, $copyJoin = true)
if (!file_exists($target)) {
return rename($src, $target);
if (!$copyJoin || !is_dir($target)) {
$del = self::localRmdirRecursive($target);
return rename($src, $target);
foreach (self::localScandir($src) as $item) {
$res |= self::localMoveRecursive($src . DIRECTORY_SEPARATOR . $item, $target . DIRECTORY_SEPARATOR . $item, $overWrite, $copyJoin);
* Create Zip archive using PHP class ZipArchive
* @param string $dir target dir
* @param array $files files names list
* @param string|object $zipPath Zip archive name
protected static function zipArchiveZip($dir, $files, $zipPath)
if ($start = is_string($zipPath)) {
if ($zip->open($dir . DIRECTORY_SEPARATOR . $zipPath, ZipArchive::CREATE) !== true) {
foreach ($files as $file) {
$path = $dir . DIRECTORY_SEPARATOR . $file;
$zip->addEmptyDir($file);
if ($handle = opendir($path)) {
while (false !== ($entry = readdir($handle))) {
if ($entry !== "." && $entry !== "..") {
$_files[] = $file . DIRECTORY_SEPARATOR . $entry;
self::zipArchiveZip($dir, $_files, $zip);
$zip->addFile($path, $file);
* Unpack Zip archive using PHP class ZipArchive
* @param string $zipPath Zip archive name
* @param string $toDir Extract to path
protected static function zipArchiveUnzip($zipPath, $toDir)
if ($zip->open($zipPath) === true) {
// Check total file size after extraction
$maxSize = empty(self::$maxArcFilesSize)? '' : (string)self::$maxArcFilesSize;
$comp = function_exists('bccomp')? 'bccomp' : 'strnatcmp';
for ($i = 0; $i < $num; $i++) {
$stat = $zip->statIndex($i);
if (strpos((string)$size, 'E') !== false) {
// Cannot handle values exceeding PHP_INT_MAX
throw new Exception(elFinder::ERROR_ARC_MAXSIZE);
if ($comp($size, $maxSize) > 0) {
throw new Exception(elFinder::ERROR_ARC_MAXSIZE);
* Recursive symlinks search
* @param string $path file/dir path
* @author Dmitry (dio) Levashov
protected static function localFindSymlinks($path)
foreach (self::localScandir($path) as $name) {
$p = $path . DIRECTORY_SEPARATOR . $name;
if (is_dir($p) && self::localFindSymlinks($p)) {
/**==================================* abstract methods *====================================**/
/*********************** paths/urls *************************/
* Return parent directory path
* @param string $path file path
* @author Dmitry (dio) Levashov
abstract protected function _dirname($path);
* @param string $path file path
* @author Dmitry (dio) Levashov
abstract protected function _basename($path);
* Join dir name and file name and return full path.
* Some drivers (db) use int as path - so we give to concat path to driver itself
* @param string $dir dir path
* @param string $name file name
* @author Dmitry (dio) Levashov
abstract protected function _joinPath($dir, $name);
* @param string $path file path
* @author Dmitry (dio) Levashov
abstract protected function _normpath($path);
* Return file path related to root dir
* @param string $path file path
* @author Dmitry (dio) Levashov
abstract protected function _relpath($path);
* Convert path related to root dir into real path
* @param string $path rel file path
* @author Dmitry (dio) Levashov
abstract protected function _abspath($path);
* Return fake path started from root dir.
* Required to show path on client side.
* @param string $path file path
* @author Dmitry (dio) Levashov
abstract protected function _path($path);
* Return true if $path is children of $parent
* @param string $path path to check
* @param string $parent parent path
* @author Dmitry (dio) Levashov
abstract protected function _inpath($path, $parent);
* Return stat for given path.
* Stat contains following fields:
* - (int) size file size in b. required
* - (int) ts file modification time in unix time. required
* - (string) mime mimetype. required for folders, others - optionally
* - (bool) read read permissions. required
* - (bool) write write permissions. required
* - (bool) locked is object locked. optionally
* - (bool) hidden is object hidden. optionally
* - (string) alias for symlinks - link target path relative to root path. optionally
* - (string) target for symlinks - link target path. optionally
* If file does not exists - returns empty array or false.
* @param string $path file path
* @author Dmitry (dio) Levashov
abstract protected function _stat($path);
/***************** file stat ********************/
* Return true if path is dir and has at least one childs directory
* @param string $path dir path
* @author Dmitry (dio) Levashov
abstract protected function _subdirs($path);
* Return object width and height
* Ususaly used for images, but can be realize for video etc...
* @param string $path file path
* @param string $mime file mime type
* @author Dmitry (dio) Levashov
abstract protected function _dimensions($path, $mime);
/******************** file/dir content *********************/
* Return files list in directory
* @param string $path dir path
* @author Dmitry (dio) Levashov
abstract protected function _scandir($path);
* Open file and return file pointer