Test Failed
Branch develop (db5506)
by Felipe
03:46
created

Misc::isDumpEnabled()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 2
nc 2
nop 1
dl 0
loc 5
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace PHPPgAdmin;
4
5
use \PHPPgAdmin\Decorators\Decorator;
6
7
/**
8
 * Class to hold various commonly used functions
9
 *
10
 * $Id: Misc.php,v 1.171 2008/03/17 21:35:48 ioguix Exp $
11
 */
12
13
class Misc
14
{
15
    use \PHPPgAdmin\HelperTrait;
16
17
    private $_connection       = null;
18
    private $_no_db_connection = false;
19
    private $_reload_browser   = false;
20
    private $app               = null;
0 ignored issues
show
Unused Code introduced by
The property $app is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
21
    private $data              = null;
22
    private $database          = null;
23
    private $server_id         = null;
24
    public $appLangFiles       = [];
25
    public $appName            = '';
26
    public $appVersion         = '';
27
    public $form               = '';
28
    public $href               = '';
29
    public $_name              = 'Misc';
30
    public $lang               = [];
31
    private $server_info       = null;
32
    private $error_msg         = '';
33
34
    private $container = null;
35
36
    /* Constructor */
37
    public function __construct(\Slim\Container $container)
0 ignored issues
show
Coding Style introduced by
__construct uses the super-global variable $_REQUEST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
Coding Style introduced by
__construct uses the super-global variable $_SESSION which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
38
    {
39
        $this->container = $container;
40
41
        $this->lang = $container->get('lang');
42
        $this->conf = $container->get('conf');
43
        //$this->view           = $container->get('view');
44
        $this->plugin_manager = $container->get('plugin_manager');
45
        $this->appLangFiles   = $container->get('appLangFiles');
46
47
        $this->appName          = $container->get('settings')['appName'];
48
        $this->appVersion       = $container->get('settings')['appVersion'];
49
        $this->postgresqlMinVer = $container->get('settings')['postgresqlMinVer'];
50
        $this->phpMinVer        = $container->get('settings')['phpMinVer'];
51
52
        $base_version = $container->get('settings')['base_version'];
53
54
        // Check for config file version mismatch
55
        if (!isset($this->conf['version']) || $base_version > $this->conf['version']) {
56
            $container->get('utils')->addError($this->lang['strbadconfig']);
57
        }
58
59
        // Check database support is properly compiled in
60
        if (!function_exists('pg_connect')) {
61
            $container->get('utils')->addError($this->lang['strnotloaded']);
62
        }
63
64
        // Check the version of PHP
65
        if (version_compare(phpversion(), $this->phpMinVer, '<')) {
66
            $container->get('utils')->addError(sprintf('Version of PHP not supported. Please upgrade to version %s or later.', $this->phpMinVer));
67
        }
68
69
        if (count($this->conf['servers']) === 1) {
70
            $info            = $this->conf['servers'][0];
71
            $this->server_id = $info['host'] . ':' . $info['port'] . ':' . $info['sslmode'];
72
        } elseif (isset($_REQUEST['server'])) {
73
            $this->server_id = $_REQUEST['server'];
74
        } elseif (isset($_SESSION['webdbLogin']) && count($_SESSION['webdbLogin']) > 0) {
75
            $this->server_id = array_keys($_SESSION['webdbLogin'])[0];
76
        }
77
    }
78
79
    /**
80
     * Sets the view instance property of this class
81
     * @param \Slim\Views\Twig $view [description]
82
     */
83
    public function setView(\Slim\Views\Twig $view)
84
    {
85
        $this->view = $view;
86
    }
87
88
    /**
89
     * Adds or modifies a key in the $conf instance property of this class
90
     * @param string $key   [description]
91
     * @param mixed $value [description]
92
     * @return $this
93
     */
94
    public function setConf(string $key, $value)
95
    {
96
        $this->conf[$key] = $value;
97
        return $this;
98
    }
99
100
    /**
101
     * gets the value of a config property, or the array of all config properties
102
     * @param  mixed $key value of the key to be retrieved. If null, the full array is returnes
103
     * @return mixed the whole $conf array, the value of $conf[key] or null if said key does not exist
104
     */
105
    public function getConf($key = null)
106
    {
107
        if ($key === null) {
108
            return $this->conf;
109
        } elseif (array_key_exists($key, $this->conf)) {
110
            return $this->conf[$key];
111
        }
112
        return null;
113
    }
114
115
    public function getServerId()
116
    {
117
        return $this->server_id;
118
    }
119
120
    /**
121
     * Displays link to the context help.
122
     * @param $str   - the string that the context help is related to (already escaped)
123
     * @param $help  - help section identifier
124
     * @param $do_print true to echo, false to return
125
     */
126
    public function printHelp($str, $help = null, $do_print = true)
127
    {
128
        //\PC::debug(['str' => $str, 'help' => $help], 'printHelp');
129
        if ($help !== null) {
130
            $helplink = $this->getHelpLink($help);
131
            $str .= '<a class="help" href="' . $helplink . '" title="' . $this->lang['strhelp'] . '" target="phppgadminhelp">' . $this->lang['strhelpicon'] . '</a>';
132
        }
133
        if ($do_print) {
134
            echo $str;
135
        } else {
136
            return $str;
137
        }
138
    }
139
140
    public function getHelpLink($help)
141
    {
142
        return htmlspecialchars(SUBFOLDER . '/help?help=' . urlencode($help) . '&server=' . urlencode($this->getServerId()));
143
    }
144
145
    /**
146
     * [setReloadBrowser description]
147
     *
148
     * @param boolean $flag sets internal $_reload_browser var which will be passed to the footer methods
149
     * @return $this
150
     */
151
    public function setReloadBrowser($flag)
152
    {
153
        $this->_reload_browser = boolval($flag);
154
        return $this;
155
    }
156
157
    public function getReloadBrowser()
158
    {
159
        return $this->_reload_browser;
160
    }
161
162
    /**
163
     * Default Error Handler. This will be called with the following params
164
     *
165
     * @param $dbms         the RDBMS you are connecting to
166
     * @param $fn           the name of the calling function (in uppercase)
167
     * @param $errno        the native error number from the database
168
     * @param $errmsg       the native error msg from the database
169
     * @param $p1           $fn specific parameter - see below
170
     * @param $p2
171
     * @param $thisConnection
172
     * @throws \PHPPgAdmin\ADOdbException
173
     * @internal param $P2 $fn specific parameter - see below
174
     */
0 ignored issues
show
Documentation Bug introduced by
The doc comment $p1 at position 0 could not be parsed: Unknown type name '$p1' at position 0 in $p1.
Loading history...
175
    public static function adodb_throw($dbms, $fn, $errno, $errmsg, $p1, $p2, $thisConnection)
176
    {
177
        if (error_reporting() == 0) {
178
            return;
179
        }
180
181
        $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2);
182
183
        $btarray0 = [
184
            'msg'      => 'ADOdbException at ',
185
            'class'    => $backtrace[1]['class'],
186
            'type'     => $backtrace[1]['type'],
187
            'function' => $backtrace[1]['function'],
188
            'spacer'   => ' ',
189
            'line'     => $backtrace[0]['line'],
190
        ];
191
192
        $errmsg = htmlspecialchars(\PHPPgAdmin\HelperTrait::br2ln($errmsg));
193
        $p1     = htmlspecialchars(\PHPPgAdmin\HelperTrait::br2ln($p1));
194
        $p2     = htmlspecialchars(\PHPPgAdmin\HelperTrait::br2ln($p2));
195
        switch ($fn) {
196
            case 'EXECUTE':
197
                $sql         = $p1;
198
                $inputparams = $p2;
199
200
                $error_msg = '<p><b>strsqlerror</b><br />' . nl2br($errmsg) . '</p> <p><b>SQL:</b><br />' . nl2br($sql) . '</p>	';
201
202
                echo '<table class="error" cellpadding="5"><tr><td>' . nl2br($error_msg) . '</td></tr></table><br />' . "\n";
203
204
                break;
205
206
            case 'PCONNECT':
207
            case 'CONNECT':
208
                // do nothing;
209
                break;
210
            default:
211
                $s = "$dbms error: [$errno: $errmsg] in $fn($p1, $p2)\n";
212
                echo "<table class=\"error\" cellpadding=\"5\"><tr><td>{$s}</td></tr></table><br />\n";
213
                break;
214
        }
215
216
        $tag = implode('', $btarray0);
217
218
        \PC::debug(['errno' => $errno, 'fn' => $fn, 'errmsg' => $errmsg], $tag);
219
220
        throw new \PHPPgAdmin\ADOdbException($dbms, $fn, $errno, $errmsg, $p1, $p2, $thisConnection);
221
    }
222
223
    public function getContainer()
224
    {
225
        return $this->container;
226
    }
227
228
    /**
229
     * sets $_no_db_connection boolean value, allows to render scripts that do not need an active session
230
     *
231
     * @param boolean $flag [description]
232
     * @return $this
233
     */
234
    public function setNoDBConnection($flag)
235
    {
236
        $this->_no_db_connection = boolval($flag);
237
        return $this;
238
    }
239
240
    public function getNoDBConnection()
241
    {
242
        return $this->_no_db_connection;
243
    }
244
245
    /**
246
     * Sets the last error message to display afterwards instead of just dying with the error msg
247
     * @param [string] $msg error message string
248
     */
0 ignored issues
show
Documentation Bug introduced by
The doc comment [string] at position 0 could not be parsed: Unknown type name '[' at position 0 in [string].
Loading history...
249
    public function setErrorMsg($msg)
250
    {
251
        $this->error_msg = $msg;
252
        return $this;
253
    }
254
255
    public function getErrorMsg()
256
    {
257
        return $this->error_msg;
258
    }
259
260
    /**
261
     * Creates a database accessor
262
     *
263
     * @param string $database
264
     * @param null   $server_id
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $server_id is correct as it would always require null to be passed?
Loading history...
265
     * @return null
266
     */
267
    public function getDatabaseAccessor($database = '', $server_id = null)
