Issues (54)

src/Helpers/Secure.php (4 issues)

1
<?php
2
3
namespace BFW\Helpers;
4
5
use \Exception;
6
7
/**
8
 * Helpers to securize data
9
 */
10
class Secure
11
{
12
    /**
13
     * @const ERR_SECURE_KNOWN_TYPE_FILTER_NOT_MANAGED Exception code if the
14
     * data type into the method secureKnownTypes() is not managed.
15
     */
16
    const ERR_SECURE_KNOWN_TYPE_FILTER_NOT_MANAGED = 1609001;
17
    
18
    /**
19
     * @const ERR_SECURE_ARRAY_KEY_NOT_EXIST If the asked key not exist into
20
     * the array to secure.
21
     */
22
    const ERR_SECURE_ARRAY_KEY_NOT_EXIST = 1609002;
23
    
24
    /**
25
     * Hash a string
26
     * 
27
     * @param string $val String to hash
28
     * 
29
     * @return string
30
     */
31
    public static function hash(string $val): string
32
    {
33
        return hash('sha256', md5($val));
34
    }
35
36
    /**
37
     * Securize a string for some types with filter_var function.
38
     * 
39
     * @param mixed $data String to securize
40
     * @param string $type Type of filter
41
     * 
42
     * @return mixed
43
     * 
44
     * @throws \Exception If the type is unknown
45
     */
46
    public static function secureKnownType($data, string $type)
47
    {
48
        $filterType = 'text';
49
50
        if ($type === 'int' || $type === 'integer') {
51
            $filterType = FILTER_VALIDATE_INT;
52
        } elseif ($type === 'float' || $type === 'double') {
53
            $filterType = FILTER_VALIDATE_FLOAT;
54
        } elseif ($type === 'bool' || $type === 'boolean') {
55
            $filterType = FILTER_VALIDATE_BOOLEAN;
56
        } elseif ($type === 'email') {
57
            $filterType = FILTER_VALIDATE_EMAIL;
58
        }
59
60
        if ($filterType === 'text') {
61
            throw new Exception(
62
                'Cannot secure the type',
63
                self::ERR_SECURE_KNOWN_TYPE_FILTER_NOT_MANAGED
64
            );
65
        }
66
67
        return filter_var($data, $filterType);
0 ignored issues
show
It seems like $filterType can also be of type string; however, parameter $filter of filter_var() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

67
        return filter_var($data, /** @scrutinizer ignore-type */ $filterType);
Loading history...
68
    }
69
    
70
    /**
71
     * Securise a mixed data type who are not managed by securiseKnownType.
72
     * We work the data like if the type is a string.
73
     * 
74
     * @param mixed $data The variable to securise
75
     * @param string $type The type of datas
76
     * @param boolean $htmlentities If use htmlentities function
77
     *  to a better security
78
     * 
79
     * @return mixed
80
     */
81
    public static function secureUnknownType(
82
            $data, 
0 ignored issues
show
Multi-line function declaration not indented correctly; expected 8 spaces but found 12
Loading history...
83
            string $type,
0 ignored issues
show
Multi-line function declaration not indented correctly; expected 8 spaces but found 12
Loading history...
84
            bool $htmlentities
0 ignored issues
show
Multi-line function declaration not indented correctly; expected 8 spaces but found 12
Loading history...
85
    ): string {
86
        if ($type !== 'html') {
87
            $data = strip_tags($data);
88
        }
89
        
90
        if ($type === 'html' || $htmlentities === true) {
91
            return htmlentities($data, ENT_QUOTES | ENT_HTML401);
92
        }
93
        
94
        return addslashes($data);
95
    }
96
97
    /**
98
     * Securise a variable
99
     * 
100
     * @param mixed $data The variable to securise
101
     * @param string $type The type of datas
102
     * @param boolean $htmlentities If use htmlentities function
103
     *  to a better security
104
     * 
105
     * @return mixed
106
     * 
107
     * @throws \Exception If an error with a type of data
108
     */
109
    public static function secureData($data, string $type, bool $htmlentities)
110
    {
111
        $currentClass = get_called_class();
112
        
113
        if (is_array($data)) {
114
            foreach ($data as $key => $val) {
115
                unset($data[$key]);
116
117
                $key = $currentClass::secureData($key, gettype($key), true);
118
                $val = $currentClass::secureData($val, $type, $htmlentities);
119
120
                $data[$key] = $val;
121
            }
122
123
            return $data;
124
        }
125
126
        try {
127
            return $currentClass::secureKnownType($data, $type);
128
        } catch (Exception $ex) {
129
            if ($ex->getCode() !== self::ERR_SECURE_KNOWN_TYPE_FILTER_NOT_MANAGED) {
130
                throw new Exception($ex->getMessage(), $ex->getCode());
131
            }
132
            //Else : Use securise like if it's a text type
133
        }
134
135
        return $currentClass::secureUnknownType($data, $type, $htmlentities);
136
    }
137
138
    /**
139
     * Securise the value of an array key for a declared type.
140
     * 
141
     * @param array &$array The array where is the key
142
     * @param string $key The key where is the value to securize
143
     * @param string $type The type of data
144
     * @param boolean $htmlentities (default: false) If use htmlentities
145
     *  function to a better security
146
     * @param boolean $inline (default: true) If array data are inline
147
     * 
148
     * @return mixed
149
     * 
150
     * @throws \Exception If the key not exist in array
151
     */
152
    public static function getSecureKeyInArray(
153
        array &$array,
154
        string $key,
155
        string $type,
156
        bool $htmlentities = false,
157
        bool $inline = true
158
    ) {
159
        if (!isset($array[$key])) {
160
            throw new Exception(
161
                'The key '.$key.' not exist',
162
                self::ERR_SECURE_ARRAY_KEY_NOT_EXIST
163
            );
164
        }
165
166
        $currentClass = get_called_class();
167
        
168
        if (!$inline) {
169
            //Only space, NUL-byte, and vertical tab.
170
            $data = trim($array[$key], ' \0\x0B');
171
        } else {
172
            $data = trim($array[$key]);
173
        }
174
        
175
        return $currentClass::secureData(
176
            $data,
177
            $type,
178
            $htmlentities
179
        );
180
    }
181
    
182
    /**
183
     * Obtain many key from an array in one time
184
     * 
185
     * @param array &$arraySrc The source array
186
     * @param array $keysList The key list to obtain.
187
     *  For each item, the key is the name of the key in source array; And the
188
     *  value the type of the value. The value can also be an object. In this
189
     *  case, the properties "type" contain the value type, the "htmlenties"
190
     *  property contain the boolean who indicate if secure system 
191
     *  will use htmlentities, and the "inline" property contain the boolean who 
192
     *  indicate if data are inline
193
     * @param boolean $throwOnError (defaut true) If a key not exist, throw an
194
     *  exception. If false, the value will be null into returned array
195
     * 
196
     * @return array
197
     * 
198
     * @throws \Exception If a key is not found and if $throwOnError is true
199
     */
200
    public static function getManySecureKeys(
201
        array &$arraySrc,
202
        array $keysList,
203
        bool $throwOnError = true
204
    ): array {
205
        $currentClass = get_called_class();
206
        $result       = [];
207
        
208
        foreach ($keysList as $keyName => $infos) {
209
            if (!is_array($infos)) {
210
                $infos = [
211
                    'type'         => $infos,
212
                    'htmlentities' => false,
213
                    'inline'       => true
214
                ];
215
            }
216
            
217
            try {
218
                $result[$keyName] = $currentClass::getSecureKeyInArray(
219
                    $arraySrc,
220
                    $keyName,
221
                    $infos['type'],
222
                    $infos['htmlentities'],
223
                    $infos['inline']
224
                );
225
            } catch (Exception $ex) {
226
                if ($throwOnError === true) {
227
                    throw new Exception(
228
                        'Error to obtain the key '.$keyName,
229
                        self::ERR_SECURE_ARRAY_KEY_NOT_EXIST,
230
                        $ex
231
                    );
232
                } else {
233
                    $result[$keyName] = null;
234
                }
235
            }
236
        }
237
        
238
        return $result;
239
    }
240
}
241