Config.php 10.2 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
<?php
/**
 * Created by PhpStorm.
 * User: crose
 * Date: 3/6/17
 * Time: 8:47 PM
 */

namespace qfq;

use qfq;

13
14
require_once(__DIR__ . '/../Constants.php');
require_once(__DIR__ . '/../helper/Support.php');
15
16
17
18
19
20

class Config {

    /**
     * Read config.qfq.ini.
     *
21
     * @param string $fileConfigIni
Carsten  Rose's avatar
Carsten Rose committed
22
     *
23
24
     * @return array
     * @throws UserFormException
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
     */
    public function readConfig($fileConfigIni = '') {

        if ($fileConfigIni == '') {
            // Production Path to CONFIG_INI
            $fileConfigIni = __DIR__ . '/../../../../../' . CONFIG_INI;
            if (!file_exists($fileConfigIni)) {
                // PHPUnit Path to CONFIG_INI
                $fileConfigIni = __DIR__ . '/../../../' . CONFIG_INI;
            }
        }

        try {
            $config = parse_ini_file($fileConfigIni, false);

        } catch (\Exception $e) {
            throw new qfq\UserFormException ("Error read file " . $fileConfigIni . ": " . $e->getMessage(), ERROR_IO_READ_FILE);
        }

        $config = self::renameConfigElements($config);
45
        $config = self::setDefaults($config);
46
        self::checkDeprecated($config);
47
48
49
50
51
        self::checkForAttack($config);

        return $config;
    }

52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
    /**
     * Checks for deprecated options.
     */
    private static function checkDeprecated(array $config) {

        foreach ([SYSTEM_VAR_ADD_BY_SQL] as $key) {

            if (isset($config[$key])) {
                $msg = '';
                switch ($key) {
                    case SYSTEM_VAR_ADD_BY_SQL:
                        $msg = 'Replaced by: ' . SYSTEM_FILL_STORE_SYSTEM_BY_SQL . '_1|2|3';
                }
                throw new qfq\UserFormException ("Deprecated option in " . CONFIG_INI . ": " . SYSTEM_VAR_ADD_BY_SQL . " - " . $msg);
            }
        }
    }


71
72
73
74
    /**
     * @param array $config
     */
    private static function checkForAttack(array $config) {
75
        $attack = false;
76
        $key = '';
77
78
79
80

        // Iterate over all fake vars
        $arr = explode(',', $config[SYSTEM_SECURITY_VARS_HONEYPOT]);
        foreach ($arr as $key) {
81
82
83
84
            $key = trim($key);
            if ($key === '') {
                continue;
            }
85
            if (!empty($_POST[$key]) || !empty($_GET[$key])) {
86
87
88
89
90
91
92
                $attack = true;
            }
        }

        // Limit length of all get vars: protect against SQL injection based on long ...%34%34%24%34...
        $maxLength = $config[SYSTEM_SECURITY_GET_MAX_LENGTH];
        if ($maxLength > 0) {
93
94
95
            foreach ($_GET as $key => $value) {
                // Check if the variable is something like 'my_name_100' - if the part after the last '_' is numerical, this means a valid, non standard length.
                $arr = explode(GET_EXTRA_LENGTH_TOKEN, $key);
96

97
98
                $cnt = count($arr);
                if ($cnt > 1 && is_numeric($arr[$cnt - 1])) {
99
100
101
102
103
104
                    $maxLength = $arr[$cnt - 1];
                } else {
                    $maxLength = $config[SYSTEM_SECURITY_GET_MAX_LENGTH]; // might change again.
                }

                if (strlen($value) > $maxLength) {
105
                    $attack = true;
106
                    break;
107
                }
108
109
110
111
            }
        }

        // Nothing found?
112
        if ($attack === false) {
113
114
115
            return;
        }

116
        self::attackDetectedExitNow($config, $key);
117
118
119
120
121
    }

    /**
     * @throws UserFormException
     */
122
    public static function attackDetectedExitNow(array $config = array(), $getParamName = '') {
123
124
125

        if (count($config) == 0) {
            $config = self::readConfig();
126
127
        }

128
129
130
        // In case of an attack: log out the current user.
        Session::destroy();

131
132
133
134
135
136
        // Sleep
        $penalty = (empty($config[SYSTEM_SECURITY_ATTACK_DELAY]) || !is_numeric($config[SYSTEM_SECURITY_ATTACK_DELAY])) ?
            SYSTEM_SECURITY_ATTACK_DELAY_DEFAULT : $config[SYSTEM_SECURITY_ATTACK_DELAY];

        sleep($penalty);

137
        if ($config[SYSTEM_SECURITY_SHOW_MESSAGE] == 'true' || $config[SYSTEM_SECURITY_SHOW_MESSAGE] == 1) {
138

139
            echo "Attack detected - stop process";
140
141
142
143
144
145
146
//            $answer[API_STATUS] = API_ANSWER_STATUS_ERROR;
//            $answer[API_MESSAGE] = 'Attack detected - stop process.';
//            if($getParamName!='') {
//                $answer[API_MESSAGE] .= " Attack parameter: $getParamName";
//            }
//            header("Content-Type: application/json");
//            echo json_encode($answer);
147
148
149
150
151
152
153
        }

        exit;
    }

