Issues (1107)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

lib/elFinderVolumeDropbox2.class.php (5 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
use Kunnu\Dropbox\Dropbox;
4
use Kunnu\Dropbox\DropboxApp;
5
use Kunnu\Dropbox\DropboxFile;
6
use Kunnu\Dropbox\Models\FileMetadata;
7
use Kunnu\Dropbox\Models\FolderMetadata;
8
use Kunnu\Dropbox\Exceptions\DropboxClientException;
9
10
elFinder::$netDrivers['dropbox2'] = 'Dropbox2';
11
12
/**
13
 * Simple elFinder driver for Dropbox
14
 * kunalvarma05/dropbox-php-sdk:0.1.5 or above.
15
 *
16
 * @author Naoki Sawada
17
 **/
18
class elFinderVolumeDropbox2 extends elFinderVolumeDriver
19
{
20
    /**
21
     * Net mount key.
22
     *
23
     * @var string
24
     **/
25
    public $netMountKey = '';
26
    /**
27
     * Driver id
28
     * Must be started from letter and contains [a-z0-9]
29
     * Used as part of volume id.
30
     *
31
     * @var string
32
     **/
33
    protected $driverId = 'db';
34
35
    /**
36
     * Dropbox service object.
37
     *
38
     * @var object
39
     **/
40
    protected $service = null;
41
42
    /**
43
     * Directory for tmp files
44
     * If not set driver will try to use tmbDir as tmpDir.
45
     *
46
     * @var string
47
     **/
48
    protected $tmp = '';
49
50
    /**
51
     * Fetch options.
52
     *
53
     * @var string
54
     */
55
    private $FETCH_OPTIONS = [];
56
57
    /**
58
     * Constructor
59
     * Extend options with required fields.
60
     *
61
     * @author Naoki Sawada
62
     **/
63 View Code Duplication
    public function __construct()
64
    {
65
        $opts = [
66
            'app_key' => '',
67
            'app_secret' => '',
68
            'access_token' => '',
69
            'aliasFormat' => '%s@Dropbox',
70
            'path' => '/',
71
            'separator' => '/',
72
            'acceptedName' => '#^[^/\\?*:|"<>]*[^./\\?*:|"<>]$#',
73
            'rootCssClass' => 'elfinder-navbar-root-dropbox',
74
            'publishPermission' => [
75
                'requested_visibility' => 'public',
76
                //'link_password' => '',
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
77
                //'expires' => '',
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
78
            ],
79
            'getThumbSize' => 'medium', // Available sizes: 'thumb', 'small', 'medium', 'large', 'huge'
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
80
        ];
81
        $this->options = array_merge($this->options, $opts);
82
        $this->options['mimeDetect'] = 'internal';
83
    }
84
85
    /**
86
     * Get OAuth2 access token form OAuth1 tokens.
87
     *
88
     * @param string $app_key
89
     * @param string $app_secret
90
     * @param string $oauth1_token
91
     * @param string $oauth1_secret
92
     *
93
     * @return string|false
94
     */
95
    public static function getTokenFromOauth1($app_key, $app_secret, $oauth1_token, $oauth1_secret)
96
    {
97
        $data = [
98
                'oauth1_token' => $oauth1_token,
99
                'oauth1_token_secret' => $oauth1_secret,
100
        ];
101
        $auth = base64_encode($app_key.':'.$app_secret);
102
103
        $ch = curl_init('https://api.dropboxapi.com/2/auth/token/from_oauth1');
104
        curl_setopt($ch, CURLOPT_POST, true);
105
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
106
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
107
            'Content-Type: application/json',
108
            'Authorization: Basic '.$auth,
109
        ]);
110
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
111
        $result = curl_exec($ch);
112
        curl_close($ch);
113
114
        $res = $result ? json_decode($result, true) : [];
115
116
        return isset($res['oauth2_token']) ? $res['oauth2_token'] : false;
117
    }
118
119
    /*********************************************************************/
120
    /*                        EXTENDED FUNCTIONS                         */
121
    /*********************************************************************/
122
123
    /**
124
     * Prepare
125
     * Call from elFinder::netmout() before volume->mount().
126
     *
127
     * @return array
128
     *
129
     * @author Naoki Sawada
130
     **/
131
    public function netmountPrepare($options)
