Passed
Pull Request — master (#70)
by Felipe
03:51
created

FulltextController   F

Complexity

Total Complexity 132

Size/Duplication

Total Lines 1312
Duplicated Lines 13.64 %

Importance

Changes 0
Metric Value
dl 179
loc 1312
rs 0.6314
c 0
b 0
f 0
wmc 132

22 Methods

Rating   Name   Duplication   Size   Complexity  
D render() 0 113 26
C doDropMapping() 0 60 10
F doCreateConfig() 27 103 10
B doAlterDict() 0 51 5
C doAddMapping() 0 68 10
B doDefault() 0 81 1
C doSaveCreateDict() 5 43 8
D doDropDict() 1 31 3
A doSaveAddMapping() 13 13 3
F doCreateDict() 13 116 13
A doSaveAlterDict() 0 12 2
B doViewDicts() 0 79 1
B doAlterConfig() 0 57 6
C doSaveCreateConfig() 5 39 8
B doViewParsers() 32 32 1
B doDropConfig() 29 29 3
B doTree() 29 29 1
B doSubTree() 0 47 4
A doSaveAlterConfig() 0 11 2
B doViewConfig() 0 92 1
A doSaveAlterMapping() 13 13 3
C doAlterMapping() 0 77 11

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like FulltextController often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use FulltextController, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace PHPPgAdmin\Controller;
4
5
use PHPPgAdmin\Decorators\Decorator;
6
7
/**
8
 * Base controller class.
9
 */
10
class FulltextController extends BaseController
11
{
12
    public $_name = 'FulltextController';
13
14
    public function render()
15
    {
16
        $conf = $this->conf;
1 ignored issue
show
Unused Code introduced by
The assignment to $conf is dead and can be removed.
Loading history...
17
        $misc = $this->misc;
0 ignored issues
show
Unused Code introduced by
The assignment to $misc is dead and can be removed.
Loading history...
18
        $lang = $this->lang;
19
20
        $action = $this->action;
21
        if ($action == 'tree') {
22
            return $this->doTree();
23
        } elseif ($action == 'subtree') {
24
            return $this->doSubTree($_REQUEST['what']);
25
        }
26
27
        $this->printHeader($lang['strschemas']);
28
        $this->printBody();
29
30
        if (isset($_POST['cancel'])) {
31
            if (isset($_POST['prev_action'])) {
32
                $action = $_POST['prev_action'];
33
            } else {
34
                $action = '';
35
            }
36
        }
37
38
        switch ($action) {
39
            case 'createconfig':
40
                if (isset($_POST['create'])) {
41
                    $this->doSaveCreateConfig();
42
                } else {
43
                    $this->doCreateConfig();
44
                }
45
46
                break;
47
            case 'alterconfig':
48
                if (isset($_POST['alter'])) {
49
                    $this->doSaveAlterConfig();
50
                } else {
51
                    $this->doAlterConfig();
52
                }
53
54
                break;
55
            case 'dropconfig':
56
                if (isset($_POST['drop'])) {
57
                    $this->doDropConfig(false);
58
                } else {
59
                    $this->doDropConfig(true);
60
                }
61
62
                break;
63
            case 'viewconfig':
64
                $this->doViewConfig($_REQUEST['ftscfg']);
65
                break;
66
            case 'viewparsers':
67
                $this->doViewParsers();
68
                break;
69
            case 'viewdicts':
70
                $this->doViewDicts();
71
                break;
72
            case 'createdict':
73
                if (isset($_POST['create'])) {
74
                    $this->doSaveCreateDict();
75
                } else {
76
                    doCreateDict();
0 ignored issues
show
Bug introduced by
The function doCreateDict was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

76
                    /** @scrutinizer ignore-call */ doCreateDict();
Loading history...
77
                }
78
79
                break;
80
            case 'alterdict':
81
                if (isset($_POST['alter'])) {
82
                    $this->doSaveAlterDict();
83
                } else {
84
                    $this->doAlterDict();
85
                }
86
87
                break;
88
            case 'dropdict':
89
                if (isset($_POST['drop'])) {
90
                    $this->doDropDict(false);
91
                } else {
92
                    $this->doDropDict(true);
93
                }
94
95
                break;
96
            case 'dropmapping':
97
                if (isset($_POST['drop'])) {
98
                    $this->doDropMapping(false);
99
                } else {
100
                    $this->doDropMapping(true);
101
                }
102
103
                break;
104
            case 'altermapping':
105
                if (isset($_POST['alter'])) {
106
                    $this->doSaveAlterMapping();
107
                } else {
108
                    $this->doAlterMapping();
109
                }
110
111
                break;
112
            case 'addmapping':
113
                if (isset($_POST['add'])) {
114
                    $this->doSaveAddMapping();
115
                } else {
116
                    $this->doAddMapping();
117
                }
118
119
                break;
120
121
            default:
122
                $this->doDefault();
123
                break;
124
        }
125
126
        return $this->printFooter();
127
    }
128
129
    public function doDefault($msg = '')
130
    {
131
        $conf = $this->conf;
132
        $misc = $this->misc;
133
        $lang = $this->lang;
134
        $data = $misc->getDatabaseAccessor();
135
136
        $this->printTrail('schema');
137
        $this->printTabs('schema', 'fulltext');
138
        $this->printTabs('fulltext', 'ftsconfigs');
139
        $this->printMsg($msg);
140
141
        $cfgs = $data->getFtsConfigurations(false);
142
143
        $columns = [
144
            'configuration' => [
145
                'title' => $lang['strftsconfig'],
146
                'field' => Decorator::field('name'),
147
                'url'   => "fulltext.php?action=viewconfig&amp;{$misc->href}&amp;",
148
                'vars'  => ['ftscfg' => 'name'],
149
            ],
150
            'schema'        => [
151
                'title' => $lang['strschema'],
152
                'field' => Decorator::field('schema'),
153
            ],
154
            'actions'       => [
155
                'title' => $lang['stractions'],
156
            ],
157
            'comment'       => [
158
                'title' => $lang['strcomment'],
159
                'field' => Decorator::field('comment'),
160
            ],
161
        ];
162
163
        $actions = [
164
            'drop'  => [
165
                'content' => $lang['strdrop'],
166
                'attr'    => [
167
                    'href' => [
168
                        'url'     => 'fulltext.php',
169
                        'urlvars' => [
170
                            'action' => 'dropconfig',
171
                            'ftscfg' => Decorator::field('name'),
172
                        ],
173
                    ],
174
                ],
175
            ],
176
            'alter' => [
177
                'content' => $lang['stralter'],
178
                'attr'    => [
179
                    'href' => [
180
                        'url'     => 'fulltext.php',
181
                        'urlvars' => [
182
                            'action' => 'alterconfig',
183
                            'ftscfg' => Decorator::field('name'),
184
                        ],
185
                    ],
186
                ],
187
            ],
188
        ];
189
190
        echo $this->printTable($cfgs, $columns, $actions, 'fulltext-fulltext', $lang['strftsnoconfigs']);
191
192
        $navlinks = [
193
            'createconf' => [
194
                'attr'    => [
195
                    'href' => [
196
                        'url'     => 'fulltext.php',
197
                        'urlvars' => [
198
                            'action'   => 'createconfig',
199
                            'server'   => $_REQUEST['server'],
200
                            'database' => $_REQUEST['database'],
201
                            'schema'   => $_REQUEST['schema'],
202
                        ],
203
                    ],
204
                ],
205
                'content' => $lang['strftscreateconfig'],
206
            ],
207
        ];
208
209
        $this->printNavLinks($navlinks, 'fulltext-fulltext', get_defined_vars());
210
    }
211
212
    /**
213
     * Generate XML for the browser tree.
214
     */
215 View Code Duplication
    public function doTree()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
216
    {
217
        $conf = $this->conf;
0 ignored issues
show
Unused Code introduced by
The assignment to $conf is dead and can be removed.
Loading history...
218
        $misc = $this->misc;
219
        $lang = $this->lang;
0 ignored issues
show
Unused Code introduced by
The assignment to $lang is dead and can be removed.
Loading history...
220
        $data = $misc->getDatabaseAccessor();
0 ignored issues
show
Unused Code introduced by
The assignment to $data is dead and can be removed.
Loading history...
221
222
        $tabs = $misc->getNavTabs('fulltext');
223
        $items = $this->adjustTabsForTree($tabs);
224
225
        $reqvars = $misc->getRequestVars('ftscfg');
226
227
        $attrs = [
228
            'text'   => Decorator::field('title'),
229
            'icon'   => Decorator::field('icon'),
230
            'action' => Decorator::actionurl('fulltext.php',
231
                $reqvars,
232
                field('urlvars')
0 ignored issues
show
Bug introduced by
The function field was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

232
                /** @scrutinizer ignore-call */ field('urlvars')
Loading history...
233
            ),
234
            'branch' => Decorator::url('fulltext.php',
235
                $reqvars,
236
                [
237
                    'action' => 'subtree',
238
                    'what'   => Decorator::field('icon'), // IZ: yeah, it's ugly, but I do not want to change navigation tabs arrays
239
                ]
240
            ),
241
        ];
242
243
        return $this->printTree($items, $attrs, 'fts');
244
    }
245
246
    public function doSubTree($what)
247
    {
248
        $conf = $this->conf;
0 ignored issues
show
Unused Code introduced by
The assignment to $conf is dead and can be removed.
Loading history...
249
        $misc = $this->misc;
250
        $lang = $this->lang;
0 ignored issues
show
Unused Code introduced by
The assignment to $lang is dead and can be removed.
Loading history...
251
        $data = $misc->getDatabaseAccessor();
252
253
        switch ($what) {
254
            case 'FtsCfg':
255
                $items = $data->getFtsConfigurations(false);
256
                $urlvars = ['action' => 'viewconfig', 'ftscfg' => Decorator::field('name')];
257
                break;
258
            case 'FtsDict':
259
                $items = $data->getFtsDictionaries(false);
260
                $urlvars = ['action' => 'viewdicts'];
261
                break;
262
            case 'FtsParser':
263
                $items = $data->getFtsParsers(false);
264
                $urlvars = ['action' => 'viewparsers'];
265
                break;
266
            default:
267
                return;
268
        }
269
270
        $reqvars = $misc->getRequestVars('ftscfg');
271
272
        $attrs = [
273
            'text'    => Decorator::field('name'),
274
            'icon'    => $what,
275
            'toolTip' => Decorator::field('comment'),
276
            'action'  => Decorator::actionurl('fulltext.php',
277
                $reqvars,
278
                $urlvars
279
            ),
280
            'branch'  => Decorator::ifempty(Decorator::field('branch'),
281
                '',
282
                url('fulltext.php',
0 ignored issues
show
Bug introduced by
The function url was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

282
                /** @scrutinizer ignore-call */ url('fulltext.php',
Loading history...
283
                    $reqvars,
284
                    [
285
                        'action' => 'subtree',
286
                        'ftscfg' => Decorator::field('name'),
287
                    ]
288
                )
289
            ),
290
        ];
291
292
        return $this->printTree($items, $attrs, strtolower($what));
293
    }
294
295 View Code Duplication
    public function doDropConfig($confirm)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
296
    {
297
        $conf = $this->conf;
0 ignored issues
show
Unused Code introduced by
The assignment to $conf is dead and can be removed.
Loading history...
298
        $misc = $this->misc;
299
        $lang = $this->lang;
300
        $data = $misc->getDatabaseAccessor();
301
302
        if ($confirm) {
303
            $this->printTrail('ftscfg');
304
            $this->printTitle($lang['strdrop'], 'pg.ftscfg.drop');
305
306
            echo '<p>', sprintf($lang['strconfdropftsconfig'], $misc->printVal($_REQUEST['ftscfg'])), "</p>\n";
307
308
            echo '<form action="'.SUBFOLDER."/src/views/fulltext.php\" method=\"post\">\n";
309
            echo "<p><input type=\"checkbox\" id=\"cascade\" name=\"cascade\" /> <label for=\"cascade\">{$lang['strcascade']}</label></p>\n";
310
            echo "<p><input type=\"hidden\" name=\"action\" value=\"dropconfig\" />\n";
311
            echo '<input type="hidden" name="database" value="', htmlspecialchars($_REQUEST['database']), "\" />\n";
312
            echo '<input type="hidden" name="ftscfg" value="', htmlspecialchars($_REQUEST['ftscfg']), "\" />\n";
313
            echo $misc->form;
314
            echo "<input type=\"submit\" name=\"drop\" value=\"{$lang['strdrop']}\" />\n";
315
            echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" /></p>\n";
316
            echo "</form>\n";
317
        } else {
318
            $status = $data->dropFtsConfiguration($_POST['ftscfg'], isset($_POST['cascade']));
319
            if ($status == 0) {
320
                $this->misc->setReloadBrowser(true);
321
                $this->doDefault($lang['strftsconfigdropped']);
322
            } else {
323
                $this->doDefault($lang['strftsconfigdroppedbad']);
324
            }
325
        }
326
    }
327
328
    public function doDropDict($confirm)
329
    {
330
        $conf = $this->conf;
0 ignored issues
show
Unused Code introduced by
The assignment to $conf is dead and can be removed.
Loading history...
331
        $misc = $this->misc;
332
        $lang = $this->lang;
333
        $data = $misc->getDatabaseAccessor();
334
335
        if ($confirm) {
336
            $this->printTrail('ftscfg'); // TODO: change to smth related to dictionary
337
            $this->printTitle($lang['strdrop'], 'pg.ftsdict.drop');
338
339
            echo '<p>', sprintf($lang['strconfdropftsdict'], $misc->printVal($_REQUEST['ftsdict'])), "</p>\n";
340
341
            echo '<form action="'.SUBFOLDER."/src/views/fulltext.php\" method=\"post\">\n";
342
            echo "<p><input type=\"checkbox\" id=\"cascade\" name=\"cascade\" /> <label for=\"cascade\">{$lang['strcascade']}</label></p>\n";
343
            echo "<p><input type=\"hidden\" name=\"action\" value=\"dropdict\" />\n";
344
            echo '<input type="hidden" name="database" value="', htmlspecialchars($_REQUEST['database']), "\" />\n";
345
            echo '<input type="hidden" name="ftsdict" value="', htmlspecialchars($_REQUEST['ftsdict']), "\" />\n";
346
            //echo "<input type=\"hidden\" name=\"ftscfg\" value=\"", htmlspecialchars($_REQUEST['ftscfg']), "\" />\n";
347
            echo "<input type=\"hidden\" name=\"prev_action\" value=\"viewdicts\" /></p>\n";
348
            echo $misc->form;
349
            echo "<input type=\"submit\" name=\"drop\" value=\"{$lang['strdrop']}\" />\n";
350
            echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" /></p>\n";
351
            echo "</form>\n";
352
        } else {
353
            $status = $data->dropFtsDictionary($_POST['ftsdict'], isset($_POST['cascade']));
354
            if ($status == 0) {
355
                $this->misc->setReloadBrowser(true);
356
                $this->doViewDicts($lang['strftsdictdropped']);
357
            } else {
358
                $this->doViewDicts($lang['strftsdictdroppedbad']);
359
            }
360
        }
361
    }
362
363
    /**
364
     * Displays a screen where one can enter a new FTS configuration.
365
     */
366
    public function doCreateConfig($msg = '')
367
    {
368
        $conf = $this->conf;
0 ignored issues
show
Unused Code introduced by
The assignment to $conf is dead and can be removed.
Loading history...
369
        $misc = $this->misc;
370
        $lang = $this->lang;
371
        $data = $misc->getDatabaseAccessor();
372
373
        $server_info = $misc->getServerInfo();
0 ignored issues
show
Unused Code introduced by
The assignment to $server_info is dead and can be removed.
Loading history...
374
375
        if (!isset($_POST['formName'])) {
376
            $_POST['formName'] = '';
377
        }
378
379
        if (!isset($_POST['formParser'])) {
380
            $_POST['formParser'] = '';
381
        }
382
383
        if (!isset($_POST['formTemplate'])) {
384
            $_POST['formTemplate'] = '';
385
        }
386
387
        if (!isset($_POST['formWithMap'])) {
388
            $_POST['formWithMap'] = '';
389
        }
390
391
        if (!isset($_POST['formComment'])) {
392
            $_POST['formComment'] = '';
393
        }
394
395
        // Fetch all FTS configurations from the database
396
        $ftscfgs = $data->getFtsConfigurations();
397
        // Fetch all FTS parsers from the database
398
        $ftsparsers = $data->getFtsParsers();
399
400
        $this->printTrail('schema');
401
        $this->printTitle($lang['strftscreateconfig'], 'pg.ftscfg.create');
402
        $this->printMsg($msg);
403
404
        echo '<form action="'.SUBFOLDER."/src/views/fulltext.php\" method=\"post\">\n";
405
        echo "<table>\n";
406
        /* conf name */
407
        echo "\t<tr>\n\t\t<th class=\"data left required\">{$lang['strname']}</th>\n";
408
        echo "\t\t<td class=\"data1\"><input name=\"formName\" size=\"32\" maxlength=\"{$data->_maxNameLen}\" value=\"",
409
        htmlspecialchars($_POST['formName']), "\" /></td>\n\t</tr>\n";
410
411
        // Template
412
        echo "\t<tr>\n\t\t<th class=\"data left\">{$lang['strftstemplate']}</th>\n";
413
        echo "\t\t<td class=\"data1\">";
414
415
        $tpls = [];
416
        $tplsel = '';
417 View Code Duplication
        while (!$ftscfgs->EOF) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
418
            $data->fieldClean($ftscfgs->fields['schema']);
419
            $data->fieldClean($ftscfgs->fields['name']);
420
            $tplname = $ftscfgs->fields['schema'].'.'.$ftscfgs->fields['name'];
421
            $tpls[$tplname] = serialize([
422
                'name'   => $ftscfgs->fields['name'],
423
                'schema' => $ftscfgs->fields['schema'],
424
            ]);
425
            if ($_POST['formTemplate'] == $tpls[$tplname]) {
426
                $tplsel = htmlspecialchars($tpls[$tplname]);
427
            }
428
            $ftscfgs->moveNext();
429
        }
430
        echo \PHPPgAdmin\XHtml\HTMLController::printCombo($tpls, 'formTemplate', true, $tplsel, false);
431
        echo "\n\t\t</td>\n\t</tr>\n";
432
433
        // Parser
434
        echo "\t<tr>\n\t\t<th class=\"data left\">{$lang['strftsparser']}</th>\n";
435
        echo "\t\t<td class=\"data1\">\n";
436
        $ftsparsers_ = [];
437
        $ftsparsel = '';
438 View Code Duplication
        while (!$ftsparsers->EOF) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
439
            $data->fieldClean($ftsparsers->fields['schema']);
440
            $data->fieldClean($ftsparsers->fields['name']);
441
            $parsername = $ftsparsers->fields['schema'].'.'.$ftsparsers->fields['name'];
442
443
            $ftsparsers_[$parsername] = serialize([
444
                'parser' => $ftsparsers->fields['name'],
445
                'schema' => $ftsparsers->fields['schema'],
446
            ]);
447
            if ($_POST['formParser'] == $ftsparsers_[$parsername]) {
448
                $ftsparsel = htmlspecialchars($ftsparsers_[$parsername]);
449
            }
450
            $ftsparsers->moveNext();
451
        }
452
        echo \PHPPgAdmin\XHtml\HTMLController::printCombo($ftsparsers_, 'formParser', true, $ftsparsel, false);
453
        echo "\n\t\t</td>\n\t</tr>\n";
454
455
        // Comment
456
        echo "\t<tr>\n\t\t<th class=\"data left\">{$lang['strcomment']}</th>\n";
457
        echo "\t\t<td class=\"data1\"><textarea name=\"formComment\" rows=\"3\" cols=\"32\">",
458
        htmlspecialchars($_POST['formComment']), "</textarea></td>\n\t</tr>\n";
459
460
        echo "</table>\n";
461
        echo "<p>\n";
462
        echo "<input type=\"hidden\" name=\"action\" value=\"createconfig\" />\n";
463
        echo '<input type="hidden" name="database" value="', htmlspecialchars($_REQUEST['database']), "\" />\n";
464
        echo $misc->form;
465
        echo "<input type=\"submit\" name=\"create\" value=\"{$lang['strcreate']}\" />\n";
466
        echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" />\n";
467
        echo "</p>\n";
468
        echo "</form>\n";
469
    }
470
471
    /**
472
     * Actually creates the new FTS configuration in the database.
473
     */
474
    public function doSaveCreateConfig()
475
    {
476
        $conf = $this->conf;
0 ignored issues
show
Unused Code introduced by
The assignment to $conf is dead and can be removed.
Loading history...
477
        $misc = $this->misc;
478
        $lang = $this->lang;
479
        $data = $misc->getDatabaseAccessor();
480
481
        $err = '';
482
        // Check that they've given a name
483
        if ($_POST['formName'] == '') {
484
            $err .= "{$lang['strftsconfigneedsname']}<br />";
485
        }
486
487
        if (($_POST['formParser'] != '') && ($_POST['formTemplate'] != '')) {
488
            $err .= "{$lang['strftscantparsercopy']}<br />";
489
        }
490
491
        if ($err != '') {
492
            return doCreateConfig($err);
0 ignored issues
show
Bug introduced by
The function doCreateConfig was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

492
            return /** @scrutinizer ignore-call */ doCreateConfig($err);
Loading history...
493
        }
494
495
        if ($_POST['formParser'] != '') {
496
            $formParser = unserialize($_POST['formParser']);
497
        } else {
498
            $formParser = '';
499
        }
500
501 View Code Duplication
        if ($_POST['formTemplate'] != '') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
502
            $formTemplate = unserialize($_POST['formTemplate']);
503
        } else {
504
            $formTemplate = '';
505
        }
506
507
        $status = $data->createFtsConfiguration($_POST['formName'], $formParser, $formTemplate, $_POST['formComment']);
508
        if ($status == 0) {
509
            $this->misc->setReloadBrowser(true);
510
            $this->doDefault($lang['strftsconfigcreated']);
511
        } else {
512
            $this->doCreateConfig($lang['strftsconfigcreatedbad']);
513
        }
514
    }
