Passed
Push — develop ( a518ac...108247 )
by Felipe
04:30
created

Misc::setReloadBrowser()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 5
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * PHPPgAdmin v6.0.0-beta.33
5
 */
6
7
namespace PHPPgAdmin;
8
9
use PHPPgAdmin\Decorators\Decorator;
10
11
/**
12
 * @file
13
 * Class to hold various commonly used functions
14
 *
15
 * Id: Misc.php,v 1.171 2008/03/17 21:35:48 ioguix Exp $
16
 * @package PHPPgAdmin
17
 */
18
19
/**
20
 * Class to hold various commonly used functions.
21
 *
22
 * $Id: Misc.php,v 1.171 2008/03/17 21:35:48 ioguix Exp $
23
 *
24
 * @package PHPPgAdmin
25
 */
26
class Misc
27
{
28
    use \PHPPgAdmin\HelperTrait;
29
30
    private $_connection;
31
    private $_no_db_connection = false;
32
    private $_reload_browser   = false;
33
    private $_data;
34
    private $_database;
35
    private $_server_id;
36
    private $_server_info;
37
    private $_error_msg = '';
38
39
    public $appLangFiles    = [];
40
    public $appName         = '';
41
    public $appVersion      = '';
42
    public $form            = '';
43
    public $href            = '';
44
    public $controller_name = 'Misc';
45
    public $lang            = [];
46
47
    protected $container;
48
49
    /**
50
     * @param \Slim\Container $container The container
51
     */
52
    public function __construct(\Slim\Container $container)
53
    {
54
        $this->container = $container;
55
56
        $this->lang = $container->get('lang');
57
        $this->conf = $container->get('conf');
58
        //$this->view           = $container->get('view');
59
        $this->plugin_manager = $container->get('plugin_manager');
60
        $this->appLangFiles   = $container->get('appLangFiles');
61
62
        $this->appName          = $container->get('settings')['appName'];
63
        $this->appVersion       = $container->get('settings')['appVersion'];
64
        $this->postgresqlMinVer = $container->get('settings')['postgresqlMinVer'];
65
        $this->phpMinVer        = $container->get('settings')['phpMinVer'];
66
67
        $base_version = $container->get('settings')['base_version'];
68
69
        // Check for config file version mismatch
70
        if (!isset($this->conf['version']) || $base_version > $this->conf['version']) {
71
            $container->get('utils')->addError($this->lang['strbadconfig']);
72
        }
73
74
        // Check database support is properly compiled in
75
        if (!function_exists('pg_connect')) {
76
            $container->get('utils')->addError($this->lang['strnotloaded']);
77
        }
78
79
        // Check the version of PHP
80
        if (version_compare(phpversion(), $this->phpMinVer, '<')) {
81
            $container->get('utils')->addError(sprintf('Version of PHP not supported. Please upgrade to version %s or later.', $this->phpMinVer));
82
        }
83
84
        if (count($this->conf['servers']) === 1) {
85
            $info             = $this->conf['servers'][0];
86
            $this->_server_id = ($info['host'] . ':' . $info['port'] . ':' . $info['sslmode']);
87
        } elseif (isset($_REQUEST['server'])) {
88
            $this->_server_id = $_REQUEST['server'];
89
        } elseif (isset($_SESSION['webdbLogin']) && count($_SESSION['webdbLogin']) > 0) {
90
            $this->_server_id = array_keys($_SESSION['webdbLogin'])[0];
91
        }
92
    }
93
94
    /**
95
     * Sets the view instance property of this class.
96
     *
97
     * @param \Slim\Views\Twig $view [description]
98
     */
99
    public function setView(\Slim\Views\Twig $view)
100
    {
101
        $this->view = $view;
102
    }
103
104
    /**
105
     * Adds or modifies a key in the $conf instance property of this class.
106
     *
107
     * @param string $key   name of the key to set
108
     * @param mixed  $value value of the key to set
109
     *
110
     * @return $this
111
     */
112
    public function setConf(string $key, $value)
113
    {
114
        $this->conf[$key] = $value;
115
116
        return $this;
117
    }
118
119
    /**
120
     * gets the value of a config property, or the array of all config properties.
1 ignored issue
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
121
     *
122
     * @param mixed $key value of the key to be retrieved. If null, the full array is returnes
123
     *
124
     * @return mixed the whole $conf array, the value of $conf[key] or null if said key does not exist
125
     */
126
    public function getConf($key = null)
127
    {
128
        if ($key === null) {
129
            return $this->conf;
130
        }
131
        if (array_key_exists($key, $this->conf)) {
132
            return $this->conf[$key];
133
        }
134
135
        return null;
136
    }
137
138
    public function getServerId()
139
    {
140
        return $this->_server_id;
141
    }
142
143
    /**
144
     * Displays link to the context help.
145
     *
146
     * @param $str   the string that the context help is related to (already escaped)
147
     * @param $help  help section identifier
148
     * @param $do_print true to echo, false to return
149
     */
150
    public function printHelp($str, $help = null, $do_print = true)
151
    {
152
        //\PC::debug(['str' => $str, 'help' => $help], 'printHelp');
153
        if ($help !== null) {
154
            $helplink = $this->getHelpLink($help);
155
            $str .= '<a class="help" href="' . $helplink . '" title="' . $this->lang['strhelp'] . '" target="phppgadminhelp">' . $this->lang['strhelpicon'] . '</a>';
156
        }
157
        if ($do_print) {
158
            echo $str;
159
        } else {
160
            return $str;
161
        }
162
    }
163
164
    public function getHelpLink($help)
165
    {
166
        return htmlspecialchars(SUBFOLDER . '/help?help=' . urlencode($help) . '&server=' . urlencode($this->getServerId()));
167
    }
168
169
    /**
170
     * Internally sets the reload browser property.
171
     *
172
     * @param bool $flag sets internal $_reload_browser var which will be passed to the footer methods
173
     *
174
     * @return $this
175
     */
176
    public function setReloadBrowser($flag)
177
    {
178
        $this->_reload_browser = (bool) $flag;
179
180
        return $this;
181
    }
182
183
    public function getReloadBrowser()
184
    {
185
        return $this->_reload_browser;
186
    }
187
188
    /**
189
     * Default Error Handler. This will be called with the following params.
190
     *
191
     * @param $dbms         the RDBMS you are connecting to
192
     * @param $fn           the name of the calling function (in uppercase)
193
     * @param $errno        the native error number from the database
194
     * @param $errmsg       the native error msg from the database
195
     * @param $p1           $fn specific parameter - see below
0 ignored issues
show
Coding Style introduced by
Doc comment for parameter $fn does not match actual variable name $p1
Loading history...
196
     * @param $p2           parameter 2
197
     * @param $thisConnection connection
198
     *
199
     * @throws \PHPPgAdmin\ADOdbException
200
     *
201
     * @internal param $P2 $fn specific parameter - see below
202
     */
203
    public static function adodb_throw($dbms, $fn, $errno, $errmsg, $p1, $p2, $thisConnection)
1 ignored issue
show
Coding Style introduced by
Public method name "Misc::adodb_throw" is not in camel caps format
Loading history...
204
    {
205
        if (error_reporting() == 0) {
206
            return;
207
        }
208
209
        $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2);
210
211
        $btarray0 = [
212
            'msg'      => 'ADOdbException at ',
213
            'class'    => $backtrace[1]['class'],
214
            'type'     => $backtrace[1]['type'],
215
            'function' => $backtrace[1]['function'],
216
            'spacer'   => ' ',
217
            'line'     => $backtrace[0]['line'],
218
        ];
219
220
        $errmsg = htmlentities(\PHPPgAdmin\HelperTrait::br2ln($errmsg), ENT_NOQUOTES);
221
        $p1     = htmlentities(\PHPPgAdmin\HelperTrait::br2ln($p1), ENT_NOQUOTES);
222
        $p2     = htmlentities(\PHPPgAdmin\HelperTrait::br2ln($p2), ENT_NOQUOTES);
223
224
        switch ($fn) {
225
            case 'EXECUTE':
226
                $sql = str_replace([
1 ignored issue
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
227
                    'SELECT',
228
                    'WHERE',
229
                    'GROUP BY',
230
                    'FROM',
231
                    'HAVING',
232
                    'LIMIT',
233
                ],
0 ignored issues
show
Coding Style introduced by
This line of the multi-line function call does not seem to be indented correctly. Expected 20 spaces, but found 16.
Loading history...
234
                    ["\nSELECT", "\nWHERE", "\nGROUP BY", "\nFROM", "\nHAVING", "\nLIMIT"],
235
                    $p1);
1 ignored issue
show
Coding Style introduced by
This line of the multi-line function call does not seem to be indented correctly. Expected 16 spaces, but found 20.
Loading history...
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
236
237
                $inputparams = $p2;
238
239
                $error_msg = '<p><b>strsqlerror</b><br />' . nl2br($errmsg) . '</p> <p><b>SQL:</b><br />' . nl2br($sql) . '</p>	';
240
241
                echo '<table class="error" cellpadding="5"><tr><td>' . nl2br($error_msg) . '</td></tr></table><br />' . "\n";
242
243
                break;
244
            case 'PCONNECT':
245
            case 'CONNECT':
246
                // do nothing;
247
                break;
248
            default:
249
                $s = "${dbms} error: [${errno}: ${errmsg}] in ${fn}(${p1}, ${p2})\n";
250
                echo "<table class=\"error\" cellpadding=\"5\"><tr><td>{$s}</td></tr></table><br />\n";
251
252
                break;
253
        }
254
255
        $tag = implode('', $btarray0);
256
257
        \PC::debug(['errno' => $errno, 'fn' => $fn, 'errmsg' => $errmsg], $tag);
258
259
        throw new \PHPPgAdmin\ADOdbException($dbms, $fn, $errno, $errmsg, $p1, $p2, $thisConnection);
260
    }
261
262
    public function getContainer()
263
    {
264
        return $this->container;
265
    }
266
267
    /**
268
     * sets $_no_db_connection boolean value, allows to render scripts that do not need an active session.
1 ignored issue
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
269
     *
270
     * @param bool $flag true or false to allow unconnected clients to access the view
271
     *
272
     * @return $this
273
     */
274
    public function setNoDBConnection($flag)
275
    {
276
        $this->_no_db_connection = (bool) $flag;
277
278
        return $this;
279
    }
280
281
    public function getNoDBConnection()
282
    {
283
        return $this->_no_db_connection;
284
    }
285
286
    /**
287
     * Sets the last error message to display afterwards instead of just dying with the error msg.
288
     *
289
     * @param string $msg error message string
290
     */
291
    public function setErrorMsg($msg)
292
    {
293
        $this->_error_msg = $msg;
294
295
        return $this;
296
    }
297
298
    public function getErrorMsg()
299
    {
300
        return $this->_error_msg;
301
    }
302
303
    /**
304
     * Creates a database accessor.
305
     *
306
     * @param string $database  the name of the database
307
     * @param mixed  $server_id the id of the server
308
     */
309
    public function getDatabaseAccessor($database = '', $server_id = null)
