Completed
Push — V6 ( b8a845...864daf )
by Georges
10s
created

IOHelperTrait   B

Complexity

Total Complexity 51

Size/Duplication

Total Lines 291
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 2

Importance

Changes 0
Metric Value
dl 0
loc 291
rs 8.3206
c 0
b 0
f 0
wmc 51
lcom 2
cbo 2

9 Methods

Rating   Name   Duplication   Size   Complexity  
F getPath() 0 90 25
B getFilePath() 0 25 5
A encodeFilename() 0 4 1
A isExpired() 0 6 1
A setChmodAuto() 0 8 4
A cleanFileName() 0 11 1
C htaccessGen() 0 30 7
A readfile() 0 20 4
B writefile() 0 34 3

How to fix   Complexity   

Complex Class

Complex classes like IOHelperTrait 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 IOHelperTrait, 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\Pool\IO;
16
17
use phpFastCache\Core\Pool\ExtendedCacheItemPoolInterface;
18
use phpFastCache\Exceptions\phpFastCacheIOException;
19
use phpFastCache\Util\Directory;
20
21
trait IOHelperTrait
22
{
23
    /**
24
     * @var array
25
     */
26
    public $tmp = [];
27
28
    /**
29
     * @param bool $readonly
30
     * @return string
31
     * @throws phpFastCacheIOException
32
     */
33
    public function getPath($readonly = false)
34
    {
35
        /**
36
         * Get the base system temporary directory
37
         */
38
        $tmp_dir = rtrim(ini_get('upload_tmp_dir') ?: sys_get_temp_dir(), '\\/') . DIRECTORY_SEPARATOR . 'phpfastcache';
39
40
        /**
41
         * Calculate the security key
42
         */
43
        {
44
            $securityKey = array_key_exists('securityKey', $this->config) ? $this->config[ 'securityKey' ] : '';
0 ignored issues
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...
45
            if (!$securityKey || $securityKey === 'auto') {
46
                if (isset($_SERVER[ 'HTTP_HOST' ])) {
47
                    $securityKey = preg_replace('/^www./', '', strtolower(str_replace(':', '_', $_SERVER[ 'HTTP_HOST' ])));
48
                } else {
49
                    $securityKey = ($this->isPHPModule() ? 'web' : 'cli');
50
                }
51
            }
52
53
            if ($securityKey !== '') {
54
                $securityKey .= '/';
55
            }
56
57
            $securityKey = static::cleanFileName($securityKey);
58
        }
59
60
        /**
61
         * Extends the temporary directory
62
         * with the security key and the driver name
63
         */
64
        $tmp_dir = rtrim($tmp_dir, '/') . DIRECTORY_SEPARATOR;
65
66
        if (empty($this->config[ 'path' ]) || !is_string($this->config[ 'path' ])) {
67
            $path = $tmp_dir;
68
        } else {
69
            $path = rtrim($this->config[ 'path' ], '/') . DIRECTORY_SEPARATOR;
70
        }
71
72
        $path_suffix = $securityKey . DIRECTORY_SEPARATOR . $this->getDriverName();
73
        $full_path = $path . $path_suffix;
74
        $full_path_tmp = $tmp_dir . $path_suffix;
75
        $full_path_hash = md5($full_path);
76
77
        /**
78
         * In readonly mode we only attempt
79
         * to verify if the directory exists
80
         * or not, if it does not then we
81
         * return the temp dir
82
         */
83
        if ($readonly === true) {
84
            if($this->config[ 'autoTmpFallback' ] && (!@file_exists($full_path) || !@is_writable($full_path))){
85
                return $full_path_tmp;
86
            }
87
            return $full_path;
88
        }else{
89
            if (!isset($this->tmp[ $full_path_hash ]) || (!@file_exists($full_path) || !@is_writable($full_path))) {
90
                if (!@file_exists($full_path)) {
91
                    @mkdir($full_path, $this->setChmodAuto(), true);
0 ignored issues
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.

1 path for user data to reach this point

  1. Fetching key HTTP_HOST from $_SERVER, and $_SERVER['HTTP_HOST'] is passed through str_replace(), and str_replace(':', '_', $_SERVER['HTTP_HOST']) is passed through strtolower(), and strtolower(str_replace(':', '_', $_SERVER['HTTP_HOST'])) is passed through preg_replace(), and $securityKey is assigned
    in src/phpFastCache/Core/Pool/IO/IOHelperTrait.php on line 47
  2. Data is passed through trim(), and Data is passed through preg_replace()
    in vendor/src/phpFastCache/Core/Pool/IO/IOHelperTrait.php on line 204
  3. $securityKey is assigned
    in src/phpFastCache/Core/Pool/IO/IOHelperTrait.php on line 57
  4. $path_suffix is assigned
    in src/phpFastCache/Core/Pool/IO/IOHelperTrait.php on line 72
  5. $full_path is assigned
    in src/phpFastCache/Core/Pool/IO/IOHelperTrait.php on line 73

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...
92
                }else if (!@is_writable($full_path)) {
93
                    @chmod($full_path, $this->setChmodAuto());
0 ignored issues
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.

1 path for user data to reach this point

  1. Fetching key HTTP_HOST from $_SERVER, and $_SERVER['HTTP_HOST'] is passed through str_replace(), and str_replace(':', '_', $_SERVER['HTTP_HOST']) is passed through strtolower(), and strtolower(str_replace(':', '_', $_SERVER['HTTP_HOST'])) is passed through preg_replace(), and $securityKey is assigned
    in src/phpFastCache/Core/Pool/IO/IOHelperTrait.php on line 47
  2. Data is passed through trim(), and Data is passed through preg_replace()
    in vendor/src/phpFastCache/Core/Pool/IO/IOHelperTrait.php on line 204
  3. $securityKey is assigned
    in src/phpFastCache/Core/Pool/IO/IOHelperTrait.php on line 57
  4. $path_suffix is assigned
    in src/phpFastCache/Core/Pool/IO/IOHelperTrait.php on line 72
  5. $full_path is assigned
    in src/phpFastCache/Core/Pool/IO/IOHelperTrait.php on line 73

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...
94
                }
95
96
                if ($this->config[ 'autoTmpFallback' ] && !@is_writable($full_path)) {
97
                    /**
98
                     * Switch back to tmp dir
99
                     * again if the path is not writable
100
                     */
101
                    $full_path = $full_path_tmp;
102
                    if (!@file_exists($full_path)) {
103
                        @mkdir($full_path, $this->setChmodAuto(), true);
0 ignored issues
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.

1 path for user data to reach this point

  1. Fetching key HTTP_HOST from $_SERVER, and $_SERVER['HTTP_HOST'] is passed through str_replace(), and str_replace(':', '_', $_SERVER['HTTP_HOST']) is passed through strtolower(), and strtolower(str_replace(':', '_', $_SERVER['HTTP_HOST'])) is passed through preg_replace(), and $securityKey is assigned
    in src/phpFastCache/Core/Pool/IO/IOHelperTrait.php on line 47
  2. Data is passed through trim(), and Data is passed through preg_replace()
    in vendor/src/phpFastCache/Core/Pool/IO/IOHelperTrait.php on line 204
  3. $securityKey is assigned
    in src/phpFastCache/Core/Pool/IO/IOHelperTrait.php on line 57
  4. $path_suffix is assigned
    in src/phpFastCache/Core/Pool/IO/IOHelperTrait.php on line 72
  5. $full_path_tmp is assigned
    in src/phpFastCache/Core/Pool/IO/IOHelperTrait.php on line 74
  6. $full_path is assigned
    in src/phpFastCache/Core/Pool/IO/IOHelperTrait.php on line 101

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...
104
                    }
105
                }
106
107
                /**
108
                 * In case there is no directory
109
                 * writable including tye temporary
110
                 * one, we must throw an exception
111
                 */
112
                if (!@file_exists($full_path) || !@is_writable($full_path)) {
113
                    throw new phpFastCacheIOException('PLEASE CREATE OR CHMOD ' . $full_path . ' - 0777 OR ANY WRITABLE PERMISSION!');
114
                }
115
116
                $this->tmp[ $full_path_hash ] = $full_path;
117
                $this->htaccessGen($full_path, array_key_exists('htaccess', $this->config) ? $this->config[ 'htaccess' ] : false);
118
            }
119
        }
120
121
        return realpath($full_path);
122
    }
123
124
125
    /**
126
     * @param $keyword
127
     * @param bool $skip
128
     * @return string
129
     * @throws phpFastCacheIOException
130
     */
131
    private function getFilePath($keyword, $skip = false)
132
    {
133
        $path = $this->getPath();
134
135
        if ($keyword === false) {
136
            return $path;
137
        }
138
139
        $filename = $this->encodeFilename($keyword);
140
        $folder = substr($filename, 0, 2) . DIRECTORY_SEPARATOR . substr($filename, 2, 2);
141
        $path = rtrim($path, '/\\') . DIRECTORY_SEPARATOR . $folder;
142
143
        /**
144
         * Skip Create Sub Folders;
145
         */
146
        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...
147
            if (!file_exists($path)) {
148
                if (@!mkdir($path, $this->setChmodAuto(), true)) {
149
                    throw new phpFastCacheIOException('PLEASE CHMOD ' . $path . ' - ' . $this->setChmodAuto() . ' OR ANY WRITABLE PERMISSION!');
150
                }
151
            }
152
        }
153
154
        return $path . '/' . $filename . '.txt';
155
    }
