Config.php 9.94 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 $configIni
22
23
     * @return array
     * @throws UserFormException
24
     */
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
    public function readConfig($configIni = '') {
        $configT3qfq = array();

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

        // In case there is a $configIni given: do not try to include T3 LocalConfiguration.php
        if (empty($configIni)) {
            # Read 'LocalConfiguration.php'
            if (isset($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf'][EXT_KEY])) {
                $configT3qfq = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf'][EXT_KEY]);
            } else {
                $all = include_once($pathTypo3Conf . '/' . CONFIG_T3);
                $configT3qfq = unserialize($all['EXT']['extConf'][EXT_KEY]);
                unset($all);
44
            }
45
            $configIni = $pathTypo3Conf . '/' . CONFIG_QFQ;
46
47
48
        }

        try {
49
            $config = parse_ini_file($configIni, false);
50
        } catch (\Exception $e) {
51
            throw new qfq\UserFormException ("Error read file " . $pathTypo3Conf . ": " . $e->getMessage(), ERROR_IO_READ_FILE);
52
        }
53
54
        // Settings in  config.qfq.ini overwrite T3 settings
        $config = array_merge($configT3qfq, $config);
55
56

        $config = self::renameConfigElements($config);
57
        $config = self::setDefaults($config);
58
        self::checkDeprecated($config);
59
60
61
62
63
        self::checkForAttack($config);

        return $config;
    }

64
65
    /**
     * Checks for deprecated options.
66
67
     * @param array $config
     * @throws UserFormException
68
69
70
71
72
73
74
75
76
     */
    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:
77
                        $msg = 'Replaced by: ' . SYSTEM_FILL_STORE_SYSTEM_BY_SQL . '1|2|3';
78
                }
79
                throw new qfq\UserFormException ("Deprecated option in " . CONFIG_QFQ . ": " . SYSTEM_VAR_ADD_BY_SQL . " - " . $msg);
80
81
82
83
84
            }
        }
    }


85
86
87
88
    /**
     * @param array $config
     */
    private static function checkForAttack(array $config) {
89
        $attack = false;
90
        $key = '';
91
92
93
94

        // Iterate over all fake vars
        $arr = explode(',', $config[SYSTEM_SECURITY_VARS_HONEYPOT]);
        foreach ($arr as $key) {
95
96
97
98
            $key = trim($key);
            if ($key === '') {
                continue;
            }
99
            if (!empty($_POST[$key]) || !empty($_GET[$key])) {
100
101
102
103
104
105
106
                $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) {
107
108
109
            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);
110

111
112
                $cnt = count($arr);
                if ($cnt > 1 && is_numeric($arr[$cnt - 1])) {
113
114
115
116
117
118
                    $maxLength = $arr[$cnt - 1];
                } else {
                    $maxLength = $config[SYSTEM_SECURITY_GET_MAX_LENGTH]; // might change again.
                }

                if (strlen($value) > $maxLength) {
119
                    $attack = true;
120
                    break;
121
                }
122
123
124
125
            }
        }

        // Nothing found?
126
        if ($attack === false) {
127
128
129
            return;
        }

130
        self::attackDetectedExitNow($config, $key);
131
132
133
134
135
    }

    /**
     * @throws UserFormException
     */
136
    public static function attackDetectedExitNow(array $config = array(), $getParamName = '') {
137
138
139

        if (count($config) == 0) {
            $config = self::readConfig();
140
141
        }

142
143
144
        // In case of an attack: log out the current user.
        Session::destroy();

145
146
147
148
149
150
        // 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);

151
        if ($config[SYSTEM_SECURITY_SHOW_MESSAGE] == 'true' || $config[SYSTEM_SECURITY_SHOW_MESSAGE] == 1) {
152

153
            echo "Attack detected - stop process";
154
155
156
157
158
159
160
//            $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);
161
162
163
164
165
166
167
        }

        exit;
    }

    /**
     * @param array $config
Carsten  Rose's avatar
Carsten Rose committed
168
     *
169
170
171
     * @return array
     */
    private static function setDefaults(array $config) {
172
173
174
175
        // Defaults: do not worry: parse_ini_file() will replace 'none' and 'off' by ''.

        $default = [

176
            SYSTEM_DB_INIT => 'set names utf8',
177
178
            SYSTEM_DB_INDEX_DATA => DB_INDEX_DEFAULT,
            SYSTEM_DB_INDEX_QFQ => DB_INDEX_DEFAULT,
179
180
181
182
183
184
185
186
187
188
189

            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',

190
            SYSTEM_CMD_WKHTMLTOPDF => '/opt/wkhtmltox/bin/wkhtmltopdf',
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216

            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
217
            SYSTEM_SECURITY_VARS_HONEYPOT => 'email,username,password',
218
219
220
221
            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,
222
223
            SYSTEM_EXTRA_BUTTON_INFO_INLINE => '<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span>',
            SYSTEM_EXTRA_BUTTON_INFO_BELOW => '<span class="glyphicon glyphicon-info-sign text-info" aria-hidden="true"></span>',
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
            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,

        ];

239
240
241
242
        // To let run legacy code
        $config[SYSTEM_DB_INDEX_DATA_DEPRECATED] = $config[SYSTEM_DB_INDEX_DATA];
        $config[SYSTEM_DB_INDEX_QFQ_DEPRECATED] = $config[SYSTEM_DB_INDEX_QFQ];

243
        return array_merge($default, $config);
244
245
246
247
    }

    /**
     * Rename Elements defined in config.qfq.ini to more appropriate in user interaction.
Carsten  Rose's avatar
Carsten Rose committed
248
249
     * E.g.: in config.qfq.ini everything is in upper case and word space is '_'. In Form.parameter it's lowercase and
     * camel hook.
250
251
     *
     * @param array $config
Carsten  Rose's avatar
Carsten Rose committed
252
     *
253
254
255
256
257
258
     * @return array
     */
    private static function renameConfigElements(array $config) {

        // oldname > newname
        $setting = [
259
            [SYSTEM_FORM_BS_COLUMNS, F_BS_COLUMNS],
260
261
262
            [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],
263

264
265
266
267
            [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],
268

269
270
271
            [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],
272
            [SYSTEM_SAVE_BUTTON_CLASS_ON_CHANGE, F_BUTTON_ON_CHANGE_CLASS],
273

274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
        ];

        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;
    }
}