0 ignored issues
show
Coding Style introduced by
getDatabaseAccessor uses the super-global variable $_REQUEST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
268
    {
269
        $lang = $this->lang;
270
271
        if ($server_id !== null) {
272
            $this->server_id = $server_id;
273
        }
274
275
        $server_info = $this->getServerInfo($this->server_id);
276
277
        if ($this->_no_db_connection || !isset($server_info['username'])) {
278
            return null;
279
        }
280
281
        if ($this->data === null) {
282
            try {
283
                $_connection = $this->getConnection($database, $this->server_id);
284
            } catch (\Exception $e) {
285
                $this->setServerInfo(null, null, $this->server_id);
286
                $this->setNoDBConnection(true);
287
                $this->setErrorMsg($e->getMessage());
288
                return null;
289
            }
290
291
            //$this->prtrace('_connection', $_connection);
292
            if (!$_connection) {
293
                $this->container->utils->addError($lang['strloginfailed']);
294
                $this->setErrorMsg($lang['strloginfailed']);
295
                return null;
296
            }
297
            // Get the name of the database driver we need to use.
298
            // The description of the server is returned in $platform.
299
            $_type = $_connection->getDriver($platform);
300
301
            //$this->prtrace(['type' => $_type, 'platform' => $platform, 'pgVersion' => $_connection->conn->pgVersion]);
302
303
            if ($_type === null) {
304
                $errormsg = sprintf($lang['strpostgresqlversionnotsupported'], $this->postgresqlMinVer);
305
                $this->container->utils->addError($errormsg);
306
                $this->setErrorMsg($errormsg);
307
                return null;
308
            }
309
            $_type = '\PHPPgAdmin\Database\\' . $_type;
310
311
            $this->setServerInfo('platform', $platform, $this->server_id);
312
            $this->setServerInfo('pgVersion', $_connection->conn->pgVersion, $this->server_id);
313
314
            // Create a database wrapper class for easy manipulation of the
315
            // connection.
316
317
            $this->data              = new $_type($_connection->conn, $this->conf);
318
            $this->data->platform    = $_connection->platform;
319
            $this->data->server_info = $server_info;
320
            $this->data->conf        = $this->conf;
321
            $this->data->lang        = $this->lang;
322
323
            //$this->data->getHelpPages();
324
325
            //$this->prtrace('help_page has ' . count($this->data->help_page) . ' items');
326
327
            /* we work on UTF-8 only encoding */
328
            $this->data->execute("SET client_encoding TO 'UTF-8'");
329
330
            if ($this->data->hasByteaHexDefault()) {
331
                $this->data->execute('SET bytea_output TO escape');
332
            }
333
        }
334
335
        if ($this->_no_db_connection === false && $this->getDatabase() !== null && isset($_REQUEST['schema'])) {
336
            $status = $this->data->setSchema($_REQUEST['schema']);
337
338
            if ($status != 0) {
339
                $this->container->utils->addError($this->lang['strbadschema']);
340
                $this->setErrorMsg($this->lang['strbadschema']);
341
                return null;
342
            }
343
        }
344
345
        return $this->data;
346
    }
347
348
    public function getConnection($database = '', $server_id = null)
349
    {
350
        $lang = $this->lang;
351
352
        if ($this->_connection === null) {
353
            if ($server_id !== null) {
354
                $this->server_id = $server_id;
355
            }
356
            $server_info     = $this->getServerInfo($this->server_id);
357
            $database_to_use = $this->getDatabase($database);
358
359
            // Perform extra security checks if this config option is set
360
            if ($this->conf['extra_login_security']) {
361
                // Disallowed logins if extra_login_security is enabled.
362
                // These must be lowercase.
363
                $bad_usernames = [
364
                    'pgsql'         => 'pgsql',
365
                    'postgres'      => 'postgres',
366
                    'root'          => 'root',
367
                    'administrator' => 'administrator',
368
                ];
369
370
                if (isset($server_info['username']) && array_key_exists(strtolower($server_info['username']), $bad_usernames)) {
371
                    $msg = $lang['strlogindisallowed'];
372
                    throw new \Exception($msg);
373
                }
374
375
                if (!isset($server_info['password']) || $server_info['password'] == '') {
376
                    $msg = $lang['strlogindisallowed'];
377
378
                    throw new \Exception($msg);
379
                }
380
            }
381
382
            try {
383
                // Create the connection object and make the connection
384
                $this->_connection = new \PHPPgAdmin\Database\Connection(
385
                    $server_info['host'],
386
                    $server_info['port'],
387
                    $server_info['sslmode'],
388
                    $server_info['username'],
389
                    $server_info['password'],
390
                    $database_to_use
391
                );
392
            } catch (\PHPPgAdmin\ADOdbException $e) {
393
                throw new \Exception($lang['strloginfailed']);
394
            }
395
        }
396
        return $this->_connection;
397
    }
398
399
    /**
400
     * Validate and retrieve information on a server.
401
     * If the parameter isn't supplied then the currently
402
     * connected server is returned.
403
     * @param $server_id A server identifier (host:port)
404
     * @return An associative array of server properties
405
     */
406
    public function getServerInfo($server_id = null)
0 ignored issues
show
Coding Style introduced by
getServerInfo uses the super-global variable $_SESSION which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
407
    {
408
409
        //\PC::debug(['$server_id' => $server_id]);
410
411
        if ($server_id !== null) {
412
            $this->server_id = $server_id;
413
        } elseif ($this->server_info !== null) {
414
            return $this->server_info;
415
        }
416
417
        // Check for the server in the logged-in list
418
        if (isset($_SESSION['webdbLogin'][$this->server_id])) {
419
            $this->server_info = $_SESSION['webdbLogin'][$this->server_id];
420
            return $this->server_info;
421
        }
422
423
        // Otherwise, look for it in the conf file
424
        foreach ($this->conf['servers'] as $idx => $info) {
425
            if ($this->server_id == $info['host'] . ':' . $info['port'] . ':' . $info['sslmode']) {
426
                // Automatically use shared credentials if available
427
                if (!isset($info['username']) && isset($_SESSION['sharedUsername'])) {
428
                    $info['username'] = $_SESSION['sharedUsername'];
429
                    $info['password'] = $_SESSION['sharedPassword'];
430
                    $this->setReloadBrowser(true);
431
                    $this->setServerInfo(null, $info, $this->server_id);
432
                }
433
                $this->server_info = $info;
434
                return $this->server_info;
435
            }
436
        }
437
438
        if ($server_id === null) {
439
            $this->server_info = null;
440
            return $this->server_info;
441
        }
442
443
        $this->server_info = null;
444
        // Unable to find a matching server, are we being hacked?
445
        echo $this->lang['strinvalidserverparam'];
446
447
        exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The method getServerInfo() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
448
    }
449
450
    /**
451
     * Set server information.
452
     * @param $key parameter name to set, or null to replace all
453
     *             params with the assoc-array in $value.
454
     * @param $value the new value, or null to unset the parameter
455
     * @param $server_id the server identifier, or null for current
456
     *                   server.
457
     */
458
    public function setServerInfo($key, $value, $server_id = null)
0 ignored issues
show
Coding Style introduced by
setServerInfo uses the super-global variable $_REQUEST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
Coding Style introduced by
setServerInfo uses the super-global variable $_SESSION which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
459
    {
460
        //\PC::debug('setsetverinfo');
461
        if ($server_id === null && isset($_REQUEST['server'])) {
462
            $server_id = $_REQUEST['server'];
463
        }
464
465
        if ($key === null) {
466 View Code Duplication
            if ($value === null) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
467
                unset($_SESSION['webdbLogin'][$server_id]);
468
            } else {
469
                //\PC::debug(['server_id' => $server_id, 'value' => $value], 'webdbLogin null key');
470
                $_SESSION['webdbLogin'][$server_id] = $value;
471
            }
472 View Code Duplication
        } else {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
473
            if ($value === null) {
474
                unset($_SESSION['webdbLogin'][$server_id][$key]);
475
            } else {
476
                //\PC::debug(['server_id' => $server_id, 'key' => $key, 'value' => $value], __FILE__ . ' ' . __LINE__ . ' webdbLogin key ' . $key);
477
                $_SESSION['webdbLogin'][$server_id][$key] = $value;
478
            }
479
        }
480
    }
481
482
    public function getDatabase($database = '')
0 ignored issues
show
Coding Style introduced by
getDatabase uses the super-global variable $_REQUEST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
483
    {
484
        if ($this->server_id === null && !isset($_REQUEST['database'])) {
485
            return null;
486
        }
487
488
        $server_info = $this->getServerInfo($this->server_id);
489
490
        if ($this->server_id !== null && isset($server_info['useonlydefaultdb']) && $server_info['useonlydefaultdb'] === true) {
491
            $this->database = $server_info['defaultdb'];
492
        } elseif ($database !== '') {
493
            $this->database = $database;
494
        } elseif (isset($_REQUEST['database'])) {
495
            // Connect to the current database
496
            $this->database = $_REQUEST['database'];
497
        } else {
498
            // or if one is not specified then connect to the default database.
499
            $this->database = $server_info['defaultdb'];
500
        }
501
502
        return $this->database;
503
    }
504
505
    /**
506
     * Get list of server groups
507
     *
508
     * @param bool $recordset return as RecordSet suitable for HTMLTableController::printTable if true, otherwise just return an array.
509
     * @param mixed $group_id     a group name to filter the returned servers using $this->conf[srv_groups]
510
     * @return array|\PHPPgAdmin\ArrayRecordSet either an array or a Recordset suitable for HTMLTableController::printTable
511
     */
512
    public function getServersGroups($recordset = false, $group_id = false)
513
    {
514
        $lang = $this->lang;
515
        $grps = [];
516
517
        if (isset($this->conf['srv_groups'])) {
518
            foreach ($this->conf['srv_groups'] as $i => $group) {
519
                if (
520
                    (($group_id === false) and (!isset($group['parents']))) /* root */
521
                    or (
522
                        ($group_id !== false)
523
                        and isset($group['parents'])
524
                        and in_array($group_id, explode(',',
525
                            preg_replace('/\s/', '', $group['parents'])
526
                        ))
527
                    ) /* nested group */
528
                ) {
529
                    $grps[$i] = [
530
                        'id'     => $i,
531
                        'desc'   => $group['desc'],
532
                        'icon'   => 'Servers',
533
                        'action' => Decorator::url('/views/servers',
534
                            [
535
                                'group' => Decorator::field('id'),
536
                            ]
537
                        ),
538
                        'branch' => Decorator::url('/tree/servers',
539
                            [
540
                                'group' => $i,
541
                            ]
542
                        ),
543
                    ];
544
                }
545
            }
546
547
            if ($group_id === false) {
548
                $grps['all'] = [
549
                    'id'     => 'all',
550
                    'desc'   => $lang['strallservers'],
551
                    'icon'   => 'Servers',
552
                    'action' => Decorator::url('/views/servers',
553
                        [
554
                            'group' => Decorator::field('id'),
555
                        ]
556
                    ),
557
                    'branch' => Decorator::url('/tree/servers',
558
                        [
559
                            'group' => 'all',
560
                        ]
561
                    ),
562
                ];
563
            }
564
        }
565
566
        if ($recordset) {
567
            return new ArrayRecordSet($grps);
568
        }
569
570
        return $grps;
571
    }
572
573
    /**
574
     * Get list of servers
575
     *
576
     * @param bool $recordset return as RecordSet suitable for HTMLTableController::printTable if true, otherwise just return an array.
577
     * @param mixed $group     a group name to filter the returned servers using $this->conf[srv_groups]
578
     * @return array|\PHPPgAdmin\ArrayRecordSet either an array or a Recordset suitable for HTMLTableController::printTable
579
     */
580
    public function getServers($recordset = false, $group = false)
