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/elFinderVolumeDropbox.class.php (70 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
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 11 and the first side effect is on line 3.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
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
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
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
89
        // check with composer
90
        $this->dropbox_phpFound = class_exists('Dropbox_API');
91
92
        if (! $this->dropbox_phpFound) {
93
            // check with pear
94
            if (include_once 'Dropbox/autoload.php') {
95
                $this->dropbox_phpFound = in_array('Dropbox_autoload', spl_autoload_functions());
96
            }
97
        }
98
99
        $opts = [
100
            'consumerKey' => '',
101
            'consumerSecret' => '',
102
            'accessToken' => '',
103
            'accessTokenSecret' => '',
104
            'dropboxUid' => '',
105
            'root' => 'dropbox',
106
            'path' => '/',
107
            'separator' => '/',
108
            'PDO_DSN' => '', // if empty use 'sqlite:(metaCachePath|tmbPath)/elFinder_dropbox_db_(hash:dropboxUid+consumerSecret)'
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...
109
            'PDO_User' => '',
110
            'PDO_Pass' => '',
111
            'PDO_Options' => [],
112
            'PDO_DBName' => 'dropbox',
113
            'treeDeep' => 0,
114
            'tmbPath' => '',
115
            'tmbURL' => '',
116
            'tmpPath' => '',
117
            'getTmbSize' => 'large', // small: 32x32, medium or s: 64x64, large or m: 128x128, l: 640x480, xl: 1024x768
118
            'metaCachePath' => '',
119
            'metaCacheTime' => '600', // 10m
120
            'acceptedName' => '#^[^/\\?*:|"<>]*[^./\\?*:|"<>]$#',
121
            'rootCssClass' => 'elfinder-navbar-root-dropbox',
122
        ];
123
        $this->options = array_merge($this->options, $opts);
124
        $this->options['mimeDetect'] = 'internal';
125
    }
126
127
    /**
128
     * Prepare
129
     * Call from elFinder::netmout() before volume->mount().
130
     *
131
     * @param $options
132
     * @return array
133
     * @author Naoki Sawada
134
     */
135
    public function netmountPrepare($options)
0 ignored issues
show
netmountPrepare uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
netmountPrepare uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
netmountPrepare uses the super-global variable $_GET which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
136
    {
137
        if (empty($options['consumerKey']) && defined('ELFINDER_DROPBOX_CONSUMERKEY')) {
138
            $options['consumerKey'] = ELFINDER_DROPBOX_CONSUMERKEY;
139
        }
140
        if (empty($options['consumerSecret']) && defined('ELFINDER_DROPBOX_CONSUMERSECRET')) {
141
            $options['consumerSecret'] = ELFINDER_DROPBOX_CONSUMERSECRET;
142
        }
143
144
        if ($options['user'] === 'init') {
145
            if (! $this->dropbox_phpFound || empty($options['consumerKey']) || empty($options['consumerSecret']) || ! class_exists('PDO', false)) {
146
                return ['exit' => true, 'body' => '{msg:errNetMountNoDriver}'];
147
            }
148
149
            if (defined('ELFINDER_DROPBOX_USE_CURL_PUT')) {
150
                $this->oauth = new Dropbox_OAuth_Curl($options['consumerKey'], $options['consumerSecret']);
0 ignored issues
show
Documentation Bug introduced by
It seems like new \Dropbox_OAuth_Curl(...ions['consumerSecret']) of type object<Dropbox_OAuth_Curl> is incompatible with the declared type object<oauth> of property $oauth.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
151
            } else {
152
                if (class_exists('OAuth', false)) {
153
                    $this->oauth = new Dropbox_OAuth_PHP($options['consumerKey'], $options['consumerSecret']);
0 ignored issues
show
Documentation Bug introduced by
It seems like new \Dropbox_OAuth_PHP($...ions['consumerSecret']) of type object<Dropbox_OAuth_PHP> is incompatible with the declared type object<oauth> of property $oauth.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
154
                } else {
155
                    if (! class_exists('HTTP_OAuth_Consumer')) {
156
                        // We're going to try to load in manually
157
                        include 'HTTP/OAuth/Consumer.php';
158
                    }
159
                    if (class_exists('HTTP_OAuth_Consumer', false)) {
160
                        $this->oauth = new Dropbox_OAuth_PEAR($options['consumerKey'], $options['consumerSecret']);
0 ignored issues
show
Documentation Bug introduced by
It seems like new \Dropbox_OAuth_PEAR(...ions['consumerSecret']) of type object<Dropbox_OAuth_PEAR> is incompatible with the declared type object<oauth> of property $oauth.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
161
                    }
162
                }
163
            }
164
165
            if (! $this->oauth) {
166
                return ['exit' => true, 'body' => '{msg:errNetMountNoDriver}'];
167
            }
168
169
            if ($options['pass'] === 'init') {
170
                $html = '';
171
                if ($sessionToken = $this->session->get('DropboxTokens')) {
172
                    // token check
173
                    try {
174
                        list(, $accessToken, $accessTokenSecret) = $sessionToken;
175
                        $this->oauth->setToken($accessToken, $accessTokenSecret);
176
                        $this->dropbox = new Dropbox_API($this->oauth, $this->options['root']);
0 ignored issues
show
Documentation Bug introduced by
It seems like new \Dropbox_API($this->...$this->options['root']) of type object<Dropbox_API> is incompatible with the declared type object<dropbox> of property $dropbox.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
177
                        $this->dropbox->getAccountInfo();
178
                        $script = '<script>
179
							$("#'.$options['id'].'").elfinder("instance").trigger("netmount", {protocol: "dropbox", mode: "done"});
180
						</script>';
181
                        $html = $script;
182
                    } catch (Dropbox_Exception $e) {
0 ignored issues
show
The class Dropbox_Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
183
                        $this->session->remove('DropboxTokens');
184
                    }
185
                }
186
                if (! $html) {
187
                    // get customdata
188
                    $cdata = '';
189
                    $innerKeys = ['cmd', 'host', 'options', 'pass', 'protocol', 'user'];
190
                    $this->ARGS = $_SERVER['REQUEST_METHOD'] === 'POST' ? $_POST : $_GET;
191 View Code Duplication
                    foreach ($this->ARGS as $k => $v) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
192
                        if (! in_array($k, $innerKeys)) {
193
                            $cdata .= '&'.$k.'='.rawurlencode($v);
194
                        }
195
                    }
196
                    if (strpos($options['url'], 'http') !== 0) {
197
                        $options['url'] = elFinder::getConnectorUrl();
198
                    }
199
                    $callback = $options['url']
200
                               .'?cmd=netmount&protocol=dropbox&host=dropbox.com&user=init&pass=return&node='.$options['id'].$cdata;
201
202
                    try {
203
                        $tokens = $this->oauth->getRequestToken();
204
                        $url = $this->oauth->getAuthorizeUrl(rawurlencode($callback));
205
                    } catch (Dropbox_Exception $e) {
0 ignored issues
show
The class Dropbox_Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
206
                        return ['exit' => true, 'body' => '{msg:errAccess}'];
207
                    }
208
209
                    $this->session->set('DropboxAuthTokens', $tokens);
210
                    $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.'\')">';
211
                    $html .= '<script>
212
						$("#'.$options['id'].'").elfinder("instance").trigger("netmount", {protocol: "dropbox", mode: "makebtn"});
213
					</script>';
214
                }
215
216
                return ['exit' => true, 'body' => $html];
217
            } else {
218
                $this->oauth->setToken($this->session->get('DropboxAuthTokens'));
219
                $this->session->remove('DropboxAuthTokens');
220
                $tokens = $this->oauth->getAccessToken();
221
                $this->session->set('DropboxTokens', [$_GET['uid'], $tokens['token'], $tokens['token_secret']]);
222
223
                $out = [
224
                    'node' => $_GET['node'],
225
                    'json' => '{"protocol": "dropbox", "mode": "done"}',
226
                    'bind' => 'netmount',
227
                ];
228
229
                return ['exit' => 'callback', 'out' => $out];
230
            }
231
        }
