: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
public static function getStreamByUrl($data, $redirectLimit = 5)
if (isset($data['target'])) {
'url' => $data['target'],
'headers' => isset($data['headers']) ? $data['headers'] : array(),
'postData' => isset($data['postData']) ? $data['postData'] : array(),
if ($data['cnt'] > $redirectLimit) {
$headers = $data['headers'];
$url = parse_url($dlurl);
$url['scheme'] = strtolower($url['scheme']);
if (!isset($url['port']) && isset($ports[$url['scheme']])) {
$url['port'] = $ports[$url['scheme']];
if (!isset($url['port'])) {
foreach ($data['cookies'] as $d => $c) {
if (strpos($url['host'], $d) !== false) {
$transport = ($url['scheme'] === 'https') ? 'ssl' : 'tcp';
$query = isset($url['query']) ? '?' . $url['query'] : '';
if (!($stream = stream_socket_client($transport . '://' . $url['host'] . ':' . $url['port']))) {
if (!empty($data['postData'])) {
if (is_array($data['postData'])) {
$body = http_build_query($data['postData']);
$body = $data['postData'];
$sends[] = "$method {$url['path']}{$query} HTTP/1.1";
$sends[] = "Host: {$url['host']}";
foreach ($headers as $header) {
$sends[] = trim($header, "\r\n");
$sends[] = 'Connection: Close';
$sends[] = 'Cookie: ' . implode('; ', $cookies);
if ($method === 'POST') {
$sends[] = 'Content-Type: application/x-www-form-urlencoded';
$sends[] = 'Content-Length: ' . strlen($body);
$sends[] = "\r\n" . $body;
stream_set_timeout($stream, 300);
fputs($stream, join("\r\n", $sends) . "\r\n");
while (($res = trim(fgets($stream))) !== '') {
if (preg_match('/^Location: (.+)$/i', $res, $m)) {
if (strpos($res, 'Set-Cookie:') === 0) {
if (preg_match('/^Set-Cookie:(.+)(?:domain=\s*([^ ;]+))?/i', $res, $c1)) {
if (preg_match('/([^ ]+=[^;]+)/', $c1[1], $c2)) {
$data['cookies'][$domain] = $c2[1];
if (preg_match('/^(Accept-Ranges|Content-Range): bytes/i', $res)) {
elFinder::$seekableUrlFps[(int)$stream] = true;
return self::getStreamByUrl($data, $redirectLimit);
* Gets the fetch cookie file for curl.
* @return string The fetch cookie file.
public function getFetchCookieFile()
if ($tmpDir = $this->getTempDir()) {
$file = $tmpDir . '/.elFinderAnonymousCookie';
* Call curl_exec() with supported redirect on `safe_mode` or `open_basedir`
public static function curlExec($curl, $options = array(), $headers = array(), $postData = array())
$followLocation = (!ini_get('safe_mode') && !ini_get('open_basedir'));
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
curl_setopt_array($curl, $options);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
$result = curl_exec($curl);
if (!$followLocation && $redirect = curl_getinfo($curl, CURLINFO_REDIRECT_URL)) {
if ($stream = self::getStreamByUrl(array('target' => $redirect, 'headers' => $headers, 'postData' => $postData))) {
$result = stream_get_contents($stream);
throw new \Exception('curl_exec() failed: ' . curl_error($curl));
throw new \Exception('curl_exec(): empty response');
* Return bool that current request was aborted by client side
public static function aborted()
if ($file = self::$abortCheckFile) {
(version_compare(PHP_VERSION, '5.3.0') >= 0) ? clearstatcache(true, $file) : clearstatcache();
list($ptn) = explode('elfreq', $file);
self::GlobGC($ptn . 'elfreq*', 43200);
* Return array ["name without extention", "extention"] by filename
public static function splitFileExtention($name)
if (preg_match('/^(.+?)?\.((?:tar\.(?:gz|bz|bz2|z|lzo))|cpio\.gz|ps\.gz|xcf\.(?:gz|bz2)|[a-z0-9]{1,10})$/i', $name, $m)) {
return array((string)$m[1], $m[2]);
* Gets the memory size by imageinfo.
* @param array $imgInfo array that result of getimagesize()
* @return integer The memory size by imageinfo.
public static function getMemorySizeByImageInfo($imgInfo)
$bits = isset($imgInfo['bits']) ? $imgInfo['bits'] : 24;
$channels = isset($imgInfo['channels']) ? $imgInfo['channels'] : 3;
return round(($width * $height * $bits * $channels / 8 + Pow(2, 16)) * 1.65);
* Auto expand memory for GD processing
* @param array $imgInfos The image infos
public static function expandMemoryForGD($imgInfos)
if (elFinder::$memoryLimitGD != 0 && $imgInfos && is_array($imgInfos)) {
if (!is_array($imgInfos[0])) {
$imgInfos = array($imgInfos);
$limit = self::getIniBytes('', elFinder::$memoryLimitGD);
$memLimit = self::getIniBytes('memory_limit');
foreach ($imgInfos as $info) {
$needs += self::getMemorySizeByImageInfo($info);
$needs += memory_get_usage();
if ($needs > $memLimit && ($limit == -1 || $limit > $needs)) {
ini_set('memory_limit', $needs);
* Decontaminate of filename
* @param String $name The name
* @return String Decontaminated filename
public static function filenameDecontaminate($name)
// Directory traversal defense
if (DIRECTORY_SEPARATOR === '\\') {
$name = str_replace('\\', '/', $name);
$parts = explode('/', trim($name, '/'));
$name = array_pop($parts);
* @param string $command command line
* @param string $output stdout strings
* @param int $return_var process exit code
* @param string $error_output stderr strings
* @throws elFinderAbortException
* @author Alexey Sukhotin
public static function procExec($command, &$output = '', &$return_var = -1, &$error_output = '', $cwd = null)
if ($allowed = function_exists('proc_open')) {
if ($disabled = ini_get('disable_functions')) {
$funcs = array_map('trim', explode(',', $disabled));
$allowed = !in_array('proc_open', $funcs);
0 => array("pipe", "r"), // stdin
1 => array("pipe", "w"), // stdout
2 => array("pipe", "w") // stderr
$process = proc_open($command, $descriptorspec, $pipes, $cwd, null);
if (is_resource($process)) {
stream_set_blocking($pipes[1], 0);
stream_set_blocking($pipes[2], 0);
while (feof($pipes[1]) === false || feof($pipes[2]) === false) {
elFinder::extendTimeLimit();
$read = array($pipes[1], $pipes[2]);
$ret = stream_select($read, $write, $except, 1);
foreach ($read as $sock) {
if ($sock === $pipes[1]) {
$tmpout .= fread($sock, 4096);
} else if ($sock === $pipes[2]) {
$tmperr .= fread($sock, 4096);
$return_var = proc_close($process);
/***************************************************************************/
/***************************************************************************/
* Get command name of binded "commandName.subName"
protected static function getCmdOfBind($cmd)
list($ret) = explode('.', $cmd);
* Add subName to commandName
protected static function addSubToBindName($cmd, $sub)
return $cmd . '.' . trim($sub);
* Remove a file if connection is disconnected
public static function rmFileInDisconnected($file)
(connection_aborted() || connection_status() !== CONNECTION_NORMAL) && is_file($file) && unlink($file);
* Call back function on shutdown
* - delete files in $GLOBALS['elFinderTempFiles']
public static function onShutdown()
self::$abortCheckFile = null;
if (!empty($GLOBALS['elFinderTempFps'])) {
foreach (array_keys($GLOBALS['elFinderTempFps']) as $fp) {
is_resource($fp) && fclose($fp);
if (!empty($GLOBALS['elFinderTempFiles'])) {
foreach (array_keys($GLOBALS['elFinderTempFiles']) as $f) {
is_file($f) && is_writable($f) && unlink($f);
* Garbage collection with glob
public static function GlobGC($pattern, $time)
foreach (glob($pattern) as $file) {
(filemtime($file) < ($now - $time)) && unlink($file);
* Custom exception class for aborting request
class elFinderAbortException extends Exception
class elFinderTriggerException extends Exception