132
    {
133
        if (empty($options['app_key']) && defined('ELFINDER_DROPBOX_APPKEY')) {
134
            $options['app_key'] = ELFINDER_DROPBOX_APPKEY;
135
        }
136
        if (empty($options['app_secret']) && defined('ELFINDER_DROPBOX_APPSECRET')) {
137
            $options['app_secret'] = ELFINDER_DROPBOX_APPSECRET;
138
        }
139
140
        if (! isset($options['pass'])) {
141
            $options['pass'] = '';
142
        }
143
144
        try {
145
            $this->session->start();
146
            $app = new DropboxApp($options['app_key'], $options['app_secret']);
147
            $dropbox = new Dropbox($app);
148
            $authHelper = $dropbox->getAuthHelper();
149
150
            if ($options['pass'] === 'reauth') {
151
                $options['pass'] = '';
152
                $this->session->set('Dropbox2AuthParams', [])->set('Dropbox2Tokens', []);
153
            } elseif ($options['pass'] === 'dropbox2') {
154
                $options['pass'] = '';
155
            }
156
157
            $options = array_merge($this->session->get('Dropbox2AuthParams', []), $options);
158
159
            if (! isset($options['tokens'])) {
160
                $options['tokens'] = $this->session->get('Dropbox2Tokens', []);
161
                $this->session->remove('Dropbox2Tokens');
162
            }
163
            $aToken = $options['tokens'];
164
            if (! is_array($aToken) || ! isset($aToken['access_token'])) {
165
                $aToken = [];
166
            }
167
168
            $rootObj = $service = null;
169
            if ($aToken) {
170
                try {
171
                    $dropbox->setAccessToken($aToken['access_token']);
172
                    $this->session->set('Dropbox2AuthParams', $options);
173
                } catch (DropboxClientException $e) {
174
                    $aToken = [];
175
                    $options['tokens'] = [];
176
                    if ($options['user'] !== 'init') {
177
                        $this->session->set('Dropbox2AuthParams', $options);
178
179
                        return ['exit' => true, 'error' => elFinder::ERROR_REAUTH_REQUIRE];
180
                    }
181
                }
182
            }
183
184
            if ($options['user'] === 'init') {
185
                if (empty($options['url'])) {
186
                    $options['url'] = elFinder::getConnectorUrl();
187
                }
188
189
                $callback = $options['url']
190
                           .'?cmd=netmount&protocol=dropbox2&host=1';
191
192
                if (! $aToken && empty($_GET['code'])) {
193
                    $url = $authHelper->getAuthUrl($callback);
194
195
                    $html = '<input id="elf-volumedriver-dropbox2-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.'\')">';
196
                    $html .= '<script>
197
                        $("#'.$options['id'].'").elfinder("instance").trigger("netmount", {protocol: "dropbox2", mode: "makebtn"});
198
                    </script>';
199 View Code Duplication
                    if (empty($options['pass']) && $options['host'] !== '1') {
200
                        $options['pass'] = 'return';
201
                        $this->session->set('Dropbox2AuthParams', $options);
202
203
                        return ['exit' => true, 'body' => $html];
204
                    } else {
205
                        $out = [
206
                            'node' => $options['id'],
207
                            'json' => '{"protocol": "dropbox2", "mode": "makebtn", "body" : "'.str_replace($html, '"', '\\"').'", "error" : "'.elFinder::ERROR_ACCESS_DENIED.'"}',
208
                            'bind' => 'netmount',
209
                        ];
210
211
                        return ['exit' => 'callback', 'out' => $out];
212
                    }
213
                } else {
214
                    if (! empty($_GET['code']) && isset($_GET['state'])) {
215
                        $tokenObj = $authHelper->getAccessToken($_GET['code'], $_GET['state'], $callback);
216
                        $options['tokens'] = [
217
                            'access_token' => $tokenObj->getToken(),
218
                            'uid' => $tokenObj->getUid(),
219
                        ];
220
                        $this->session->set('Dropbox2Tokens', $options['tokens'])->set('Dropbox2AuthParams', $options);
221
                        $out = [
222
                            'node' => $options['id'],
223
                            'json' => '{"protocol": "dropbox2", "mode": "done", "reset": 1}',
224
                            'bind' => 'netmount',
225
                        ];
226
227
                        return ['exit' => 'callback', 'out' => $out];
228
                    }
229
                    $path = $options['path'];
230
                    $folders = [];
231
                    $listFolderContents = $dropbox->listFolder($path);
232
                    $items = $listFolderContents->getItems();
233
                    foreach ($items as $item) {
234
                        $data = $item->getData();
235
                        if ($data['.tag'] === 'folder') {
236
                            $folders[$data['path_lower']] = $data['name'];
237
                        }
238
                    }
239
                    natcasesort($folders);
240
241
                    if ($options['pass'] === 'folders') {
242
                        return ['exit' => true, 'folders' => $folders];
243
                    }
244
245
                    $folders = ['/' => '/'] + $folders;
246
                    $folders = json_encode($folders);
247
                    $json = '{"protocol": "dropbox2", "mode": "done", "folders": '.$folders.'}';
248
                    $options['pass'] = 'return';
249
                    $html = 'Dropbox.com';
250
                    $html .= '<script>
251
                        $("#'.$options['id'].'").elfinder("instance").trigger("netmount", '.$json.');
252
                    </script>';
253
                    $this->session->set('Dropbox2AuthParams', $options);
254
255
                    return ['exit' => true, 'body' => $html];
256
                }
257
            }
258
        } catch (DropboxClientException $e) {
259
            $this->session->remove('Dropbox2AuthParams')->remove('Dropbox2Tokens');
260 View Code Duplication
            if (empty($options['pass'])) {
261
                return ['exit' => true, 'body' => '{msg:'.elFinder::ERROR_ACCESS_DENIED.'}'.' '.$e->getMessage()];
262
            } else {
263
                return ['exit' => true, 'error' => [elFinder::ERROR_ACCESS_DENIED, $e->getMessage()]];
264
            }
265
        }
266
267
        if (! $aToken) {
268
            return ['exit' => true, 'error' => elFinder::ERROR_REAUTH_REQUIRE];
269
        }
270
271
        if ($options['path'] === 'root') {
272
            $options['path'] = '/';
273
        }
274
275
        try {
276
            if ($options['path'] !== '/') {
277
                $file = $dropbox->getMetadata($options['path']);
278
                $name = $file->getName();
279
            } else {
280
                $name = 'root';
281
            }
282
            $options['alias'] = sprintf($this->options['aliasFormat'], $name);
283
        } catch (DropboxClientException $e) {
284
            return ['exit' => true, 'error' => $e->getMessage()];
285
        }
286
287 View Code Duplication
        foreach (['host', 'user', 'pass', 'id', 'offline'] as $key) {
288
            unset($options[$key]);
289
        }
290
291
        return $options;
292
    }
293
294
    /**
295
     * process of on netunmount
296
     * Drop `Dropbox` & rm thumbs.
297
     *
298
     * @param array $options
299
     *
300
     * @return bool
301
     */
302
    public function netunmount($netVolumes, $key)
303
    {
304
        if ($tmbs = glob(rtrim($this->options['tmbPath'], '\\/').DIRECTORY_SEPARATOR.$this->driverId.'_'.$this->options['tokens']['uid'].'*.png')) {
305
            foreach ($tmbs as $file) {
306
                unlink($file);
307
            }
308
        }
309
310
        return true;
311
    }
312
313
    /*********************************************************************/
314
    /*                               FS API                              */
315
    /*********************************************************************/
316
317
    /**
318
     * Close opened connection.
319
     **/
320
    public function umount()
321
    {
322
    }
323
324
    /**
325
     * Return content URL (for netmout volume driver)
326
     * If file.url == 1 requests from JavaScript client with XHR.
327
     *
328
     * @param string $hash    file hash
329
     * @param array  $options options array
330
     *
331
     * @return bool|string
332
     *
333
     * @author Naoki Sawada
334
     */
