Completed
Pull Request — 8.3 (#43)
by ARP
01:59
created

PhpVarsCheckRouter::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
c 0
b 0
f 0
rs 10
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
3
namespace Mouf\Mvc\Splash\Routers;
4
5
use Mouf\Mvc\Splash\Utils\SplashException;
6
use Psr\Http\Message\ResponseInterface as Response;
7
use Psr\Http\Message\ResponseInterface;
8
use Psr\Http\Message\ServerRequestInterface as Request;
9
use Psr\Http\Server\MiddlewareInterface;
10
use Psr\Http\Server\RequestHandlerInterface;
11
use Psr\Log\LoggerInterface;
12
13
/**
14
 * This router :
15
 *  - just checks that some PHP settings are not exceeded : max_input_vars, max_post_size
16
 *  - doesn't actually 'routes' the request. It's more like a filter to me applied and check the request.
17
 *  - should be placed BEFORE the effective applications router and AFTER the Exceptions handling routers.
18
 *
19
 * @author Kevin Nguyen
20
 */
21
class PhpVarsCheckRouter implements MiddlewareInterface
22
{
23
24
    /**
25
     * A simple counter to check requests' length (GET, POST, REQUEST).
26
     *
27
     * @var int
28
     */
29
    private $count;
30
31
    /**
32
     * Get the min in 2 values if there exist.
33
     *
34
     * @param int $val1
35
     * @param int $val2
36
     *
37
     * @return int|NULL
38
     */
39
    private function getMinInConfiguration($val1, $val2)
40
    {
41
        if ($val1 && $val2) {
42
            return min(array($val1, $val2));
43
        }
44
        if ($val1) {
45
            return $val1;
46
        }
47
        if ($val2) {
48
            return $val2;
49
        }
50
51
        return null;
52
    }
53
54
    /**
55
     * Returns the number of bytes from php.ini parameter.
56
     *
57
     * @param $val
58
     *
59
     * @return int|string
60
     */
61
    private static function iniGetBytes($val)
62
    {
63
        $val = trim(ini_get($val));
64
        if ($val != '') {
65
            $last = strtolower(
66
                    $val{strlen($val) - 1}
67
            );
68
        } else {
69
            $last = '';
70
        }
71
        $val = (int) $val;
72
        switch ($last) {
73
            // The 'G' modifier is available since PHP 5.1.0
74
            case 'g':
75
                $val *= 1024;
76
            case 'm':
77
                $val *= 1024;
78
            case 'k':
79
                $val *= 1024;
80
        }
81
82
        return $val;
83
    }
84
85
    /**
86
     * Count number of element in array.
87
     *
88
     * @param mixed $item
89
     * @param mixed $key
90
     */
91
    private function countRecursive($item, $key)
0 ignored issues
show
Unused Code introduced by
The parameter $item is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $key is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
92
    {
93
        ++$this->count;
94
    }
95
96
    /**
97
     * Process an incoming server request and return a response, optionally delegating
98
     * to the next middleware component to create the response.
99
     *
100
     * @param Request $request
101
     *
102
     * @param RequestHandlerInterface $handler
103
     * @return ResponseInterface
104
     * @throws SplashException
105
     */
106
    public function process(Request $request, RequestHandlerInterface $handler): ResponseInterface
107
    {
108
        // Check if there is a limit of input number in php
109
        // Throw exception if the limit is reached
110 View Code Duplication
        if (ini_get('max_input_vars') || ini_get('suhosin.get.max_vars')) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
111
            $maxGet = $this->getMinInConfiguration(ini_get('max_input_vars'), ini_get('suhosin.get.max_vars'));
112
            if ($maxGet !== null) {
113
                $this->count = 0;
114
                array_walk_recursive($_GET, array($this, 'countRecursive'));
115
                if ($this->count === $maxGet) {
116
                    throw new SplashException('Max input vars reaches for get parameters ('.$maxGet.'). Check your variable max_input_vars in php.ini or suhosin module suhosin.get.max_vars.');
117
                }
118
            }
119
        }
120 View Code Duplication
        if (ini_get('max_input_vars') || ini_get('suhosin.post.max_vars')) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
121
            $maxPost = $this->getMinInConfiguration(ini_get('max_input_vars'), ini_get('suhosin.post.max_vars'));
122
            if ($maxPost !== null) {
123
                $this->count = 0;
124
                array_walk_recursive($_POST, array($this, 'countRecursive'));
125
                if ($this->count === $maxPost) {
126
                    throw new SplashException('Max input vars reaches for post parameters ('.$maxPost.'). Check your variable max_input_vars in php.ini or suhosin module suhosin.post.max_vars.');
127
                }
128
            }
129
        }
130 View Code Duplication
        if (ini_get('max_input_vars') || ini_get('suhosin.request.max_vars')) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
131
            $maxRequest = $this->getMinInConfiguration(ini_get('max_input_vars'), ini_get('suhosin.request.max_vars'));
132
            if ($maxRequest !== null) {
133
                $this->count = 0;
134
                array_walk_recursive($_REQUEST, array($this, 'countRecursive'));
135
                if ($this->count === $maxRequest) {
136
                    throw new SplashException('Max input vars reaches for request parameters ('.$maxRequest.'). Check your variable max_input_vars in php.ini or suhosin module suhosin.request.max_vars.');
137
                }
138
            }
139
        }
140
        if (isset($_SERVER['REQUEST_METHOD']) && strtolower($_SERVER['REQUEST_METHOD']) == 'post' && empty($_POST) && empty($_FILES)) {
141
            $maxPostSize = self::iniGetBytes('post_max_size');
142
            if ($_SERVER['CONTENT_LENGTH'] > $maxPostSize) {
143
                throw new SplashException(
144
                    sprintf('Max post size exceeded! Got %s bytes, but limit is %s bytes. Edit post_max_size setting in your php.ini.',
145
                        $_SERVER['CONTENT_LENGTH'],
146
                        $maxPostSize
147
                    )
148
                );
149
            }
150
        }
151
152
        //If no Exception has been thrown, call next router
153
        return $handler->handle($request);
154
    }
155
}
156