Completed
Push — master ( 17c5b4...da708e )
by Bjørn
03:12
created

PathChecker::checkSourceAndDestinationPaths()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 2
dl 0
loc 4
ccs 0
cts 3
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace WebPConvert\Helpers;
4
5
use WebPConvert\Exceptions\InvalidInputException;
6
use WebPConvert\Exceptions\InvalidInput\TargetNotFoundException;
7
8
/**
9
 * Functions for sanitizing.
10
 *
11
 * @package    WebPConvert
12
 * @author     Bjørn Rosell <[email protected]>
13
 * @since      Class available since Release 2.0.6
14
 */
15
class PathChecker
16
{
17
18
     /**
19
      * Check absolute file path to prevent attacks.
20
      *
21
      * - Prevents non printable characters
22
      * - Prevents stream wrappers
23
      * - Prevents directory traversal
24
      *
25
      * Preventing non printable characters is especially done to prevent the NUL character, which can be used
26
      * to bypass other tests. See https://st-g.de/2011/04/doing-filename-checks-securely-in-PHP.
27
      *
28
      * Preventeng stream wrappers is especially done to protect against Phar Deserialization.
29
      * See https://blog.ripstech.com/2018/new-php-exploitation-technique/
30
      *
31
      * @param  string  $absFilePath
32
      * @return string  sanitized file path
33
      */
34 36
    public static function checkAbsolutePath($absFilePath, $text = 'file')
35
    {
36 36
        if (empty($absFilePath)) {
37
            throw new InvalidInputException('Empty filepath for ' . $text);
38
        }
39
40
        // Prevent non printable characters
41 36
        if (!ctype_print($absFilePath)) {
42
            throw new InvalidInputException('Non-printable characters are not allowed in ' . $text);
43
        }
44
45
        // Prevent directory traversal
46 36
        if (preg_match('#\.\.\/#', $absFilePath)) {
47
            throw new InvalidInputException('Directory traversal is not allowed in ' . $text . ' path');
48
        }
49
50
        // Prevent stream wrappers ("phar://", "php://" and the like)
51
        // https://www.php.net/manual/en/wrappers.phar.php
52 36
        if (preg_match('#^\\w+://#', $absFilePath)) {
53
            throw new InvalidInputException('Stream wrappers are not allowed in ' . $text . ' path');
54
        }
55 36
    }
56
57 36
    public static function checkAbsolutePathAndExists($absFilePath, $text = 'file')
58
    {
59 36
        if (empty($absFilePath)) {
60
            throw new TargetNotFoundException($text . ' argument missing');
61
        }
62 36
        self::checkAbsolutePath($absFilePath, $text);
63 36
        if (@!file_exists($absFilePath)) {
64 5
            throw new TargetNotFoundException($text . ' file was not found');
65
        }
66 35
        if (@is_dir($absFilePath)) {
67
            throw new InvalidInputException($text . ' is a directory');
68
        }
69 35
    }
70
71
    /**
72
     *  Checks that source path is secure, file exists and it is not a dir.
73
     *
74
     *  To also check mime type, use InputValidator::checkSource
75
     */
76 31
    public static function checkSourcePath($source)
77
    {
78 31
        self::checkAbsolutePathAndExists($source, 'source');
79 30
    }
80
81 30
    public static function checkDestinationPath($destination)
82
    {
83 30
        if (empty($destination)) {
84
            throw new InvalidInputException('Destination argument missing');
85
        }
86 30
        self::checkAbsolutePath($destination, 'destination');
87 30
        if (@is_dir($destination)) {
88
            throw new InvalidInputException('Destination is a directory');
89
        }
90 30
    }
91
92
    public static function checkSourceAndDestinationPaths($source, $destination)
93
    {
94
        self::checkSourcePath($source);
95
        self::checkDestinationPath($destination);
96
    }
97
}
98