protected function upload($args)
{
$ngReg = '/[\\/\\?*:|"<>]/';
$target = $args['target'];
$volume = $this->volume($target);
$files = isset($args['FILES']['upload']) && is_array($args['FILES']['upload']) ? $args['FILES']['upload'] : array();
$header = empty($args['html']) ? array() : array('header' => 'Content-Type: text/html; charset=utf-8');
$result = array_merge(array('added' => array()), $header);
$paths = $args['upload_path'] ? $args['upload_path'] : array();
$chunk = $args['chunk'] ? $args['chunk'] : '';
$cid = $args['cid'] ? (int) $args['cid'] : '';
$mtimes = $args['mtime'] ? $args['mtime'] : array();
$renames = $hashes = array();
$suffix = '~';
if ($args['renames'] && is_array($args['renames'])) {
$renames = array_flip($args['renames']);
if (is_string($args['suffix']) && !preg_match($ngReg, $args['suffix'])) {
$suffix = $args['suffix'];
}
}
if ($args['hashes'] && is_array($args['hashes'])) {
$hashes = array_flip($args['hashes']);
}
if (!$volume) {
return array_merge(array('error' => $this->error(self::ERROR_UPLOAD, self::ERROR_TRGDIR_NOT_FOUND, '#' . $target)), $header);
}
// regist Shutdown function
$GLOBALS['elFinderTempFiles'] = array();
// if (version_compare(PHP_VERSION, '5.3.0', '>=')) {
// $shutdownfunc = function(){ // <- Parse error on PHP < 5.3 ;-(
// foreach(array_keys($GLOBALS['elFinderTempFiles']) as $f){
// unlink($f);
// }
// };
// } else {
$shutdownfunc = create_function('', '
foreach(array_keys($GLOBALS[\'elFinderTempFiles\']) as $f){
is_file($f) && unlink($f);
}
');
// }
register_shutdown_function($shutdownfunc);
// file extentions table by MIME
$extTable = array_flip(array_unique($volume->getMimeTable()));
if (empty($files)) {
//--- This part is unnecessary code from 2.1.7 START ---//
if (!$args['upload'] && $args['name'] && is_array($args['name'])) {
$error = '';
$result['name'] = array();
foreach ($args['name'] as $_i => $_name) {
if (!$volume->isUploadableByName($_name)) {
$error = $this->error(self::ERROR_UPLOAD_FILE, $_name, self::ERROR_UPLOAD_FILE_MIME);
break;
}
$result['name'][$_i] = preg_replace($ngReg, '_', $_name);
}
if ($error) {
$result['error'] = $error;
return $result;
}
$result = array_merge_recursive($result, $this->ls($args));
if (empty($result['list'])) {
$result['name'] = array();
} else {
// It is using the old(<=2.1.6) JavaScript in the new(>2.1.6) back-end?
unset($result['list']['exists'], $result['list']['hashes']);
$result['name'] = array_merge(array_intersect($result['name'], $result['list']));
}
return $result;
}
//--- This part is unnessesaly code from 2.1.7 END ---//
if (isset($args['upload']) && is_array($args['upload']) && ($tempDir = $this->getTempDir($volume->getTempPath()))) {
$names = array();
foreach ($args['upload'] as $i => $url) {
// check chunked file upload commit
if ($args['chunk']) {
if ($url === 'chunkfail' && $args['mimes'] === 'chunkfail') {
$this->checkChunkedFile(null, $chunk, $cid, $tempDir);
if (preg_match('/^(.+)(\\.\\d+_(\\d+))\\.part$/s', $chunk, $m)) {
$result['warning'] = $this->error(self::ERROR_UPLOAD_FILE, $m[1], self::ERROR_UPLOAD_TRANSFER);
}
return $result;
} else {
$tmpfname = $tempDir . '/' . $args['chunk'];
$files['tmp_name'][$i] = $tmpfname;
$files['name'][$i] = $url;
$files['error'][$i] = 0;
$GLOBALS['elFinderTempFiles'][$tmpfname] = true;
break;
}
}
$tmpfname = $tempDir . DIRECTORY_SEPARATOR . 'ELF_FATCH_' . md5($url . microtime(true));
$_name = '';
// check is data:
if (substr($url, 0, 5) === 'data:') {
list($data, $args['name'][$i]) = $this->parse_data_scheme($url, $extTable);
} else {
$fp = fopen($tmpfname, 'wb');
$data = $this->get_remote_contents($url, 30, 5, 'Mozilla/5.0', $fp);
$_POST['overwrite'] = false;
$_name = preg_replace('~^.*?([^/#?]+)(?:\\?.*)?(?:#.*)?$~', '$1', rawurldecode($url));
// Check `Content-Disposition` response header
if ($data && ($headers = get_headers($url, true)) && !empty($headers['Content-Disposition'])) {
if (preg_match('/filename\\*?=(?:([a-zA-Z0-9_-]+?)\'\')?"?([a-z0-9_.~%-]+)"?/i', $headers['Content-Disposition'], $m)) {
$_name = rawurldecode($m[2]);
if ($m[1] && strtoupper($m[1]) !== 'UTF-8' && function_exists('mb_convert_encoding')) {
$_name = mb_convert_encoding($_name, 'UTF-8', $m[1]);
}
}
}
}
if ($data) {
if (isset($args['name'][$i])) {
$_name = $args['name'][$i];
}
if ($_name) {
$_ext = '';
if (preg_match('/(\\.[a-z0-9]{1,7})$/', $_name, $_match)) {
$_ext = $_match[1];
}
if (is_resource($data) && fclose($data) || file_put_contents($tmpfname, $data)) {
$GLOBALS['elFinderTempFiles'][$tmpfname] = true;
$_name = preg_replace($ngReg, '_', $_name);
list($_a, $_b) = array_pad(explode('.', $_name, 2), 2, '');
if ($_b === '') {
if ($_ext) {
rename($tmpfname, $tmpfname . $_ext);
$tmpfname = $tmpfname . $_ext;
}
$_b = $this->detectFileExtension($tmpfname);
$_name = $_a . $_b;
} else {
$_b = '.' . $_b;
}
if (isset($names[$_name])) {
$_name = $_a . '_' . $names[$_name]++ . $_b;
} else {
$names[$_name] = 1;
}
$files['tmp_name'][$i] = $tmpfname;
$files['name'][$i] = $_name;
$files['error'][$i] = 0;
} else {
unlink($tmpfname);
}
}
}
}
}
if (empty($files)) {
return array_merge(array('error' => $this->error(self::ERROR_UPLOAD, self::ERROR_UPLOAD_NO_FILES)), $header);
}
}
$addedDirs = array();
foreach ($files['name'] as $i => $name) {
if (($error = $files['error'][$i]) > 0) {
$result['warning'] = $this->error(self::ERROR_UPLOAD_FILE, $name, $error == UPLOAD_ERR_INI_SIZE || $error == UPLOAD_ERR_FORM_SIZE ? self::ERROR_UPLOAD_FILE_SIZE : self::ERROR_UPLOAD_TRANSFER);
$this->uploadDebug = 'Upload error code: ' . $error;
break;
}
$tmpname = $files['tmp_name'][$i];
$path = $paths && isset($paths[$i]) ? $paths[$i] : '';
$mtime = isset($mtimes[$i]) ? $mtimes[$i] : 0;
if ($name === 'blob') {
if ($chunk) {
if ($tempDir = $this->getTempDir($volume->getTempPath())) {
list($tmpname, $name) = $this->checkChunkedFile($tmpname, $chunk, $cid, $tempDir, $volume);
if ($tmpname) {
if ($name === false) {
preg_match('/^(.+)(\\.\\d+_(\\d+))\\.part$/s', $chunk, $m);
$result['error'] = $this->error(self::ERROR_UPLOAD_FILE, $m[1], $tmpname);
$result['_chunkfailure'] = true;
$this->uploadDebug = 'Upload error: ' . $tmpname;
} else {
if ($name) {
$result['_chunkmerged'] = basename($tmpname);
$result['_name'] = $name;
$result['_mtime'] = $mtime;
}
}
}
} else {
$result['error'] = $this->error(self::ERROR_UPLOAD_FILE, $chunk, self::ERROR_UPLOAD_TRANSFER);
$this->uploadDebug = 'Upload error: unable open tmp file';
}
return $result;
} else {
// for form clipboard with Google Chrome
$type = $files['type'][$i];
$ext = isset($extTable[$type]) ? '.' . $extTable[$type] : '';
$name = substr(md5(basename($tmpname)), 0, 8) . $ext;
}
}
// do hook function 'upload.presave'
if (!empty($this->listeners['upload.presave'])) {
foreach ($this->listeners['upload.presave'] as $handler) {
call_user_func_array($handler, array(&$path, &$name, $tmpname, $this, $volume));
}
}
if ($mtime) {
touch($tmpname, $mtime);
}
if (($fp = fopen($tmpname, 'rb')) == false) {
$result['warning'] = $this->error(self::ERROR_UPLOAD_FILE, $name, self::ERROR_UPLOAD_TRANSFER);
$this->uploadDebug = 'Upload error: unable open tmp file';
if (!is_uploaded_file($tmpname)) {
if (unlink($tmpname)) {
unset($GLOBALS['elFinderTempFiles'][$tmpfname]);
}
continue;
}
break;
}
$rnres = array();
if ($path !== '' && $path !== $target) {
if ($dir = $volume->dir($path)) {
$_target = $path;
if (!isset($addedDirs[$path])) {
$addedDirs[$path] = true;
$result['added'][] = $dir;
}
} else {
$result['error'] = $this->error(self::ERROR_UPLOAD, self::ERROR_TRGDIR_NOT_FOUND, 'hash@' . $path);
break;
}
} else {
$_target = $target;
// file rename for backup
if (isset($renames[$name])) {
$dir = $volume->realpath($_target);
if (isset($hashes[$name])) {
$hash = $hashes[$name];
} else {
$hash = $volume->getHash($dir, $name);
}
$rnres = $this->rename(array('target' => $hash, 'name' => $volume->uniqueName($dir, $name, $suffix, true, 0)));
if (!empty($rnres['error'])) {
$result['warning'] = $rnres['error'];
break;
}
}
}
if (!$_target || ($file = $volume->upload($fp, $_target, $name, $tmpname, $hashes)) === false) {
$result['warning'] = $this->error(self::ERROR_UPLOAD_FILE, $name, $volume->error());
fclose($fp);
if (!is_uploaded_file($tmpname)) {
if (unlink($tmpname)) {
unset($GLOBALS['elFinderTempFiles'][$tmpname]);
}
continue;
}
break;
}
is_resource($fp) && fclose($fp);
if (!is_uploaded_file($tmpname)) {
clearstatcache();
if (!is_file($tmpname) || unlink($tmpname)) {
unset($GLOBALS['elFinderTempFiles'][$tmpname]);
}
}
$result['added'][] = $file;
if ($rnres) {
$result = array_merge_recursive($result, $rnres);
}
}
if ($GLOBALS['elFinderTempFiles']) {
foreach (array_keys($GLOBALS['elFinderTempFiles']) as $_temp) {
unlink($_temp);
}
}
$result['removed'] = $volume->removed();
if (!empty($args['node'])) {
$result['callback'] = array('node' => $args['node'], 'bind' => 'upload');
}
return $result;
}