    /**
     * @param array $config
Carsten  Rose's avatar
Carsten Rose committed
154
     *
155
156
157
     * @return array
     */
    private static function setDefaults(array $config) {
158
159
160
161
        // Defaults: do not worry: parse_ini_file() will replace 'none' and 'off' by ''.

        $default = [

162
            SYSTEM_DB_INIT => 'set names utf8',
163
164
            SYSTEM_DB_INDEX_DATA => DB_INDEX_DEFAULT,
            SYSTEM_DB_INDEX_QFQ => DB_INDEX_DEFAULT,
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202

            SYSTEM_DATE_FORMAT => 'yyyy-mm-dd',
            SYSTEM_SHOW_DEBUG_INFO => SYSTEM_SHOW_DEBUG_INFO_AUTO,
            SYSTEM_SQL_LOG => SYSTEM_SQL_LOG_FILE,
            SYSTEM_SQL_LOG_MODE => 'modify',
            SYSTEM_MAIL_LOG => SYSTEM_MAIL_LOG_FILE,
            F_BS_COLUMNS => '12',
            F_BS_LABEL_COLUMNS => '3',
            F_BS_INPUT_COLUMNS => '6',
            F_BS_NOTE_COLUMNS => '3',

            SYSTEM_WKHTMLTOPDF => '/opt/wkhtmltox/bin/wkhtmltopdf',

            F_CLASS_PILL => 'qfq-color-grey-1',
            F_CLASS_BODY => 'qfq-color-grey-2',

            F_SAVE_BUTTON_TEXT => '',
            F_SAVE_BUTTON_TOOLTIP => 'Save',
            F_SAVE_BUTTON_CLASS => 'btn btn-default navbar-btn',
            F_SAVE_BUTTON_GLYPH_ICON => GLYPH_ICON_CHECK,

            F_CLOSE_BUTTON_TEXT => '',
            F_CLOSE_BUTTON_TOOLTIP => 'Close',
            F_CLOSE_BUTTON_CLASS => 'btn btn-default navbar-btn',
            F_CLOSE_BUTTON_GLYPH_ICON => GLYPH_ICON_CLOSE,

            F_DELETE_BUTTON_TEXT => '',
            F_DELETE_BUTTON_TOOLTIP => 'Delete',
            F_DELETE_BUTTON_CLASS => 'btn btn-default navbar-btn',
            F_DELETE_BUTTON_GLYPH_ICON => GLYPH_ICON_DELETE,

            F_NEW_BUTTON_TEXT => '',
            F_NEW_BUTTON_TOOLTIP => 'New',
            F_NEW_BUTTON_CLASS => 'btn btn-default navbar-btn',
            F_NEW_BUTTON_GLYPH_ICON => GLYPH_ICON_NEW,

            F_BUTTON_ON_CHANGE_CLASS => 'btn-info alert-info',
            SYSTEM_EDIT_FORM_PAGE => 'form',
Carsten  Rose's avatar
Carsten Rose committed
203
            SYSTEM_SECURITY_VARS_HONEYPOT => 'email,username,password',
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
            SYSTEM_SECURITY_ATTACK_DELAY => SYSTEM_SECURITY_ATTACK_DELAY_DEFAULT,
            SYSTEM_SECURITY_SHOW_MESSAGE => '0',
            SYSTEM_SECURITY_GET_MAX_LENGTH => SYSTEM_SECURITY_GET_MAX_LENGTH_DEFAULT,
            SYSTEM_ESCAPE_TYPE_DEFAULT => TOKEN_ESCAPE_MYSQL,
            SYSTEM_GFX_EXTRA_BUTTON_INFO_INLINE => '<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span>',
            SYSTEM_GFX_EXTRA_BUTTON_INFO_BELOW => '<span class="glyphicon glyphicon-info-sign text-info" aria-hidden="true"></span>',
            SYSTEM_EXTRA_BUTTON_INFO_CLASS => '',

            SYSTEM_DB_UPDATE => SYSTEM_DB_UPDATE_AUTO,
            SYSTEM_RECORD_LOCK_TIMEOUT_SECONDS => SYSTEM_RECORD_LOCK_TIMEOUT_SECONDS_DEFAULT,

            DOCUMENTATION_QFQ => DOCUMENTATION_QFQ_URL,
            SYSTEM_ENTER_AS_SUBMIT => 1,

            SYSTEM_CMD_INKSCAPE => 'inkscape',
            SYSTEM_CMD_CONVERT => 'convert',
            SYSTEM_THUMBNAIL_DIR_SECURE => SYSTEM_THUMBNAIL_DIR_SECURE_DEFAULT,
            SYSTEM_THUMBNAIL_DIR_PUBLIC => SYSTEM_THUMBNAIL_DIR_PUBLIC_DEFAULT,

        ];

        return array_merge($default, $config);
226
227
228
229
    }