156
157
158
159
    /**
160
     * @param $keyword
161
     * @return string
162
     */
163
    protected function encodeFilename($keyword)
164
    {
165
        return md5($keyword);
166
    }
167
168
    /**
169
     * @return bool
170
     */
171
    public function isExpired()
172
    {
173
        trigger_error(__FUNCTION__ . '() is deprecated, use ExtendedCacheItemInterface::isExpired() instead.', E_USER_DEPRECATED);
174
175
        return true;
176
    }
177
178
    /**
179
     * @param $this ->config
180
     * @return int
181
     */
182
    public function setChmodAuto()
183
    {
184
        if (!isset($this->config[ 'default_chmod' ]) || $this->config[ 'default_chmod' ] == '' || is_null($this->config[ 'default_chmod' ])) {
185
            return 0777;
186
        } else {
187
            return $this->config[ 'default_chmod' ];
188
        }
189
    }
190
191
    /**
192
     * @param $filename
193
     * @return mixed
194
     */
195
    protected static function cleanFileName($filename)
196
    {
197
        $regex = [
198
          '/[\?\[\]\/\\\=\<\>\:\;\,\'\"\&\$\#\*\(\)\|\~\`\!\{\}]/',
199
          '/\.$/',
200
          '/^\./',
201
        ];
202
        $replace = ['-', '', ''];
203
204
        return trim(preg_replace($regex, $replace, trim($filename)), '-');
205
    }