0 ignored issues
show
Coding Style introduced by
getServers uses the super-global variable $_SESSION which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
581
    {
582
        $logins = isset($_SESSION['webdbLogin']) && is_array($_SESSION['webdbLogin']) ? $_SESSION['webdbLogin'] : [];
583
        $srvs   = [];
584
585
        if (($group !== false) && ($group !== 'all')) {
586
            if (isset($this->conf['srv_groups'][$group]['servers'])) {
587
                $group = array_fill_keys(explode(',', preg_replace('/\s/', '',
588
                    $this->conf['srv_groups'][$group]['servers'])), 1);
589
            } else {
590
                $group = '';
591
            }
592
        }
593
594
        foreach ($this->conf['servers'] as $idx => $info) {
595
            $server_id = $info['host'] . ':' . $info['port'] . ':' . $info['sslmode'];
596
            if ($group === false || isset($group[$idx]) || ($group === 'all')) {
597
                $server_id = $info['host'] . ':' . $info['port'] . ':' . $info['sslmode'];
598
599
                if (isset($logins[$server_id])) {
600
                    $srvs[$server_id] = $logins[$server_id];
601
                } else {
602
                    $srvs[$server_id] = $info;
603
                }
604
605
                $srvs[$server_id]['id']     = $server_id;
606
                $srvs[$server_id]['action'] = Decorator::url('/redirect/server',
607
                    [
608
                        'server' => Decorator::field('id'),
609
                    ]
610
                );
611
                if (isset($srvs[$server_id]['username'])) {
612
                    $srvs[$server_id]['icon']   = 'Server';
613
                    $srvs[$server_id]['branch'] = Decorator::url('/src/views/alldb',
614
                        [
615
                            'action'  => 'tree',
616
                            'subject' => 'server',
617
                            'server'  => Decorator::field('id'),
618
                        ]
619
                    );
620
                } else {
621
                    $srvs[$server_id]['icon']   = 'DisconnectedServer';
622
                    $srvs[$server_id]['branch'] = false;
623
                }
624
            }
625
        }
626
627
        uasort($srvs, ['self', '_cmp_desc']);
628
629
        if ($recordset) {
630
            return new ArrayRecordSet($srvs);
631
        }
632
        return $srvs;
633
    }
634
635
    /**
636
     * Set the current schema
637
     *
638
     * @param $schema The schema name
639
     * @return int 0 on success
640
     */
641
    public function setCurrentSchema($schema)
0 ignored issues
show
Coding Style introduced by
setCurrentSchema uses the super-global variable $_REQUEST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
642
    {
643
        $data = $this->getDatabaseAccessor();
644
645
        $status = $data->setSchema($schema);
646
        if ($status != 0) {
647
            return $status;
648
        }
649
650
        $_REQUEST['schema'] = $schema;
651
        $this->setHREF();
652
        return 0;
653
    }
654
655
    public static function _cmp_desc($a, $b)
656
    {
657
        return strcmp($a['desc'], $b['desc']);
658
    }
659
660
    /**
661
     * Checks if dumps are properly set up
662
     * @param $all (optional) True to check pg_dumpall, false to just check pg_dump
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 $exclude_from
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $exclude_from is correct as it would always require null to be passed?
Loading history...
686
     * @return string
687
     */
688
    public function getHREF($exclude_from = null)
0 ignored issues
show
Coding Style introduced by
getHREF uses the super-global variable $_REQUEST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
689
    {
690
        $href = [];
691 View Code Duplication
        if (isset($_REQUEST['server']) && $exclude_from != 'server') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
692
            $href[] = 'server=' . urlencode($_REQUEST['server']);
693
        }
694 View Code Duplication
        if (isset($_REQUEST['database']) && $exclude_from != 'database') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
695
            $href[] = 'database=' . urlencode($_REQUEST['database']);
696
        }
697 View Code Duplication
        if (isset($_REQUEST['schema']) && $exclude_from != 'schema') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
698
            $href[] = 'schema=' . urlencode($_REQUEST['schema']);
699
        }
700
701
        return htmlentities(implode('&', $href));
702
    }
703
704
    public function getSubjectParams($subject)
0 ignored issues
show
Coding Style introduced by
getSubjectParams uses the super-global variable $_REQUEST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
705
    {
706
        $plugin_manager = $this->plugin_manager;
707
708
        $vars = [];
709
710
        switch ($subject) {
711
            case 'root':
712
                $vars = [
713
                    'params' => [
714
                        'subject' => 'root',
715
                    ],
716
                ];
717
                break;
718
            case 'server':
719
                $vars = ['params' => [
720
                    'server'  => $_REQUEST['server'],
721
                    'subject' => 'server',
722
                ]];
723
                break;
724
            case 'role':
725
                $vars = ['params' => [
726
                    'server'   => $_REQUEST['server'],
727
                    'subject'  => 'role',
728
                    'action'   => 'properties',
729
                    'rolename' => $_REQUEST['rolename'],
730
                ]];
731
                break;
732
            case 'database':
733
                $vars = ['params' => [
734
                    'server'   => $_REQUEST['server'],
735
                    'subject'  => 'database',
736
                    'database' => $_REQUEST['database'],
737
                ]];
738
                break;
739
            case 'schema':
740
                $vars = ['params' => [
741
                    'server'   => $_REQUEST['server'],
742
                    'subject'  => 'schema',
743
                    'database' => $_REQUEST['database'],
744
                    'schema'   => $_REQUEST['schema'],
745
                ]];
746
                break;
747
            case 'table':
748
                $vars = ['params' => [
749
                    'server'   => $_REQUEST['server'],
750
                    'subject'  => 'table',
751
                    'database' => $_REQUEST['database'],
752
                    'schema'   => $_REQUEST['schema'],
753
                    'table'    => $_REQUEST['table'],
754
                ]];
755
                break;
756 View Code Duplication
            case 'selectrows':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
757
                $vars = [
758
                    'url'    => 'tables.php',
759
                    'params' => [
760
                        'server'   => $_REQUEST['server'],
761
                        'subject'  => 'table',
762
                        'database' => $_REQUEST['database'],
763
                        'schema'   => $_REQUEST['schema'],
764
                        'table'    => $_REQUEST['table'],
765
                        'action'   => 'confselectrows',
766
                    ]];
767
                break;
768
            case 'view':
769
                $vars = ['params' => [
770
                    'server'   => $_REQUEST['server'],
771
                    'subject'  => 'view',
772
                    'database' => $_REQUEST['database'],
773
                    'schema'   => $_REQUEST['schema'],
774
                    'view'     => $_REQUEST['view'],
775
                ]];
776
                break;
777
            case 'matview':
778
                $vars = ['params' => [
779
                    'server'   => $_REQUEST['server'],
780
                    'subject'  => 'matview',
781
                    'database' => $_REQUEST['database'],
782
                    'schema'   => $_REQUEST['schema'],
783
                    'matview'  => $_REQUEST['matview'],
784
                ]];
785
                break;
786
787
            case 'fulltext':
788 View Code Duplication
            case 'ftscfg':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
789
                $vars = ['params' => [
790
                    'server'   => $_REQUEST['server'],
791
                    'subject'  => 'fulltext',
792
                    'database' => $_REQUEST['database'],
793
                    'schema'   => $_REQUEST['schema'],
794
                    'action'   => 'viewconfig',
795
                    'ftscfg'   => $_REQUEST['ftscfg'],
796
                ]];
797
                break;
798 View Code Duplication
            case 'function':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
799
                $vars = ['params' => [
800
                    'server'       => $_REQUEST['server'],
801
                    'subject'      => 'function',
802
                    'database'     => $_REQUEST['database'],
803
                    'schema'       => $_REQUEST['schema'],
804
                    'function'     => $_REQUEST['function'],
805
                    'function_oid' => $_REQUEST['function_oid'],
806
                ]];
807
                break;
808 View Code Duplication
            case 'aggregate':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
809
                $vars = ['params' => [
810
                    'server'   => $_REQUEST['server'],
811
                    'subject'  => 'aggregate',
812
                    'action'   => 'properties',
813
                    'database' => $_REQUEST['database'],
814
                    'schema'   => $_REQUEST['schema'],
815
                    'aggrname' => $_REQUEST['aggrname'],
816
                    'aggrtype' => $_REQUEST['aggrtype'],
817
                ]];
818
                break;
819
            case 'column':
820
                if (isset($_REQUEST['table'])) {
821
                    $vars = ['params' => [
822
                        'server'   => $_REQUEST['server'],
823
                        'subject'  => 'column',
824
                        'database' => $_REQUEST['database'],
825
                        'schema'   => $_REQUEST['schema'],
826
                        'table'    => $_REQUEST['table'],
827
                        'column'   => $_REQUEST['column'],
828
                    ]];
829
                } else {
830
                    $vars = ['params' => [
831
                        'server'   => $_REQUEST['server'],
832
                        'subject'  => 'column',
833
                        'database' => $_REQUEST['database'],
834
                        'schema'   => $_REQUEST['schema'],
835
                        'view'     => $_REQUEST['view'],
836
                        'column'   => $_REQUEST['column'],
837
                    ]];
838
                }
839
840
                break;
841
            case 'plugin':
842
                $vars = [
843
                    'url'    => 'plugin.php',
844
                    'params' => [
845
                        'server'  => $_REQUEST['server'],
846
                        'subject' => 'plugin',
847
                        'plugin'  => $_REQUEST['plugin'],
848
                    ]];
849
850
                if (!is_null($plugin_manager->getPlugin($_REQUEST['plugin']))) {
851
                    $vars['params'] = array_merge($vars['params'], $plugin_manager->getPlugin($_REQUEST['plugin'])->get_subject_params());
852
                }
853
854
                break;
855
            default:
856
                return false;
857
        }
858
859
        if (!isset($vars['url'])) {
860
            $vars['url'] = SUBFOLDER . '/redirect';
861
        }
862
        if ($vars['url'] == SUBFOLDER . '/redirect' && isset($vars['params']['subject'])) {
863
            $vars['url'] = SUBFOLDER . '/redirect/' . $vars['params']['subject'];
864
            unset($vars['params']['subject']);
865
        }
866
867
        return $vars;
868
    }
869
870
    /**
871
     * Sets the form tracking variable
872
     */
873
    public function setForm()
0 ignored issues
show
Coding Style introduced by
setForm uses the super-global variable $_REQUEST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
874
    {
875
        $form = [];
876
        if (isset($_REQUEST['server'])) {
877
            $form[] = '<input type="hidden" name="server" value="' . htmlspecialchars($_REQUEST['server']) . '" />';
878
        }
879
        if (isset($_REQUEST['database'])) {
880
            $form[] = '<input type="hidden" name="database" value="' . htmlspecialchars($_REQUEST['database']) . '" />';
881
        }
882
883
        if (isset($_REQUEST['schema'])) {
884
            $form[] = '<input type="hidden" name="schema" value="' . htmlspecialchars($_REQUEST['schema']) . '" />';
885
        }
886
        $this->form = implode("\n", $form);
887
        return $this->form;
888
889
        //\PC::debug($this->form, 'Misc::form');
890
    }
891
892
    /**
893
     * Render a value into HTML using formatting rules specified
894
     * by a type name and parameters.
895
     *
896
     * @param                        $str    The string to change
897
     *
898
     * @param                        $type   Field type (optional), this may be an internal PostgreSQL type, or:
899
     *                                       yesno    - same as bool, but renders as 'Yes' or 'No'.
900
     *                                       pre      - render in a <pre> block.
901
     *                                       nbsp     - replace all spaces with &nbsp;'s
902
     *                                       verbatim - render exactly as supplied, no escaping what-so-ever.
903
     *                                       callback - render using a callback function supplied in the 'function' param.
904
     *
905
     * @param array|\PHPPgAdmin\Type $params Type parameters (optional), known parameters:
906
     *                                       null     - string to display if $str is null, or set to TRUE to use a default 'NULL' string,
907
     *                                       otherwise nothing is rendered.
908
     *                                       clip     - if true, clip the value to a fixed length, and append an ellipsis...
909
     *                                       cliplen  - the maximum length when clip is enabled (defaults to $conf['max_chars'])
910
     *                                       ellipsis - the string to append to a clipped value (defaults to $lang['strellipsis'])
911
     *                                       tag      - an HTML element name to surround the value.
912
     *                                       class    - a class attribute to apply to any surrounding HTML element.
913
     *                                       align    - an align attribute ('left','right','center' etc.)
914
     *                                       true     - (type='bool') the representation of true.
915
     *                                       false    - (type='bool') the representation of false.
916
     *                                       function - (type='callback') a function name, accepts args ($str, $params) and returns a rendering.
917
     *                                       lineno   - prefix each line with a line number.
918
     *                                       map      - an associative array.
919
     * @return \PHPPgAdmin\The HTML rendered value
920
     */