    /**
     * Rename Elements defined in config.qfq.ini to more appropriate in user interaction.
Carsten  Rose's avatar
Carsten Rose committed
230
231
     * E.g.: in config.qfq.ini everything is in upper case and word space is '_'. In Form.parameter it's lowercase and
     * camel hook.
232
233
     *
     * @param array $config
Carsten  Rose's avatar
Carsten Rose committed
234
     *
235
236
237
238
239
240
     * @return array
     */
    private static function renameConfigElements(array $config) {

        // oldname > newname
        $setting = [
241
            [SYSTEM_FORM_BS_COLUMNS, F_BS_COLUMNS],
242
243
244
245
246
247
248
249
250
251
252
            [SYSTEM_FORM_BS_LABEL_COLUMNS, F_BS_LABEL_COLUMNS],
            [SYSTEM_FORM_BS_INPUT_COLUMNS, F_BS_INPUT_COLUMNS],
            [SYSTEM_FORM_BS_NOTE_COLUMNS, F_BS_NOTE_COLUMNS],
            [SYSTEM_FORM_DATA_PATTERN_ERROR, F_FE_DATA_PATTERN_ERROR],
            [SYSTEM_FORM_DATA_REQUIRED_ERROR, F_FE_DATA_REQUIRED_ERROR],
            [SYSTEM_FORM_DATA_MATCH_ERROR, F_FE_DATA_MATCH_ERROR],
            [SYSTEM_FORM_DATA_ERROR, F_FE_DATA_ERROR],
            [SYSTEM_CSS_CLASS_QFQ_FORM, F_CLASS],
            [SYSTEM_CSS_CLASS_QFQ_FORM_PILL, F_CLASS_PILL],
            [SYSTEM_CSS_CLASS_QFQ_FORM_BODY, F_CLASS_BODY],
            [SYSTEM_FORM_BUTTON_ON_CHANGE_CLASS, F_BUTTON_ON_CHANGE_CLASS],
253
            [SYSTEM_ESCAPE_TYPE_DEFAULT, F_ESCAPE_TYPE_DEFAULT],
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274

            [SYSTEM_SAVE_BUTTON_TEXT, F_SAVE_BUTTON_TEXT],
            [SYSTEM_SAVE_BUTTON_TOOLTIP, F_SAVE_BUTTON_TOOLTIP],
            [SYSTEM_SAVE_BUTTON_CLASS, F_SAVE_BUTTON_CLASS],
            [SYSTEM_SAVE_BUTTON_GLYPH_ICON, F_SAVE_BUTTON_GLYPH_ICON],

            [SYSTEM_CLOSE_BUTTON_TEXT, F_CLOSE_BUTTON_TEXT],
            [SYSTEM_CLOSE_BUTTON_TOOLTIP, F_CLOSE_BUTTON_TOOLTIP],
            [SYSTEM_CLOSE_BUTTON_CLASS, F_CLOSE_BUTTON_CLASS],
            [SYSTEM_CLOSE_BUTTON_GLYPH_ICON, F_CLOSE_BUTTON_GLYPH_ICON],

            [SYSTEM_DELETE_BUTTON_TEXT, F_DELETE_BUTTON_TEXT],
            [SYSTEM_DELETE_BUTTON_TOOLTIP, F_DELETE_BUTTON_TOOLTIP],
            [SYSTEM_DELETE_BUTTON_CLASS, F_DELETE_BUTTON_CLASS],
            [SYSTEM_DELETE_BUTTON_GLYPH_ICON, F_DELETE_BUTTON_GLYPH_ICON],

            [SYSTEM_NEW_BUTTON_TEXT, F_NEW_BUTTON_TEXT],
            [SYSTEM_NEW_BUTTON_TOOLTIP, F_NEW_BUTTON_TOOLTIP],
            [SYSTEM_NEW_BUTTON_CLASS, F_NEW_BUTTON_CLASS],
            [SYSTEM_NEW_BUTTON_GLYPH_ICON, F_NEW_BUTTON_GLYPH_ICON],

275
276
            [SYSTEM_EXTRA_BUTTON_INFO_CLASS, FE_INPUT_EXTRA_BUTTON_INFO_CLASS],

277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
        ];

        foreach ($setting as $row) {
            $oldName = $row[0];
            $newName = $row[1];

            if (isset($config[$oldName])) {
                $config[$newName] = $config[$oldName];
                if ($oldName != $newName) {
                    unset($config[$oldName]);
                }
            }
        }

        return $config;
    }
}