206
207
    /**
208
     * @param $path
209
     * @param bool $create
210
     * @throws phpFastCacheIOException
211
     */
212
    protected function htaccessGen($path, $create = true)
213
    {
214
        if ($create === true) {
215
            if (!is_writable($path)) {
216
                try {
217
                    if(!chmod($path, 0777)){
218
                        throw new phpFastCacheIOException('Chmod failed on : ' . $path);
219
                    }
220
                } catch (phpFastCacheIOException $e) {
221
                    throw new phpFastCacheIOException('PLEASE CHMOD ' . $path . ' - 0777 OR ANY WRITABLE PERMISSION!', 0, $e);
222
                }
223
            }
224
225
            if (!file_exists($path . "/.htaccess")) {
226
                $content = <<<HTACCESS
227
### This .htaccess is auto-generated by PhpFastCache ###
228
order deny, allow
229
deny from all
230
allow from 127.0.0.1
231
HTACCESS;
232
233
                $file = @fopen($path . '/.htaccess', 'w+');
234
                if (!$file) {
235
                    throw new phpFastCacheIOException('PLEASE CHMOD ' . $path . ' - 0777 OR ANY WRITABLE PERMISSION!');
236
                }
237
                fwrite($file, $content);
238
                fclose($file);
239
            }
240
        }
241
    }
242
243
244
    /**
245
     * @param $file
246
     * @return string
247
     * @throws phpFastCacheIOException
248
     */
249
    protected function readfile($file)