921
    public function printVal($str, $type = null, $params = [])
922
    {
923
        $lang = $this->lang;
924
        $data = $this->data;
925
926
        // Shortcircuit for a NULL value
927
        if (is_null($str)) {
928
            return isset($params['null'])
929
            ? ($params['null'] === true ? '<i>NULL</i>' : $params['null'])
930
            : '';
931
        }
932
933
        if (isset($params['map']) && isset($params['map'][$str])) {
934
            $str = $params['map'][$str];
935
        }
936
937
        // Clip the value if the 'clip' parameter is true.
938
        if (isset($params['clip']) && $params['clip'] === true) {
939
            $maxlen   = isset($params['cliplen']) && is_integer($params['cliplen']) ? $params['cliplen'] : $this->conf['max_chars'];
940
            $ellipsis = isset($params['ellipsis']) ? $params['ellipsis'] : $lang['strellipsis'];
941
            if (strlen($str) > $maxlen) {
942
                $str = substr($str, 0, $maxlen - 1) . $ellipsis;
943
            }
944
        }
945
946
        $out = '';
947
948
        switch ($type) {
949
            case 'int2':
950
            case 'int4':
951
            case 'int8':
952
            case 'float4':
953
            case 'float8':
954
            case 'money':
955
            case 'numeric':
956
            case 'oid':
957
            case 'xid':
958
            case 'cid':
959
            case 'tid':
960
                $align = 'right';
961
                $out   = nl2br(htmlspecialchars(\PHPPgAdmin\HelperTrait::br2ln($str)));
962
                break;
963
            case 'yesno':
964
                if (!isset($params['true'])) {
965
                    $params['true'] = $lang['stryes'];
966
                }
967
968
                if (!isset($params['false'])) {
969
                    $params['false'] = $lang['strno'];
970
                }
971
972
            // No break - fall through to boolean case.
973
            case 'bool':
974
            case 'boolean':
975
                if (is_bool($str)) {
976
                    $str = $str ? 't' : 'f';
977
                }
978
979
                switch ($str) {
980
                    case 't':
981
                        $out   = (isset($params['true']) ? $params['true'] : $lang['strtrue']);
982
                        $align = 'center';
983
                        break;
984
                    case 'f':
985
                        $out   = (isset($params['false']) ? $params['false'] : $lang['strfalse']);
986
                        $align = 'center';
987
                        break;
988
                    default:
989
                        $out = htmlspecialchars($str);
990
                }
991
                break;
992
            case 'bytea':
993
                $tag   = 'div';
994
                $class = 'pre';
995
                $out   = $data->escapeBytea($str);
996
                break;
997
            case 'errormsg':
998
                $tag   = 'pre';
999
                $class = 'error';
1000
                $out   = htmlspecialchars($str);
1001
                break;
1002
            case 'pre':
1003
                $tag = 'pre';
1004
                $out = htmlspecialchars($str);
1005
                break;
1006
            case 'prenoescape':
1007
                $tag = 'pre';
1008
                $out = $str;
1009
                break;
1010
            case 'nbsp':
1011
                $out = nl2br(str_replace(' ', '&nbsp;', \PHPPgAdmin\HelperTrait::br2ln($str)));
1012
1013
                break;
1014
            case 'verbatim':
1015
                $out = $str;
1016
                break;
1017
            case 'callback':
1018
                $out = $params['function']($str, $params);
1019
                break;
1020
            case 'prettysize':
1021
                if ($str == -1) {
1022
                    $out = $lang['strnoaccess'];
1023
                } else {
1024
                    $limit = 10 * 1024;
1025
                    $mult  = 1;
1026
                    if ($str < $limit * $mult) {
1027
                        $out = $str . ' ' . $lang['strbytes'];
1028
                    } else {
1029
                        $mult *= 1024;
1030
                        if ($str < $limit * $mult) {
1031
                            $out = floor(($str + $mult / 2) / $mult) . ' ' . $lang['strkb'];
1032
                        } else {
1033
                            $mult *= 1024;
1034
                            if ($str < $limit * $mult) {
1035
                                $out = floor(($str + $mult / 2) / $mult) . ' ' . $lang['strmb'];
1036
                            } else {
1037
                                $mult *= 1024;
1038
                                if ($str < $limit * $mult) {
1039
                                    $out = floor(($str + $mult / 2) / $mult) . ' ' . $lang['strgb'];
1040
                                } else {
1041
                                    $mult *= 1024;
1042
                                    if ($str < $limit * $mult) {
1043
                                        $out = floor(($str + $mult / 2) / $mult) . ' ' . $lang['strtb'];
1044
                                    }
1045
                                }
1046
                            }
1047
                        }
1048
                    }
1049
                }
1050
                break;
1051
            default:
1052
                // If the string contains at least one instance of >1 space in a row, a tab
1053
                // character, a space at the start of a line, or a space at the start of
1054
                // the whole string then render within a pre-formatted element (<pre>).
1055
                if (preg_match('/(^ |  |\t|\n )/m', $str)) {
1056
                    $tag   = 'pre';
1057
                    $class = 'data';
1058
                    $out   = htmlspecialchars($str);
1059
                } else {
1060
                    $out = nl2br(htmlspecialchars(\PHPPgAdmin\HelperTrait::br2ln($str)));
1061
                }
1062
        }
1063
1064
        if (isset($params['class'])) {
1065
            $class = $params['class'];
1066
        }
1067
1068
        if (isset($params['align'])) {
1069
            $align = $params['align'];
1070
        }
1071
1072
        if (!isset($tag) && (isset($class) || isset($align))) {
1073
            $tag = 'div';
1074
        }
1075
1076
        if (isset($tag)) {
1077
            $alignattr = isset($align) ? " style=\"text-align: {$align}\"" : '';
1078
            $classattr = isset($class) ? " class=\"{$class}\"" : '';
1079
            $out       = "<{$tag}{$alignattr}{$classattr}>{$out}</{$tag}>";
1080
        }
1081
1082
        // Add line numbers if 'lineno' param is true
1083
        if (isset($params['lineno']) && $params['lineno'] === true) {
1084
            $lines = explode("\n", $str);
1085
            $num   = count($lines);
1086
            if ($num > 0) {
1087
                $temp = "<table>\n<tr><td class=\"{$class}\" style=\"vertical-align: top; padding-right: 10px;\"><pre class=\"{$class}\">";
1088
                for ($i = 1; $i <= $num; $i++) {
1089
                    $temp .= $i . "\n";
1090
                }
1091
                $temp .= "</pre></td><td class=\"{$class}\" style=\"vertical-align: top;\">{$out}</td></tr></table>\n";
1092
                $out = $temp;
1093
            }
1094
            unset($lines);
1095
        }
1096
1097
        return $out;
1098
    }
1099
1100
    /**
1101
     * A function to recursively strip slashes.  Used to
1102
     * enforce magic_quotes_gpc being off.
1103
     * @param &var The variable to strip
1104
     */
1105
    public function stripVar(&$var)
1106
    {
1107
        if (is_array($var)) {
1108
            foreach ($var as $k => $v) {
1109
                $this->stripVar($var[$k]);
1110
1111
                /* magic_quotes_gpc escape keys as well ...*/
1112
                if (is_string($k)) {
1113
                    $ek = stripslashes($k);
1114
                    if ($ek !== $k) {
1115
                        $var[$ek] = $var[$k];
1116
                        unset($var[$k]);
1117
                    }
1118
                }
1119
            }
1120
        } else {
1121
            $var = stripslashes($var);
1122
        }
1123
    }
1124
1125
    /**
1126
     * Retrieve the tab info for a specific tab bar.
1127
     *
1128
     * @param $section The name of the tab bar.
1129
     * @return array
1130
     */
1131
    public function getNavTabs($section)
