PageRenderTime 39ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/plugins/MediaManager/src/Lib/ElFinder/elFinderVolumeLocalFileSystem.class.php

http://github.com/QuickAppsCMS/QuickApps-CMS
PHP | 821 lines | 384 code | 104 blank | 333 comment | 103 complexity | ce5190a4ddfdc4cd6cb56b57cecf79ad MD5 | raw file
Possible License(s): LGPL-2.1, MPL-2.0-no-copyleft-exception, GPL-3.0
  1. <?php
  2. /**
  3. * elFinder driver for local filesystem.
  4. *
  5. * @author Dmitry (dio) Levashov
  6. * @author Troex Nevelin
  7. **/
  8. class elFinderVolumeLocalFileSystem extends elFinderVolumeDriver {
  9. /**
  10. * Driver id
  11. * Must be started from letter and contains [a-z0-9]
  12. * Used as part of volume id
  13. *
  14. * @var string
  15. **/
  16. protected $driverId = 'l';
  17. /**
  18. * Required to count total archive files size
  19. *
  20. * @var int
  21. **/
  22. protected $archiveSize = 0;
  23. /**
  24. * Canonicalized absolute pathname of $root
  25. *
  26. * @var strung
  27. */
  28. protected $aroot;
  29. /**
  30. * Constructor
  31. * Extend options with required fields
  32. *
  33. * @return void
  34. * @author Dmitry (dio) Levashov
  35. **/
  36. public function __construct() {
  37. $this->options['alias'] = ''; // alias to replace root dir name
  38. $this->options['dirMode'] = 0755; // new dirs mode
  39. $this->options['fileMode'] = 0644; // new files mode
  40. $this->options['quarantine'] = '.quarantine'; // quarantine folder name - required to check archive (must be hidden)
  41. $this->options['maxArcFilesSize'] = 0; // max allowed archive files size (0 - no limit)
  42. $this->options['icon'] = (defined('ELFINDER_IMG_PARENT_URL')? (rtrim(ELFINDER_IMG_PARENT_URL, '/').'/') : '').'img/volume_icon_local.png';
  43. }
  44. /*********************************************************************/
  45. /* INIT AND CONFIGURE */
  46. /*********************************************************************/
  47. /**
  48. * Prepare driver before mount volume.
  49. * Return true if volume is ready.
  50. *
  51. * @return bool
  52. **/
  53. protected function init() {
  54. // Normalize directory separator for windows
  55. if (DIRECTORY_SEPARATOR !== '/') {
  56. foreach(array('path', 'tmbPath', 'quarantine') as $key) {
  57. if ($this->options[$key]) {
  58. $this->options[$key] = str_replace('/', DIRECTORY_SEPARATOR, $this->options[$key]);
  59. }
  60. }
  61. }
  62. return true;
  63. }
  64. /**
  65. * Configure after successfull mount.
  66. *
  67. * @return void
  68. * @author Dmitry (dio) Levashov
  69. **/
  70. protected function configure() {
  71. $this->aroot = realpath($this->root);
  72. $root = $this->stat($this->root);
  73. // chek thumbnails path
  74. if ($this->options['tmbPath']) {
  75. $this->options['tmbPath'] = strpos($this->options['tmbPath'], DIRECTORY_SEPARATOR) === false
  76. // tmb path set as dirname under root dir
  77. ? $this->_abspath($this->options['tmbPath'])
  78. // tmb path as full path
  79. : $this->_normpath($this->options['tmbPath']);
  80. }
  81. parent::configure();
  82. // if no thumbnails url - try detect it
  83. if ($root['read'] && !$this->tmbURL && $this->URL) {
  84. if (strpos($this->tmbPath, $this->root) === 0) {
  85. $this->tmbURL = $this->URL.str_replace(DIRECTORY_SEPARATOR, '/', substr($this->tmbPath, strlen($this->root)+1));
  86. if (preg_match("|[^/?&=]$|", $this->tmbURL)) {
  87. $this->tmbURL .= '/';
  88. }
  89. }
  90. }
  91. // check quarantine dir
  92. $this->quarantine = '';
  93. if (!empty($this->options['quarantine'])) {
  94. if (is_dir($this->options['quarantine'])) {
  95. if (is_writable($this->options['quarantine'])) {
  96. $this->quarantine = $this->options['quarantine'];
  97. }
  98. $this->options['quarantine'] = '';
  99. } else {
  100. $this->quarantine = $this->_abspath($this->options['quarantine']);
  101. if ((!is_dir($this->quarantine) && !$this->_mkdir($this->root, $this->options['quarantine'])) || !is_writable($this->quarantine)) {
  102. $this->options['quarantine'] = $this->quarantine = '';
  103. }
  104. }
  105. }
  106. if (!$this->quarantine) {
  107. $this->archivers['extract'] = array();
  108. $this->disabled[] = 'extract';
  109. }
  110. if ($this->options['quarantine']) {
  111. $this->attributes[] = array(
  112. 'pattern' => '~^'.preg_quote(DIRECTORY_SEPARATOR.$this->options['quarantine']).'$~',
  113. 'read' => false,
  114. 'write' => false,
  115. 'locked' => true,
  116. 'hidden' => true
  117. );
  118. }
  119. }
  120. /*********************************************************************/
  121. /* FS API */
  122. /*********************************************************************/
  123. /*********************** paths/urls *************************/
  124. /**
  125. * Return parent directory path
  126. *
  127. * @param string $path file path
  128. * @return string
  129. * @author Dmitry (dio) Levashov
  130. **/
  131. protected function _dirname($path) {
  132. return dirname($path);
  133. }
  134. /**
  135. * Return file name
  136. *
  137. * @param string $path file path
  138. * @return string
  139. * @author Dmitry (dio) Levashov
  140. **/
  141. protected function _basename($path) {
  142. return basename($path);
  143. }
  144. /**
  145. * Join dir name and file name and retur full path
  146. *
  147. * @param string $dir
  148. * @param string $name
  149. * @return string
  150. * @author Dmitry (dio) Levashov
  151. **/
  152. protected function _joinPath($dir, $name) {
  153. return $dir.DIRECTORY_SEPARATOR.$name;
  154. }
  155. /**
  156. * Return normalized path, this works the same as os.path.normpath() in Python
  157. *
  158. * @param string $path path
  159. * @return string
  160. * @author Troex Nevelin
  161. **/
  162. protected function _normpath($path) {
  163. if (empty($path)) {
  164. return '.';
  165. }
  166. $changeSep = (DIRECTORY_SEPARATOR !== '/');
  167. if ($changeSep) {
  168. $path = str_replace(DIRECTORY_SEPARATOR, '/', $path);
  169. }
  170. if (strpos($path, '/') === 0) {
  171. $initial_slashes = true;
  172. } else {
  173. $initial_slashes = false;
  174. }
  175. if (($initial_slashes)
  176. && (strpos($path, '//') === 0)
  177. && (strpos($path, '///') === false)) {
  178. $initial_slashes = 2;
  179. }
  180. $initial_slashes = (int) $initial_slashes;
  181. $comps = explode('/', $path);
  182. $new_comps = array();
  183. foreach ($comps as $comp) {
  184. if (in_array($comp, array('', '.'))) {
  185. continue;
  186. }
  187. if (($comp != '..')
  188. || (!$initial_slashes && !$new_comps)
  189. || ($new_comps && (end($new_comps) == '..'))) {
  190. array_push($new_comps, $comp);
  191. } elseif ($new_comps) {
  192. array_pop($new_comps);
  193. }
  194. }
  195. $comps = $new_comps;
  196. $path = implode('/', $comps);
  197. if ($initial_slashes) {
  198. $path = str_repeat('/', $initial_slashes) . $path;
  199. }
  200. if ($changeSep) {
  201. $path = str_replace('/', DIRECTORY_SEPARATOR, $path);
  202. }
  203. return $path ? $path : '.';
  204. }
  205. /**
  206. * Return file path related to root dir
  207. *
  208. * @param string $path file path
  209. * @return string
  210. * @author Dmitry (dio) Levashov
  211. **/
  212. protected function _relpath($path) {
  213. return $path == $this->root ? '' : substr($path, strlen($this->root)+1);
  214. }
  215. /**
  216. * Convert path related to root dir into real path
  217. *
  218. * @param string $path file path
  219. * @return string
  220. * @author Dmitry (dio) Levashov
  221. **/
  222. protected function _abspath($path) {
  223. return $path == DIRECTORY_SEPARATOR ? $this->root : $this->root.DIRECTORY_SEPARATOR.$path;
  224. }
  225. /**
  226. * Return fake path started from root dir
  227. *
  228. * @param string $path file path
  229. * @return string
  230. * @author Dmitry (dio) Levashov
  231. **/
  232. protected function _path($path) {
  233. return $this->rootName.($path == $this->root ? '' : $this->separator.$this->_relpath($path));
  234. }
  235. /**
  236. * Return true if $path is children of $parent
  237. *
  238. * @param string $path path to check
  239. * @param string $parent parent path
  240. * @return bool
  241. * @author Dmitry (dio) Levashov
  242. **/
  243. protected function _inpath($path, $parent) {
  244. $real_path = realpath($path);
  245. $real_parent = realpath($parent);
  246. if ($real_path && $real_parent) {
  247. return $real_path === $real_parent || strpos($real_path, rtrim($real_parent, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR) === 0;
  248. }
  249. return false;
  250. }
  251. /***************** file stat ********************/
  252. /**
  253. * Return stat for given path.
  254. * Stat contains following fields:
  255. * - (int) size file size in b. required
  256. * - (int) ts file modification time in unix time. required
  257. * - (string) mime mimetype. required for folders, others - optionally
  258. * - (bool) read read permissions. required
  259. * - (bool) write write permissions. required
  260. * - (bool) locked is object locked. optionally
  261. * - (bool) hidden is object hidden. optionally
  262. * - (string) alias for symlinks - link target path relative to root path. optionally
  263. * - (string) target for symlinks - link target path. optionally
  264. *
  265. * If file does not exists - returns empty array or false.
  266. *
  267. * @param string $path file path
  268. * @return array|false
  269. * @author Dmitry (dio) Levashov
  270. **/
  271. protected function _stat($path) {
  272. $stat = array();
  273. if (!file_exists($path)) {
  274. return $stat;
  275. }
  276. //Verifies the given path is the root or is inside the root. Prevents directory traveral.
  277. if (!$this->aroot) {
  278. // for Inheritance class ( not calling parent::configure() )
  279. $this->aroot = realpath($this->root);
  280. }
  281. if (!$this->_inpath($path, $this->aroot)) {
  282. return $stat;
  283. }
  284. if ($path != $this->root && is_link($path)) {
  285. if (($target = $this->readlink($path)) == false
  286. || $target == $path) {
  287. $stat['mime'] = 'symlink-broken';
  288. $stat['read'] = false;
  289. $stat['write'] = false;
  290. $stat['size'] = 0;
  291. return $stat;
  292. }
  293. $stat['alias'] = $this->_path($target);
  294. $stat['target'] = $target;
  295. $path = $target;
  296. $lstat = lstat($path);
  297. $size = sprintf('%u', $lstat['size']);
  298. } else {
  299. $size = sprintf('%u', @filesize($path));
  300. }
  301. $dir = is_dir($path);
  302. $stat['mime'] = $dir ? 'directory' : $this->mimetype($path);
  303. $stat['ts'] = filemtime($path);
  304. //logical rights first
  305. $stat['read'] = is_readable($path)? null : false;
  306. $stat['write'] = is_writable($path)? null : false;
  307. if (is_null($stat['read'])) {
  308. $stat['size'] = $dir ? 0 : $size;
  309. }
  310. return $stat;
  311. }
  312. /**
  313. * Return true if path is dir and has at least one childs directory
  314. *
  315. * @param string $path dir path
  316. * @return bool
  317. * @author Dmitry (dio) Levashov
  318. **/
  319. protected function _subdirs($path) {
  320. if (($dir = dir($path))) {
  321. $dir = dir($path);
  322. while (($entry = $dir->read()) !== false) {
  323. $p = $dir->path.DIRECTORY_SEPARATOR.$entry;
  324. if ($entry != '.' && $entry != '..' && is_dir($p) && !$this->attr($p, 'hidden')) {
  325. $dir->close();
  326. return true;
  327. }
  328. }
  329. $dir->close();
  330. }
  331. return false;
  332. }
  333. /**
  334. * Return object width and height
  335. * Usualy used for images, but can be realize for video etc...
  336. *
  337. * @param string $path file path
  338. * @param string $mime file mime type
  339. * @return string
  340. * @author Dmitry (dio) Levashov
  341. **/
  342. protected function _dimensions($path, $mime) {
  343. clearstatcache();
  344. return strpos($mime, 'image') === 0 && ($s = @getimagesize($path)) !== false
  345. ? $s[0].'x'.$s[1]
  346. : false;
  347. }
  348. /******************** file/dir content *********************/
  349. /**
  350. * Return symlink target file
  351. *
  352. * @param string $path link path
  353. * @return string
  354. * @author Dmitry (dio) Levashov
  355. **/
  356. protected function readlink($path) {
  357. if (!($target = @readlink($path))) {
  358. return false;
  359. }
  360. if (substr($target, 0, 1) != DIRECTORY_SEPARATOR) {
  361. $target = dirname($path).DIRECTORY_SEPARATOR.$target;
  362. }
  363. if ($this->_inpath($target, $this->aroot)) {
  364. $atarget = realpath($target);
  365. return $this->_normpath($this->root.DIRECTORY_SEPARATOR.substr($atarget, strlen($this->aroot)+1));
  366. }
  367. return false;
  368. }
  369. /**
  370. * Return files list in directory.
  371. *
  372. * @param string $path dir path
  373. * @return array
  374. * @author Dmitry (dio) Levashov
  375. **/
  376. protected function _scandir($path) {
  377. $files = array();
  378. foreach (scandir($path) as $name) {
  379. if ($name != '.' && $name != '..') {
  380. $files[] = $path.DIRECTORY_SEPARATOR.$name;
  381. }
  382. }
  383. return $files;
  384. }
  385. /**
  386. * Open file and return file pointer
  387. *
  388. * @param string $path file path
  389. * @param bool $write open file for writing
  390. * @return resource|false
  391. * @author Dmitry (dio) Levashov
  392. **/
  393. protected function _fopen($path, $mode='rb') {
  394. return @fopen($path, $mode);
  395. }
  396. /**
  397. * Close opened file
  398. *
  399. * @param resource $fp file pointer
  400. * @return bool
  401. * @author Dmitry (dio) Levashov
  402. **/
  403. protected function _fclose($fp, $path='') {
  404. return @fclose($fp);
  405. }
  406. /******************** file/dir manipulations *************************/
  407. /**
  408. * Create dir and return created dir path or false on failed
  409. *
  410. * @param string $path parent dir path
  411. * @param string $name new directory name
  412. * @return string|bool
  413. * @author Dmitry (dio) Levashov
  414. **/
  415. protected function _mkdir($path, $name) {
  416. $path = $path.DIRECTORY_SEPARATOR.$name;
  417. if (@mkdir($path)) {
  418. @chmod($path, $this->options['dirMode']);
  419. return $path;
  420. }
  421. return false;
  422. }
  423. /**
  424. * Create file and return it's path or false on failed
  425. *
  426. * @param string $path parent dir path
  427. * @param string $name new file name
  428. * @return string|bool
  429. * @author Dmitry (dio) Levashov
  430. **/
  431. protected function _mkfile($path, $name) {
  432. $path = $path.DIRECTORY_SEPARATOR.$name;
  433. if (($fp = @fopen($path, 'w'))) {
  434. @fclose($fp);
  435. @chmod($path, $this->options['fileMode']);
  436. return $path;
  437. }
  438. return false;
  439. }
  440. /**
  441. * Create symlink
  442. *
  443. * @param string $source file to link to
  444. * @param string $targetDir folder to create link in
  445. * @param string $name symlink name
  446. * @return bool
  447. * @author Dmitry (dio) Levashov
  448. **/
  449. protected function _symlink($source, $targetDir, $name) {
  450. return @symlink($source, $targetDir.DIRECTORY_SEPARATOR.$name);
  451. }
  452. /**
  453. * Copy file into another file
  454. *
  455. * @param string $source source file path
  456. * @param string $targetDir target directory path
  457. * @param string $name new file name
  458. * @return bool
  459. * @author Dmitry (dio) Levashov
  460. **/
  461. protected function _copy($source, $targetDir, $name) {
  462. return copy($source, $targetDir.DIRECTORY_SEPARATOR.$name);
  463. }
  464. /**
  465. * Move file into another parent dir.
  466. * Return new file path or false.
  467. *
  468. * @param string $source source file path
  469. * @param string $target target dir path
  470. * @param string $name file name
  471. * @return string|bool
  472. * @author Dmitry (dio) Levashov
  473. **/
  474. protected function _move($source, $targetDir, $name) {
  475. $target = $targetDir.DIRECTORY_SEPARATOR.$name;
  476. return @rename($source, $target) ? $target : false;
  477. }
  478. /**
  479. * Remove file
  480. *
  481. * @param string $path file path
  482. * @return bool
  483. * @author Dmitry (dio) Levashov
  484. **/
  485. protected function _unlink($path) {
  486. return @unlink($path);
  487. }
  488. /**
  489. * Remove dir
  490. *
  491. * @param string $path dir path
  492. * @return bool
  493. * @author Dmitry (dio) Levashov
  494. **/
  495. protected function _rmdir($path) {
  496. return @rmdir($path);
  497. }
  498. /**
  499. * Create new file and write into it from file pointer.
  500. * Return new file path or false on error.
  501. *
  502. * @param resource $fp file pointer
  503. * @param string $dir target dir path
  504. * @param string $name file name
  505. * @param array $stat file stat (required by some virtual fs)
  506. * @return bool|string
  507. * @author Dmitry (dio) Levashov
  508. **/
  509. protected function _save($fp, $dir, $name, $stat) {
  510. $path = $dir.DIRECTORY_SEPARATOR.$name;
  511. if (@file_put_contents($path, $fp, LOCK_EX) === false) {
  512. return false;
  513. }
  514. @chmod($path, $this->options['fileMode']);
  515. clearstatcache();
  516. return $path;
  517. }
  518. /**
  519. * Get file contents
  520. *
  521. * @param string $path file path
  522. * @return string|false
  523. * @author Dmitry (dio) Levashov
  524. **/
  525. protected function _getContents($path) {
  526. return file_get_contents($path);
  527. }
  528. /**
  529. * Write a string to a file
  530. *
  531. * @param string $path file path
  532. * @param string $content new file content
  533. * @return bool
  534. * @author Dmitry (dio) Levashov
  535. **/
  536. protected function _filePutContents($path, $content) {
  537. if (@file_put_contents($path, $content, LOCK_EX) !== false) {
  538. clearstatcache();
  539. return true;
  540. }
  541. return false;
  542. }
  543. /**
  544. * Detect available archivers
  545. *
  546. * @return void
  547. **/
  548. protected function _checkArchivers() {
  549. $this->archivers = $this->getArchivers();
  550. return;
  551. }
  552. /**
  553. * Unpack archive
  554. *
  555. * @param string $path archive path
  556. * @param array $arc archiver command and arguments (same as in $this->archivers)
  557. * @return void
  558. * @author Dmitry (dio) Levashov
  559. * @author Alexey Sukhotin
  560. **/
  561. protected function _unpack($path, $arc) {
  562. $cwd = getcwd();
  563. $dir = $this->_dirname($path);
  564. chdir($dir);
  565. $cmd = $arc['cmd'].' '.$arc['argc'].' '.escapeshellarg($this->_basename($path));
  566. $this->procExec($cmd, $o, $c);
  567. chdir($cwd);
  568. }
  569. /**
  570. * Recursive symlinks search
  571. *
  572. * @param string $path file/dir path
  573. * @return bool
  574. * @author Dmitry (dio) Levashov
  575. **/
  576. protected function _findSymlinks($path) {
  577. if (is_link($path)) {
  578. return true;
  579. }
  580. if (is_dir($path)) {
  581. foreach (scandir($path) as $name) {
  582. if ($name != '.' && $name != '..') {
  583. $p = $path.DIRECTORY_SEPARATOR.$name;
  584. if (is_link($p) || !$this->nameAccepted($name)) {
  585. $this->setError(elFinder::ERROR_SAVE, $name);
  586. return true;
  587. }
  588. if (is_dir($p) && $this->_findSymlinks($p)) {
  589. return true;
  590. } elseif (is_file($p)) {
  591. $this->archiveSize += sprintf('%u', filesize($p));
  592. }
  593. }
  594. }
  595. } else {
  596. $this->archiveSize += sprintf('%u', filesize($path));
  597. }
  598. return false;
  599. }
  600. /**
  601. * Extract files from archive
  602. *
  603. * @param string $path archive path
  604. * @param array $arc archiver command and arguments (same as in $this->archivers)
  605. * @return true
  606. * @author Dmitry (dio) Levashov,
  607. * @author Alexey Sukhotin
  608. **/
  609. protected function _extract($path, $arc) {
  610. if ($this->quarantine) {
  611. $dir = $this->quarantine.DIRECTORY_SEPARATOR.md5(basename($path).mt_rand());
  612. $archive = $dir.DIRECTORY_SEPARATOR.basename($path);
  613. if (!@mkdir($dir)) {
  614. return false;
  615. }
  616. // insurance unexpected shutdown
  617. register_shutdown_function(array($this, 'rmdirRecursive'), realpath($dir));
  618. chmod($dir, 0777);
  619. // copy in quarantine
  620. if (!copy($path, $archive)) {
  621. return false;
  622. }
  623. // extract in quarantine
  624. $this->_unpack($archive, $arc);
  625. unlink($archive);
  626. // get files list
  627. $ls = array();
  628. foreach (scandir($dir) as $i => $name) {
  629. if ($name != '.' && $name != '..') {
  630. $ls[] = $name;
  631. }
  632. }
  633. // no files - extract error ?
  634. if (empty($ls)) {
  635. return false;
  636. }
  637. $this->archiveSize = 0;
  638. // find symlinks
  639. $symlinks = $this->_findSymlinks($dir);
  640. if ($symlinks) {
  641. $this->delTree($dir);
  642. return $this->setError(array_merge($this->error, array(elFinder::ERROR_ARC_SYMLINKS)));
  643. }
  644. // check max files size
  645. if ($this->options['maxArcFilesSize'] > 0 && $this->options['maxArcFilesSize'] < $this->archiveSize) {
  646. $this->delTree($dir);
  647. return $this->setError(elFinder::ERROR_ARC_MAXSIZE);
  648. }
  649. // archive contains one item - extract in archive dir
  650. $src = $dir.DIRECTORY_SEPARATOR.$ls[0];
  651. if (count($ls) === 1 && is_file($src)) {
  652. $name = $ls[0];
  653. } else {
  654. // for several files - create new directory
  655. // create unique name for directory
  656. $src = $dir;
  657. $name = basename($path);
  658. if (preg_match('/\.((tar\.(gz|bz|bz2|z|lzo))|cpio\.gz|ps\.gz|xcf\.(gz|bz2)|[a-z0-9]{1,4})$/i', $name, $m)) {
  659. $name = substr($name, 0, strlen($name)-strlen($m[0]));
  660. }
  661. $test = dirname($path).DIRECTORY_SEPARATOR.$name;
  662. if (file_exists($test) || is_link($test)) {
  663. $name = $this->uniqueName(dirname($path), $name, '-', false);
  664. }
  665. }
  666. $result = dirname($path).DIRECTORY_SEPARATOR.$name;
  667. if (! @rename($src, $result)) {
  668. $this->delTree($dir);
  669. return false;
  670. }
  671. is_dir($dir) && $this->delTree($dir);
  672. return file_exists($result) ? $result : false;
  673. }
  674. }
  675. /**
  676. * Create archive and return its path
  677. *
  678. * @param string $dir target dir
  679. * @param array $files files names list
  680. * @param string $name archive name
  681. * @param array $arc archiver options
  682. * @return string|bool
  683. * @author Dmitry (dio) Levashov,
  684. * @author Alexey Sukhotin
  685. **/
  686. protected function _archive($dir, $files, $name, $arc) {
  687. $cwd = getcwd();
  688. chdir($dir);
  689. $files = array_map('escapeshellarg', $files);
  690. $cmd = $arc['cmd'].' '.$arc['argc'].' '.escapeshellarg($name).' '.implode(' ', $files);
  691. $this->procExec($cmd, $o, $c);
  692. chdir($cwd);
  693. $path = $dir.DIRECTORY_SEPARATOR.$name;
  694. return file_exists($path) ? $path : false;
  695. }
  696. /******************** Over write functions *************************/
  697. /**
  698. * File path of local server side work file path
  699. *
  700. * @param string $path
  701. * @return string
  702. * @author Naoki Sawada
  703. */
  704. protected function getWorkFile($path) {
  705. return $path;
  706. }
  707. /**
  708. * Delete dirctory trees
  709. *
  710. * @param string $localpath path need convert encoding to server encoding
  711. * @return boolean
  712. * @author Naoki Sawada
  713. */
  714. protected function delTree($localpath) {
  715. return $this->rmdirRecursive($localpath);
  716. }
  717. } // END class