232
        if ($sessionToken = $this->session->get('DropboxTokens')) {
233
            list($options['dropboxUid'], $options['accessToken'], $options['accessTokenSecret']) = $sessionToken;
234
        }
235
        unset($options['user'], $options['pass']);
236
237
        return $options;
238
    }
239
240
    /**
241
     * process of on netunmount
242
     * Drop table `dropbox` & rm thumbs.
243
     *
244
     * @param $netVolumes
245
     * @param $key
246
     * @return bool
247
     * @internal param array $options
248
     */
249
    public function netunmount($netVolumes, $key)
250
    {
251
        $count = 0;
252
        $dropboxUid = '';
253
        if (isset($netVolumes[$key])) {
254
            $dropboxUid = $netVolumes[$key]['dropboxUid'];
255
        }
256
        foreach ($netVolumes as $volume) {
257
            if ($volume['host'] === 'dropbox' && $volume['dropboxUid'] === $dropboxUid) {
258
                $count++;
259
            }
260
        }
261
        if ($count === 1) {
262
            $this->DB->exec('drop table '.$this->DB_TableName);
0 ignored issues
show
The property DB does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
263
            foreach (glob(rtrim($this->options['tmbPath'], '\\/').DIRECTORY_SEPARATOR.$this->tmbPrefix.'*.png') as $tmb) {
264
                unlink($tmb);
265
            }
266
        }
267
268
        return true;
269
    }
270
271
    /*********************************************************************/
272
    /*                               FS API                              */
273
    /*********************************************************************/
274
275
    /**
276
     * Close opened connection.
277
     *
278
     * @return void
279
     * @author Dmitry (dio) Levashov
280
     **/
281
    public function umount()
282
    {
283
    }
284
285
    /**
286
     * Return content URL.
287
     *
288
     * @param string  $hash  file hash
289
     * @param array $options options
290
     * @return array
291
     * @author Naoki Sawada
292
     **/
293
    public function getContentUrl($hash, $options = [])
294
    {
295
        if (($file = $this->file($hash)) == false || ! $file['url'] || $file['url'] == 1) {
296
            $path = $this->decode($hash);
297
            $cache = $this->getDBdat($path);
298
            $url = '';
299
            if (isset($cache['share']) && strpos($cache['share'], $this->dropbox_dlhost) !== false) {
300
                $res = $this->getHttpResponseHeader($cache['share']);
301
                if (preg_match("/^HTTP\/[01\.]+ ([0-9]{3})/", $res, $match)) {
302
                    if ($match[1] < 400) {
303
                        $url = $cache['share'];
304
                    }
305
                }
306
            }
307
            if (! $url) {
308
                try {
309
                    $res = $this->dropbox->share($path, null, false);
310
                    $url = $res['url'];
311
                    if (strpos($url, 'www.dropbox.com') === false) {
312
                        $res = $this->getHttpResponseHeader($url);
313
                        if (preg_match('/^location:\s*(http[^\s]+)/im', $res, $match)) {
314
                            $url = $match[1];
315
                        }
316
                    }
317
                    list($url) = explode('?', $url);
318
                    $url = str_replace('www.dropbox.com', $this->dropbox_dlhost, $url);
319
                    if (! isset($cache['share']) || $cache['share'] !== $url) {
320
                        $cache['share'] = $url;
321
                        $this->updateDBdat($path, $cache);
322
                    }
323
                } catch (Dropbox_Exception $e) {
0 ignored issues
show
The class Dropbox_Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
324
                    return false;
325
                }
326
            }
327
328
            return $url;
329
        }
330
331
        return $file['url'];
332
    }
333
334
    /*********************************************************************/
335
    /*                        INIT AND CONFIGURE                         */
336
    /*********************************************************************/
337
338
    /**
339
     * Prepare FTP connection
340
     * Connect to remote server and check if credentials are correct, if so, store the connection id in $ftp_conn.
341
     *
342
     * @return bool
343
     * @author Dmitry (dio) Levashov
344
     * @author Cem (DiscoFever)
345
     **/
346
    protected function init()
347
    {
348
        if (! class_exists('PDO', false)) {
349
            return $this->setError('PHP PDO class is require.');
350
        }
351
352
        if (! $this->options['consumerKey']
353
        || ! $this->options['consumerSecret']
354
        || ! $this->options['accessToken']
355
        || ! $this->options['accessTokenSecret']) {
356
            return $this->setError('Required options undefined.');
357
        }
358
359
        if (empty($this->options['metaCachePath']) && defined('ELFINDER_DROPBOX_META_CACHE_PATH')) {
360
            $this->options['metaCachePath'] = ELFINDER_DROPBOX_META_CACHE_PATH;
361
        }
362
363
        // make net mount key
364
        $this->netMountKey = md5(implode('-', ['dropbox', $this->options['path']]));
365
366
        if (! $this->oauth) {
367
            if (defined('ELFINDER_DROPBOX_USE_CURL_PUT')) {
368
                $this->oauth = new Dropbox_OAuth_Curl($this->options['consumerKey'], $this->options['consumerSecret']);
0 ignored issues
show
Documentation Bug introduced by
It seems like new \Dropbox_OAuth_Curl(...ions['consumerSecret']) of type object<Dropbox_OAuth_Curl> is incompatible with the declared type object<oauth> of property $oauth.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
369
            } else {
370
                if (class_exists('OAuth', false)) {
371
                    $this->oauth = new Dropbox_OAuth_PHP($this->options['consumerKey'], $this->options['consumerSecret']);
0 ignored issues
show
Documentation Bug introduced by
It seems like new \Dropbox_OAuth_PHP($...ions['consumerSecret']) of type object<Dropbox_OAuth_PHP> is incompatible with the declared type object<oauth> of property $oauth.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
372
                } else {
373
                    if (! class_exists('HTTP_OAuth_Consumer')) {
374
                        // We're going to try to load in manually
375
                        include 'HTTP/OAuth/Consumer.php';
376
                    }
377
                    if (class_exists('HTTP_OAuth_Consumer', false)) {
378
                        $this->oauth = new Dropbox_OAuth_PEAR($this->options['consumerKey'], $this->options['consumerSecret']);
0 ignored issues
show
Documentation Bug introduced by
It seems like new \Dropbox_OAuth_PEAR(...ions['consumerSecret']) of type object<Dropbox_OAuth_PEAR> is incompatible with the declared type object<oauth> of property $oauth.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
379
                    }
380
                }
381
            }
382
        }
383
384
        if (! $this->oauth) {
385
            return $this->setError('OAuth extension not loaded.');
386
        }
387
388
        // normalize root path
389
        $this->root = $this->options['path'] = $this->_normpath($this->options['path']);
390
391 View Code Duplication
        if (empty($this->options['alias'])) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
392
            $this->options['alias'] = ($this->options['path'] === '/') ? 'Dropbox.com' : 'Dropbox'.$this->options['path'];
393
        }