1132
    {
1133
        $data           = $this->data;
1134
        $lang           = $this->lang;
1135
        $plugin_manager = $this->plugin_manager;
1136
1137
        $hide_advanced = ($this->conf['show_advanced'] === false);
1138
        $tabs          = [];
1139
1140
        switch ($section) {
1141
            case 'root':
1142
                $tabs = [
1143
                    'intro'   => [
1144
                        'title' => $lang['strintroduction'],
1145
                        'url'   => 'intro.php',
1146
                        'icon'  => 'Introduction',
1147
                    ],
1148
                    'servers' => [
1149
                        'title' => $lang['strservers'],
1150
                        'url'   => 'servers.php',
1151
                        'icon'  => 'Servers',
1152
                    ],
1153
                ];
1154
                break;
1155
1156
            case 'server':
1157
                $hide_users = true;
1158
                if ($data) {
1159
                    $hide_users = !$data->isSuperUser();
1160
                }
1161
1162
                $tabs = [
1163
                    'databases' => [
1164
                        'title'   => $lang['strdatabases'],
1165
                        'url'     => 'alldb.php',
1166
                        'urlvars' => ['subject' => 'server'],
1167
                        'help'    => 'pg.database',
1168
                        'icon'    => 'Databases',
1169
                    ],
1170
                ];
1171
                if ($data && $data->hasRoles()) {
1172
                    $tabs = array_merge($tabs, [
1173
                        'roles' => [
1174
                            'title'   => $lang['strroles'],
1175
                            'url'     => 'roles.php',
1176
                            'urlvars' => ['subject' => 'server'],
1177
                            'hide'    => $hide_users,
1178
                            'help'    => 'pg.role',
1179
                            'icon'    => 'Roles',
1180
                        ],
1181
                    ]);
1182
                } else {
1183
                    $tabs = array_merge($tabs, [
1184
                        'users'  => [
1185
                            'title'   => $lang['strusers'],
1186
                            'url'     => 'users.php',
1187
                            'urlvars' => ['subject' => 'server'],
1188
                            'hide'    => $hide_users,
1189
                            'help'    => 'pg.user',
1190
                            'icon'    => 'Users',
1191
                        ],
1192
                        'groups' => [
1193
                            'title'   => $lang['strgroups'],
1194
                            'url'     => 'groups.php',
1195
                            'urlvars' => ['subject' => 'server'],
1196
                            'hide'    => $hide_users,
1197
                            'help'    => 'pg.group',
1198
                            'icon'    => 'UserGroups',
1199
                        ],
1200
                    ]);
1201
                }
1202
1203
                $tabs = array_merge($tabs, [
1204
                    'account'     => [
1205
                        'title'   => $lang['straccount'],
1206
                        'url'     => ($data && $data->hasRoles()) ? 'roles.php' : 'users.php',
1207
                        'urlvars' => ['subject' => 'server', 'action' => 'account'],
1208
                        'hide'    => !$hide_users,
1209
                        'help'    => 'pg.role',
1210
                        'icon'    => 'User',
1211
                    ],
1212
                    'tablespaces' => [
1213
                        'title'   => $lang['strtablespaces'],
1214
                        'url'     => 'tablespaces.php',
1215
                        'urlvars' => ['subject' => 'server'],
1216
                        'hide'    => !$data || !$data->hasTablespaces(),
1217
                        'help'    => 'pg.tablespace',
1218
                        'icon'    => 'Tablespaces',
1219
                    ],
1220
                    'export'      => [
1221
                        'title'   => $lang['strexport'],
1222
                        'url'     => 'alldb.php',
1223
                        'urlvars' => ['subject' => 'server', 'action' => 'export'],
1224
                        'hide'    => !$this->isDumpEnabled(),
1225
                        'icon'    => 'Export',
1226
                    ],
1227
                ]);
1228
                break;
1229
            case 'database':
1230
                $tabs = [
1231
                    'schemas'    => [
1232
                        'title'   => $lang['strschemas'],
1233
                        'url'     => 'schemas.php',
1234
                        'urlvars' => ['subject' => 'database'],
1235
                        'help'    => 'pg.schema',
1236
                        'icon'    => 'Schemas',
1237
                    ],
1238
                    'sql'        => [
1239
                        'title'   => $lang['strsql'],
1240
                        'url'     => 'database.php',
1241
                        'urlvars' => ['subject' => 'database', 'action' => 'sql', 'new' => 1],
1242
                        'help'    => 'pg.sql',
1243
                        'tree'    => false,
1244
                        'icon'    => 'SqlEditor',
1245
                    ],
1246
                    'find'       => [
1247
                        'title'   => $lang['strfind'],
1248
                        'url'     => 'database.php',
1249
                        'urlvars' => ['subject' => 'database', 'action' => 'find'],
1250
                        'tree'    => false,
1251
                        'icon'    => 'Search',
1252
                    ],
1253
                    'variables'  => [
1254
                        'title'   => $lang['strvariables'],
1255
                        'url'     => 'database.php',
1256
                        'urlvars' => ['subject' => 'database', 'action' => 'variables'],
1257
                        'help'    => 'pg.variable',
1258
                        'tree'    => false,
1259
                        'icon'    => 'Variables',
1260
                    ],
1261
                    'processes'  => [
1262
                        'title'   => $lang['strprocesses'],
1263
                        'url'     => 'database.php',
1264
                        'urlvars' => ['subject' => 'database', 'action' => 'processes'],
1265
                        'help'    => 'pg.process',
1266
                        'tree'    => false,
1267
                        'icon'    => 'Processes',
1268
                    ],
1269
                    'locks'      => [
1270
                        'title'   => $lang['strlocks'],
1271
                        'url'     => 'database.php',
1272
                        'urlvars' => ['subject' => 'database', 'action' => 'locks'],
1273
                        'help'    => 'pg.locks',
1274
                        'tree'    => false,
1275
                        'icon'    => 'Key',
1276
                    ],
1277
                    'admin'      => [
1278
                        'title'   => $lang['stradmin'],
1279
                        'url'     => 'database.php',
1280
                        'urlvars' => ['subject' => 'database', 'action' => 'admin'],
1281
                        'tree'    => false,
1282
                        'icon'    => 'Admin',
1283
                    ],
1284
                    'privileges' => [
1285
                        'title'   => $lang['strprivileges'],
1286
                        'url'     => 'privileges.php',
1287
                        'urlvars' => ['subject' => 'database'],
1288
                        'hide'    => !isset($data->privlist['database']),
1289
                        'help'    => 'pg.privilege',
1290
                        'tree'    => false,
1291
                        'icon'    => 'Privileges',
1292
                    ],
1293
                    'languages'  => [
1294
                        'title'   => $lang['strlanguages'],
1295
                        'url'     => 'languages.php',
1296
                        'urlvars' => ['subject' => 'database'],
1297
                        'hide'    => $hide_advanced,
1298
                        'help'    => 'pg.language',
1299
                        'icon'    => 'Languages',
1300
                    ],
1301
                    'casts'      => [
1302
                        'title'   => $lang['strcasts'],
1303
                        'url'     => 'casts.php',
1304
                        'urlvars' => ['subject' => 'database'],
1305
                        'hide'    => $hide_advanced,
1306
                        'help'    => 'pg.cast',
1307
                        'icon'    => 'Casts',
1308
                    ],
1309
                    'export'     => [
1310
                        'title'   => $lang['strexport'],
1311
                        'url'     => 'database.php',
1312
                        'urlvars' => ['subject' => 'database', 'action' => 'export'],
1313
                        'hide'    => !$this->isDumpEnabled(),
1314
                        'tree'    => false,
1315
                        'icon'    => 'Export',
1316
                    ],
1317
                ];
1318
                break;
1319
1320
            case 'schema':
1321
                $tabs = [
1322
                    'tables'      => [
1323
                        'title'   => $lang['strtables'],
1324
                        'url'     => 'tables.php',
1325
                        'urlvars' => ['subject' => 'schema'],
1326
                        'help'    => 'pg.table',
1327
                        'icon'    => 'Tables',
1328
                    ],
1329
                    'views'       => [
1330
                        'title'   => $lang['strviews'],
1331
                        'url'     => 'views.php',
1332
                        'urlvars' => ['subject' => 'schema'],
1333
                        'help'    => 'pg.view',
1334
                        'icon'    => 'Views',
1335
                    ],
1336
                    'matviews'    => [
1337
                        'title'   => 'M ' . $lang['strviews'],
1338
                        'url'     => 'materializedviews.php',
1339
                        'urlvars' => ['subject' => 'schema'],
1340
                        'help'    => 'pg.matview',
1341
                        'icon'    => 'MViews',
1342
                    ],
1343
                    'sequences'   => [
1344
                        'title'   => $lang['strsequences'],
1345
                        'url'     => 'sequences.php',
1346
                        'urlvars' => ['subject' => 'schema'],
1347
                        'help'    => 'pg.sequence',
1348
                        'icon'    => 'Sequences',
1349
                    ],
1350
                    'functions'   => [
1351
                        'title'   => $lang['strfunctions'],
1352
                        'url'     => 'functions.php',
1353
                        'urlvars' => ['subject' => 'schema'],
1354
                        'help'    => 'pg.function',
1355
                        'icon'    => 'Functions',
1356
                    ],
1357
                    'fulltext'    => [
1358
                        'title'   => $lang['strfulltext'],
1359
                        'url'     => 'fulltext.php',
1360
                        'urlvars' => ['subject' => 'schema'],
1361
                        'help'    => 'pg.fts',
1362
                        'tree'    => true,
1363
                        'icon'    => 'Fts',
1364
                    ],
1365
                    'domains'     => [
1366
                        'title'   => $lang['strdomains'],
1367
                        'url'     => 'domains.php',
1368
                        'urlvars' => ['subject' => 'schema'],
1369
                        'help'    => 'pg.domain',
1370
                        'icon'    => 'Domains',
1371
                    ],
1372
                    'aggregates'  => [
1373
                        'title'   => $lang['straggregates'],
1374
                        'url'     => 'aggregates.php',
1375
                        'urlvars' => ['subject' => 'schema'],
1376
                        'hide'    => $hide_advanced,
1377
                        'help'    => 'pg.aggregate',
1378
                        'icon'    => 'Aggregates',
1379
                    ],
1380
                    'types'       => [
1381
                        'title'   => $lang['strtypes'],
1382
                        'url'     => 'types.php',
1383
                        'urlvars' => ['subject' => 'schema'],
1384
                        'hide'    => $hide_advanced,
1385
                        'help'    => 'pg.type',
1386
                        'icon'    => 'Types',
1387
                    ],
1388
                    'operators'   => [
1389
                        'title'   => $lang['stroperators'],
1390
                        'url'     => 'operators.php',
1391
                        'urlvars' => ['subject' => 'schema'],
1392
                        'hide'    => $hide_advanced,
1393
                        'help'    => 'pg.operator',
1394
                        'icon'    => 'Operators',
1395
                    ],
1396
                    'opclasses'   => [
1397
                        'title'   => $lang['stropclasses'],
1398
                        'url'     => 'opclasses.php',
1399
                        'urlvars' => ['subject' => 'schema'],
1400
                        'hide'    => $hide_advanced,
1401
                        'help'    => 'pg.opclass',
1402
                        'icon'    => 'OperatorClasses',
1403
                    ],
1404
                    'conversions' => [
1405
                        'title'   => $lang['strconversions'],
1406
                        'url'     => 'conversions.php',
1407
                        'urlvars' => ['subject' => 'schema'],
1408
                        'hide'    => $hide_advanced,
1409
                        'help'    => 'pg.conversion',
1410
                        'icon'    => 'Conversions',
1411
                    ],
1412
                    'privileges'  => [
1413
                        'title'   => $lang['strprivileges'],
1414
                        'url'     => 'privileges.php',
1415
                        'urlvars' => ['subject' => 'schema'],
1416
                        'help'    => 'pg.privilege',
1417
                        'tree'    => false,
1418
                        'icon'    => 'Privileges',
1419
                    ],
1420
                    'export'      => [
1421
                        'title'   => $lang['strexport'],
1422
                        'url'     => 'schemas.php',
1423
                        'urlvars' => ['subject' => 'schema', 'action' => 'export'],
1424
                        'hide'    => !$this->isDumpEnabled(),
1425
                        'tree'    => false,
1426
                        'icon'    => 'Export',
1427
                    ],
1428
                ];
1429
                if (!$data->hasFTS()) {
1430
                    unset($tabs['fulltext']);
1431
                }
1432
1433
                break;
1434
1435
            case 'table':
1436
                $tabs = [
1437
                    'columns'     => [
1438
                        'title'   => $lang['strcolumns'],
1439
                        'url'     => 'tblproperties.php',
1440
                        'urlvars' => ['subject' => 'table', 'table' => Decorator::field('table')],
1441
                        'icon'    => 'Columns',
1442
                        'branch'  => true,
1443
                    ],
1444
                    'browse'      => [
1445
                        'title'   => $lang['strbrowse'],
1446
                        'icon'    => 'Columns',
1447
                        'url'     => 'display.php',
1448
                        'urlvars' => ['subject' => 'table', 'table' => Decorator::field('table')],
1449
                        'return'  => 'table',
1450
                        'branch'  => true,
1451
                    ],
1452
                    'select'      => [
1453
                        'title'   => $lang['strselect'],
1454
                        'icon'    => 'Search',
1455
                        'url'     => 'tables.php',
1456
                        'urlvars' => ['subject' => 'table', 'table' => Decorator::field('table'), 'action' => 'confselectrows'],
1457
                        'help'    => 'pg.sql.select',
1458
                    ],
1459
                    'insert'      => [
1460
                        'title'   => $lang['strinsert'],
1461
                        'url'     => 'tables.php',
1462
                        'urlvars' => [
1463
                            'action' => 'confinsertrow',
1464
                            'table'  => Decorator::field('table'),
1465
                        ],
1466
                        'help'    => 'pg.sql.insert',
1467
                        'icon'    => 'Operator',
1468
                    ],
1469
                    'indexes'     => [
1470
                        'title'   => $lang['strindexes'],
1471
                        'url'     => 'indexes.php',
1472
                        'urlvars' => ['subject' => 'table', 'table' => Decorator::field('table')],
1473
                        'help'    => 'pg.index',
1474
                        'icon'    => 'Indexes',
1475
                        'branch'  => true,
1476
                    ],
1477
                    'constraints' => [
1478
                        'title'   => $lang['strconstraints'],
1479
                        'url'     => 'constraints.php',
1480
                        'urlvars' => ['subject' => 'table', 'table' => Decorator::field('table')],
1481
                        'help'    => 'pg.constraint',
1482
                        'icon'    => 'Constraints',
1483
                        'branch'  => true,
1484
                    ],
1485
                    'triggers'    => [
1486
                        'title'   => $lang['strtriggers'],
1487
                        'url'     => 'triggers.php',
1488
                        'urlvars' => ['subject' => 'table', 'table' => Decorator::field('table')],
1489
                        'help'    => 'pg.trigger',
1490
                        'icon'    => 'Triggers',
1491
                        'branch'  => true,
1492
                    ],
1493
                    'rules'       => [
1494
                        'title'   => $lang['strrules'],
1495
                        'url'     => 'rules.php',
1496
                        'urlvars' => ['subject' => 'table', 'table' => Decorator::field('table')],
1497
                        'help'    => 'pg.rule',
1498
                        'icon'    => 'Rules',
1499
                        'branch'  => true,
1500
                    ],
1501
                    'admin'       => [
1502
                        'title'   => $lang['stradmin'],
1503
                        'url'     => 'tables.php',
1504
                        'urlvars' => ['subject' => 'table', 'table' => Decorator::field('table'), 'action' => 'admin'],
1505
                        'icon'    => 'Admin',
1506
                    ],
1507
                    'info'        => [
1508
                        'title'   => $lang['strinfo'],
1509
                        'url'     => 'info.php',
1510
                        'urlvars' => ['subject' => 'table', 'table' => Decorator::field('table')],
1511
                        'icon'    => 'Statistics',
1512
                    ],
1513
                    'privileges'  => [
1514
                        'title'   => $lang['strprivileges'],
1515
                        'url'     => 'privileges.php',
1516
                        'urlvars' => ['subject' => 'table', 'table' => Decorator::field('table')],
1517
                        'help'    => 'pg.privilege',
1518
                        'icon'    => 'Privileges',
1519
                    ],
1520
                    'import'      => [
1521
                        'title'   => $lang['strimport'],
1522
                        'url'     => 'tblproperties.php',
1523
                        'urlvars' => ['subject' => 'table', 'table' => Decorator::field('table'), 'action' => 'import'],
1524
                        'icon'    => 'Import',
1525
                        'hide'    => false,
1526
                    ],
1527
                    'export'      => [
1528
                        'title'   => $lang['strexport'],
1529
                        'url'     => 'tblproperties.php',
1530
                        'urlvars' => ['subject' => 'table', 'table' => Decorator::field('table'), 'action' => 'export'],
1531
                        'icon'    => 'Export',
1532
                        'hide'    => false,
1533
                    ],
1534
                ];
1535
                break;
1536
1537
            case 'view':
1538
                $tabs = [
1539
                    'columns'    => [
1540
                        'title'   => $lang['strcolumns'],
1541
                        'url'     => 'viewproperties.php',
1542
                        'urlvars' => ['subject' => 'view', 'view' => Decorator::field('view')],
1543
                        'icon'    => 'Columns',
1544
                        'branch'  => true,
1545
                    ],
1546
                    'browse'     => [
1547
                        'title'   => $lang['strbrowse'],
1548
                        'icon'    => 'Columns',
1549
                        'url'     => 'display.php',
1550
                        'urlvars' => [
1551
                            'action'  => 'confselectrows',
1552
                            'return'  => 'schema',
1553
                            'subject' => 'view',
1554
                            'view'    => Decorator::field('view'),
1555
                        ],
1556
                        'branch'  => true,
1557
                    ],
1558
                    'select'     => [
1559
                        'title'   => $lang['strselect'],
1560
                        'icon'    => 'Search',
1561
                        'url'     => 'views.php',
1562
                        'urlvars' => ['action' => 'confselectrows', 'view' => Decorator::field('view')],
1563
                        'help'    => 'pg.sql.select',
1564
                    ],
1565
                    'definition' => [
1566
                        'title'   => $lang['strdefinition'],
1567
                        'url'     => 'viewproperties.php',
1568
                        'urlvars' => ['subject' => 'view', 'view' => Decorator::field('view'), 'action' => 'definition'],
1569
                        'icon'    => 'Definition',
1570
                    ],
1571
                    'rules'      => [
1572
                        'title'   => $lang['strrules'],
1573
                        'url'     => 'rules.php',
1574
                        'urlvars' => ['subject' => 'view', 'view' => Decorator::field('view')],
1575
                        'help'    => 'pg.rule',
1576
                        'icon'    => 'Rules',
1577
                        'branch'  => true,
1578
                    ],
1579
                    'privileges' => [
1580
                        'title'   => $lang['strprivileges'],
1581
                        'url'     => 'privileges.php',
1582
                        'urlvars' => ['subject' => 'view', 'view' => Decorator::field('view')],
1583
                        'help'    => 'pg.privilege',
1584
                        'icon'    => 'Privileges',
1585
                    ],
1586
                    'export'     => [
1587
                        'title'   => $lang['strexport'],
1588
                        'url'     => 'viewproperties.php',
1589
                        'urlvars' => ['subject' => 'view', 'view' => Decorator::field('view'), 'action' => 'export'],
1590
                        'icon'    => 'Export',
1591
                        'hide'    => false,
1592
                    ],
1593
                ];
1594
                break;
1595
1596
            case 'matview':
1597
                $tabs = [
1598
                    'columns'    => [
1599
                        'title'   => $lang['strcolumns'],
1600
                        'url'     => 'materializedviewproperties.php',
1601
                        'urlvars' => ['subject' => 'matview', 'matview' => Decorator::field('matview')],
1602
                        'icon'    => 'Columns',
1603
                        'branch'  => true,
1604
                    ],
1605
                    'browse'     => [
1606
                        'title'   => $lang['strbrowse'],
1607
                        'icon'    => 'Columns',
1608
                        'url'     => 'display.php',
1609
                        'urlvars' => [
1610
                            'action'  => 'confselectrows',
1611
                            'return'  => 'schema',
1612
                            'subject' => 'matview',
1613
                            'matview' => Decorator::field('matview'),
1614
                        ],
1615
                        'branch'  => true,
1616
                    ],
1617
                    'select'     => [
1618
                        'title'   => $lang['strselect'],
1619
                        'icon'    => 'Search',
1620
                        'url'     => 'materializedviews.php',
1621
                        'urlvars' => ['action' => 'confselectrows', 'matview' => Decorator::field('matview')],
1622
                        'help'    => 'pg.sql.select',
1623
                    ],
1624
                    'definition' => [
1625
                        'title'   => $lang['strdefinition'],
1626
                        'url'     => 'materializedviewproperties.php',
1627
                        'urlvars' => ['subject' => 'matview', 'matview' => Decorator::field('matview'), 'action' => 'definition'],
1628
                        'icon'    => 'Definition',
1629
                    ],
1630
                    'indexes'    => [
1631
                        'title'   => $lang['strindexes'],
1632
                        'url'     => 'indexes.php',
1633
                        'urlvars' => ['subject' => 'matview', 'matview' => Decorator::field('matview')],
1634
                        'help'    => 'pg.index',
1635
                        'icon'    => 'Indexes',
1636
                        'branch'  => true,
1637
                    ],
1638
                    /*'constraints' => [
1639
                    'title' => $lang['strconstraints'],
1640
                    'url' => 'constraints.php',
1641
                    'urlvars' => ['subject' => 'matview', 'matview' => Decorator::field('matview')],
1642
                    'help' => 'pg.constraint',
1643
                    'icon' => 'Constraints',
1644
                    'branch' => true,
1645
                     */
1646
1647
                    'rules'      => [
1648
                        'title'   => $lang['strrules'],
1649
                        'url'     => 'rules.php',
1650
                        'urlvars' => ['subject' => 'matview', 'matview' => Decorator::field('matview')],
1651
                        'help'    => 'pg.rule',
1652
                        'icon'    => 'Rules',
1653
                        'branch'  => true,
1654
                    ],
1655
                    'privileges' => [
1656
                        'title'   => $lang['strprivileges'],
1657
                        'url'     => 'privileges.php',
1658
                        'urlvars' => ['subject' => 'matview', 'matview' => Decorator::field('matview')],
1659
                        'help'    => 'pg.privilege',
1660
                        'icon'    => 'Privileges',
1661
                    ],
1662
                    'export'     => [
1663
                        'title'   => $lang['strexport'],
1664
                        'url'     => 'materializedviewproperties.php',
1665
                        'urlvars' => ['subject' => 'matview', 'matview' => Decorator::field('matview'), 'action' => 'export'],
1666
                        'icon'    => 'Export',
1667
                        'hide'    => false,
1668
                    ],
1669
                ];
1670
                break;
1671
1672 View Code Duplication
            case 'function':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1673
                $tabs = [
1674
                    'definition' => [
1675
                        'title'   => $lang['strdefinition'],
1676
                        'url'     => 'functions.php',
1677
                        'urlvars' => [
1678
                            'subject'      => 'function',
1679
                            'function'     => Decorator::field('function'),
1680
                            'function_oid' => Decorator::field('function_oid'),
1681
                            'action'       => 'properties',
1682
                        ],
1683
                        'icon'    => 'Definition',
1684
                    ],
1685
                    'privileges' => [
1686
                        'title'   => $lang['strprivileges'],
1687
                        'url'     => 'privileges.php',
1688
                        'urlvars' => [
1689
                            'subject'      => 'function',
1690
                            'function'     => Decorator::field('function'),
1691
                            'function_oid' => Decorator::field('function_oid'),
1692
                        ],
1693
                        'icon'    => 'Privileges',
1694
                    ],
1695
                ];
1696
                break;
1697
1698 View Code Duplication
            case 'aggregate':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1699
                $tabs = [
1700
                    'definition' => [
1701
                        'title'   => $lang['strdefinition'],
1702
                        'url'     => 'aggregates.php',
1703
                        'urlvars' => [
1704
                            'subject'  => 'aggregate',
1705
                            'aggrname' => Decorator::field('aggrname'),
1706
                            'aggrtype' => Decorator::field('aggrtype'),
1707
                            'action'   => 'properties',
1708
                        ],
1709
                        'icon'    => 'Definition',
1710
                    ],
1711
                ];
1712
                break;
1713
1714 View Code Duplication
            case 'role':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1715
                $tabs = [
1716
                    'definition' => [
1717
                        'title'   => $lang['strdefinition'],
1718
                        'url'     => 'roles.php',
1719
                        'urlvars' => [
1720
                            'subject'  => 'role',
1721
                            'rolename' => Decorator::field('rolename'),
1722
                            'action'   => 'properties',
1723
                        ],
1724
                        'icon'    => 'Definition',
1725
                    ],
1726
                ];
1727
                break;
1728
1729
            case 'popup':
1730
                $tabs = [
1731
                    'sql'  => [
1732
                        'title'   => $lang['strsql'],
1733
                        'url'     => '/src/views/sqledit.php',
1734
                        'urlvars' => ['action' => 'sql', 'subject' => 'schema'],
1735
                        'help'    => 'pg.sql',
1736
                        'icon'    => 'SqlEditor',
1737
                    ],
1738
                    'find' => [
1739
                        'title'   => $lang['strfind'],
1740
                        'url'     => '/src/views/sqledit.php',
1741
                        'urlvars' => ['action' => 'find', 'subject' => 'schema'],
1742
                        'icon'    => 'Search',
1743
                    ],
1744
                ];
1745
                break;
1746
1747 View Code Duplication
            case 'column':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1748
                $tabs = [
1749
                    'properties' => [
1750
                        'title'   => $lang['strcolprop'],
1751
                        'url'     => 'colproperties.php',
1752
                        'urlvars' => [
1753
                            'subject' => 'column',
1754
                            'table'   => Decorator::field('table'),
1755
                            'column'  => Decorator::field('column'),
1756
                        ],
1757
                        'icon'    => 'Column',
1758
                    ],
1759
                    'privileges' => [
1760
                        'title'   => $lang['strprivileges'],
1761
                        'url'     => 'privileges.php',
1762
                        'urlvars' => [
1763
                            'subject' => 'column',
1764
                            'table'   => Decorator::field('table'),
1765
                            'column'  => Decorator::field('column'),
1766
                        ],
1767
                        'help'    => 'pg.privilege',
1768
                        'icon'    => 'Privileges',
1769
                    ],
1770
                ];
1771
                break;
1772
1773
            case 'fulltext':
1774
                $tabs = [
1775
                    'ftsconfigs' => [
1776
                        'title'   => $lang['strftstabconfigs'],
1777
                        'url'     => 'fulltext.php',
1778
                        'urlvars' => ['subject' => 'schema'],
1779
                        'hide'    => !$data->hasFTS(),
1780
                        'help'    => 'pg.ftscfg',
1781
                        'tree'    => true,
1782
                        'icon'    => 'FtsCfg',
1783
                    ],
1784
                    'ftsdicts'   => [
1785
                        'title'   => $lang['strftstabdicts'],
1786
                        'url'     => 'fulltext.php',
1787
                        'urlvars' => ['subject' => 'schema', 'action' => 'viewdicts'],
1788
                        'hide'    => !$data->hasFTS(),
1789
                        'help'    => 'pg.ftsdict',
1790
                        'tree'    => true,
1791
                        'icon'    => 'FtsDict',
1792
                    ],
1793
                    'ftsparsers' => [
1794
                        'title'   => $lang['strftstabparsers'],
1795
                        'url'     => 'fulltext.php',
1796
                        'urlvars' => ['subject' => 'schema', 'action' => 'viewparsers'],
1797
                        'hide'    => !$data->hasFTS(),
1798
                        'help'    => 'pg.ftsparser',
1799
                        'tree'    => true,
1800
                        'icon'    => 'FtsParser',
1801
                    ],
1802
                ];
1803
                break;
1804
        }
1805
1806
        // Tabs hook's place
1807
        $plugin_functions_parameters = [
1808
            'tabs'    => &$tabs,
1809
            'section' => $section,
1810
        ];
1811
        $plugin_manager->do_hook('tabs', $plugin_functions_parameters);
1812
1813
        return $tabs;
1814
    }
