Completed
Branch final (ad8b8d)
by Georges
03:08 queued 28s
created

PathSeekerTrait   B

Complexity

Total Complexity 46

Size/Duplication

Total Lines 210
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 210
rs 8.3999
wmc 46
lcom 1
cbo 2

8 Methods

Rating   Name   Duplication   Size   Complexity  
A setChmodAuto() 0 8 4
A cleanFileName() 0 11 1
A encodeFilename() 0 4 1
F getPath() 0 73 26
A isExpired() 0 6 1
A getFileDir() 0 4 1
B getFilePath() 0 24 5
C htaccessGen() 0 27 7

How to fix   Complexity   

Complex Class

Complex classes like PathSeekerTrait often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use PathSeekerTrait, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 *
4
 * This file is part of phpFastCache.
5
 *
6
 * @license MIT License (MIT)
7
 *
8
 * For full copyright and license information, please see the docs/CREDITS.txt file.
9
 *
10
 * @author Khoa Bui (khoaofgod)  <[email protected]> http://www.phpfastcache.com
11
 * @author Georges.L (Geolim4)  <[email protected]>
12
 *
13
 */
14
15
namespace phpFastCache\Core;
16
17
use phpFastCache\Exceptions\phpFastCacheCoreException;
18
use phpFastCache\Exceptions\phpFastCacheDriverException;
19
20
trait PathSeekerTrait
21
{
22
    /**
23
     * @var array
24
     */
25
    public $tmp = [];
26
27
    /**
28
     * @param bool $skip_create_path
0 ignored issues
show
Bug introduced by
There is no parameter named $skip_create_path. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
29
     * @param $config
30
     * @return string
31
     * @throws \Exception
32
     */
33
    public function getPath($getBasePath = false)
34
    {
35
        $tmp_dir = rtrim(ini_get('upload_tmp_dir') ? ini_get('upload_tmp_dir') : sys_get_temp_dir(), '\\/') . DIRECTORY_SEPARATOR . 'phpfastcache';
36
37
        if (!isset($this->config[ 'path' ]) || $this->config[ 'path' ] == '') {
38
            if (self::isPHPModule()) {
39
                $path = $tmp_dir;
40
            } else {
41
                $document_root_path = rtrim($_SERVER[ 'DOCUMENT_ROOT' ], '/') . '/../';
42
                $path = isset($_SERVER[ 'DOCUMENT_ROOT' ]) && is_writable($document_root_path) ? $document_root_path : rtrim(__DIR__, '/') . '/';
43
            }
44
45
            if ($this->config[ 'path' ] != '') {
46
                $path = $this->config[ 'path' ];
1 ignored issue
show
Bug introduced by
The property config 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...
47
            }
48
49
        } else {
50
            $path = $this->config[ 'path' ];
51
        }
52
53
        if ($getBasePath === true) {
54
            return $path;
55
        }
56
57
        $securityKey = array_key_exists('securityKey', $this->config) ? $this->config[ 'securityKey' ] : '';
58
        if (!$securityKey || $securityKey === 'auto') {
59
            if (isset($_SERVER[ 'HTTP_HOST' ])) {
60
                $securityKey = preg_replace('/^www./', '', strtolower(str_replace(':', '_', $_SERVER[ 'HTTP_HOST' ])));
61
            } else {
62
                $securityKey = ($this->isPHPModule() ? 'web' : 'cli');
63
            }
64
        }
65
66
        if ($securityKey !== '') {
67
            $securityKey .= '/';
68
        }
69
70
        $securityKey = static::cleanFileName($securityKey);
71
72
        $full_path = rtrim($path, '/') . '/' . $securityKey;
73
        $full_pathx = md5($full_path);
74
75
76
        if (!isset($this->tmp[ $full_pathx ])) {
77
78
            if (!@file_exists($full_path) || !@is_writable($full_path)) {
79
                if (!@file_exists($full_path)) {
80
                    @mkdir($full_path, $this->setChmodAuto(), true);
1 ignored issue
show
Security File Manipulation introduced by
$full_path can contain request data and is used in file manipulation context(s) leading to a potential security vulnerability.

General Strategies to prevent injection

In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:

if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
    throw new \InvalidArgumentException('This input is not allowed.');
}

For numeric data, we recommend to explicitly cast the data:

$sanitized = (integer) $tainted;
Loading history...
81
                }
82
                if (!@is_writable($full_path)) {
83
                    @chmod($full_path, $this->setChmodAuto());
1 ignored issue
show
Security File Manipulation introduced by
$full_path can contain request data and is used in file manipulation context(s) leading to a potential security vulnerability.

General Strategies to prevent injection

In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:

if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
    throw new \InvalidArgumentException('This input is not allowed.');
}

For numeric data, we recommend to explicitly cast the data:

$sanitized = (integer) $tainted;
Loading history...
84
                }
85
                if (!@is_writable($full_path)) {
86
                    // switch back to tmp dir again if the path is not writeable
87
                    $full_path = rtrim($tmp_dir, '/') . '/' . $securityKey;
88
                    if (!@file_exists($full_path)) {
89
                        @mkdir($full_path, $this->setChmodAuto(), true);
1 ignored issue
show
Security File Manipulation introduced by
$full_path can contain request data and is used in file manipulation context(s) leading to a potential security vulnerability.

General Strategies to prevent injection

In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:

if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
    throw new \InvalidArgumentException('This input is not allowed.');
}

For numeric data, we recommend to explicitly cast the data:

$sanitized = (integer) $tainted;
Loading history...
90
                    }
91
                    if (!@is_writable($full_path)) {
92
                        @chmod($full_path, $this->setChmodAuto());
1 ignored issue
show
Security File Manipulation introduced by
$full_path can contain request data and is used in file manipulation context(s) leading to a potential security vulnerability.

General Strategies to prevent injection

In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:

if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
    throw new \InvalidArgumentException('This input is not allowed.');
}

For numeric data, we recommend to explicitly cast the data:

$sanitized = (integer) $tainted;
Loading history...
93
                    }
94
                }