394
395
        $this->rootName = $this->options['alias'];
396
397
        try {
398
            $this->oauth->setToken($this->options['accessToken'], $this->options['accessTokenSecret']);
399
            $this->dropbox = new Dropbox_API($this->oauth, $this->options['root']);
0 ignored issues
show
Documentation Bug introduced by
It seems like new \Dropbox_API($this->...$this->options['root']) of type object<Dropbox_API> is incompatible with the declared type object<dropbox> of property $dropbox.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
400
        } catch (Dropbox_Exception $e) {
0 ignored issues
show
The class Dropbox_Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
401
            $this->session->remove('DropboxTokens');
402
403
            return $this->setError('Dropbox error: '.$e->getMessage());
404
        }
405
406
        // user
407
        if (empty($this->options['dropboxUid'])) {
408
            try {
409
                $res = $this->dropbox->getAccountInfo();
410
                $this->options['dropboxUid'] = $res['uid'];
411
            } catch (Dropbox_Exception $e) {
0 ignored issues
show
The class Dropbox_Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
412
                $this->session->remove('DropboxTokens');
413
414
                return $this->setError('Dropbox error: '.$e->getMessage());
415
            }
416
        }
417
418
        $this->dropboxUid = $this->options['dropboxUid'];
419
        $this->tmbPrefix = 'dropbox'.base_convert($this->dropboxUid, 10, 32);
420
421
        if (! empty($this->options['tmpPath'])) {
422
            if ((is_dir($this->options['tmpPath']) || mkdir($this->options['tmpPath'])) && is_writable($this->options['tmpPath'])) {
423
                $this->tmp = $this->options['tmpPath'];
424
            }
425
        }
426
        if (! $this->tmp && is_writable($this->options['tmbPath'])) {
427
            $this->tmp = $this->options['tmbPath'];
428
        }
429
        if (! $this->tmp && ($tmp = elFinder::getStaticVar('commonTempPath'))) {
430
            $this->tmp = $tmp;
431
        }
432
433 View Code Duplication
        if (! empty($this->options['metaCachePath'])) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
434
            if ((is_dir($this->options['metaCachePath']) || mkdir($this->options['metaCachePath'])) && is_writable($this->options['metaCachePath'])) {
435
                $this->metaCache = $this->options['metaCachePath'];
436
            }
437
        }
438
        if (! $this->metaCache && $this->tmp) {
439
            $this->metaCache = $this->tmp;
440
        }
441
442
        if (! $this->metaCache) {
443
            return $this->setError('Cache dirctory (metaCachePath or tmp) is require.');
444
        }
445
446
        // setup PDO
447
        if (! $this->options['PDO_DSN']) {
448
            $this->options['PDO_DSN'] = 'sqlite:'.$this->metaCache.DIRECTORY_SEPARATOR.'.elFinder_dropbox_db_'.md5($this->dropboxUid.$this->options['consumerSecret']);
449
        }
450
        // DataBase table name
451
        $this->DB_TableName = $this->options['PDO_DBName'];
452
        // DataBase check or make table
453
        try {
454
            $this->DB = new PDO($this->options['PDO_DSN'], $this->options['PDO_User'], $this->options['PDO_Pass'], $this->options['PDO_Options']);
455
            if (! $this->checkDB()) {
456
                return $this->setError('Can not make DB table');
457
            }
458
        } catch (PDOException $e) {
459
            return $this->setError('PDO connection failed: '.$e->getMessage());
460
        }
461
462
        $res = $this->deltaCheck($this->isMyReload());
463
        if ($res !== true) {
464
            if (is_string($res)) {
465
                return $this->setError($res);
466
            } else {
467
                return $this->setError('Could not check API "delta"');
468
            }
469
        }
470
471
        if (is_null($this->options['syncChkAsTs'])) {
472
            $this->options['syncChkAsTs'] = true;
473
        }
474 View Code Duplication
        if ($this->options['syncChkAsTs']) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
475
            // 'tsPlSleep' minmum 5 sec
476
            $this->options['tsPlSleep'] = max(5, $this->options['tsPlSleep']);
477
        } else {
478
            // 'lsPlSleep' minmum 10 sec
479
            $this->options['lsPlSleep'] = max(10, $this->options['lsPlSleep']);
480
        }
481
482
        return true;
483
    }
484
485
    /**
486
     * Configure after successful mount.
487
     *
488
     * @return string
489
     * @author Dmitry (dio) Levashov
490
     **/
491
    protected function configure()
492
    {
493
        parent::configure();
494
495
        $this->disabled[] = 'archive';
496
        $this->disabled[] = 'extract';
497
    }
498
499
    /**
500
     * Get delta data and DB update.
501
     *
502
     * @param bool $refresh force refresh
503
     * @return true|string error message
504
     */
505
    protected function deltaCheck($refresh = true)