310
    {
311
        $lang = $this->lang;
312
313
        if ($server_id !== null) {
314
            $this->_server_id = $server_id;
315
        }
316
317
        $server_info = $this->getServerInfo($this->_server_id);
318
319
        if ($this->_no_db_connection || !isset($server_info['username'])) {
320
            return null;
321
        }
322
323
        if ($this->_data === null) {
324
            try {
325
                $_connection = $this->getConnection($database, $this->_server_id);
326
            } catch (\Exception $e) {
327
                $this->setServerInfo(null, null, $this->_server_id);
328
                $this->setNoDBConnection(true);
329
                $this->setErrorMsg($e->getMessage());
330
331
                return null;
332
            }
333
334
            //$this->prtrace('_connection', $_connection);
335
            if (!$_connection) {
336
                $this->container->utils->addError($lang['strloginfailed']);
337
                $this->setErrorMsg($lang['strloginfailed']);
338
339
                return null;
340
            }
341
            // Get the name of the database driver we need to use.
342
            // The description of the server is returned in $platform.
343
            $_type = $_connection->getDriver($platform);
344
345
            //$this->prtrace(['type' => $_type, 'platform' => $platform, 'pgVersion' => $_connection->conn->pgVersion]);
346
347
            if ($_type === null) {
348
                $errormsg = sprintf($lang['strpostgresqlversionnotsupported'], $this->postgresqlMinVer);
349
                $this->container->utils->addError($errormsg);
350
                $this->setErrorMsg($errormsg);
351
352
                return null;
353
            }
354
            $_type = '\PHPPgAdmin\Database\\' . $_type;
355
356
            $this->setServerInfo('platform', $platform, $this->_server_id);
357
            $this->setServerInfo('pgVersion', $_connection->conn->pgVersion, $this->_server_id);
358
359
            // Create a database wrapper class for easy manipulation of the
360
            // connection.
361
362
            $this->_data              = new $_type($_connection->conn, $this->conf);
363
            $this->_data->platform    = $_connection->platform;
364
            $this->_data->server_info = $server_info;
365
            $this->_data->conf        = $this->conf;
366
            $this->_data->lang        = $this->lang;
367
368
            //$this->_data->getHelpPages();
369
370
            //$this->prtrace('help_page has ' . count($this->_data->help_page) . ' items');
371
372
            /* we work on UTF-8 only encoding */
373
            $this->_data->execute("SET client_encoding TO 'UTF-8'");
374
375
            if ($this->_data->hasByteaHexDefault()) {
376
                $this->_data->execute('SET bytea_output TO escape');
377
            }
378
        }
379
380
        if ($this->_no_db_connection === false && $this->getDatabase() !== null && isset($_REQUEST['schema'])) {
381
            $status = $this->_data->setSchema($_REQUEST['schema']);
382
383
            if ($status != 0) {
384
                $this->container->utils->addError($this->lang['strbadschema']);
385
                $this->setErrorMsg($this->lang['strbadschema']);
386
387
                return null;
388
            }
389
        }
390
391
        return $this->_data;
392
    }
393
394
    public function getConnection($database = '', $server_id = null)
395
    {
396
        $lang = $this->lang;
397
398
        if ($this->_connection === null) {
399
            if ($server_id !== null) {
400
                $this->_server_id = $server_id;
401
            }
402
            $server_info     = $this->getServerInfo($this->_server_id);
403
            $database_to_use = $this->getDatabase($database);
404
405
            // Perform extra security checks if this config option is set
406
            if ($this->conf['extra_login_security']) {
407
                // Disallowed logins if extra_login_security is enabled.
408
                // These must be lowercase.
409
                $bad_usernames = [
410
                    'pgsql'         => 'pgsql',
411
                    'postgres'      => 'postgres',
412
                    'root'          => 'root',
413
                    'administrator' => 'administrator',
414
                ];
415
416
                if (isset($server_info['username']) && array_key_exists(strtolower($server_info['username']), $bad_usernames)) {
417
                    $msg = $lang['strlogindisallowed'];
418
419
                    throw new \Exception($msg);
420
                }
421
422
                if (!isset($server_info['password']) || $server_info['password'] == '') {
423
                    $msg = $lang['strlogindisallowed'];
424
425
                    throw new \Exception($msg);
426
                }
427
            }
428
429
            try {
430
                // Create the connection object and make the connection
431
                $this->_connection = new \PHPPgAdmin\Database\Connection(
432
                    $server_info['host'],
433
                    $server_info['port'],
434
                    $server_info['sslmode'],
435
                    $server_info['username'],
436
                    $server_info['password'],
437
                    $database_to_use
438
                );
439
            } catch (\PHPPgAdmin\ADOdbException $e) {
440
                throw new \Exception($lang['strloginfailed']);
441
            }
442
        }
443
444
        return $this->_connection;
445
    }
446
447
    /**
448
     * Validate and retrieve information on a server.
449
     * If the parameter isn't supplied then the currently
450
     * connected server is returned.
451
     *
452
     * @param $server_id A server identifier (host:port)
453
     *
454
     * @return An associative array of server properties
455
     */
456
    public function getServerInfo($server_id = null)
457
    {
458
        //\PC::debug(['$server_id' => $server_id]);
459
460
        if ($server_id !== null) {
461
            $this->_server_id = $server_id;
462
        } elseif ($this->_server_info !== null) {
463
            return $this->_server_info;
464
        }
465
466
        // Check for the server in the logged-in list
467
        if (isset($_SESSION['webdbLogin'][$this->_server_id])) {
468
            $this->_server_info = $_SESSION['webdbLogin'][$this->_server_id];
469
470
            return $this->_server_info;
471
        }
472
473
        // Otherwise, look for it in the conf file
474
        foreach ($this->conf['servers'] as $idx => $info) {
475
            $server_string = $info['host'] . ':' . $info['port'] . ':' . $info['sslmode'];
476
            $server_sha    = sha1($server_string);
477
478
            if ($this->_server_id == $server_string || $this->_server_id == $server_sha) {
479
                $this->prtrace($server_sha);
480
                if (isset($info['username'])) {
481
                    $this->setServerInfo(null, $info, $this->_server_id);
482
                } elseif (isset($_SESSION['sharedUsername'])) {
483
                    $info['username'] = $_SESSION['sharedUsername'];
484
                    $info['password'] = $_SESSION['sharedPassword'];
485
                    $this->setReloadBrowser(true);
486
                    $this->setServerInfo(null, $info, $this->_server_id);
487
                }
488
                $this->_server_info = $info;
489
490
                return $this->_server_info;
491
            }
492
        }
493
494
        if ($server_id === null) {
495
            $this->_server_info = null;
496
497
            return $this->_server_info;
498
        }
499
500
        $this->prtrace('Invalid server param');
501
        $this->_server_info = null;
502
        // Unable to find a matching server, are we being hacked?
503
        return $this->halt($this->lang['strinvalidserverparam']);
504
    }
505
506
    /**
507
     * Set server information.
508
     *
509
     * @param $key parameter name to set, or null to replace all
510
     *             params with the assoc-array in $value
511
     * @param $value the new value, or null to unset the parameter
512
     * @param $server_id the server identifier, or null for current server
513
     */
514
    public function setServerInfo($key, $value, $server_id = null)
515
    {
516
        //\PC::debug('setsetverinfo');
517
        if ($server_id === null && isset($_REQUEST['server'])) {
518
            $server_id = $_REQUEST['server'];
519
        }
520
521
        if ($key === null) {
522
            if ($value === null) {
523
                unset($_SESSION['webdbLogin'][$server_id]);
524
            } else {
525
                //\PC::debug(['server_id' => $server_id, 'value' => $value], 'webdbLogin null key');
526
                $_SESSION['webdbLogin'][$server_id] = $value;
527
            }
528
        } else {
529
            if ($value === null) {
530
                unset($_SESSION['webdbLogin'][$server_id][$key]);
531
            } else {
532
                //\PC::debug(['server_id' => $server_id, 'key' => $key, 'value' => $value], __FILE__ . ' ' . __LINE__ . ' webdbLogin key ' . $key);
533
                $_SESSION['webdbLogin'][$server_id][$key] = $value;
534
            }
535
        }
536
    }
537
538
    public function getDatabase($database = '')
539
    {
540
        if ($this->_server_id === null && !isset($_REQUEST['database'])) {
541
            return null;
542
        }
543
544
        $server_info = $this->getServerInfo($this->_server_id);
545
546
        if ($this->_server_id !== null && isset($server_info['useonlydefaultdb']) && $server_info['useonlydefaultdb'] === true) {
547
            $this->_database = $server_info['defaultdb'];
548
        } elseif ($database !== '') {
549
            $this->_database = $database;
550
        } elseif (isset($_REQUEST['database'])) {
551
            // Connect to the current database
552
            $this->_database = $_REQUEST['database'];
553
        } else {
554
            // or if one is not specified then connect to the default database.
555
            $this->_database = $server_info['defaultdb'];
556
        }
557
558
        return $this->_database;
559
    }
560
561
    /**
562
     * Get list of servers.
563
     *
564
     * @param bool  $recordset return as RecordSet suitable for HTMLTableController::printTable if true, otherwise just return an array
565
     * @param mixed $group     a group name to filter the returned servers using $this->conf[srv_groups]
566
     *
567
     * @return array|\PHPPgAdmin\ArrayRecordSet either an array or a Recordset suitable for HTMLTableController::printTable
568
     */
569
    public function getServers($recordset = false, $group = false)
570
    {
571
        $logins = isset($_SESSION['webdbLogin']) && is_array($_SESSION['webdbLogin']) ? $_SESSION['webdbLogin'] : [];
572
        $srvs   = [];
573
574
        if (($group !== false) && ($group !== 'all')) {
575
            if (isset($this->conf['srv_groups'][$group]['servers'])) {
576
                $group = array_fill_keys(explode(',', preg_replace(
1 ignored issue
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
577
                    '/\s/',
578
                    '',
579
                    $this->conf['srv_groups'][$group]['servers']
580
                )), 1);
1 ignored issue
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
581
            } else {
582
                $group = '';
583
            }
584
        }
585
586
        foreach ($this->conf['servers'] as $idx => $info) {
587
            $server_id = $info['host'] . ':' . $info['port'] . ':' . $info['sslmode'];
588
            if ($group === false || isset($group[$idx]) || ($group === 'all')) {
589
                $server_id = $info['host'] . ':' . $info['port'] . ':' . $info['sslmode'];
590
591
                if (isset($logins[$server_id])) {
592
                    $srvs[$server_id] = $logins[$server_id];
593
                } else {
594
                    $srvs[$server_id] = $info;
595
                }
596
597
                $srvs[$server_id]['id']     = $server_id;
598
                $srvs[$server_id]['action'] = Decorator::url(
599
                    '/redirect/server',
600
                    [
601
                        'server' => Decorator::field('id'),
602
                    ]
603
                );
604
                if (isset($srvs[$server_id]['username'])) {
605
                    $srvs[$server_id]['icon']   = 'Server';
606
                    $srvs[$server_id]['branch'] = Decorator::url(
607
                        '/src/views/alldb',
608
                        [
609
                            'action'  => 'tree',
610
                            'subject' => 'server',
611
                            'server'  => Decorator::field('id'),
612
                        ]
613
                    );
614
                } else {
615
                    $srvs[$server_id]['icon']   = 'DisconnectedServer';
616
                    $srvs[$server_id]['branch'] = false;
617
                }
618
            }
619
        }
620
621
        uasort($srvs, ['self', '_cmp_desc']);
622
623
        if ($recordset) {
624
            return new ArrayRecordSet($srvs);
625
        }
626
627
        return $srvs;
628
    }
