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