0 ignored issues
show
deltaCheck uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
506
    {
507
        $chk = false;
508
        if (! $refresh && $chk = $this->query('select dat from '.$this->DB_TableName.' where path=\'\' and fname=\'\' limit 1')) {
509
            $chk = unserialize($chk[0]);
510
        }
511
        if ($chk && ($chk['mtime'] + $this->options['metaCacheTime']) > $_SERVER['REQUEST_TIME']) {
512
            return true;
513
        }
514
515
        try {
516
            $more = true;
0 ignored issues
show
$more is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
517
            $this->DB->beginTransaction();
518
519
            if ($res = $this->query('select dat from '.$this->DB_TableName.' where path=\'\' and fname=\'\' limit 1')) {
520
                $res = unserialize($res[0]);
521
                $cursor = $res['cursor'];
522
            } else {
523
                $cursor = '';
524
            }
525
            $delete = false;
526
            $reset = false;
527
            $ptimes = [];
528
            $now = time();
529
            do {
530
                ini_set('max_execution_time', 120);
531
                $_info = $this->dropbox->delta($cursor);
532
                if (! empty($_info['reset'])) {
533
                    $this->DB->exec('TRUNCATE table '.$this->DB_TableName);
534
                    $this->DB->exec('insert into '.$this->DB_TableName.' values(\'\', \'\', \''.serialize(['cursor' => '', 'mtime' => 0]).'\', 0);');
535
                    $this->DB->exec('insert into '.$this->DB_TableName.' values(\'/\', \'\', \''.serialize([
536
                        'path' => '/',
537
                        'is_dir' => 1,
538
                        'mime_type' => '',
539
                        'bytes' => 0,
540
                    ]).'\', 0);');
541
                    $reset = true;
542
                }
543
                $cursor = $_info['cursor'];
544
545
                foreach ($_info['entries'] as $entry) {
546
                    $key = strtolower($entry[0]);
547
                    $pkey = strtolower($this->_dirname($key));
548
549
                    $path = $this->DB->quote($pkey);
550
                    $fname = $this->DB->quote(strtolower($this->_basename($key)));
551
                    $where = 'where path='.$path.' and fname='.$fname;
552
553
                    if (empty($entry[1])) {
554
                        $ptimes[$pkey] = isset($ptimes[$pkey]) ? max([$now, $ptimes[$pkey]]) : $now;
555
                        $this->DB->exec('delete from '.$this->DB_TableName.' '.$where);
556
                        ! $delete && $delete = true;
557
                        continue;
558
                    }
559
560
                    $_itemTime = strtotime(isset($entry[1]['client_mtime']) ? $entry[1]['client_mtime'] : $entry[1]['modified']);
561
                    $ptimes[$pkey] = isset($ptimes[$pkey]) ? max([$_itemTime, $ptimes[$pkey]]) : $_itemTime;
562
                    $sql = 'select path from '.$this->DB_TableName.' '.$where.' limit 1';
563
                    if (! $reset && $this->query($sql)) {
564
                        $this->DB->exec('update '.$this->DB_TableName.' set dat='.$this->DB->quote(serialize($entry[1])).', isdir='.($entry[1]['is_dir'] ? 1 : 0).' '.$where);
565
                    } else {
566
                        $this->DB->exec('insert into '.$this->DB_TableName.' values ('.$path.', '.$fname.', '.$this->DB->quote(serialize($entry[1])).', '.(int) $entry[1]['is_dir'].')');
567
                    }
568
                }
569
            } while (! empty($_info['has_more']));
570
571
            // update time stamp of parent holder
572
            foreach ($ptimes as $_p => $_t) {
573
                if ($praw = $this->getDBdat($_p)) {
574
                    $_update = false;
575 View Code Duplication
                    if (isset($praw['client_mtime']) && $_t > strtotime($praw['client_mtime'])) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
576
                        $praw['client_mtime'] = date('r', $_t);
577
                        $_update = true;
578
                    }
579 View Code Duplication
                    if (isset($praw['modified']) && $_t > strtotime($praw['modified'])) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
580
                        $praw['modified'] = date('r', $_t);
581
                        $_update = true;
582
                    }
583
                    if ($_update) {
584
                        $pwhere = 'where path='.$this->DB->quote(strtolower($this->_dirname($_p))).' and fname='.$this->DB->quote(strtolower($this->_basename($_p)));
585
                        $this->DB->exec('update '.$this->DB_TableName.' set dat='.$this->DB->quote(serialize($praw)).' '.$pwhere);
586
                    }
587
                }
588
            }
589
590
            $this->DB->exec('update '.$this->DB_TableName.' set dat='.$this->DB->quote(serialize(['cursor' => $cursor, 'mtime' => $_SERVER['REQUEST_TIME']])).' where path=\'\' and fname=\'\'');
591
            if (! $this->DB->commit()) {
592
                $e = $this->DB->errorInfo();
593
594
                return $e[2];
595
            }
596
            if ($delete) {
597
                $this->DB->exec('vacuum');
598
            }
599
        } catch (Dropbox_Exception $e) {
0 ignored issues
show
The class Dropbox_Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
600
            return $e->getMessage();
601
        }
602
603
        return true;
604
    }
605
606
    /**
607
     * Parse line from dropbox metadata output and return file stat (array).
608
     *
609
     * @param  string  $raw  line from ftp_rawlist() output
610
     * @return array
611
     * @author Dmitry Levashov
612
     **/
613
    protected function parseRaw($raw)
0 ignored issues
show
parseRaw uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
614
    {
615
        $stat = [];
616
617
        $stat['rev'] = isset($raw['rev']) ? $raw['rev'] : 'root';
618
        $stat['name'] = $this->_basename($raw['path']);
619
        $stat['mime'] = $raw['is_dir'] ? 'directory' : $raw['mime_type'];
620
        $stat['size'] = $stat['mime'] == 'directory' ? 0 : $raw['bytes'];
621
        $stat['ts'] = isset($raw['client_mtime']) ? strtotime($raw['client_mtime']) :
622
                        (isset($raw['modified']) ? strtotime($raw['modified']) : $_SERVER['REQUEST_TIME']);
623
        $stat['dirs'] = 0;
624
        if ($raw['is_dir']) {
625
            $stat['dirs'] = (int) (bool) $this->query('select path from '.$this->DB_TableName.' where isdir=1 and path='.$this->DB->quote(strtolower($raw['path'])));
626
        }
627
628
        if (! empty($raw['url'])) {
629
            $stat['url'] = $raw['url'];
630
        } elseif (! $this->disabledGetUrl) {
631
            $stat['url'] = '1';
632
        }
633
        if (isset($raw['width'])) {
634
            $stat['width'] = $raw['width'];
635
        }
636
        if (isset($raw['height'])) {
637
            $stat['height'] = $raw['height'];
638
        }
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
    {
652
        $this->dirsCache[$path] = [];
653
        $hasDir = false;
654
655
        $res = $this->query('select dat from '.$this->DB_TableName.' where path='.$this->DB->quote(strtolower($path)));
656
657
        if ($res) {
658
            foreach ($res as $raw) {
0 ignored issues
show
The expression $res of type boolean|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
659
                $raw = unserialize($raw);
660 View Code Duplication
                if ($stat = $this->parseRaw($raw)) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
661
                    $stat = $this->updateCache($raw['path'], $stat);
662
                    if (empty($stat['hidden']) && $path !== $raw['path']) {
663
                        if (! $hasDir && $stat['mime'] === 'directory') {
664
                            $hasDir = true;
665
                        }
666
                        $this->dirsCache[$path][] = $raw['path'];
667
                    }
668
                }
669
            }
670
        }
671
672
        if (isset($this->sessionCache['subdirs'])) {
673
            $this->sessionCache['subdirs'][$path] = $hasDir;
674
        }
675
676
        return $this->dirsCache[$path];
677
    }
678
679
    /**
680
     * Recursive files search.
681
     *
682
     * @param  string  $path   dir path
683
     * @param  string  $q      search string
684
     * @param  array   $mimes
685
     * @return array
686
     * @author Naoki Sawada
687
     **/
688
    protected function doSearch($path, $q, $mimes)
689
    {
690
        $result = [];
691
        $sth = $this->DB->prepare('select dat from '.$this->DB_TableName.' WHERE path LIKE ? AND fname LIKE ?');
692
        $sth->execute([(($path === '/') ? '' : strtolower($path)).'%', '%'.strtolower($q).'%']);
693
        $res = $sth->fetchAll(PDO::FETCH_COLUMN);
694
        $timeout = $this->options['searchTimeout'] ? $this->searchStart + $this->options['searchTimeout'] : 0;
695
696
        if ($res) {
697
            foreach ($res as $raw) {
698 View Code Duplication
                if ($timeout && $timeout < time()) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
699
                    $this->setError(elFinder::ERROR_SEARCH_TIMEOUT, $this->path($this->encode($path)));
700
                    break;
701
                }
702
703
                $raw = unserialize($raw);
704
                if ($stat = $this->parseRaw($raw)) {
705
                    if (! isset($this->cache[$raw['path']])) {
706
                        $stat = $this->updateCache($raw['path'], $stat);
707
                    }
708
                    if (! empty($stat['hidden']) || ($mimes && $stat['mime'] === 'directory') || ! $this->mimeAccepted($stat['mime'], $mimes)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $mimes of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
709
                        continue;
710
                    }
711
                    $stat = $this->stat($raw['path']);
712
                    $stat['path'] = $this->path($stat['hash']);
713
                    $result[] = $stat;
714
                }
715
            }
716
        }