95
                if (!@file_exists($full_path) || !@is_writable($full_path)) {
96
                    throw new phpFastCacheCoreException('PLEASE CREATE OR CHMOD ' . $full_path . ' - 0777 OR ANY WRITABLE PERMISSION!', 92);
97
                }
98
            }
99
100
            $this->tmp[ $full_pathx ] = true;
101
            $this->htaccessGen($full_path, array_key_exists('htaccess', $this->config) ? $this->config[ 'htaccess' ] : false);
102
        }
103
104
        return realpath($full_path);
105
    }
106
107
    /**
108
     * @param $keyword
109
     * @return string
110
     */
111
    protected function encodeFilename($keyword)
112
    {
113
        return md5($keyword);
114
    }
115
116
    /**
117
     * @return bool
118
     */
119
    public function isExpired()
120
    {
121
        trigger_error(__FUNCTION__ . '() is deprecated, use ExtendedCacheItemInterface::isExpired() instead.', E_USER_DEPRECATED);
122
123
        return true;
124
    }
125
126
127
    /**
128
     * @return string
129
     * @throws \phpFastCache\Exceptions\phpFastCacheCoreException
130
     */
131
    public function getFileDir()
132
    {
133
        return $this->getPath() . DIRECTORY_SEPARATOR . self::FILE_DIR;
134
    }
135
136
    /**
137
     * @param $keyword
138
     * @param bool $skip
139
     * @return string
140
     * @throws phpFastCacheDriverException
141
     */
142
    private function getFilePath($keyword, $skip = false)
143
    {
144
        $path = $this->getFileDir();
145
146
        if ($keyword === false) {
147
            return $path;
148
        }
149
150
        $filename = $this->encodeFilename($keyword);
151
        $folder = substr($filename, 0, 2);
152
        $path = rtrim($path, '/') . '/' . $folder;
153
        /**
154
         * Skip Create Sub Folders;
155
         */
156
        if ($skip == false) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
157
            if (!file_exists($path)) {
158
                if (@!mkdir($path, $this->setChmodAuto(), true)) {
1 ignored issue
show
Security File Manipulation introduced by
$path can contain request data and is used in file manipulation context(s) leading to a potential security vulnerability.

General Strategies to prevent injection

In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:

if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
    throw new \InvalidArgumentException('This input is not allowed.');
}

For numeric data, we recommend to explicitly cast the data:

$sanitized = (integer) $tainted;
Loading history...
159
                    throw new phpFastCacheDriverException('PLEASE CHMOD ' . $this->getPath() . ' - ' . $this->setChmodAuto() . ' OR ANY WRITABLE PERMISSION!');
160
                }
161
            }
162
        }
163
164
        return $path . '/' . $filename . '.txt';
165
    }
166
167
168
    /**
169
     * @param $this ->config
170
     * @return int
171
     */
172
    public function setChmodAuto()
173
    {
174
        if (!isset($this->config[ 'default_chmod' ]) || $this->config[ 'default_chmod' ] == '' || is_null($this->config[ 'default_chmod' ])) {
175
            return 0777;
176
        } else {
177
            return $this->config[ 'default_chmod' ];
178
        }
179
    }
180
181
    /**
182
     * @param $filename
183
     * @return mixed
184
     */
185
    protected static function cleanFileName($filename)
186
    {
187
        $regex = [
188
          '/[\?\[\]\/\\\=\<\>\:\;\,\'\"\&\$\#\*\(\)\|\~\`\!\{\}]/',
189
          '/\.$/',
190
          '/^\./',
191
        ];
192
        $replace = ['-', '', ''];
193
194
        return trim(preg_replace($regex, $replace, trim($filename)), '-');
195
    }
196
197
    /**
198
     * @param $path
199
     * @param bool $create
200
     * @throws \Exception
201
     */
202
    protected function htaccessGen($path, $create = true)
203
    {
204
        if ($create === true) {
205
            if (!is_writable($path)) {
206
                try {
207
                    if(!chmod($path, 0777)){
1 ignored issue
show
Security File Manipulation introduced by
$path can contain request data and is used in file manipulation context(s) leading to a potential security vulnerability.

General Strategies to prevent injection

In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:

if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
    throw new \InvalidArgumentException('This input is not allowed.');
}

For numeric data, we recommend to explicitly cast the data:

$sanitized = (integer) $tainted;
Loading history...
208
                        throw new phpFastCacheDriverException('Chmod failed on : ' . $path);
209
                    }
210
                } catch (phpFastCacheDriverException $e) {
211
                    throw new phpFastCacheDriverException('PLEASE CHMOD ' . $path . ' - 0777 OR ANY WRITABLE PERMISSION!', 0, $e);
212
                }
213
            }
214
215
            if (!file_exists($path . "/.htaccess")) {
216
                $html = "order deny, allow \r\n
217
deny from all \r\n
218
allow from 127.0.0.1";
219
220
                $file = @fopen($path . '/.htaccess', 'w+');
221
                if (!$file) {
222
                    throw new phpFastCacheDriverException('PLEASE CHMOD ' . $path . ' - 0777 OR ANY WRITABLE PERMISSION!');
223
                }
224
                fwrite($file, $html);
225
                fclose($file);
226
            }
227
        }
228
    }
229
}