4 * elFinder - file manager for web.
8 * @author Dmitry (dio) Levashov
9 * @author Troex Nevelin
10 * @author Alexey Sukhotin
19 protected $version = '2.0';
22 * Storages (root dirs)
26 protected $volumes = array();
29 * Mounted volumes count
30 * Required to create unique volume id
34 public static $volumesCnt = 1;
37 * Default root (storage)
39 * @var elFinderStorageDriver
41 protected $default = null;
44 * Commands and required arguments list
48 protected $commands = array(
49 'open' => array('target' => false, 'tree' => false, 'init' => false, 'mimes' => false),
50 'ls' => array('target' => true, 'mimes' => false),
51 'tree' => array('target' => true),
52 'parents' => array('target' => true),
53 'tmb' => array('targets' => true),
54 'file' => array('target' => true, 'download' => false),
55 'size' => array('targets' => true),
56 'mkdir' => array('target' => true, 'name' => true),
57 'mkfile' => array('target' => true, 'name' => true, 'mimes' => false),
58 'rm' => array('targets' => true),
59 'rename' => array('target' => true, 'name' => true, 'mimes' => false),
60 'duplicate' => array('targets' => true, 'suffix' => false),
61 'paste' => array('dst' => true, 'targets' => true, 'cut' => false, 'mimes' => false),
62 'upload' => array('target' => true, 'FILES' => true, 'mimes' => false, 'html' => false),
63 'get' => array('target' => true),
64 'put' => array('target' => true, 'content' => '', 'mimes' => false),
65 'archive' => array('targets' => true, 'type' => true, 'mimes' => false),
66 'extract' => array('target' => true, 'mimes' => false),
67 'search' => array('q' => true, 'mimes' => false),
68 'info' => array('targets' => true),
69 'dim' => array('target' => true),
70 'resize' => array('target' => true, 'width' => true, 'height' => true, 'mode' => false, 'x' => false, 'y' => false, 'degree' => false)
78 protected $listeners = array();
81 * script work time for debug
87 * Is elFinder init correctly?
91 protected $loaded = false;
93 * Send debug to client?
97 protected $debug = false;
100 * undocumented class variable
104 protected $uploadDebug = '';
107 * Errors from not mounted volumes
111 public $mountErrors = array();
114 const ERROR_UNKNOWN
= 'errUnknown';
115 const ERROR_UNKNOWN_CMD
= 'errUnknownCmd';
116 const ERROR_CONF
= 'errConf';
117 const ERROR_CONF_NO_JSON
= 'errJSON';
118 const ERROR_CONF_NO_VOL
= 'errNoVolumes';
119 const ERROR_INV_PARAMS
= 'errCmdParams';
120 const ERROR_OPEN
= 'errOpen';
121 const ERROR_DIR_NOT_FOUND
= 'errFolderNotFound';
122 const ERROR_FILE_NOT_FOUND
= 'errFileNotFound'; // 'File not found.'
123 const ERROR_TRGDIR_NOT_FOUND
= 'errTrgFolderNotFound'; // 'Target folder "$1" not found.'
124 const ERROR_NOT_DIR
= 'errNotFolder';
125 const ERROR_NOT_FILE
= 'errNotFile';
126 const ERROR_PERM_DENIED
= 'errPerm';
127 const ERROR_LOCKED
= 'errLocked'; // '"$1" is locked and can not be renamed, moved or removed.'
128 const ERROR_EXISTS
= 'errExists'; // 'File named "$1" already exists.'
129 const ERROR_INVALID_NAME
= 'errInvName'; // 'Invalid file name.'
130 const ERROR_MKDIR
= 'errMkdir';
131 const ERROR_MKFILE
= 'errMkfile';
132 const ERROR_RENAME
= 'errRename';
133 const ERROR_COPY
= 'errCopy';
134 const ERROR_MOVE
= 'errMove';
135 const ERROR_COPY_FROM
= 'errCopyFrom';
136 const ERROR_COPY_TO
= 'errCopyTo';
137 const ERROR_COPY_ITSELF
= 'errCopyInItself';
138 const ERROR_REPLACE
= 'errReplace'; // 'Unable to replace "$1".'
139 const ERROR_RM
= 'errRm'; // 'Unable to remove "$1".'
140 const ERROR_RM_SRC
= 'errRmSrc'; // 'Unable remove source file(s)'
141 const ERROR_UPLOAD
= 'errUpload'; // 'Upload error.'
142 const ERROR_UPLOAD_FILE
= 'errUploadFile'; // 'Unable to upload "$1".'
143 const ERROR_UPLOAD_NO_FILES
= 'errUploadNoFiles'; // 'No files found for upload.'
144 const ERROR_UPLOAD_TOTAL_SIZE
= 'errUploadTotalSize'; // 'Data exceeds the maximum allowed size.'
145 const ERROR_UPLOAD_FILE_SIZE
= 'errUploadFileSize'; // 'File exceeds maximum allowed size.'
146 const ERROR_UPLOAD_FILE_MIME
= 'errUploadMime'; // 'File type not allowed.'
147 const ERROR_UPLOAD_TRANSFER
= 'errUploadTransfer'; // '"$1" transfer error.'
148 // const ERROR_ACCESS_DENIED = 'errAccess';
149 const ERROR_NOT_REPLACE
= 'errNotReplace'; // Object "$1" already exists at this location and can not be replaced with object of another type.
150 const ERROR_SAVE
= 'errSave';
151 const ERROR_EXTRACT
= 'errExtract';
152 const ERROR_ARCHIVE
= 'errArchive';
153 const ERROR_NOT_ARCHIVE
= 'errNoArchive';
154 const ERROR_ARCHIVE_TYPE
= 'errArcType';
155 const ERROR_ARC_SYMLINKS
= 'errArcSymlinks';
156 const ERROR_ARC_MAXSIZE
= 'errArcMaxSize';
157 const ERROR_RESIZE
= 'errResize';
158 const ERROR_UNSUPPORT_TYPE
= 'errUsupportType';
159 const ERROR_NOT_UTF8_CONTENT
= 'errNotUTF8Content';
164 * @param array elFinder and roots configurations
166 * @author Dmitry (dio) Levashov
168 public function __construct($opts) {
170 $this->time
= $this->utime();
171 $this->debug
= (isset($opts['debug']) && $opts['debug'] ?
true : false);
173 setlocale(LC_ALL
, !empty($opts['locale']) ?
$opts['locale'] : 'en_US.UTF-8');
175 // bind events listeners
176 if (!empty($opts['bind']) && is_array($opts['bind'])) {
177 foreach ($opts['bind'] as $cmd => $handler) {
178 $this->bind($cmd, $handler);
183 if (isset($opts['roots']) && is_array($opts['roots'])) {
185 foreach ($opts['roots'] as $i => $o) {
186 $class = 'elFinderVolume'.(isset($o['driver']) ?
$o['driver'] : '');
188 if (class_exists($class)) {
189 $volume = new $class();
191 if ($volume->mount($o)) {
192 // unique volume id (ends on "_") - used as prefix to files hash
195 $this->volumes
[$id] = $volume;
196 if (!$this->default && $volume->isReadable()) {
197 $this->default = $this->volumes
[$id];
200 $this->mountErrors
[] = 'Driver "'.$class.'" : '.implode(' ', $volume->error());
203 $this->mountErrors
[] = 'Driver "'.$class.'" does not exists';
207 // if at least one redable volume - ii desu >_<
208 $this->loaded
= !empty($this->default);
212 * Return true if fm init correctly
215 * @author Dmitry (dio) Levashov
217 public function loaded() {
218 return $this->loaded
;
222 * Return version (api) number
225 * @author Dmitry (dio) Levashov
227 public function version() {
228 return $this->version
;
232 * Add handler to elFinder command
234 * @param string command name
235 * @param string|array callback name or array(object, method)
237 * @author Dmitry (dio) Levashov
239 public function bind($cmd, $handler) {
240 $cmds = array_map('trim', explode(' ', $cmd));
242 foreach ($cmds as $cmd) {
244 if (!isset($this->listeners
[$cmd])) {
245 $this->listeners
[$cmd] = array();
248 if ((is_array($handler) && count($handler) == 2 && is_object($handler[0]) && method_exists($handler[0], $handler[1]))
249 ||
function_exists($handler)) {
250 $this->listeners
[$cmd][] = $handler;
259 * Remove event (command exec) handler
261 * @param string command name
262 * @param string|array callback name or array(object, method)
264 * @author Dmitry (dio) Levashov
266 public function unbind($cmd, $handler) {
267 if (!empty($this->listeners
[$cmd])) {
268 foreach ($this->listeners
[$cmd] as $i => $h) {
269 if ($h === $handler) {
270 unset($this->listeners
[$cmd][$i]);
279 * Return true if command exists
281 * @param string command name
283 * @author Dmitry (dio) Levashov
285 public function commandExists($cmd) {
286 return $this->loaded
&& isset($this->commands
[$cmd]) && method_exists($this, $cmd);
290 * Return command required arguments info
292 * @param string command name
294 * @author Dmitry (dio) Levashov
296 public function commandArgsList($cmd) {
297 return $this->commandExists($cmd) ?
$this->commands
[$cmd] : array();
301 * Exec command and return result
303 * @param string $cmd command name
304 * @param array $args command arguments
306 * @author Dmitry (dio) Levashov
308 public function exec($cmd, $args) {
310 if (!$this->loaded
) {
311 return array('error' => $this->error(self
::ERROR_CONF
, self
::ERROR_CONF_NO_VOL
));
314 if (!$this->commandExists($cmd)) {
315 return array('error' => $this->error(self
::ERROR_UNKNOWN_CMD
));
318 if (!empty($args['mimes']) && is_array($args['mimes'])) {
319 foreach ($this->volumes
as $id => $v) {
320 $this->volumes
[$id]->setMimesFilter($args['mimes']);
324 $result = $this->$cmd($args);
326 if (isset($result['removed'])) {
327 foreach ($this->volumes
as $volume) {
328 $result['removed'] = array_merge($result['removed'], $volume->removed());
329 $volume->resetRemoved();
333 // call handlers for this command
334 if (!empty($this->listeners
[$cmd])) {
335 foreach ($this->listeners
[$cmd] as $handler) {
336 if ((is_array($handler) && $handler[0]->{$handler[1]}($cmd, $result, $args, $this))
337 ||
(!is_array($handler) && $handler($cmd, $result, $args, $this))) {
338 // handler return true to force sync client after command completed
339 $result['sync'] = true;
344 // replace removed files info with removed files hashes
345 if (!empty($result['removed'])) {
347 foreach ($result['removed'] as $file) {
348 $removed[] = $file['hash'];
350 $result['removed'] = array_unique($removed);
352 // remove hidden files and filter files by mimetypes
353 if (!empty($result['added'])) {
354 $result['added'] = $this->filter($result['added']);
356 // remove hidden files and filter files by mimetypes
357 if (!empty($result['changed'])) {
358 $result['changed'] = $this->filter($result['changed']);
361 if ($this->debug ||
!empty($args['debug'])) {
362 $result['debug'] = array(
363 'connector' => 'php',
364 'phpver' => PHP_VERSION
,
365 'time' => $this->utime() - $this->time
,
366 'memory' => (function_exists('memory_get_peak_usage') ?
ceil(memory_get_peak_usage()/1024).'Kb / ' : '').ceil(memory_get_usage()/1024).'Kb / '.ini_get('memory_limit'),
367 'upload' => $this->uploadDebug
,
368 'volumes' => array(),
369 'mountErrors' => $this->mountErrors
372 foreach ($this->volumes
as $id => $volume) {
373 $result['debug']['volumes'][] = $volume->debug();
377 foreach ($this->volumes
as $volume) {
385 * Return file real path
387 * @param string $hash file hash
389 * @author Dmitry (dio) Levashov
391 public function realpath($hash) {
392 if (($volume = $this->volume($hash)) == false) {
395 return $volume->realpath($hash);
398 /***************************************************************************/
400 /***************************************************************************/
403 * Normalize error messages
406 * @author Dmitry (dio) Levashov
408 public function error() {
411 foreach (func_get_args() as $msg) {
412 if (is_array($msg)) {
413 $errors = array_merge($errors, $msg);
419 return count($errors) ?
$errors : array(self
::ERROR_UNKNOWN
);
424 * Return array with following elements
425 * - cwd - opened dir info
426 * - files - opened dir content [and dirs tree if $args[tree]]
427 * - api - api version (if $args[init])
428 * - uplMaxSize - if $args[init]
429 * - error - on failed
431 * @param array command arguments
433 * @author Dmitry (dio) Levashov
435 protected function open($args) {
436 $target = $args['target'];
437 $init = !empty($args['init']);
438 $tree = !empty($args['tree']);
439 $volume = $this->volume($target);
440 $cwd = $volume ?
$volume->dir($target, true) : false;
441 $hash = $init ?
'default folder' : '#'.$target;
443 // on init request we can get invalid dir hash -
444 // dir which can not be opened now, but remembered by client,
445 // so open default dir
446 if ((!$cwd ||
!$cwd['read']) && $init) {
447 $volume = $this->default;
448 $cwd = $volume->dir($volume->defaultPath(), true);
452 return array('error' => $this->error(self
::ERROR_OPEN
, $hash, self
::ERROR_DIR_NOT_FOUND
));
455 return array('error' => $this->error(self
::ERROR_OPEN
, $hash, self
::ERROR_PERM_DENIED
));
462 foreach ($this->volumes
as $id => $v) {
464 if (($tree = $v->tree('', 0, $cwd['hash'])) != false) {
465 $files = array_merge($files, $tree);
470 // get current working directory files list and add to $files if not exists in it
471 if (($ls = $volume->scandir($cwd['hash'])) === false) {
472 return array('error' => $this->error(self
::ERROR_OPEN
, $cwd['name'], $volume->error()));
475 foreach ($ls as $file) {
476 if (!in_array($file, $files)) {
483 'options' => $volume->options($cwd['hash']),
487 if (!empty($args['init'])) {
488 $result['api'] = $this->version
;
489 $result['uplMaxSize'] = ini_get('upload_max_filesize');
496 * Return dir files names list
498 * @param array command arguments
500 * @author Dmitry (dio) Levashov
502 protected function ls($args) {
503 $target = $args['target'];
505 if (($volume = $this->volume($target)) == false
506 ||
($list = $volume->ls($target)) === false) {
507 return array('error' => $this->error(self
::ERROR_OPEN
, '#'.$target));
509 return array('list' => $list);
513 * Return subdirs for required directory
515 * @param array command arguments
517 * @author Dmitry (dio) Levashov
519 protected function tree($args) {
520 $target = $args['target'];
522 if (($volume = $this->volume($target)) == false
523 ||
($tree = $volume->tree($target)) == false) {
524 return array('error' => $this->error(self
::ERROR_OPEN
, '#'.$target));
527 return array('tree' => $tree);
531 * Return parents dir for required directory
533 * @param array command arguments
535 * @author Dmitry (dio) Levashov
537 protected function parents($args) {
538 $target = $args['target'];
540 if (($volume = $this->volume($target)) == false
541 ||
($tree = $volume->parents($target)) == false) {
542 return array('error' => $this->error(self
::ERROR_OPEN
, '#'.$target));
545 return array('tree' => $tree);
549 * Return new created thumbnails list
551 * @param array command arguments
553 * @author Dmitry (dio) Levashov
555 protected function tmb($args) {
557 $result = array('images' => array());
558 $targets = $args['targets'];
560 foreach ($targets as $target) {
561 if (($volume = $this->volume($target)) != false
562 && (($tmb = $volume->tmb($target)) != false)) {
563 $result['images'][$target] = $tmb;
570 * Required to output file in browser when volume URL is not set
571 * Return array contains opened file pointer, root itself and required headers
573 * @param array command arguments
575 * @author Dmitry (dio) Levashov
577 protected function file($args) {
578 $target = $args['target'];
579 $download = !empty($args['download']);
580 $h403 = 'HTTP/1.x 403 Access Denied';
581 $h404 = 'HTTP/1.x 404 Not Found';
583 if (($volume = $this->volume($target)) == false) {
584 return array('error' => 'File not found', 'header' => $h404, 'raw' => true);
587 if (($file = $volume->file($target)) == false) {
588 return array('error' => 'File not found', 'header' => $h404, 'raw' => true);
591 if (!$file['read']) {
592 return array('error' => 'Access denied', 'header' => $h403, 'raw' => true);
595 if (($fp = $volume->open($target)) == false) {
596 return array('error' => 'File not found', 'header' => $h404, 'raw' => true);
600 $disp = 'attachment';
601 $mime = 'application/octet-stream';
603 $disp = preg_match('/^(image|text)/i', $file['mime']) ||
$file['mime'] == 'application/x-shockwave-flash'
606 $mime = $file['mime'];
609 $filenameEncoded = rawurlencode($file['name']);
610 if (strpos($filenameEncoded, '%') === false) { // ASCII only
611 $filename = 'filename="'.$file['name'].'"';
613 $ua = $_SERVER["HTTP_USER_AGENT"];
614 if (preg_match('/MSIE [4-8]/', $ua)) { // IE < 9 do not support RFC 6266 (RFC 2231/RFC 5987)
615 $filename = 'filename="'.$filenameEncoded.'"';
616 } else { // RFC 6266 (RFC 2231/RFC 5987)
617 $filename = 'filename*=UTF-8\'\''.$filenameEncoded;
626 'Content-Type: '.$mime,
627 'Content-Disposition: '.$disp.'; '.$filename,
628 'Content-Location: '.$file['name'],
629 'Content-Transfer-Encoding: binary',
630 'Content-Length: '.$file['size'],
638 * Count total files size
640 * @param array command arguments
642 * @author Dmitry (dio) Levashov
644 protected function size($args) {
647 foreach ($args['targets'] as $target) {
648 if (($volume = $this->volume($target)) == false
649 ||
($file = $volume->file($target)) == false
651 return array('error' => $this->error(self
::ERROR_OPEN
, '#'.$target));
654 $size +
= $volume->size($target);
656 return array('size' => $size);
662 * @param array command arguments
664 * @author Dmitry (dio) Levashov
666 protected function mkdir($args) {
667 $target = $args['target'];
668 $name = $args['name'];
670 if (($volume = $this->volume($target)) == false) {
671 return array('error' => $this->error(self
::ERROR_MKDIR
, $name, self
::ERROR_TRGDIR_NOT_FOUND
, '#'.$target));
674 return ($dir = $volume->mkdir($target, $name)) == false
675 ?
array('error' => $this->error(self
::ERROR_MKDIR
, $name, $volume->error()))
676 : array('added' => array($dir));
682 * @param array command arguments
684 * @author Dmitry (dio) Levashov
686 protected function mkfile($args) {
687 $target = $args['target'];
688 $name = $args['name'];
690 if (($volume = $this->volume($target)) == false) {
691 return array('error' => $this->error(self
::ERROR_MKFILE
, $name, self
::ERROR_TRGDIR_NOT_FOUND
, '#'.$target));
694 return ($file = $volume->mkfile($target, $args['name'])) == false
695 ?
array('error' => $this->error(self
::ERROR_MKFILE
, $name, $volume->error()))
696 : array('added' => array($file));
704 * @author Dmitry (dio) Levashov
706 protected function rename($args) {
707 $target = $args['target'];
708 $name = $args['name'];
710 if (($volume = $this->volume($target)) == false
711 ||
($rm = $volume->file($target)) == false) {
712 return array('error' => $this->error(self
::ERROR_RENAME
, '#'.$target, self
::ERROR_FILE_NOT_FOUND
));
714 $rm['realpath'] = $volume->realpath($target);
716 return ($file = $volume->rename($target, $name)) == false
717 ?
array('error' => $this->error(self
::ERROR_RENAME
, $rm['name'], $volume->error()))
718 : array('added' => array($file), 'removed' => array($rm));
722 * Duplicate file - create copy with "copy %d" suffix
724 * @param array $args command arguments
726 * @author Dmitry (dio) Levashov
728 protected function duplicate($args) {
729 $targets = is_array($args['targets']) ?
$args['targets'] : array();
730 $result = array('added' => array());
731 $suffix = empty($args['suffix']) ?
'copy' : $args['suffix'];
733 foreach ($targets as $target) {
734 if (($volume = $this->volume($target)) == false
735 ||
($src = $volume->file($target)) == false) {
736 $result['warning'] = $this->error(self
::ERROR_COPY
, '#'.$target, self
::ERROR_FILE_NOT_FOUND
);
740 if (($file = $volume->duplicate($target, $suffix)) == false) {
741 $result['warning'] = $this->error($volume->error());
745 $result['added'][] = $file;
754 * @param array command arguments
756 * @author Dmitry (dio) Levashov
758 protected function rm($args) {
759 $targets = is_array($args['targets']) ?
$args['targets'] : array();
760 $result = array('removed' => array());
762 foreach ($targets as $target) {
763 if (($volume = $this->volume($target)) == false) {
764 $result['warning'] = $this->error(self
::ERROR_RM
, '#'.$target, self
::ERROR_FILE_NOT_FOUND
);
767 if (!$volume->rm($target)) {
768 $result['warning'] = $this->error($volume->error());
777 * Save uploaded files
781 * @author Dmitry (dio) Levashov
783 protected function upload($args) {
784 $target = $args['target'];
785 $volume = $this->volume($target);
786 $files = isset($args['FILES']['upload']) && is_array($args['FILES']['upload']) ?
$args['FILES']['upload'] : array();
787 $result = array('added' => array(), 'header' => empty($args['html']) ?
false : 'Content-Type: text/html; charset=utf-8');
790 return array('error' => $this->error(self
::ERROR_UPLOAD
, self
::ERROR_UPLOAD_NO_FILES
), 'header' => $header);
794 return array('error' => $this->error(self
::ERROR_UPLOAD
, self
::ERROR_TRGDIR_NOT_FOUND
, '#'.$target), 'header' => $header);
797 foreach ($files['name'] as $i => $name) {
798 if (($error = $files['error'][$i]) > 0) {
799 $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
);
800 $this->uploadDebug
= 'Upload error code: '.$error;
804 $tmpname = $files['tmp_name'][$i];
806 if (($fp = fopen($tmpname, 'rb')) == false) {
807 $result['warning'] = $this->error(self
::ERROR_UPLOAD_FILE
, $name, self
::ERROR_UPLOAD_TRANSFER
);
808 $this->uploadDebug
= 'Upload error: unable open tmp file';
812 if (($file = $volume->upload($fp, $target, $name, $tmpname)) === false) {
813 $result['warning'] = $this->error(self
::ERROR_UPLOAD_FILE
, $name, $volume->error());
819 $result['added'][] = $file;
826 * Copy/move files into new destination
828 * @param array command arguments
830 * @author Dmitry (dio) Levashov
832 protected function paste($args) {
834 $targets = is_array($args['targets']) ?
$args['targets'] : array();
835 $cut = !empty($args['cut']);
836 $error = $cut ? self
::ERROR_MOVE
: self
::ERROR_COPY
;
837 $result = array('added' => array(), 'removed' => array());
839 if (($dstVolume = $this->volume($dst)) == false) {
840 return array('error' => $this->error($error, '#'.$targets[0], self
::ERROR_TRGDIR_NOT_FOUND
, '#'.$dst));
843 foreach ($targets as $target) {
844 if (($srcVolume = $this->volume($target)) == false) {
845 $result['warning'] = $this->error($error, '#'.$target, self
::ERROR_FILE_NOT_FOUND
);
849 if (($file = $dstVolume->paste($srcVolume, $target, $dst, $cut)) == false) {
850 $result['warning'] = $this->error($dstVolume->error());
854 $result['added'][] = $file;
860 * Return file content
862 * @param array $args command arguments
864 * @author Dmitry (dio) Levashov
866 protected function get($args) {
867 $target = $args['target'];
868 $volume = $this->volume($target);
870 if (!$volume ||
($file = $volume->file($target)) == false) {
871 return array('error' => $this->error(self
::ERROR_OPEN
, '#'.$target, self
::ERROR_FILE_NOT_FOUND
));
874 if (($content = $volume->getContents($target)) === false) {
875 return array('error' => $this->error(self
::ERROR_OPEN
, $volume->path($target), $volume->error()));
878 $json = json_encode($content);
880 if ($json == 'null' && strlen($json) < strlen($content)) {
881 return array('error' => $this->error(self
::ERROR_NOT_UTF8_CONTENT
, $volume->path($target)));
884 return array('content' => $content);
888 * Save content into text file
891 * @author Dmitry (dio) Levashov
893 protected function put($args) {
894 $target = $args['target'];
896 if (($volume = $this->volume($target)) == false
897 ||
($file = $volume->file($target)) == false) {
898 return array('error' => $this->error(self
::ERROR_SAVE
, '#'.$target, self
::ERROR_FILE_NOT_FOUND
));
901 if (($file = $volume->putContents($target, $args['content'])) == false) {
902 return array('error' => $this->error(self
::ERROR_SAVE
, $volume->path($target), $volume->error()));
905 return array('changed' => array($file));
909 * Extract files from archive
911 * @param array $args command arguments
913 * @author Dmitry (dio) Levashov,
914 * @author Alexey Sukhotin
916 protected function extract($args) {
917 $target = $args['target'];
918 $mimes = !empty($args['mimes']) && is_array($args['mimes']) ?
$args['mimes'] : array();
919 $error = array(self
::ERROR_EXTRACT
, '#'.$target);
921 if (($volume = $this->volume($target)) == false
922 ||
($file = $volume->file($target)) == false) {
923 return array('error' => $this->error(self
::ERROR_EXTRACT
, '#'.$target, self
::ERROR_FILE_NOT_FOUND
));
926 return ($file = $volume->extract($target))
927 ?
array('added' => array($file))
928 : array('error' => $this->error(self
::ERROR_EXTRACT
, $volume->path($target), $volume->error()));
934 * @param array $args command arguments
936 * @author Dmitry (dio) Levashov,
937 * @author Alexey Sukhotin
939 protected function archive($args) {
940 $type = $args['type'];
941 $targets = isset($args['targets']) && is_array($args['targets']) ?
$args['targets'] : array();
943 if (($volume = $this->volume($targets[0])) == false) {
944 return $this->error(self
::ERROR_ARCHIVE
, self
::ERROR_TRGDIR_NOT_FOUND
);
947 return ($file = $volume->archive($targets, $args['type']))
948 ?
array('added' => array($file))
949 : array('error' => $this->error(self
::ERROR_ARCHIVE
, $volume->error()));
955 * @param array $args command arguments
957 * @author Dmitry Levashov
959 protected function search($args) {
960 $q = trim($args['q']);
961 $mimes = !empty($args['mimes']) && is_array($args['mimes']) ?
$args['mimes'] : array();
964 foreach ($this->volumes
as $volume) {
965 $result = array_merge($result, $volume->search($q, $mimes));
968 return array('files' => $result);
972 * Return file info (used by client "places" ui)
974 * @param array $args command arguments
976 * @author Dmitry Levashov
978 protected function info($args) {
981 foreach ($args['targets'] as $hash) {
982 if (($volume = $this->volume($hash)) != false
983 && ($info = $volume->file($hash)) != false) {
988 return array('files' => $files);
992 * Return image dimmensions
994 * @param array $args command arguments
996 * @author Dmitry (dio) Levashov
998 protected function dim($args) {
999 $target = $args['target'];
1001 if (($volume = $this->volume($target)) != false) {
1002 $dim = $volume->dimensions($target);
1003 return $dim ?
array('dim' => $dim) : array();
1011 * @param array command arguments
1013 * @author Dmitry (dio) Levashov
1014 * @author Alexey Sukhotin
1016 protected function resize($args) {
1017 $target = $args['target'];
1018 $width = $args['width'];
1019 $height = $args['height'];
1020 $x = (int)$args['x'];
1021 $y = (int)$args['y'];
1022 $mode = $args['mode'];
1024 $degree = (int)$args['degree'];
1026 if (($volume = $this->volume($target)) == false
1027 ||
($file = $volume->file($target)) == false) {
1028 return array('error' => $this->error(self
::ERROR_RESIZE
, '#'.$target, self
::ERROR_FILE_NOT_FOUND
));
1031 return ($file = $volume->resize($target, $width, $height, $x, $y, $mode, $bg, $degree))
1032 ?
array('changed' => array($file))
1033 : array('error' => $this->error(self
::ERROR_RESIZE
, $volume->path($target), $volume->error()));
1036 /***************************************************************************/
1038 /***************************************************************************/
1041 * Return root - file's owner
1043 * @param string file hash
1044 * @return elFinderStorageDriver
1045 * @author Dmitry (dio) Levashov
1047 protected function volume($hash) {
1048 foreach ($this->volumes
as $id => $v) {
1049 if (strpos(''.$hash, $id) === 0) {
1050 return $this->volumes
[$id];
1057 * Return files info array
1059 * @param array $data one file info or files info
1061 * @author Dmitry (dio) Levashov
1063 protected function toArray($data) {
1064 return isset($data['hash']) ||
!is_array($data) ?
array($data) : $data;
1068 * Return fils hashes list
1070 * @param array $files files info
1072 * @author Dmitry (dio) Levashov
1074 protected function hashes($files) {
1076 foreach ($files as $file) {
1077 $ret[] = $file['hash'];
1083 * Remove from files list hidden files and files with required mime types
1085 * @param array $files files info
1087 * @author Dmitry (dio) Levashov
1089 protected function filter($files) {
1090 foreach ($files as $i => $file) {
1091 if (!empty($file['hidden']) ||
!$this->default->mimeAccepted($file['mime'])) {
1095 return array_merge($files, array());
1098 protected function utime() {
1099 $time = explode(" ", microtime());
1100 return (double)$time[1] +
(double)$time[0];