629
630
    /**
631
     * Set the current schema.
632
     *
633
     * @param $schema The schema name
634
     *
635
     * @return int 0 on success
636
     */
637
    public function setCurrentSchema($schema)
638
    {
639
        $data = $this->getDatabaseAccessor();
640
641
        $status = $data->setSchema($schema);
642
        if ($status != 0) {
643
            return $status;
644
        }
645
646
        $_REQUEST['schema'] = $schema;
647
        $this->container->offsetSet('schema', $schema);
648
        $this->setHREF();
649
650
        return 0;
651
    }
652
653
    public static function _cmp_desc($a, $b)
1 ignored issue
show
Coding Style introduced by
Public method name "Misc::_cmp_desc" must not be prefixed with an underscore
Loading history...
654
    {
655
        return strcmp($a['desc'], $b['desc']);
656
    }
657
658
    /**
659
     * Checks if dumps are properly set up.
660
     *
661
     * @param $all (optional) True to check pg_dumpall, false to just check pg_dump
662
     *
663
     * @return True, dumps are set up, false otherwise
664
     */
665
    public function isDumpEnabled($all = false)
666
    {
667
        $info = $this->getServerInfo();
668
669
        return !empty($info[$all ? 'pg_dumpall_path' : 'pg_dump_path']);
670
    }
671
672
    /**
673
     * Sets the href tracking variable.
674
     */
675
    public function setHREF()
676
    {
677
        $this->href = $this->getHREF();
678
        //\PC::debug($this->href, 'Misc::href');
679
        return $this;
680
    }
681
682
    /**
683
     * Get a href query string, excluding objects below the given object type (inclusive).
684
     *
685
     * @param null|string $exclude_from
686
     *
687
     * @return string
688
     */
689
    public function getHREF($exclude_from = null)
690
    {
691
        $href = [];
692
693
        $server   = $this->container->server || isset($_REQUEST['server']) ? $_REQUEST['server'] : null;
694
        $database = $this->container->database || isset($_REQUEST['database']) ? $_REQUEST['database'] : null;
695
        $schema   = $this->container->schema || isset($_REQUEST['schema']) ? $_REQUEST['schema'] : null;
696
697
        if ($server && $exclude_from !== 'server') {
698
            $href[] = 'server=' . urlencode($server);
699
        }
700
        if ($database && $exclude_from !== 'database') {
701
            $href[] = 'database=' . urlencode($database);
702
        }
703
        if ($schema && $exclude_from !== 'schema') {
704
            $href[] = 'schema=' . urlencode($schema);
705
        }
706
707
        $this->href = htmlentities(implode('&', $href));
708
        return $this->href;
709
    }
710
711
    public function getSubjectParams($subject)
712
    {
713
        $plugin_manager = $this->plugin_manager;
714
715
        $vars = [];
716
717
        switch ($subject) {
718
            case 'root':
719
                $vars = [
720
                    'params' => [
721
                        'subject' => 'root',
722
                    ],
723
                ];
724
725
                break;
726
            case 'server':
727
                $vars = ['params' => [
728
                    'server'  => $_REQUEST['server'],
729
                    'subject' => 'server',
730
                ]];
731
732
                break;
733
            case 'role':
734
                $vars = ['params' => [
735
                    'server'   => $_REQUEST['server'],
736
                    'subject'  => 'role',
737
                    'action'   => 'properties',
738
                    'rolename' => $_REQUEST['rolename'],
739
                ]];
740
741
                break;
742
            case 'database':
743
                $vars = ['params' => [
744
                    'server'   => $_REQUEST['server'],
745
                    'subject'  => 'database',
746
                    'database' => $_REQUEST['database'],
747
                ]];
748
749
                break;
750
            case 'schema':
751
                $vars = ['params' => [
752
                    'server'   => $_REQUEST['server'],
753
                    'subject'  => 'schema',
754
                    'database' => $_REQUEST['database'],
755
                    'schema'   => $_REQUEST['schema'],
756
                ]];
757
758
                break;
759
            case 'table':
760
                $vars = ['params' => [
761
                    'server'   => $_REQUEST['server'],
762
                    'subject'  => 'table',
763
                    'database' => $_REQUEST['database'],
764
                    'schema'   => $_REQUEST['schema'],
765
                    'table'    => $_REQUEST['table'],
766
                ]];
767
768
                break;
769
            case 'selectrows':
770
                $vars = [
771
                    'url'    => 'tables',
772
                    'params' => [
773
                        'server'   => $_REQUEST['server'],
774
                        'subject'  => 'table',
775
                        'database' => $_REQUEST['database'],
776
                        'schema'   => $_REQUEST['schema'],
777
                        'table'    => $_REQUEST['table'],
778
                        'action'   => 'confselectrows',
779
                    ]];
780
781
                break;
782
            case 'view':
783
                $vars = ['params' => [
784
                    'server'   => $_REQUEST['server'],
785
                    'subject'  => 'view',
786
                    'database' => $_REQUEST['database'],
787
                    'schema'   => $_REQUEST['schema'],
788
                    'view'     => $_REQUEST['view'],
789
                ]];
790
791
                break;
792
            case 'matview':
793
                $vars = ['params' => [
794
                    'server'   => $_REQUEST['server'],
795
                    'subject'  => 'matview',
796
                    'database' => $_REQUEST['database'],
797
                    'schema'   => $_REQUEST['schema'],
798
                    'matview'  => $_REQUEST['matview'],
799
                ]];
800
801
                break;
802
            case 'fulltext':
803
            case 'ftscfg':
804
                $vars = ['params' => [
805
                    'server'   => $_REQUEST['server'],
806
                    'subject'  => 'fulltext',
807
                    'database' => $_REQUEST['database'],
808
                    'schema'   => $_REQUEST['schema'],
809
                    'action'   => 'viewconfig',
810
                    'ftscfg'   => $_REQUEST['ftscfg'],
811
                ]];
812
813
                break;
814
            case 'function':
815
                $vars = ['params' => [
816
                    'server'       => $_REQUEST['server'],
817
                    'subject'      => 'function',
818
                    'database'     => $_REQUEST['database'],
819
                    'schema'       => $_REQUEST['schema'],
820
                    'function'     => $_REQUEST['function'],
821
                    'function_oid' => $_REQUEST['function_oid'],
822
                ]];
823
824
                break;
825
            case 'aggregate':
826
                $vars = ['params' => [
827
                    'server'   => $_REQUEST['server'],
828
                    'subject'  => 'aggregate',
829
                    'action'   => 'properties',
830
                    'database' => $_REQUEST['database'],
831
                    'schema'   => $_REQUEST['schema'],
832
                    'aggrname' => $_REQUEST['aggrname'],
833
                    'aggrtype' => $_REQUEST['aggrtype'],
834
                ]];
835
836
                break;
837
            case 'column':
838
                if (isset($_REQUEST['table'])) {
839
                    $vars = ['params' => [
840
                        'server'   => $_REQUEST['server'],
841
                        'subject'  => 'column',
842
                        'database' => $_REQUEST['database'],
843
                        'schema'   => $_REQUEST['schema'],
844
                        'table'    => $_REQUEST['table'],
845
                        'column'   => $_REQUEST['column'],
846
                    ]];
847
                } else {
848
                    $vars = ['params' => [
849
                        'server'   => $_REQUEST['server'],
850
                        'subject'  => 'column',
851
                        'database' => $_REQUEST['database'],
852
                        'schema'   => $_REQUEST['schema'],
853
                        'view'     => $_REQUEST['view'],
854
                        'column'   => $_REQUEST['column'],
855
                    ]];
856
                }
857
858
                break;
859
            case 'plugin':
860
                $vars = [
861
                    'url'    => 'plugin',
862
                    'params' => [
863
                        'server'  => $_REQUEST['server'],
864
                        'subject' => 'plugin',
865
                        'plugin'  => $_REQUEST['plugin'],
866
                    ]];
867
868
                if (!is_null($plugin_manager->getPlugin($_REQUEST['plugin']))) {
869
                    $vars['params'] = array_merge($vars['params'], $plugin_manager->getPlugin($_REQUEST['plugin'])->get_subject_params());
870
                }
871
872
                break;
873
            default:
874
                return false;
875
        }
876
877
        if (!isset($vars['url'])) {
878
            $vars['url'] = SUBFOLDER . '/redirect';
879
        }
880
        if ($vars['url'] == SUBFOLDER . '/redirect' && isset($vars['params']['subject'])) {
881
            $vars['url'] = SUBFOLDER . '/redirect/' . $vars['params']['subject'];
882
            unset($vars['params']['subject']);
883
        }
884
885
        return $vars;
886
    }
887
888
    /**
889
     * Sets the form tracking variable.
890
     */
891
    public function setForm()
892
    {
893
        $form = [];
894
        if ($this->container->server) {
895
            $form[] = '<input type="hidden" name="server" value="' . htmlspecialchars($this->container->server) . '" />';
896
        }
897
        if ($this->container->database) {
898
            $form[] = '<input type="hidden" name="database" value="' . htmlspecialchars($this->container->database) . '" />';
899
        }
900
901
        if ($this->container->schema) {
902
            $form[] = '<input type="hidden" name="schema" value="' . htmlspecialchars($this->container->schema) . '" />';
903
        }
904
        $this->form = implode("\n", $form);
905
906
        return $this->form;
907
        //\PC::debug($this->form, 'Misc::form');
908
    }
909
910
    /**
911
     * Render a value into HTML using formatting rules specified
912
     * by a type name and parameters.
913
     *
914
     * @param                        $str    The string to change
915
     * @param                        $type   Field type (optional), this may be an internal PostgreSQL type, or:
916
     *                                       yesno    - same as bool, but renders as 'Yes' or 'No'.
917
     *                                       pre      - render in a <pre> block.
918
     *                                       nbsp     - replace all spaces with &nbsp;'s
919
     *                                       verbatim - render exactly as supplied, no escaping what-so-ever.
920
     *                                       callback - render using a callback function supplied in the 'function' param.
921
     * @param array $params Type parameters (optional), known parameters:
922
     *                                       null     - string to display if $str is null, or set to TRUE to use a default 'NULL' string,
923
     *                                       otherwise nothing is rendered.
924
     *                                       clip     - if true, clip the value to a fixed length, and append an ellipsis...
925
     *                                       cliplen  - the maximum length when clip is enabled (defaults to $conf['max_chars'])
926
     *                                       ellipsis - the string to append to a clipped value (defaults to $lang['strellipsis'])
927
     *                                       tag      - an HTML element name to surround the value.
928
     *                                       class    - a class attribute to apply to any surrounding HTML element.
929
     *                                       align    - an align attribute ('left','right','center' etc.)
930
     *                                       true     - (type='bool') the representation of true.
931
     *                                       false    - (type='bool') the representation of false.
932
     *                                       function - (type='callback') a function name, accepts args ($str, $params) and returns a rendering.
933
     *                                       lineno   - prefix each line with a line number.
934
     *                                       map      - an associative array.
935
     *
936
     * @return string The HTML rendered value
937
     */