515
516
    /**
517
     * Display a form to permit editing FTS configuration properies.
518
     */
519
    public function doAlterConfig($msg = '')
520
    {
521
        $conf = $this->conf;
0 ignored issues
show
Unused Code introduced by
The assignment to $conf is dead and can be removed.
Loading history...
522
        $misc = $this->misc;
523
        $lang = $this->lang;
524
        $data = $misc->getDatabaseAccessor();
525
526
        $this->printTrail('ftscfg');
527
        $this->printTitle($lang['stralter'], 'pg.ftscfg.alter');
528
        $this->printMsg($msg);
529
530
        $ftscfg = $data->getFtsConfigurationByName($_REQUEST['ftscfg']);
531
        if ($ftscfg->recordCount() > 0) {
532
            if (!isset($_POST['formComment'])) {
533
                $_POST['formComment'] = $ftscfg->fields['comment'];
534
            }
535
536
            if (!isset($_POST['ftscfg'])) {
537
                $_POST['ftscfg'] = $_REQUEST['ftscfg'];
538
            }
539
540
            if (!isset($_POST['formName'])) {
541
                $_POST['formName'] = $_REQUEST['ftscfg'];
542
            }
543
544
            if (!isset($_POST['formParser'])) {
545
                $_POST['formParser'] = '';
546
            }
547
548
            // Fetch all FTS parsers from the database
549
            $ftsparsers = $data->getFtsParsers();
1 ignored issue
show
Unused Code introduced by
The assignment to $ftsparsers is dead and can be removed.
Loading history...
550
551
            echo '<form action="'.SUBFOLDER."/src/views/fulltext.php\" method=\"post\">\n";
552
            echo "<table>\n";
553
554
            echo "\t<tr>\n";
555
            echo "\t\t<th class=\"data left required\">{$lang['strname']}</th>\n";
556
            echo "\t\t<td class=\"data1\">";
557
            echo "\t\t\t<input name=\"formName\" size=\"32\" maxlength=\"{$data->_maxNameLen}\" value=\"",
558
            htmlspecialchars($_POST['formName']), "\" />\n";
559
            echo "\t\t</td>\n";
560
            echo "\t</tr>\n";
561
562
            // Comment
563
            echo "\t<tr>\n";
564
            echo "\t\t<th class=\"data\">{$lang['strcomment']}</th>\n";
565
            echo "\t\t<td class=\"data1\"><textarea cols=\"32\" rows=\"3\"name=\"formComment\">", htmlspecialchars($_POST['formComment']), "</textarea></td>\n";
566
            echo "\t</tr>\n";
567
            echo "</table>\n";
568
            echo "<p><input type=\"hidden\" name=\"action\" value=\"alterconfig\" />\n";
569
            echo '<input type="hidden" name="ftscfg" value="', htmlspecialchars($_POST['ftscfg']), "\" />\n";
570
            echo $misc->form;
571
            echo "<input type=\"submit\" name=\"alter\" value=\"{$lang['stralter']}\" />\n";
572
            echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" /></p>\n";
573
            echo "</form>\n";
574
        } else {
575
            echo "<p>{$lang['strnodata']}</p>\n";
576
        }
577
    }