335
    public function getContentUrl($hash, $options = [])
336
    {
337 View Code Duplication
        if (! empty($options['temporary'])) {
338
            // try make temporary file
339
            $url = parent::getContentUrl($hash, $options);
340
            if ($url) {
341
                return $url;
342
            }
343
        }
344
        $file = $this->file($hash);
345
        if (($file = $this->file($hash)) !== false && (! $file['url'] || $file['url'] == 1)) {
346
            $path = $this->decode($hash);
347
            $url = '';
348
            try {
349
                $res = $this->service->postToAPI('/sharing/list_shared_links', ['path' => $path, 'direct_only' => true])->getDecodedBody();
350
                if ($res && ! empty($res['links'])) {
351
                    foreach ($res['links'] as $link) {
352
                        if (isset($link['link_permissions'])
353
                                && isset($link['link_permissions']['requested_visibility'])
354
                                && $link['link_permissions']['requested_visibility']['.tag'] === $this->options['publishPermission']['requested_visibility']) {
355
                            $url = $link['url'];
356
                            break;
357
                        }
358
                    }
359
                }
360
                if (! $url) {
361
                    $res = $this->service->postToAPI('/sharing/create_shared_link_with_settings', ['path' => $path, 'settings' => $this->options['publishPermission']])->getDecodedBody();
362
                    if (isset($res['url'])) {
363
                        $url = $res['url'];
364
                    }
365
                }
366
                if ($url) {
367
                    $url = str_replace('www.dropbox.com', 'dl.dropboxusercontent.com', $url);
368
                    $url = str_replace('?dl=0', '', $url);
369
370
                    return $url;
371
                }
372
            } catch (DropboxClientException $e) {
373
                return $this->$this->setError('Dropbox error: '.$e->getMessage());
374
            }
375
        }
376
377
        return false;
378
    }
379
380
    /**
381
     * Return debug info for client.
382
     *
383
     * @return array
384
     **/
385
    public function debug()
386
    {
387
        $res = parent::debug();
388
        if (isset($this->options['tokens']) && ! empty($this->options['tokens']['uid'])) {
389
            $res['Dropbox uid'] = $this->options['tokens']['uid'];
390
            $res['access_token'] = $this->options['tokens']['access_token'];
391
        }
392
393
        return $res;
394
    }
395
396
    /*********************************************************************/
397
    /*                        ORIGINAL FUNCTIONS                         */
398
    /*********************************************************************/
399
400
    /**
401
     * Get Parent ID, Item ID, Parent Path as an array from path.
402
     *
403
     * @param string $path
404
     *
405
     * @return array
406
     */
407
    protected function _db_splitPath($path)
408
    {
409
        $path = trim($path, '/');
410
        if ($path === '') {
411
            $dirname = '/';
412
            $basename = '';
413
        } else {
414
            $pos = strrpos($path, '/');
415
            if ($pos === false) {
416
                $dirname = '/';
417
                $basename = $path;
418
            } else {
419
                $dirname = '/'.substr($path, 0, $pos);
420
                $basename = substr($path, $pos + 1);
421
            }
422
        }
423
424
        return [$dirname, $basename];
425
    }
426
427
    /**
428
     * Parse line from Dropbox metadata output and return file stat (array).
429
     *
430
     * @param string $raw line from ftp_rawlist() output
431
     *
432
     * @return array
433
     *
434
     * @author Naoki Sawada
435
     **/
436
    protected function _db_parseRaw($raw)
437
    {
438
        $stat = [];
439
        $isFolder = false;
440
        if ($raw === true) {
441
            // root folder
442
            $isFolder = true;
443
            $stat['name'] = '';
444
            $stat['iid'] = '0';
445
        }
446
447
        $data = [];
448
        if (is_object($raw)) {
449
            $isFolder = $raw instanceof FolderMetadata;
450
            $data = $raw->getData();
451
        } elseif (is_array($raw)) {
452
            $isFolder = $raw['.tag'] === 'folder';
453
            $data = $raw;
454
        }
455
456
        if (isset($data['path_lower'])) {
457
            $stat['path'] = $data['path_lower'];
458
        }
459
460
        if (isset($data['name'])) {
461
            $stat['name'] = $data['name'];
462
        }
463
464
        if (isset($data['id'])) {
465
            $stat['iid'] = substr($data['id'], 3);
466
        }
467
468
        if ($isFolder) {
469
            $stat['mime'] = 'directory';
470
            $stat['size'] = 0;
471
            $stat['ts'] = 0;
472
            $stat['dirs'] = -1;
473
        } else {
474
            $stat['size'] = isset($data['size']) ? (int) $data['size'] : 0;
475
            if (isset($data['server_modified'])) {
476
                $stat['ts'] = strtotime($data['server_modified']);
477
            } elseif (isset($data['client_modified'])) {
478
                $stat['ts'] = strtotime($data['client_modified']);
479
            } else {
480
                $stat['ts'] = 0;
481
            }
482
            $stat['url'] = '1';
483
        }
484
485
        return $stat;
486
    }
487
488
    /**
489
     * Get thumbnail from Dropbox.
490
     *
491
     * @param string $path
492
     * @param string $size
493
     *
494
     * @return string | boolean
495
     */
496
    protected function _db_getThumbnail($path)
497
    {
498
        try {
499
            return $this->service->getThumbnail($path, $this->options['getThumbSize'])->getContents();
500
        } catch (DropboxClientException $e) {
501
            return false;
502
        }
503
    }
504
505
    /**
506
     * Join dir name and file name(display name) and retur full path.
507
     *
508
     * @param unknown $dir
509
     * @param unknown $displayName
510
     *
511
     * @return string
512
     */
513
    protected function _db_joinName($dir, $displayName)
514
    {
515
        return rtrim($dir, '/').'/'.$displayName;
516
    }
517
518
    /*********************************************************************/
519
    /*                        INIT AND CONFIGURE                         */
