Sanitize.php 7.06 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
<?php
/**
 * Created by PhpStorm.
 * User: crose
 * Date: 1/2/16
 * Time: 10:57 PM
 */

namespace qfq;

Carsten  Rose's avatar
Carsten Rose committed
11
use qfq;
12
13
14

//use qfq\CodeException;
//use qfq\UserFormException;
15

16
require_once(__DIR__ . '/../../qfq/Constants.php');
17
//require_once(__DIR__ . '/../exceptions/UserFormException.php');
18

Carsten  Rose's avatar
Carsten Rose committed
19
/**
Carsten  Rose's avatar
Carsten Rose committed
20
 * Class Sanitize
Carsten  Rose's avatar
Carsten Rose committed
21
22
 * @package qfq
 */
Carsten  Rose's avatar
Carsten Rose committed
23
class Sanitize {
24

25

26
27
28
29
30
    private function __construct() {
        // Class should never be instantiated
    }

    /**
31
32
     * Check $value against given checkType/pattern. If check succeed, returns values.
     *   If check fails, depending on $mode, throws an UserException or return an empty string.
33
     *
34
35
36
37
38
     * @param string $value value to check
     * @param string $sanatizeClass SANITIZE_ALLOW_*
     * @param string $patternOrRange Pattern as regexp or MIN|MAX values
     * @param string $mode SANATIZE_EXCEPTION | SANATIZE_EMPTY_STRING
     * @return string
39
     * @throws UserFormException
40
     * @throws \qfq\CodeException
41
     */
42
43
44
45
46
    public static function sanitize($value, $sanatizeClass = SANITIZE_DEFAULT, $patternOrRange = '', $mode = SANATIZE_EMPTY_STRING) {
        $pattern = '';
        $minMax = array();
        $valueCompare = '';
        $errorCode = 0;
47
        $errorText = '';
48

49
50
51
52
53
54
55
56
57
        // Prepare MIN|MAX
        switch ($sanatizeClass) {
            case SANITIZE_ALLOW_MIN_MAX:
                $minMax = explode('|', $patternOrRange);
                $valueCompare = $value;
                break;

            case SANITIZE_ALLOW_MIN_MAX_DATE:
                $minMax = explode('|', $patternOrRange);
58
59
60
61
62

                //TODO: hier sollten die Exceptions abgefangen werden um zwei unterschiedliche Fehlermeldungen ausgeben zu koenenn:
                // a) der Value verletzt die Datumsgrenzen
                // b) die Definition der Grenzen ist buggy
//                try {
63
                $valueCompare = Support::dateTimeGermanToInternational($value);
64
65
66
67
68
//                } catch (UserFormException $e) {
//                    throw new UserFormException("Date or time not recognized '" . $value . "' - " . $e->formatMessage(), ERROR_SANATIZE_INVALID_VALUE);
//                }

//                try {
69
70
                $minMax[0] = Support::dateTimeGermanToInternational($minMax[0]);
                $minMax[1] = Support::dateTimeGermanToInternational($minMax[1]);
71
72
73
74
//                } catch  (UserFormException $e) {
//                    throw new UserFormException("Date or time of min|max definition not recognized '" . $patternOrRange . "' - " . $e->formatMessage(), ERROR_SANATIZE_INVALID_VALUE);
//                }

75
76
77
78
79
80
81
82
83
84
85
86
                break;

            default:
                break;
        }

        // Prepare Check
        switch ($sanatizeClass) {
            case SANITIZE_ALLOW_MIN_MAX:
            case SANITIZE_ALLOW_MIN_MAX_DATE:

                if ($minMax[0] === '' || $minMax[1] === '') {
87
                    throw new UserFormException('Missing definition of value for min or max.', ERROR_MISSING_MIN_MAX);
88
                }
89
            $errorText = "Value '$value' is out of range of '$patternOrRange'.";
90
91
92
93
94

                if ($minMax[0] <= $valueCompare && $valueCompare <= $minMax[1])
                    return $value;

                $errorCode = ERROR_MIN_MAX_VIOLATION;
95
96
                break;

97
98
            case SANITIZE_ALLOW_PATTERN:
                $pattern = $patternOrRange;
99
100
                break;

101
102
103
            case SANITIZE_ALLOW_DIGIT:
            case SANITIZE_ALLOW_EMAIL:
            case SANITIZE_ALLOW_ALNUMX:
104
            case SANITIZE_ALLOW_ALLBUT:
105
106
                $arr = self::inputCheckPatternArray();
                $pattern = $arr[$sanatizeClass];
107
108
                break;

109
110
111
            case SANITIZE_ALLOW_ALL: // no checktype specified.
                return $value;

112
            default:
113
114
115
116
117
118
119
120
121
                throw new CodeException("Unknown checkType: " . $sanatizeClass, ERROR_UNKNOWN_CHECKTYPE);
        }

        // No error until here: do a final check
        if ($errorCode == 0) {
            if (preg_match("/$pattern/", $value) === 1)
                return $value;
            else
                $errorCode = ERROR_PATTERN_VIOLATION;
122
123
        }

124
        if ($mode === SANATIZE_EXCEPTION) {
125
126
            if ($errorText === '')
                $errorText = "Value '$value' violates checkrule " . $sanatizeClass . " with pattern '$pattern'.";
127
            throw new UserFormException($errorText, $errorCode);
128
129
130
131
132
133
134
135
136
        }

        // check failed: return empty string
        return '';
    }