578
579
    /**
580
     * Save the form submission containing changes to a FTS configuration.
581
     */
582
    public function doSaveAlterConfig()
583
    {
584
        $conf = $this->conf;
0 ignored issues
show
Unused Code introduced by
The assignment to $conf is dead and can be removed.
Loading history...
585
        $misc = $this->misc;
586
        $lang = $this->lang;
587
        $data = $misc->getDatabaseAccessor();
588
        $status = $data->updateFtsConfiguration($_POST['ftscfg'], $_POST['formComment'], $_POST['formName']);
589
        if ($status == 0) {
590
            $this->doDefault($lang['strftsconfigaltered']);
591
        } else {
592
            $this->doAlterConfig($lang['strftsconfigalteredbad']);
593
        }
594
    }
595
596
    /**
597
     * View list of FTS parsers.
598
     */
599 View Code Duplication
    public function doViewParsers($msg = '')
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
600
    {
601
        $conf = $this->conf;
0 ignored issues
show
Unused Code introduced by
The assignment to $conf is dead and can be removed.
Loading history...
602
        $misc = $this->misc;
603
        $lang = $this->lang;
604
        $data = $misc->getDatabaseAccessor();
605
606
        $this->printTrail('schema');
607
        $this->printTabs('schema', 'fulltext');
608
        $this->printTabs('fulltext', 'ftsparsers');
609
        $this->printMsg($msg);
610
611
        $parsers = $data->getFtsParsers(false);
612
613
        $columns = [
614
            'schema'  => [
615
                'title' => $lang['strschema'],
616
                'field' => Decorator::field('schema'),
617
            ],
618
            'name'    => [
619
                'title' => $lang['strname'],
620
                'field' => Decorator::field('name'),
621
            ],
622
            'comment' => [
623
                'title' => $lang['strcomment'],
624
                'field' => Decorator::field('comment'),
625
            ],
626
        ];
627
628
        $actions = [];
629
630
        echo $this->printTable($parsers, $columns, $actions, 'fulltext-viewparsers', $lang['strftsnoparsers']);
631
632
        //TODO: navlink to "create parser"
633
    }