520
    /*********************************************************************/
521
522
    /**
523
     * Prepare FTP connection
524
     * Connect to remote server and check if credentials are correct, if so, store the connection id in $ftp_conn.
525
     *
526
     * @return bool
527
     *
528
     * @author Naoki Sawada
529
     **/
530
    protected function init()
531
    {
532
        if (empty($options['app_key'])) {
533
            if (defined('ELFINDER_DROPBOX_APPKEY') && ELFINDER_DROPBOX_APPKEY) {
534
                $this->options['app_key'] = ELFINDER_DROPBOX_APPKEY;
535
            } else {
536
                return $this->setError('Required option "app_key" is undefined.');
537
            }
538
        }
539
        if (empty($options['app_secret'])) {
540
            if (defined('ELFINDER_DROPBOX_APPSECRET') && ELFINDER_DROPBOX_APPSECRET) {
541
                $this->options['app_secret'] = ELFINDER_DROPBOX_APPSECRET;
542
            } else {
543
                return $this->setError('Required option "app_secret" is undefined.');
544
            }
545
        }
546 View Code Duplication
        if (isset($this->options['tokens']) && is_array($this->options['tokens']) && ! empty($this->options['tokens']['access_token'])) {
547
            $this->options['access_token'] = $this->options['tokens']['access_token'];
548
        }
549
        if (! $this->options['access_token']) {
550
            return $this->setError('Required option "access_token" or "refresh_token" is undefined.');
551
        }
552
553
        try {
554
            // make net mount key for network mount
555
            $aToken = $this->options['access_token'];
556
            $this->netMountKey = md5($aToken.'-'.$this->options['path']);
557
558
            $errors = [];
559
            if (! $this->service) {
560
                $app = new DropboxApp($this->options['app_key'], $this->options['app_secret'], $aToken);
561
                $this->service = new Dropbox($app);
562
            }
563
        } catch (DropboxClientException $e) {
564
            $errors[] = 'Dropbox error: '.$e->getMessage();
565
        } catch (Exception $e) {
566
            $errors[] = $e->getMessage();
567
        }
568
569
        if (! $this->service) {
570
            $errors[] = 'Dropbox Service could not be loaded.';
571
572
            return $this->setError($errors);
573
        }
574
575
        // normalize root path
576
        $this->options['path'] = strtolower($this->options['path']);
577
        if ($this->options['path'] == 'root') {
578
            $this->options['path'] = '/';
579
        }
580
        $this->root = $this->options['path'] = $this->_normpath($this->options['path']);
581
582 View Code Duplication
        if (empty($this->options['alias'])) {
583
            $this->options['alias'] = sprintf($this->options['aliasFormat'], ($this->options['path'] === '/') ? 'root' : $this->_basename($this->options['path']));
584
        }
585
586
        $this->rootName = $this->options['alias'];
587
588
        if (! empty($this->options['tmpPath'])) {
589
            if ((is_dir($this->options['tmpPath']) || mkdir($this->options['tmpPath'])) && is_writable($this->options['tmpPath'])) {
590
                $this->tmp = $this->options['tmpPath'];
591
            }
592
        }
593
594
        if (! $this->tmp && ($tmp = elFinder::getStaticVar('commonTempPath'))) {
595
            $this->tmp = $tmp;
596
        }
597
598
        // This driver dose not support `syncChkAsTs`
599
        $this->options['syncChkAsTs'] = false;
600
601
        // 'lsPlSleep' minmum 10 sec
602
        $this->options['lsPlSleep'] = max(10, $this->options['lsPlSleep']);
603
604
        return true;
605
    }
606
607
    /**
608
     * Configure after successfull mount.
609
     *
610
     * @author Naoki Sawada
611
     **/
612 View Code Duplication
    protected function configure()
613
    {
614
        parent::configure();
615
616
        // fallback of $this->tmp
617
        if (! $this->tmp && $this->tmbPathWritable) {
618
            $this->tmp = $this->tmbPath;
619
        }
620
621
        $this->disabled[] = 'archive';
622
        $this->disabled[] = 'extract';
623
624
        if ($this->isMyReload()) {
625
            //$this->_db_getDirectoryData(false);
0 ignored issues
show
Unused Code Comprehensibility introduced by
86% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
626
        }
627
    }
628
629
    /**
630
     * Cache dir contents.
631
     *
632
     * @param string $path dir path
633
     *
634
     * @author Naoki Sawada
635
     **/
636
    protected function cacheDir($path)
637
    {
638
        $this->dirsCache[$path] = [];
639
        $hasDir = false;
640
641
        $res = $this->service->listFolder($path, $this->FETCH_OPTIONS);
642
643
        if ($res) {
644
            $items = $res->getItems()->all();
645
            foreach ($items as $raw) {
646
                if ($stat = $this->_db_parseRaw($raw)) {
647
                    $mountPath = $this->_joinPath($path, $stat['name']);
648
                    $stat = $this->updateCache($mountPath, $stat);
649
                    if (empty($stat['hidden']) && $path !== $mountPath) {
650
                        if (! $hasDir && $stat['mime'] === 'directory') {
651
                            $hasDir = true;
652
                        }
653
                        $this->dirsCache[$path][] = $mountPath;
654
                    }
655
                }
656
            }
657
        }
658
659
        if (isset($this->sessionCache['subdirs'])) {
660
            $this->sessionCache['subdirs'][$path] = $hasDir;
661
        }
662
663
        return $this->dirsCache[$path];
664
    }
665
666
    /**
667
     * Recursive files search.
668
     *
669
     * @param string $path  dir path
670
     * @param string $q     search string
671
     * @param array  $mimes
672
     *
673
     * @return array
674
     *
675
     * @author Naoki Sawada
676
     **/
677
    protected function doSearch($path, $q, $mimes)