717
718
        return $result;
719
    }
720
721
    /**
722
     * Copy file/recursive copy dir only in current volume.
723
     * Return new file path or false.
724
     *
725
     * @param  string  $src   source path
726
     * @param  string  $dst   destination dir path
727
     * @param  string  $name  new file name (optionaly)
728
     * @return string|false
729
     * @author Dmitry (dio) Levashov
730
     * @author Naoki Sawada
731
     **/
732
    protected function copy($src, $dst, $name)
733
    {
734
        $this->clearcache();
735
736
        return $this->_copy($src, $dst, $name)
737
        ? $this->_joinPath($dst, $name)
738
        : $this->setError(elFinder::ERROR_COPY, $this->_path($src));
739
    }
740
741
    /**
742
     * Remove file/ recursive remove dir.
743
     *
744
     * @param  string $path file path
745
     * @param  bool $force try to remove even if file locked
746
     * @param bool $recursive
747
     * @return bool
748
     * @author Dmitry (dio) Levashov
749
     * @author Naoki Sawada
750
     */
751 View Code Duplication
    protected function remove($path, $force = false, $recursive = false)
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
752
    {
753
        $stat = $this->stat($path);
754
        $stat['realpath'] = $path;
755
        $this->rmTmb($stat);
0 ignored issues
show
$stat is of type array<string,string,{"realpath":"string"}>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
756
        $this->clearcache();
757
758
        if (empty($stat)) {
759
            return $this->setError(elFinder::ERROR_RM, $this->_path($path), elFinder::ERROR_FILE_NOT_FOUND);
760
        }
761
762
        if (! $force && ! empty($stat['locked'])) {
763
            return $this->setError(elFinder::ERROR_LOCKED, $this->_path($path));
764
        }
765
766
        if ($stat['mime'] == 'directory') {
767
            if (! $recursive && ! $this->_rmdir($path)) {
768
                return $this->setError(elFinder::ERROR_RM, $this->_path($path));
769
            }
770
        } else {
771
            if (! $recursive && ! $this->_unlink($path)) {
772
                return $this->setError(elFinder::ERROR_RM, $this->_path($path));
773
            }
774
        }
775
776
        $this->removed[] = $stat;
777
778
        return true;
779
    }
780
781
    /**
782
     * Create thumnbnail and return it's URL on success.
783
     *
784
     * @param  string $path file path
785
     * @param $stat
786
     * @return false|string
787
     * @internal param string $mime file mime type
788
     * @author Dmitry (dio) Levashov
789
     * @author Naoki Sawada
790
     */
791 View Code Duplication
    protected function createTmb($path, $stat)
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
792
    {
793
        if (! $stat || ! $this->canCreateTmb($path, $stat)) {
794
            return false;
795
        }
796
797
        $name = $this->tmbname($stat);
798
        $tmb = $this->tmbPath.DIRECTORY_SEPARATOR.$name;
799
800
        // copy image into tmbPath so some drivers does not store files on local fs
801
        if (! $data = $this->getThumbnail($path, $this->options['getTmbSize'])) {
802
            return false;
803
        }
804
        if (! file_put_contents($tmb, $data)) {
805
            return false;
806
        }
807
808
        $result = false;
0 ignored issues
show
$result is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
809
810
        $tmbSize = $this->tmbSize;
811
812
        if (($s = getimagesize($tmb)) == false) {
813
            return false;
814
        }
815
816
        /* If image smaller or equal thumbnail size - just fitting to thumbnail square */
817
        if ($s[0] <= $tmbSize && $s[1] <= $tmbSize) {
818
            $result = $this->imgSquareFit($tmb, $tmbSize, $tmbSize, 'center', 'middle', $this->options['tmbBgColor'], 'png');
819
        } else {
820
            if ($this->options['tmbCrop']) {
821
822
                /* Resize and crop if image bigger than thumbnail */
823
                if (! (($s[0] > $tmbSize && $s[1] <= $tmbSize) || ($s[0] <= $tmbSize && $s[1] > $tmbSize)) || ($s[0] > $tmbSize && $s[1] > $tmbSize)) {
824
                    $result = $this->imgResize($tmb, $tmbSize, $tmbSize, true, false, 'png');
0 ignored issues
show
$result is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
825
                }
826
827
                if (($s = getimagesize($tmb)) != false) {
828
                    $x = $s[0] > $tmbSize ? intval(($s[0] - $tmbSize) / 2) : 0;
829
                    $y = $s[1] > $tmbSize ? intval(($s[1] - $tmbSize) / 2) : 0;
830
                    $result = $this->imgCrop($tmb, $tmbSize, $tmbSize, $x, $y, 'png');
0 ignored issues
show
$x is of type integer, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
$y is of type integer, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
$result is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
831
                }
832
            } else {
833
                $result = $this->imgResize($tmb, $tmbSize, $tmbSize, true, true, 'png');
0 ignored issues
show
$result is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
834
            }
835
836
            $result = $this->imgSquareFit($tmb, $tmbSize, $tmbSize, 'center', 'middle', $this->options['tmbBgColor'], 'png');
837
        }
838
839
        if (! $result) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $result of type false|string is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
840
            unlink($tmb);
841
842
            return false;
843
        }
844
845
        return $name;
846
    }
847
848
    /**
849
     * Return thumbnail file name for required file.
850
     *
851
     * @param  array  $stat  file stat
852
     * @return string
853
     * @author Dmitry (dio) Levashov
854
     **/
855
    protected function tmbname($stat)
856
    {
857
        return $this->tmbPrefix.$stat['rev'].'.png';
858
    }
859
860
    /**
861
     * Get thumbnail from dropbox.com.
862
     * @param string $path
863
     * @param string $size
864
     * @return string | boolean
865
     */
866
    protected function getThumbnail($path, $size = 'small')
867
    {
868
        try {
869
            return $this->dropbox->getThumbnail($path, $size);
870
        } catch (Dropbox_Exception $e) {
0 ignored issues
show
The class Dropbox_Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
871
            return false;
872
        }
873
    }
874
875
    /*********************** paths/urls *************************/
876
877
    /**
878
     * Return parent directory path.
879
     *
880
     * @param  string  $path  file path
881
     * @return string
882
     * @author Dmitry (dio) Levashov
883
     **/
884
    protected function _dirname($path)
885
    {
886
        return $this->_normpath(substr($path, 0, strrpos($path, '/')));
887
    }
888
889
    /**
890
     * Return file name.
891
     *
892
     * @param  string  $path  file path
893
     * @return string
894
     * @author Dmitry (dio) Levashov
895
     **/
896
    protected function _basename($path)
897
    {
898
        return substr($path, strrpos($path, '/') + 1);
899
    }
900
901
    /**
902
     * Join dir name and file name and retur full path.
903
     *
904
     * @param  string  $dir
905
     * @param  string  $name
906
     * @return string
907
     * @author Dmitry (dio) Levashov
908
     **/
909
    protected function _joinPath($dir, $name)
910
    {
911
        return $this->_normpath($dir.'/'.$name);
912
    }
