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

TablesController   F

Complexity

Total Complexity 165

Size/Duplication

Total Lines 1203
Duplicated Lines 12.55 %

Importance

Changes 0
Metric Value
dl 151
loc 1203
rs 0.6314
c 0
b 0
f 0
wmc 165

10 Methods

Rating   Name   Duplication   Size   Complexity  
B doSubTree() 0 30 1
A doTree() 0 23 1
C doDrop() 25 76 12
D doInsertRow() 23 140 24
B doDefault() 0 207 4
F doCreateLike() 0 111 19
D doSelectRows() 36 120 17
C doEmpty() 24 61 10
F doCreate() 41 264 56
D render() 0 110 21

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 TablesController 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 TablesController, 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 TablesController extends BaseController
11
{
12
    use AdminTrait;
13
    public $script = 'tables.php';
14
    public $_name = 'TablesController';
15
    public $table_place = 'tables-tables';
16
17
    public function render()
18
    {
19
        $conf = $this->conf;
20
        $misc = $this->misc;
21
        $lang = $this->lang;
22
        $action = $this->action;
23
24
        if ($action == 'tree') {
25
            return $this->doTree();
26
        } elseif ($action == 'subtree') {
27
            return $this->doSubTree();
28
        }
29
30
        $data = $misc->getDatabaseAccessor();
31
32
        $header_template = 'header.twig';
33
        $footer_template = 'footer.twig';
34
35
        ob_start();
36
37
        switch ($action) {
38
            case 'create':
39
40
                if (isset($_POST['cancel'])) {
41
                    $this->doDefault();
42
                } else {
43
                    $header_template = 'header_select2.twig';
44
                    $this->doCreate();
45
                }
46
47
                break;
48
            case 'createlike':
49
                $header_template = 'header_select2.twig';
50
                $this->doCreateLike(false);
51
                break;
52
            case 'confcreatelike':
53
                if (isset($_POST['cancel'])) {
54
                    $header_template = 'header_datatables.twig';
55
                    $this->doDefault();
56
                } else {
57
                    //$header_template = 'header_select2.twig';
58
                    $this->doCreateLike(true);
59
                }
60
61
                break;
62
            case 'selectrows':
63
                if (!isset($_POST['cancel'])) {
64
                    $this->doSelectRows(false);
65
                } else {
66
                    $header_template = 'header_datatables.twig';
67
                    $this->doDefault();
68
                }
69
70
                break;
71
            case 'confselectrows':
72
                $this->doSelectRows(true);
73
                break;
74
            case 'insertrow':
75
                if (!isset($_POST['cancel'])) {
76
                    $this->doInsertRow(false);
77
                } else {
78
                    $header_template = 'header_datatables.twig';
79
                    $this->doDefault();
80
                }
81
82
                break;
83
            case 'confinsertrow':
84
                $this->doInsertRow(true);
85
                break;
86
            case 'empty':
87
                if (isset($_POST['empty'])) {
88
                    $this->doEmpty(false);
89
                } else {
90
                    $header_template = 'header_datatables.twig';
91
                    $this->doDefault();
92
                }
93
94
                break;
95
            case 'confirm_empty':
96
                $this->doEmpty(true);
97
                break;
98
            case 'drop':
99
                if (isset($_POST['drop'])) {
100
                    $this->doDrop(false);
101
                } else {
102
                    $header_template = 'header_datatables.twig';
103
                    $this->doDefault();
104
                }
105
106
                break;
107
            case 'confirm_drop':
108
                $this->doDrop(true);
109
                break;
110
            default:
111
                if ($this->adminActions($action, 'table') === false) {
112
                    $header_template = 'header_datatables.twig';
113
                    $this->doDefault();
114
                }
115
116
                break;
117
        }
118
119
        $output = ob_get_clean();
120
121
        $this->printHeader($lang['strtables'], null, true, $header_template);
122
        $this->printBody();
123
124
        echo $output;
125
126
        return $this->printFooter();
127
    }
128
129
    /**
130
     * Show default list of tables in the database.
131
     */
132
    public function doDefault($msg = '')
133
    {
134
        $conf = $this->conf;
135
        $misc = $this->misc;
136
        $lang = $this->lang;
137
        $data = $misc->getDatabaseAccessor();
138
139
        $this->printTrail('schema');
140
        $this->printTabs('schema', 'tables');
141
        $this->printMsg($msg);
142
143
        $tables = $data->getTables();
144
145
        $columns = [
146
            'table'      => [
147
                'title' => $lang['strtable'],
148
                'field' => Decorator::field('relname'),
149
                'url'   => SUBFOLDER."/redirect/table?{$misc->href}&amp;",
150
                'vars'  => ['table' => 'relname'],
151
            ],
152
            'owner'      => [
153
                'title' => $lang['strowner'],
154
                'field' => Decorator::field('relowner'),
155
            ],
156
            'tablespace' => [
157
                'title' => $lang['strtablespace'],
158
                'field' => Decorator::field('tablespace'),
159
            ],
160
            'tuples'     => [
161
                'title' => $lang['strestimatedrowcount'],
162
                'field' => Decorator::field('reltuples'),
163
                'type'  => 'numeric',
164
            ],
165
            'actions'    => [
166
                'title' => $lang['stractions'],
167
            ],
168
            'comment'    => [
169
                'title' => $lang['strcomment'],
170
                'field' => Decorator::field('relcomment'),
171
            ],
172
        ];
173
174
        $actions = [
175
            'multiactions' => [
176
                'keycols' => ['table' => 'relname'],
177
                'url'     => 'tables.php',
178
                'default' => 'analyze',
179
            ],
180
            'browse'       => [
181
                'content' => $lang['strbrowse'],
182
                'attr'    => [
183
                    'href' => [
184
                        'url'     => 'display.php',
185
                        'urlvars' => [
186
                            'subject' => 'table',
187
                            'return'  => 'table',
188
                            'table'   => Decorator::field('relname'),
189
                        ],
190
                    ],
191
                ],
192
            ],
193
            'select'       => [
194
                'content' => $lang['strselect'],
195
                'attr'    => [
196
                    'href' => [
197
                        'url'     => 'tables.php',
198
                        'urlvars' => [
199
                            'action' => 'confselectrows',
200
                            'table'  => Decorator::field('relname'),
201
                        ],
202
                    ],
203
                ],
204
            ],
205
            'insert'       => [
206
                'content' => $lang['strinsert'],
207
                'attr'    => [
208
                    'href' => [
209
                        'url'     => 'tables.php',
210
                        'urlvars' => [
211
                            'action' => 'confinsertrow',
212
                            'table'  => Decorator::field('relname'),
213
                        ],
214
                    ],
215
                ],
216
            ],
217
            'empty'        => [
218
                'multiaction' => 'confirm_empty',
219
                'content'     => $lang['strempty'],
220
                'attr'        => [
221
                    'href' => [
222
                        'url'     => 'tables.php',
223
                        'urlvars' => [
224
                            'action' => 'confirm_empty',
225
                            'table'  => Decorator::field('relname'),
226
                        ],
227
                    ],
228
                ],
229
            ],
230
            'alter'        => [
231
                'content' => $lang['stralter'],
232
                'attr'    => [
233
                    'href' => [
234
                        'url'     => 'tblproperties.php',
235
                        'urlvars' => [
236
                            'action' => 'confirm_alter',
237
                            'table'  => Decorator::field('relname'),
238
                        ],
239
                    ],
240
                ],
241
            ],
242
            'drop'         => [
243
                'multiaction' => 'confirm_drop',
244
                'content'     => $lang['strdrop'],
245
                'attr'        => [
246
                    'href' => [
247
                        'url'     => 'tables.php',
248
                        'urlvars' => [
249
                            'action' => 'confirm_drop',
250
                            'table'  => Decorator::field('relname'),
251
                        ],
252
                    ],
253
                ],
254
            ],
255
            'vacuum'       => [
256
                'multiaction' => 'confirm_vacuum',
257
                'content'     => $lang['strvacuum'],
258
                'attr'        => [
259
                    'href' => [
260
                        'url'     => 'tables.php',
261
                        'urlvars' => [
262
                            'action' => 'confirm_vacuum',
263
                            'table'  => Decorator::field('relname'),
264
                        ],
265
                    ],
266
                ],
267
            ],
268
            'analyze'      => [
269
                'multiaction' => 'confirm_analyze',
270
                'content'     => $lang['stranalyze'],
271
                'attr'        => [
272
                    'href' => [
273
                        'url'     => 'tables.php',
274
                        'urlvars' => [
275
                            'action' => 'confirm_analyze',
276
                            'table'  => Decorator::field('relname'),
277
                        ],
278
                    ],
279
                ],
280
            ],
281
            'reindex'      => [
282
                'multiaction' => 'confirm_reindex',
283
                'content'     => $lang['strreindex'],
284
                'attr'        => [
285
                    'href' => [
286
                        'url'     => 'tables.php',
287
                        'urlvars' => [
288
                            'action' => 'confirm_reindex',
289
                            'table'  => Decorator::field('relname'),
290
                        ],
291
                    ],
292
                ],
293
            ],
294
            //'cluster' TODO ?
295
        ];
296
297
        if (!$data->hasTablespaces()) {
298
            unset($columns['tablespace']);
299
        }
300
301
        //\Kint::dump($tables);
302
303
        echo $this->printTable($tables, $columns, $actions, $this->table_place, $lang['strnotables']);
304
305
        $navlinks = [
306
            'create' => [
307
                'attr'    => [
308
                    'href' => [
309
                        'url'     => 'tables.php',
310
                        'urlvars' => [
311
                            'action'   => 'create',
312
                            'server'   => $_REQUEST['server'],
313
                            'database' => $_REQUEST['database'],
314
                            'schema'   => $_REQUEST['schema'],
315
                        ],
316
                    ],
317
                ],
318
                'content' => $lang['strcreatetable'],
319
            ],
320
        ];
321
322
        if (($tables->recordCount() > 0) && $data->hasCreateTableLike()) {
323
            $navlinks['createlike'] = [
324
                'attr'    => [
325
                    'href' => [
326
                        'url'     => 'tables.php',
327
                        'urlvars' => [
328
                            'action'   => 'createlike',
329
                            'server'   => $_REQUEST['server'],
330
                            'database' => $_REQUEST['database'],
331
                            'schema'   => $_REQUEST['schema'],
332
                        ],
333
                    ],
334
                ],
335
                'content' => $lang['strcreatetablelike'],
336
            ];
337
        }
338
        $this->printNavLinks($navlinks, 'tables-tables', get_defined_vars());
339
    }
340
341
    /**
342
     * Generate XML for the browser tree.
343
     */
344
    public function doTree()
345
    {
346
        $conf = $this->conf;
347
        $misc = $this->misc;
348
        $lang = $this->lang;
349
        $data = $misc->getDatabaseAccessor();
350
351
        //\PC::debug($misc->getDatabase(), 'getDatabase');
352
353
        $tables = $data->getTables();
354
355
        $reqvars = $misc->getRequestVars('table');
356
357
        $attrs = [
358
            'text'       => Decorator::field('relname'),
359
            'icon'       => 'Table',
360
            'iconAction' => Decorator::url('display.php', $reqvars, ['table' => Decorator::field('relname')]),
361
            'toolTip'    => Decorator::field('relcomment'),
362
            'action'     => Decorator::redirecturl('redirect.php', $reqvars, ['table' => Decorator::field('relname')]),
363
            'branch'     => Decorator::url('tables.php', $reqvars, ['action' => 'subtree', 'table' => Decorator::field('relname')]),
364
        ];
365
366
        return $this->printTree($tables, $attrs, 'tables');
367
    }
368
369
    public function doSubTree()
370
    {
371
        $conf = $this->conf;
372
        $misc = $this->misc;
373
        $lang = $this->lang;
374
        $data = $misc->getDatabaseAccessor();
375
376
        $tabs = $misc->getNavTabs('table');
377
        $items = $this->adjustTabsForTree($tabs);
378
        $reqvars = $misc->getRequestVars('table');
379
380
        $attrs = [
381
            'text'   => Decorator::field('title'),
382
            'icon'   => Decorator::field('icon'),
383
            'action' => Decorator::actionurl(
384
                Decorator::field('url'),
385
                $reqvars,
386
                Decorator::field('urlvars'),
387
                ['table' => $_REQUEST['table']]
388
            ),
389
            'branch' => Decorator::ifempty(
390
                Decorator::field('branch'), '', Decorator::url(Decorator::field('url'), $reqvars, [
391
                    'action' => 'tree',
392
                    'table'  => $_REQUEST['table'],
393
                ]
394
                )
395
            ),
396
        ];
397
398
        return $this->printTree($items, $attrs, 'table');
399
    }
400
401
    /**
402
     * Displays a screen where they can enter a new table.
403
     */
404
    public function doCreate($msg = '')
405
    {
406
        $conf = $this->conf;
407
        $misc = $this->misc;
408
        $lang = $this->lang;
409
        $data = $misc->getDatabaseAccessor();
410
411
        if (!isset($_REQUEST['stage'])) {
412
            $_REQUEST['stage'] = 1;
413
            $default_with_oids = $data->getDefaultWithOid();
414
            if ($default_with_oids == 'off') {
415
                $_REQUEST['withoutoids'] = 'on';
416
            }
417
        }
418
419
        if (!isset($_REQUEST['name'])) {
420
            $_REQUEST['name'] = '';
421
        }
422
423
        if (!isset($_REQUEST['fields'])) {
424
            $_REQUEST['fields'] = '';
425
        }
426
427
        if (!isset($_REQUEST['tblcomment'])) {
428
            $_REQUEST['tblcomment'] = '';
429
        }
430
431
        if (!isset($_REQUEST['spcname'])) {
432
            $_REQUEST['spcname'] = '';
433
        }
434
435
        switch ($_REQUEST['stage']) {
436
            case 1:
437
                // You are presented with a form in which you describe the table, pick the tablespace and state how many fields it will have
438
                // Fetch all tablespaces from the database
439
                if ($data->hasTablespaces()) {
440
                    $tablespaces = $data->getTablespaces();
441
                }
442
443
                $this->printTrail('schema');
444
                $this->printTitle($lang['strcreatetable'], 'pg.table.create');
445
                $this->printMsg($msg);
446
447
                echo '<form action="'.SUBFOLDER.'/src/views/'.$this->script.'" method="post">';
448
                echo "\n";
449
                echo "<table>\n";
450
                echo "\t<tr>\n\t\t<th class=\"data left required\">{$lang['strname']}</th>\n";
451
                echo "\t\t<td class=\"data\"><input name=\"name\" size=\"32\" maxlength=\"{$data->_maxNameLen}\" value=\"",
452
                htmlspecialchars($_REQUEST['name']), "\" /></td>\n\t</tr>\n";
453
                echo "\t<tr>\n\t\t<th class=\"data left required\">{$lang['strnumcols']}</th>\n";
454
                echo "\t\t<td class=\"data\"><input name=\"fields\" size=\"5\" maxlength=\"{$data->_maxNameLen}\" value=\"",
455
                htmlspecialchars($_REQUEST['fields']), "\" /></td>\n\t</tr>\n";
456
                echo "\t<tr>\n\t\t<th class=\"data left\">{$lang['stroptions']}</th>\n";
457
                echo "\t\t<td class=\"data\"><label for=\"withoutoids\"><input type=\"checkbox\" id=\"withoutoids\" name=\"withoutoids\"", isset($_REQUEST['withoutoids']) ? ' checked="checked"' : '', " />WITHOUT OIDS</label></td>\n\t</tr>\n";
458
459
                // Tablespace (if there are any)
460 View Code Duplication
                if ($data->hasTablespaces() && $tablespaces->recordCount() > 0) {
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...
461
                    echo "\t<tr>\n\t\t<th class=\"data left\">{$lang['strtablespace']}</th>\n";
462
                    echo "\t\t<td class=\"data1\">\n\t\t\t<select name=\"spcname\">\n";
463
                    // Always offer the default (empty) option
464
                    echo "\t\t\t\t<option value=\"\"",
465
                    ($_REQUEST['spcname'] == '') ? ' selected="selected"' : '', "></option>\n";
466
                    // Display all other tablespaces
467
                    while (!$tablespaces->EOF) {
468
                        $spcname = htmlspecialchars($tablespaces->fields['spcname']);
469
                        echo "\t\t\t\t<option value=\"{$spcname}\"",
470
                        ($tablespaces->fields['spcname'] == $_REQUEST['spcname']) ? ' selected="selected"' : '', ">{$spcname}</option>\n";
471
                        $tablespaces->moveNext();
472
                    }
473
                    echo "\t\t\t</select>\n\t\t</td>\n\t</tr>\n";
474
                }
475
476
                echo "\t<tr>\n\t\t<th class=\"data left\">{$lang['strcomment']}</th>\n";
477
                echo "\t\t<td><textarea name=\"tblcomment\" rows=\"3\" cols=\"32\">",
478
                htmlspecialchars($_REQUEST['tblcomment']), "</textarea></td>\n\t</tr>\n";
479
480
                echo "</table>\n";
481
                echo "<p><input type=\"hidden\" name=\"action\" value=\"create\" />\n";
482
                echo "<input type=\"hidden\" name=\"stage\" value=\"2\" />\n";
483
                echo $misc->form;
484
                echo "<input type=\"submit\" value=\"{$lang['strnext']}\" />\n";
485
                echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" /></p>\n";
486
                echo "</form>\n";
487
                break;
488
            case 2:
489
490
                // Check inputs
491
                $fields = trim($_REQUEST['fields']);
492 View Code Duplication
                if (trim($_REQUEST['name']) == '') {
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...
493
                    $_REQUEST['stage'] = 1;
494
                    $this->doCreate($lang['strtableneedsname']);
495
496
                    return;
497
                } elseif ($fields == '' || !is_numeric($fields) || $fields != (int) $fields || $fields < 1) {
498
                    $_REQUEST['stage'] = 1;
499
                    $this->doCreate($lang['strtableneedscols']);
500
501
                    return;
502
                }
503
504
                $types = $data->getTypes(true, false, true);
505
                $types_for_js = [];
506
507
                $this->printTrail('schema');
508
                $this->printTitle($lang['strcreatetable'], 'pg.table.create');
509
                $this->printMsg($msg);
510
511
                echo '<script src="'.SUBFOLDER.'/js/tables.js" type="text/javascript"></script>';
512
                echo '<form action="'.SUBFOLDER."/src/views/tables.php\" method=\"post\">\n";
513
514
                // Output table header
515
                echo "<table>\n";
516
                echo "\t<tr><th colspan=\"2\" class=\"data required\">{$lang['strcolumn']}</th><th colspan=\"2\" class=\"data required\">{$lang['strtype']}</th>";
517
                echo "<th class=\"data\">{$lang['strlength']}</th><th class=\"data\">{$lang['strnotnull']}</th>";
518
                echo "<th class=\"data\">{$lang['struniquekey']}</th><th class=\"data\">{$lang['strprimarykey']}</th>";
519
                echo "<th class=\"data\">{$lang['strdefault']}</th><th class=\"data\">{$lang['strcomment']}</th></tr>\n";
520
521
                for ($i = 0; $i < $_REQUEST['fields']; $i++) {
522
                    if (!isset($_REQUEST['field'][$i])) {
523
                        $_REQUEST['field'][$i] = '';
524
                    }
525
526
                    if (!isset($_REQUEST['length'][$i])) {
527
                        $_REQUEST['length'][$i] = '';
528
                    }
529
530
                    if (!isset($_REQUEST['default'][$i])) {
531
                        $_REQUEST['default'][$i] = '';
532
                    }
533
534
                    if (!isset($_REQUEST['colcomment'][$i])) {
535
                        $_REQUEST['colcomment'][$i] = '';
536
                    }
537
538
                    echo "\t<tr>\n\t\t<td>", $i + 1, ".&nbsp;</td>\n";
539
                    echo "\t\t<td><input name=\"field[{$i}]\" size=\"16\" maxlength=\"{$data->_maxNameLen}\" value=\"",
540
                    htmlspecialchars($_REQUEST['field'][$i]), "\" /></td>\n";
541
                    echo "\t\t<td>\n\t\t\t<select name=\"type[{$i}]\" class=\"select2\" id=\"types{$i}\" onchange=\"checkLengths(this.options[this.selectedIndex].value,{$i});\">\n";
542
                    // Output any "magic" types
543
                    foreach ($data->extraTypes as $v) {
544
                        $types_for_js[strtolower($v)] = 1;
545
                        echo "\t\t\t\t<option value=\"", htmlspecialchars($v), '"',
546
                        (isset($_REQUEST['type'][$i]) && $v == $_REQUEST['type'][$i]) ? ' selected="selected"' : '', '>',
547
                        $misc->printVal($v), "</option>\n";
548
                    }
549
                    $types->moveFirst();
550 View Code Duplication
                    while (!$types->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...
551
                        $typname = $types->fields['typname'];
552
                        $types_for_js[$typname] = 1;
553
                        echo "\t\t\t\t<option value=\"", htmlspecialchars($typname), '"',
554
                        (isset($_REQUEST['type'][$i]) && $typname == $_REQUEST['type'][$i]) ? ' selected="selected"' : '', '>',
555
                        $misc->printVal($typname), "</option>\n";
556
                        $types->moveNext();
557
                    }
558
                    echo "\t\t\t</select>\n\t\t\n";
559
                    if ($i == 0) {
560
                        // only define js types array once
561
                        $predefined_size_types = array_intersect($data->predefined_size_types, array_keys($types_for_js));
562
                        $escaped_predef_types = []; // the JS escaped array elements
563
                        foreach ($predefined_size_types as $value) {
564
                            $escaped_predef_types[] = "'{$value}'";
565
                        }
566
                        echo '<script type="text/javascript">predefined_lengths = new Array('.implode(',', $escaped_predef_types).");</script>\n\t</td>";
567
                    }
568
569
                    // Output array type selector
570
                    echo "\t\t<td>\n\t\t\t<select name=\"array[{$i}]\">\n";
571
                    echo "\t\t\t\t<option value=\"\"", (isset($_REQUEST['array'][$i]) && $_REQUEST['array'][$i] == '') ? ' selected="selected"' : '', "></option>\n";
572
                    echo "\t\t\t\t<option value=\"[]\"", (isset($_REQUEST['array'][$i]) && $_REQUEST['array'][$i] == '[]') ? ' selected="selected"' : '', ">[ ]</option>\n";
573
                    echo "\t\t\t</select>\n\t\t</td>\n";
574
575
                    echo "\t\t<td><input name=\"length[{$i}]\" id=\"lengths{$i}\" size=\"10\" value=\"",
576
                    htmlspecialchars($_REQUEST['length'][$i]), "\" /></td>\n";
577
                    echo "\t\t<td><input type=\"checkbox\" name=\"notnull[{$i}]\"", (isset($_REQUEST['notnull'][$i])) ? ' checked="checked"' : '', " /></td>\n";
578
                    echo "\t\t<td style=\"text-align: center\"><input type=\"checkbox\" name=\"uniquekey[{$i}]\""
579
                        .(isset($_REQUEST['uniquekey'][$i]) ? ' checked="checked"' : '')." /></td>\n";
580
                    echo "\t\t<td style=\"text-align: center\"><input type=\"checkbox\" name=\"primarykey[{$i}]\" "
581
                        .(isset($_REQUEST['primarykey'][$i]) ? ' checked="checked"' : '')
582
                        ." /></td>\n";
583
                    echo "\t\t<td><input name=\"default[{$i}]\" size=\"20\" value=\"",
584
                    htmlspecialchars($_REQUEST['default'][$i]), "\" /></td>\n";
585
                    echo "\t\t<td><input name=\"colcomment[{$i}]\" size=\"40\" value=\"",
586
                    htmlspecialchars($_REQUEST['colcomment'][$i]), "\" />
587
						<script type=\"text/javascript\">checkLengths(document.getElementById('types{$i}').value,{$i});</script>
588
						</td>\n\t</tr>\n";
589
                }
590
                echo "</table>\n";
591
                echo "<p><input type=\"hidden\" name=\"action\" value=\"create\" />\n";
592
                echo "<input type=\"hidden\" name=\"stage\" value=\"3\" />\n";
593
                echo $misc->form;
594
                echo '<input type="hidden" name="name" value="', htmlspecialchars($_REQUEST['name']), "\" />\n";
595
                echo '<input type="hidden" name="fields" value="', htmlspecialchars($_REQUEST['fields']), "\" />\n";
596
                if (isset($_REQUEST['withoutoids'])) {
597
                    echo "<input type=\"hidden\" name=\"withoutoids\" value=\"true\" />\n";
598
                }
599
                echo '<input type="hidden" name="tblcomment" value="', htmlspecialchars($_REQUEST['tblcomment']), "\" />\n";
600
                if (isset($_REQUEST['spcname'])) {
601
                    echo '<input type="hidden" name="spcname" value="', htmlspecialchars($_REQUEST['spcname']), "\" />\n";
602
                }
603
                echo "<input type=\"submit\" value=\"{$lang['strcreate']}\" />\n";
604
                echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" /></p>\n";
605
                echo "</form>\n";
606
607
                break;
608
            case 3:
609
610
                if (!isset($_REQUEST['notnull'])) {
611
                    $_REQUEST['notnull'] = [];
612
                }
613
614
                if (!isset($_REQUEST['uniquekey'])) {
615
                    $_REQUEST['uniquekey'] = [];
616
                }
617
618
                if (!isset($_REQUEST['primarykey'])) {
619
                    $_REQUEST['primarykey'] = [];
620
                }
621
622
                if (!isset($_REQUEST['length'])) {
623
                    $_REQUEST['length'] = [];
624
                }
625
626
                // Default tablespace to null if it isn't set
627
                if (!isset($_REQUEST['spcname'])) {
628
                    $_REQUEST['spcname'] = null;
629
                }
630
631
                // Check inputs
632
                $fields = trim($_REQUEST['fields']);
633 View Code Duplication
                if (trim($_REQUEST['name']) == '') {
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...
634
                    $_REQUEST['stage'] = 1;
635
                    $this->doCreate($lang['strtableneedsname']);
636
637
                    return;
638
                } elseif ($fields == '' || !is_numeric($fields) || $fields != (int) $fields || $fields <= 0) {
639
                    $_REQUEST['stage'] = 1;
640
                    $this->doCreate($lang['strtableneedscols']);
641
642
                    return;
643
                }
644
645
                $status = $data->createTable($_REQUEST['name'], $_REQUEST['fields'], $_REQUEST['field'],
646
                    $_REQUEST['type'], $_REQUEST['array'], $_REQUEST['length'], $_REQUEST['notnull'], $_REQUEST['default'],
647
                    isset($_REQUEST['withoutoids']), $_REQUEST['colcomment'], $_REQUEST['tblcomment'], $_REQUEST['spcname'],
648
                    $_REQUEST['uniquekey'], $_REQUEST['primarykey']);
649
650
                if ($status == 0) {
651
                    $misc->setReloadBrowser(true);
652
653
                    return $this->doDefault($lang['strtablecreated']);
654
                } elseif ($status == -1) {
655
                    $_REQUEST['stage'] = 2;
656
                    $this->doCreate($lang['strtableneedsfield']);
657
658
                    return;
659
                } else {
660
                    $_REQUEST['stage'] = 2;
661
                    $this->doCreate($lang['strtablecreatedbad']);
662
663
                    return;
664
                }
665
                break;
666
            default:
667
                echo "<p>{$lang['strinvalidparam']}</p>\n";
668
        }
669
    }
670
671
    /**
672
     * Dsiplay a screen where user can create a table from an existing one.
673
     * We don't have to check if pg supports schema cause create table like
674
     * is available under pg 7.4+ which has schema.
675
     */
676
    public function doCreateLike($confirm, $msg = '')
677
    {
678
        $conf = $this->conf;
679
        $misc = $this->misc;
680
        $lang = $this->lang;
681
        $data = $misc->getDatabaseAccessor();
682
683
        if (!$confirm) {
684
            if (!isset($_REQUEST['name'])) {
685
                $_REQUEST['name'] = '';
686
            }
687
688
            if (!isset($_REQUEST['like'])) {
689
                $_REQUEST['like'] = '';
690
            }
691
692
            if (!isset($_REQUEST['tablespace'])) {
693
                $_REQUEST['tablespace'] = '';
694
            }
695
696
            $this->printTrail('schema');
697
            $this->printTitle($lang['strcreatetable'], 'pg.table.create');
698
            $this->printMsg($msg);
699
700
            $tbltmp = $data->getTables(true);
701
            $tbltmp = $tbltmp->getArray();
702
703
            $tables = [];
704
            $tblsel = '';
705
            foreach ($tbltmp as $a) {
706
                $data->fieldClean($a['nspname']);
707
                $data->fieldClean($a['relname']);
708
                $tables["\"{$a['nspname']}\".\"{$a['relname']}\""] = serialize(['schema' => $a['nspname'], 'table' => $a['relname']]);
709
                if ($_REQUEST['like'] == $tables["\"{$a['nspname']}\".\"{$a['relname']}\""]) {
710
                    $tblsel = htmlspecialchars($tables["\"{$a['nspname']}\".\"{$a['relname']}\""]);
711
                }
712
            }
713
714
            unset($tbltmp);
715
716
            echo '<form action="'.SUBFOLDER."/src/views/tables.php\" method=\"post\">\n";
717
            echo "<table>\n\t<tr>\n\t\t<th class=\"data left required\">{$lang['strname']}</th>\n";
718
            echo "\t\t<td class=\"data\"><input name=\"name\" size=\"32\" maxlength=\"{$data->_maxNameLen}\" value=\"", htmlspecialchars($_REQUEST['name']), "\" /></td>\n\t</tr>\n";
719
            echo "\t<tr>\n\t\t<th class=\"data left required\">{$lang['strcreatetablelikeparent']}</th>\n";
720
            echo "\t\t<td class=\"data\">";
721
            echo \PHPPgAdmin\XHtml\HTMLController::printCombo($tables, 'like', true, $tblsel, false);
722
            echo "</td>\n\t</tr>\n";
723
            if ($data->hasTablespaces()) {
724
                $tblsp_ = $data->getTablespaces();
725
                if ($tblsp_->recordCount() > 0) {
726
                    $tblsp_ = $tblsp_->getArray();
727
                    $tblsp = [];
728
                    foreach ($tblsp_ as $a) {
729
                        $tblsp[$a['spcname']] = $a['spcname'];
730
                    }
731
732
                    echo "\t<tr>\n\t\t<th class=\"data left\">{$lang['strtablespace']}</th>\n";
733
                    echo "\t\t<td class=\"data\">";
734
                    echo \PHPPgAdmin\XHtml\HTMLController::printCombo($tblsp, 'tablespace', true, $_REQUEST['tablespace'], false);
735
                    echo "</td>\n\t</tr>\n";
736
                }
737
            }
738
            echo "\t<tr>\n\t\t<th class=\"data left\">{$lang['stroptions']}</th>\n\t\t<td class=\"data\">";
739
            echo '<label for="withdefaults"><input type="checkbox" id="withdefaults" name="withdefaults"',
740
            isset($_REQUEST['withdefaults']) ? ' checked="checked"' : '',
741
                "/>{$lang['strcreatelikewithdefaults']}</label>";
742
            if ($data->hasCreateTableLikeWithConstraints()) {
743
                echo '<br /><label for="withconstraints"><input type="checkbox" id="withconstraints" name="withconstraints"',
744
                isset($_REQUEST['withconstraints']) ? ' checked="checked"' : '',
745
                    "/>{$lang['strcreatelikewithconstraints']}</label>";
746
            }
747
            if ($data->hasCreateTableLikeWithIndexes()) {
748
                echo '<br /><label for="withindexes"><input type="checkbox" id="withindexes" name="withindexes"',
749
                isset($_REQUEST['withindexes']) ? ' checked="checked"' : '',
750
                    "/>{$lang['strcreatelikewithindexes']}</label>";
751
            }
752
            echo "</td>\n\t</tr>\n";
753
            echo '</table>';
754
755
            echo "<input type=\"hidden\" name=\"action\" value=\"confcreatelike\" />\n";
756
            echo $misc->form;
757
            echo "<p><input type=\"submit\" value=\"{$lang['strcreate']}\" />\n";
758
            echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" /></p>\n";
759
            echo "</form>\n";
760
        } else {
761
            if (trim($_REQUEST['name']) == '') {
762
                $this->doCreateLike(false, $lang['strtableneedsname']);
763
764
                return;
765
            }
766
            if (trim($_REQUEST['like']) == '') {
767
                $this->doCreateLike(false, $lang['strtablelikeneedslike']);
768
769
                return;
770
            }
771
772
            if (!isset($_REQUEST['tablespace'])) {
773
                $_REQUEST['tablespace'] = '';
774
            }
775
776
            $status = $data->createTableLike($_REQUEST['name'], unserialize($_REQUEST['like']), isset($_REQUEST['withdefaults']),
0 ignored issues
show
Security introduced by
$_REQUEST['like'] 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
    in src/controllers/TablesController.php on line 776

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...
777
                isset($_REQUEST['withconstraints']), isset($_REQUEST['withindexes']), $_REQUEST['tablespace']);
778
779
            if ($status == 0) {
780
                $misc->setReloadBrowser(true);
781
782
                return $this->doDefault($lang['strtablecreated']);
783
            } else {
784
                $this->doCreateLike(false, $lang['strtablecreatedbad']);
785
786
                return;
787
            }
788
        }
789
    }
790
791
    /**
792
     * Ask for select parameters and perform select.
793
     */
794
    public function doSelectRows($confirm, $msg = '')
795
    {
796
        $conf = $this->conf;
797
        $misc = $this->misc;
798
        $lang = $this->lang;
799
        $data = $misc->getDatabaseAccessor();
800
801
        if ($confirm) {
802
            $this->printTrail('table');
803
            $this->printTabs('table', 'select');
804
            $this->printMsg($msg);
805
806
            $attrs = $data->getTableAttributes($_REQUEST['table']);
807
808
            echo '<form action="'.SUBFOLDER."/src/views/tables.php\" method=\"post\" id=\"selectform\">\n";
809
            if ($attrs->recordCount() > 0) {
810
                // JavaScript for select all feature
811
                echo "<script type=\"text/javascript\">\n";
812
                echo "//<![CDATA[\n";
813
                echo "	function selectAll() {\n";
814
                echo "		for (var i=0; i<document.getElementById('selectform').elements.length; i++) {\n";
815
                echo "			var e = document.getElementById('selectform').elements[i];\n";
816
                echo "			if (e.name.indexOf('show') == 0) e.checked = document.getElementById('selectform').selectall.checked;\n";
817
                echo "		}\n";
818
                echo "	}\n";
819
                echo "//]]>\n";
820
                echo "</script>\n";
821
822
                echo "<table>\n";
823
824
                // Output table header
825
                echo "<tr><th class=\"data\">{$lang['strshow']}</th><th class=\"data\">{$lang['strcolumn']}</th>";
826
                echo "<th class=\"data\">{$lang['strtype']}</th><th class=\"data\">{$lang['stroperator']}</th>";
827
                echo "<th class=\"data\">{$lang['strvalue']}</th></tr>";
828
829
                $i = 0;
830
                while (!$attrs->EOF) {
831
                    $attrs->fields['attnotnull'] = $data->phpBool($attrs->fields['attnotnull']);
832
                    // Set up default value if there isn't one already
833
                    if (!isset($_REQUEST['values'][$attrs->fields['attname']])) {
834
                        $_REQUEST['values'][$attrs->fields['attname']] = null;
835
                    }
836
837
                    if (!isset($_REQUEST['ops'][$attrs->fields['attname']])) {
838
                        $_REQUEST['ops'][$attrs->fields['attname']] = null;
839
                    }
840
841
                    // Continue drawing row
842
                    $id = (($i % 2) == 0 ? '1' : '2');
843
                    echo "<tr class=\"data{$id}\">\n";
844
                    echo '<td style="white-space:nowrap;">';
845
                    echo '<input type="checkbox" name="show[', htmlspecialchars($attrs->fields['attname']), ']"',
846
                    isset($_REQUEST['show'][$attrs->fields['attname']]) ? ' checked="checked"' : '', ' /></td>';
847
                    echo '<td style="white-space:nowrap;">', $misc->printVal($attrs->fields['attname']), '</td>';
848
                    echo '<td style="white-space:nowrap;">', $misc->printVal($data->formatType($attrs->fields['type'], $attrs->fields['atttypmod'])), '</td>';
849
                    echo '<td style="white-space:nowrap;">';
850
                    echo "<select name=\"ops[{$attrs->fields['attname']}]\">\n";
851
                    foreach (array_keys($data->selectOps) as $v) {
852
                        echo '<option value="', htmlspecialchars($v), '"', ($v == $_REQUEST['ops'][$attrs->fields['attname']]) ? ' selected="selected"' : '',
853
                        '>', htmlspecialchars($v), "</option>\n";
854
                    }
855
                    echo "</select>\n</td>\n";
856
                    echo '<td style="white-space:nowrap;">', $data->printField("values[{$attrs->fields['attname']}]",
857
                        $_REQUEST['values'][$attrs->fields['attname']], $attrs->fields['type']), '</td>';
858
                    echo "</tr>\n";
859
                    $i++;
860
                    $attrs->moveNext();
861
                }
862
                // Select all checkbox
863
                echo "<tr><td colspan=\"5\"><input type=\"checkbox\" id=\"selectall\" name=\"selectall\" accesskey=\"a\" onclick=\"javascript:selectAll()\" /><label for=\"selectall\">{$lang['strselectallfields']}</label></td>";
864
                echo "</tr></table>\n";
865
            } else {
866
                echo "<p>{$lang['strinvalidparam']}</p>\n";
867
            }
868
869
            echo "<p><input type=\"hidden\" name=\"action\" value=\"selectrows\" />\n";
870
            echo '<input type="hidden" name="table" value="', htmlspecialchars($_REQUEST['table']), "\" />\n";
871
            echo "<input type=\"hidden\" name=\"subject\" value=\"table\" />\n";
872
            echo $misc->form;
873
            echo "<input type=\"submit\" name=\"select\" accesskey=\"r\" value=\"{$lang['strselect']}\" />\n";
874
            echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" /></p>\n";
875
            echo "</form>\n";
876
877
            return;
878 View Code Duplication
        } else {
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...
879
            if (!isset($_POST['show'])) {
880
                $_POST['show'] = [];
881
            }
882
883
            if (!isset($_POST['values'])) {
884
                $_POST['values'] = [];
885
            }
886
887
            if (!isset($_POST['nulls'])) {
888
                $_POST['nulls'] = [];
889
            }
890
891
            // Verify that they haven't supplied a value for unary operators
892
            foreach ($_POST['ops'] as $k => $v) {
893
                if ($data->selectOps[$v] == 'p' && $_POST['values'][$k] != '') {
894
                    $this->doSelectRows(true, $lang['strselectunary']);
895
896
                    return;
897
                }
898
            }
899
900
            if (count($_POST['show']) == 0) {
901
                $this->doSelectRows(true, $lang['strselectneedscol']);
902
            } else {
903
                // Generate query SQL
904
                $query = $data->getSelectSQL($_REQUEST['table'], array_keys($_POST['show']),
905
                    $_POST['values'], $_POST['ops']);
906
                $_REQUEST['query'] = $query;
907
                $_REQUEST['return'] = 'selectrows';
908
909
                $this->setNoOutput(true);
910
911
                $display_controller = new DisplayController($this->getContainer());
912
913
                return $display_controller->render();
914
            }
915
        }
916
    }
917
918
    /**
919
     * Ask for insert parameters and then actually insert row.
920
     */
921
    public function doInsertRow($confirm, $msg = '')
922
    {
923
        $conf = $this->conf;
924
        $misc = $this->misc;
925
        $lang = $this->lang;
926
        $data = $misc->getDatabaseAccessor();
927
928
        if ($confirm) {
929
            $this->printTrail('table');
930
            $this->printTabs('table', 'insert');
931
932
            $this->printMsg($msg);
933
934
            $attrs = $data->getTableAttributes($_REQUEST['table']);
935
936 View Code Duplication
            if (($conf['autocomplete'] != 'disable')) {
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...
937
                $fksprops = $misc->getAutocompleteFKProperties($_REQUEST['table']);
938
                if ($fksprops !== false) {
939
                    echo $fksprops['code'];
940
                }
941
            } else {
942
                $fksprops = false;
943
            }
944
945
            echo '<form action="'.SUBFOLDER."/src/views/tables.php\" method=\"post\" id=\"ac_form\">\n";
946
            if ($attrs->recordCount() > 0) {
947
                echo "<table>\n";
948
949
                // Output table header
950
                echo "<tr><th class=\"data\">{$lang['strcolumn']}</th><th class=\"data\">{$lang['strtype']}</th>";
951
                echo "<th class=\"data\">{$lang['strformat']}</th>";
952
                echo "<th class=\"data\">{$lang['strnull']}</th><th class=\"data\">{$lang['strvalue']}</th></tr>";
953
954
                $i = 0;
955
                $fields = [];
956
                while (!$attrs->EOF) {
957
                    $fields[$attrs->fields['attnum']] = $attrs->fields['attname'];
958
                    $attrs->fields['attnotnull'] = $data->phpBool($attrs->fields['attnotnull']);
959
                    // Set up default value if there isn't one already
960 View Code Duplication
                    if (!isset($_REQUEST['values'][$attrs->fields['attnum']])) {
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...
961
                        $_REQUEST['values'][$attrs->fields['attnum']] = $attrs->fields['adsrc'];
962
                    }
963
964
                    // Default format to 'VALUE' if there is no default,
965
                    // otherwise default to 'EXPRESSION'
966 View Code Duplication
                    if (!isset($_REQUEST['format'][$attrs->fields['attnum']])) {
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...
967
                        $_REQUEST['format'][$attrs->fields['attnum']] = ($attrs->fields['adsrc'] === null) ? 'VALUE' : 'EXPRESSION';
968
                    }
969
970
                    // Continue drawing row
971
                    $id = (($i % 2) == 0 ? '1' : '2');
972
                    echo "<tr class=\"data{$id}\">\n";
973
                    echo '<td style="white-space:nowrap;">', $misc->printVal($attrs->fields['attname']), '</td>';
974
                    echo "<td style=\"white-space:nowrap;\">\n";
975
                    echo $misc->printVal($data->formatType($attrs->fields['type'], $attrs->fields['atttypmod']));
976
                    echo "<input type=\"hidden\" name=\"types[{$attrs->fields['attnum']}]\" value=\"",
977
                    htmlspecialchars($attrs->fields['type']), '" /></td>';
978
                    echo "<td style=\"white-space:nowrap;\">\n";
979
                    echo "<select name=\"format[{$attrs->fields['attnum']}]\">\n";
980
                    echo '<option value="VALUE"', ($_REQUEST['format'][$attrs->fields['attnum']] == 'VALUE') ? ' selected="selected"' : '', ">{$lang['strvalue']}</option>\n";
981
                    echo '<option value="EXPRESSION"', ($_REQUEST['format'][$attrs->fields['attnum']] == 'EXPRESSION') ? ' selected="selected"' : '', ">{$lang['strexpression']}</option>\n";
982
                    echo "</select>\n</td>\n";
983
                    echo '<td style="white-space:nowrap;">';
984
                    // Output null box if the column allows nulls (doesn't look at CHECKs or ASSERTIONS)
985
                    if (!$attrs->fields['attnotnull']) {
986
                        echo "<label><span><input type=\"checkbox\" name=\"nulls[{$attrs->fields['attnum']}]\"",
987
                        isset($_REQUEST['nulls'][$attrs->fields['attnum']]) ? ' checked="checked"' : '', ' /></span></label></td>';
988
                    } else {
989
                        echo '&nbsp;</td>';
990
                    }
991
                    echo "<td id=\"row_att_{$attrs->fields['attnum']}\" style=\"white-space:nowrap;\">";
992
                    if (($fksprops !== false) && isset($fksprops['byfield'][$attrs->fields['attnum']])) {
993
                        echo $data->printField("values[{$attrs->fields['attnum']}]", $_REQUEST['values'][$attrs->fields['attnum']], 'fktype' /*force FK*/,
994
                            [
995
                                'id'           => "attr_{$attrs->fields['attnum']}",
996
                                'autocomplete' => 'off',
997
                            ]
998
                        );
999
                    } else {
1000
                        echo $data->printField("values[{$attrs->fields['attnum']}]", $_REQUEST['values'][$attrs->fields['attnum']], $attrs->fields['type']);
1001
                    }
1002
                    echo "</td>\n";
1003
                    echo "</tr>\n";
1004
                    $i++;
1005
                    $attrs->moveNext();
1006
                }
1007
                echo "</table>\n";
1008
1009
                if (!isset($_SESSION['counter'])) {
1010
                    $_SESSION['counter'] = 0;
1011
                }
1012
1013
                echo "<input type=\"hidden\" name=\"action\" value=\"insertrow\" />\n";
1014
                echo '<input type="hidden" name="fields" value="', htmlentities(serialize($fields), ENT_QUOTES, 'UTF-8'), "\" />\n";
1015
                echo '<input type="hidden" name="protection_counter" value="'.$_SESSION['counter']."\" />\n";
1016
                echo '<input type="hidden" name="table" value="', htmlspecialchars($_REQUEST['table']), "\" />\n";
1017
                echo "<p><input type=\"submit\" name=\"insert\" value=\"{$lang['strinsert']}\" />\n";
1018
                echo "<input type=\"submit\" name=\"insertandrepeat\" accesskey=\"r\" value=\"{$lang['strinsertandrepeat']}\" />\n";
1019
                echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" />\n";
1020
1021 View Code Duplication
                if ($fksprops !== false) {
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...
1022
                    if ($conf['autocomplete'] != 'default off') {
1023
                        echo "<input type=\"checkbox\" id=\"no_ac\" value=\"1\" checked=\"checked\" /><label for=\"no_ac\">{$lang['strac']}</label>\n";
1024
                    } else {
1025
                        echo "<input type=\"checkbox\" id=\"no_ac\" value=\"0\" /><label for=\"no_ac\">{$lang['strac']}</label>\n";
1026
                    }
1027
                }
1028
                echo "</p>\n";
1029
            } else {
1030
                echo "<p>{$lang['strnofieldsforinsert']}</p>\n";
1031
                echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" />\n";
1032
            }
1033
            echo $misc->form;
1034
            echo "</form>\n";
1035
        } else {
1036
            if (!isset($_POST['values'])) {
1037
                $_POST['values'] = [];
1038
            }
1039
1040
            if (!isset($_POST['nulls'])) {
1041
                $_POST['nulls'] = [];
1042
            }
1043
1044
            $_POST['fields'] = unserialize(htmlspecialchars_decode($_POST['fields'], 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 $_POST, and Data is passed through htmlspecialchars_decode()
    in src/controllers/TablesController.php on line 1044

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...
1045
1046
            if ($_SESSION['counter']++ == $_POST['protection_counter']) {
1047
                $status = $data->insertRow($_POST['table'], $_POST['fields'], $_POST['values'], $_POST['nulls'], $_POST['format'], $_POST['types']);
1048
                if ($status == 0) {
1049
                    if (isset($_POST['insert'])) {
1050
                        return $this->doDefault($lang['strrowinserted']);
1051
                    } else {
1052
                        $_REQUEST['values'] = [];
1053
                        $_REQUEST['nulls'] = [];
1054
                        $this->doInsertRow(true, $lang['strrowinserted']);
1055
                    }
1056
                } else {
1057
                    $this->doInsertRow(true, $lang['strrowinsertedbad']);
1058
                }
1059
            } else {
1060
                $this->doInsertRow(true, $lang['strrowduplicate']);
1061
            }
1062
        }
1063
    }
1064
1065
    /**
1066
     * Show confirmation of empty and perform actual empty.
1067
     */
1068
    public function doEmpty($confirm)
1069
    {
1070
        $conf = $this->conf;
1071
        $misc = $this->misc;
1072
        $lang = $this->lang;
1073
        $data = $misc->getDatabaseAccessor();
1074
1075 View Code Duplication
        if (empty($_REQUEST['table']) && empty($_REQUEST['ma'])) {
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...
1076
            return $this->doDefault($lang['strspecifytabletoempty']);
1077
            exit();
1078
        }
1079
1080
        if ($confirm) {
1081 View Code Duplication
            if (isset($_REQUEST['ma'])) {
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...
1082
                $this->printTrail('schema');
1083
                $this->printTitle($lang['strempty'], 'pg.table.empty');
1084
1085
                echo '<form action="'.SUBFOLDER."/src/views/tables.php\" method=\"post\">\n";
1086
                foreach ($_REQUEST['ma'] as $v) {
1087
                    $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/TablesController.php on line 1086
  2. Data is passed through htmlspecialchars_decode()
    in src/controllers/TablesController.php on line 1087

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...
1088
                    echo '<p>', sprintf($lang['strconfemptytable'], $misc->printVal($a['table'])), "</p>\n";
1089
                    printf('<input type="hidden" name="table[]" value="%s" />', htmlspecialchars($a['table']));
1090
                }
1091
            } // END mutli empty
1092
            else {
1093
                $this->printTrail('table');
1094
                $this->printTitle($lang['strempty'], 'pg.table.empty');
1095
1096
                echo '<p>', sprintf($lang['strconfemptytable'], $misc->printVal($_REQUEST['table'])), "</p>\n";
1097
1098
                echo '<form action="'.SUBFOLDER."/src/views/tables.php\" method=\"post\">\n";
1099
                echo '<input type="hidden" name="table" value="', htmlspecialchars($_REQUEST['table']), "\" />\n";
1100
            } // END not mutli empty
1101
1102
            echo "<input type=\"hidden\" name=\"action\" value=\"empty\" />\n";
1103
            echo $misc->form;
1104
            echo "<input type=\"submit\" name=\"empty\" value=\"{$lang['strempty']}\" /> <input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" />\n";
1105
            echo "</form>\n";
1106
        } // END if confirm
1107
        else {
1108
            // Do Empty
1109
            if (is_array($_REQUEST['table'])) {
1110
                $msg = '';
1111
                foreach ($_REQUEST['table'] as $t) {
1112
                    $status = $data->emptyTable($t);
1113
                    if ($status == 0) {
1114
                        $msg .= sprintf('%s: %s<br />', htmlentities($t, ENT_QUOTES, 'UTF-8'), $lang['strtableemptied']);
1115
                    } else {
1116
                        $this->doDefault(sprintf('%s%s: %s<br />', $msg, htmlentities($t, ENT_QUOTES, 'UTF-8'), $lang['strtableemptiedbad']));
1117
1118
                        return;
1119
                    }
1120
                }
1121
                $this->doDefault($msg);
1122
            } // END mutli empty
1123
            else {
1124
                $status = $data->emptyTable($_POST['table']);
1125
                if ($status == 0) {
1126
                    return $this->doDefault($lang['strtableemptied']);
1127
                } else {
1128
                    return $this->doDefault($lang['strtableemptiedbad']);
1129
                }
1130
            } // END not mutli empty
1131
        } // END do Empty
1132
    }
1133
1134
    /**
1135
     * Show confirmation of drop and perform actual drop.
1136
     */
1137
    public function doDrop($confirm)
1138
    {
1139
        $conf = $this->conf;
1140
        $misc = $this->misc;
1141
        $lang = $this->lang;
1142
        $data = $misc->getDatabaseAccessor();
1143
1144 View Code Duplication
        if (empty($_REQUEST['table']) && empty($_REQUEST['ma'])) {
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...
1145
            return $this->doDefault($lang['strspecifytabletodrop']);
1146
            exit();
1147
        }
1148
1149
        if ($confirm) {
1150
            //If multi drop
1151 View Code Duplication
            if (isset($_REQUEST['ma'])) {
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...
1152
                $this->printTrail('schema');
1153
                $this->printTitle($lang['strdrop'], 'pg.table.drop');
1154
1155
                echo '<form action="'.SUBFOLDER."/src/views/tables.php\" method=\"post\">\n";
1156
                foreach ($_REQUEST['ma'] as $v) {
1157
                    $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/TablesController.php on line 1156
  2. Data is passed through htmlspecialchars_decode()
    in src/controllers/TablesController.php on line 1157

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...
1158
                    echo '<p>', sprintf($lang['strconfdroptable'], $misc->printVal($a['table'])), "</p>\n";
1159
                    printf('<input type="hidden" name="table[]" value="%s" />', htmlspecialchars($a['table']));
1160
                }
1161
            } else {
1162
                $this->printTrail('table');
1163
                $this->printTitle($lang['strdrop'], 'pg.table.drop');
1164
1165
                echo '<p>', sprintf($lang['strconfdroptable'], $misc->printVal($_REQUEST['table'])), "</p>\n";
1166
1167
                echo '<form action="'.SUBFOLDER."/src/views/tables.php\" method=\"post\">\n";
1168
                echo '<input type="hidden" name="table" value="', htmlspecialchars($_REQUEST['table']), "\" />\n";
1169
            } // END if multi drop
1170
1171
            echo "<input type=\"hidden\" name=\"action\" value=\"drop\" />\n";
1172
            echo $misc->form;
1173
            echo "<p><input type=\"checkbox\" id=\"cascade\" name=\"cascade\" /> <label for=\"cascade\">{$lang['strcascade']}</label></p>\n";
1174
            echo "<input type=\"submit\" name=\"drop\" value=\"{$lang['strdrop']}\" />\n";
1175
            echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" />\n";
1176
            echo "</form>\n";
1177
        } // END confirm
1178
        else {
1179
            //If multi drop
1180
            if (is_array($_REQUEST['table'])) {
1181
                $msg = '';
1182
                $status = $data->beginTransaction();
1183
                if ($status == 0) {
1184
                    foreach ($_REQUEST['table'] as $t) {
1185
                        $status = $data->dropTable($t, isset($_POST['cascade']));
1186
                        if ($status == 0) {
1187
                            $msg .= sprintf('%s: %s<br />', htmlentities($t, ENT_QUOTES, 'UTF-8'), $lang['strtabledropped']);
1188
                        } else {
1189
                            $data->endTransaction();
1190
1191
                            return $this->doDefault(sprintf('%s%s: %s<br />', $msg, htmlentities($t, ENT_QUOTES, 'UTF-8'), $lang['strtabledroppedbad']));
1192
1193
                            return;
0 ignored issues
show
Unused Code introduced by
return is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
1194
                        }
1195
                    }
1196
                }
1197
                if ($data->endTransaction() == 0) {
1198
                    // Everything went fine, back to the Default page....
1199
                    $misc->setReloadBrowser(true);
1200
1201
                    return $this->doDefault($msg);
1202
                } else {
1203
                    return $this->doDefault($lang['strtabledroppedbad']);
1204
                }
1205
            } else {
1206
                $status = $data->dropTable($_POST['table'], isset($_POST['cascade']));
1207
                if ($status == 0) {
1208
                    $misc->setReloadBrowser(true);
1209
1210
                    return $this->doDefault($lang['strtabledropped']);
1211
                } else {
1212
                    return $this->doDefault($lang['strtabledroppedbad']);
1213
                }
1214
            }
1215
        } // END DROP
1216
    }
1217
1218
    // END Function
1219
}
1220