678
    {
679
        if ($mimes) {
680
            return parent::doSearch($path, $q, $mimes);
681
        }
682
683
        $timeout = $this->options['searchTimeout'] ? $this->searchStart + $this->options['searchTimeout'] : 0;
684
685
        $searchRes = $this->service->search($path, $q, ['start' => 0, 'max_results' => 1000]);
686
        $items = $searchRes->getItems();
687
        $more = $searchRes->hasMoreItems();
688
        while ($more) {
689
            if ($timeout && $timeout < time()) {
690
                $this->setError(elFinder::ERROR_SEARCH_TIMEOUT, $this->_path($path));
691
                break;
692
            }
693
            $searchRes = $this->service->search($path, $q, ['start' => $searchRes->getCursor(), 'max_results' => 1000]);
694
            $more = $searchRes->hasMoreItems();
695
            $items = $items->merge($searchRes->getItems());
696
        }
697
698
        $result = [];
699
        foreach ($items as $raw) {
700
            if ($stat = $this->_db_parseRaw($raw->getMetadata())) {
701
                $stat = $this->updateCache($stat['path'], $stat);
702
                if (empty($stat['hidden'])) {
703
                    $result[] = $stat;
704
                }
705
            }
706
        }
707
708
        return $result;
709
    }
710
711
    /**
712
     * Copy file/recursive copy dir only in current volume.
713
     * Return new file path or false.
714
     *
715
     * @param string $src  source path
716
     * @param string $dst  destination dir path
717
     * @param string $name new file name (optionaly)
718
     *
719
     * @return string|false
720
     *
721
     * @author Naoki Sawada
722
     **/
723
    protected function copy($src, $dst, $name)
724
    {
725
        $srcStat = $this->stat($src);
726
        $target = $this->_joinPath($dst, $name);
727
        $tgtStat = $this->stat($target);
728
        if ($tgtStat) {
729
            if ($srcStat['mime'] === 'directory') {
730
                return parent::copy($src, $dst, $name);
731
            } else {
732
                $this->_unlink($target);
733
            }
734
        }
735
        $this->clearcache();
736
        if ($res = $this->_copy($src, $dst, $name)) {
737
            $this->added[] = $this->stat($target);
738
            $res = $target;
739
        }
740
741
        return $res;
742
    }
743
744
    /**
745
     * Remove file/ recursive remove dir.
746
     *
747
     * @param string $path  file path
748
     * @param bool   $force try to remove even if file locked
749
     *
750
     * @return bool
751
     *
752
     * @author Naoki Sawada
753
     **/
754 View Code Duplication
    protected function remove($path, $force = false, $recursive = false)
755
    {
756
        $stat = $this->stat($path);
757
        $stat['realpath'] = $path;
758
        $this->rmTmb($stat);
759
        $this->clearcache();
760
761
        if (empty($stat)) {
762
            return $this->setError(elFinder::ERROR_RM, $this->_path($path), elFinder::ERROR_FILE_NOT_FOUND);
763
        }
764
765
        if (! $force && ! empty($stat['locked'])) {
766
            return $this->setError(elFinder::ERROR_LOCKED, $this->_path($path));
767
        }
768
769
        if ($stat['mime'] == 'directory') {
770
            if (! $recursive && ! $this->_rmdir($path)) {
771
                return $this->setError(elFinder::ERROR_RM, $this->_path($path));
772
            }
773
        } else {
774
            if (! $recursive && ! $this->_unlink($path)) {
775
                return $this->setError(elFinder::ERROR_RM, $this->_path($path));
776
            }
777
        }
778
779
        $this->removed[] = $stat;
780
781
        return true;
782
    }
783
784
    /**
785
     * Create thumnbnail and return it's URL on success.
786
     *
787
     * @param string $path file path
788
     * @param string $mime file mime type
789
     *
790
     * @return string|false
791
     *
792
     * @author Naoki Sawada
793
     **/
794 View Code Duplication
    protected function createTmb($path, $stat)
795
    {
796
        if (! $stat || ! $this->canCreateTmb($path, $stat)) {
797
            return false;
798
        }
799
800
        $name = $this->tmbname($stat);
801
        $tmb = $this->tmbPath.DIRECTORY_SEPARATOR.$name;
802
803
        // copy image into tmbPath so some drivers does not store files on local fs
804
        if (! $data = $this->_db_getThumbnail($path)) {
805
            return false;
806
        }
807
        if (! file_put_contents($tmb, $data)) {
808
            return false;
809
        }
810
811
        $result = false;
812
813
        $tmbSize = $this->tmbSize;
814
815
        if (($s = getimagesize($tmb)) == false) {
816
            return false;
817
        }
818
819
        /* If image smaller or equal thumbnail size - just fitting to thumbnail square */
820
        if ($s[0] <= $tmbSize && $s[1] <= $tmbSize) {
821
            $result = $this->imgSquareFit($tmb, $tmbSize, $tmbSize, 'center', 'middle', $this->options['tmbBgColor'], 'png');
822
        } else {
823
            if ($this->options['tmbCrop']) {
824
825
                /* Resize and crop if image bigger than thumbnail */
826
                if (! (($s[0] > $tmbSize && $s[1] <= $tmbSize) || ($s[0] <= $tmbSize && $s[1] > $tmbSize)) || ($s[0] > $tmbSize && $s[1] > $tmbSize)) {
827
                    $result = $this->imgResize($tmb, $tmbSize, $tmbSize, true, false, 'png');
828
                }
829
830
                if (($s = getimagesize($tmb)) != false) {
831
                    $x = $s[0] > $tmbSize ? intval(($s[0] - $tmbSize) / 2) : 0;
832
                    $y = $s[1] > $tmbSize ? intval(($s[1] - $tmbSize) / 2) : 0;
833
                    $result = $this->imgCrop($tmb, $tmbSize, $tmbSize, $x, $y, 'png');
834
                }
835
            } else {
836
                $result = $this->imgResize($tmb, $tmbSize, $tmbSize, true, true, 'png');
837
            }
838
839
            $result = $this->imgSquareFit($tmb, $tmbSize, $tmbSize, 'center', 'middle', $this->options['tmbBgColor'], 'png');
840
        }
841
842
        if (! $result) {
843
            unlink($tmb);
844
845
            return false;
846
        }
847
848
        return $name;
849
    }