    /**
     * @return array
     */
137
    public static function inputCheckPatternArray() {
138
        //EMail Regex: http://www.regular-expressions.info/email.html
139
        return [
140
            SANITIZE_ALLOW_ALNUMX => '^[@\-_\.,;: \/\(\)a-zA-Z0-9ÀÈÌÒÙàèìòùÁÉÍÓÚÝáéíóúýÂÊÎÔÛâêîôûÃÑÕãñõÄËÏÖÜŸäëïöüÿ]*$', // ':alnum:' does not work here in FF
141
            SANITIZE_ALLOW_DIGIT => '^[\d]*$',
142
            SANITIZE_ALLOW_EMAIL => '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$',
143
144
145
            SANITIZE_ALLOW_MIN_MAX => '',
            SANITIZE_ALLOW_MIN_MAX_DATE => '',
            SANITIZE_ALLOW_PATTERN => '',
146
            SANITIZE_ALLOW_ALLBUT => '^[^\[\]{}%&\\\\#]*$',
147
148
            SANITIZE_ALLOW_ALL => '.*'
        ];
149
150
    }

151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179

    /**
     * Sanatizes a filename. Copied from http://www.phpit.net/code/filename-safe/
     *
     * @param $filename
     * @return mixed
     */
    public static function safeFilename($filename) {
        $search = array(
            // Definition of German Umlauts START
            '/ß/',
            '/ä/', '/Ä/',
            '/ö/', '/Ö/',
            '/ü/', '/Ü/',
            // Definition of German Umlauts ENDE
            '([^[:alnum:]._])' // Disallow: Not alphanumeric, dot or underscore
        );

        $replace = array(
            'ss',
            'ae', 'Ae',
            'oe', 'Oe',
            'ue', 'Ue',
            '_'
        );

        return preg_replace($search, $replace, $filename);
    } // safeFilename()

180
    /**
Carsten  Rose's avatar
Carsten Rose committed
181
182
183
     * Take the given $item (or iterates over all elements of the given array) and normalize the content.
     * Only strings will be normalized. Sub arrays will be recursived normalized. Numeric content is skipped.
     * Throws an exception for unknown content.
184
185
     *
     * It's important to normalize the user input: e.g. someone is searching for a record and input the search string
Carsten  Rose's avatar
Carsten Rose committed
186
     * with composed characters (happens e.g. on Apple Mac / Safari without special user invention).
187
     *
188
189
190
     * @param array|string $item
     * @return array|string
     * @throws CodeException
191
     */
192
193
194
195
196
197
198
199
200
201
202
    public static function normalize($item) {

        if (is_array($item)) {
            foreach ($item as $key => $value) {
                $value = self::normalize($value);
                $item[$key] = $value;
            }
        } else {
            if (is_string($item)) {
                $item = \normalizer::normalize($item, \Normalizer::FORM_C);
            } elseif (!is_numeric($item)) {
203
204
205
                throw new qfq\CodeException ("Expect type 'string / numeric / array' - but there is something else.", ERROR_UNEXPECTED_TYPE);
            }
        }
206
        return $item;
207
    }
208
}