634
635
    /**
636
     * View list of FTS dictionaries.
637
     */
638
    public function doViewDicts($msg = '')
639
    {
640
        $conf = $this->conf;
641
        $misc = $this->misc;
642
        $lang = $this->lang;
643
        $data = $misc->getDatabaseAccessor();
644
645
        $this->printTrail('schema');
646
        $this->printTabs('schema', 'fulltext');
647
        $this->printTabs('fulltext', 'ftsdicts');
648
        $this->printMsg($msg);
649
650
        $dicts = $data->getFtsDictionaries(false);
651
652
        $columns = [
653
            'schema'  => [
654
                'title' => $lang['strschema'],
655
                'field' => Decorator::field('schema'),
656
            ],
657
            'name'    => [
658
                'title' => $lang['strname'],
659
                'field' => Decorator::field('name'),
660
            ],
661
            'actions' => [
662
                'title' => $lang['stractions'],
663
            ],
664
            'comment' => [
665
                'title' => $lang['strcomment'],
666
                'field' => Decorator::field('comment'),
667
            ],
668
        ];
669
670
        $actions = [
671
            'drop'  => [
672
                'content' => $lang['strdrop'],
673
                'attr'    => [
674
                    'href' => [
675
                        'url'     => 'fulltext.php',
676
                        'urlvars' => [
677
                            'action'  => 'dropdict',
678
                            'ftsdict' => Decorator::field('name'),
679
                        ],
680
                    ],
681
                ],
682
            ],
683
            'alter' => [
684
                'content' => $lang['stralter'],
685
                'attr'    => [
686
                    'href' => [
687
                        'url'     => 'fulltext.php',
688
                        'urlvars' => [
689
                            'action'  => 'alterdict',
690
                            'ftsdict' => Decorator::field('name'),
691
                        ],
692
                    ],
693
                ],
694
            ],
695
        ];
696
697
        echo $this->printTable($dicts, $columns, $actions, 'fulltext-viewdicts', $lang['strftsnodicts']);
698
699
        $navlinks = [
700
            'createdict' => [
701
                'attr'    => [
702
                    'href' => [
703
                        'url'     => 'fulltext.php',
704
                        'urlvars' => [
705
                            'action'   => 'createdict',
706
                            'server'   => $_REQUEST['server'],
707
                            'database' => $_REQUEST['database'],
708
                            'schema'   => $_REQUEST['schema'],
709
                        ],
710
                    ],
711
                ],
712
                'content' => $lang['strftscreatedict'],
713
            ],
714
        ];
715
716
        $this->printNavLinks($navlinks, 'fulltext-viewdicts', get_defined_vars());
717
    }
718
719
    /**
720
     * View details of FTS configuration given.
721
     */
722
    public function doViewConfig($ftscfg, $msg = '')
723
    {
724
        $conf = $this->conf;
725
        $misc = $this->misc;
726
        $lang = $this->lang;
727
        $data = $misc->getDatabaseAccessor();
728
729
        $this->printTrail('ftscfg');
730
        $this->printTabs('schema', 'fulltext');
731
        $this->printTabs('fulltext', 'ftsconfigs');
732
        $this->printMsg($msg);
733
734
        echo "<h3>{$lang['strftsconfigmap']}</h3>\n";
735
736
        $map = $data->getFtsConfigurationMap($ftscfg);
737
738
        $columns = [
739
            'name'         => [
740
                'title' => $lang['strftsmapping'],
741
                'field' => Decorator::field('name'),
742
            ],
743
            'dictionaries' => [
744
                'title' => $lang['strftsdicts'],
745
                'field' => Decorator::field('dictionaries'),
746
            ],
747
            'actions'      => [
748
                'title' => $lang['stractions'],
749
            ],
750
            'comment'      => [
751
                'title' => $lang['strcomment'],
752
                'field' => Decorator::field('description'),
753
            ],
754
        ];
755
756
        $actions = [
757
            'drop'         => [
758
                'multiaction' => 'dropmapping',
759
                'content'     => $lang['strdrop'],
760
                'attr'        => [
761
                    'href' => [
762
                        'url'     => 'fulltext.php',
763
                        'urlvars' => [
764
                            'action'  => 'dropmapping',
765
                            'mapping' => Decorator::field('name'),
766
                            'ftscfg'  => Decorator::field('cfgname'),
767
                        ],
768
                    ],
769
                ],
770
            ],
771
            'alter'        => [
772
                'content' => $lang['stralter'],
773
                'attr'    => [
774
                    'href' => [
775
                        'url'     => 'fulltext.php',
776
                        'urlvars' => [
777
                            'action'  => 'altermapping',
778
                            'mapping' => Decorator::field('name'),
779
                            'ftscfg'  => Decorator::field('cfgname'),
780
                        ],
781
                    ],
782
                ],
783
            ],
784
            'multiactions' => [
785
                'keycols' => ['mapping' => 'name'],
786
                'url'     => 'fulltext.php',
787
                'default' => null,
788
                'vars'    => ['ftscfg' => $ftscfg],
789
            ],
790
791
        ];
792
793
        echo $this->printTable($map, $columns, $actions, 'fulltext-viewconfig', $lang['strftsemptymap']);
794
795
        $navlinks = [
796
            'addmapping' => [
797
                'attr'    => [
798
                    'href' => [
799
                        'url'     => 'fulltext.php',
800
                        'urlvars' => [
801
                            'action'   => 'addmapping',
802
                            'server'   => $_REQUEST['server'],
803
                            'database' => $_REQUEST['database'],
804
                            'schema'   => $_REQUEST['schema'],
805
                            'ftscfg'   => $ftscfg,
806
                        ],
807
                    ],
808
                ],
809
                'content' => $lang['strftsaddmapping'],
810
            ],
811
        ];
812
813
        $this->printNavLinks($navlinks, 'fulltext-viewconfig', get_defined_vars());
814
    }