938
    public function printVal($str, $type = null, $params = [])
939
    {
940
        $lang = $this->lang;
941
        $data = $this->getDatabaseAccessor();
942
943
        // Shortcircuit for a NULL value
944
        if (is_null($str)) {
945
            return isset($params['null'])
946
            ? ($params['null'] === true ? '<i>NULL</i>' : $params['null'])
947
            : '';
948
        }
949
950
        if (isset($params['map'], $params['map'][$str])) {
951
            $str = $params['map'][$str];
952
        }
953
954
        // Clip the value if the 'clip' parameter is true.
955
        if (isset($params['clip']) && $params['clip'] === true) {
956
            $maxlen   = isset($params['cliplen']) && is_integer($params['cliplen']) ? $params['cliplen'] : $this->conf['max_chars'];
957
            $ellipsis = isset($params['ellipsis']) ? $params['ellipsis'] : $lang['strellipsis'];
958
            if (strlen($str) > $maxlen) {
959
                $str = substr($str, 0, $maxlen - 1) . $ellipsis;
960
            }
961
        }
962
963
        $out = '';
964
965
        switch ($type) {
966
            case 'int2':
967
            case 'int4':
968
            case 'int8':
969
            case 'float4':
970
            case 'float8':
971
            case 'money':
972
            case 'numeric':
973
            case 'oid':
974
            case 'xid':
975
            case 'cid':
976
            case 'tid':
977
                $align = 'right';
978
                $out   = nl2br(htmlspecialchars(\PHPPgAdmin\HelperTrait::br2ln($str)));
979
980
                break;
981
            case 'yesno':
982
                if (!isset($params['true'])) {
983
                    $params['true'] = $lang['stryes'];
984
                }
985
986
                if (!isset($params['false'])) {
987
                    $params['false'] = $lang['strno'];
988
                }
989
990
            // no break - fall through to boolean case.
991
            case 'bool':
992
            case 'boolean':
993
                if (is_bool($str)) {
994
                    $str = $str ? 't' : 'f';
995
                }
996
997
                switch ($str) {
998
                    case 't':
999
                        $out   = (isset($params['true']) ? $params['true'] : $lang['strtrue']);
1000
                        $align = 'center';
1001
1002
                        break;
1003
                    case 'f':
1004
                        $out   = (isset($params['false']) ? $params['false'] : $lang['strfalse']);
1005
                        $align = 'center';
1006
1007
                        break;
1008
                    default:
1009
                        $out = htmlspecialchars($str);
1010
                }
1011
1012
                break;
1013
            case 'bytea':
1014
                $tag   = 'div';
1015
                $class = 'pre';
1016
                $out   = $data->escapeBytea($str);
1017
1018
                break;
1019
            case 'errormsg':
1020
                $tag   = 'pre';
1021
                $class = 'error';
1022
                $out   = htmlspecialchars($str);
1023
1024
                break;
1025
            case 'pre':
1026
                $tag = 'pre';
1027
                $out = htmlspecialchars($str);
1028
1029
                break;
1030
            case 'prenoescape':
1031
                $tag = 'pre';
1032
                $out = $str;
1033
1034
                break;
1035
            case 'nbsp':
1036
                $out = nl2br(str_replace(' ', '&nbsp;', \PHPPgAdmin\HelperTrait::br2ln($str)));
1037
1038
                break;
1039
            case 'verbatim':
1040
                $out = $str;
1041
1042
                break;
1043
            case 'callback':
1044
                $out = $params['function']($str, $params);
1045
1046
                break;
1047
            case 'prettysize':
1048
                if ($str == -1) {
1049
                    $out = $lang['strnoaccess'];
1050
                } else {
1051
                    $limit = 10 * 1024;
1052
                    $mult  = 1;
1053
                    if ($str < $limit * $mult) {
1054
                        $out = $str . ' ' . $lang['strbytes'];
1055
                    } else {
1056
                        $mult *= 1024;
1057
                        if ($str < $limit * $mult) {
1058
                            $out = floor(($str + $mult / 2) / $mult) . ' ' . $lang['strkb'];
1059
                        } else {
1060
                            $mult *= 1024;
1061
                            if ($str < $limit * $mult) {
1062
                                $out = floor(($str + $mult / 2) / $mult) . ' ' . $lang['strmb'];
1063
                            } else {
1064
                                $mult *= 1024;
1065
                                if ($str < $limit * $mult) {
1066
                                    $out = floor(($str + $mult / 2) / $mult) . ' ' . $lang['strgb'];
1067
                                } else {
1068
                                    $mult *= 1024;
1069
                                    if ($str < $limit * $mult) {
1070
                                        $out = floor(($str + $mult / 2) / $mult) . ' ' . $lang['strtb'];
1071
                                    }
1072
                                }
1073
                            }
1074
                        }
1075
                    }
1076
                }
1077
1078
                break;
1079
            default:
1080
                // If the string contains at least one instance of >1 space in a row, a tab
1081
                // character, a space at the start of a line, or a space at the start of
1082
                // the whole string then render within a pre-formatted element (<pre>).
1083
                if (preg_match('/(^ |  |\t|\n )/m', $str)) {
1084
                    $tag   = 'pre';
1085
                    $class = 'data';
1086
                    $out   = htmlspecialchars($str);
1087
                } else {
1088
                    $out = nl2br(htmlspecialchars(\PHPPgAdmin\HelperTrait::br2ln($str)));
1089
                }
1090
        }
1091
1092
        if (isset($params['class'])) {
1093
            $class = $params['class'];
1094
        }
1095
1096
        if (isset($params['align'])) {
1097
            $align = $params['align'];
1098
        }
1099
1100
        if (!isset($tag) && (isset($class) || isset($align))) {
1101
            $tag = 'div';
1102
        }
1103
1104
        if (isset($tag)) {
1105
            $alignattr = isset($align) ? " style=\"text-align: {$align}\"" : '';
1106
            $classattr = isset($class) ? " class=\"{$class}\"" : '';
1107
            $out       = "<{$tag}{$alignattr}{$classattr}>{$out}</{$tag}>";
1108
        }
1109
1110
        // Add line numbers if 'lineno' param is true
1111
        if (isset($params['lineno']) && $params['lineno'] === true) {
1112
            $lines = explode("\n", $str);
1113
            $num   = count($lines);
1114
            if ($num > 0) {
1115
                $temp = "<table>\n<tr><td class=\"{$class}\" style=\"vertical-align: top; padding-right: 10px;\"><pre class=\"{$class}\">";
1116
                for ($i = 1; $i <= $num; ++$i) {
1117
                    $temp .= $i . "\n";
1118
                }
1119
                $temp .= "</pre></td><td class=\"{$class}\" style=\"vertical-align: top;\">{$out}</td></tr></table>\n";
1120
                $out = $temp;
1121
            }
1122
            unset($lines);
1123
        }
1124
1125
        return $out;
1126
    }
1127
1128
    /**
1129
     * A function to recursively strip slashes.  Used to
1130
     * enforce magic_quotes_gpc being off.
1131
     *
1132
     * @param &var The variable to strip
1133
     */
1134
    public function stripVar(&$var)
1135
    {
1136
        if (is_array($var)) {
1137
            foreach ($var as $k => $v) {
1138
                $this->stripVar($var[$k]);
1139
1140
                /* magic_quotes_gpc escape keys as well ...*/
1141
                if (is_string($k)) {
1142
                    $ek = stripslashes($k);
1143
                    if ($ek !== $k) {
1144
                        $var[$ek] = $var[$k];
1145
                        unset($var[$k]);
1146
                    }
1147
                }
1148
            }
1149
        } else {
1150
            $var = stripslashes($var);
1151
        }
1152
    }
1153
1154
    /**
1155
     * Retrieve the tab info for a specific tab bar.
1156
     *
1157
     * @param $section the name of the tab bar
1158
     *
1159
     * @return array
1160
     */
1161
    public function getNavTabs($section)