1815
1816
    /**
1817
     * Get the URL for the last active tab of a particular tab bar.
1818
     *
1819
     * @param $section
1820
     * @return mixed|null
1821
     */
1822
    public function getLastTabURL($section)
0 ignored issues
show
Coding Style introduced by
getLastTabURL uses the super-global variable $_SESSION which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
1823
    {
1824
        $data = $this->getDatabaseAccessor();
1825
1826
        $tabs = $this->getNavTabs($section);
1827
1828 View Code Duplication
        if (isset($_SESSION['webdbLastTab'][$section]) && isset($tabs[$_SESSION['webdbLastTab'][$section]])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1829
            $tab = $tabs[$_SESSION['webdbLastTab'][$section]];
1830
        } else {
1831
            $tab = reset($tabs);
1832
        }
1833
        $this->prtrace(['section' => $section, 'tabs' => $tabs, 'tab' => $tab]);
1834
        return isset($tab['url']) ? $tab : null;
1835
    }
1836
1837
    /**
1838
     * Do multi-page navigation.  Displays the prev, next and page options.
1839
     * @param $page - the page currently viewed
1840
     * @param $pages - the maximum number of pages
1841
     * @param $gets -  the parameters to include in the link to the wanted page
1842
     * @param $max_width - the number of pages to make available at any one time (default = 20)
1843
     */
