Completed
Push — 3.0 ( 5276e1...94e02b )
by Vermeulen
01:25
created

Secure::secureUnknownType()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 16
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 9
nc 4
nop 2
dl 0
loc 16
rs 9.9666
c 0
b 0
f 0
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
Bug introduced by
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 boolean $htmlentities If use htmlentities function
76
     *  to a better security
77
     * 
78
     * @return mixed
79
     */
80
    public static function secureUnknownType($data, bool $htmlentities)
81
    {
82
        $currentClass    = get_called_class();
83
        $sqlSecureMethod = $currentClass::getSqlSecureMethod();
84
        
85
        if ($sqlSecureMethod !== null) {
86
            $data = $sqlSecureMethod($data);
87
        } else {
88
            $data = addslashes($data);
89
        }
90
91
        if ($htmlentities === true) {
92
            $data = htmlentities($data, ENT_COMPAT | ENT_HTML401);
93
        }
94
        
95
        return $data;
96
    }
97
98
    /**
99
     * Securise a variable
100
     * 
101
     * @param mixed $data The variable to securise
102
     * @param string $type The type of datas
103
     * @param boolean $htmlentities If use htmlentities function
104
     *  to a better security
105
     * 
106
     * @return mixed
107
     * 
108
     * @throws \Exception If an error with a type of data
109
     */
110
    public static function secureData($data, string $type, bool $htmlentities)
111
    {
112
        $currentClass = get_called_class();
113
        
114
        if (is_array($data)) {
115
            foreach ($data as $key => $val) {
116
                unset($data[$key]);
117
118
                $key = $currentClass::secureData($key, gettype($key), true);
119
                $val = $currentClass::secureData($val, $type, $htmlentities);
120
121
                $data[$key] = $val;
122
            }
123
124
            return $data;
125
        }
126
127
        try {
128
            return $currentClass::secureKnownType($data, $type);
129
        } catch (Exception $ex) {
130
            if ($ex->getCode() !== self::ERR_SECURE_KNOWN_TYPE_FILTER_NOT_MANAGED) {
131
                throw new Exception($ex->getMessage(), $ex->getCode());
132
            }
133
            //Else : Use securise like if it's a text type
134
        }
135
136
        return $currentClass::secureUnknownType($data, $htmlentities);
137
    }
138
139
    /**
140
     * Get the sqlSecure function declared in bfw config file
141
     * 
142
     * @return null|string
143
     */
144
    public static function getSqlSecureMethod()
145
    {
146
        $app       = \BFW\Application::getInstance();
147
        $secureFct = $app->getConfig()->getValue(
148
            'sqlSecureMethod',
149
            'global.php'
150
        );
151
152
        if (!is_callable($secureFct, false)) {
153
            return null;
154
        }
155
156
        return $secureFct;
157
    }
158
159
    /**
160
     * Securise the value of an array key for a declared type.
161
     * 
162
     * @param array &$array The array where is the key
163
     * @param string $key The key where is the value to securize
164
     * @param string $type The type of data
165
     * @param boolean $htmlentities (default: false) If use htmlentities
166
     *  function to a better security
167
     * 
168
     * @return mixed
169
     * 
170
     * @throws \Exception If the key not exist in array
171
     */
172
    public static function getSecureKeyInArray(
173
        array &$array,
174
        string $key,
175
        string $type,
176
        bool $htmlentities = false
177
    ) {
178
        if (!isset($array[$key])) {
179
            throw new Exception(
180
                'The key '.$key.' not exist',
181
                self::ERR_SECURE_ARRAY_KEY_NOT_EXIST
182
            );
183
        }
184
185
        $currentClass = get_called_class();
186
        return $currentClass::secureData(
187
            trim($array[$key]),
188
            $type,
189
            $htmlentities
190
        );
191
    }
192
    
193
    /**
194
     * Obtain many key from an array in one time
195
     * 
196
     * @param array &$arraySrc The source array
197
     * @param array $keysList The key list to obtain.
198
     *  For each item, the key is the name of the key in source array; And the
199
     *  value the type of the value. The value can also be an object. In this
200
     *  case, the properties "type" contain the value type, and the "htmlenties"
201
     *  property contain the boolean who indicate if secure system 
202
     *  will use htmlentities.
203
     * @param boolean $throwOnError (defaut true) If a key not exist, throw an
204
     *  exception. If false, the value will be null into returned array
205
     * 
206
     * @return array
207
     * 
208
     * @throws \Exception If a key is not found and if $throwOnError is true
209
     */
210
    public static function getManySecureKeys(
211
        array &$arraySrc,
212
        array $keysList,
213
        bool $throwOnError = true
214
    ): array {
215
        $currentClass = get_called_class();
216
        $result       = [];
217
        
218
        foreach ($keysList as $keyName => $infos) {
219
            if (!is_array($infos)) {
220
                $infos = [
221
                    'type'         => $infos,
222
                    'htmlentities' => false
223
                ];
224
            }
225
            
226
            try {
227
                $result[$keyName] = $currentClass::getSecureKeyInArray(
228
                    $arraySrc,
229
                    $keyName,
230
                    $infos['type'],
231
                    $infos['htmlentities']
232
                );
233
            } catch (Exception $ex) {
234
                if ($throwOnError === true) {
235
                    throw new Exception(
236
                        'Error to obtain the key '.$keyName,
237
                        self::ERR_SECURE_ARRAY_KEY_NOT_EXIST,
238
                        $ex
239
                    );
240
                } else {
241
                    $result[$keyName] = null;
242
                }
243
            }
244
        }
245
        
246
        return $result;
247
    }
248
}
249