850
851
    /**
852
     * Return thumbnail file name for required file.
853
     *
854
     * @param array $stat file stat
855
     *
856
     * @return string
857
     *
858
     * @author Naoki Sawada
859
     **/
860
    protected function tmbname($stat)
861
    {
862
        $name = $this->driverId.'_';
863
        if (isset($this->options['tokens']) && is_array($this->options['tokens'])) {
864
            $name .= $this->options['tokens']['uid'];
865
        }
866
867
        return $name.md5($stat['iid']).$stat['ts'].'.png';
868
    }
869
870
    /*********************** paths/urls *************************/
871
872
    /**
873
     * Return parent directory path.
874
     *
875
     * @param string $path file path
876
     *
877
     * @return string
878
     *
879
     * @author Naoki Sawada
880
     **/
881
    protected function _dirname($path)
882
    {
883
        list($dirname) = $this->_db_splitPath($path);
884
885
        return $dirname;
886
    }
887
888
    /**
889
     * Return file name.
890
     *
891
     * @param string $path file path
892
     *
893
     * @return string
894
     *
895
     * @author Naoki Sawada
896
     **/
897
    protected function _basename($path)
898
    {
899
        list(, $basename) = $this->_db_splitPath($path);
900
901
        return $basename;
902
    }
903
904
    /**
905
     * Join dir name and file name and retur full path.
906
     *
907
     * @param string $dir
908
     * @param string $name
909
     *
910
     * @return string
911
     *
912
     * @author Dmitry (dio) Levashov
913
     **/
914
    protected function _joinPath($dir, $name)
915
    {
916
        return rtrim($dir, '/').'/'.strtolower($name);
917
    }
918
919
    /**
920
     * Return normalized path, this works the same as os.path.normpath() in Python.
921
     *
922
     * @param string $path path
923
     *
924
     * @return string
925
     *
926
     * @author Naoki Sawada
927
     **/
928
    protected function _normpath($path)
929
    {
930
        return '/'.ltrim($path, '/');
931
    }
932
933
    /**
934
     * Return file path related to root dir.
935
     *
936
     * @param string $path file path
937
     *
938
     * @return string
939
     *
940
     * @author Dmitry (dio) Levashov
941
     **/
942
    protected function _relpath($path)
943
    {
944
        if ($path === $this->root) {
945
            return '';
946
        } else {
947
            return ltrim(substr($path, strlen($this->root)), '/');
948
        }
949
    }
950
951
    /**
952
     * Convert path related to root dir into real path.
953
     *
954
     * @param string $path file path
955
     *
956
     * @return string
957
     *
958
     * @author Naoki Sawada
959
     **/
960
    protected function _abspath($path)
961
    {
962
        if ($path === '/') {
963
            return $this->root;
964
        } else {
965
            return $this->_joinPath($this->root, $path);
966
        }
967
    }
968
969
    /**
970
     * Return fake path started from root dir.
971
     *
972
     * @param string $path file path
973
     *
974
     * @return string
975
     *
976
     * @author Naoki Sawada
977
     **/
978
    protected function _path($path)
979
    {
980
        $path = $this->_normpath(substr($path, strlen($this->root)));
981
982
        return $path;
983
    }
984
985
    /**
986
     * Return true if $path is children of $parent.
987
     *
988
     * @param string $path   path to check
989
     * @param string $parent parent path
990
     *
991
     * @return bool
992
     *
993
     * @author Naoki Sawada
994
     **/
995
    protected function _inpath($path, $parent)
996
    {
997
        return $path == $parent || strpos($path, $parent.'/') === 0;
998
    }
999
1000
    /***************** file stat ********************/
1001
1002
    /**
1003
     * Return stat for given path.
1004
     * Stat contains following fields:
1005
     * - (int)    size    file size in b. required
1006
     * - (int)    ts      file modification time in unix time. required
1007
     * - (string) mime    mimetype. required for folders, others - optionally
1008
     * - (bool)   read    read permissions. required
1009
     * - (bool)   write   write permissions. required
1010
     * - (bool)   locked  is object locked. optionally
1011
     * - (bool)   hidden  is object hidden. optionally
1012
     * - (string) alias   for symlinks - link target path relative to root path. optionally
1013
     * - (string) target  for symlinks - link target path. optionally.
1014
     *
1015
     * If file does not exists - returns empty array or false.
1016
     *
1017
     * @param string $path file path
1018
     *
1019
     * @return array|false
1020
     *
1021
     * @author Dmitry (dio) Levashov
1022
     **/
1023
    protected function _stat($path)
1024
    {
1025
        if ($raw = $this->_db_getFile($path)) {
1026
            return $this->_db_parseRaw($raw);
1027
        }
1028
1029
        return false;
1030
    }
1031
1032
    /**
1033
     * Return true if path is dir and has at least one childs directory.
1034
     *
1035
     * @param string $path dir path
1036
     *
1037
     * @return bool
1038
     *
1039
     * @author Naoki Sawada
1040
     **/
1041
    protected function _subdirs($path)
1042
    {
1043
        $hasdir = false;
1044
1045
        try {
1046
            $res = $this->service->listFolder($path);
1047
            if ($res) {
1048
                $items = $res->getItems();
1049
                foreach ($items as $raw) {
1050
                    if ($raw instanceof FolderMetadata) {
1051
                        $hasdir = true;
1052
                        break;
1053
                    }
1054
                }
1055
            }
1056
        } catch (DropboxClientException $e) {
1057
            $this->setError('Dropbox error: '.$e->getMessage());
1058
        }
1059
1060
        return $hasdir;
1061
    }
1062
1063
    /**
1064
     * Return object width and height
1065
     * Ususaly used for images, but can be realize for video etc...
1066
     *
1067
     * @param string $path file path
1068
     * @param string $mime file mime type
1069
     *
1070
     * @return string
1071
     *
1072
     * @author Naoki Sawada
1073
     **/
1074
    protected function _dimensions($path, $mime)