1162
    {
1163
        $data           = $this->getDatabaseAccessor();
1164
        $lang           = $this->lang;
1165
        $plugin_manager = $this->plugin_manager;
1166
1167
        $hide_advanced = ($this->conf['show_advanced'] === false);
1168
        $tabs          = [];
1169
1170
        switch ($section) {
1171
            case 'root':
1172
                $tabs = [
1173
                    'intro'   => [
1174
                        'title' => $lang['strintroduction'],
1175
                        'url'   => 'intro',
1176
                        'icon'  => 'Introduction',
1177
                    ],
1178
                    'servers' => [
1179
                        'title' => $lang['strservers'],
1180
                        'url'   => 'servers',
1181
                        'icon'  => 'Servers',
1182
                    ],
1183
                ];
1184
1185
                break;
1186
            case 'server':
1187
                $hide_users = true;
1188
                if ($data) {
1189
                    $hide_users = !$data->isSuperUser();
1190
                }
1191
1192
                $tabs = [
1193
                    'databases' => [
1194
                        'title'   => $lang['strdatabases'],
1195
                        'url'     => 'alldb',
1196
                        'urlvars' => ['subject' => 'server'],
1197
                        'help'    => 'pg.database',
1198
                        'icon'    => 'Databases',
1199
                    ],
1200
                ];
1201
                if ($data && $data->hasRoles()) {
1202
                    $tabs = array_merge($tabs, [
1 ignored issue
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
1203
                        'roles' => [
1204
                            'title'   => $lang['strroles'],
1205
                            'url'     => 'roles',
1206
                            'urlvars' => ['subject' => 'server'],
1207
                            'hide'    => $hide_users,
1208
                            'help'    => 'pg.role',
1209
                            'icon'    => 'Roles',
1210
                        ],
1211
                    ]);
1 ignored issue
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
1212
                } else {
1213
                    $tabs = array_merge($tabs, [
1 ignored issue
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
1214
                        'users'  => [
1215
                            'title'   => $lang['strusers'],
1216
                            'url'     => 'users',
1217
                            'urlvars' => ['subject' => 'server'],
1218
                            'hide'    => $hide_users,
1219
                            'help'    => 'pg.user',
1220
                            'icon'    => 'Users',
1221
                        ],
1222
                        'groups' => [
1223
                            'title'   => $lang['strgroups'],
1224
                            'url'     => 'groups',
1225
                            'urlvars' => ['subject' => 'server'],
1226
                            'hide'    => $hide_users,
1227
                            'help'    => 'pg.group',
1228
                            'icon'    => 'UserGroups',
1229
                        ],
1230
                    ]);
1 ignored issue
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
1231
                }
1232
1233
                $tabs = array_merge($tabs, [
1 ignored issue
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
1234
                    'account'     => [
1235
                        'title'   => $lang['straccount'],
1236
                        'url'     => ($data && $data->hasRoles()) ? 'roles' : 'users',
1237
                        'urlvars' => ['subject' => 'server', 'action' => 'account'],
1238
                        'hide'    => !$hide_users,
1239
                        'help'    => 'pg.role',
1240
                        'icon'    => 'User',
1241
                    ],
1242
                    'tablespaces' => [
1243
                        'title'   => $lang['strtablespaces'],
1244
                        'url'     => 'tablespaces',
1245
                        'urlvars' => ['subject' => 'server'],
1246
                        'hide'    => !$data || !$data->hasTablespaces(),
1247
                        'help'    => 'pg.tablespace',
1248
                        'icon'    => 'Tablespaces',
1249
                    ],
1250
                    'export'      => [
1251
                        'title'   => $lang['strexport'],
1252
                        'url'     => 'alldb',
1253
                        'urlvars' => ['subject' => 'server', 'action' => 'export'],
1254
                        'hide'    => !$this->isDumpEnabled(),
1255
                        'icon'    => 'Export',
1256
                    ],
1257
                ]);
1 ignored issue
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
1258
1259
                break;
1260
            case 'database':
1261
                $tabs = [
1262
                    'schemas'    => [
1263
                        'title'   => $lang['strschemas'],
1264
                        'url'     => 'schemas',
1265
                        'urlvars' => ['subject' => 'database'],
1266
                        'help'    => 'pg.schema',
1267
                        'icon'    => 'Schemas',
1268
                    ],
1269
                    'sql'        => [
1270
                        'title'   => $lang['strsql'],
1271
                        'url'     => 'database',
1272
                        'urlvars' => ['subject' => 'database', 'action' => 'sql', 'new' => 1],
1273
                        'help'    => 'pg.sql',
1274
                        'tree'    => false,
1275
                        'icon'    => 'SqlEditor',
1276
                    ],
1277
                    'find'       => [
1278
                        'title'   => $lang['strfind'],
1279
                        'url'     => 'database',
1280
                        'urlvars' => ['subject' => 'database', 'action' => 'find'],
1281
                        'tree'    => false,
1282
                        'icon'    => 'Search',
1283
                    ],
1284
                    'variables'  => [
1285
                        'title'   => $lang['strvariables'],
1286
                        'url'     => 'database',
1287
                        'urlvars' => ['subject' => 'database', 'action' => 'variables'],
1288
                        'help'    => 'pg.variable',
1289
                        'tree'    => false,
1290
                        'icon'    => 'Variables',
1291
                    ],
1292
                    'processes'  => [
1293
                        'title'   => $lang['strprocesses'],
1294
                        'url'     => 'database',
1295
                        'urlvars' => ['subject' => 'database', 'action' => 'processes'],
1296
                        'help'    => 'pg.process',
1297
                        'tree'    => false,
1298
                        'icon'    => 'Processes',
1299
                    ],
1300
                    'locks'      => [
1301
                        'title'   => $lang['strlocks'],
1302
                        'url'     => 'database',
1303
                        'urlvars' => ['subject' => 'database', 'action' => 'locks'],
1304
                        'help'    => 'pg.locks',
1305
                        'tree'    => false,
1306
                        'icon'    => 'Key',
1307
                    ],
1308
                    'admin'      => [
1309
                        'title'   => $lang['stradmin'],
1310
                        'url'     => 'database',
1311
                        'urlvars' => ['subject' => 'database', 'action' => 'admin'],
1312
                        'tree'    => false,
1313
                        'icon'    => 'Admin',
1314
                    ],
1315
                    'privileges' => [
1316
                        'title'   => $lang['strprivileges'],
1317
                        'url'     => 'privileges',
1318
                        'urlvars' => ['subject' => 'database'],
1319
                        'hide'    => !isset($data->privlist['database']),
1320
                        'help'    => 'pg.privilege',
1321
                        'tree'    => false,
1322
                        'icon'    => 'Privileges',
1323
                    ],
1324
                    'languages'  => [
1325
                        'title'   => $lang['strlanguages'],
1326
                        'url'     => 'languages',
1327
                        'urlvars' => ['subject' => 'database'],
1328
                        'hide'    => $hide_advanced,
1329
                        'help'    => 'pg.language',
1330
                        'icon'    => 'Languages',
1331
                    ],
1332
                    'casts'      => [
1333
                        'title'   => $lang['strcasts'],
1334
                        'url'     => 'casts',
1335
                        'urlvars' => ['subject' => 'database'],
1336
                        'hide'    => $hide_advanced,
1337
                        'help'    => 'pg.cast',
1338
                        'icon'    => 'Casts',
1339
                    ],
1340
                    'export'     => [
1341
                        'title'   => $lang['strexport'],
1342
                        'url'     => 'database',
1343
                        'urlvars' => ['subject' => 'database', 'action' => 'export'],
1344
                        'hide'    => !$this->isDumpEnabled(),
1345
                        'tree'    => false,
1346
                        'icon'    => 'Export',
1347
                    ],
1348
                ];
1349
1350
                break;
1351
            case 'schema':
1352
                $tabs = [
1353
                    'tables'      => [
1354
                        'title'   => $lang['strtables'],
1355
                        'url'     => 'tables',
1356
                        'urlvars' => ['subject' => 'schema'],
1357
                        'help'    => 'pg.table',
1358
                        'icon'    => 'Tables',
1359
                    ],
1360
                    'views'       => [
1361
                        'title'   => $lang['strviews'],
1362
                        'url'     => 'views',
1363
                        'urlvars' => ['subject' => 'schema'],
1364
                        'help'    => 'pg.view',
1365
                        'icon'    => 'Views',
1366
                    ],
1367
                    'matviews'    => [
1368
                        'title'   => 'M ' . $lang['strviews'],
1369
                        'url'     => 'materializedviews',
1370
                        'urlvars' => ['subject' => 'schema'],
1371
                        'help'    => 'pg.matview',
1372
                        'icon'    => 'MViews',
1373
                    ],
1374
                    'sequences'   => [
1375
                        'title'   => $lang['strsequences'],
1376
                        'url'     => 'sequences',
1377
                        'urlvars' => ['subject' => 'schema'],
1378
                        'help'    => 'pg.sequence',
1379
                        'icon'    => 'Sequences',
1380
                    ],
1381
                    'functions'   => [
1382
                        'title'   => $lang['strfunctions'],
1383
                        'url'     => 'functions',
1384
                        'urlvars' => ['subject' => 'schema'],
1385
                        'help'    => 'pg.function',
1386
                        'icon'    => 'Functions',
1387
                    ],
1388
                    'fulltext'    => [
1389
                        'title'   => $lang['strfulltext'],
1390
                        'url'     => 'fulltext',
1391
                        'urlvars' => ['subject' => 'schema'],
1392
                        'help'    => 'pg.fts',
1393
                        'tree'    => true,
1394
                        'icon'    => 'Fts',
1395
                    ],
1396
                    'domains'     => [
1397
                        'title'   => $lang['strdomains'],
1398
                        'url'     => 'domains',
1399
                        'urlvars' => ['subject' => 'schema'],
1400
                        'help'    => 'pg.domain',
1401
                        'icon'    => 'Domains',
1402
                    ],
1403
                    'aggregates'  => [
1404
                        'title'   => $lang['straggregates'],
1405
                        'url'     => 'aggregates',
1406
                        'urlvars' => ['subject' => 'schema'],
1407
                        'hide'    => $hide_advanced,
1408
                        'help'    => 'pg.aggregate',
1409
                        'icon'    => 'Aggregates',
1410
                    ],
1411
                    'types'       => [
1412
                        'title'   => $lang['strtypes'],
1413
                        'url'     => 'types',
1414
                        'urlvars' => ['subject' => 'schema'],
1415
                        'hide'    => $hide_advanced,
1416
                        'help'    => 'pg.type',
1417
                        'icon'    => 'Types',
1418
                    ],
1419
                    'operators'   => [
1420
                        'title'   => $lang['stroperators'],
1421
                        'url'     => 'operators',
1422
                        'urlvars' => ['subject' => 'schema'],
1423
                        'hide'    => $hide_advanced,
1424
                        'help'    => 'pg.operator',
1425
                        'icon'    => 'Operators',
1426
                    ],
1427
                    'opclasses'   => [
1428
                        'title'   => $lang['stropclasses'],
1429
                        'url'     => 'opclasses',
1430
                        'urlvars' => ['subject' => 'schema'],
1431
                        'hide'    => $hide_advanced,
1432
                        'help'    => 'pg.opclass',
1433
                        'icon'    => 'OperatorClasses',
1434
                    ],
1435
                    'conversions' => [
1436
                        'title'   => $lang['strconversions'],
1437
                        'url'     => 'conversions',
1438
                        'urlvars' => ['subject' => 'schema'],
1439
                        'hide'    => $hide_advanced,
1440
                        'help'    => 'pg.conversion',
1441
                        'icon'    => 'Conversions',
1442
                    ],
1443
                    'privileges'  => [
1444
                        'title'   => $lang['strprivileges'],
1445
                        'url'     => 'privileges',
1446
                        'urlvars' => ['subject' => 'schema'],
1447
                        'help'    => 'pg.privilege',
1448
                        'tree'    => false,
1449
                        'icon'    => 'Privileges',
1450
                    ],
1451
                    'export'      => [
1452
                        'title'   => $lang['strexport'],
1453
                        'url'     => 'schemas',
1454
                        'urlvars' => ['subject' => 'schema', 'action' => 'export'],
1455
                        'hide'    => !$this->isDumpEnabled(),
1456
                        'tree'    => false,
1457
                        'icon'    => 'Export',
1458
                    ],
1459
                ];
1460
                if (!$data->hasFTS()) {
1461
                    unset($tabs['fulltext']);
1462
                }
1463
1464
                break;
1465
            case 'table':
1466
                $tabs = [
1467
                    'columns'     => [
1468
                        'title'   => $lang['strcolumns'],
1469
                        'url'     => 'tblproperties',
1470
                        'urlvars' => ['subject' => 'table', 'table' => Decorator::field('table')],
1471
                        'icon'    => 'Columns',
1472
                        'branch'  => true,
1473
                    ],
1474
                    'browse'      => [
1475
                        'title'   => $lang['strbrowse'],
1476
                        'icon'    => 'Columns',
1477
                        'url'     => 'display',
1478
                        'urlvars' => ['subject' => 'table', 'table' => Decorator::field('table')],
1479
                        'return'  => 'table',
1480
                        'branch'  => true,
1481
                    ],
1482
                    'select'      => [
1483
                        'title'   => $lang['strselect'],
1484
                        'icon'    => 'Search',
1485
                        'url'     => 'tables',
1486
                        'urlvars' => ['subject' => 'table', 'table' => Decorator::field('table'), 'action' => 'confselectrows'],
1487
                        'help'    => 'pg.sql.select',
1488
                    ],
1489
                    'insert'      => [
1490
                        'title'   => $lang['strinsert'],
1491
                        'url'     => 'tables',
1492
                        'urlvars' => [
1493
                            'action' => 'confinsertrow',
1494
                            'table'  => Decorator::field('table'),
1495
                        ],
1496
                        'help'    => 'pg.sql.insert',
1497
                        'icon'    => 'Operator',
1498
                    ],
1499
                    'indexes'     => [
1500
                        'title'   => $lang['strindexes'],
1501
                        'url'     => 'indexes',
1502
                        'urlvars' => ['subject' => 'table', 'table' => Decorator::field('table')],
1503
                        'help'    => 'pg.index',
1504
                        'icon'    => 'Indexes',
1505
                        'branch'  => true,
1506
                    ],
1507
                    'constraints' => [
1508
                        'title'   => $lang['strconstraints'],
1509
                        'url'     => 'constraints',
1510
                        'urlvars' => ['subject' => 'table', 'table' => Decorator::field('table')],
1511
                        'help'    => 'pg.constraint',
1512
                        'icon'    => 'Constraints',
1513
                        'branch'  => true,
1514
                    ],
1515
                    'triggers'    => [
1516
                        'title'   => $lang['strtriggers'],
1517
                        'url'     => 'triggers',
1518
                        'urlvars' => ['subject' => 'table', 'table' => Decorator::field('table')],
1519
                        'help'    => 'pg.trigger',
1520
                        'icon'    => 'Triggers',
1521
                        'branch'  => true,
1522
                    ],
1523
                    'rules'       => [
1524
                        'title'   => $lang['strrules'],
1525
                        'url'     => 'rules',
1526
                        'urlvars' => ['subject' => 'table', 'table' => Decorator::field('table')],
1527
                        'help'    => 'pg.rule',
1528
                        'icon'    => 'Rules',
1529
                        'branch'  => true,
1530
                    ],
1531
                    'admin'       => [
1532
                        'title'   => $lang['stradmin'],
1533
                        'url'     => 'tables',
1534
                        'urlvars' => ['subject' => 'table', 'table' => Decorator::field('table'), 'action' => 'admin'],
1535
                        'icon'    => 'Admin',
1536
                    ],
1537
                    'info'        => [
1538
                        'title'   => $lang['strinfo'],
1539
                        'url'     => 'info',
1540
                        'urlvars' => ['subject' => 'table', 'table' => Decorator::field('table')],
1541
                        'icon'    => 'Statistics',
1542
                    ],
1543
                    'privileges'  => [
1544
                        'title'   => $lang['strprivileges'],
1545
                        'url'     => 'privileges',
1546
                        'urlvars' => ['subject' => 'table', 'table' => Decorator::field('table')],
1547
                        'help'    => 'pg.privilege',
1548
                        'icon'    => 'Privileges',
1549
                    ],
1550
                    'import'      => [
1551
                        'title'   => $lang['strimport'],
1552
                        'url'     => 'tblproperties',
1553
                        'urlvars' => ['subject' => 'table', 'table' => Decorator::field('table'), 'action' => 'import'],
1554
                        'icon'    => 'Import',
1555
                        'hide'    => false,
1556
                    ],
1557
                    'export'      => [
1558
                        'title'   => $lang['strexport'],
1559
                        'url'     => 'tblproperties',
1560
                        'urlvars' => ['subject' => 'table', 'table' => Decorator::field('table'), 'action' => 'export'],
1561
                        'icon'    => 'Export',
1562
                        'hide'    => false,
1563
                    ],
1564
                ];
1565
1566
                break;
1567
            case 'view':
1568
                $tabs = [
1569
                    'columns'    => [
1570
                        'title'   => $lang['strcolumns'],
1571
                        'url'     => 'viewproperties',
1572
                        'urlvars' => ['subject' => 'view', 'view' => Decorator::field('view')],
1573
                        'icon'    => 'Columns',
1574
                        'branch'  => true,
1575
                    ],
1576
                    'browse'     => [
1577
                        'title'   => $lang['strbrowse'],
1578
                        'icon'    => 'Columns',
1579
                        'url'     => 'display',
1580
                        'urlvars' => [
1581
                            'action'  => 'confselectrows',
1582
                            'return'  => 'schema',
1583
                            'subject' => 'view',
1584
                            'view'    => Decorator::field('view'),
1585
                        ],
1586
                        'branch'  => true,
1587
                    ],
1588
                    'select'     => [
1589
                        'title'   => $lang['strselect'],
1590
                        'icon'    => 'Search',
1591
                        'url'     => 'views',
1592
                        'urlvars' => ['action' => 'confselectrows', 'view' => Decorator::field('view')],
1593
                        'help'    => 'pg.sql.select',
1594
                    ],
1595
                    'definition' => [
1596
                        'title'   => $lang['strdefinition'],
1597
                        'url'     => 'viewproperties',
1598
                        'urlvars' => ['subject' => 'view', 'view' => Decorator::field('view'), 'action' => 'definition'],
1599
                        'icon'    => 'Definition',
1600
                    ],
1601
                    'rules'      => [
1602
                        'title'   => $lang['strrules'],
1603
                        'url'     => 'rules',
1604
                        'urlvars' => ['subject' => 'view', 'view' => Decorator::field('view')],
1605
                        'help'    => 'pg.rule',
1606
                        'icon'    => 'Rules',
1607
                        'branch'  => true,
1608
                    ],
1609
                    'privileges' => [
1610
                        'title'   => $lang['strprivileges'],
1611
                        'url'     => 'privileges',
1612
                        'urlvars' => ['subject' => 'view', 'view' => Decorator::field('view')],
1613
                        'help'    => 'pg.privilege',
1614
                        'icon'    => 'Privileges',
1615
                    ],
1616
                    'export'     => [
1617
                        'title'   => $lang['strexport'],
1618
                        'url'     => 'viewproperties',
1619
                        'urlvars' => ['subject' => 'view', 'view' => Decorator::field('view'), 'action' => 'export'],
1620
                        'icon'    => 'Export',
1621
                        'hide'    => false,
1622
                    ],
1623
                ];
1624
1625
                break;
1626
            case 'matview':
1627
                $tabs = [
1628
                    'columns'    => [
1629
                        'title'   => $lang['strcolumns'],
1630
                        'url'     => 'materializedviewproperties',
1631
                        'urlvars' => ['subject' => 'matview', 'matview' => Decorator::field('matview')],
1632
                        'icon'    => 'Columns',
1633
                        'branch'  => true,
1634
                    ],
1635
                    'browse'     => [
1636
                        'title'   => $lang['strbrowse'],
1637
                        'icon'    => 'Columns',
1638
                        'url'     => 'display',
1639
                        'urlvars' => [
1640
                            'action'  => 'confselectrows',
1641
                            'return'  => 'schema',
1642
                            'subject' => 'matview',
1643
                            'matview' => Decorator::field('matview'),
1644
                        ],
1645
                        'branch'  => true,
1646
                    ],
1647
                    'select'     => [
1648
                        'title'   => $lang['strselect'],
1649
                        'icon'    => 'Search',
1650
                        'url'     => 'materializedviews',
1651
                        'urlvars' => ['action' => 'confselectrows', 'matview' => Decorator::field('matview')],
1652
                        'help'    => 'pg.sql.select',
1653
                    ],
1654
                    'definition' => [
1655
                        'title'   => $lang['strdefinition'],
1656
                        'url'     => 'materializedviewproperties',
1657
                        'urlvars' => ['subject' => 'matview', 'matview' => Decorator::field('matview'), 'action' => 'definition'],
1658
                        'icon'    => 'Definition',
1659
                    ],
1660
                    'indexes'    => [
1661
                        'title'   => $lang['strindexes'],
1662
                        'url'     => 'indexes',
1663
                        'urlvars' => ['subject' => 'matview', 'matview' => Decorator::field('matview')],
1664
                        'help'    => 'pg.index',
1665
                        'icon'    => 'Indexes',
1666
                        'branch'  => true,
1667
                    ],
1668
                    /*'constraints' => [
1669
                    'title' => $lang['strconstraints'],
1670
                    'url' => 'constraints',
1671
                    'urlvars' => ['subject' => 'matview', 'matview' => Decorator::field('matview')],
1672
                    'help' => 'pg.constraint',
1673
                    'icon' => 'Constraints',
1674
                    'branch' => true,
1675
                     */
1676
1677
                    'rules'      => [
1678
                        'title'   => $lang['strrules'],
1679
                        'url'     => 'rules',
1680
                        'urlvars' => ['subject' => 'matview', 'matview' => Decorator::field('matview')],
1681
                        'help'    => 'pg.rule',
1682
                        'icon'    => 'Rules',
1683
                        'branch'  => true,
1684
                    ],
1685
                    'privileges' => [
1686
                        'title'   => $lang['strprivileges'],
1687
                        'url'     => 'privileges',
1688
                        'urlvars' => ['subject' => 'matview', 'matview' => Decorator::field('matview')],
1689
                        'help'    => 'pg.privilege',
1690
                        'icon'    => 'Privileges',
1691
                    ],
1692
                    'export'     => [
1693
                        'title'   => $lang['strexport'],
1694
                        'url'     => 'materializedviewproperties',
1695
                        'urlvars' => ['subject' => 'matview', 'matview' => Decorator::field('matview'), 'action' => 'export'],
1696
                        'icon'    => 'Export',
1697
                        'hide'    => false,
1698
                    ],
1699
                ];
1700
1701
                break;
1702
            case 'function':
1703
                $tabs = [
1704
                    'definition' => [
1705
                        'title'   => $lang['strdefinition'],
1706
                        'url'     => 'functions',
1707
                        'urlvars' => [
1708
                            'subject'      => 'function',
1709
                            'function'     => Decorator::field('function'),
1710
                            'function_oid' => Decorator::field('function_oid'),
1711
                            'action'       => 'properties',
1712
                        ],
1713
                        'icon'    => 'Definition',
1714
                    ],
1715
                    'privileges' => [
1716
                        'title'   => $lang['strprivileges'],
1717
                        'url'     => 'privileges',
1718
                        'urlvars' => [
1719
                            'subject'      => 'function',
1720
                            'function'     => Decorator::field('function'),
1721
                            'function_oid' => Decorator::field('function_oid'),
1722
                        ],
1723
                        'icon'    => 'Privileges',
1724
                    ],
1725
                ];
1726
1727
                break;
1728
            case 'aggregate':
1729
                $tabs = [
1730
                    'definition' => [
1731
                        'title'   => $lang['strdefinition'],
1732
                        'url'     => 'aggregates',
1733
                        'urlvars' => [
1734
                            'subject'  => 'aggregate',
1735
                            'aggrname' => Decorator::field('aggrname'),
1736
                            'aggrtype' => Decorator::field('aggrtype'),
1737
                            'action'   => 'properties',
1738
                        ],
1739
                        'icon'    => 'Definition',
1740
                    ],
1741
                ];
1742
1743
                break;
1744
            case 'role':
1745
                $tabs = [
1746
                    'definition' => [
1747
                        'title'   => $lang['strdefinition'],
1748
                        'url'     => 'roles',
1749
                        'urlvars' => [
1750
                            'subject'  => 'role',
1751
                            'rolename' => Decorator::field('rolename'),
1752
                            'action'   => 'properties',
1753
                        ],
1754
                        'icon'    => 'Definition',
1755
                    ],
1756
                ];
1757
1758
                break;
1759
            case 'popup':
1760
                $tabs = [
1761
                    'sql'  => [
1762
                        'title'   => $lang['strsql'],
1763
                        'url'     => '/src/views/sqledit',
1764
                        'urlvars' => ['action' => 'sql', 'subject' => 'schema'],
1765
                        'help'    => 'pg.sql',
1766
                        'icon'    => 'SqlEditor',
1767
                    ],
1768
                    'find' => [
1769
                        'title'   => $lang['strfind'],
1770
                        'url'     => '/src/views/sqledit',
1771
                        'urlvars' => ['action' => 'find', 'subject' => 'schema'],
1772
                        'icon'    => 'Search',
1773
                    ],
1774
                ];
1775
1776
                break;
1777
            case 'column':
1778
                $tabs = [
1779
                    'properties' => [
1780
                        'title'   => $lang['strcolprop'],
1781
                        'url'     => 'colproperties',
1782
                        'urlvars' => [
1783
                            'subject' => 'column',
1784
                            'table'   => Decorator::field('table'),
1785
                            'column'  => Decorator::field('column'),
1786
                        ],
1787
                        'icon'    => 'Column',
1788
                    ],
1789
                    'privileges' => [
1790
                        'title'   => $lang['strprivileges'],
1791
                        'url'     => 'privileges',
1792
                        'urlvars' => [
1793
                            'subject' => 'column',
1794
                            'table'   => Decorator::field('table'),
1795
                            'column'  => Decorator::field('column'),
1796
                        ],
1797
                        'help'    => 'pg.privilege',
1798
                        'icon'    => 'Privileges',
1799
                    ],
1800
                ];
1801
1802
                break;
1803
            case 'fulltext':
1804
                $tabs = [
1805
                    'ftsconfigs' => [
1806
                        'title'   => $lang['strftstabconfigs'],
1807
                        'url'     => 'fulltext',
1808
                        'urlvars' => ['subject' => 'schema'],
1809
                        'hide'    => !$data->hasFTS(),
1810
                        'help'    => 'pg.ftscfg',
1811
                        'tree'    => true,
1812
                        'icon'    => 'FtsCfg',
1813
                    ],
1814
                    'ftsdicts'   => [
1815
                        'title'   => $lang['strftstabdicts'],
1816
                        'url'     => 'fulltext',
1817
                        'urlvars' => ['subject' => 'schema', 'action' => 'viewdicts'],
1818
                        'hide'    => !$data->hasFTS(),
1819
                        'help'    => 'pg.ftsdict',
1820
                        'tree'    => true,
1821
                        'icon'    => 'FtsDict',
1822
                    ],
1823
                    'ftsparsers' => [
1824
                        'title'   => $lang['strftstabparsers'],
1825
                        'url'     => 'fulltext',
1826
                        'urlvars' => ['subject' => 'schema', 'action' => 'viewparsers'],
1827
                        'hide'    => !$data->hasFTS(),
1828
                        'help'    => 'pg.ftsparser',
1829
                        'tree'    => true,
1830
                        'icon'    => 'FtsParser',
1831
                    ],
1832
                ];
1833
1834
                break;
1835
        }
1836
1837
        // Tabs hook's place
1838
        $plugin_functions_parameters = [
1839
            'tabs'    => &$tabs,
1840
            'section' => $section,
1841
        ];
1842
        $plugin_manager->do_hook('tabs', $plugin_functions_parameters);
1843
1844
        return $tabs;
1845
    }