815
816
    /**
817
     * Displays a screen where one can enter a details of a new FTS dictionary.
818
     */
819
    public function doCreateDict($msg = '')
820
    {
821
        $conf = $this->conf;
0 ignored issues
show
Unused Code introduced by
The assignment to $conf is dead and can be removed.
Loading history...
822
        $misc = $this->misc;
823
        $lang = $this->lang;
824
        $data = $misc->getDatabaseAccessor();
825
826
        $server_info = $misc->getServerInfo();
0 ignored issues
show
Unused Code introduced by
The assignment to $server_info is dead and can be removed.
Loading history...
827
828
        if (!isset($_POST['formName'])) {
829
            $_POST['formName'] = '';
830
        }
831
832
        if (!isset($_POST['formIsTemplate'])) {
833
            $_POST['formIsTemplate'] = false;
834
        }
835
836
        if (!isset($_POST['formTemplate'])) {
837
            $_POST['formTemplate'] = '';
838
        }
839
840
        if (!isset($_POST['formLexize'])) {
841
            $_POST['formLexize'] = '';
842
        }
843
844
        if (!isset($_POST['formInit'])) {
845
            $_POST['formInit'] = '';
846
        }
847
848
        if (!isset($_POST['formOption'])) {
849
            $_POST['formOption'] = '';
850
        }
851
852
        if (!isset($_POST['formComment'])) {
853
            $_POST['formComment'] = '';
854
        }
855
856
        // Fetch all FTS dictionaries from the database
857
        $ftstpls = $data->getFtsDictionaryTemplates();
858
859
        $this->printTrail('schema');
860
        // TODO: create doc links
861
        $this->printTitle($lang['strftscreatedict'], 'pg.ftsdict.create');
862
        $this->printMsg($msg);
863
864
        echo '<form action="'.SUBFOLDER."/src/views/fulltext.php\" method=\"post\">\n";
865
        echo "<table>\n";
866
        echo "\t<tr>\n\t\t<th class=\"data left required\">{$lang['strname']}</th>\n";
867
        echo "\t\t<td class=\"data1\"><input name=\"formName\" size=\"32\" maxlength=\"{$data->_maxNameLen}\" value=\"",
868
        htmlspecialchars($_POST['formName']), '" />&nbsp;',
869
        '<input type="checkbox" name="formIsTemplate" id="formIsTemplate"', $_POST['formIsTemplate'] ? ' checked="checked" ' : '', " />\n",
870
            "<label for=\"formIsTemplate\">{$lang['strftscreatedicttemplate']}</label></td>\n\t</tr>\n";
871
872
        // Template
873
        echo "\t<tr>\n\t\t<th class=\"data left\">{$lang['strftstemplate']}</th>\n";
874
        echo "\t\t<td class=\"data1\">";
875
        $tpls = [];
876
        $tplsel = '';
877 View Code Duplication
        while (!$ftstpls->EOF) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
878
            $data->fieldClean($ftstpls->fields['schema']);
879
            $data->fieldClean($ftstpls->fields['name']);
880
            $tplname = $ftstpls->fields['schema'].'.'.$ftstpls->fields['name'];
881
            $tpls[$tplname] = serialize([
882
                'name'   => $ftstpls->fields['name'],
883
                'schema' => $ftstpls->fields['schema'],
884
            ]);
885
            if ($_POST['formTemplate'] == $tpls[$tplname]) {
886
                $tplsel = htmlspecialchars($tpls[$tplname]);
887
            }
888
            $ftstpls->moveNext();
889
        }
890
        echo \PHPPgAdmin\XHtml\HTMLController::printCombo($tpls, 'formTemplate', true, $tplsel, false);
891
        echo "\n\t\t</td>\n\t</tr>\n";
892
893
        // TODO: what about maxlengths?
894
        // Lexize
895
        echo "\t<tr>\n\t\t<th class=\"data left\">{$lang['strftslexize']}</th>\n";
896
        echo "\t\t<td class=\"data1\"><input name=\"formLexize\" size=\"32\" maxlength=\"1000\" value=\"",
897
        htmlspecialchars($_POST['formLexize']), '" ', isset($_POST['formIsTemplate']) ? '' : ' disabled="disabled" ',
898
            "/></td>\n\t</tr>\n";
899
900
        // Init
901
        echo "\t<tr>\n\t\t<th class=\"data left\">{$lang['strftsinit']}</th>\n";
902
        echo "\t\t<td class=\"data1\"><input name=\"formInit\" size=\"32\" maxlength=\"1000\" value=\"",
903
        htmlspecialchars($_POST['formInit']), '"', @$_POST['formIsTemplate'] ? '' : ' disabled="disabled" ',
904
            "/></td>\n\t</tr>\n";
905
906
        // Option
907
        echo "\t<tr>\n\t\t<th class=\"data left\">{$lang['strftsoptionsvalues']}</th>\n";
908
        echo "\t\t<td class=\"data1\"><input name=\"formOption\" size=\"32\" maxlength=\"1000\" value=\"",
909
        htmlspecialchars($_POST['formOption']), "\" /></td>\n\t</tr>\n";
910
911
        // Comment
912
        echo "\t<tr>\n\t\t<th class=\"data left\">{$lang['strcomment']}</th>\n";
913
        echo "\t\t<td class=\"data1\"><textarea name=\"formComment\" rows=\"3\" cols=\"32\">",
914
        htmlspecialchars($_POST['formComment']), "</textarea></td>\n\t</tr>\n";
915
916
        echo "</table>\n";
917
        echo "<p>\n";
918
        echo "<input type=\"hidden\" name=\"action\" value=\"createdict\" />\n";
919
        echo '<input type="hidden" name="database" value="', htmlspecialchars($_REQUEST['database']), "\" />\n";
920
        echo $misc->form;
921
        echo "<input type=\"submit\" name=\"create\" value=\"{$lang['strcreate']}\" />\n";
922
        echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" />\n";
923
        echo "</p>\n";
924
        echo "</form>\n",
925
            "<script type=\"text/javascript\">
926
				function templateOpts() {
927
					isTpl = document.getElementsByName('formIsTemplate')[0].checked;
928
					$this->document.getElementsByName('formTemplate')[0].disabled = isTpl;
0 ignored issues
show
Bug Best Practice introduced by
The property document does not exist on PHPPgAdmin\Controller\FulltextController. Did you maybe forget to declare it?
Loading history...
929
					$this->document.getElementsByName('formOption')[0].disabled = isTpl;
930
					$this->document.getElementsByName('formLexize')[0].disabled = !isTpl;
931
					$this->document.getElementsByName('formInit')[0].disabled = !isTpl;
932
				}
933
934
				$this->document.getElementsByName('formIsTemplate')[0].onchange = templateOpts;
935
936
				templateOpts();