250
    {
251
        if (function_exists('file_get_contents')) {
252
            return file_get_contents($file);
0 ignored issues
show
Security File Exposure introduced by
$file can contain request data and is used in file inclusion context(s) leading to a potential security vulnerability.

1 path for user data to reach this point

  1. Fetching key HTTP_HOST from $_SERVER, and $_SERVER['HTTP_HOST'] is passed through str_replace(), and str_replace(':', '_', $_SERVER['HTTP_HOST']) is passed through strtolower(), and strtolower(str_replace(':', '_', $_SERVER['HTTP_HOST'])) is passed through preg_replace(), and $securityKey is assigned
    in src/phpFastCache/Core/Pool/IO/IOHelperTrait.php on line 47
  2. Data is passed through trim(), and Data is passed through preg_replace()
    in vendor/src/phpFastCache/Core/Pool/IO/IOHelperTrait.php on line 204
  3. $securityKey is assigned
    in src/phpFastCache/Core/Pool/IO/IOHelperTrait.php on line 57
  4. $path_suffix is assigned
    in src/phpFastCache/Core/Pool/IO/IOHelperTrait.php on line 72
  5. $full_path_tmp is assigned
    in src/phpFastCache/Core/Pool/IO/IOHelperTrait.php on line 74
  6. IOHelperTrait::getPath() returns tainted data, and $path is assigned
    in src/phpFastCache/Core/Pool/IO/IOHelperTrait.php on line 133
  7. IOHelperTrait::getFilePath() returns tainted data, and $file_path is assigned
    in src/phpFastCache/Drivers/Files/Driver.php on line 98
  8. $file_path is passed to IOHelperTrait::readfile()
    in src/phpFastCache/Drivers/Files/Driver.php on line 103

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...
253
        } else {
254
            $string = '';
255
256
            $file_handle = @fopen($file, 'r');
257
            if (!$file_handle) {
258
                throw new phpFastCacheIOException("Cannot read file located at: {$file}");
259
            }
260
            while (!feof($file_handle)) {
261
                $line = fgets($file_handle);
262
                $string .= $line;
263
            }
264
            fclose($file_handle);
265
266
            return $string;
267
        }
268
    }
269
270
    /**
271
     * @param string $file
272
     * @param string $data
273
     * @param bool $secureFileManipulation
274
     * @return bool
275
     * @throws phpFastCacheIOException
276
     */
277
    protected function writefile($file, $data, $secureFileManipulation = false)
278
    {
279
        /**
280
         * @eventName CacheWriteFileOnDisk
281
         * @param ExtendedCacheItemPoolInterface $this
282
         * @param string $file
283
         * @param bool $secureFileManipulation
284
         *
285
         */
286
        $this->eventManager->dispatch('CacheWriteFileOnDisk', $this, $file, $secureFileManipulation);
0 ignored issues
show
Bug introduced by
The property eventManager 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...
287
288
        if($secureFileManipulation){
289
            $tmpFilename = Directory::getAbsolutePath(dirname($file) . '/tmp_' . md5(
290
                str_shuffle(uniqid($this->getDriverName(), false))
291
                . str_shuffle(uniqid($this->getDriverName(), false))
292
              ));
293
294
            $f = fopen($tmpFilename, 'w+');
295
            flock($f, LOCK_EX);
296
            $octetWritten = fwrite($f, $data);
297
            flock($f, LOCK_UN);
298
            fclose($f);
299
300
            if(!rename($tmpFilename, $file)){
0 ignored issues
show
Security File Manipulation introduced by
$file can contain request data and is used in file manipulation context(s) leading to a potential security vulnerability.

1 path for user data to reach this point

  1. Fetching key HTTP_HOST from $_SERVER, and $_SERVER['HTTP_HOST'] is passed through str_replace(), and str_replace(':', '_', $_SERVER['HTTP_HOST']) is passed through strtolower(), and strtolower(str_replace(':', '_', $_SERVER['HTTP_HOST'])) is passed through preg_replace(), and $securityKey is assigned
    in src/phpFastCache/Core/Pool/IO/IOHelperTrait.php on line 47
  2. Data is passed through trim(), and Data is passed through preg_replace()
    in vendor/src/phpFastCache/Core/Pool/IO/IOHelperTrait.php on line 204
  3. $securityKey is assigned
    in src/phpFastCache/Core/Pool/IO/IOHelperTrait.php on line 57
  4. $path_suffix is assigned
    in src/phpFastCache/Core/Pool/IO/IOHelperTrait.php on line 72
  5. $full_path_tmp is assigned
    in src/phpFastCache/Core/Pool/IO/IOHelperTrait.php on line 74
  6. IOHelperTrait::getPath() returns tainted data, and $path is assigned
    in src/phpFastCache/Core/Pool/IO/IOHelperTrait.php on line 133
  7. IOHelperTrait::getFilePath() returns tainted data, and $file_path is assigned
    in src/phpFastCache/Drivers/Files/Driver.php on line 73
  8. $file_path is passed to IOHelperTrait::writefile()
    in src/phpFastCache/Drivers/Files/Driver.php on line 80

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...
301
                throw new phpFastCacheIOException(sprintf('Failed to rename %s to %s', $tmpFilename, $file));
302
            }
303
        }else{
304
            $f = fopen($file, 'w+');
305
            $octetWritten = fwrite($f, $data);
306
            fclose($f);
307
        }
308
309
        return $octetWritten !== false;
310
    }
311
}