1846
1847
    /**
1848
     * Get the URL for the last active tab of a particular tab bar.
1849
     *
1850
     * @param $section
1851
     *
1852
     * @return null|mixed
1853
     */
1854
    public function getLastTabURL($section)
1855
    {
1856
        //$data = $this->getDatabaseAccessor();
1857
1858
        $tabs = $this->getNavTabs($section);
1859
1860
        if (isset($_SESSION['webdbLastTab'][$section])) {
1861
            $tab = $tabs[$_SESSION['webdbLastTab'][$section]];
1862
        } else {
1863
            $tab = reset($tabs);
1864
        }
1865
        //$this->prtrace(['section' => $section, 'tabs' => $tabs, 'tab' => $tab]);
1866
        return isset($tab['url']) ? $tab : null;
1867
    }
1868
1869
    /**
1870
     * Do multi-page navigation.  Displays the prev, next and page options.
0 ignored issues
show
Documentation Bug introduced by
The doc comment - at position 0 could not be parsed: Unknown type name '-' at position 0 in -.
Loading history...
1871
     *
1872
     * @param $page - the page currently viewed
1873
     * @param $pages - the maximum number of pages
1874
     * @param $gets -  the parameters to include in the link to the wanted page
1875
     * @param $max_width - the number of pages to make available at any one time (default = 20)
1876
     */