937
			</script>\n";
938
    }
939
940
    /**
941
     * Actually creates the new FTS dictionary in the database.
942
     */
943
    public function doSaveCreateDict()
944
    {
945
        $conf = $this->conf;
0 ignored issues
show
Unused Code introduced by
The assignment to $conf is dead and can be removed.
Loading history...
946
        $misc = $this->misc;
947
        $lang = $this->lang;
948
        $data = $misc->getDatabaseAccessor();
949
950
        // Check that they've given a name
951
        if ($_POST['formName'] == '') {
952
            $this->doCreateDict($lang['strftsdictneedsname']);
953
        } else {
954
            if (!isset($_POST['formIsTemplate'])) {
955
                $_POST['formIsTemplate'] = false;
956
            }
957
958 View Code Duplication
            if (isset($_POST['formTemplate'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
959
                $formTemplate = unserialize($_POST['formTemplate']);
0 ignored issues
show
Security introduced by
$_POST['formTemplate'] can contain request data and is used in unserialized context(s) leading to a potential security vulnerability.

1 path for user data to reach this point

  1. Read from $_POST
    in src/controllers/FulltextController.php on line 959

Preventing Object Injection Attacks

If you pass raw user-data to unserialize() for example, this can be used to create an object of any class that is available in your local filesystem. For an attacker, classes that have magic methods like __destruct or __wakeup are particularly interesting in such a case, as they can be exploited very easily.

We recommend to not pass user data to such a function. In case of unserialize, better use JSON to transfer data.

General Strategies to prevent injection

In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:

if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
    throw new \InvalidArgumentException('This input is not allowed.');
}

For numeric data, we recommend to explicitly cast the data:

$sanitized = (integer) $tainted;
Loading history...
960
            } else {
961
                $formTemplate = '';
962
            }
963
964
            if (!isset($_POST['formLexize'])) {
965
                $_POST['formLexize'] = '';
966
            }
967
968
            if (!isset($_POST['formInit'])) {
969
                $_POST['formInit'] = '';
970
            }
971
972
            if (!isset($_POST['formOption'])) {
973
                $_POST['formOption'] = '';
974
            }
975
976
            $status = $data->createFtsDictionary($_POST['formName'], $_POST['formIsTemplate'],
977
                $formTemplate, $_POST['formLexize'],
978
                $_POST['formInit'], $_POST['formOption'], $_POST['formComment']
979
            );
980
981
            if ($status == 0) {
982
                $this->misc->setReloadBrowser(true);
983
                $this->doViewDicts($lang['strftsdictcreated']);
984
            } else {
985
                $this->doCreateDict($lang['strftsdictcreatedbad']);
986
            }
987
        }
988
    }
989
990
    /**
991
     * Display a form to permit editing FTS dictionary properies.
992
     */
993
    public function doAlterDict($msg = '')
994
    {
995
        $conf = $this->conf;
0 ignored issues
show
Unused Code introduced by
The assignment to $conf is dead and can be removed.
Loading history...
996
        $misc = $this->misc;
997
        $lang = $this->lang;
998
        $data = $misc->getDatabaseAccessor();
999
1000
        $this->printTrail('ftscfg'); // TODO: change to smth related to dictionary
1001
        $this->printTitle($lang['stralter'], 'pg.ftsdict.alter');
1002
        $this->printMsg($msg);
1003
1004
        $ftsdict = $data->getFtsDictionaryByName($_REQUEST['ftsdict']);
1005
        if ($ftsdict->recordCount() > 0) {
1006
            if (!isset($_POST['formComment'])) {
1007
                $_POST['formComment'] = $ftsdict->fields['comment'];
1008
            }
1009
1010
            if (!isset($_POST['ftsdict'])) {
1011
                $_POST['ftsdict'] = $_REQUEST['ftsdict'];
1012
            }
1013
1014
            if (!isset($_POST['formName'])) {
1015
                $_POST['formName'] = $_REQUEST['ftsdict'];
1016
            }
1017
1018
            echo '<form action="'.SUBFOLDER."/src/views/fulltext.php\" method=\"post\">\n";
1019
            echo "<table>\n";
1020
1021
            echo "\t<tr>\n";
1022
            echo "\t\t<th class=\"data left required\">{$lang['strname']}</th>\n";
1023
            echo "\t\t<td class=\"data1\">";
1024
            echo "\t\t\t<input name=\"formName\" size=\"32\" maxlength=\"{$data->_maxNameLen}\" value=\"",
1025
            htmlspecialchars($_POST['formName']), "\" />\n";
1026
            echo "\t\t</td>\n";
1027
            echo "\t</tr>\n";
1028
1029
            // Comment
1030
            echo "\t<tr>\n";
1031
            echo "\t\t<th class=\"data\">{$lang['strcomment']}</th>\n";
1032
            echo "\t\t<td class=\"data1\"><textarea cols=\"32\" rows=\"3\"name=\"formComment\">", htmlspecialchars($_POST['formComment']), "</textarea></td>\n";
1033
            echo "\t</tr>\n";
1034
            echo "</table>\n";
1035
            echo "<p><input type=\"hidden\" name=\"action\" value=\"alterdict\" />\n";
1036
            echo '<input type="hidden" name="ftsdict" value="', htmlspecialchars($_POST['ftsdict']), "\" />\n";
1037
            echo "<input type=\"hidden\" name=\"prev_action\" value=\"viewdicts\" /></p>\n";
1038
            echo $misc->form;
1039
            echo "<input type=\"submit\" name=\"alter\" value=\"{$lang['stralter']}\" />\n";
1040
            echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" /></p>\n";
1041
            echo "</form>\n";
1042
        } else {
1043
            echo "<p>{$lang['strnodata']}</p>\n";
1044
        }
1045
    }
1046
1047
    /**
1048
     * Save the form submission containing changes to a FTS dictionary.
1049
     */
1050
    public function doSaveAlterDict()
1051
    {
1052
        $conf = $this->conf;
0 ignored issues
show
Unused Code introduced by
The assignment to $conf is dead and can be removed.
Loading history...
1053
        $misc = $this->misc;
1054
        $lang = $this->lang;
1055
        $data = $misc->getDatabaseAccessor();
1056
1057
        $status = $data->updateFtsDictionary($_POST['ftsdict'], $_POST['formComment'], $_POST['formName']);
1058
        if ($status == 0) {
1059
            $this->doViewDicts($lang['strftsdictaltered']);
1060
        } else {
1061
            $this->doAlterDict($lang['strftsdictalteredbad']);
1062
        }
1063
    }
1064
1065
    /**
1066
     * Show confirmation of drop and perform actual drop of FTS mapping.
1067
     */
1068
    public function doDropMapping($confirm)
1069
    {
1070
        $conf = $this->conf;
0 ignored issues
show
Unused Code introduced by
The assignment to $conf is dead and can be removed.
Loading history...
1071
        $misc = $this->misc;
1072
        $lang = $this->lang;
1073
        $data = $misc->getDatabaseAccessor();
1074
1075
        if (empty($_REQUEST['mapping']) && empty($_REQUEST['ma'])) {
1076
            $this->doDefault($lang['strftsspecifymappingtodrop']);
1077
1078
            return;
1079
        }
1080
1081
        if (empty($_REQUEST['ftscfg'])) {
1082
            $this->doDefault($lang['strftsspecifyconfigtoalter']);
1083
1084
            return;
1085
        }
1086
1087
        if ($confirm) {
1088
            $this->printTrail('ftscfg'); // TODO: proper breadcrumbs
1089
            $this->printTitle($lang['strdrop'], 'pg.ftscfg.alter');
1090
1091
            echo '<form action="'.SUBFOLDER."/src/views/fulltext.php\" method=\"post\">\n";
1092
1093
            // Case of multiaction drop
1094
            if (isset($_REQUEST['ma'])) {
1095
                foreach ($_REQUEST['ma'] as $v) {
1096
                    $a = unserialize(htmlspecialchars_decode($v, ENT_QUOTES));
0 ignored issues
show
Security introduced by
htmlspecialchars_decode(...\Controller\ENT_QUOTES) can contain request data and is used in unserialized context(s) leading to a potential security vulnerability.

1 path for user data to reach this point

  1. Read from $_REQUEST, and $_REQUEST['ma'] is assigned to $v
    in src/controllers/FulltextController.php on line 1095
  2. Data is passed through htmlspecialchars_decode()
    in src/controllers/FulltextController.php on line 1096

Preventing Object Injection Attacks

If you pass raw user-data to unserialize() for example, this can be used to create an object of any class that is available in your local filesystem. For an attacker, classes that have magic methods like __destruct or __wakeup are particularly interesting in such a case, as they can be exploited very easily.

We recommend to not pass user data to such a function. In case of unserialize, better use JSON to transfer data.

General Strategies to prevent injection

In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:

if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
    throw new \InvalidArgumentException('This input is not allowed.');
}

For numeric data, we recommend to explicitly cast the data:

$sanitized = (integer) $tainted;
Loading history...
1097
                    echo '<p>', sprintf($lang['strconfdropftsmapping'], $misc->printVal($a['mapping']), $misc->printVal($_REQUEST['ftscfg'])), "</p>\n";
1098
                    printf('<input type="hidden" name="mapping[]" value="%s" />', htmlspecialchars($a['mapping']));
1099
                }
1100
            } else {
1101
                echo '<p>', sprintf($lang['strconfdropftsmapping'], $misc->printVal($_REQUEST['mapping']), $misc->printVal($_REQUEST['ftscfg'])), "</p>\n";
1102
                echo '<input type="hidden" name="mapping" value="', htmlspecialchars($_REQUEST['mapping']), "\" />\n";
1103
            }
1104
1105
            echo "<input type=\"hidden\" name=\"ftscfg\" value=\"{$_REQUEST['ftscfg']}\" />\n";
1106
            echo "<input type=\"hidden\" name=\"action\" value=\"dropmapping\" />\n";
1107
            echo "<input type=\"hidden\" name=\"prev_action\" value=\"viewconfig\" /></p>\n";
1108
            echo $misc->form;
1109
            echo "<input type=\"submit\" name=\"drop\" value=\"{$lang['strdrop']}\" />\n";
1110
            echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" />\n";
1111
            echo "</form>\n";
1112
        } else {
1113
            // Case of multiaction drop
1114
            if (is_array($_REQUEST['mapping'])) {
1115
                $status = $data->changeFtsMapping($_REQUEST['ftscfg'], $_REQUEST['mapping'], 'drop');
1116
                if ($status != 0) {
1117
                    $this->doViewConfig($_REQUEST['ftscfg'], $lang['strftsmappingdroppedbad']);
1118
1119
                    return;
1120
                }
1121
                $this->doViewConfig($_REQUEST['ftscfg'], $lang['strftsmappingdropped']);
1122
            } else {
1123
                $status = $data->changeFtsMapping($_REQUEST['ftscfg'], [$_REQUEST['mapping']], 'drop');
1124
                if ($status == 0) {
1125
                    $this->doViewConfig($_REQUEST['ftscfg'], $lang['strftsmappingdropped']);
1126
                } else {
1127
                    $this->doViewConfig($_REQUEST['ftscfg'], $lang['strftsmappingdroppedbad']);
1128
                }
1129
            }
1130
        }
1131
    }
