Issues (30)

Security Analysis    no request data  

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.

src/Adapter/Ftp.php (1 issue)

Upgrade to new PHP Analysis Engine

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

1
<?php
2
3
namespace League\Flysystem\Adapter;
4
5
use ErrorException;
6
use League\Flysystem\AdapterInterface;
7
use League\Flysystem\Config;
8
use League\Flysystem\Util;
9
use League\Flysystem\Util\MimeType;
10
use RuntimeException;
11
12
class Ftp extends AbstractFtpAdapter
13
{
14
    /**
15
     * Copy a file.
16
     *
17
     * @param string $path
18
     * @param string $newpath
19
     *
20
     * @return bool
21
     */
22 View Code Duplication
    public function copy($path, $newpath)
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...
23
    {
24
        $response = $this->readStream($path);
25
26
        if ($response === false || ! is_resource($response['stream'])) {
27
            return false;
28
        }
29
30
        $result = $this->writeStream($newpath, $response['stream'], new Config());
31
32
        if ($result !== false && is_resource($response['stream'])) {
33
            fclose($response['stream']);
34
        }
35
36
        return $result !== false;
37
    }
38
39
    /**
40
     * @var int
41
     */
42
    protected $transferMode = FTP_BINARY;
43
44
    /**
45
     * @var null|bool
46
     */
47
    protected $ignorePassiveAddress = null;
48
49
    /**
50
     * @var bool
51
     */
52
    protected $recurseManually = false;
53
54
    /**
55
     * @var array
56
     */
57
    protected $configurable = array(
58
        'host',
59
        'port',
60
        'username',
61
        'password',
62
        'ssl',
63
        'timeout',
64
        'root',
65
        'permPrivate',
66
        'permPublic',
67
        'passive',
68
        'transferMode',
69
        'systemType',
70
        'ignorePassiveAddress',
71
        'recurseManually',
72
    );
73
74
    /**
75
     * Set the transfer mode.
76
     *
77
     * @param int $mode
78
     *
79
     * @return $this
80
     */
81 3
    public function setTransferMode($mode)
82
    {
83 3
        $this->transferMode = $mode;
84
85 3
        return $this;
86
    }
87
88
    /**
89
     * Set if Ssl is enabled.
90
     *
91
     * @param bool $ssl
92
     *
93
     * @return $this
94
     */
95 96
    public function setSsl($ssl)
96
    {
97 96
        $this->ssl = (bool) $ssl;
98
99 96
        return $this;
100
    }
101
102
    /**
103
     * Set if passive mode should be used.
104
     *
105
     * @param bool $passive
106
     */
107 78
    public function setPassive($passive = true)
108
    {
109 78
        $this->passive = $passive;
110 78
    }
111
112
    /**
113
     * @param bool $ignorePassiveAddress
114
     */
115 3
    public function setIgnorePassiveAddress($ignorePassiveAddress)
116
    {
117 3
        $this->ignorePassiveAddress = $ignorePassiveAddress;
118 3
    }
119
120
    /**
121
     * @param bool $recurseManually
122
     */
123 66
    public function setRecurseManually($recurseManually)
124
    {
125 66
        $this->recurseManually = $recurseManually;
126 66
    }
127
128
    /**
129
     * Connect to the FTP server.
130
     */
131 90
    public function connect()
132
    {
133 90
        if ($this->ssl) {
134 87
            $this->connection = ftp_ssl_connect($this->getHost(), $this->getPort(), $this->getTimeout());
135 87
        } else {
136 3
            $this->connection = ftp_connect($this->getHost(), $this->getPort(), $this->getTimeout());
137
        }
138
139 90
        if ( ! $this->connection) {
140 6
            throw new RuntimeException('Could not connect to host: ' . $this->getHost() . ', port:' . $this->getPort());
141
        }
142
143 84
        $this->login();
144 81
        $this->setConnectionPassiveMode();
145 78
        $this->setConnectionRoot();
146 75
    }
147
148
    /**
149
     * Set the connections to passive mode.
150
     *
151
     * @throws RuntimeException
152
     */
153 81
    protected function setConnectionPassiveMode()
154
    {
155 81
        if (is_bool($this->ignorePassiveAddress) && defined('FTP_USEPASVADDRESS')) {
156 3
            ftp_set_option($this->connection, FTP_USEPASVADDRESS, ! $this->ignorePassiveAddress);
157 3
        }
158
159 81
        if ( ! ftp_pasv($this->connection, $this->passive)) {
160 3
            throw new RuntimeException(
161 3
                'Could not set passive mode for connection: ' . $this->getHost() . '::' . $this->getPort()
162 3
            );
163
        }
164 78
    }
165
166
    /**
167
     * Set the connection root.
168
     */
169 78
    protected function setConnectionRoot()
170
    {
171 78
        $root = $this->getRoot();
172 78
        $connection = $this->connection;
173
174 78
        if (empty($root) === false && ! ftp_chdir($connection, $root)) {
175 3
            throw new RuntimeException('Root is invalid or does not exist: ' . $this->getRoot());
176
        }
177
178
        // Store absolute path for further reference.
179
        // This is needed when creating directories and
180
        // initial root was a relative path, else the root
181
        // would be relative to the chdir'd path.
182 75
        $this->root = ftp_pwd($connection);
183 75
    }
184
185
    /**
186
     * Login.
187
     *
188
     * @throws RuntimeException
189
     */
190 84
    protected function login()
191
    {
192 84
        set_error_handler(
193 3
            function () {
194 3
            }
195 84
        );
196 84
        $isLoggedIn = ftp_login($this->connection, $this->getUsername(), $this->getPassword());
197 84
        restore_error_handler();
198
199 84
        if ( ! $isLoggedIn) {
200 3
            $this->disconnect();
201 3
            throw new RuntimeException(
202 3
                'Could not login with connection: ' . $this->getHost() . '::' . $this->getPort(
203 3
                ) . ', username: ' . $this->getUsername()
204 3
            );
205
        }
206 81
    }
207
208
    /**
209
     * Disconnect from the FTP server.
210
     */
211 96
    public function disconnect()
212
    {
213 96
        if ($this->isConnected()) {
214 3
            ftp_close($this->connection);
215 3
        }
216
217 96
        $this->connection = null;
218 96
    }
219
220
    /**
221
     * @inheritdoc
222
     */
223 9
    public function write($path, $contents, Config $config)
224
    {
225 9
        $stream = fopen('php://temp', 'w+b');
226 9
        fwrite($stream, $contents);
227 9
        rewind($stream);
228 9
        $result = $this->writeStream($path, $stream, $config);
229 9
        fclose($stream);
230
231 9
        if ($result === false) {
232 6
            return false;
233
        }
234
235 6
        $result['contents'] = $contents;
236 6
        $result['mimetype'] = Util::guessMimeType($path, $contents);
237
238 6
        return $result;
239
    }
240
241
    /**
242
     * @inheritdoc
243
     */
244 9
    public function writeStream($path, $resource, Config $config)
245
    {
246 9
        $this->ensureDirectory(Util::dirname($path));
247
248 9
        if ( ! ftp_fput($this->getConnection(), $path, $resource, $this->transferMode)) {
249 6
            return false;
250
        }
251
252 6
        if ($visibility = $config->get('visibility')) {
253 6
            $this->setVisibility($path, $visibility);
254 6
        }
255
256 6
        return compact('path', 'visibility');
257
    }
258
259
    /**
260
     * @inheritdoc
261
     */
262 6
    public function update($path, $contents, Config $config)
263
    {
264 6
        return $this->write($path, $contents, $config);
265
    }
266
267
    /**
268
     * @inheritdoc
269
     */
270 3
    public function updateStream($path, $resource, Config $config)
271
    {
272 3
        return $this->writeStream($path, $resource, $config);
273
    }
274
275
    /**
276
     * @inheritdoc
277
     */
278 3
    public function rename($path, $newpath)
279
    {
280 3
        return ftp_rename($this->getConnection(), $path, $newpath);
281
    }
282
283
    /**
284
     * @inheritdoc
285
     */
286 3
    public function delete($path)
287
    {
288 3
        return ftp_delete($this->getConnection(), $path);
289
    }
290
291
    /**
292
     * @inheritdoc
293
     */
294 3
    public function deleteDir($dirname)
295
    {
296 3
        $connection = $this->getConnection();
297 3
        $contents = array_reverse($this->listDirectoryContents($dirname));
298
299 3
        foreach ($contents as $object) {
300 3
            if ($object['type'] === 'file') {
301 3
                if ( ! ftp_delete($connection, $object['path'])) {
302 3
                    return false;
303
                }
304 3
            } elseif ( ! ftp_rmdir($connection, $object['path'])) {
305 3
                return false;
306
            }
307 3
        }
308
309 3
        return ftp_rmdir($connection, $dirname);
310
    }
311
312
    /**
313
     * @inheritdoc
314
     */
315 6
    public function createDir($dirname, Config $config)
316
    {
317 6
        $connection = $this->getConnection();
318 6
        $directories = explode('/', $dirname);
319
320 6
        foreach ($directories as $directory) {
321 6
            if (false === $this->createActualDirectory($directory, $connection)) {
322 3
                $this->setConnectionRoot();
323
324 3
                return false;
325
            }
326
327 6
            ftp_chdir($connection, $directory);
328 6
        }
329
330 3
        $this->setConnectionRoot();
331
332 3
        return array('path' => $dirname);
333
    }
334
335
    /**
336
     * Create a directory.
337
     *
338
     * @param string   $directory
339
     * @param resource $connection
340
     *
341
     * @return bool
342
     */
343 6
    protected function createActualDirectory($directory, $connection)
344
    {
345
        // List the current directory
346 6
        $listing = ftp_nlist($connection, '.') ?: array();
347
348 6
        foreach ($listing as $key => $item) {
349 6
            if (preg_match('~^\./.*~', $item)) {
350 6
                $listing[$key] = substr($item, 2);
351 6
            }
352 6
        }
353
354 6
        if (in_array($directory, $listing)) {
355 3
            return true;
356
        }
357
358 6
        return (boolean) ftp_mkdir($connection, $directory);
359
    }
360
361
    /**
362
     * @inheritdoc
363
     */
364 30
    public function getMetadata($path)
365
    {
366 30
        $connection = $this->getConnection();
367
368 30
        if ($path === '') {
369 3
            return array('type' => 'dir', 'path' => '');
370
        }
371
372 27
        if (@ftp_chdir($connection, $path) === true) {
373 3
            $this->setConnectionRoot();
374
375 3
            return array('type' => 'dir', 'path' => $path);
376
        }
377
378 27
        $listing = ftp_rawlist($connection, '-A ' . str_replace('*', '\\*', $path));
379
380 27
        if (empty($listing)) {
381 3
            return false;
382
        }
383
384 24
        if (preg_match('/.* not found/', $listing[0])) {
385 6
            return false;
386
        }
387
388 18
        if (preg_match('/^total [0-9]*$/', $listing[0])) {
389 3
            array_shift($listing);
390 3
        }
391
392 18
        return $this->normalizeObject($listing[0], '');
393
    }
394
395
    /**
396
     * @inheritdoc
397
     */
398 9
    public function getMimetype($path)
399
    {
400 9
        if ( ! $metadata = $this->getMetadata($path)) {
401 6
            return false;
402
        }
403
404 6
        $metadata['mimetype'] = MimeType::detectByFilename($path);
405
406 6
        return $metadata;
407
    }
408
409
    /**
410
     * @inheritdoc
411
     */
412 12
    public function getTimestamp($path)
413
    {
414 12
        $timestamp = ftp_mdtm($this->getConnection(), $path);
415
416 12
        return ($timestamp !== -1) ? array('timestamp' => $timestamp) : false;
417
    }
418
419
    /**
420
     * @inheritdoc
421
     */
422 6
    public function read($path)
423
    {
424 6
        if ( ! $object = $this->readStream($path)) {
425 3
            return false;
426
        }
427
428 3
        $object['contents'] = stream_get_contents($object['stream']);
429 3
        fclose($object['stream']);
430 3
        unset($object['stream']);
431
432 3
        return $object;
433
    }
434
435
    /**
436
     * @inheritdoc
437
     */
438 6
    public function readStream($path)
439
    {
440 6
        $stream = fopen('php://temp', 'w+b');
441 6
        $result = ftp_fget($this->getConnection(), $stream, $path, $this->transferMode);
442 6
        rewind($stream);
443
444 6
        if ( ! $result) {
445 3
            fclose($stream);
446
447 3
            return false;
448
        }
449
450 3
        return compact('stream');
451
    }
452
453
    /**
454
     * @inheritdoc
455
     */
456 9
    public function setVisibility($path, $visibility)
457
    {
458 9
        $mode = $visibility === AdapterInterface::VISIBILITY_PUBLIC ? $this->getPermPublic() : $this->getPermPrivate();
459
460 9
        if ( ! ftp_chmod($this->getConnection(), $mode, $path)) {
461 6
            return false;
462
        }
463
464 6
        return compact('visibility');
465
    }
466
467
    /**
468
     * @inheritdoc
469
     *
470
     * @param string $directory
471
     */
472 21
    protected function listDirectoryContents($directory, $recursive = true)
473
    {
474 21
        $directory = str_replace('*', '\\*', $directory);
475
476 21
        if ($recursive && $this->recurseManually) {
477 3
            return $this->listDirectoryContentsRecursive($directory);
478
        }
479
480 18
        $options = $recursive ? '-alnR' : '-aln';
481 18
        $listing = ftp_rawlist($this->getConnection(), $options . ' ' . $directory);
482
483 18
        return $listing ? $this->normalizeListing($listing, $directory) : array();
484
    }
485
486
    /**
487
     * @inheritdoc
488
     *
489
     * @param string $directory
490
     */
491 3
    protected function listDirectoryContentsRecursive($directory)
492
    {
493 3
        $listing = $this->normalizeListing(ftp_rawlist($this->getConnection(), '-aln' . ' ' . $directory) ?: array());
494 3
        $output = array();
495
496 3
        foreach ($listing as $directory) {
497 3
            $output[] = $directory;
498 3
            if ($directory['type'] !== 'dir') continue;
499
500 3
            $output = array_merge($output, $this->listDirectoryContentsRecursive($directory['path']));
501 3
        }
502
503 3
        return $output;
504
    }
505
506
    /**
507
     * Check if the connection is open.
508
     *
509
     * @return bool
510
     * @throws ErrorException
511
     */
512 96
    public function isConnected()
513
    {
514
        try {
515 96
            return is_resource($this->connection) && ftp_rawlist($this->connection, '/') !== false;
516 6
        } catch (ErrorException $e) {
517 6
            fclose($this->connection);
518 6
            $this->connection = null;
519
520 6
            if (strpos($e->getMessage(), 'ftp_rawlist') === false) {
521 3
                throw $e;
522
            }
523
524 3
            return false;
525
        }
526
    }
527
}
528