1844
    public function printPages($page, $pages, $gets, $max_width = 20)
1845
    {
1846
        $lang = $this->lang;
1847
1848
        $window = 10;
1849
1850
        if ($page < 0 || $page > $pages) {
1851
            return;
1852
        }
1853
1854
        if ($pages < 0) {
1855
            return;
1856
        }
1857
1858
        if ($max_width <= 0) {
1859
            return;
1860
        }
1861
1862
        unset($gets['page']);
1863
        $url = http_build_query($gets);
1864
1865
        if ($pages > 1) {
1866
            echo "<p style=\"text-align: center\">\n";
1867
            if ($page != 1) {
1868
                echo "<a class=\"pagenav\" href=\"?{$url}&amp;page=1\">{$lang['strfirst']}</a>\n";
1869
                $temp = $page - 1;
1870
                echo "<a class=\"pagenav\" href=\"?{$url}&amp;page={$temp}\">{$lang['strprev']}</a>\n";
1871
            }
1872
1873
            if ($page <= $window) {
1874
                $min_page = 1;
1875
                $max_page = min(2 * $window, $pages);
1876
            } elseif ($page > $window && $pages >= $page + $window) {
1877
                $min_page = ($page - $window) + 1;
1878
                $max_page = $page + $window;
1879
            } else {
1880
                $min_page = ($page - (2 * $window - ($pages - $page))) + 1;
1881
                $max_page = $pages;
1882
            }
1883
1884
            // Make sure min_page is always at least 1
1885
            // and max_page is never greater than $pages
1886
            $min_page = max($min_page, 1);
1887
            $max_page = min($max_page, $pages);
1888
1889
            for ($i = $min_page; $i <= $max_page; $i++) {
1890
                #if ($i != $page) echo "<a class=\"pagenav\" href=\"?{$url}&amp;page={$i}\">$i</a>\n";
1891
                if ($i != $page) {
1892
                    echo "<a class=\"pagenav\" href=\"display.php?{$url}&amp;page={$i}\">$i</a>\n";
1893
                } else {
1894
                    echo "$i\n";
1895
                }
1896
            }
1897
            if ($page != $pages) {
1898
                $temp = $page + 1;
1899
                echo "<a class=\"pagenav\" href=\"display.php?{$url}&amp;page={$temp}\">{$lang['strnext']}</a>\n";
1900
                echo "<a class=\"pagenav\" href=\"display.php?{$url}&amp;page={$pages}\">{$lang['strlast']}</a>\n";
1901
            }
1902
            echo "</p>\n";
1903
        }
1904
    }
1905
1906
    /**
1907
     * Converts a PHP.INI size variable to bytes.  Taken from publically available
1908
     * function by Chris DeRose, here: http://www.php.net/manual/en/configuration.directives.php#ini.file-uploads
1909
     * @param $strIniSize The PHP.INI variable
1910
     * @return size in bytes, false on failure
1911
     */
1912
    public function inisizeToBytes($strIniSize)
1913
    {
1914
        // This function will take the string value of an ini 'size' parameter,
1915
        // and return a double (64-bit float) representing the number of bytes
1916
        // that the parameter represents. Or false if $strIniSize is unparseable.
1917
        $a_IniParts = [];
1918
1919
        if (!is_string($strIniSize)) {
1920
            return false;
1921
        }
1922
1923
        if (!preg_match('/^(\d+)([bkm]*)$/i', $strIniSize, $a_IniParts)) {
1924
            return false;
1925
        }
1926
1927
        $nSize   = (double) $a_IniParts[1];
1928
        $strUnit = strtolower($a_IniParts[2]);
1929
1930
        switch ($strUnit) {
1931
            case 'm':
1932
                return ($nSize * (double) 1048576);
1933
            case 'k':
1934
                return ($nSize * (double) 1024);
1935
            case 'b':
1936
            default:
1937
                return $nSize;
1938
        }
1939
    }
1940
1941
    public function getRequestVars($subject = '')
0 ignored issues
show
Coding Style introduced by
getRequestVars uses the super-global variable $_REQUEST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
1942
    {
1943
        $v = [];
1944
        if (!empty($subject)) {
1945
            $v['subject'] = $subject;
1946
        }
1947
1948
        if ($this->server_id !== null && $subject != 'root') {
1949
            $v['server'] = $this->server_id;
1950
            if ($this->database !== null && $subject != 'server') {
1951
                $v['database'] = $this->database;
1952
                if (isset($_REQUEST['schema']) && $subject != 'database') {
1953
                    $v['schema'] = $_REQUEST['schema'];
1954
                }
1955
            }
1956
        }
1957
        //$this->prtrace($v);
1958
        return $v;
1959
    }
1960
1961
    public function icon($icon)
1962
    {
1963
        if (is_string($icon)) {
1964
            $path = "/images/themes/{$this->conf['theme']}/{$icon}";
1965 View Code Duplication
            if (file_exists(BASE_PATH . $path . '.png')) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1966
                return SUBFOLDER . $path . '.png';
1967
            }
1968
1969 View Code Duplication
            if (file_exists(BASE_PATH . $path . '.gif')) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1970
                return SUBFOLDER . $path . '.gif';
1971
            }
1972
1973 View Code Duplication
            if (file_exists(BASE_PATH . $path . '.ico')) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1974
                return SUBFOLDER . $path . '.ico';
1975
            }
1976
1977
            $path = "/images/themes/default/{$icon}";
1978 View Code Duplication
            if (file_exists(BASE_PATH . $path . '.png')) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1979
                return SUBFOLDER . $path . '.png';
1980
            }
1981
1982 View Code Duplication
            if (file_exists(BASE_PATH . $path . '.gif')) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1983
                return SUBFOLDER . $path . '.gif';
1984
            }
1985
1986 View Code Duplication
            if (file_exists(BASE_PATH . $path . '.ico')) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1987
                return SUBFOLDER . $path . '.ico';
1988
            }
1989
        } else {
1990
            // Icon from plugins
1991
            $path = "/plugins/{$icon[0]}/images/{$icon[1]}";
1992 View Code Duplication
            if (file_exists(BASE_PATH . $path . '.png')) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1993
                return SUBFOLDER . $path . '.png';
1994
            }
1995
1996 View Code Duplication
            if (file_exists(BASE_PATH . $path . '.gif')) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1997
                return SUBFOLDER . $path . '.gif';
1998
            }
1999
2000 View Code Duplication
            if (file_exists(BASE_PATH . $path . '.ico')) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
2001
                return SUBFOLDER . $path . '.ico';
2002
            }
2003
        }
2004
        return '';
2005
    }
2006
2007
    /**
2008
     * Function to escape command line parameters
2009
     * @param string $str The string to escape
2010
     * @return string The escaped string
2011
     */
2012
    public function escapeShellArg($str)