913
914
    /**
915
     * Return normalized path, this works the same as os.path.normpath() in Python.
916
     *
917
     * @param  string  $path  path
918
     * @return string
919
     * @author Troex Nevelin
920
     **/
921
    protected function _normpath($path)
922
    {
923
        $path = '/'.ltrim($path, '/');
924
925
        return $path;
926
    }
927
928
    /**
929
     * Return file path related to root dir.
930
     *
931
     * @param  string  $path  file path
932
     * @return string
933
     * @author Dmitry (dio) Levashov
934
     **/
935
    protected function _relpath($path)
936
    {
937
        return $path;
938
    }
939
940
    /**
941
     * Convert path related to root dir into real path.
942
     *
943
     * @param  string  $path  file path
944
     * @return string
945
     * @author Dmitry (dio) Levashov
946
     **/
947
    protected function _abspath($path)
948
    {
949
        return $path;
950
    }
951
952
    /**
953
     * Return fake path started from root dir.
954
     *
955
     * @param  string  $path  file path
956
     * @return string
957
     * @author Dmitry (dio) Levashov
958
     **/
959
    protected function _path($path)
960
    {
961
        return $this->rootName.$this->_normpath(substr($path, strlen($this->root)));
962
    }
963
964
    /**
965
     * Return true if $path is children of $parent.
966
     *
967
     * @param  string  $path    path to check
968
     * @param  string  $parent  parent path
969
     * @return bool
970
     * @author Dmitry (dio) Levashov
971
     **/
972
    protected function _inpath($path, $parent)
973
    {
974
        return $path == $parent || strpos($path, $parent.'/') === 0;
975
    }
976
977
    /***************** file stat ********************/
978
979
    /**
980
     * Return stat for given path.
981
     * Stat contains following fields:
982
     * - (int)    size    file size in b. required
983
     * - (int)    ts      file modification time in unix time. required
984
     * - (string) mime    mimetype. required for folders, others - optionally
985
     * - (bool)   read    read permissions. required
986
     * - (bool)   write   write permissions. required
987
     * - (bool)   locked  is object locked. optionally
988
     * - (bool)   hidden  is object hidden. optionally
989
     * - (string) alias   for symlinks - link target path relative to root path. optionally
990
     * - (string) target  for symlinks - link target path. optionally.
991
     *
992
     * If file does not exists - returns empty array or false.
993
     *
994
     * @param  string  $path    file path
995
     * @return array|false
996
     * @author Dmitry (dio) Levashov
997
     **/
998
    protected function _stat($path)
999
    {
1000
        //if (!empty($this->ARGS['reload']) && isset($this->ARGS['target']) && strpos($this->ARGS['target'], $this->id) === 0) {
0 ignored issues
show
Unused Code Comprehensibility introduced by
70% 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...
1001
        if ($this->isMyReload()) {
1002
            $this->deltaCheck();
1003
        }
1004
        if ($raw = $this->getDBdat($path)) {
1005
            return $this->parseRaw($raw);
0 ignored issues
show
$raw is of type array, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1006
        }
1007
1008
        return false;
1009
    }
1010
1011
    /**
1012
     * Return true if path is dir and has at least one childs directory.
1013
     *
1014
     * @param  string  $path  dir path
1015
     * @return bool
1016
     * @author Dmitry (dio) Levashov
1017
     **/
1018
    protected function _subdirs($path)
1019
    {
1020
        return ($stat = $this->stat($path)) && isset($stat['dirs']) ? $stat['dirs'] : false;
1021
    }
1022
1023
    /**
1024
     * Return object width and height
1025
     * Ususaly used for images, but can be realize for video etc...
1026
     *
1027
     * @param  string  $path  file path
1028
     * @param  string  $mime  file mime type
1029
     * @return string
1030
     * @author Dmitry (dio) Levashov
1031
     **/
1032
    protected function _dimensions($path, $mime)
1033
    {
1034
        if (strpos($mime, 'image') !== 0) {
1035
            return '';
1036
        }
1037
        $cache = $this->getDBdat($path);
1038 View Code Duplication
        if (isset($cache['width']) && isset($cache['height'])) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1039
            return $cache['width'].'x'.$cache['height'];
1040
        }
1041
        $ret = '';
1042
        if ($work = $this->getWorkFile($path)) {
1043 View Code Duplication
            if ($size = getimagesize($work)) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1044
                $cache['width'] = $size[0];
1045
                $cache['height'] = $size[1];
1046
                $this->updateDBdat($path, $cache);
1047
                $ret = $size[0].'x'.$size[1];
1048
            }
1049
        }
1050
        is_file($work) && unlink($work);
1051
1052
        return $ret;
1053
    }
1054
1055
    /******************** file/dir content *********************/
1056
1057
    /**
1058
     * Return files list in directory.
1059
     *
1060
     * @param  string  $path  dir path
1061
     * @return array
1062
     * @author Dmitry (dio) Levashov
1063
     * @author Cem (DiscoFever)
1064
     **/
1065
    protected function _scandir($path)
1066
    {
1067
        return isset($this->dirsCache[$path])
1068
            ? $this->dirsCache[$path]
1069
            : $this->cacheDir($path);
1070
    }
1071
1072
    /**
1073
     * Open file and return file pointer.
1074
     *
1075
     * @param  string $path file path
1076
     * @param string $mode
1077
     * @return false|resource
1078
     * @internal param bool $write open file for writing
1079
     * @author Dmitry (dio) Levashov
1080
     */
1081
    protected function _fopen($path, $mode = 'rb')
1082
    {
1083
        if (($mode == 'rb' || $mode == 'r')) {
1084
            try {
1085
                $res = $this->dropbox->media($path);
1086
                $url = parse_url($res['url']);
1087
                $fp = stream_socket_client('ssl://'.$url['host'].':443');
1088
                fwrite($fp, "GET {$url['path']} HTTP/1.0\r\n");
1089
                fwrite($fp, "Host: {$url['host']}\r\n");
1090
                fwrite($fp, "\r\n");
1091
                while (trim(fgets($fp)) !== '') {
0 ignored issues
show
This while loop is empty and can be removed.

This check looks for while loops that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

Consider removing the loop.

Loading history...
1092
                }
1093
1094
                return $fp;
1095
            } catch (Dropbox_Exception $e) {
0 ignored issues
show
The class Dropbox_Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
1096
                return false;
1097
            }
1098
        }
1099
1100
        if ($this->tmp) {
1101
            $contents = $this->_getContents($path);
1102
1103
            if ($contents === false) {
1104
                return false;
1105
            }
1106
1107
            if ($local = $this->getTempFile($path)) {
1108
                if (file_put_contents($local, $contents, LOCK_EX) !== false) {
1109
                    return fopen($local, $mode);
1110
                }
1111
            }
1112
        }
1113
1114
        return false;
1115
    }
1116
1117
    /**
1118
     * Close opened file.
1119
     *
1120
     * @param  resource $fp file pointer
1121
     * @param string $path
1122
     * @return bool
1123
     * @author Dmitry (dio) Levashov
1124
     */
1125
    protected function _fclose($fp, $path = '')
1126
    {
1127
        fclose($fp);
1128
        if ($path) {
1129
            unlink($this->getTempFile($path));
1130
        }
1131
    }
1132
1133
    /********************  file/dir manipulations *************************/