1132
1133
    public function doAlterMapping($msg = '')
1134
    {
1135
        $conf = $this->conf;
0 ignored issues
show
Unused Code introduced by
The assignment to $conf is dead and can be removed.
Loading history...
1136
        $misc = $this->misc;
1137
        $lang = $this->lang;
1138
        $data = $misc->getDatabaseAccessor();
1139
        $this->printTrail('ftscfg');
1140
        $this->printTitle($lang['stralter'], 'pg.ftscfg.alter');
1141
        $this->printMsg($msg);
1142
1143
        $ftsdicts = $data->getFtsDictionaries();
1144
        if ($ftsdicts->recordCount() > 0) {
1145
            if (!isset($_POST['formMapping'])) {
1146
                $_POST['formMapping'] = @$_REQUEST['mapping'];
1147
            }
1148
1149
            if (!isset($_POST['formDictionary'])) {
1150
                $_POST['formDictionary'] = '';
1151
            }
1152
1153
            if (!isset($_POST['ftscfg'])) {
1154
                $_POST['ftscfg'] = $_REQUEST['ftscfg'];
1155
            }
1156
1157
            echo '<form action="'.SUBFOLDER."/src/views/fulltext.php\" method=\"post\">\n";
1158
1159
            echo "<table>\n";
1160
            echo "\t<tr>\n";
1161
            echo "\t\t<th class=\"data left required\">{$lang['strftsmapping']}</th>\n";
1162
            echo "\t\t<td class=\"data1\">";
1163
1164
            // Case of multiaction drop
1165
            if (isset($_REQUEST['ma'])) {
1166
                $ma_mappings = [];
1167
                $ma_mappings_names = [];
1168
                foreach ($_REQUEST['ma'] as $v) {
1169
                    $a = unserialize(htmlspecialchars_decode($v, ENT_QUOTES));
0 ignored issues
show
Security introduced by
htmlspecialchars_decode(...\Controller\ENT_QUOTES) can contain request data and is used in unserialized context(s) leading to a potential security vulnerability.

1 path for user data to reach this point

  1. Read from $_REQUEST, and $_REQUEST['ma'] is assigned to $v
    in src/controllers/FulltextController.php on line 1168
  2. Data is passed through htmlspecialchars_decode()
    in src/controllers/FulltextController.php on line 1169

Preventing Object Injection Attacks

If you pass raw user-data to unserialize() for example, this can be used to create an object of any class that is available in your local filesystem. For an attacker, classes that have magic methods like __destruct or __wakeup are particularly interesting in such a case, as they can be exploited very easily.

We recommend to not pass user data to such a function. In case of unserialize, better use JSON to transfer data.

General Strategies to prevent injection

In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:

if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
    throw new \InvalidArgumentException('This input is not allowed.');
}

For numeric data, we recommend to explicitly cast the data:

$sanitized = (integer) $tainted;
Loading history...
1170
                    printf('<input type="hidden" name="formMapping[]" value="%s" />', htmlspecialchars($a['mapping']));
1171
                    $ma_mappings[] = $data->getFtsMappingByName($_POST['ftscfg'], $a['mapping']);
1172
                    $ma_mappings_names[] = $a['mapping'];
1173
                }
1174
                echo implode(', ', $ma_mappings_names);
0 ignored issues
show
Security introduced by
implode(', ', $ma_mappings_names) can contain request data and is used in output context(s) leading to a potential security vulnerability.

1 path for user data to reach this point

  1. Read from $_REQUEST, and $_REQUEST['ma'] is assigned to $v
    in src/controllers/FulltextController.php on line 1168
  2. Data is passed through htmlspecialchars_decode(), and Data is passed through unserialize(), and unserialize(htmlspecialchars_decode($v, PHPPgAdmin\Controller\ENT_QUOTES)) is assigned to $a
    in src/controllers/FulltextController.php on line 1169
  3. $a['mapping'] is assigned to $ma_mappings_names
    in src/controllers/FulltextController.php on line 1172
  4. Data is passed through implode()
    in src/controllers/FulltextController.php on line 1174

Preventing Cross-Site-Scripting Attacks

Cross-Site-Scripting allows an attacker to inject malicious code into your website - in particular Javascript code, and have that code executed with the privileges of a visiting user. This can be used to obtain data, or perform actions on behalf of that visiting user.

In order to prevent this, make sure to escape all user-provided data:

// for HTML
$sanitized = htmlentities($tainted, ENT_QUOTES);

// for URLs
$sanitized = urlencode($tainted);

General Strategies to prevent injection

In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:

if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
    throw new \InvalidArgumentException('This input is not allowed.');
}

For numeric data, we recommend to explicitly cast the data:

$sanitized = (integer) $tainted;
Loading history...
1175
            } else {
1176
                $mapping = $data->getFtsMappingByName($_POST['ftscfg'], $_POST['formMapping']);
1177
                echo $mapping->fields['name'];
1178
                echo '<input type="hidden" name="formMapping" value="', htmlspecialchars($_POST['formMapping']), "\" />\n";
1179
            }
