: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
return imagegif($image, $filename);
if ($this->options['jpgProgressive']) {
imageinterlace($image, true);
return imagejpeg($image, $filename, $jpgQuality);
return imagewbmp($image, $filename);
return imagepng($image, $filename);
* Output imagick image to file
* @param imagick $img imagick image resource
* @param string $filename The path to save the file to.
* @param string $destformat The Image type to use for $filename
* @param int $jpgQuality JEPG quality (1-100)
protected function imagickImage($img, $filename, $destformat, $jpgQuality = null)
$jpgQuality = $this->options['jpgQuality'];
if ($destformat === 'gif') {
$img->setImageFormat('gif');
} else if ($destformat === 'png') {
$img->setImageFormat('png');
} else if ($destformat === 'jpg') {
$img->setImageFormat('jpeg');
if (strtoupper($img->getImageFormat()) === 'JPEG') {
$img->setImageCompression(imagick::COMPRESSION_JPEG);
$img->setImageCompressionQuality($jpgQuality);
if ($this->options['jpgProgressive']) {
$img->setInterlaceScheme(Imagick::INTERLACE_PLANE);
$orientation = $img->getImageOrientation();
} catch (ImagickException $e) {
$img->setImageOrientation($orientation);
$result = $img->writeImage($filename);
* Assign the proper background to a gd image
* @param resource $image gd image resource
* @param string $bgcolor background color in #rrggbb format
protected function gdImageBackground($image, $bgcolor)
if ($bgcolor === 'transparent') {
imagealphablending($image, false);
imagesavealpha($image, true);
list($r, $g, $b) = sscanf($bgcolor, "#%02x%02x%02x");
$bgcolor1 = imagecolorallocate($image, $r, $g, $b);
imagefill($image, 0, 0, $bgcolor1);
* Prepare variables for exec convert of ImageMagick
* @param string $destformat
* @param array $imageSize
* @throws elFinderAbortException
protected function imageMagickConvertPrepare($path, $destformat, $jpgQuality, $imageSize = null, $mime = null)
if (is_null($imageSize)) {
$imageSize = getimagesize($path);
$mime = $this->mimetype($path);
$srcType = $this->getExtentionByMime($mime, ':');
if (preg_match('/^(?:gif|png|ico)/', $srcType)) {
$cmd = ELFINDER_IDENTIFY_PATH . ' -- ' . escapeshellarg($srcType . $path);
if ($this->procExec($cmd, $o) === 0) {
$ani = preg_split('/(?:\r\n|\n|\r)/', trim($o));
$coalesce = $index = $interlace = '';
$deconstruct = ' +repage';
if ($ani && $destformat !== 'png'/* not createTmb */) {
if (is_null($destformat)) {
$coalesce = ' -coalesce -repage 0x0';
$deconstruct = ' +repage -deconstruct -layers optimize';
if ($srcType === 'ico:') {
foreach ($ani as $_i => $_info) {
if (preg_match('/ (\d+)x(\d+) /', $_info, $m)) {
if ($m[1] == $imageSize[0] && $m[2] == $imageSize[1]) {
$index = '[' . $_i . ']';
if ($imageSize && ($imageSize[2] === IMAGETYPE_JPEG || $imageSize[2] === IMAGETYPE_JPEG2000)) {
$jpgQuality = ' -quality ' . $jpgQuality;
if ($this->options['jpgProgressive']) {
$interlace = ' -interlace Plane';
$quotedPath = escapeshellarg($srcType . $path . $index);
$quotedDstPath = escapeshellarg(($destformat ? ($destformat . ':') : $srcType) . $path);
return compact('ani', 'index', 'coalesce', 'deconstruct', 'jpgQuality', 'quotedPath', 'quotedDstPath', 'interlace');
/*********************** misc *************************/
* Find position of first occurrence of string in a string with multibyte support
* @param string $haystack The string being checked.
* @param string $needle The string to find in haystack.
* @param int $offset The search offset. If it is not specified, 0 is used.
* @author Alexey Sukhotin
protected function stripos($haystack, $needle, $offset = 0)
if (function_exists('mb_stripos')) {
return mb_stripos($haystack, $needle, $offset, 'UTF-8');
} else if (function_exists('mb_strtolower') && function_exists('mb_strpos')) {
return mb_strpos(mb_strtolower($haystack, 'UTF-8'), mb_strtolower($needle, 'UTF-8'), $offset);
return stripos($haystack, $needle, $offset);
* Default serach match method (name match)
* @param String $name Item name
* @param String $query Query word
* @param String $path Item path
* @return bool @return bool
protected function searchMatchName($name, $query, $path)
return $this->stripos($name, $query) !== false;
* Get server side available archivers
* @throws elFinderAbortException
protected function getArchivers($use_cache = true)
$sessionKey = 'archivers';
if (isset($this->options['archivers']) && is_array($this->options['archivers']) && $this->options['archivers']) {
$cache = $this->options['archivers'];
$cache = elFinder::$archivers;
if ($cache = $this->session->get($sessionKey, array())) {
return elFinder::$archivers = $cache;
if ($this->procExec('') === 0) {
$this->procExec(ELFINDER_TAR_PATH . ' --version', $o, $ctar);
$arcs['create']['application/x-tar'] = array('cmd' => ELFINDER_TAR_PATH, 'argc' => '-chf', 'ext' => 'tar');
$arcs['extract']['application/x-tar'] = array('cmd' => ELFINDER_TAR_PATH, 'argc' => '-xf', 'ext' => 'tar', 'toSpec' => '-C ', 'getsize' => array('argc' => '-xvf', 'toSpec' => '--to-stdout|wc -c', 'regex' => '/^.+(?:\r\n|\n|\r)[^\r\n0-9]*([0-9]+)[^\r\n]*$/s', 'replace' => '$1'));
$this->procExec(ELFINDER_GZIP_PATH . ' --version', $o, $c);
$arcs['create']['application/x-gzip'] = array('cmd' => ELFINDER_TAR_PATH, 'argc' => '-czhf', 'ext' => 'tgz');
$arcs['extract']['application/x-gzip'] = array('cmd' => ELFINDER_TAR_PATH, 'argc' => '-xzf', 'ext' => 'tgz', 'toSpec' => '-C ', 'getsize' => array('argc' => '-xvf', 'toSpec' => '--to-stdout|wc -c', 'regex' => '/^.+(?:\r\n|\n|\r)[^\r\n0-9]*([0-9]+)[^\r\n]*$/s', 'replace' => '$1'));
$this->procExec(ELFINDER_BZIP2_PATH . ' --version', $o, $c);
$arcs['create']['application/x-bzip2'] = array('cmd' => ELFINDER_TAR_PATH, 'argc' => '-cjhf', 'ext' => 'tbz');
$arcs['extract']['application/x-bzip2'] = array('cmd' => ELFINDER_TAR_PATH, 'argc' => '-xjf', 'ext' => 'tbz', 'toSpec' => '-C ', 'getsize' => array('argc' => '-xvf', 'toSpec' => '--to-stdout|wc -c', 'regex' => '/^.+(?:\r\n|\n|\r)[^\r\n0-9]*([0-9]+)[^\r\n]*$/s', 'replace' => '$1'));
$this->procExec(ELFINDER_XZ_PATH . ' --version', $o, $c);
$arcs['create']['application/x-xz'] = array('cmd' => ELFINDER_TAR_PATH, 'argc' => '-cJhf', 'ext' => 'xz');
$arcs['extract']['application/x-xz'] = array('cmd' => ELFINDER_TAR_PATH, 'argc' => '-xJf', 'ext' => 'xz', 'toSpec' => '-C ', 'getsize' => array('argc' => '-xvf', 'toSpec' => '--to-stdout|wc -c', 'regex' => '/^.+(?:\r\n|\n|\r)[^\r\n0-9]*([0-9]+)[^\r\n]*$/s', 'replace' => '$1'));
$this->procExec(ELFINDER_ZIP_PATH . ' -h', $o, $c);
$arcs['create']['application/zip'] = array('cmd' => ELFINDER_ZIP_PATH, 'argc' => '-r9 -q', 'ext' => 'zip');
$this->procExec(ELFINDER_UNZIP_PATH . ' --help', $o, $c);
$arcs['extract']['application/zip'] = array('cmd' => ELFINDER_UNZIP_PATH, 'argc' => '-q', 'ext' => 'zip', 'toSpec' => '-d ', 'getsize' => array('argc' => '-Z -t', 'regex' => '/^.+?,\s?([0-9]+).+$/', 'replace' => '$1'));
$this->procExec(ELFINDER_RAR_PATH, $o, $c);
if ($c == 0 || $c == 7) {
$arcs['create']['application/x-rar'] = array('cmd' => ELFINDER_RAR_PATH, 'argc' => 'a -inul' . (defined('ELFINDER_RAR_MA4') && ELFINDER_RAR_MA4? ' -ma4' : '') . ' --', 'ext' => 'rar');
$this->procExec(ELFINDER_UNRAR_PATH, $o, $c);
if ($c == 0 || $c == 7) {
$arcs['extract']['application/x-rar'] = array('cmd' => ELFINDER_UNRAR_PATH, 'argc' => 'x -y', 'ext' => 'rar', 'toSpec' => '', 'getsize' => array('argc' => 'l', 'regex' => '/^.+(?:\r\n|\n|\r)(?:(?:[^\r\n0-9]+[0-9]+[^\r\n0-9]+([0-9]+)[^\r\n]+)|(?:[^\r\n0-9]+([0-9]+)[^\r\n0-9]+[0-9]+[^\r\n]*))$/s', 'replace' => '$1'));
$this->procExec(ELFINDER_7Z_PATH, $o, $c);
$arcs['create']['application/x-7z-compressed'] = array('cmd' => ELFINDER_7Z_PATH, 'argc' => 'a --', 'ext' => '7z');
$arcs['extract']['application/x-7z-compressed'] = array('cmd' => ELFINDER_7Z_PATH, 'argc' => 'x -y', 'ext' => '7z', 'toSpec' => '-o', 'getsize' => array('argc' => 'l', 'regex' => '/^.+(?:\r\n|\n|\r)[^\r\n0-9]+([0-9]+)[^\r\n]+$/s', 'replace' => '$1'));
if (empty($arcs['create']['application/zip'])) {
$arcs['create']['application/zip'] = array('cmd' => ELFINDER_7Z_PATH, 'argc' => 'a -tzip --', 'ext' => 'zip');
if (empty($arcs['extract']['application/zip'])) {
$arcs['extract']['application/zip'] = array('cmd' => ELFINDER_7Z_PATH, 'argc' => 'x -tzip -y', 'ext' => 'zip', 'toSpec' => '-o', 'getsize' => array('argc' => 'l', 'regex' => '/^.+(?:\r\n|\n|\r)[^\r\n0-9]+([0-9]+)[^\r\n]+$/s', 'replace' => '$1'));
if (empty($arcs['create']['application/x-tar'])) {
$arcs['create']['application/x-tar'] = array('cmd' => ELFINDER_7Z_PATH, 'argc' => 'a -ttar --', 'ext' => 'tar');
if (empty($arcs['extract']['application/x-tar'])) {
$arcs['extract']['application/x-tar'] = array('cmd' => ELFINDER_7Z_PATH, 'argc' => 'x -ttar -y', 'ext' => 'tar', 'toSpec' => '-o', 'getsize' => array('argc' => 'l', 'regex' => '/^.+(?:\r\n|\n|\r)[^\r\n0-9]+([0-9]+)[^\r\n]+$/s', 'replace' => '$1'));
if (substr(PHP_OS, 0, 3) === 'WIN' && empty($arcs['extract']['application/x-rar'])) {
$arcs['extract']['application/x-rar'] = array('cmd' => ELFINDER_7Z_PATH, 'argc' => 'x -trar -y', 'ext' => 'rar', 'toSpec' => '-o', 'getsize' => array('argc' => 'l', 'regex' => '/^.+(?:\r\n|\n|\r)[^\r\n0-9]+([0-9]+)[^\r\n]+$/s', 'replace' => '$1'));
// Use PHP ZipArchive Class
if (class_exists('ZipArchive', false)) {
if (empty($arcs['create']['application/zip'])) {
$arcs['create']['application/zip'] = array('cmd' => 'phpfunction', 'argc' => array('self', 'zipArchiveZip'), 'ext' => 'zip');
if (empty($arcs['extract']['application/zip'])) {
$arcs['extract']['application/zip'] = array('cmd' => 'phpfunction', 'argc' => array('self', 'zipArchiveUnzip'), 'ext' => 'zip');
$this->session->set($sessionKey, $arcs);
return elFinder::$archivers = $arcs;
* Resolve relative / (Unix-like)absolute path
* @param string $path target path
* @param string $base base path
protected function getFullPath($path, $base)
$separator = $this->separator;
$systemroot = $this->systemRoot;
if ($base[0] === $separator && substr($base, 0, strlen($systemroot)) !== $systemroot) {
$base = $systemroot . substr($base, 1);
if ($base !== $systemroot) {
$base = rtrim($base, $separator);
$sepquoted = preg_quote($separator, '#');
$path = preg_replace('#' . $sepquoted . '+#', $separator, $path); // '#/+#'
$path = preg_replace('#(?<=^|' . $sepquoted . ')\.' . $sepquoted . '#', '', $path); // '#(?<=^|/)\./#'
if ($path === '') return $base;
// join $base to $path if $path start `../`
if (substr($path, 0, 3) === '..' . $separator) {
$path = $base . $separator . $path;
$normreg = '#(' . $sepquoted . ')[^' . $sepquoted . ']+' . $sepquoted . '\.\.' . $sepquoted . '#'; // '#(/)[^\/]+/\.\./#'
while (preg_match($normreg, $path)) {
$path = preg_replace($normreg, '$1', $path, 1);
if ($path !== $systemroot) {
$path = rtrim($path, $separator);
// discard the surplus `../`
$path = str_replace('..' . $separator, '', $path);
if ($path[0] === $separator || strpos($path, $systemroot) === 0) {
$preg_separator = '#' . $sepquoted . '#';
// Relative path from 'Here'
if (substr($path, 0, 2) === '.' . $separator || $path[0] !== '.') {
$arrn = preg_split($preg_separator, $path, -1, PREG_SPLIT_NO_EMPTY);
array_unshift($arrn, '.');
$arrn[0] = rtrim($base, $separator);
return join($separator, $arrn);
* Remove directory recursive on local file system
* @param string $dir Target dirctory path
* @throws elFinderAbortException
public function rmdirRecursive($dir)
return self::localRmdirRecursive($dir);
* 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 makeArchive($dir, $files, $name, $arc)
if ($arc['cmd'] === 'phpfunction') {
if (is_callable($arc['argc'])) {
call_user_func_array($arc['argc'], array($dir, $files, $name));
foreach ($files as $i => $file) {
$files[$i] = '.' . DIRECTORY_SEPARATOR . basename($file);
$files = array_map('escapeshellarg', $files);
// The zip command accepts the "-" at the beginning of the file name as a command switch,
// and can't use '--' before archive name, so add "./" to name for security reasons.
if ($arc['ext'] === 'zip' && strpos($arc['argc'], '-tzip') === false) {
$cmd = $arc['cmd'] . ' ' . $arc['argc'] . ' ' . $prefix . escapeshellarg($name) . ' ' . $switch . implode(' ', $files);
$this->procExec($cmd, $o, $c, $err_out, $dir);
$path = $dir . DIRECTORY_SEPARATOR . $name;
return file_exists($path) ? $path : false;
* @param string $path archive path
* @param array $arc archiver command and arguments (same as in $this->archivers)
* @param bool|string $mode bool: remove archive ( unlink($path) ) | string: extract to directory
* @throws elFinderAbortException
* @author Dmitry (dio) Levashov
* @author Alexey Sukhotin
protected function unpackArchive($path, $arc, $mode = true)
if ($arc['cmd'] === 'phpfunction') {
if (is_callable($arc['argc'])) {
call_user_func_array($arc['argc'], array($path, $dir));
if (!$chdir || chdir($dir)) {
if (!empty($arc['getsize'])) {
// Check total file size after extraction
$getsize = $arc['getsize'];
if (is_array($getsize) && !empty($getsize['regex']) && !empty($getsize['replace'])) {
$cmd = $arc['cmd'] . ' ' . $getsize['argc'] . ' ' . escapeshellarg($path) . (!empty($getsize['toSpec'])? (' ' . $getsize['toSpec']): '');
$this->procExec($cmd, $o, $c);
$size = preg_replace($getsize['regex'], $getsize['replace'], trim($o));
$comp = function_exists('bccomp')? 'bccomp' : 'strnatcmp';
if (!empty($this->options['maxArcFilesSize'])) {
if ($comp($size, (string)$this->options['maxArcFilesSize']) > 0) {
throw new Exception(elFinder::ERROR_ARC_MAXSIZE);
$cmd = $arc['cmd'] . ' ' . $arc['argc'] . ' ' . escapeshellarg(basename($path));
$cmd = $arc['cmd'] . ' ' . $arc['argc'] . ' ' . escapeshellarg($path) . ' ' . $arc['toSpec'] . escapeshellarg($dir);
$this->procExec($cmd, $o, $c);
$remove && unlink($path);