2013
    {
2014
        $data = $this->getDatabaseAccessor();
2015
        $lang = $this->lang;
2016
2017
        if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
2018
            // Due to annoying PHP bugs, shell arguments cannot be escaped
2019
            // (command simply fails), so we cannot allow complex objects
2020
            // to be dumped.
2021
            if (preg_match('/^[_.[:alnum:]]+$/', $str)) {
2022
                return $str;
2023
            }
2024
2025
            echo $lang['strcannotdumponwindows'];
2026
            exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The method escapeShellArg() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
2027
        } else {
2028
            return escapeshellarg($str);
2029
        }
2030
    }
2031
2032
    /**
2033
     * Function to escape command line programs
2034
     * @param string $str The string to escape
2035
     * @return string The escaped string
2036
     */
2037
    public function escapeShellCmd($str)
2038
    {
2039
        $data = $this->getDatabaseAccessor();
2040
2041
        if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
2042
            $data->fieldClean($str);
2043
            return '"' . $str . '"';
2044
        }
2045
2046
        return escapeshellcmd($str);
2047
    }
2048
2049
    /**
2050
     * Save the given SQL script in the history
2051
     * of the database and server.
2052
     * @param $script the SQL script to save.
2053
     */
2054
    public function saveScriptHistory($script)
0 ignored issues
show
Coding Style introduced by
saveScriptHistory uses the super-global variable $_SESSION which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
Coding Style introduced by
saveScriptHistory uses the super-global variable $_REQUEST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
2055
    {
2056
        list($usec, $sec)                                                         = explode(' ', microtime());
2057
        $time                                                                     = ((float) $usec + (float) $sec);
2058
        $_SESSION['history'][$_REQUEST['server']][$_REQUEST['database']]["$time"] = [
2059
            'query'    => $script,
2060
            'paginate' => !isset($_REQUEST['paginate']) ? 'f' : 't',
2061
            'queryid'  => $time,
2062
        ];
2063
    }
2064
2065
    /*
2066
     * Output dropdown list to select server and
2067
     * databases form the popups windows.
2068
     * @param $onchange Javascript action to take when selections change.
2069
     */
2070
    public function printConnection($onchange, $do_print = true)
0 ignored issues
show
Coding Style introduced by
printConnection uses the super-global variable $_REQUEST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
2071
    {
2072
        $lang = $this->lang;
2073
2074
        $connection_html = "<table class=\"printconnection\" style=\"width: 100%\"><tr><td class=\"popup_select1\">\n";
2075
2076
        $servers      = $this->getServers();
2077
        $forcedserver = null;
2078
        if (count($servers) === 1) {
2079
            $forcedserver = $this->server_id;
2080
            $connection_html .= '<input type="hidden" readonly="readonly" value="' . $this->server_id . '" name="server">';
2081
        } else {
2082
            $connection_html .= '<label>';
2083
            $connection_html .= $this->printHelp($lang['strserver'], 'pg.server', false);
2084
            $connection_html .= ': </label>';
2085
            $connection_html .= " <select name=\"server\" {$onchange}>\n";
2086
            foreach ($servers as $info) {
2087
                if (empty($info['username'])) {
2088
                    continue;
2089
                }
2090
                $selected = isset($_REQUEST['server']) && $info['id'] == $_REQUEST['server'] ? ' selected="selected"' : '';
2091
                // not logged on this server
2092
                $connection_html .= '<option value="' . htmlspecialchars($info['id']) . '" ' . $selected . '>';
2093
                $connection_html .= htmlspecialchars("{$info['desc']} ({$info['id']})");
2094
                $connection_html .= "</option>\n";
2095
            }
2096
            $connection_html .= "</select>\n";
2097
        }
2098
2099
        $connection_html .= "</td><td class=\"popup_select2\" style=\"text-align: right\">\n";
2100
2101
        if (count($servers) === 1 && isset($servers[$this->server_id]['useonlydefaultdb']) && $servers[$this->server_id]['useonlydefaultdb'] === true) {
2102
            $connection_html .= '<input type="hidden" name="database" value="' . htmlspecialchars($servers[$this->server_id]['defaultdb']) . "\" />\n";
2103
        } else {
2104
2105
            // Get the list of all databases
2106
            $data      = $this->getDatabaseAccessor();
2107
            $databases = $data->getDatabases();
2108
            if ($databases->recordCount() > 0) {
2109
                $connection_html .= '<label>';
2110
                $connection_html .= $this->printHelp($lang['strdatabase'], 'pg.database', false);
2111
                $connection_html .= ": <select name=\"database\" {$onchange}>\n";
2112
2113
                //if no database was selected, user should select one
2114
                if (!isset($_REQUEST['database'])) {
2115
                    $connection_html .= "<option value=\"\">--</option>\n";
2116
                }
2117
2118
                while (!$databases->EOF) {
2119
                    $dbname     = $databases->fields['datname'];
2120
                    $dbselected = isset($_REQUEST['database']) && $dbname == $_REQUEST['database'] ? ' selected="selected"' : '';
2121
                    $connection_html .= '<option value="' . htmlspecialchars($dbname) . '" ' . $dbselected . '>' . htmlspecialchars($dbname) . "</option>\n";
2122
2123
                    $databases->moveNext();
2124
                }
2125
                $connection_html .= "</select></label>\n";
2126
            } else {
2127
                $server_info = $misc->getServerInfo();
2128
                $connection_html .= '<input type="hidden" name="database" value="' . htmlspecialchars($server_info['defaultdb']) . "\" />\n";
2129
            }
2130
        }
2131
2132
        $connection_html .= "</td></tr></table>\n";
2133
2134
        if ($do_print) {
2135
            echo $connection_html;
2136
        } else {
2137
            return $connection_html;
2138
        }
2139
    }
2140
2141
    /**
2142
     * returns an array representing FKs definition for a table, sorted by fields
2143
     * or by constraint.
2144
     * @param $table The table to retrieve FK contraints from
2145
     * @returns the array of FK definition:
2146
     *   array(
2147
     *     'byconstr' => array(
2148
     *       constrain id => array(
2149
     *         confrelid => foreign relation oid
2150
     *         f_schema => foreign schema name
2151
     *         f_table => foreign table name
2152
     *         pattnums => array of parent's fields nums
2153
     *         pattnames => array of parent's fields names
2154
     *         fattnames => array of foreign attributes names
2155
     *       )
2156
     *     ),
2157
     *     'byfield' => array(
2158
     *       attribute num => array (constraint id, ...)
2159
     *     ),
2160
     *     'code' => HTML/js code to include in the page for auto-completion
2161
     *   )
2162
     **/
2163
    public function getAutocompleteFKProperties($table)
0 ignored issues
show
Coding Style introduced by
getAutocompleteFKProperties uses the super-global variable $_REQUEST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
2164
    {
2165
        $data = $this->getDatabaseAccessor();
2166
2167
        $fksprops = [
2168
            'byconstr' => [],
2169
            'byfield'  => [],
2170
            'code'     => '',
2171
        ];
2172
2173
        $constrs = $data->getConstraintsWithFields($table);
2174
2175
        if (!$constrs->EOF) {
2176
            $conrelid = $constrs->fields['conrelid'];
2177
            while (!$constrs->EOF) {
2178
                if ($constrs->fields['contype'] == 'f') {
2179
                    if (!isset($fksprops['byconstr'][$constrs->fields['conid']])) {
2180
                        $fksprops['byconstr'][$constrs->fields['conid']] = [
2181
                            'confrelid' => $constrs->fields['confrelid'],
2182
                            'f_table'   => $constrs->fields['f_table'],
2183
                            'f_schema'  => $constrs->fields['f_schema'],
2184
                            'pattnums'  => [],
2185
                            'pattnames' => [],
2186
                            'fattnames' => [],
2187
                        ];
2188
                    }
2189
2190
                    $fksprops['byconstr'][$constrs->fields['conid']]['pattnums'][]  = $constrs->fields['p_attnum'];
2191
                    $fksprops['byconstr'][$constrs->fields['conid']]['pattnames'][] = $constrs->fields['p_field'];
2192
                    $fksprops['byconstr'][$constrs->fields['conid']]['fattnames'][] = $constrs->fields['f_field'];
2193
2194
                    if (!isset($fksprops['byfield'][$constrs->fields['p_attnum']])) {
2195
                        $fksprops['byfield'][$constrs->fields['p_attnum']] = [];
2196
                    }
2197
2198
                    $fksprops['byfield'][$constrs->fields['p_attnum']][] = $constrs->fields['conid'];
2199
                }
2200
                $constrs->moveNext();
2201
            }
2202
2203
            $fksprops['code'] = "<script type=\"text/javascript\">\n";
2204
            $fksprops['code'] .= "var constrs = {};\n";
2205
            foreach ($fksprops['byconstr'] as $conid => $props) {
2206
                $fksprops['code'] .= "constrs.constr_{$conid} = {\n";
2207
                $fksprops['code'] .= 'pattnums: [' . implode(',', $props['pattnums']) . "],\n";
2208
                $fksprops['code'] .= "f_table:'" . addslashes(htmlentities($props['f_table'], ENT_QUOTES, 'UTF-8')) . "',\n";
2209
                $fksprops['code'] .= "f_schema:'" . addslashes(htmlentities($props['f_schema'], ENT_QUOTES, 'UTF-8')) . "',\n";
2210
                $_ = '';
2211 View Code Duplication
                foreach ($props['pattnames'] as $n) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
2212
                    $_ .= ",'" . htmlentities($n, ENT_QUOTES, 'UTF-8') . "'";
2213
                }
2214
                $fksprops['code'] .= 'pattnames: [' . substr($_, 1) . "],\n";
2215
2216
                $_ = '';
2217 View Code Duplication
                foreach ($props['fattnames'] as $n) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
2218
                    $_ .= ",'" . htmlentities($n, ENT_QUOTES, 'UTF-8') . "'";
2219
                }
2220
2221
                $fksprops['code'] .= 'fattnames: [' . substr($_, 1) . "]\n";
2222
                $fksprops['code'] .= "};\n";
2223
            }
2224
2225
            $fksprops['code'] .= "var attrs = {};\n";
2226
            foreach ($fksprops['byfield'] as $attnum => $cstrs) {
2227
                $fksprops['code'] .= "attrs.attr_{$attnum} = [" . implode(',', $fksprops['byfield'][$attnum]) . "];\n";
2228
            }
2229
2230
            $fksprops['code'] .= "var table='" . addslashes(htmlentities($table, ENT_QUOTES, 'UTF-8')) . "';";
2231
            $fksprops['code'] .= "var server='" . htmlentities($_REQUEST['server'], ENT_QUOTES, 'UTF-8') . "';";
2232
            $fksprops['code'] .= "var database='" . addslashes(htmlentities($_REQUEST['database'], ENT_QUOTES, 'UTF-8')) . "';";
2233
            $fksprops['code'] .= "var subfolder='" . SUBFOLDER . "';";
2234
            $fksprops['code'] .= "</script>\n";
2235
2236
            $fksprops['code'] .= '<div id="fkbg"></div>';
2237
            $fksprops['code'] .= '<div id="fklist"></div>';
2238
            $fksprops['code'] .= '<script src="' . SUBFOLDER . '/js/ac_insert_row.js" type="text/javascript"></script>';
2239
        } else /* we have no foreign keys on this table */
2240
        {
2241
            return false;
2242
        }
2243
2244
        return $fksprops;
2245
    }
2246
}
2247