1075
    {
1076
        if (strpos($mime, 'image') !== 0) {
1077
            return '';
1078
        }
1079
        $ret = '';
1080
1081
        if ($data = $this->_getContents($path)) {
1082
            $tmp = $this->getTempFile();
1083
            file_put_contents($tmp, $data);
1084
            $size = getimagesize($tmp);
1085
            if ($size) {
1086
                return $size[0].'x'.$size[1];
1087
            }
1088
        }
1089
1090
        return $ret;
1091
    }
1092
1093
    /******************** file/dir content *********************/
1094
1095
    /**
1096
     * Return files list in directory.
1097
     *
1098
     * @param string $path dir path
1099
     *
1100
     * @return array
1101
     *
1102
     * @author Naoki Sawada
1103
     **/
1104
    protected function _scandir($path)
1105
    {
1106
        return isset($this->dirsCache[$path])
1107
            ? $this->dirsCache[$path]
1108
            : $this->cacheDir($path);
1109
    }
1110
1111
    /**
1112
     * Open file and return file pointer.
1113
     *
1114
     * @param string $path  file path
1115
     * @param bool   $write open file for writing
1116
     *
1117
     * @return resource|false
1118
     *
1119
     * @author Naoki Sawada
1120
     **/
1121
    protected function _fopen($path, $mode = 'rb')
1122
    {
1123
        if ($mode === 'rb' || $mode === 'r') {
1124
            if ($link = $this->service->getTemporaryLink($path)) {
1125
                $access_token = $this->service->getAccessToken();
1126
                if ($access_token) {
1127
                    $data = [
1128
                                'target' => $link->getLink(),
1129
                                'headers' => ['Authorization: Bearer '.$access_token],
1130
                        ];
1131
1132
                    return elFinder::getStreamByUrl($data);
1133
                }
1134
            }
1135
        }
1136
1137
        return false;
1138
    }
1139
1140
    /**
1141
     * Close opened file.
1142
     *
1143
     * @param resource $fp file pointer
1144
     *
1145
     * @return bool
1146
     *
1147
     * @author Naoki Sawada
1148
     **/
1149
    protected function _fclose($fp, $path = '')
1150
    {
1151
        fclose($fp);
1152
    }
1153
1154
    /********************  file/dir manipulations *************************/
1155
1156
    /**
1157
     * Create dir and return created dir path or false on failed.
1158
     *
1159
     * @param string $path parent dir path
1160
     * @param string $name new directory name
1161
     *
1162
     * @return string|bool
1163
     *
1164
     * @author Naoki Sawada
1165
     **/
1166 View Code Duplication
    protected function _mkdir($path, $name)
1167
    {
1168
        try {
1169
            return $this->service->createFolder($this->_db_joinName($path, $name))->getPathLower();
1170
        } catch (DropboxClientException $e) {
1171
            return $this->setError('Dropbox error: '.$e->getMessage());
1172
        }
1173
    }
1174
1175
    /**
1176
     * Create file and return it's path or false on failed.
1177
     *
1178
     * @param string $path parent dir path
1179
     * @param string $name new file name
1180
     *
1181
     * @return string|bool
1182
     *
1183
     * @author Naoki Sawada
1184
     **/
1185
    protected function _mkfile($path, $name)
1186
    {
1187
        return $this->_save(tmpfile(), $path, $name, []);
1188
    }
1189
1190
    /**
1191
     * Create symlink. FTP driver does not support symlinks.
1192
     *
1193
     * @param string $target link target
1194
     * @param string $path   symlink path
1195
     *
1196
     * @return bool
1197
     *
1198
     * @author Naoki Sawada
1199
     **/
1200
    protected function _symlink($target, $path, $name)
1201
    {
1202
        return false;
1203
    }
1204
1205
    /**
1206
     * Copy file into another file.
1207
     *
1208
     * @param string $source    source file path
1209
     * @param string $targetDir target directory path
1210
     * @param string $name      new file name
1211
     *
1212
     * @return bool
1213
     *
1214
     * @author Naoki Sawada
1215
     **/
1216 View Code Duplication
    protected function _copy($source, $targetDir, $name)
1217
    {
1218
        try {
1219
            $this->service->copy($source, $this->_db_joinName($targetDir, $name))->getPathLower();
1220
        } catch (DropboxClientException $e) {
1221
            return $this->setError('Dropbox error: '.$e->getMessage());
1222
        }
1223
1224
        return true;
1225
    }
1226
1227
    /**
1228
     * Move file into another parent dir.
1229
     * Return new file path or false.
1230
     *
1231
     * @param string $source source file path
1232
     * @param string $target target dir path
1233
     * @param string $name   file name
1234
     *
1235
     * @return string|bool
1236
     *
1237
     * @author Naoki Sawada
1238
     **/
1239 View Code Duplication
    protected function _move($source, $targetDir, $name)
1240
    {
1241
        try {
1242
            return $this->service->move($source, $this->_db_joinName($targetDir, $name))->getPathLower();
1243
        } catch (DropboxClientException $e) {
1244
            return $this->setError('Dropbox error: '.$e->getMessage());
1245
        }
1246
    }
1247
1248
    /**
1249
     * Remove file.
1250
     *
1251
     * @param string $path file path
1252
     *
1253
     * @return bool
1254
     *
1255
     * @author Naoki Sawada
1256
     **/
1257
    protected function _unlink($path)
1258
    {
1259
        try {
1260
            $this->service->delete($path);
1261
1262
            return true;
1263
        } catch (DropboxClientException $e) {
1264
            return $this->setError('Dropbox error: '.$e->getMessage());
1265
        }
1266
1267
        return true;
1268
    }
1269
1270
    /**
1271
     * Remove dir.
1272
     *
1273
     * @param string $path dir path
1274
     *
1275
     * @return bool
1276
     *
1277
     * @author Naoki Sawada
1278
     **/
1279
    protected function _rmdir($path)
1280
    {
1281
        return $this->_unlink($path);
1282
    }
1283
1284
    /**
1285
     * Create new file and write into it from file pointer.
1286
     * Return new file path or false on error.
1287
     *
1288
     * @param resource $fp   file pointer
1289
     * @param string   $dir  target dir path
1290
     * @param string   $name file name
1291
     * @param array    $stat file stat (required by some virtual fs)
1292
     *
1293
     * @return bool|string
1294
     *
1295
     * @author Naoki Sawada
1296
     **/