1134
1135
    /**
1136
     * Create dir and return created dir path or false on failed.
1137
     *
1138
     * @param  string  $path  parent dir path
1139
     * @param string  $name  new directory name
1140
     * @return string|bool
1141
     * @author Dmitry (dio) Levashov
1142
     **/
1143
    protected function _mkdir($path, $name)
1144
    {
1145
        $path = $this->_normpath($path.'/'.$name);
1146
        try {
1147
            $this->dropbox->createFolder($path);
1148
        } catch (Dropbox_Exception $e) {
0 ignored issues
show
The class Dropbox_Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
1149
            $this->deltaCheck();
1150
            if ($this->dir($this->encode($path))) {
1151
                return $path;
1152
            }
1153
1154
            return $this->setError('Dropbox error: '.$e->getMessage());
1155
        }
1156
        $this->deltaCheck();
1157
1158
        return $path;
1159
    }
1160
1161
    /**
1162
     * Create file and return it's path or false on failed.
1163
     *
1164
     * @param  string  $path  parent dir path
1165
     * @param string  $name  new file name
1166
     * @return string|bool
1167
     * @author Dmitry (dio) Levashov
1168
     **/
1169
    protected function _mkfile($path, $name)
1170
    {
1171
        return $this->_filePutContents($path.'/'.$name, '');
1172
    }
1173
1174
    /**
1175
     * Create symlink. FTP driver does not support symlinks.
1176
     *
1177
     * @param  string $target link target
1178
     * @param  string $path symlink path
1179
     * @param string $name
1180
     * @return bool
1181
     * @author Dmitry (dio) Levashov
1182
     */
1183
    protected function _symlink($target, $path, $name)
1184
    {
1185
        return false;
1186
    }
1187
1188
    /**
1189
     * Copy file into another file.
1190
     *
1191
     * @param  string  $source     source file path
1192
     * @param  string  $targetDir  target directory path
1193
     * @param  string  $name       new file name
1194
     * @return bool
1195
     * @author Dmitry (dio) Levashov
1196
     **/
1197 View Code Duplication
    protected function _copy($source, $targetDir, $name)
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1198
    {
1199
        $path = $this->_normpath($targetDir.'/'.$name);
1200
        try {
1201
            $this->dropbox->copy($source, $path);
1202
        } catch (Dropbox_Exception $e) {
0 ignored issues
show
The class Dropbox_Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
1203
            return $this->setError('Dropbox error: '.$e->getMessage());
1204
        }
1205
        $this->deltaCheck();
1206
1207
        return true;
1208
    }
1209
1210
    /**
1211
     * Move file into another parent dir.
1212
     * Return new file path or false.
1213
     *
1214
     * @param  string $source source file path
1215
     * @param $targetDir
1216
     * @param  string $name file name
1217
     * @return bool|string
1218
     * @internal param string $target target dir path
1219
     * @author Dmitry (dio) Levashov
1220
     */
1221 View Code Duplication
    protected function _move($source, $targetDir, $name)
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1222
    {
1223
        $target = $this->_normpath($targetDir.'/'.$name);
1224
        try {
1225
            $this->dropbox->move($source, $target);
1226
        } catch (Dropbox_Exception $e) {
0 ignored issues
show
The class Dropbox_Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
1227
            return $this->setError('Dropbox error: '.$e->getMessage());
1228
        }
1229
        $this->deltaCheck();
1230
1231
        return $target;
1232
    }
1233
1234
    /**
1235
     * Remove file.
1236
     *
1237
     * @param  string  $path  file path
1238
     * @return bool
1239
     * @author Dmitry (dio) Levashov
1240
     **/
1241
    protected function _unlink($path)
1242
    {
1243
        try {
1244
            $this->dropbox->delete($path);
1245
        } catch (Dropbox_Exception $e) {
0 ignored issues
show
The class Dropbox_Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
1246
            return $this->setError('Dropbox error: '.$e->getMessage());
1247
        }
1248
        $this->deltaCheck();
1249
1250
        return true;
1251
    }
1252
1253
    /**
1254
     * Remove dir.
1255
     *
1256
     * @param  string  $path  dir path
1257
     * @return bool
1258
     * @author Dmitry (dio) Levashov
1259
     **/
1260
    protected function _rmdir($path)
1261
    {
1262
        return $this->_unlink($path);
1263
    }
1264
1265
    /**
1266
     * Create new file and write into it from file pointer.
1267
     * Return new file path or false on error.
1268
     *
1269
     * @param  resource $fp file pointer
1270
     * @param string $path
1271
     * @param  string $name file name
1272
     * @param  array $stat file stat (required by some virtual fs)
1273
     * @return bool|string
1274
     * @internal param string $dir target dir path
1275
     * @author Dmitry (dio) Levashov
1276
     */
1277
    protected function _save($fp, $path, $name, $stat)
1278
    {
1279
        if ($name) {
1280
            $path .= '/'.$name;
1281
        }
1282
        $path = $this->_normpath($path);
1283
        try {
1284
            $this->dropbox->putFile($path, $fp);
1285
        } catch (Dropbox_Exception $e) {
0 ignored issues
show
The class Dropbox_Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
1286
            return $this->setError('Dropbox error: '.$e->getMessage());
1287
        }
1288
        $this->deltaCheck();
1289
        if (is_array($stat)) {
1290
            $raw = $this->getDBdat($path);
1291
            if (isset($stat['width'])) {
1292
                $raw['width'] = $stat['width'];
1293
            }
1294
            if (isset($stat['height'])) {
1295
                $raw['height'] = $stat['height'];
1296
            }
1297
            $this->updateDBdat($path, $raw);
1298
        }
1299
1300
        return $path;
1301
    }
1302
1303
    /**
1304
     * Get file contents.
1305
     *
1306
     * @param  string  $path  file path
1307
     * @return string|false
1308
     * @author Dmitry (dio) Levashov
1309
     **/
1310
    protected function _getContents($path)
1311
    {
1312
        $contents = '';
1313
        try {
1314
            $contents = $this->dropbox->getFile($path);
1315
        } catch (Dropbox_Exception $e) {
0 ignored issues
show
The class Dropbox_Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
1316
            return $this->setError('Dropbox error: '.$e->getMessage());
1317
        }
1318
1319
        return $contents;
1320
    }
1321
1322
    /**
1323
     * Write a string to a file.
1324
     *
1325
     * @param  string  $path     file path
1326
     * @param  string  $content  new file content
1327
     * @return bool
1328
     * @author Dmitry (dio) Levashov
1329
     **/
1330 View Code Duplication
    protected function _filePutContents($path, $content)
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1331
    {
1332
        $res = false;
1333
1334
        if ($local = $this->getTempFile($path)) {
1335
            if (file_put_contents($local, $content, LOCK_EX) !== false
1336
            && ($fp = fopen($local, 'rb'))) {
1337
                clearstatcache();
1338
                $res = $this->_save($fp, $path, '', []);
1339
                fclose($fp);
1340
            }
1341
            file_exists($local) && unlink($local);
1342
        }
1343
1344
        return $res;
1345
    }
1346
1347
    /**
1348
     * Detect available archivers.
1349
     *
1350
     * @return array
1351
     **/
1352
    protected function _checkArchivers()
1353
    {
1354
        // 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...
1355
        return [];
1356
    }
1357
1358
    /**
1359
     * chmod implementation.
1360
     *
1361
     * @param string $path
1362
     * @param string $mode
1363
     * @return bool
1364
     */