1180
1181
            echo "\t\t</td>\n";
1182
            echo "\t</tr>\n";
1183
1184
            // Dictionary
1185
            echo "\t<tr>\n";
1186
            echo "\t\t<th class=\"data left required\">{$lang['strftsdict']}</th>\n";
1187
            echo "\t\t<td class=\"data1\">";
1188
            echo "\t\t\t<select name=\"formDictionary\">\n";
1189
            while (!$ftsdicts->EOF) {
1190
                $ftsdict = htmlspecialchars($ftsdicts->fields['name']);
1191
                echo "\t\t\t\t<option value=\"{$ftsdict}\"",
1192
                ($ftsdict == $_POST['formDictionary'] || $ftsdict == @$mapping->fields['dictionaries'] || $ftsdict == @$ma_mappings[0]->fields['dictionaries']) ? ' selected="selected"' : '', ">{$ftsdict}</option>\n";
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $mapping does not seem to be defined for all execution paths leading up to this point.
Loading history...
Comprehensibility Best Practice introduced by
The variable $ma_mappings does not seem to be defined for all execution paths leading up to this point.
Loading history...
1193
                $ftsdicts->moveNext();
1194
            }
1195
1196
            echo "\t\t</td>\n";
1197
            echo "\t</tr>\n";
1198
1199
            echo "</table>\n";
1200
            echo "<p><input type=\"hidden\" name=\"action\" value=\"altermapping\" />\n";
1201
            echo '<input type="hidden" name="ftscfg" value="', htmlspecialchars($_POST['ftscfg']), "\" />\n";
1202
            echo "<input type=\"hidden\" name=\"prev_action\" value=\"viewconfig\" /></p>\n";
1203
1204
            echo $misc->form;
1205
            echo "<input type=\"submit\" name=\"alter\" value=\"{$lang['stralter']}\" />\n";
1206
            echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" /></p>\n";
1207
            echo "</form>\n";
1208
        } else {
1209
            echo "<p>{$lang['strftsnodictionaries']}</p>\n";
1210
        }
1211
    }
1212
1213
    /**
1214
     * Save the form submission containing changes to a FTS mapping.
1215
     */
1216 View Code Duplication
    public function doSaveAlterMapping()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1217
    {
1218
        $conf = $this->conf;
0 ignored issues
show
Unused Code introduced by
The assignment to $conf is dead and can be removed.
Loading history...
1219
        $misc = $this->misc;
1220
        $lang = $this->lang;
1221
        $data = $misc->getDatabaseAccessor();
1222
1223
        $mappingArray = (is_array($_POST['formMapping']) ? $_POST['formMapping'] : [$_POST['formMapping']]);
1224
        $status = $data->changeFtsMapping($_POST['ftscfg'], $mappingArray, 'alter', $_POST['formDictionary']);
1225
        if ($status == 0) {
1226
            $this->doViewConfig($_POST['ftscfg'], $lang['strftsmappingaltered']);
1227
        } else {
1228
            $this->doAlterMapping($lang['strftsmappingalteredbad']);
1229
        }
1230
    }
1231
1232
    /**
1233
     * Show the form to enter parameters of a new FTS mapping.
1234
     */
1235
    public function doAddMapping($msg = '')
1236
    {
1237
        $conf = $this->conf;
0 ignored issues
show
Unused Code introduced by
The assignment to $conf is dead and can be removed.
Loading history...
1238
        $misc = $this->misc;
1239
        $lang = $this->lang;
1240
        $data = $misc->getDatabaseAccessor();
1241
1242
        $this->printTrail('ftscfg');
1243
        $this->printTitle($lang['stralter'], 'pg.ftscfg.alter');
1244
        $this->printMsg($msg);
1245
1246
        $ftsdicts = $data->getFtsDictionaries();
1247
        if ($ftsdicts->recordCount() > 0) {
1248
            if (!isset($_POST['formMapping'])) {
1249
                $_POST['formMapping'] = '';
1250
            }
1251
1252
            if (!isset($_POST['formDictionary'])) {
1253
                $_POST['formDictionary'] = '';
1254
            }
1255
1256
            if (!isset($_POST['ftscfg'])) {
1257
                $_POST['ftscfg'] = $_REQUEST['ftscfg'];
1258
            }
1259
1260
            $mappings = $data->getFtsMappings($_POST['ftscfg']);
1261
1262
            echo '<form action="'.SUBFOLDER."/src/views/fulltext.php\" method=\"post\">\n";
1263
            echo "<table>\n";
1264
            echo "\t<tr>\n";
1265
            echo "\t\t<th class=\"data left required\">{$lang['strftsmapping']}</th>\n";
1266
            echo "\t\t<td class=\"data1\">";
1267
            echo "\t\t\t<select name=\"formMapping\">\n";
1268
            while (!$mappings->EOF) {
1269
                $mapping = htmlspecialchars($mappings->fields['name']);
1270
                $mapping_desc = htmlspecialchars($mappings->fields['description']);
1271
                echo "\t\t\t\t<option value=\"{$mapping}\"",
1272
                $mapping == $_POST['formMapping'] ? ' selected="selected"' : '', ">{$mapping}", $mapping_desc ? " - {$mapping_desc}" : '', "</option>\n";
1273
                $mappings->moveNext();
1274
            }
1275
            echo "\t\t</td>\n";
1276
            echo "\t</tr>\n";
1277
1278
            // Dictionary
1279
            echo "\t<tr>\n";
1280
            echo "\t\t<th class=\"data left required\">{$lang['strftsdict']}</th>\n";
1281
            echo "\t\t<td class=\"data1\">";
1282
            echo "\t\t\t<select name=\"formDictionary\">\n";
1283
            while (!$ftsdicts->EOF) {
1284
                $ftsdict = htmlspecialchars($ftsdicts->fields['name']);
1285
                echo "\t\t\t\t<option value=\"{$ftsdict}\"",
1286
                $ftsdict == $_POST['formDictionary'] ? ' selected="selected"' : '', ">{$ftsdict}</option>\n";
1287
                $ftsdicts->moveNext();
1288
            }
1289
1290
            echo "\t\t</td>\n";
1291
            echo "\t</tr>\n";
1292
1293
            echo "</table>\n";
1294
            echo "<p><input type=\"hidden\" name=\"action\" value=\"addmapping\" />\n";
1295
            echo '<input type="hidden" name="ftscfg" value="', htmlspecialchars($_POST['ftscfg']), "\" />\n";
1296
            echo "<input type=\"hidden\" name=\"prev_action\" value=\"viewconfig\" /></p>\n";
1297
            echo $misc->form;
1298
            echo "<input type=\"submit\" name=\"add\" value=\"{$lang['stradd']}\" />\n";
1299
            echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" /></p>\n";
1300
            echo "</form>\n";
1301
        } else {
1302
            echo "<p>{$lang['strftsnodictionaries']}</p>\n";
1303
        }
1304
    }
1305
1306
    /**
1307
     * Save the form submission containing parameters of a new FTS mapping.
1308
     */
1309 View Code Duplication
    public function doSaveAddMapping()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1310
    {
1311
        $conf = $this->conf;
0 ignored issues
show
Unused Code introduced by
The assignment to $conf is dead and can be removed.
Loading history...
1312
        $misc = $this->misc;
1313
        $lang = $this->lang;
1314
        $data = $misc->getDatabaseAccessor();
1315
1316
        $mappingArray = (is_array($_POST['formMapping']) ? $_POST['formMapping'] : [$_POST['formMapping']]);
1317
        $status = $data->changeFtsMapping($_POST['ftscfg'], $mappingArray, 'add', $_POST['formDictionary']);
1318
        if ($status == 0) {
1319
            $this->doViewConfig($_POST['ftscfg'], $lang['strftsmappingadded']);
1320
        } else {
1321
            $this->doAddMapping($lang['strftsmappingaddedbad']);
1322
        }
1323
    }
1324
}
1325