This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
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
|
|||
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 |
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.