1365
    protected function _chmod($path, $mode)
1366
    {
1367
        return false;
1368
    }
1369
1370
    /**
1371
     * Unpack archive.
1372
     *
1373
     * @param  string  $path  archive path
1374
     * @param  array   $arc   archiver command and arguments (same as in $this->archivers)
1375
     * @return true
1376
     * @return void
1377
     * @author Dmitry (dio) Levashov
1378
     * @author Alexey Sukhotin
1379
     **/
1380
    protected function _unpack($path, $arc)
0 ignored issues
show
The parameter $path is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
The parameter $arc is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1381
    {
1382
        die('Not yet implemented. (_unpack)');
0 ignored issues
show
Coding Style Compatibility introduced by
The method _unpack() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
1383
    }
1384
1385
    /**
1386
     * Recursive symlinks search.
1387
     *
1388
     * @param  string  $path  file/dir path
1389
     * @return bool
1390
     * @author Dmitry (dio) Levashov
1391
     **/
1392
    protected function _findSymlinks($path)
0 ignored issues
show
The parameter $path is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1393
    {
1394
        die('Not yet implemented. (_findSymlinks)');
0 ignored issues
show
Coding Style Compatibility introduced by
The method _findSymlinks() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
1395
    }
1396
1397
    /**
1398
     * Extract files from archive.
1399
     *
1400
     * @param  string  $path  archive path
1401
     * @param  array   $arc   archiver command and arguments (same as in $this->archivers)
1402
     * @return true
1403
     * @author Dmitry (dio) Levashov,
1404
     * @author Alexey Sukhotin
1405
     **/
1406
    protected function _extract($path, $arc)
1407
    {
1408
        die('Not yet implemented. (_extract)');
0 ignored issues
show
Coding Style Compatibility introduced by
The method _extract() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
1409
    }
1410
1411
    /**
1412
     * Create archive and return its path.
1413
     *
1414
     * @param  string  $dir    target dir
1415
     * @param  array   $files  files names list
1416
     * @param  string  $name   archive name
1417
     * @param  array   $arc    archiver options
1418
     * @return string|bool
1419
     * @author Dmitry (dio) Levashov,
1420
     * @author Alexey Sukhotin
1421
     **/
1422
    protected function _archive($dir, $files, $name, $arc)
1423
    {
1424
        die('Not yet implemented. (_archive)');
0 ignored issues
show
Coding Style Compatibility introduced by
The method _archive() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
1425
    }
1426
1427
    /**
1428
     * Check DB for delta cache.
1429
     *
1430
     * @return bool
1431
     */
1432
    private function checkDB()
0 ignored issues
show
checkDB uses the super-global variable $_REQUEST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
1433
    {
1434
        $res = $this->query('SELECT * FROM sqlite_master WHERE type=\'table\' AND name=\''.$this->DB_TableName.'\'');
1435
        if ($res && isset($_REQUEST['init'])) {
1436
            // check is index(nameidx) UNIQUE?
1437
            $chk = $this->query('SELECT sql FROM sqlite_master WHERE type=\'index\' and name=\'nameidx\'');
1438
            if (! $chk || strpos(strtoupper($chk[0]), 'UNIQUE') === false) {
1439
                // remake
1440
                $this->DB->exec('DROP TABLE '.$this->DB_TableName);
1441
                $res = false;
1442
            }
1443
        }
1444
        if (! $res) {
1445
            try {
1446
                $this->DB->exec('CREATE TABLE '.$this->DB_TableName.'(path text, fname text, dat blob, isdir integer);');
1447
                $this->DB->exec('CREATE UNIQUE INDEX nameidx ON '.$this->DB_TableName.'(path, fname)');
1448
                $this->DB->exec('CREATE INDEX isdiridx ON '.$this->DB_TableName.'(isdir)');
1449
            } catch (PDOException $e) {
1450
                return $this->setError($e->getMessage());
1451
            }
1452
        }
1453
1454
        return true;
1455
    }
1456
1457
    /**
1458
     * DB query and fetchAll.
1459
     *
1460
     * @param string $sql
1461
     * @return bool|array
1462
     */
1463
    private function query($sql)
1464
    {
1465
        if ($sth = $this->DB->query($sql)) {
1466
            $res = $sth->fetchAll(PDO::FETCH_COLUMN);
1467
        } else {
1468
            $res = false;
1469
        }
1470
1471
        return $res;
1472
    }
1473
1474
    /**
1475
     * Get dat(dropbox metadata) from DB.
1476
     *
1477
     * @param string $path
1478
     * @return array dropbox metadata
1479
     */
1480
    private function getDBdat($path)
1481
    {
1482
        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')) {
1483
            return unserialize($res[0]);
1484
        } else {
1485
            return [];
1486
        }
1487
    }
1488
1489
    /**
1490
     * Update DB dat(dropbox metadata).
1491
     *
1492
     * @param string $path
1493
     * @param array $dat
1494
     * @return bool|array
1495
     */
1496
    private function updateDBdat($path, $dat)
1497
    {
1498
        return $this->query('update '.$this->DB_TableName.' set dat='.$this->DB->quote(serialize($dat))
1499
                .', isdir='.($dat['is_dir'] ? 1 : 0)
1500
                .' where path='.$this->DB->quote(strtolower($this->_dirname($path))).' and fname='.$this->DB->quote(strtolower($this->_basename($path))));
1501
    }
1502
1503
    /**
1504
     * Get HTTP request response header string.
1505
     *
1506
     * @param string $url target URL
1507
     * @return string
1508
     * @author Naoki Sawada
1509
     */
1510
    private function getHttpResponseHeader($url)
1511
    {
1512
        if (function_exists('curl_exec')) {
1513
            $c = curl_init();
1514
            curl_setopt($c, CURLOPT_RETURNTRANSFER, true);
1515
            curl_setopt($c, CURLOPT_CUSTOMREQUEST, 'HEAD');
1516
            curl_setopt($c, CURLOPT_HEADER, 1);
1517
            curl_setopt($c, CURLOPT_NOBODY, true);
1518
            curl_setopt($c, CURLOPT_URL, $url);
1519
            $res = curl_exec($c);
1520
        } else {
1521
            require_once 'HTTP/Request2.php';
1522
            try {
1523
                $request2 = new HTTP_Request2();
1524
                $request2->setConfig([
1525
                    'ssl_verify_peer' => false,
1526
                    'ssl_verify_host' => false,
1527
                ]);
1528
                $request2->setUrl($url);
1529
                $request2->setMethod(HTTP_Request2::METHOD_HEAD);
1530
                $result = $request2->send();
1531
                $res = [];
1532
                $res[] = 'HTTP/'.$result->getVersion().' '.$result->getStatus().' '.$result->getReasonPhrase();
1533
                foreach ($result->getHeader() as $key => $val) {
1534
                    $res[] = $key.': '.$val;
1535
                }
1536
                $res = implode("\r\n", $res);
1537
            } catch (HTTP_Request2_Exception $e) {
0 ignored issues
show
The class HTTP_Request2_Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
1538
                $res = '';
1539
            } catch (Exception $e) {
1540
                $res = '';
1541
            }
1542
        }
1543
1544
        return $res;
1545
    }
1546
} // END class
1547