1297
    protected function _save($fp, $path, $name, $stat)
1298
    {
1299
        try {
1300
            $info = stream_get_meta_data($fp);
1301
            if (empty($info['uri']) || preg_match('#^[a-z0-9.-]+://#', $info['uri'])) {
1302 View Code Duplication
                if ($filepath = $this->getTempFile()) {
1303
                    $_fp = fopen($filepath, 'wb');
1304
                    stream_copy_to_stream($fp, $_fp);
1305
                    fclose($_fp);
1306
                }
1307
            } else {
1308
                $filepath = $info['uri'];
1309
            }
1310
            $dropboxFile = new DropboxFile($filepath);
1311
            if ($name === '') {
1312
                $dir = $this->_dirname($path);
1313
                $name = $this->_basename($path);
1314
                $fullpath = $path;
1315
            } else {
1316
                $dir = $path;
1317
                $fullpath = $this->_db_joinName($path, $name);
1318
            }
1319
1320
            return $this->service->upload($dropboxFile, $fullpath, ['mode' => 'overwrite'])->getPathLower();
1321
        } catch (DropboxClientException $e) {
1322
            return $this->setError('Dropbox error: '.$e->getMessage());
1323
        }
1324
    }
1325
1326
    /**
1327
     * Get file contents.
1328
     *
1329
     * @param string $path file path
1330
     *
1331
     * @return string|false
1332
     *
1333
     * @author Naoki Sawada
1334
     **/
1335
    protected function _getContents($path)
1336
    {
1337
        $contents = '';
1338
1339
        try {
1340
            $file = $this->service->download($path);
1341
            $contents = $file->getContents();
1342
        } catch (Exception $e) {
1343
            return $this->setError('Dropbox error: '.$e->getMessage());
1344
        }
1345
1346
        return $contents;
1347
    }
1348
1349
    /**
1350
     * Write a string to a file.
1351
     *
1352
     * @param string $path    file path
1353
     * @param string $content new file content
1354
     *
1355
     * @return bool
1356
     *
1357
     * @author Naoki Sawada
1358
     **/
1359 View Code Duplication
    protected function _filePutContents($path, $content)
1360
    {
1361
        $res = false;
1362
1363
        if ($local = $this->getTempFile($path)) {
1364
            if (file_put_contents($local, $content, LOCK_EX) !== false
1365
            && ($fp = fopen($local, 'rb'))) {
1366
                clearstatcache();
1367
                $res = $this->_save($fp, $path, '', []);
1368
                fclose($fp);
1369
            }
1370
            file_exists($local) && unlink($local);
1371
        }
1372
1373
        return $res;
1374
    }
1375
1376
    /**
1377
     * Detect available archivers.
1378
     **/
1379
    protected function _checkArchivers()
1380
    {
1381
        // die('Not yet implemented. (_checkArchivers)');
0 ignored issues
show
Unused Code Comprehensibility introduced by
84% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1382
        return [];
1383
    }
1384
1385
    /**
1386
     * chmod implementation.
1387
     *
1388
     * @return bool
1389
     **/
1390
    protected function _chmod($path, $mode)
1391
    {
1392
        return false;
1393
    }
1394
1395
    /**
1396
     * Unpack archive.
1397
     *
1398
     * @param string $path archive path
1399
     * @param array  $arc  archiver command and arguments (same as in $this->archivers)
1400
     *
1401
     * @return true
1402
     *
1403
     * @author Dmitry (dio) Levashov
1404
     * @author Alexey Sukhotin
1405
     **/
1406
    protected function _unpack($path, $arc)
1407
    {
1408
        die('Not yet implemented. (_unpack)');
1409
        //return false;
1410
    }
1411
1412
    /**
1413
     * Recursive symlinks search.
1414
     *
1415
     * @param string $path file/dir path
1416
     *
1417
     * @return bool
1418
     *
1419
     * @author Dmitry (dio) Levashov
1420
     **/
1421
    protected function _findSymlinks($path)
1422
    {
1423
        die('Not yet implemented. (_findSymlinks)');
1424
    }
1425
1426
    /**
1427
     * Extract files from archive.
1428
     *
1429
     * @param string $path archive path
1430
     * @param array  $arc  archiver command and arguments (same as in $this->archivers)
1431
     *
1432
     * @return true
1433
     *
1434
     * @author Dmitry (dio) Levashov,
1435
     * @author Alexey Sukhotin
1436
     **/
1437
    protected function _extract($path, $arc)
1438
    {
1439
        die('Not yet implemented. (_extract)');
1440
    }
1441
1442
    /**
1443
     * Create archive and return its path.
1444
     *
1445
     * @param string $dir   target dir
1446
     * @param array  $files files names list
1447
     * @param string $name  archive name
1448
     * @param array  $arc   archiver options
1449
     *
1450
     * @return string|bool
1451
     *
1452
     * @author Dmitry (dio) Levashov,
1453
     * @author Alexey Sukhotin
1454
     **/
1455
    protected function _archive($dir, $files, $name, $arc)
1456
    {
1457
        die('Not yet implemented. (_archive)');
1458
    }
1459
1460
    /**
1461
     * Get dat(Dropbox metadata) from Dropbox.
1462
     *
1463
     * @param string $path
1464
     *
1465
     * @return object Dropbox metadata
1466
     */
1467
    private function _db_getFile($path, $fields = '')
1468
    {
1469
        if ($path === '/') {
1470
            return true;
1471
        }
1472
1473
        $res = false;
1474
        try {
1475
            $file = $this->service->getMetadata($path, $this->FETCH_OPTIONS);
1476
            if ($file instanceof FolderMetadata || $file instanceof FileMetadata) {
1477
                $res = $file;
1478
            }
1479
1480
            return $res;
1481
        } catch (DropboxClientException $e) {
1482
            return false;
1483
        }
1484
    }
1485
} // END class
1486