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 / elFinderVolumeDropbox.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
elFinderVolumeDropbox.class.php
1465 lines
1 <?php
2
3 elFinder::$netDrivers['dropbox'] = 'Dropbox';
4
5 /**
6 * Simple elFinder driver for FTP
7 *
8 * @author Dmitry (dio) Levashov
9 * @author Cem (discofever)
10 **/
11 class elFinderVolumeDropbox extends elFinderVolumeDriver {
12
13 /**
14 * Driver id
15 * Must be started from letter and contains [a-z0-9]
16 * Used as part of volume id
17 *
18 * @var string
19 **/
20 protected $driverId = 'd';
21
22 /**
23 * OAuth object
24 *
25 * @var oauth
26 **/
27 protected $oauth = null;
28
29 /**
30 * Dropbox object
31 *
32 * @var dropbox
33 **/
34 protected $dropbox = null;
35
36 /**
37 * Directory for meta data caches
38 * If not set driver not cache meta data
39 *
40 * @var string
41 **/
42 protected $metaCache = '';
43
44 /**
45 * Last API error message
46 *
47 * @var string
48 **/
49 protected $apiError = '';
50
51 /**
52 * Directory for tmp files
53 * If not set driver will try to use tmbDir as tmpDir
54 *
55 * @var string
56 **/
57 protected $tmp = '';
58
59 /**
60 * Dropbox.com uid
61 *
62 * @var string
63 **/
64 protected $dropboxUid = '';
65
66 /**
67 * Dropbox download host, replaces 'www.dropbox.com' of shares URL
68 *
69 * @var string
70 */
71 private $dropbox_dlhost = 'dl.dropboxusercontent.com';
72
73 private $dropbox_phpFound = false;
74
75 private $DB_TableName = '';
76
77 private $tmbPrefix = '';
78
79 /**
80 * Constructor
81 * Extend options with required fields
82 *
83 * @author Dmitry (dio) Levashov
84 * @author Cem (DiscoFever)
85 */
86 public function __construct() {
87
88 // check with composer
89 $this->dropbox_phpFound = class_exists('Dropbox_API');
90
91 if (! $this->dropbox_phpFound) {
92 // check with pear
93 if (include_once 'Dropbox/autoload.php') {
94 $this->dropbox_phpFound = in_array('Dropbox_autoload', spl_autoload_functions());
95 }
96 }
97
98 $opts = array(
99 'consumerKey' => '',
100 'consumerSecret' => '',
101 'accessToken' => '',
102 'accessTokenSecret' => '',
103 'dropboxUid' => '',
104 'root' => 'dropbox',
105 'path' => '/',
106 'separator' => '/',
107 'PDO_DSN' => '', // if empty use 'sqlite:(metaCachePath|tmbPath)/elFinder_dropbox_db_(hash:dropboxUid+consumerSecret)'
108 'PDO_User' => '',
109 'PDO_Pass' => '',
110 'PDO_Options' => array(),
111 'PDO_DBName' => 'dropbox',
112 'treeDeep' => 0,
113 'tmbPath' => '',
114 'tmbURL' => '',
115 'tmpPath' => '',
116 'getTmbSize' => 'large', // small: 32x32, medium or s: 64x64, large or m: 128x128, l: 640x480, xl: 1024x768
117 'metaCachePath' => '',
118 'metaCacheTime' => '600', // 10m
119 'acceptedName' => '#^[^/\\?*:|"<>]*[^./\\?*:|"<>]$#',
120 'rootCssClass' => 'elfinder-navbar-root-dropbox'
121 );
122 $this->options = array_merge($this->options, $opts);
123 $this->options['mimeDetect'] = 'internal';
124 }
125
126 /**
127 * Prepare
128 * Call from elFinder::netmout() before volume->mount()
129 *
130 * @param $options
131 * @return Array
132 * @author Naoki Sawada
133 */
134 public function netmountPrepare($options) {
135 if (empty($options['consumerKey']) && defined('ELFINDER_DROPBOX_CONSUMERKEY')) $options['consumerKey'] = ELFINDER_DROPBOX_CONSUMERKEY;
136 if (empty($options['consumerSecret']) && defined('ELFINDER_DROPBOX_CONSUMERSECRET')) $options['consumerSecret'] = ELFINDER_DROPBOX_CONSUMERSECRET;
137
138 if ($options['user'] === 'init') {
139
140 if (! $this->dropbox_phpFound || empty($options['consumerKey']) || empty($options['consumerSecret']) || !class_exists('PDO', false)) {
141 return array('exit' => true, 'body' => '{msg:errNetMountNoDriver}');
142 }
143
144 if (defined('ELFINDER_DROPBOX_USE_CURL_PUT')) {
145 $this->oauth = new Dropbox_OAuth_Curl($options['consumerKey'], $options['consumerSecret']);
146 } else {
147 if (class_exists('OAuth', false)) {
148 $this->oauth = new Dropbox_OAuth_PHP($options['consumerKey'], $options['consumerSecret']);
149 } else {
150 if (! class_exists('HTTP_OAuth_Consumer')) {
151 // We're going to try to load in manually
152 include 'HTTP/OAuth/Consumer.php';
153 }
154 if (class_exists('HTTP_OAuth_Consumer', false)) {
155 $this->oauth = new Dropbox_OAuth_PEAR($options['consumerKey'], $options['consumerSecret']);
156 }
157 }
158 }
159
160 if (! $this->oauth) {
161 return array('exit' => true, 'body' => '{msg:errNetMountNoDriver}');
162 }
163
164 if ($options['pass'] === 'init') {
165 $html = '';
166 if ($sessionToken = $this->session->get('DropboxTokens')) {
167 // token check
168 try {
169 list(, $accessToken, $accessTokenSecret) = $sessionToken;
170 $this->oauth->setToken($accessToken, $accessTokenSecret);
171 $this->dropbox = new Dropbox_API($this->oauth, $this->options['root']);
172 $this->dropbox->getAccountInfo();
173 $script = '<script>
174 $("#'.$options['id'].'").elfinder("instance").trigger("netmount", {protocol: "dropbox", mode: "done"});
175 </script>';
176 $html = $script;
177 } catch (Dropbox_Exception $e) {
178 $this->session->remove('DropboxTokens');
179 }
180 }
181 if (! $html) {
182 // get customdata
183 $cdata = '';
184 $innerKeys = array('cmd', 'host', 'options', 'pass', 'protocol', 'user');
185 $this->ARGS = $_SERVER['REQUEST_METHOD'] === 'POST'? $_POST : $_GET;
186 foreach($this->ARGS as $k => $v) {
187 if (! in_array($k, $innerKeys)) {
188 $cdata .= '&' . $k . '=' . rawurlencode($v);
189 }
190 }
191 if (strpos($options['url'], 'http') !== 0 ) {
192 $options['url'] = elFinder::getConnectorUrl();
193 }
194 $callback = $options['url']
195 . '?cmd=netmount&protocol=dropbox&host=dropbox.com&user=init&pass=return&node='.$options['id'].$cdata;
196
197 try {
198 $tokens = $this->oauth->getRequestToken();
199 $url= $this->oauth->getAuthorizeUrl(rawurlencode($callback));
200 } catch (Dropbox_Exception $e) {
201 return array('exit' => true, 'body' => '{msg:errAccess}');
202 }
203
204 $this->session->set('DropboxAuthTokens', $tokens);
205 $html = '<input id="elf-volumedriver-dropbox-host-btn" class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only" value="{msg:btnApprove}" type="button" onclick="window.open(\''.$url.'\')">';
206 $html .= '<script>
207 $("#'.$options['id'].'").elfinder("instance").trigger("netmount", {protocol: "dropbox", mode: "makebtn"});
208 </script>';
209 }
210 return array('exit' => true, 'body' => $html);
211 } else {
212 $this->oauth->setToken($this->session->get('DropboxAuthTokens'));
213 $this->session->remove('DropboxAuthTokens');
214 $tokens = $this->oauth->getAccessToken();
215 $this->session->set('DropboxTokens', array($_GET['uid'], $tokens['token'], $tokens['token_secret']));
216
217 $out = array(
218 'node' => $_GET['node'],
219 'json' => '{"protocol": "dropbox", "mode": "done"}',
220 'bind' => 'netmount'
221 );
222
223 return array('exit' => 'callback', 'out' => $out);
224 }
225 }
226 if ($sessionToken = $this->session->get('DropboxTokens')) {
227 list($options['dropboxUid'], $options['accessToken'], $options['accessTokenSecret']) = $sessionToken;
228 }
229 unset($options['user'], $options['pass']);
230 return $options;
231 }
232
233 /**
234 * process of on netunmount
235 * Drop table `dropbox` & rm thumbs
236 *
237 * @param $netVolumes
238 * @param $key
239 * @return bool
240 * @internal param array $options
241 */
242 public function netunmount($netVolumes, $key) {
243 $count = 0;
244 $dropboxUid = '';
245 if (isset($netVolumes[$key])) {
246 $dropboxUid = $netVolumes[$key]['dropboxUid'];
247 }
248 foreach($netVolumes as $volume) {
249 if ($volume['host'] === 'dropbox' && $volume['dropboxUid'] === $dropboxUid) {
250 $count++;
251 }
252 }
253 if ($count === 1) {
254 $this->DB->exec('drop table '.$this->DB_TableName);
255 foreach(glob(rtrim($this->options['tmbPath'], '\\/').DIRECTORY_SEPARATOR.$this->tmbPrefix.'*.png') as $tmb) {
256 unlink($tmb);
257 }
258 }
259 return true;
260 }
261
262 /*********************************************************************/
263 /* INIT AND CONFIGURE */
264 /*********************************************************************/
265
266 /**
267 * Prepare FTP connection
268 * Connect to remote server and check if credentials are correct, if so, store the connection id in $ftp_conn
269 *
270 * @return bool
271 * @author Dmitry (dio) Levashov
272 * @author Cem (DiscoFever)
273 **/
274 protected function init() {
275 if (!class_exists('PDO', false)) {
276 return $this->setError('PHP PDO class is require.');
277 }
278
279 if (!$this->options['consumerKey']
280 || !$this->options['consumerSecret']
281 || !$this->options['accessToken']
282 || !$this->options['accessTokenSecret']) {
283 return $this->setError('Required options undefined.');
284 }
285
286 if (empty($this->options['metaCachePath']) && defined('ELFINDER_DROPBOX_META_CACHE_PATH')) {
287 $this->options['metaCachePath'] = ELFINDER_DROPBOX_META_CACHE_PATH;
288 }
289
290 // make net mount key
291 $this->netMountKey = md5(join('-', array('dropbox', $this->options['path'])));
292
293 if (! $this->oauth) {
294 if (defined('ELFINDER_DROPBOX_USE_CURL_PUT')) {
295 $this->oauth = new Dropbox_OAuth_Curl($this->options['consumerKey'], $this->options['consumerSecret']);
296 } else {
297 if (class_exists('OAuth', false)) {
298 $this->oauth = new Dropbox_OAuth_PHP($this->options['consumerKey'], $this->options['consumerSecret']);
299 } else {
300 if (! class_exists('HTTP_OAuth_Consumer')) {
301 // We're going to try to load in manually
302 include 'HTTP/OAuth/Consumer.php';
303 }
304 if (class_exists('HTTP_OAuth_Consumer', false)) {
305 $this->oauth = new Dropbox_OAuth_PEAR($this->options['consumerKey'], $this->options['consumerSecret']);
306 }
307 }
308 }
309 }
310
311 if (! $this->oauth) {
312 return $this->setError('OAuth extension not loaded.');
313 }
314
315 // normalize root path
316 $this->root = $this->options['path'] = $this->_normpath($this->options['path']);
317
318 if (empty($this->options['alias'])) {
319 $this->options['alias'] = ($this->options['path'] === '/')? 'Dropbox.com' : 'Dropbox'.$this->options['path'];
320 }
321
322 $this->rootName = $this->options['alias'];
323
324 try {
325 $this->oauth->setToken($this->options['accessToken'], $this->options['accessTokenSecret']);
326 $this->dropbox = new Dropbox_API($this->oauth, $this->options['root']);
327 } catch (Dropbox_Exception $e) {
328 $this->session->remove('DropboxTokens');
329 return $this->setError('Dropbox error: '.$e->getMessage());
330 }
331
332 // user
333 if (empty($this->options['dropboxUid'])) {
334 try {
335 $res = $this->dropbox->getAccountInfo();
336 $this->options['dropboxUid'] = $res['uid'];
337 } catch (Dropbox_Exception $e) {
338 $this->session->remove('DropboxTokens');
339 return $this->setError('Dropbox error: '.$e->getMessage());
340 }
341 }
342
343 $this->dropboxUid = $this->options['dropboxUid'];
344 $this->tmbPrefix = 'dropbox'.base_convert($this->dropboxUid, 10, 32);
345
346 if (!empty($this->options['tmpPath'])) {
347 if ((is_dir($this->options['tmpPath']) || mkdir($this->options['tmpPath'])) && is_writable($this->options['tmpPath'])) {
348 $this->tmp = $this->options['tmpPath'];
349 }
350 }
351 if (!$this->tmp && is_writable($this->options['tmbPath'])) {
352 $this->tmp = $this->options['tmbPath'];
353 }
354 if (!$this->tmp && ($tmp = elFinder::getStaticVar('commonTempPath'))) {
355 $this->tmp = $tmp;
356 }
357
358 if (!empty($this->options['metaCachePath'])) {
359 if ((is_dir($this->options['metaCachePath']) || mkdir($this->options['metaCachePath'])) && is_writable($this->options['metaCachePath'])) {
360 $this->metaCache = $this->options['metaCachePath'];
361 }
362 }
363 if (!$this->metaCache && $this->tmp) {
364 $this->metaCache = $this->tmp;
365 }
366
367 if (!$this->metaCache) {
368 return $this->setError('Cache dirctory (metaCachePath or tmp) is require.');
369 }
370
371 // setup PDO
372 if (! $this->options['PDO_DSN']) {
373 $this->options['PDO_DSN'] = 'sqlite:'.$this->metaCache.DIRECTORY_SEPARATOR.'.elFinder_dropbox_db_'.md5($this->dropboxUid.$this->options['consumerSecret']);
374 }
375 // DataBase table name
376 $this->DB_TableName = $this->options['PDO_DBName'];
377 // DataBase check or make table
378 try {
379 $this->DB = new PDO($this->options['PDO_DSN'], $this->options['PDO_User'], $this->options['PDO_Pass'], $this->options['PDO_Options']);
380 if (! $this->checkDB()) {
381 return $this->setError('Can not make DB table');
382 }
383 } catch (PDOException $e) {
384 return $this->setError('PDO connection failed: '.$e->getMessage());
385 }
386
387 $res = $this->deltaCheck($this->isMyReload());
388 if ($res !== true) {
389 if (is_string($res)) {
390 return $this->setError($res);
391 } else {
392 return $this->setError('Could not check API "delta"');
393 }
394 }
395
396 if (is_null($this->options['syncChkAsTs'])) {
397 $this->options['syncChkAsTs'] = true;
398 }
399 if ($this->options['syncChkAsTs']) {
400 // 'tsPlSleep' minmum 5 sec
401 $this->options['tsPlSleep'] = max(5, $this->options['tsPlSleep']);
402 } else {
403 // 'lsPlSleep' minmum 10 sec
404 $this->options['lsPlSleep'] = max(10, $this->options['lsPlSleep']);
405 }
406
407 return true;
408 }
409
410
411 /**
412 * Configure after successful mount.
413 *
414 * @return string
415 * @author Dmitry (dio) Levashov
416 **/
417 protected function configure() {
418 parent::configure();
419
420 $this->disabled[] = 'archive';
421 $this->disabled[] = 'extract';
422 }
423
424 /**
425 * Check DB for delta cache
426 *
427 * @return bool
428 */
429 private function checkDB() {
430 $res = $this->query('SELECT * FROM sqlite_master WHERE type=\'table\' AND name=\''.$this->DB_TableName.'\'');
431 if ($res && isset($_REQUEST['init'])) {
432 // check is index(nameidx) UNIQUE?
433 $chk = $this->query('SELECT sql FROM sqlite_master WHERE type=\'index\' and name=\'nameidx\'');
434 if (!$chk || strpos(strtoupper($chk[0]), 'UNIQUE') === false) {
435 // remake
436 $this->DB->exec('DROP TABLE '.$this->DB_TableName);
437 $res = false;
438 }
439 }
440 if (! $res) {
441 try {
442 $this->DB->exec('CREATE TABLE '.$this->DB_TableName.'(path text, fname text, dat blob, isdir integer);');
443 $this->DB->exec('CREATE UNIQUE INDEX nameidx ON '.$this->DB_TableName.'(path, fname)');
444 $this->DB->exec('CREATE INDEX isdiridx ON '.$this->DB_TableName.'(isdir)');
445 } catch (PDOException $e) {
446 return $this->setError($e->getMessage());
447 }
448 }
449 return true;
450 }
451
452 /**
453 * DB query and fetchAll
454 *
455 * @param string $sql
456 * @return boolean|array
457 */
458 private function query($sql) {
459 if ($sth = $this->DB->query($sql)) {
460 $res = $sth->fetchAll(PDO::FETCH_COLUMN);
461 } else {
462 $res = false;
463 }
464 return $res;
465 }
466
467 /**
468 * Get dat(dropbox metadata) from DB
469 *
470 * @param string $path
471 * @return array dropbox metadata
472 */
473 private function getDBdat($path) {
474 if ($res = $this->query('select dat from '.$this->DB_TableName.' where path='.$this->DB->quote(strtolower($this->_dirname($path))).' and fname='.$this->DB->quote(strtolower($this->_basename($path))).' limit 1')) {
475 return unserialize($res[0]);
476 } else {
477 return array();
478 }
479 }
480
481 /**
482 * Update DB dat(dropbox metadata)
483 *
484 * @param string $path
485 * @param array $dat
486 * @return bool|array
487 */
488 private function updateDBdat($path, $dat) {
489 return $this->query('update '.$this->DB_TableName.' set dat='.$this->DB->quote(serialize($dat))
490 . ', isdir=' . ($dat['is_dir']? 1 : 0)
491 . ' where path='.$this->DB->quote(strtolower($this->_dirname($path))).' and fname='.$this->DB->quote(strtolower($this->_basename($path))));
492 }
493 /*********************************************************************/
494 /* FS API */
495 /*********************************************************************/
496
497 /**
498 * Close opened connection
499 *
500 * @return void
501 * @author Dmitry (dio) Levashov
502 **/
503 public function umount() {
504
505 }
506
507 /**
508 * Get delta data and DB update
509 *
510 * @param boolean $refresh force refresh
511 * @return true|string error message
512 */
513 protected function deltaCheck($refresh = true) {
514 $chk = false;
515 if (! $refresh && $chk = $this->query('select dat from '.$this->DB_TableName.' where path=\'\' and fname=\'\' limit 1')) {
516 $chk = unserialize($chk[0]);
517 }
518 if ($chk && ($chk['mtime'] + $this->options['metaCacheTime']) > $_SERVER['REQUEST_TIME']) {
519 return true;
520 }
521
522 try {
523 $more = true;
524 $this->DB->beginTransaction();
525
526 if ($res = $this->query('select dat from '.$this->DB_TableName.' where path=\'\' and fname=\'\' limit 1')) {
527 $res = unserialize($res[0]);
528 $cursor = $res['cursor'];
529 } else {
530 $cursor = '';
531 }
532 $delete = false;
533 $reset = false;
534 $ptimes = array();
535 $now = time();
536 do {
537 ini_set('max_execution_time', 120);
538 $_info = $this->dropbox->delta($cursor);
539 if (! empty($_info['reset'])) {
540 $this->DB->exec('TRUNCATE table '.$this->DB_TableName);
541 $this->DB->exec('insert into '.$this->DB_TableName.' values(\'\', \'\', \''.serialize(array('cursor' => '', 'mtime' => 0)).'\', 0);');
542 $this->DB->exec('insert into '.$this->DB_TableName.' values(\'/\', \'\', \''.serialize(array(
543 'path' => '/',
544 'is_dir' => 1,
545 'mime_type' => '',
546 'bytes' => 0
547 )).'\', 0);');
548 $reset = true;
549 }
550 $cursor = $_info['cursor'];
551
552 foreach($_info['entries'] as $entry) {
553 $key = strtolower($entry[0]);
554 $pkey = strtolower($this->_dirname($key));
555
556 $path = $this->DB->quote($pkey);
557 $fname = $this->DB->quote(strtolower($this->_basename($key)));
558 $where = 'where path='.$path.' and fname='.$fname;
559
560 if (empty($entry[1])) {
561 $ptimes[$pkey] = isset($ptimes[$pkey])? max(array($now, $ptimes[$pkey])) : $now;
562 $this->DB->exec('delete from '.$this->DB_TableName.' '.$where);
563 ! $delete && $delete = true;
564 continue;
565 }
566
567 $_itemTime = strtotime(isset($entry[1]['client_mtime'])? $entry[1]['client_mtime'] : $entry[1]['modified']);
568 $ptimes[$pkey] = isset($ptimes[$pkey])? max(array($_itemTime, $ptimes[$pkey])) : $_itemTime;
569 $sql = 'select path from '.$this->DB_TableName.' '.$where.' limit 1';
570 if (! $reset && $this->query($sql)) {
571 $this->DB->exec('update '.$this->DB_TableName.' set dat='.$this->DB->quote(serialize($entry[1])).', isdir='.($entry[1]['is_dir']? 1 : 0).' ' .$where);
572 } else {
573 $this->DB->exec('insert into '.$this->DB_TableName.' values ('.$path.', '.$fname.', '.$this->DB->quote(serialize($entry[1])).', '.(int)$entry[1]['is_dir'].')');
574 }
575 }
576 } while (! empty($_info['has_more']));
577
578 // update time stamp of parent holder
579 foreach ($ptimes as $_p => $_t) {
580 if ($praw = $this->getDBdat($_p)) {
581 $_update = false;
582 if (isset($praw['client_mtime']) && $_t > strtotime($praw['client_mtime'])) {
583 $praw['client_mtime'] = date('r', $_t);
584 $_update = true;
585 }
586 if (isset($praw['modified']) && $_t > strtotime($praw['modified'])) {
587 $praw['modified'] = date('r', $_t);
588 $_update = true;
589 }
590 if ($_update) {
591 $pwhere = 'where path='.$this->DB->quote(strtolower($this->_dirname($_p))).' and fname='.$this->DB->quote(strtolower($this->_basename($_p)));
592 $this->DB->exec('update '.$this->DB_TableName.' set dat='.$this->DB->quote(serialize($praw)).' '.$pwhere);
593 }
594 }
595 }
596
597 $this->DB->exec('update '.$this->DB_TableName.' set dat='.$this->DB->quote(serialize(array('cursor'=>$cursor, 'mtime'=>$_SERVER['REQUEST_TIME']))).' where path=\'\' and fname=\'\'');
598 if (! $this->DB->commit()) {
599 $e = $this->DB->errorInfo();
600 return $e[2];
601 }
602 if ($delete) {
603 $this->DB->exec('vacuum');
604 }
605 } catch(Dropbox_Exception $e) {
606 return $e->getMessage();
607 }
608 return true;
609 }
610
611 /**
612 * Parse line from dropbox metadata output and return file stat (array)
613 *
614 * @param string $raw line from ftp_rawlist() output
615 * @return array
616 * @author Dmitry Levashov
617 **/
618 protected function parseRaw($raw) {
619 $stat = array();
620
621 $stat['rev'] = isset($raw['rev'])? $raw['rev'] : 'root';
622 $stat['name'] = $this->_basename($raw['path']);
623 $stat['mime'] = $raw['is_dir']? 'directory' : $raw['mime_type'];
624 $stat['size'] = $stat['mime'] == 'directory' ? 0 : $raw['bytes'];
625 $stat['ts'] = isset($raw['client_mtime'])? strtotime($raw['client_mtime']) :
626 (isset($raw['modified'])? strtotime($raw['modified']) : $_SERVER['REQUEST_TIME']);
627 $stat['dirs'] = 0;
628 if ($raw['is_dir']) {
629 $stat['dirs'] = (int)(bool)$this->query('select path from '.$this->DB_TableName.' where isdir=1 and path='.$this->DB->quote(strtolower($raw['path'])));
630 }
631
632 if (!empty($raw['url'])) {
633 $stat['url'] = $raw['url'];
634 } else if (! $this->disabledGetUrl) {
635 $stat['url'] = '1';
636 }
637 if (isset($raw['width'])) $stat['width'] = $raw['width'];
638 if (isset($raw['height'])) $stat['height'] = $raw['height'];
639
640 return $stat;
641 }
642
643 /**
644 * Cache dir contents
645 *
646 * @param string $path dir path
647 * @return string
648 * @author Dmitry Levashov
649 **/
650 protected function cacheDir($path) {
651 $this->dirsCache[$path] = array();
652 $hasDir = false;
653
654 $res = $this->query('select dat from '.$this->DB_TableName.' where path='.$this->DB->quote(strtolower($path)));
655
656 if ($res) {
657 foreach($res as $raw) {
658 $raw = unserialize($raw);
659 if ($stat = $this->parseRaw($raw)) {
660 $stat = $this->updateCache($raw['path'], $stat);
661 if (empty($stat['hidden']) && $path !== $raw['path']) {
662 if (! $hasDir && $stat['mime'] === 'directory') {
663 $hasDir = true;
664 }
665 $this->dirsCache[$path][] = $raw['path'];
666 }
667 }
668 }
669 }
670
671 if (isset($this->sessionCache['subdirs'])) {
672 $this->sessionCache['subdirs'][$path] = $hasDir;
673 }
674
675 return $this->dirsCache[$path];
676 }
677
678 /**
679 * Recursive files search
680 *
681 * @param string $path dir path
682 * @param string $q search string
683 * @param array $mimes
684 * @return array
685 * @author Naoki Sawada
686 **/
687 protected function doSearch($path, $q, $mimes) {
688 $result = array();
689 $sth = $this->DB->prepare('select dat from '.$this->DB_TableName.' WHERE path LIKE ? AND fname LIKE ?');
690 $sth->execute(array((($path === '/')? '' : strtolower($path)).'%', '%'.strtolower($q).'%'));
691 $res = $sth->fetchAll(PDO::FETCH_COLUMN);
692 $timeout = $this->options['searchTimeout']? $this->searchStart + $this->options['searchTimeout'] : 0;
693
694 if ($res) {
695 foreach($res as $raw) {
696 if ($timeout && $timeout < time()) {
697 $this->setError(elFinder::ERROR_SEARCH_TIMEOUT, $this->path($this->encode($path)));
698 break;
699 }
700
701 $raw = unserialize($raw);
702 if ($stat = $this->parseRaw($raw)) {
703 if (!isset($this->cache[$raw['path']])) {
704 $stat = $this->updateCache($raw['path'], $stat);
705 }
706 if (!empty($stat['hidden']) || ($mimes && $stat['mime'] === 'directory') || !$this->mimeAccepted($stat['mime'], $mimes)) {
707 continue;
708 }
709 $stat = $this->stat($raw['path']);
710 $stat['path'] = $this->path($stat['hash']);
711 $result[] = $stat;
712 }
713 }
714 }
715 return $result;
716 }
717
718 /**
719 * Copy file/recursive copy dir only in current volume.
720 * Return new file path or false.
721 *
722 * @param string $src source path
723 * @param string $dst destination dir path
724 * @param string $name new file name (optionaly)
725 * @return string|false
726 * @author Dmitry (dio) Levashov
727 * @author Naoki Sawada
728 **/
729 protected function copy($src, $dst, $name) {
730
731 $this->clearcache();
732
733 return $this->_copy($src, $dst, $name)
734 ? $this->_joinPath($dst, $name)
735 : $this->setError(elFinder::ERROR_COPY, $this->_path($src));
736 }
737
738 /**
739 * Remove file/ recursive remove dir
740 *
741 * @param string $path file path
742 * @param bool $force try to remove even if file locked
743 * @param bool $recursive
744 * @return bool
745 * @author Dmitry (dio) Levashov
746 * @author Naoki Sawada
747 */
748 protected function remove($path, $force = false, $recursive = false) {
749 $stat = $this->stat($path);
750 $stat['realpath'] = $path;
751 $this->rmTmb($stat);
752 $this->clearcache();
753
754 if (empty($stat)) {
755 return $this->setError(elFinder::ERROR_RM, $this->_path($path), elFinder::ERROR_FILE_NOT_FOUND);
756 }
757
758 if (!$force && !empty($stat['locked'])) {
759 return $this->setError(elFinder::ERROR_LOCKED, $this->_path($path));
760 }
761
762 if ($stat['mime'] == 'directory') {
763 if (!$recursive && !$this->_rmdir($path)) {
764 return $this->setError(elFinder::ERROR_RM, $this->_path($path));
765 }
766 } else {
767 if (!$recursive && !$this->_unlink($path)) {
768 return $this->setError(elFinder::ERROR_RM, $this->_path($path));
769 }
770 }
771
772 $this->removed[] = $stat;
773 return true;
774 }
775
776 /**
777 * Create thumnbnail and return it's URL on success
778 *
779 * @param string $path file path
780 * @param $stat
781 * @return false|string
782 * @internal param string $mime file mime type
783 * @author Dmitry (dio) Levashov
784 * @author Naoki Sawada
785 */
786 protected function createTmb($path, $stat) {
787 if (!$stat || !$this->canCreateTmb($path, $stat)) {
788 return false;
789 }
790
791 $name = $this->tmbname($stat);
792 $tmb = $this->tmbPath.DIRECTORY_SEPARATOR.$name;
793
794 // copy image into tmbPath so some drivers does not store files on local fs
795 if (! $data = $this->getThumbnail($path, $this->options['getTmbSize'])) {
796 return false;
797 }
798 if (! file_put_contents($tmb, $data)) {
799 return false;
800 }
801
802 $result = false;
803
804 $tmbSize = $this->tmbSize;
805
806 if (($s = getimagesize($tmb)) == false) {
807 return false;
808 }
809
810 /* If image smaller or equal thumbnail size - just fitting to thumbnail square */
811 if ($s[0] <= $tmbSize && $s[1] <= $tmbSize) {
812 $result = $this->imgSquareFit($tmb, $tmbSize, $tmbSize, 'center', 'middle', $this->options['tmbBgColor'], 'png' );
813
814 } else {
815
816 if ($this->options['tmbCrop']) {
817
818 /* Resize and crop if image bigger than thumbnail */
819 if (!(($s[0] > $tmbSize && $s[1] <= $tmbSize) || ($s[0] <= $tmbSize && $s[1] > $tmbSize) ) || ($s[0] > $tmbSize && $s[1] > $tmbSize)) {
820 $result = $this->imgResize($tmb, $tmbSize, $tmbSize, true, false, 'png');
821 }
822
823 if (($s = getimagesize($tmb)) != false) {
824 $x = $s[0] > $tmbSize ? intval(($s[0] - $tmbSize)/2) : 0;
825 $y = $s[1] > $tmbSize ? intval(($s[1] - $tmbSize)/2) : 0;
826 $result = $this->imgCrop($tmb, $tmbSize, $tmbSize, $x, $y, 'png');
827 }
828
829 } else {
830 $result = $this->imgResize($tmb, $tmbSize, $tmbSize, true, true, 'png');
831 }
832
833 $result = $this->imgSquareFit($tmb, $tmbSize, $tmbSize, 'center', 'middle', $this->options['tmbBgColor'], 'png' );
834 }
835
836 if (!$result) {
837 unlink($tmb);
838 return false;
839 }
840
841 return $name;
842 }
843
844 /**
845 * Return thumbnail file name for required file
846 *
847 * @param array $stat file stat
848 * @return string
849 * @author Dmitry (dio) Levashov
850 **/
851 protected function tmbname($stat) {
852 return $this->tmbPrefix.$stat['rev'].'.png';
853 }
854
855 /**
856 * Get thumbnail from dropbox.com
857 * @param string $path
858 * @param string $size
859 * @return string | boolean
860 */
861 protected function getThumbnail($path, $size = 'small') {
862 try {
863 return $this->dropbox->getThumbnail($path, $size);
864 } catch (Dropbox_Exception $e) {
865 return false;
866 }
867 }
868
869 /**
870 * Return content URL
871 *
872 * @param string $hash file hash
873 * @param array $options options
874 * @return array
875 * @author Naoki Sawada
876 **/
877 public function getContentUrl($hash, $options = array()) {
878 if (($file = $this->file($hash)) == false || !$file['url'] || $file['url'] == 1) {
879 $path = $this->decode($hash);
880 $cache = $this->getDBdat($path);
881 $url = '';
882 if (isset($cache['share']) && strpos($cache['share'], $this->dropbox_dlhost) !== false) {
883 $res = $this->getHttpResponseHeader($cache['share']);
884 if (preg_match("/^HTTP\/[01\.]+ ([0-9]{3})/", $res, $match)) {
885 if ($match[1] < 400) {
886 $url = $cache['share'];
887 }
888 }
889 }
890 if (! $url) {
891 try {
892 $res = $this->dropbox->share($path, null, false);
893 $url = $res['url'];
894 if (strpos($url, 'www.dropbox.com') === false) {
895 $res = $this->getHttpResponseHeader($url);
896 if (preg_match('/^location:\s*(http[^\s]+)/im', $res, $match)) {
897 $url = $match[1];
898 }
899 }
900 list($url) = explode('?', $url);
901 $url = str_replace('www.dropbox.com', $this->dropbox_dlhost, $url);
902 if (! isset($cache['share']) || $cache['share'] !== $url) {
903 $cache['share'] = $url;
904 $this->updateDBdat($path, $cache);
905 }
906 } catch (Dropbox_Exception $e) {
907 return false;
908 }
909 }
910 return $url;
911 }
912 return $file['url'];
913 }
914
915 /**
916 * Get HTTP request response header string
917 *
918 * @param string $url target URL
919 * @return string
920 * @author Naoki Sawada
921 */
922 private function getHttpResponseHeader($url) {
923 if (function_exists('curl_exec')) {
924
925 $c = curl_init();
926 curl_setopt( $c, CURLOPT_RETURNTRANSFER, true );
927 curl_setopt( $c, CURLOPT_CUSTOMREQUEST, 'HEAD' );
928 curl_setopt( $c, CURLOPT_HEADER, 1 );
929 curl_setopt( $c, CURLOPT_NOBODY, true );
930 curl_setopt( $c, CURLOPT_URL, $url );
931 $res = curl_exec( $c );
932
933 } else {
934
935 require_once 'HTTP/Request2.php';
936 try {
937 $request2 = new HTTP_Request2();
938 $request2->setConfig(array(
939 'ssl_verify_peer' => false,
940 'ssl_verify_host' => false
941 ));
942 $request2->setUrl($url);
943 $request2->setMethod(HTTP_Request2::METHOD_HEAD);
944 $result = $request2->send();
945 $res = array();
946 $res[] = 'HTTP/'.$result->getVersion().' '.$result->getStatus().' '.$result->getReasonPhrase();
947 foreach($result->getHeader() as $key => $val) {
948 $res[] = $key . ': ' . $val;
949 }
950 $res = join("\r\n", $res);
951 } catch( HTTP_Request2_Exception $e ){
952 $res = '';
953 } catch (Exception $e){
954 $res = '';
955 }
956
957 }
958 return $res;
959 }
960
961 /*********************** paths/urls *************************/
962
963 /**
964 * Return parent directory path
965 *
966 * @param string $path file path
967 * @return string
968 * @author Dmitry (dio) Levashov
969 **/
970 protected function _dirname($path) {
971 return $this->_normpath(substr($path, 0, strrpos($path, '/')));
972 }
973
974 /**
975 * Return file name
976 *
977 * @param string $path file path
978 * @return string
979 * @author Dmitry (dio) Levashov
980 **/
981 protected function _basename($path) {
982 return substr($path, strrpos($path, '/') + 1);
983 }
984
985 /**
986 * Join dir name and file name and retur full path
987 *
988 * @param string $dir
989 * @param string $name
990 * @return string
991 * @author Dmitry (dio) Levashov
992 **/
993 protected function _joinPath($dir, $name) {
994 return $this->_normpath($dir.'/'.$name);
995 }
996
997 /**
998 * Return normalized path, this works the same as os.path.normpath() in Python
999 *
1000 * @param string $path path
1001 * @return string
1002 * @author Troex Nevelin
1003 **/
1004 protected function _normpath($path) {
1005 $path = '/' . ltrim($path, '/');
1006 return $path;
1007 }
1008
1009 /**
1010 * Return file path related to root dir
1011 *
1012 * @param string $path file path
1013 * @return string
1014 * @author Dmitry (dio) Levashov
1015 **/
1016 protected function _relpath($path) {
1017 return $path;
1018 }
1019
1020 /**
1021 * Convert path related to root dir into real path
1022 *
1023 * @param string $path file path
1024 * @return string
1025 * @author Dmitry (dio) Levashov
1026 **/
1027 protected function _abspath($path) {
1028 return $path;
1029 }
1030
1031 /**
1032 * Return fake path started from root dir
1033 *
1034 * @param string $path file path
1035 * @return string
1036 * @author Dmitry (dio) Levashov
1037 **/
1038 protected function _path($path) {
1039 return $this->rootName . $this->_normpath(substr($path, strlen($this->root)));
1040 }
1041
1042 /**
1043 * Return true if $path is children of $parent
1044 *
1045 * @param string $path path to check
1046 * @param string $parent parent path
1047 * @return bool
1048 * @author Dmitry (dio) Levashov
1049 **/
1050 protected function _inpath($path, $parent) {
1051 return $path == $parent || strpos($path, $parent.'/') === 0;
1052 }
1053
1054 /***************** file stat ********************/
1055 /**
1056 * Return stat for given path.
1057 * Stat contains following fields:
1058 * - (int) size file size in b. required
1059 * - (int) ts file modification time in unix time. required
1060 * - (string) mime mimetype. required for folders, others - optionally
1061 * - (bool) read read permissions. required
1062 * - (bool) write write permissions. required
1063 * - (bool) locked is object locked. optionally
1064 * - (bool) hidden is object hidden. optionally
1065 * - (string) alias for symlinks - link target path relative to root path. optionally
1066 * - (string) target for symlinks - link target path. optionally
1067 *
1068 * If file does not exists - returns empty array or false.
1069 *
1070 * @param string $path file path
1071 * @return array|false
1072 * @author Dmitry (dio) Levashov
1073 **/
1074 protected function _stat($path) {
1075 //if (!empty($this->ARGS['reload']) && isset($this->ARGS['target']) && strpos($this->ARGS['target'], $this->id) === 0) {
1076 if ($this->isMyReload()) {
1077 $this->deltaCheck();
1078 }
1079 if ($raw = $this->getDBdat($path)) {
1080 return $this->parseRaw($raw);
1081 }
1082 return false;
1083 }
1084
1085 /**
1086 * Return true if path is dir and has at least one childs directory
1087 *
1088 * @param string $path dir path
1089 * @return bool
1090 * @author Dmitry (dio) Levashov
1091 **/
1092 protected function _subdirs($path) {
1093 return ($stat = $this->stat($path)) && isset($stat['dirs']) ? $stat['dirs'] : false;
1094 }
1095
1096 /**
1097 * Return object width and height
1098 * Ususaly used for images, but can be realize for video etc...
1099 *
1100 * @param string $path file path
1101 * @param string $mime file mime type
1102 * @return string
1103 * @author Dmitry (dio) Levashov
1104 **/
1105 protected function _dimensions($path, $mime) {
1106 if (strpos($mime, 'image') !== 0) return '';
1107 $cache = $this->getDBdat($path);
1108 if (isset($cache['width']) && isset($cache['height'])) {
1109 return $cache['width'].'x'.$cache['height'];
1110 }
1111 $ret = '';
1112 if ($work = $this->getWorkFile($path)) {
1113 if ($size = getimagesize($work)) {
1114 $cache['width'] = $size[0];
1115 $cache['height'] = $size[1];
1116 $this->updateDBdat($path, $cache);
1117 $ret = $size[0].'x'.$size[1];
1118 }
1119 }
1120 is_file($work) && unlink($work);
1121 return $ret;
1122 }
1123
1124 /******************** file/dir content *********************/
1125
1126 /**
1127 * Return files list in directory.
1128 *
1129 * @param string $path dir path
1130 * @return array
1131 * @author Dmitry (dio) Levashov
1132 * @author Cem (DiscoFever)
1133 **/
1134 protected function _scandir($path) {
1135 return isset($this->dirsCache[$path])
1136 ? $this->dirsCache[$path]
1137 : $this->cacheDir($path);
1138 }
1139
1140 /**
1141 * Open file and return file pointer
1142 *
1143 * @param string $path file path
1144 * @param string $mode
1145 * @return false|resource
1146 * @internal param bool $write open file for writing
1147 * @author Dmitry (dio) Levashov
1148 */
1149 protected function _fopen($path, $mode='rb') {
1150
1151 if (($mode == 'rb' || $mode == 'r')) {
1152 try {
1153 $res = $this->dropbox->media($path);
1154 $url = parse_url($res['url']);
1155 $fp = stream_socket_client('ssl://'.$url['host'].':443');
1156 fputs($fp, "GET {$url['path']} HTTP/1.0\r\n");
1157 fputs($fp, "Host: {$url['host']}\r\n");
1158 fputs($fp, "\r\n");
1159 while(trim(fgets($fp)) !== ''){};
1160 return $fp;
1161 } catch (Dropbox_Exception $e) {
1162 return false;
1163 }
1164 }
1165
1166 if ($this->tmp) {
1167 $contents = $this->_getContents($path);
1168
1169 if ($contents === false) {
1170 return false;
1171 }
1172
1173 if ($local = $this->getTempFile($path)) {
1174 if (file_put_contents($local, $contents, LOCK_EX) !== false) {
1175 return fopen($local, $mode);
1176 }
1177 }
1178 }
1179
1180 return false;
1181 }
1182
1183 /**
1184 * Close opened file
1185 *
1186 * @param resource $fp file pointer
1187 * @param string $path
1188 * @return bool
1189 * @author Dmitry (dio) Levashov
1190 */
1191 protected function _fclose($fp, $path='') {
1192 fclose($fp);
1193 if ($path) {
1194 unlink($this->getTempFile($path));
1195 }
1196 }
1197
1198 /******************** file/dir manipulations *************************/
1199
1200 /**
1201 * Create dir and return created dir path or false on failed
1202 *
1203 * @param string $path parent dir path
1204 * @param string $name new directory name
1205 * @return string|bool
1206 * @author Dmitry (dio) Levashov
1207 **/
1208 protected function _mkdir($path, $name) {
1209 $path = $this->_normpath($path.'/'.$name);
1210 try {
1211 $this->dropbox->createFolder($path);
1212 } catch (Dropbox_Exception $e) {
1213 $this->deltaCheck();
1214 if ($this->dir($this->encode($path))) {
1215 return $path;
1216 }
1217 return $this->setError('Dropbox error: '.$e->getMessage());
1218 }
1219 $this->deltaCheck();
1220 return $path;
1221 }
1222
1223 /**
1224 * Create file and return it's path or false on failed
1225 *
1226 * @param string $path parent dir path
1227 * @param string $name new file name
1228 * @return string|bool
1229 * @author Dmitry (dio) Levashov
1230 **/
1231 protected function _mkfile($path, $name) {
1232 return $this->_filePutContents($path.'/'.$name, '');
1233 }
1234
1235 /**
1236 * Create symlink. FTP driver does not support symlinks.
1237 *
1238 * @param string $target link target
1239 * @param string $path symlink path
1240 * @param string $name
1241 * @return bool
1242 * @author Dmitry (dio) Levashov
1243 */
1244 protected function _symlink($target, $path, $name) {
1245 return false;
1246 }
1247
1248 /**
1249 * Copy file into another file
1250 *
1251 * @param string $source source file path
1252 * @param string $targetDir target directory path
1253 * @param string $name new file name
1254 * @return bool
1255 * @author Dmitry (dio) Levashov
1256 **/
1257 protected function _copy($source, $targetDir, $name) {
1258 $path = $this->_normpath($targetDir.'/'.$name);
1259 try {
1260 $this->dropbox->copy($source, $path);
1261 } catch (Dropbox_Exception $e) {
1262 return $this->setError('Dropbox error: '.$e->getMessage());
1263 }
1264 $this->deltaCheck();
1265 return true;
1266 }
1267
1268 /**
1269 * Move file into another parent dir.
1270 * Return new file path or false.
1271 *
1272 * @param string $source source file path
1273 * @param $targetDir
1274 * @param string $name file name
1275 * @return bool|string
1276 * @internal param string $target target dir path
1277 * @author Dmitry (dio) Levashov
1278 */
1279 protected function _move($source, $targetDir, $name) {
1280 $target = $this->_normpath($targetDir.'/'.$name);
1281 try {
1282 $this->dropbox->move($source, $target);
1283 } catch (Dropbox_Exception $e) {
1284 return $this->setError('Dropbox error: '.$e->getMessage());
1285 }
1286 $this->deltaCheck();
1287 return $target;
1288 }
1289
1290 /**
1291 * Remove file
1292 *
1293 * @param string $path file path
1294 * @return bool
1295 * @author Dmitry (dio) Levashov
1296 **/
1297 protected function _unlink($path) {
1298 try {
1299 $this->dropbox->delete($path);
1300 } catch (Dropbox_Exception $e) {
1301 return $this->setError('Dropbox error: '.$e->getMessage());
1302 }
1303 $this->deltaCheck();
1304 return true;
1305 }
1306
1307 /**
1308 * Remove dir
1309 *
1310 * @param string $path dir path
1311 * @return bool
1312 * @author Dmitry (dio) Levashov
1313 **/
1314 protected function _rmdir($path) {
1315 return $this->_unlink($path);
1316 }
1317
1318 /**
1319 * Create new file and write into it from file pointer.
1320 * Return new file path or false on error.
1321 *
1322 * @param resource $fp file pointer
1323 * @param string $path
1324 * @param string $name file name
1325 * @param array $stat file stat (required by some virtual fs)
1326 * @return bool|string
1327 * @internal param string $dir target dir path
1328 * @author Dmitry (dio) Levashov
1329 */
1330 protected function _save($fp, $path, $name, $stat) {
1331 if ($name) $path .= '/'.$name;
1332 $path = $this->_normpath($path);
1333 try {
1334 $this->dropbox->putFile($path, $fp);
1335 } catch (Dropbox_Exception $e) {
1336 return $this->setError('Dropbox error: '.$e->getMessage());
1337 }
1338 $this->deltaCheck();
1339 if (is_array($stat)) {
1340 $raw = $this->getDBdat($path);
1341 if (isset($stat['width'])) $raw['width'] = $stat['width'];
1342 if (isset($stat['height'])) $raw['height'] = $stat['height'];
1343 $this->updateDBdat($path, $raw);
1344 }
1345 return $path;
1346 }
1347
1348 /**
1349 * Get file contents
1350 *
1351 * @param string $path file path
1352 * @return string|false
1353 * @author Dmitry (dio) Levashov
1354 **/
1355 protected function _getContents($path) {
1356 $contents = '';
1357 try {
1358 $contents = $this->dropbox->getFile($path);
1359 } catch (Dropbox_Exception $e) {
1360 return $this->setError('Dropbox error: '.$e->getMessage());
1361 }
1362 return $contents;
1363 }
1364
1365 /**
1366 * Write a string to a file
1367 *
1368 * @param string $path file path
1369 * @param string $content new file content
1370 * @return bool
1371 * @author Dmitry (dio) Levashov
1372 **/
1373 protected function _filePutContents($path, $content) {
1374 $res = false;
1375
1376 if ($local = $this->getTempFile($path)) {
1377 if (file_put_contents($local, $content, LOCK_EX) !== false
1378 && ($fp = fopen($local, 'rb'))) {
1379 clearstatcache();
1380 $res = $this->_save($fp, $path, '', array());
1381 fclose($fp);
1382 }
1383 file_exists($local) && unlink($local);
1384 }
1385
1386 return $res;
1387 }
1388
1389 /**
1390 * Detect available archivers
1391 *
1392 * @return array
1393 **/
1394 protected function _checkArchivers() {
1395 // die('Not yet implemented. (_checkArchivers)');
1396 return array();
1397 }
1398
1399 /**
1400 * chmod implementation
1401 *
1402 * @param string $path
1403 * @param string $mode
1404 * @return bool
1405 */
1406 protected function _chmod($path, $mode) {
1407 return false;
1408 }
1409
1410 /**
1411 * Unpack archive
1412 *
1413 * @param string $path archive path
1414 * @param array $arc archiver command and arguments (same as in $this->archivers)
1415 * @return true
1416 * @return void
1417 * @author Dmitry (dio) Levashov
1418 * @author Alexey Sukhotin
1419 **/
1420 protected function _unpack($path, $arc) {
1421 die('Not yet implemented. (_unpack)');
1422 }
1423
1424 /**
1425 * Recursive symlinks search
1426 *
1427 * @param string $path file/dir path
1428 * @return bool
1429 * @author Dmitry (dio) Levashov
1430 **/
1431 protected function _findSymlinks($path) {
1432 die('Not yet implemented. (_findSymlinks)');
1433 }
1434
1435 /**
1436 * Extract files from archive
1437 *
1438 * @param string $path archive path
1439 * @param array $arc archiver command and arguments (same as in $this->archivers)
1440 * @return true
1441 * @author Dmitry (dio) Levashov,
1442 * @author Alexey Sukhotin
1443 **/
1444 protected function _extract($path, $arc) {
1445 die('Not yet implemented. (_extract)');
1446
1447 }
1448
1449 /**
1450 * Create archive and return its path
1451 *
1452 * @param string $dir target dir
1453 * @param array $files files names list
1454 * @param string $name archive name
1455 * @param array $arc archiver options
1456 * @return string|bool
1457 * @author Dmitry (dio) Levashov,
1458 * @author Alexey Sukhotin
1459 **/
1460 protected function _archive($dir, $files, $name, $arc) {
1461 die('Not yet implemented. (_archive)');
1462 }
1463
1464 } // END class
1465