1877
    public function printPages($page, $pages, $gets, $max_width = 20)
1878
    {
1879
        $lang = $this->lang;
1880
1881
        $window = 10;
1882
1883
        if ($page < 0 || $page > $pages) {
1884
            return;
1885
        }
1886
1887
        if ($pages < 0) {
1888
            return;
1889
        }
1890
1891
        if ($max_width <= 0) {
1892
            return;
1893
        }
1894
1895
        unset($gets['page']);
1896
        $url = http_build_query($gets);
1897
1898
        if ($pages > 1) {
1899
            echo "<p style=\"text-align: center\">\n";
1900
            if ($page != 1) {
1901
                echo "<a class=\"pagenav\" href=\"?{$url}&amp;page=1\">{$lang['strfirst']}</a>\n";
1902
                $temp = $page - 1;
1903
                echo "<a class=\"pagenav\" href=\"?{$url}&amp;page={$temp}\">{$lang['strprev']}</a>\n";
1904
            }
1905
1906
            if ($page <= $window) {
1907
                $min_page = 1;
1908
                $max_page = min(2 * $window, $pages);
1909
            } elseif ($page > $window && $pages >= $page + $window) {
1910
                $min_page = ($page - $window) + 1;
1911
                $max_page = $page + $window;
1912
            } else {
1913
                $min_page = ($page - (2 * $window - ($pages - $page))) + 1;
1914
                $max_page = $pages;
1915
            }
1916
1917
            // Make sure min_page is always at least 1
1918
            // and max_page is never greater than $pages
1919
            $min_page = max($min_page, 1);
1920
            $max_page = min($max_page, $pages);
1921
1922
            for ($i = $min_page; $i <= $max_page; ++$i) {
1923
                #if ($i != $page) echo "<a class=\"pagenav\" href=\"?{$url}&amp;page={$i}\">$i</a>\n";
0 ignored issues
show
Coding Style introduced by
Perl-style comments are not allowed. Use "// Comment." or "/* comment */" instead.
Loading history...
1924
                if ($i != $page) {
1925
                    echo "<a class=\"pagenav\" href=\"display?{$url}&amp;page={$i}\">${i}</a>\n";
1926
                } else {
1927
                    echo "${i}\n";
1928
                }
1929
            }
1930
            if ($page != $pages) {
1931
                $temp = $page + 1;
1932
                echo "<a class=\"pagenav\" href=\"display?{$url}&amp;page={$temp}\">{$lang['strnext']}</a>\n";
1933
                echo "<a class=\"pagenav\" href=\"display?{$url}&amp;page={$pages}\">{$lang['strlast']}</a>\n";
1934
            }
1935
            echo "</p>\n";
1936
        }
1937
    }
1938
1939
    /**
1940
     * Converts a PHP.INI size variable to bytes.  Taken from publically available
1941
     * function by Chris DeRose, here: http://www.php.net/manual/en/configuration.directives.php#ini.file-uploads.
1942
     *
1943
     * @param $strIniSize The PHP.INI variable
1944
     *
1945
     * @return size in bytes, false on failure
1946
     */
1947
    public function inisizeToBytes($strIniSize)
1948
    {
1949
        // This function will take the string value of an ini 'size' parameter,
1950
        // and return a double (64-bit float) representing the number of bytes
1951
        // that the parameter represents. Or false if $strIniSize is unparseable.
1952
        $a_IniParts = [];
1953
1954
        if (!is_string($strIniSize)) {
1955
            return false;
1956
        }
1957
1958
        if (!preg_match('/^(\d+)([bkm]*)$/i', $strIniSize, $a_IniParts)) {
1959
            return false;
1960
        }
1961
1962
        $nSize   = (float) $a_IniParts[1];
1963
        $strUnit = strtolower($a_IniParts[2]);
1964
1965
        switch ($strUnit) {
1966
            case 'm':
1967
                return $nSize * (float) 1048576;
1968
            case 'k':
1969
                return $nSize * (float) 1024;
1970
            case 'b':
1971
            default:
1972
                return $nSize;
1973
        }
1974
    }
1975
1976
    public function getRequestVars($subject = '')
1977
    {
1978
        $v = [];
1979
        if (!empty($subject)) {
1980
            $v['subject'] = $subject;
1981
        }
1982
1983
        if ($this->_server_id !== null && $subject != 'root') {
1984
            $v['server'] = $this->_server_id;
1985
            if ($this->_database !== null && $subject != 'server') {
1986
                $v['database'] = $this->_database;
1987
                if (isset($_REQUEST['schema']) && $subject != 'database') {
1988
                    $v['schema'] = $_REQUEST['schema'];
1989
                }
1990
            }
1991
        }
1992
        //$this->prtrace($v);
1993
        return $v;
1994
    }
1995
1996
    public function icon($icon)
1997
    {
1998
        if (is_string($icon)) {
1999
            $path = "/images/themes/{$this->conf['theme']}/{$icon}";
2000
            if (file_exists(\BASE_PATH . $path . '.png')) {
2001
                return SUBFOLDER . $path . '.png';
2002
            }
2003
2004
            if (file_exists(\BASE_PATH . $path . '.gif')) {
2005
                return SUBFOLDER . $path . '.gif';
2006
            }
2007
2008
            if (file_exists(\BASE_PATH . $path . '.ico')) {
2009
                return SUBFOLDER . $path . '.ico';
2010
            }
2011
2012
            $path = "/images/themes/default/{$icon}";
2013
            if (file_exists(\BASE_PATH . $path . '.png')) {
2014
                return SUBFOLDER . $path . '.png';
2015
            }
2016
2017
            if (file_exists(\BASE_PATH . $path . '.gif')) {
2018
                return SUBFOLDER . $path . '.gif';
2019
            }
2020
2021
            if (file_exists(\BASE_PATH . $path . '.ico')) {
2022
                return SUBFOLDER . $path . '.ico';
2023
            }
2024
        } else {
2025
            // Icon from plugins
2026
            $path = "/plugins/{$icon[0]}/images/{$icon[1]}";
2027
            if (file_exists(\BASE_PATH . $path . '.png')) {
2028
                return SUBFOLDER . $path . '.png';
2029
            }
2030
2031
            if (file_exists(\BASE_PATH . $path . '.gif')) {
2032
                return SUBFOLDER . $path . '.gif';
2033
            }
2034
2035
            if (file_exists(\BASE_PATH . $path . '.ico')) {
2036
                return SUBFOLDER . $path . '.ico';
2037
            }
2038
        }
2039
2040
        return '';
2041
    }
2042
2043
    /**
2044
     * Function to escape command line parameters.
2045
     *
2046
     * @param string $str The string to escape
2047
     *
2048
     * @return string The escaped string
2049
     */
2050
    public function escapeShellArg($str)
