PluginProbe ʕ •ᴥ•ʔ
Advanced File Manager – Ultimate File Manager for WordPress And Document Library Solution / trunk
Advanced File Manager – Ultimate File Manager for WordPress And Document Library Solution vtrunk
trunk 4.1.5 4.1.6 5.0 5.2.13 5.2.14 5.3.0 5.3.1 5.3.2 5.3.3 5.3.4 5.3.5 5.3.6 5.4.0 5.4.1 5.4.10 5.4.11 5.4.12 5.4.2 5.4.3 5.4.4 5.4.5 5.4.6 5.4.7 5.4.8
file-manager-advanced / application / library / php / elFinderVolumeSFTPphpseclib.class.php
file-manager-advanced / application / library / php Last commit date
.tmp 10 months ago editors 1 month ago libs 7 years ago plugins 3 years ago resources 7 years ago MySQLStorage.sql 1 year ago autoload.php 10 months ago connector.maximal.php-dist 1 year ago connector.minimal.php-dist 1 year ago elFinder.class.php 1 month ago elFinderConnector.class.php 1 month ago elFinderFlysystemGoogleDriveNetmount.php 5 years ago elFinderPlugin.php 7 years ago elFinderSession.php 4 years ago elFinderSessionInterface.php 7 years ago elFinderVolumeBox.class.php 5 years ago elFinderVolumeDriver.class.php 1 month ago elFinderVolumeDropbox.class.php 1 year ago elFinderVolumeDropbox2.class.php 1 month ago elFinderVolumeFTP.class.php 5 years ago elFinderVolumeGoogleDrive.class.php 5 years ago elFinderVolumeGroup.class.php 7 years ago elFinderVolumeLocalFileSystem.class.php 2 years ago elFinderVolumeMySQL.class.php 10 months ago elFinderVolumeOneDrive.class.php 1 month ago elFinderVolumeSFTPphpseclib.class.php 1 month ago elFinderVolumeTrash.class.php 7 years ago elFinderVolumeTrashMySQL.class.php 7 years ago mime.types 3 years ago
elFinderVolumeSFTPphpseclib.class.php
854 lines
1 <?php
2
3 /**
4 * Simple elFinder driver for SFTP using phpseclib 1
5 *
6 * @author Dmitry (dio) Levashov
7 * @author Cem (discofever), sitecode
8 * @reference http://phpseclib.sourceforge.net/sftp/2.0/examples.html
9 **/
10 class elFinderVolumeSFTPphpseclib extends elFinderVolumeFTP {
11
12 /**
13 * Simple hack that could break for quick compatibility with phpseclib version 1-3
14 * Same value substitue for reference NET_SFTP_LOCAL_FILE and SFTP::SOURCE_LOCAL_FILE
15 */
16 const NET_SFTP_LOCAL_FILE = 1;
17
18 /**
19 * Constructor
20 * Extend options with required fields
21 *
22 * @author Dmitry (dio) Levashov
23 * @author Cem (DiscoFever)
24 */
25 public function __construct()
26 {
27 $opts = array(
28 'host' => 'localhost',
29 'user' => '',
30 'pass' => '',
31 'port' => 22,
32 'path' => '/',
33 'timeout' => 20,
34 'owner' => true,
35 'tmbPath' => '',
36 'tmpPath' => '',
37 'separator' => '/',
38 'phpseclibDir' => '../phpseclib/',
39 'connectCallback' => null, //provide your own already instantiated phpseclib $Sftp object returned by this callback
40 //'connectCallback'=> function($options) {
41 // //load and instantiate phpseclib $sftp
42 // return $sftp;
43 // },
44 'checkSubfolders' => -1,
45 'dirMode' => 0755,
46 'fileMode' => 0644,
47 'rootCssClass' => 'elfinder-navbar-root-ftp',
48 );
49 $this->options = array_merge($this->options, $opts);
50 $this->options['mimeDetect'] = 'internal';
51 }
52
53 /**
54 * Prepare
55 * Call from elFinder::netmout() before volume->mount()
56 *
57 * @param $options
58 *
59 * @return array volume root options
60 * @author Naoki Sawada
61 */
62 public function netmountPrepare($options)
63 {
64 $options['statOwner'] = true;
65 $options['allowChmodReadOnly'] = true;
66 $options['acceptedName'] = '#^[^/\\?*:|"<>]*[^./\\?*:|"<>]$#';
67 return $options;
68 }
69
70 /*********************************************************************/
71 /* INIT AND CONFIGURE */
72 /*********************************************************************/
73
74 /**
75 * Prepare SFTP connection
76 * Connect to remote server and check if credentials are correct, if so, store the connection
77 *
78 * @return bool
79 * @author Dmitry (dio) Levashov
80 * @author Cem (DiscoFever)
81 **/
82 protected function init()
83 {
84 if (!$this->options['connectCallback']) {
85 if (!$this->options['host']
86 || !$this->options['port']) {
87 return $this->setError('Required options undefined.');
88 }
89
90 if (!$this->options['path']) {
91 $this->options['path'] = '/';
92 }
93
94 // make net mount key
95 $this->netMountKey = md5(join('-', array('sftpphpseclib', $this->options['host'], $this->options['port'], $this->options['path'], $this->options['user'])));
96
97 set_include_path(get_include_path() . PATH_SEPARATOR . getcwd().'/'.$this->options['phpseclibDir']);
98 include_once('Net/SFTP.php');
99
100 if (!class_exists('Net_SFTP')) {
101 return $this->setError('SFTP extension not loaded. Install phpseclib version 1: http://phpseclib.sourceforge.net/ Set option "phpseclibDir" accordingly.');
102 }
103
104 // remove protocol from host
105 $scheme = parse_url($this->options['host'], PHP_URL_SCHEME);
106
107 if ($scheme) {
108 $this->options['host'] = substr($this->options['host'], strlen($scheme) + 3);
109 }
110 } else {
111 // make net mount key
112 $this->netMountKey = md5(join('-', array('sftpphpseclib', $this->options['path'])));
113 }
114
115 // normalize root path
116 $this->root = $this->options['path'] = $this->_normpath($this->options['path']);
117
118 if (empty($this->options['alias'])) {
119 $this->options['alias'] = $this->options['user'] . '@' . $this->options['host'];
120 if (!empty($this->options['netkey'])) {
121 elFinder::$instance->updateNetVolumeOption($this->options['netkey'], 'alias', $this->options['alias']);
122 }
123 }
124
125 $this->rootName = $this->options['alias'];
126 $this->options['separator'] = '/';
127
128 if (is_null($this->options['syncChkAsTs'])) {
129 $this->options['syncChkAsTs'] = true;
130 }
131
132 return $this->needOnline? $this->connect() : true;
133
134 }
135
136
137 /**
138 * Configure after successfull mount.
139 *
140 * @return void
141 * @throws elFinderAbortException
142 * @author Dmitry (dio) Levashov
143 */
144 protected function configure()
145 {
146 parent::configure();
147
148 if (!$this->tmp) {
149 $this->disabled[] = 'mkfile';
150 $this->disabled[] = 'paste';
151 $this->disabled[] = 'upload';
152 $this->disabled[] = 'edit';
153 //$this->disabled[] = 'archive';
154 //$this->disabled[] = 'extract';
155 }
156
157 $this->disabled[] = 'archive';
158 $this->disabled[] = 'extract';
159 }
160
161 /**
162 * Connect to sftp server
163 *
164 * @return bool
165 * @author sitecode
166 **/
167 protected function connect()
168 {
169 //use ca
170 if ($this->options['connectCallback']) {
171 $this->connect = $this->options['connectCallback']($this->options);
172 if (!$this->connect || !$this->connect->isConnected()) {
173 return $this->setError('Unable to connect successfully');
174 }
175
176 return true;
177 }
178
179 try{
180 $host = $this->options['host'] . ($this->options['port'] != 22 ? ':' . $this->options['port'] : '');
181 $this->connect = new Net_SFTP($host);
182 //TODO check fingerprint before login, fail if no match to last time
183 if (!$this->connect->login($this->options['user'], $this->options['pass'])) {
184 return $this->setError('Unable to connect to SFTP server ' . $host);
185 }
186 } catch (Exception $e) {
187 return $this->setError('Error while connecting to SFTP server ' . $host . ': ' . $e->getMessage());
188 }
189
190 if (!$this->connect->chdir($this->root)
191 /*|| $this->root != $this->connect->pwd()*/) {
192 //$this->umount();
193 return $this->setError('Unable to open root folder.');
194 }
195
196 return true;
197 }
198
199 /**
200 * Call rawlist
201 *
202 * @param string $path
203 *
204 * @return array
205 */
206 protected function ftpRawList($path)
207 {
208 return $this->connect->rawlist($path ?: '.') ?: [];
209 }
210
211 /*********************************************************************/
212 /* FS API */
213 /*********************************************************************/
214
215 /**
216 * Close opened connection
217 *
218 * @return void
219 * @author Dmitry (dio) Levashov
220 **/
221 public function umount()
222 {
223 $this->connect && $this->connect->disconnect();
224 }
225
226
227 /**
228 * Parse line from rawlist() output and return file stat (array)
229 *
230 * @param array $info from rawlist() output
231 * @param $base
232 * @param bool $nameOnly
233 *
234 * @return array
235 * @author Dmitry Levashov
236 */
237 protected function parseRaw($info, $base, $nameOnly = false)
238 {
239 $stat = array();
240
241 if ($info['filename'] == '.' || $info['filename'] == '..') {
242 return false;
243 }
244
245 $name = $info['filename'];
246 //for compatability with phpseclib version 2/3
247 if (empty($info['permissions'])) {
248 $info['permissions'] = $info['mode'];
249 }
250
251 if ($info['type'] === 3) {
252 // check recursive processing
253 if ($this->cacheDirTarget && $this->_joinPath($base, $name) !== $this->cacheDirTarget) {
254 return array();
255 }
256 if (!$nameOnly) {
257 $target = $this->connect->readlink($name);
258 if (substr($target, 0, 1) !== $this->separator) {
259 $target = $this->getFullPath($target, $base);
260 }
261 $target = $this->_normpath($target);
262 $stat['name'] = $name;
263 $stat['target'] = $target;
264 return $stat;
265 }
266 }
267
268 if ($nameOnly) {
269 return array('name' => $name);
270 }
271
272 $stat['ts'] = $info['mtime'];
273
274 if ($this->options['statOwner']) {
275 $stat['owner'] = $info['uid'];
276 $stat['group'] = $info['gid'];
277 $stat['perm'] = $info['permissions'];
278 $stat['isowner'] = isset($stat['owner']) ? ($this->options['owner'] ? true : ($stat['owner'] == $this->options['user'])) : true;
279 }
280
281 $owner_computed = isset($stat['isowner']) ? $stat['isowner'] : $this->options['owner'];
282 $perm = $this->parsePermissions($info['permissions'], $owner_computed);
283 $stat['name'] = $name;
284 if ($info['type'] === NET_SFTP_TYPE_DIRECTORY) {
285 $stat['mime'] = 'directory';
286 $stat['size'] = 0;
287
288 } elseif ($info['type'] === NET_SFTP_TYPE_SYMLINK) {
289 $stat['mime'] = 'symlink';
290 $stat['size'] = 0;
291
292 } else {
293 $stat['mime'] = $this->mimetype($stat['name'], true);
294 $stat['size'] = $info['size'];
295 }
296
297 $stat['read'] = $perm['read'];
298 $stat['write'] = $perm['write'];
299
300 return $stat;
301 }
302
303 /**
304 * Parse permissions string. Return array(read => true/false, write => true/false)
305 *
306 * @param int $perm
307 * The isowner parameter is computed by the caller.
308 * If the owner parameter in the options is true, the user is the actual owner of all objects even if the user used in the ftp Login
309 * is different from the file owner id.
310 * If the owner parameter is false to understand if the user is the file owner we compare the ftp user with the file owner id.
311 * @param Boolean $isowner . Tell if the current user is the owner of the object.
312 *
313 * @return array
314 * @author Dmitry (dio) Levashov
315 * @author sitecode
316 */
317 protected function parsePermissions($permissions, $isowner = true)
318 {
319 $permissions = decoct($permissions);
320 $perm = $isowner ? decbin((int)$permissions[-3]) : decbin((int)$permissions[-1]);
321
322 return array(
323 'read' => $perm[-3],
324 'write' => $perm[-2]
325 );
326 }
327
328 /**
329 * Cache dir contents
330 *
331 * @param string $path dir path
332 *
333 * @return void
334 * @author Dmitry Levashov, sitecode
335 **/
336 protected function cacheDir($path)
337 {
338 $this->dirsCache[$path] = array();
339 $hasDir = false;
340
341 $list = array();
342 $encPath = $this->convEncIn($path);
343 foreach ($this->ftpRawList($encPath) as $info) {
344 if (($stat = $this->parseRaw($info, $encPath))) {
345 $list[] = $stat;
346 }
347 }
348 $list = $this->convEncOut($list);
349 $prefix = ($path === $this->separator) ? $this->separator : $path . $this->separator;
350 $targets = array();
351 foreach ($list as $stat) {
352 $p = $prefix . $stat['name'];
353 if (isset($stat['target'])) {
354 // stat later
355 $targets[$stat['name']] = $stat['target'];
356 } else {
357 $stat = $this->updateCache($p, $stat);
358 if (empty($stat['hidden'])) {
359 if (!$hasDir && $stat['mime'] === 'directory') {
360 $hasDir = true;
361 } elseif (!$hasDir && $stat['mime'] === 'symlink') {
362 $hasDir = true;
363 }
364 $this->dirsCache[$path][] = $p;
365 }
366 }
367 }
368 // stat link targets
369 foreach ($targets as $name => $target) {
370 $stat = array();
371 $stat['name'] = $name;
372 $p = $prefix . $name;
373 $cacheDirTarget = $this->cacheDirTarget;
374 $this->cacheDirTarget = $this->convEncIn($target, true);
375 if ($tstat = $this->stat($target)) {
376 $stat['size'] = $tstat['size'];
377 $stat['alias'] = $target;
378 $stat['thash'] = $tstat['hash'];
379 $stat['mime'] = $tstat['mime'];
380 $stat['read'] = $tstat['read'];
381 $stat['write'] = $tstat['write'];
382
383 if (isset($tstat['ts'])) {
384 $stat['ts'] = $tstat['ts'];
385 }
386 if (isset($tstat['owner'])) {
387 $stat['owner'] = $tstat['owner'];
388 }
389 if (isset($tstat['group'])) {
390 $stat['group'] = $tstat['group'];
391 }
392 if (isset($tstat['perm'])) {
393 $stat['perm'] = $tstat['perm'];
394 }
395 if (isset($tstat['isowner'])) {
396 $stat['isowner'] = $tstat['isowner'];
397 }
398 } else {
399
400 $stat['mime'] = 'symlink-broken';
401 $stat['read'] = false;
402 $stat['write'] = false;
403 $stat['size'] = 0;
404
405 }
406 $this->cacheDirTarget = $cacheDirTarget;
407 $stat = $this->updateCache($p, $stat);
408 if (empty($stat['hidden'])) {
409 if (!$hasDir && $stat['mime'] === 'directory') {
410 $hasDir = true;
411 }
412 $this->dirsCache[$path][] = $p;
413 }
414 }
415
416 if (isset($this->sessionCache['subdirs'])) {
417 $this->sessionCache['subdirs'][$path] = $hasDir;
418 }
419 }
420
421
422 /***************** file stat ********************/
423
424 /**
425 * Return stat for given path.
426 * Stat contains following fields:
427 * - (int) size file size in b. required
428 * - (int) ts file modification time in unix time. required
429 * - (string) mime mimetype. required for folders, others - optionally
430 * - (bool) read read permissions. required
431 * - (bool) write write permissions. required
432 * - (bool) locked is object locked. optionally
433 * - (bool) hidden is object hidden. optionally
434 * - (string) alias for symlinks - link target path relative to root path. optionally
435 * - (string) target for symlinks - link target path. optionally
436 * If file does not exists - returns empty array or false.
437 *
438 * @param string $path file path
439 *
440 * @return array|false
441 * @author Dmitry (dio) Levashov
442 **/
443 protected function _stat($path)
444 {
445 $outPath = $this->convEncOut($path);
446 if (isset($this->cache[$outPath])) {
447 return $this->convEncIn($this->cache[$outPath]);
448 } else {
449 $this->convEncIn();
450 }
451 if ($path === $this->root) {
452 $res = array(
453 'name' => $this->root,
454 'mime' => 'directory',
455 'dirs' => -1
456 );
457 if ($this->needOnline && (($this->ARGS['cmd'] === 'open' && $this->ARGS['target'] === $this->encode($this->root)) || $this->isMyReload())) {
458 $check = array(
459 'ts' => true,
460 'dirs' => true,
461 );
462 $ts = 0;
463 foreach ($this->ftpRawList($path) as $info) {
464 if ($info['filename'] === '.') {
465 $info['filename'] = 'root';
466 if ($stat = $this->parseRaw($info, $path)) {
467 unset($stat['name']);
468 $res = array_merge($res, $stat);
469 if ($res['ts']) {
470 $ts = 0;
471 unset($check['ts']);
472 }
473 }
474 }
475 if ($check && ($stat = $this->parseRaw($info, $path))) {
476 if (isset($stat['ts']) && !empty($stat['ts'])) {
477 $ts = max($ts, $stat['ts']);
478 }
479 if (isset($stat['dirs']) && $stat['mime'] === 'directory') {
480 $res['dirs'] = 1;
481 unset($stat['dirs']);
482 }
483 if (!$check) {
484 break;
485 }
486 }
487 }
488 if ($ts) {
489 $res['ts'] = $ts;
490 }
491 $this->cache[$outPath] = $res;
492 }
493 return $res;
494 }
495
496 $pPath = $this->_dirname($path);
497 if ($this->_inPath($pPath, $this->root)) {
498 $outPPpath = $this->convEncOut($pPath);
499 if (!isset($this->dirsCache[$outPPpath])) {
500 $parentSubdirs = null;
501 if (isset($this->sessionCache['subdirs']) && isset($this->sessionCache['subdirs'][$outPPpath])) {
502 $parentSubdirs = $this->sessionCache['subdirs'][$outPPpath];
503 }
504 $this->cacheDir($outPPpath);
505 if ($parentSubdirs) {
506 $this->sessionCache['subdirs'][$outPPpath] = $parentSubdirs;
507 }
508 }
509 }
510
511 $stat = $this->convEncIn(isset($this->cache[$outPath]) ? $this->cache[$outPath] : array());
512 if (!$this->mounted) {
513 // dispose incomplete cache made by calling `stat` by 'startPath' option
514 $this->cache = array();
515 }
516
517 return $stat;
518 }
519
520 /**
521 * Return true if path is dir and has at least one childs directory
522 *
523 * @param string $path dir path
524 *
525 * @return bool
526 * @author Dmitry (dio) Levashov, sitecode
527 **/
528 protected function _subdirs($path)
529 {
530 foreach ($this->ftpRawList($path) as $info) {
531 $name = $info['filename'];
532 if ($name && $name !== '.' && $name !== '..' && $info['type'] == NET_SFTP_TYPE_DIRECTORY) {
533 return true;
534 }
535 if ($name && $name !== '.' && $name !== '..' && $info['type'] == NET_SFTP_TYPE_SYMLINK) {
536 //return true;
537 }
538 }
539
540 return false;
541 }
542
543
544 /******************** file/dir content *********************/
545
546 /**
547 * Open file and return file pointer
548 *
549 * @param string $path file path
550 * @param string $mode
551 *
552 * @return false|resource
553 * @throws elFinderAbortException
554 * @internal param bool $write open file for writing
555 * @author Dmitry (dio) Levashov
556 */
557 protected function _fopen($path, $mode = 'rb')
558 {
559 if ($this->tmp) {
560 $local = $this->getTempFile($path);
561 $this->connect->get($path, $local);
562 return @fopen($local, $mode);
563 }
564
565 return false;
566 }
567
568 /**
569 * Close opened file
570 *
571 * @param resource $fp file pointer
572 * @param string $path
573 *
574 * @return void
575 * @author Dmitry (dio) Levashov
576 */
577 protected function _fclose($fp, $path = '')
578 {
579 is_resource($fp) && fclose($fp);
580 if ($path) {
581 unlink($this->getTempFile($path));
582 }
583 }
584
585
586 /******************** file/dir manipulations *************************/
587
588 /**
589 * Create dir and return created dir path or false on failed
590 *
591 * @param string $path parent dir path
592 * @param string $name new directory name
593 *
594 * @return string|bool
595 * @author Dmitry (dio) Levashov
596 **/
597 protected function _mkdir($path, $name)
598 {
599 $path = $this->_joinPath($path, $this->_basename($name));
600 if ($this->connect->mkdir($path) === false) {
601 return false;
602 }
603
604 $this->options['dirMode'] && $this->connect->chmod($this->options['dirMode'], $path);
605 return $path;
606 }
607
608 /**
609 * Create file and return it's path or false on failed
610 *
611 * @param string $path parent dir path
612 * @param string $name new file name
613 *
614 * @return string|bool
615 * @author sitecode
616 **/
617 protected function _mkfile($path, $name)
618 {
619 $path = $this->_joinPath($path, $this->_basename($name));
620 return $this->connect->put($path, '') ? $path : false;
621 /*
622 if ($this->tmp) {
623 $path = $this->_joinPath($path, $name);
624 $local = $this->getTempFile();
625 $res = touch($local) && $this->connect->put($path, $local, self::NET_SFTP_LOCAL_FILE);
626 unlink($local);
627 return $res ? $path : false;
628 }
629
630 return false;
631 */
632 }
633
634 /**
635 * Copy file into another file
636 *
637 * @param string $source source file path
638 * @param string $targetDir target directory path
639 * @param string $name new file name
640 *
641 * @return bool
642 * @author Dmitry (dio) Levashov, sitecode
643 **/
644 protected function _copy($source, $targetDir, $name)
645 {
646 $res = false;
647
648 $target = $this->_joinPath($targetDir, $this->_basename($name));
649 if ($this->tmp) {
650 $local = $this->getTempFile();
651
652 if ($this->connect->get($source, $local)
653 && $this->connect->put($target, $local, self::NET_SFTP_LOCAL_FILE)) {
654 $res = true;
655 }
656 unlink($local);
657 } else {
658 //not memory efficient
659 $res = $this->_filePutContents($target, $this->_getContents($source));
660 }
661
662 return $res;
663 }
664
665 /**
666 * Move file into another parent dir.
667 * Return new file path or false.
668 *
669 * @param string $source source file path
670 * @param $targetDir
671 * @param string $name file name
672 *
673 * @return bool|string
674 * @internal param string $target target dir path
675 * @author Dmitry (dio) Levashov
676 */
677 protected function _move($source, $targetDir, $name)
678 {
679 $target = $this->_joinPath($targetDir, $this->_basename($name));
680 return $this->connect->rename($source, $target) ? $target : false;
681 }
682
683 /**
684 * Remove file
685 *
686 * @param string $path file path
687 *
688 * @return bool
689 * @author Dmitry (dio) Levashov
690 **/
691 protected function _unlink($path)
692 {
693 return $this->connect->delete($path, false);
694 }
695
696 /**
697 * Remove dir
698 *
699 * @param string $path dir path
700 *
701 * @return bool
702 * @author Dmitry (dio) Levashov
703 **/
704 protected function _rmdir($path)
705 {
706 return $this->connect->delete($path);
707 }
708
709 /**
710 * Create new file and write into it from file pointer.
711 * Return new file path or false on error.
712 *
713 * @param resource $fp file pointer
714 * @param string $dir target dir path
715 * @param string $name file name
716 * @param array $stat file stat (required by some virtual fs)
717 *
718 * @return bool|string
719 * @author Dmitry (dio) Levashov
720 **/
721 protected function _save($fp, $dir, $name, $stat)
722 {
723 //TODO optionally encrypt $fp before uploading if mime is not already encrypted type
724 $path = $this->_joinPath($dir, $this->_basename($name));
725 return $this->connect->put($path, $fp)
726 ? $path
727 : false;
728 }
729
730 /**
731 * Get file contents
732 *
733 * @param string $path file path
734 *
735 * @return string|false
736 * @throws elFinderAbortException
737 * @author Dmitry (dio) Levashov
738 */
739 protected function _getContents($path)
740 {
741 return $this->connect->get($path);
742 }
743
744 /**
745 * Write a string to a file
746 *
747 * @param string $path file path
748 * @param string $content new file content
749 *
750 * @return bool
751 * @author Dmitry (dio) Levashov
752 **/
753 protected function _filePutContents($path, $content)
754 {
755 return $this->connect->put($path, $content);
756 }
757
758 /**
759 * chmod availability
760 *
761 * @param string $path
762 * @param string $mode
763 *
764 * @return bool
765 */
766 protected function _chmod($path, $mode)
767 {
768 $modeOct = is_string($mode) ? octdec($mode) : octdec(sprintf("%04o", $mode));
769 return $this->connect->chmod($modeOct, $path);
770 }
771
772 /**
773 * Extract files from archive
774 *
775 * @param string $path archive path
776 * @param array $arc archiver command and arguments (same as in $this->archivers)
777 *
778 * @return true
779 * @throws elFinderAbortException
780 * @author Dmitry (dio) Levashov,
781 * @author Alexey Sukhotin
782 */
783 protected function _extract($path, $arc)
784 {
785 return false; //TODO
786 }
787
788 /**
789 * Create archive and return its path
790 *
791 * @param string $dir target dir
792 * @param array $files files names list
793 * @param string $name archive name
794 * @param array $arc archiver options
795 *
796 * @return string|bool
797 * @throws elFinderAbortException
798 * @author Dmitry (dio) Levashov,
799 * @author Alexey Sukhotin
800 */
801 protected function _archive($dir, $files, $name, $arc)
802 {
803 return false; //TODO
804 }
805
806 /**
807 * Gets an array of absolute remote SFTP paths of files and
808 * folders in $remote_directory omitting symbolic links.
809 *
810 * @param $remote_directory string remote SFTP path to scan for file and folders recursively
811 * @param $targets array Array of target item. `null` is to get all of items
812 *
813 * @return array of elements each of which is an array of two elements:
814 * <ul>
815 * <li>$item['path'] - absolute remote SFTP path</li>
816 * <li>$item['type'] - either 'f' for file or 'd' for directory</li>
817 * </ul>
818 */
819 protected function ftp_scan_dir($remote_directory, $targets = null)
820 {
821 $buff = $this->ftpRawList($remote_directory);
822 $items = array();
823 if ($targets && is_array($targets)) {
824 $targets = array_flip($targets);
825 } else {
826 $targets = false;
827 }
828 foreach ($buff as $info) {
829 $name = $info['filename'];
830 if ($name !== '.' && $name !== '..' && (!$targets || isset($targets[$name]))) {
831 switch ($info['type']) {
832 case NET_SFTP_TYPE_SYMLINK : //omit symbolic links
833 case NET_SFTP_TYPE_DIRECTORY :
834 $remote_file_path = $this->_joinPath($remote_directory, $name);
835 $item = array();
836 $item['path'] = $remote_file_path;
837 $item['type'] = 'd'; // normal file
838 $items[] = $item;
839 $items = array_merge($items, $this->ftp_scan_dir($remote_file_path));
840 break;
841 default:
842 $remote_file_path = $this->_joinPath($remote_directory, $name);
843 $item = array();
844 $item['path'] = $remote_file_path;
845 $item['type'] = 'f'; // normal file
846 $items[] = $item;
847 }
848 }
849 }
850 return $items;
851 }
852
853 } // END class
854