2051
    {
2052
        //$data = $this->getDatabaseAccessor();
2053
        $lang = $this->lang;
2054
2055
        if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
2056
            // Due to annoying PHP bugs, shell arguments cannot be escaped
2057
            // (command simply fails), so we cannot allow complex objects
2058
            // to be dumped.
2059
            if (preg_match('/^[_.[:alnum:]]+$/', $str)) {
2060
                return $str;
2061
            }
2062
2063
            return $this->halt($lang['strcannotdumponwindows']);
2064
        }
2065
2066
        return escapeshellarg($str);
2067
    }
2068
2069
    /**
2070
     * Function to escape command line programs.
2071
     *
2072
     * @param string $str The string to escape
2073
     *
2074
     * @return string The escaped string
2075
     */
2076
    public function escapeShellCmd($str)
2077
    {
2078
        $data = $this->getDatabaseAccessor();
2079
2080
        if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
2081
            $data->fieldClean($str);
2082
2083
            return '"' . $str . '"';
2084
        }
2085
2086
        return escapeshellcmd($str);
2087
    }
2088
2089
    /**
2090
     * Save the given SQL script in the history
2091
     * of the database and server.
2092
     *
2093
     * @param $script the SQL script to save
2094
     */
2095
    public function saveScriptHistory($script)
2096
    {
2097
        list($usec, $sec)                                                           = explode(' ', microtime());
2098
        $time                                                                       = ((float) $usec + (float) $sec);
2099
        $_SESSION['history'][$_REQUEST['server']][$_REQUEST['database']]["${time}"] = [
2100
            'query'    => $script,
2101
            'paginate' => !isset($_REQUEST['paginate']) ? 'f' : 't',
2102
            'queryid'  => $time,
2103
        ];
2104
    }
2105
2106
    /*
2107
     * Output dropdown list to select server and
2108
     * databases form the popups windows.
2109
     * @param $onchange Javascript action to take when selections change.
2110
     */
2111
    public function printConnection($onchange, $do_print = true)
1 ignored issue
show
Coding Style introduced by
You must use "/**" style comments for a function comment
Loading history...
2112
    {
2113
        $lang = $this->lang;
2114
2115
        $connection_html = "<table class=\"printconnection\" style=\"width: 100%\"><tr><td class=\"popup_select1\">\n";
2116
2117
        $servers      = $this->getServers();
2118
        $forcedserver = null;
2119
        if (count($servers) === 1) {
2120
            $forcedserver = $this->_server_id;
2121
            $connection_html .= '<input type="hidden" readonly="readonly" value="' . $this->_server_id . '" name="server">';
2122
        } else {
2123
            $connection_html .= '<label>';
2124
            $connection_html .= $this->printHelp($lang['strserver'], 'pg.server', false);
2125
            $connection_html .= ': </label>';
2126
            $connection_html .= " <select name=\"server\" {$onchange}>\n";
2127
            foreach ($servers as $info) {
2128
                if (empty($info['username'])) {
2129
                    continue;
2130
                }
2131
                $selected = isset($_REQUEST['server']) && $info['id'] == $_REQUEST['server'] ? ' selected="selected"' : '';
2132
                // not logged on this server
2133
                $connection_html .= '<option value="' . htmlspecialchars($info['id']) . '" ' . $selected . '>';
2134
                $connection_html .= htmlspecialchars("{$info['desc']} ({$info['id']})");
2135
                $connection_html .= "</option>\n";
2136
            }
2137
            $connection_html .= "</select>\n";
2138
        }
2139
2140
        $connection_html .= "</td><td class=\"popup_select2\" style=\"text-align: right\">\n";
2141
2142
        if (count($servers) === 1 && isset($servers[$this->_server_id]['useonlydefaultdb']) && $servers[$this->_server_id]['useonlydefaultdb'] === true) {
2143
            $connection_html .= '<input type="hidden" name="database" value="' . htmlspecialchars($servers[$this->_server_id]['defaultdb']) . "\" />\n";
2144
        } else {
2145
            // Get the list of all databases
2146
            $data      = $this->getDatabaseAccessor();
2147
            $databases = $data->getDatabases();
2148
            if ($databases->recordCount() > 0) {
2149
                $connection_html .= '<label>';
2150
                $connection_html .= $this->printHelp($lang['strdatabase'], 'pg.database', false);
2151
                $connection_html .= ": <select name=\"database\" {$onchange}>\n";
2152
2153
                //if no database was selected, user should select one
2154
                if (!isset($_REQUEST['database'])) {
2155
                    $connection_html .= "<option value=\"\">--</option>\n";
2156
                }
2157
2158
                while (!$databases->EOF) {
2159
                    $dbname     = $databases->fields['datname'];
2160
                    $dbselected = isset($_REQUEST['database']) && $dbname == $_REQUEST['database'] ? ' selected="selected"' : '';
2161
                    $connection_html .= '<option value="' . htmlspecialchars($dbname) . '" ' . $dbselected . '>' . htmlspecialchars($dbname) . "</option>\n";
2162
2163
                    $databases->moveNext();
2164
                }
2165
                $connection_html .= "</select></label>\n";
2166
            } else {
2167
                $server_info = $this->misc->getServerInfo();
2168
                $connection_html .= '<input type="hidden" name="database" value="' . htmlspecialchars($server_info['defaultdb']) . "\" />\n";
2169
            }
2170
        }
2171
2172
        $connection_html .= "</td></tr></table>\n";
2173
2174
        if ($do_print) {
2175
            echo $connection_html;
2176
        } else {
2177
            return $connection_html;
2178
        }
2179
    }
2180
2181
    /**
2182
     * returns an array representing FKs definition for a table, sorted by fields
1 ignored issue
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
2183
     * or by constraint.
2184
     *
2185
     * @param $table The table to retrieve FK contraints from
2186
     * @returns the array of FK definition:
0 ignored issues
show
Coding Style introduced by
Tag cannot be grouped with parameter tags in a doc comment
Loading history...
2187
     *   array(
2188
     *     'byconstr' => array(
2189
     *       constrain id => array(
2190
     *         confrelid => foreign relation oid
2191
     *         f_schema => foreign schema name
2192
     *         f_table => foreign table name
2193
     *         pattnums => array of parent's fields nums
2194
     *         pattnames => array of parent's fields names
2195
     *         fattnames => array of foreign attributes names
2196
     *       )
2197
     *     ),
2198
     *     'byfield' => array(
2199
     *       attribute num => array (constraint id, ...)
2200
     *     ),
2201
     *     'code' => HTML/js code to include in the page for auto-completion
2202
     *   )
2203
     */
2204
    public function getAutocompleteFKProperties($table)
2205
    {
2206
        $data = $this->getDatabaseAccessor();
2207
2208
        $fksprops = [
2209
            'byconstr' => [],
2210
            'byfield'  => [],
2211
            'code'     => '',
2212
        ];
2213
2214
        $constrs = $data->getConstraintsWithFields($table);
2215
2216
        if (!$constrs->EOF) {
2217
            $conrelid = $constrs->fields['conrelid'];
2218
            while (!$constrs->EOF) {
2219
                if ($constrs->fields['contype'] == 'f') {
2220
                    if (!isset($fksprops['byconstr'][$constrs->fields['conid']])) {
2221
                        $fksprops['byconstr'][$constrs->fields['conid']] = [
2222
                            'confrelid' => $constrs->fields['confrelid'],
2223
                            'f_table'   => $constrs->fields['f_table'],
2224
                            'f_schema'  => $constrs->fields['f_schema'],
2225
                            'pattnums'  => [],
2226
                            'pattnames' => [],
2227
                            'fattnames' => [],
2228
                        ];
2229
                    }
2230
2231
                    $fksprops['byconstr'][$constrs->fields['conid']]['pattnums'][]  = $constrs->fields['p_attnum'];
2232
                    $fksprops['byconstr'][$constrs->fields['conid']]['pattnames'][] = $constrs->fields['p_field'];
2233
                    $fksprops['byconstr'][$constrs->fields['conid']]['fattnames'][] = $constrs->fields['f_field'];
2234
2235
                    if (!isset($fksprops['byfield'][$constrs->fields['p_attnum']])) {
2236
                        $fksprops['byfield'][$constrs->fields['p_attnum']] = [];
2237
                    }
2238
2239
                    $fksprops['byfield'][$constrs->fields['p_attnum']][] = $constrs->fields['conid'];
2240
                }
2241
                $constrs->moveNext();
2242
            }
2243
2244
            $fksprops['code'] = "<script type=\"text/javascript\">\n";
2245
            $fksprops['code'] .= "var constrs = {};\n";
2246
            foreach ($fksprops['byconstr'] as $conid => $props) {
2247
                $fksprops['code'] .= "constrs.constr_{$conid} = {\n";
2248
                $fksprops['code'] .= 'pattnums: [' . implode(',', $props['pattnums']) . "],\n";
2249
                $fksprops['code'] .= "f_table:'" . addslashes(htmlentities($props['f_table'], ENT_QUOTES, 'UTF-8')) . "',\n";
2250
                $fksprops['code'] .= "f_schema:'" . addslashes(htmlentities($props['f_schema'], ENT_QUOTES, 'UTF-8')) . "',\n";
2251
                $_ = '';
2252
                foreach ($props['pattnames'] as $n) {
2253
                    $_ .= ",'" . htmlentities($n, ENT_QUOTES, 'UTF-8') . "'";
2254
                }
2255
                $fksprops['code'] .= 'pattnames: [' . substr($_, 1) . "],\n";
2256
2257
                $_ = '';
2258
                foreach ($props['fattnames'] as $n) {
2259
                    $_ .= ",'" . htmlentities($n, ENT_QUOTES, 'UTF-8') . "'";
2260
                }
2261
2262
                $fksprops['code'] .= 'fattnames: [' . substr($_, 1) . "]\n";
2263
                $fksprops['code'] .= "};\n";
2264
            }
2265
2266
            $fksprops['code'] .= "var attrs = {};\n";
2267
            foreach ($fksprops['byfield'] as $attnum => $cstrs) {
2268
                $fksprops['code'] .= "attrs.attr_{$attnum} = [" . implode(',', $fksprops['byfield'][$attnum]) . "];\n";
2269
            }
2270
2271
            $fksprops['code'] .= "var table='" . addslashes(htmlentities($table, ENT_QUOTES, 'UTF-8')) . "';";
2272
            $fksprops['code'] .= "var server='" . htmlentities($_REQUEST['server'], ENT_QUOTES, 'UTF-8') . "';";
2273
            $fksprops['code'] .= "var database='" . addslashes(htmlentities($_REQUEST['database'], ENT_QUOTES, 'UTF-8')) . "';";
2274
            $fksprops['code'] .= "var subfolder='" . SUBFOLDER . "';";
2275
            $fksprops['code'] .= "</script>\n";
2276
2277
            $fksprops['code'] .= '<div id="fkbg"></div>';
2278
            $fksprops['code'] .= '<div id="fklist"></div>';
2279
            $fksprops['code'] .= '<script src="' . SUBFOLDER . '/js/ac_insert_row.js" type="text/javascript"></script>';
2280
        } else /* we have no foreign keys on this table */
0 ignored issues
show
Coding Style introduced by
Expected "} else \n"; found " else /* we have no foreign keys on this table */\n {\n"
Loading history...
2281
        {
2282
            return false;
2283
        }
2284
2285
        return $fksprops;
2286
    }
2287
}
2288