Passed
Push — develop ( 39eda0...90489b )
by Felipe
04:51
created

Misc::escapeShellArg()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 17
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 17
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 6
nc 3
nop 1
1
<?php
2
3
/**
4
 * PHPPgAdmin v6.0.0-beta.44
5
 */
6
7
namespace PHPPgAdmin;
8
9
use PHPPgAdmin\Decorators\Decorator;
10
11
/**
12
 * @file
13
 * Class to hold various commonly used functions
14
 *
15
 * Id: Misc.php,v 1.171 2008/03/17 21:35:48 ioguix Exp $
16
 *
17
 * @package PHPPgAdmin
18
 */
19
20
/**
21
 * Class to hold various commonly used functions.
22
 *
23
 * Release: Misc.php,v 1.171 2008/03/17 21:35:48 ioguix Exp $
24
 *
25
 * @package PHPPgAdmin
26
 */
27
class Misc
28
{
29
    use \PHPPgAdmin\Traits\HelperTrait;
30
31
    private $_connection;
32
    private $_no_db_connection = false;
33
    private $_reload_browser   = false;
34
    private $_data;
35
    private $_database;
36
    private $_server_id;
37
    private $_server_info;
38
    private $_error_msg = '';
39
40
    public $appLangFiles    = [];
41
    public $appName         = '';
42
    public $appVersion      = '';
43
    public $form            = '';
44
    public $href            = '';
45
    public $controller_name = 'Misc';
46
    public $lang            = [];
47
48
    protected $container;
49
50
    /**
51
     * @param \Slim\Container $container The container
52
     */
53
    public function __construct(\Slim\Container $container)
54
    {
55
        $this->container = $container;
56
57
        $this->lang = $container->get('lang');
58
        $this->conf = $container->get('conf');
59
60
        //$this->view           = $container->get('view');
61
        $this->plugin_manager = $container->get('plugin_manager');
62
        $this->appLangFiles   = $container->get('appLangFiles');
63
64
        $this->appName          = $container->get('settings')['appName'];
65
        $this->appVersion       = $container->get('settings')['appVersion'];
66
        $this->postgresqlMinVer = $container->get('settings')['postgresqlMinVer'];
67
        $this->phpMinVer        = $container->get('settings')['phpMinVer'];
68
69
        $base_version = $container->get('settings')['base_version'];
70
71
        //$this->prtrace($base_version);
72
73
        // Check for config file version mismatch
74
        if (!isset($this->conf['version']) || $base_version > $this->conf['version']) {
75
            $container->get('utils')->addError($this->lang['strbadconfig']);
76
        }
77
78
        // Check database support is properly compiled in
79
        if (!function_exists('pg_connect')) {
80
            $container->get('utils')->addError($this->lang['strnotloaded']);
81
        }
82
83
        // Check the version of PHP
84
        if (version_compare(PHP_VERSION, $this->phpMinVer, '<')) {
85
            $container->get('utils')->addError(sprintf('Version of PHP not supported. Please upgrade to version %s or later.', $this->phpMinVer));
86
        }
87
        //$this->dumpAndDie($this);
88
89
        $this->getServerId();
90
    }
91
92
    public function serverToSha()
93
    {
94
        $request_server = $this->container->requestobj->getParam('server');
95
        if ($request_server === null) {
96
            return null;
97
        }
98
        $srv_array = explode(':', $request_server);
99
        if (count($srv_array) === 3) {
100
            return sha1($request_server);
101
        }
102
103
        return $request_server;
104
    }
105
106
    public function getServerId()
107
    {
108
        if ($this->_server_id) {
109
            return $this->_server_id;
110
        }
111
112
        $request_server = $this->serverToSha();
113
114
        if (count($this->conf['servers']) === 1) {
115
            $info             = $this->conf['servers'][0];
116
            $this->_server_id = sha1($info['host'].':'.$info['port'].':'.$info['sslmode']);
117
        } elseif ($request_server !== null) {
118
            $this->_server_id = $request_server;
119
        } elseif (isset($_SESSION['webdbLogin']) && count($_SESSION['webdbLogin']) > 0) {
120
            //$this->prtrace('webdbLogin', $_SESSION['webdbLogin']);
121
            $this->_server_id = array_keys($_SESSION['webdbLogin'])[0];
122
        }
123
124
        return $this->_server_id;
125
    }
126
127
    /**
128
     * Sets the view instance property of this class.
129
     *
130
     * @param \Slim\Views\Twig $view view instance
131
     *
132
     * @return \PHPPgAdmin\Misc this class instance
133
     */
134
    public function setView(\Slim\Views\Twig $view)
135
    {
136
        $this->view = $view;
137
138
        return $this;
139
    }
140
141
    /**
142
     * Adds or modifies a key in the $conf instance property of this class.
143
     *
144
     * @param string $key   name of the key to set
145
     * @param mixed  $value value of the key to set
146
     *
147
     * @return \PHPPgAdmin\Misc this class instance
148
     */
149
    public function setConf($key, $value)
150
    {
151
        $this->conf[$key] = $value;
152
153
        return $this;
154
    }
155
156
    /**
157
     * Gets the value of a config property, or the array of all config properties.
158
     *
159
     * @param null|string $key value of the key to be retrieved. If null, the full array is returnes
160
     *
161
     * @return null|array|string the whole $conf array, the value of $conf[key] or null if said key does not exist
162
     */
163
    public function getConf($key = null)
164
    {
165
        if ($key === null) {
166
            return $this->conf;
167
        }
168
        if (array_key_exists($key, $this->conf)) {
169
            return $this->conf[$key];
170
        }
171
172
        return null;
173
    }
174
175
    /**
176
     * Displays link to the context help.
177
     *
178
     * @param string $str      the string that the context help is related to (already escaped)
179
     * @param string $help     help section identifier
180
     * @param bool   $do_print true to echo, false to return
181
     */
182
    public function printHelp($str, $help = null, $do_print = true)
183
    {
184
        //\PC::debug(['str' => $str, 'help' => $help], 'printHelp');
185
        if ($help !== null) {
186
            $helplink = $this->getHelpLink($help);
187
            $str .= '<a class="help" href="'.$helplink.'" title="'.$this->lang['strhelp'].'" target="phppgadminhelp">';
188
            $str .= $this->lang['strhelpicon'].'</a>';
189
        }
190
        if ($do_print) {
191
            echo $str;
192
        } else {
193
            return $str;
194
        }
195
    }
196
197
    /**
198
     * Gets the help link.
199
     *
200
     * @param string $help The help subject
201
     *
202
     * @return string the help link
203
     */
204
    public function getHelpLink($help)
205
    {
206
        return htmlspecialchars(SUBFOLDER.'/help?help='.urlencode($help).'&server='.urlencode($this->getServerId()));
207
    }
208
209
    /**
210
     * Internally sets the reload browser property.
211
     *
212
     * @param bool $flag sets internal $_reload_browser var which will be passed to the footer methods
213
     *
214
     * @return \PHPPgAdmin\Misc this class instance
215
     */
216
    public function setReloadBrowser($flag)
217
    {
218
        $this->_reload_browser = (bool) $flag;
219
220
        return $this;
221
    }
222
223
    public function getReloadBrowser()
224
    {
225
        return $this->_reload_browser;
226
    }
227
228
    public function getContainer()
229
    {
230
        return $this->container;
231
    }
232
233
    /**
234
     * Sets $_no_db_connection boolean value, allows to render scripts that do not need an active session.
235
     *
236
     * @param bool $flag true or false to allow unconnected clients to access the view
237
     *
238
     * @return \PHPPgAdmin\Misc this class instance
239
     */
240
    public function setNoDBConnection($flag)
241
    {
242
        $this->_no_db_connection = (bool) $flag;
243
244
        return $this;
245
    }
246
247
    /**
248
     * Gets member variable $_no_db_connection.
249
     *
250
     * @return bool value of member variable $_no_db_connection
251
     */
252
    public function getNoDBConnection()
253
    {
254
        return $this->_no_db_connection;
255
    }
256
257
    /**
258
     * Sets the last error message to display afterwards instead of just dying with the error msg.
259
     *
260
     * @param string $msg error message string
261
     *
262
     * @return \PHPPgAdmin\Misc this class instance
263
     */
264
    public function setErrorMsg($msg)
265
    {
266
        $this->_error_msg = $msg;
267
268
        return $this;
269
    }
270
271
    /**
272
     * Returns the error messages stored in member variable $_error_msg.
273
     *
274
     * @return string the error message
275
     */
276
    public function getErrorMsg()
277
    {
278
        return $this->_error_msg;
279
    }
280
281
    /**
282
     * Creates a database accessor.
283
     *
284
     * @param string $database  the name of the database
285
     * @param mixed  $server_id the id of the server
286
     *
287
     * @internal mixed $plaform placeholder that will receive the value of the platform
288
     */
289
    public function getDatabaseAccessor($database = '', $server_id = null)
290
    {
291
        $lang = $this->lang;
292
293
        if ($server_id !== null) {
294
            $this->_server_id = $server_id;
295
        }
296
        //$this->prtrace($this->_server_id);
297
298
        $server_info = $this->getServerInfo($this->_server_id);
299
300
        if ($this->_no_db_connection || !isset($server_info['username'])) {
301
            return null;
302
        }
303
304
        if ($this->_data === null) {
305
            try {
306
                $_connection = $this->getConnection($database, $this->_server_id);
307
            } catch (\Exception $e) {
308
                $this->setServerInfo(null, null, $this->_server_id);
309
                $this->setNoDBConnection(true);
310
                $this->setErrorMsg($e->getMessage());
311
312
                return null;
313
            }
314
315
            //$this->prtrace('_connection', $_connection);
316
            if (!$_connection) {
317
                $this->container->utils->addError($lang['strloginfailed']);
318
                $this->setErrorMsg($lang['strloginfailed']);
319
320
                return null;
321
            }
322
            // Get the name of the database driver we need to use.
323
            // The description of the server is returned in $platform.
324
            $_type = $_connection->getDriver($platform);
325
326
            //$this->prtrace(['type' => $_type, 'platform' => $platform, 'pgVersion' => $_connection->conn->pgVersion]);
327
328
            if ($_type === null) {
329
                $errormsg = sprintf($lang['strpostgresqlversionnotsupported'], $this->postgresqlMinVer);
330
                $this->container->utils->addError($errormsg);
331
                $this->setErrorMsg($errormsg);
332
333
                return null;
334
            }
335
            $_type = '\PHPPgAdmin\Database\\'.$_type;
336
337
            $this->setServerInfo('platform', $platform, $this->_server_id);
338
            $this->setServerInfo('pgVersion', $_connection->conn->pgVersion, $this->_server_id);
339
340
            // Create a database wrapper class for easy manipulation of the
341
            // connection.
342
343
            $this->_data           = new $_type($_connection->conn, $this->container, $server_info);
344
            $this->_data->platform = $_connection->platform;
345
346
            //$this->_data->getHelpPages();
347
348
            //$this->prtrace('help_page has ' . count($this->_data->help_page) . ' items');
349
350
            /* we work on UTF-8 only encoding */
351
            $this->_data->execute("SET client_encoding TO 'UTF-8'");
352
353
            if ($this->_data->hasByteaHexDefault()) {
354
                $this->_data->execute('SET bytea_output TO escape');
355
            }
356
        }
357
358
        if ($this->_no_db_connection === false &&
359
            $this->getDatabase() !== null &&
360
            isset($_REQUEST['schema'])
361
        ) {
362
            $status = $this->_data->setSchema($_REQUEST['schema']);
363
364
            if ($status != 0) {
365
                $this->container->utils->addError($this->lang['strbadschema']);
366
                $this->setErrorMsg($this->lang['strbadschema']);
367
368
                return null;
369
            }
370
        }
371
372
        return $this->_data;
373
    }
374
375
    public function getConnection($database = '', $server_id = null)
376
    {
377
        $lang = $this->lang;
378
379
        if ($this->_connection === null) {
380
            if ($server_id !== null) {
381
                $this->_server_id = $server_id;
382
            }
383
            $server_info     = $this->getServerInfo($this->_server_id);
384
            $database_to_use = $this->getDatabase($database);
385
386
            // Perform extra security checks if this config option is set
387
            if ($this->conf['extra_login_security']) {
388
                // Disallowed logins if extra_login_security is enabled.
389
                // These must be lowercase.
390
                $bad_usernames = [
391
                    'pgsql'         => 'pgsql',
392
                    'postgres'      => 'postgres',
393
                    'root'          => 'root',
394
                    'administrator' => 'administrator',
395
                ];
396
397
                if (isset($server_info['username']) &&
398
                    array_key_exists(strtolower($server_info['username']), $bad_usernames)
399
                ) {
400
                    $msg = $lang['strlogindisallowed'];
401
402
                    throw new \Exception($msg);
403
                }
404
405
                if (!isset($server_info['password']) ||
406
                    $server_info['password'] == ''
407
                ) {
408
                    $msg = $lang['strlogindisallowed'];
409
410
                    throw new \Exception($msg);
411
                }
412
            }
413
414
            try {
415
                // Create the connection object and make the connection
416
                $this->_connection = new \PHPPgAdmin\Database\Connection(
417
                    $server_info,
418
                    $database_to_use,
419
                    $this->container
420
                );
421
            } catch (\PHPPgAdmin\ADOdbException $e) {
422
                throw new \Exception($lang['strloginfailed']);
423
            }
424
        }
425
426
        return $this->_connection;
427
    }
428
429
    /**
430
     * Validate and retrieve information on a server.
431
     * If the parameter isn't supplied then the currently
432
     * connected server is returned.
433
     *
434
     * @param string $server_id A server identifier (host:port)
435
     *
436
     * @return array An associative array of server properties
437
     */
438
    public function getServerInfo($server_id = null)
439
    {
440
        //\PC::debug(['$server_id' => $server_id]);
441
442
        if ($server_id !== null) {
443
            $this->_server_id = $server_id;
444
        } elseif ($this->_server_info !== null) {
445
            return $this->_server_info;
446
        }
447
448
        // Check for the server in the logged-in list
449
        if (isset($_SESSION['webdbLogin'][$this->_server_id])) {
450
            $this->_server_info = $_SESSION['webdbLogin'][$this->_server_id];
451
452
            return $this->_server_info;
453
        }
454
455
        // Otherwise, look for it in the conf file
456
        foreach ($this->conf['servers'] as $idx => $info) {
457
            $server_string = $info['host'].':'.$info['port'].':'.$info['sslmode'];
458
            $server_sha    = sha1($server_string);
459
460
            if ($this->_server_id === $server_string ||
461
                $this->_server_id === $server_sha
462
            ) {
463
                if (isset($info['username'])) {
464
                    $this->setServerInfo(null, $info, $this->_server_id);
465
                } elseif (isset($_SESSION['sharedUsername'])) {
466
                    $info['username'] = $_SESSION['sharedUsername'];
467
                    $info['password'] = $_SESSION['sharedPassword'];
468
                    $this->setReloadBrowser(true);
469
                    $this->setServerInfo(null, $info, $this->_server_id);
470
                }
471
                $this->_server_info = $info;
472
473
                return $this->_server_info;
474
            }
475
        }
476
477
        if ($server_id === null) {
478
            $this->_server_info = null;
479
480
            return $this->_server_info;
481
        }
482
483
        $this->prtrace('Invalid server param');
484
        $this->_server_info = null;
485
        // Unable to find a matching server, are we being hacked?
486
        return $this->halt($this->lang['strinvalidserverparam']);
487
    }
488
489
    /**
490
     * Set server information.
491
     *
492
     * @param null|string $key       parameter name to set, or null to replace all
493
     *                               params with the assoc-array in $value
494
     * @param mixed       $value     the new value, or null to unset the parameter
495
     * @param null|string $server_id the server identifier, or null for current server
496
     */
497
    public function setServerInfo($key, $value, $server_id = null)
498
    {
499
        //\PC::debug('setsetverinfo');
500
        if ($server_id === null) {
501
            $server_id = $this->container->requestobj->getParam('server');
502
        }
503
504
        if ($key === null) {
505
            if ($value === null) {
506
                unset($_SESSION['webdbLogin'][$server_id]);
507
            } else {
508
                //\PC::debug(['server_id' => $server_id, 'value' => $value], 'webdbLogin null key');
509
                $_SESSION['webdbLogin'][$server_id] = $value;
510
            }
511
        } else {
512
            if ($value === null) {
513
                unset($_SESSION['webdbLogin'][$server_id][$key]);
514
            } else {
515
                //\PC::debug(['server_id' => $server_id, 'key' => $key, 'value' => $value], __FILE__ . ' ' . __LINE__ . ' webdbLogin key ' . $key);
516
                $_SESSION['webdbLogin'][$server_id][$key] = $value;
517
            }
518
        }
519
    }
520
521
    public function getDatabase($database = '')
522
    {
523
        if ($this->_server_id === null && !isset($_REQUEST['database'])) {
524
            return null;
525
        }
526
527
        $server_info = $this->getServerInfo($this->_server_id);
528
529
        if ($this->_server_id !== null &&
530
            isset($server_info['useonlydefaultdb']) &&
531
            $server_info['useonlydefaultdb'] === true &&
532
            isset($server_info['defaultdb'])
533
        ) {
534
            $this->_database = $server_info['defaultdb'];
535
        } elseif ($database !== '') {
536
            $this->_database = $database;
537
        } elseif (isset($_REQUEST['database'])) {
538
            // Connect to the current database
539
            $this->_database = $_REQUEST['database'];
540
        } elseif (isset($server_info['defaultdb'])) {
541
            // or if one is not specified then connect to the default database.
542
            $this->_database = $server_info['defaultdb'];
543
        } else {
544
            return null;
545
        }
546
547
        return $this->_database;
548
    }
549
550
    /**
551
     * Set the current schema.
552
     *
553
     * @param string $schema The schema name
554
     *
555
     * @return int 0 on success
556
     */
557
    public function setCurrentSchema($schema)
558
    {
559
        $data = $this->getDatabaseAccessor();
560
561
        $status = $data->setSchema($schema);
562
        if ($status != 0) {
563
            return $status;
564
        }
565
566
        $_REQUEST['schema'] = $schema;
567
        $this->container->offsetSet('schema', $schema);
568
        $this->setHREF();
569
570
        return 0;
571
    }
572
573
    /**
574
     * Checks if dumps are properly set up.
575
     *
576
     * @param bool $all (optional) True to check pg_dumpall, false to just check pg_dump
577
     *
578
     * @return bool True, dumps are set up, false otherwise
579
     */
580
    public function isDumpEnabled($all = false)
581
    {
582
        $info = $this->getServerInfo();
583
584
        return !empty($info[$all ? 'pg_dumpall_path' : 'pg_dump_path']);
585
    }
586
587
    /**
588
     * Sets the href tracking variable.
589
     *
590
     * @return \PHPPgAdmin\Misc this class instance
591
     */
592
    public function setHREF()
593
    {
594
        $this->href = $this->getHREF();
595
        //\PC::debug($this->href, 'Misc::href');
596
        return $this;
597
    }
598
599
    /**
600
     * Get a href query string, excluding objects below the given object type (inclusive).
601
     *
602
     * @param null|string $exclude_from
603
     *
604
     * @return string
605
     */
606
    public function getHREF($exclude_from = null)
607
    {
608
        $href = [];
609
610
        $server   = $this->container->server || isset($_REQUEST['server']) ? $_REQUEST['server'] : null;
611
        $database = $this->container->database || isset($_REQUEST['database']) ? $_REQUEST['database'] : null;
612
        $schema   = $this->container->schema || isset($_REQUEST['schema']) ? $_REQUEST['schema'] : null;
613
614
        if ($server && $exclude_from !== 'server') {
615
            $href[] = 'server='.urlencode($server);
616
        }
617
        if ($database && $exclude_from !== 'database') {
618
            $href[] = 'database='.urlencode($database);
619
        }
620
        if ($schema && $exclude_from !== 'schema') {
621
            $href[] = 'schema='.urlencode($schema);
622
        }
623
624
        $this->href = htmlentities(implode('&', $href));
625
626
        return $this->href;
627
    }
628
629
    public function getSubjectParams($subject)
630
    {
631
        $plugin_manager = $this->plugin_manager;
632
633
        $vars = [];
634
635
        switch ($subject) {
636
            case 'root':
637
                $vars = [
638
                    'params' => [
639
                        'subject' => 'root',
640
                    ],
641
                ];
642
643
                break;
644
            case 'server':
645
                $vars = ['params' => [
646
                    'server'  => $_REQUEST['server'],
647
                    'subject' => 'server',
648
                ]];
649
650
                break;
651
            case 'role':
652
                $vars = ['params' => [
653
                    'server'   => $_REQUEST['server'],
654
                    'subject'  => 'role',
655
                    'action'   => 'properties',
656
                    'rolename' => $_REQUEST['rolename'],
657
                ]];
658
659
                break;
660
            case 'database':
661
                $vars = ['params' => [
662
                    'server'   => $_REQUEST['server'],
663
                    'subject'  => 'database',
664
                    'database' => $_REQUEST['database'],
665
                ]];
666
667
                break;
668
            case 'schema':
669
                $vars = ['params' => [
670
                    'server'   => $_REQUEST['server'],
671
                    'subject'  => 'schema',
672
                    'database' => $_REQUEST['database'],
673
                    'schema'   => $_REQUEST['schema'],
674
                ]];
675
676
                break;
677
            case 'table':
678
                $vars = ['params' => [
679
                    'server'   => $_REQUEST['server'],
680
                    'subject'  => 'table',
681
                    'database' => $_REQUEST['database'],
682
                    'schema'   => $_REQUEST['schema'],
683
                    'table'    => $_REQUEST['table'],
684
                ]];
685
686
                break;
687
            case 'selectrows':
688
                $vars = [
689
                    'url'    => 'tables',
690
                    'params' => [
691
                        'server'   => $_REQUEST['server'],
692
                        'subject'  => 'table',
693
                        'database' => $_REQUEST['database'],
694
                        'schema'   => $_REQUEST['schema'],
695
                        'table'    => $_REQUEST['table'],
696
                        'action'   => 'confselectrows',
697
                    ], ];
698
699
                break;
700
            case 'view':
701
                $vars = ['params' => [
702
                    'server'   => $_REQUEST['server'],
703
                    'subject'  => 'view',
704
                    'database' => $_REQUEST['database'],
705
                    'schema'   => $_REQUEST['schema'],
706
                    'view'     => $_REQUEST['view'],
707
                ]];
708
709
                break;
710
            case 'matview':
711
                $vars = ['params' => [
712
                    'server'   => $_REQUEST['server'],
713
                    'subject'  => 'matview',
714
                    'database' => $_REQUEST['database'],
715
                    'schema'   => $_REQUEST['schema'],
716
                    'matview'  => $_REQUEST['matview'],
717
                ]];
718
719
                break;
720
            case 'fulltext':
721
            case 'ftscfg':
722
                $vars = ['params' => [
723
                    'server'   => $_REQUEST['server'],
724
                    'subject'  => 'fulltext',
725
                    'database' => $_REQUEST['database'],
726
                    'schema'   => $_REQUEST['schema'],
727
                    'action'   => 'viewconfig',
728
                    'ftscfg'   => $_REQUEST['ftscfg'],
729
                ]];
730
731
                break;
732
            case 'function':
733
                $vars = ['params' => [
734
                    'server'       => $_REQUEST['server'],
735
                    'subject'      => 'function',
736
                    'database'     => $_REQUEST['database'],
737
                    'schema'       => $_REQUEST['schema'],
738
                    'function'     => $_REQUEST['function'],
739
                    'function_oid' => $_REQUEST['function_oid'],
740
                ]];
741
742
                break;
743
            case 'aggregate':
744
                $vars = ['params' => [
745
                    'server'   => $_REQUEST['server'],
746
                    'subject'  => 'aggregate',
747
                    'action'   => 'properties',
748
                    'database' => $_REQUEST['database'],
749
                    'schema'   => $_REQUEST['schema'],
750
                    'aggrname' => $_REQUEST['aggrname'],
751
                    'aggrtype' => $_REQUEST['aggrtype'],
752
                ]];
753
754
                break;
755
            case 'column':
756
                if (isset($_REQUEST['table'])) {
757
                    $vars = ['params' => [
758
                        'server'   => $_REQUEST['server'],
759
                        'subject'  => 'column',
760
                        'database' => $_REQUEST['database'],
761
                        'schema'   => $_REQUEST['schema'],
762
                        'table'    => $_REQUEST['table'],
763
                        'column'   => $_REQUEST['column'],
764
                    ]];
765
                } else {
766
                    $vars = ['params' => [
767
                        'server'   => $_REQUEST['server'],
768
                        'subject'  => 'column',
769
                        'database' => $_REQUEST['database'],
770
                        'schema'   => $_REQUEST['schema'],
771
                        'view'     => $_REQUEST['view'],
772
                        'column'   => $_REQUEST['column'],
773
                    ]];
774
                }
775
776
                break;
777
            case 'plugin':
778
                $vars = [
779
                    'url'    => 'plugin',
780
                    'params' => [
781
                        'server'  => $_REQUEST['server'],
782
                        'subject' => 'plugin',
783
                        'plugin'  => $_REQUEST['plugin'],
784
                    ], ];
785
786
                if (!is_null($plugin_manager->getPlugin($_REQUEST['plugin']))) {
787
                    $vars['params'] = array_merge($vars['params'], $plugin_manager->getPlugin($_REQUEST['plugin'])->get_subject_params());
788
                }
789
790
                break;
791
            default:
792
                return false;
793
        }
794
795
        if (!isset($vars['url'])) {
796
            $vars['url'] = SUBFOLDER.'/redirect';
797
        }
798
        if ($vars['url'] == SUBFOLDER.'/redirect' && isset($vars['params']['subject'])) {
799
            $vars['url'] = SUBFOLDER.'/redirect/'.$vars['params']['subject'];
800
            unset($vars['params']['subject']);
801
        }
802
803
        return $vars;
804
    }
805
806
    /**
807
     * Sets the form tracking variable.
808
     */
809
    public function setForm()
810
    {
811
        $form = [];
812
        if ($this->container->server) {
813
            $form[] = '<input type="hidden" name="server" value="'.htmlspecialchars($this->container->server).'" />';
814
        }
815
        if ($this->container->database) {
816
            $form[] = '<input type="hidden" name="database" value="'.htmlspecialchars($this->container->database).'" />';
817
        }
818
819
        if ($this->container->schema) {
820
            $form[] = '<input type="hidden" name="schema" value="'.htmlspecialchars($this->container->schema).'" />';
821
        }
822
        $this->form = implode("\n", $form);
823
824
        return $this->form;
825
        //\PC::debug($this->form, 'Misc::form');
826
    }
827
828
    /**
829
     * Render a value into HTML using formatting rules specified
830
     * by a type name and parameters.
831
     *
832
     * @param string $str    The string to change
833
     * @param string $type   Field type (optional), this may be an internal PostgreSQL type, or:
834
     *                       yesno    - same as bool, but renders as 'Yes' or 'No'.
835
     *                       pre      - render in a <pre> block.
836
     *                       nbsp     - replace all spaces with &nbsp;'s
837
     *                       verbatim - render exactly as supplied, no escaping what-so-ever.
838
     *                       callback - render using a callback function supplied in the 'function' param.
839
     * @param array  $params Type parameters (optional), known parameters:
840
     *                       null     - string to display if $str is null, or set to TRUE to use a default 'NULL' string,
841
     *                       otherwise nothing is rendered.
842
     *                       clip     - if true, clip the value to a fixed length, and append an ellipsis...
843
     *                       cliplen  - the maximum length when clip is enabled (defaults to $conf['max_chars'])
844
     *                       ellipsis - the string to append to a clipped value (defaults to $lang['strellipsis'])
845
     *                       tag      - an HTML element name to surround the value.
846
     *                       class    - a class attribute to apply to any surrounding HTML element.
847
     *                       align    - an align attribute ('left','right','center' etc.)
848
     *                       true     - (type='bool') the representation of true.
849
     *                       false    - (type='bool') the representation of false.
850
     *                       function - (type='callback') a function name, accepts args ($str, $params) and returns a rendering.
851
     *                       lineno   - prefix each line with a line number.
852
     *                       map      - an associative array.
853
     *
854
     * @return string The HTML rendered value
855
     */
856
    public function printVal($str, $type = null, $params = [])
857
    {
858
        $lang = $this->lang;
859
        $data = $this->getDatabaseAccessor();
860
861
        // Shortcircuit for a NULL value
862
        if (!$str) {
863
            return isset($params['null'])
864
            ? ($params['null'] === true ? '<i>NULL</i>' : $params['null'])
865
            : '';
866
        }
867
868
        if (isset($params['map'], $params['map'][$str])) {
869
            $str = $params['map'][$str];
870
        }
871
872
        // Clip the value if the 'clip' parameter is true.
873
        if (isset($params['clip']) && $params['clip'] === true) {
874
            $maxlen   = isset($params['cliplen']) && is_integer($params['cliplen']) ? $params['cliplen'] : $this->conf['max_chars'];
875
            $ellipsis = isset($params['ellipsis']) ? $params['ellipsis'] : $lang['strellipsis'];
876
            if (strlen($str) > $maxlen) {
877
                $str = substr($str, 0, $maxlen - 1).$ellipsis;
878
            }
879
        }
880
881
        $out   = '';
882
        $class = '';
883
884
        switch ($type) {
885
            case 'int2':
886
            case 'int4':
887
            case 'int8':
888
            case 'float4':
889
            case 'float8':
890
            case 'money':
891
            case 'numeric':
892
            case 'oid':
893
            case 'xid':
894
            case 'cid':
895
            case 'tid':
896
                $align = 'right';
897
                $out   = nl2br(htmlspecialchars(\PHPPgAdmin\Traits\HelperTrait::br2ln($str)));
898
899
                break;
900
            case 'yesno':
901
                if (!isset($params['true'])) {
902
                    $params['true'] = $lang['stryes'];
903
                }
904
905
                if (!isset($params['false'])) {
906
                    $params['false'] = $lang['strno'];
907
                }
908
909
            // no break - fall through to boolean case.
910
            case 'bool':
911
            case 'boolean':
912
                if (is_bool($str)) {
913
                    $str = $str ? 't' : 'f';
914
                }
915
916
                switch ($str) {
917
                    case 't':
918
                        $out   = (isset($params['true']) ? $params['true'] : $lang['strtrue']);
919
                        $align = 'center';
920
921
                        break;
922
                    case 'f':
923
                        $out   = (isset($params['false']) ? $params['false'] : $lang['strfalse']);
924
                        $align = 'center';
925
926
                        break;
927
                    default:
928
                        $out = htmlspecialchars($str);
929
                }
930
931
                break;
932
            case 'bytea':
933
                $tag   = 'div';
934
                $class = 'pre';
935
                $out   = $data->escapeBytea($str);
936
937
                break;
938
            case 'errormsg':
939
                $tag   = 'pre';
940
                $class = 'error';
941
                $out   = htmlspecialchars($str);
942
943
                break;
944
            case 'pre':
945
                $tag = 'pre';
946
                $out = htmlspecialchars($str);
947
948
                break;
949
            case 'prenoescape':
950
                $tag = 'pre';
951
                $out = $str;
952
953
                break;
954
            case 'nbsp':
955
                $out = nl2br(str_replace(' ', '&nbsp;', \PHPPgAdmin\Traits\HelperTrait::br2ln($str)));
956
957
                break;
958
            case 'verbatim':
959
                $out = $str;
960
961
                break;
962
            case 'callback':
963
                $out = $params['function']($str, $params);
964
965
                break;
966
            case 'prettysize':
967
                if ($str == -1) {
968
                    $out = $lang['strnoaccess'];
969
                } else {
970
                    $out = \PHPPgAdmin\Traits\HelperTrait::formatSizeUnits($str, $lang);
971
                }
972
973
                break;
974
            default:
975
                // If the string contains at least one instance of >1 space in a row, a tab
976
                // character, a space at the start of a line, or a space at the start of
977
                // the whole string then render within a pre-formatted element (<pre>).
978
                if (preg_match('/(^ |  |\t|\n )/m', $str)) {
979
                    $tag   = 'pre';
980
                    $class = 'data';
981
                    $out   = htmlspecialchars($str);
982
                } else {
983
                    $tag = 'span';
984
                    $out = nl2br(htmlspecialchars(\PHPPgAdmin\Traits\HelperTrait::br2ln($str)));
985
                }
986
        }
987
988
        if (isset($params['class'])) {
989
            $class = $params['class'];
990
        }
991
992
        if (isset($params['align'])) {
993
            $align = $params['align'];
994
        }
995
996
        if (!isset($tag) && (!empty($class) || isset($align))) {
997
            $tag = 'div';
998
        }
999
1000
        if (isset($tag)) {
1001
            $alignattr = isset($align) ? " style=\"text-align: {$align}\"" : '';
1002
            $classattr = !empty($class) ? " class=\"{$class}\"" : '';
1003
            $out       = "<{$tag}{$alignattr}{$classattr}>{$out}</{$tag}>";
1004
        }
1005
1006
        // Add line numbers if 'lineno' param is true
1007
        if (isset($params['lineno']) && $params['lineno'] === true) {
1008
            $lines = explode("\n", $str);
1009
            $num   = count($lines);
1010
            if ($num > 0) {
1011
                $temp = "<table>\n<tr><td class=\"{$class}\" style=\"vertical-align: top; padding-right: 10px;\"><pre class=\"{$class}\">";
1012
                for ($i = 1; $i <= $num; ++$i) {
1013
                    $temp .= $i."\n";
1014
                }
1015
                $temp .= "</pre></td><td class=\"{$class}\" style=\"vertical-align: top;\">{$out}</td></tr></table>\n";
1016
                $out = $temp;
1017
            }
1018
            unset($lines);
1019
        }
1020
1021
        return $out;
1022
    }
1023
1024
    /**
1025
     * A function to recursively strip slashes.  Used to
1026
     * enforce magic_quotes_gpc being off.
1027
     *
1028
     * @param mixed $var The variable to strip (passed by reference)
1029
     */
1030
    public function stripVar(&$var)
1031
    {
1032
        if (is_array($var)) {
1033
            foreach ($var as $k => $v) {
1034
                $this->stripVar($var[$k]);
1035
1036
                /* magic_quotes_gpc escape keys as well ...*/
1037
                if (is_string($k)) {
1038
                    $ek = stripslashes($k);
1039
                    if ($ek !== $k) {
1040
                        $var[$ek] = $var[$k];
1041
                        unset($var[$k]);
1042
                    }
1043
                }
1044
            }
1045
        } else {
1046
            $var = stripslashes($var);
1047
        }
1048
    }
1049
1050
    /**
1051
     * Retrieve the tab info for a specific tab bar.
1052
     *
1053
     * @param string $section the name of the tab bar
1054
     *
1055
     * @return array array of tabs
1056
     */
1057
    public function getNavTabs($section)
1058
    {
1059
        $data           = $this->getDatabaseAccessor();
1060
        $lang           = $this->lang;
1061
        $plugin_manager = $this->plugin_manager;
1062
1063
        $hide_advanced = ($this->conf['show_advanced'] === false);
1064
        $tabs          = [];
1065
1066
        switch ($section) {
1067
            case 'root':
1068
                $tabs = [
1069
                    'intro'   => [
1070
                        'title' => $lang['strintroduction'],
1071
                        'url'   => 'intro',
1072
                        'icon'  => 'Introduction',
1073
                    ],
1074
                    'servers' => [
1075
                        'title' => $lang['strservers'],
1076
                        'url'   => 'servers',
1077
                        'icon'  => 'Servers',
1078
                    ],
1079
                ];
1080
1081
                break;
1082
            case 'server':
1083
                $hide_users = true;
1084
                $hide_roles = false;
1085
                if ($data) {
1086
                    $hide_users = !$data->isSuperUser();
1087
                }
1088
1089
                $tabs = [
1090
                    'databases' => [
1091
                        'title'   => $lang['strdatabases'],
1092
                        'url'     => 'alldb',
1093
                        'urlvars' => ['subject' => 'server'],
1094
                        'help'    => 'pg.database',
1095
                        'icon'    => 'Databases',
1096
                    ],
1097
                ];
1098
                if ($data && $data->hasRoles()) {
1099
                    $tabs = array_merge($tabs, [
1100
                        'users' => [
1101
                            'title'   => $lang['strusers'],
1102
                            'url'     => 'users',
1103
                            'urlvars' => ['subject' => 'server'],
1104
                            'hide'    => $hide_roles,
1105
                            'help'    => 'pg.user',
1106
                            'icon'    => 'Users',
1107
                        ],
1108
                        'roles' => [
1109
                            'title'   => $lang['strroles'],
1110
                            'url'     => 'roles',
1111
                            'urlvars' => ['subject' => 'server'],
1112
                            'hide'    => $hide_roles,
1113
                            'help'    => 'pg.role',
1114
                            'icon'    => 'Roles',
1115
                        ],
1116
                    ]);
1117
                } else {
1118
                    $tabs = array_merge($tabs, [
1119
                        'users'  => [
1120
                            'title'   => $lang['strusers'],
1121
                            'url'     => 'users',
1122
                            'urlvars' => ['subject' => 'server'],
1123
                            'hide'    => $hide_users,
1124
                            'help'    => 'pg.user',
1125
                            'icon'    => 'Users',
1126
                        ],
1127
                        'groups' => [
1128
                            'title'   => $lang['strgroups'],
1129
                            'url'     => 'groups',
1130
                            'urlvars' => ['subject' => 'server'],
1131
                            'hide'    => $hide_users,
1132
                            'help'    => 'pg.group',
1133
                            'icon'    => 'UserGroups',
1134
                        ],
1135
                    ]);
1136
                }
1137
1138
                $tabs = array_merge($tabs, [
1139
                    'account'     => [
1140
                        'title'   => $lang['straccount'],
1141
                        'url'     => ($data && $data->hasRoles()) ? 'roles' : 'users',
1142
                        'urlvars' => ['subject' => 'server', 'action' => 'account'],
1143
                        'hide'    => !$hide_users,
1144
                        'help'    => 'pg.role',
1145
                        'icon'    => 'User',
1146
                    ],
1147
                    'tablespaces' => [
1148
                        'title'   => $lang['strtablespaces'],
1149
                        'url'     => 'tablespaces',
1150
                        'urlvars' => ['subject' => 'server'],
1151
                        'hide'    => !$data || !$data->hasTablespaces(),
1152
                        'help'    => 'pg.tablespace',
1153
                        'icon'    => 'Tablespaces',
1154
                    ],
1155
                    'export'      => [
1156
                        'title'   => $lang['strexport'],
1157
                        'url'     => 'alldb',
1158
                        'urlvars' => ['subject' => 'server', 'action' => 'export'],
1159
                        'hide'    => !$this->isDumpEnabled(),
1160
                        'icon'    => 'Export',
1161
                    ],
1162
                ]);
1163
1164
                break;
1165
            case 'database':
1166
                $tabs = [
1167
                    'schemas'    => [
1168
                        'title'   => $lang['strschemas'],
1169
                        'url'     => 'schemas',
1170
                        'urlvars' => ['subject' => 'database'],
1171
                        'help'    => 'pg.schema',
1172
                        'icon'    => 'Schemas',
1173
                    ],
1174
                    'sql'        => [
1175
                        'title'   => $lang['strsql'],
1176
                        'url'     => 'database',
1177
                        'urlvars' => ['subject' => 'database', 'action' => 'sql', 'new' => 1],
1178
                        'help'    => 'pg.sql',
1179
                        'tree'    => false,
1180
                        'icon'    => 'SqlEditor',
1181
                    ],
1182
                    'find'       => [
1183
                        'title'   => $lang['strfind'],
1184
                        'url'     => 'database',
1185
                        'urlvars' => ['subject' => 'database', 'action' => 'find'],
1186
                        'tree'    => false,
1187
                        'icon'    => 'Search',
1188
                    ],
1189
                    'variables'  => [
1190
                        'title'   => $lang['strvariables'],
1191
                        'url'     => 'database',
1192
                        'urlvars' => ['subject' => 'database', 'action' => 'variables'],
1193
                        'help'    => 'pg.variable',
1194
                        'tree'    => false,
1195
                        'icon'    => 'Variables',
1196
                    ],
1197
                    'processes'  => [
1198
                        'title'   => $lang['strprocesses'],
1199
                        'url'     => 'database',
1200
                        'urlvars' => ['subject' => 'database', 'action' => 'processes'],
1201
                        'help'    => 'pg.process',
1202
                        'tree'    => false,
1203
                        'icon'    => 'Processes',
1204
                    ],
1205
                    'locks'      => [
1206
                        'title'   => $lang['strlocks'],
1207
                        'url'     => 'database',
1208
                        'urlvars' => ['subject' => 'database', 'action' => 'locks'],
1209
                        'help'    => 'pg.locks',
1210
                        'tree'    => false,
1211
                        'icon'    => 'Key',
1212
                    ],
1213
                    'admin'      => [
1214
                        'title'   => $lang['stradmin'],
1215
                        'url'     => 'database',
1216
                        'urlvars' => ['subject' => 'database', 'action' => 'admin'],
1217
                        'tree'    => false,
1218
                        'icon'    => 'Admin',
1219
                    ],
1220
                    'privileges' => [
1221
                        'title'   => $lang['strprivileges'],
1222
                        'url'     => 'privileges',
1223
                        'urlvars' => ['subject' => 'database'],
1224
                        'hide'    => !isset($data->privlist['database']),
1225
                        'help'    => 'pg.privilege',
1226
                        'tree'    => false,
1227
                        'icon'    => 'Privileges',
1228
                    ],
1229
                    'languages'  => [
1230
                        'title'   => $lang['strlanguages'],
1231
                        'url'     => 'languages',
1232
                        'urlvars' => ['subject' => 'database'],
1233
                        'hide'    => $hide_advanced,
1234
                        'help'    => 'pg.language',
1235
                        'icon'    => 'Languages',
1236
                    ],
1237
                    'casts'      => [
1238
                        'title'   => $lang['strcasts'],
1239
                        'url'     => 'casts',
1240
                        'urlvars' => ['subject' => 'database'],
1241
                        'hide'    => $hide_advanced,
1242
                        'help'    => 'pg.cast',
1243
                        'icon'    => 'Casts',
1244
                    ],
1245
                    'export'     => [
1246
                        'title'   => $lang['strexport'],
1247
                        'url'     => 'database',
1248
                        'urlvars' => ['subject' => 'database', 'action' => 'export'],
1249
                        'hide'    => !$this->isDumpEnabled(),
1250
                        'tree'    => false,
1251
                        'icon'    => 'Export',
1252
                    ],
1253
                ];
1254
1255
                break;
1256
            case 'schema':
1257
                $tabs = [
1258
                    'tables'      => [
1259
                        'title'   => $lang['strtables'],
1260
                        'url'     => 'tables',
1261
                        'urlvars' => ['subject' => 'schema'],
1262
                        'help'    => 'pg.table',
1263
                        'icon'    => 'Tables',
1264
                    ],
1265
                    'views'       => [
1266
                        'title'   => $lang['strviews'],
1267
                        'url'     => 'views',
1268
                        'urlvars' => ['subject' => 'schema'],
1269
                        'help'    => 'pg.view',
1270
                        'icon'    => 'Views',
1271
                    ],
1272
                    'matviews'    => [
1273
                        'title'   => 'M '.$lang['strviews'],
1274
                        'url'     => 'materializedviews',
1275
                        'urlvars' => ['subject' => 'schema'],
1276
                        'help'    => 'pg.matview',
1277
                        'icon'    => 'MViews',
1278
                    ],
1279
                    'sequences'   => [
1280
                        'title'   => $lang['strsequences'],
1281
                        'url'     => 'sequences',
1282
                        'urlvars' => ['subject' => 'schema'],
1283
                        'help'    => 'pg.sequence',
1284
                        'icon'    => 'Sequences',
1285
                    ],
1286
                    'functions'   => [
1287
                        'title'   => $lang['strfunctions'],
1288
                        'url'     => 'functions',
1289
                        'urlvars' => ['subject' => 'schema'],
1290
                        'help'    => 'pg.function',
1291
                        'icon'    => 'Functions',
1292
                    ],
1293
                    'fulltext'    => [
1294
                        'title'   => $lang['strfulltext'],
1295
                        'url'     => 'fulltext',
1296
                        'urlvars' => ['subject' => 'schema'],
1297
                        'help'    => 'pg.fts',
1298
                        'tree'    => true,
1299
                        'icon'    => 'Fts',
1300
                    ],
1301
                    'domains'     => [
1302
                        'title'   => $lang['strdomains'],
1303
                        'url'     => 'domains',
1304
                        'urlvars' => ['subject' => 'schema'],
1305
                        'help'    => 'pg.domain',
1306
                        'icon'    => 'Domains',
1307
                    ],
1308
                    'aggregates'  => [
1309
                        'title'   => $lang['straggregates'],
1310
                        'url'     => 'aggregates',
1311
                        'urlvars' => ['subject' => 'schema'],
1312
                        'hide'    => $hide_advanced,
1313
                        'help'    => 'pg.aggregate',
1314
                        'icon'    => 'Aggregates',
1315
                    ],
1316
                    'types'       => [
1317
                        'title'   => $lang['strtypes'],
1318
                        'url'     => 'types',
1319
                        'urlvars' => ['subject' => 'schema'],
1320
                        'hide'    => $hide_advanced,
1321
                        'help'    => 'pg.type',
1322
                        'icon'    => 'Types',
1323
                    ],
1324
                    'operators'   => [
1325
                        'title'   => $lang['stroperators'],
1326
                        'url'     => 'operators',
1327
                        'urlvars' => ['subject' => 'schema'],
1328
                        'hide'    => $hide_advanced,
1329
                        'help'    => 'pg.operator',
1330
                        'icon'    => 'Operators',
1331
                    ],
1332
                    'opclasses'   => [
1333
                        'title'   => $lang['stropclasses'],
1334
                        'url'     => 'opclasses',
1335
                        'urlvars' => ['subject' => 'schema'],
1336
                        'hide'    => $hide_advanced,
1337
                        'help'    => 'pg.opclass',
1338
                        'icon'    => 'OperatorClasses',
1339
                    ],
1340
                    'conversions' => [
1341
                        'title'   => $lang['strconversions'],
1342
                        'url'     => 'conversions',
1343
                        'urlvars' => ['subject' => 'schema'],
1344
                        'hide'    => $hide_advanced,
1345
                        'help'    => 'pg.conversion',
1346
                        'icon'    => 'Conversions',
1347
                    ],
1348
                    'privileges'  => [
1349
                        'title'   => $lang['strprivileges'],
1350
                        'url'     => 'privileges',
1351
                        'urlvars' => ['subject' => 'schema'],
1352
                        'help'    => 'pg.privilege',
1353
                        'tree'    => false,
1354
                        'icon'    => 'Privileges',
1355
                    ],
1356
                    'export'      => [
1357
                        'title'   => $lang['strexport'],
1358
                        'url'     => 'schemas',
1359
                        'urlvars' => ['subject' => 'schema', 'action' => 'export'],
1360
                        'hide'    => !$this->isDumpEnabled(),
1361
                        'tree'    => false,
1362
                        'icon'    => 'Export',
1363
                    ],
1364
                ];
1365
                if (!$data->hasFTS()) {
1366
                    unset($tabs['fulltext']);
1367
                }
1368
1369
                break;
1370
            case 'table':
1371
                $tabs = [
1372
                    'columns'     => [
1373
                        'title'   => $lang['strcolumns'],
1374
                        'url'     => 'tblproperties',
1375
                        'urlvars' => ['subject' => 'table', 'table' => Decorator::field('table')],
1376
                        'icon'    => 'Columns',
1377
                        'branch'  => true,
1378
                    ],
1379
                    'browse'      => [
1380
                        'title'   => $lang['strbrowse'],
1381
                        'icon'    => 'Columns',
1382
                        'url'     => 'display',
1383
                        'urlvars' => ['subject' => 'table', 'table' => Decorator::field('table')],
1384
                        'return'  => 'table',
1385
                        'branch'  => true,
1386
                    ],
1387
                    'select'      => [
1388
                        'title'   => $lang['strselect'],
1389
                        'icon'    => 'Search',
1390
                        'url'     => 'tables',
1391
                        'urlvars' => ['subject' => 'table', 'table' => Decorator::field('table'), 'action' => 'confselectrows'],
1392
                        'help'    => 'pg.sql.select',
1393
                    ],
1394
                    'insert'      => [
1395
                        'title'   => $lang['strinsert'],
1396
                        'url'     => 'tables',
1397
                        'urlvars' => [
1398
                            'action' => 'confinsertrow',
1399
                            'table'  => Decorator::field('table'),
1400
                        ],
1401
                        'help'    => 'pg.sql.insert',
1402
                        'icon'    => 'Operator',
1403
                    ],
1404
                    'indexes'     => [
1405
                        'title'   => $lang['strindexes'],
1406
                        'url'     => 'indexes',
1407
                        'urlvars' => ['subject' => 'table', 'table' => Decorator::field('table')],
1408
                        'help'    => 'pg.index',
1409
                        'icon'    => 'Indexes',
1410
                        'branch'  => true,
1411
                    ],
1412
                    'constraints' => [
1413
                        'title'   => $lang['strconstraints'],
1414
                        'url'     => 'constraints',
1415
                        'urlvars' => ['subject' => 'table', 'table' => Decorator::field('table')],
1416
                        'help'    => 'pg.constraint',
1417
                        'icon'    => 'Constraints',
1418
                        'branch'  => true,
1419
                    ],
1420
                    'triggers'    => [
1421
                        'title'   => $lang['strtriggers'],
1422
                        'url'     => 'triggers',
1423
                        'urlvars' => ['subject' => 'table', 'table' => Decorator::field('table')],
1424
                        'help'    => 'pg.trigger',
1425
                        'icon'    => 'Triggers',
1426
                        'branch'  => true,
1427
                    ],
1428
                    'rules'       => [
1429
                        'title'   => $lang['strrules'],
1430
                        'url'     => 'rules',
1431
                        'urlvars' => ['subject' => 'table', 'table' => Decorator::field('table')],
1432
                        'help'    => 'pg.rule',
1433
                        'icon'    => 'Rules',
1434
                        'branch'  => true,
1435
                    ],
1436
                    'admin'       => [
1437
                        'title'   => $lang['stradmin'],
1438
                        'url'     => 'tables',
1439
                        'urlvars' => ['subject' => 'table', 'table' => Decorator::field('table'), 'action' => 'admin'],
1440
                        'icon'    => 'Admin',
1441
                    ],
1442
                    'info'        => [
1443
                        'title'   => $lang['strinfo'],
1444
                        'url'     => 'info',
1445
                        'urlvars' => ['subject' => 'table', 'table' => Decorator::field('table')],
1446
                        'icon'    => 'Statistics',
1447
                    ],
1448
                    'privileges'  => [
1449
                        'title'   => $lang['strprivileges'],
1450
                        'url'     => 'privileges',
1451
                        'urlvars' => ['subject' => 'table', 'table' => Decorator::field('table')],
1452
                        'help'    => 'pg.privilege',
1453
                        'icon'    => 'Privileges',
1454
                    ],
1455
                    'import'      => [
1456
                        'title'   => $lang['strimport'],
1457
                        'url'     => 'tblproperties',
1458
                        'urlvars' => ['subject' => 'table', 'table' => Decorator::field('table'), 'action' => 'import'],
1459
                        'icon'    => 'Import',
1460
                        'hide'    => false,
1461
                    ],
1462
                    'export'      => [
1463
                        'title'   => $lang['strexport'],
1464
                        'url'     => 'tblproperties',
1465
                        'urlvars' => ['subject' => 'table', 'table' => Decorator::field('table'), 'action' => 'export'],
1466
                        'icon'    => 'Export',
1467
                        'hide'    => false,
1468
                    ],
1469
                ];
1470
1471
                break;
1472
            case 'view':
1473
                $tabs = [
1474
                    'columns'    => [
1475
                        'title'   => $lang['strcolumns'],
1476
                        'url'     => 'viewproperties',
1477
                        'urlvars' => ['subject' => 'view', 'view' => Decorator::field('view')],
1478
                        'icon'    => 'Columns',
1479
                        'branch'  => true,
1480
                    ],
1481
                    'browse'     => [
1482
                        'title'   => $lang['strbrowse'],
1483
                        'icon'    => 'Columns',
1484
                        'url'     => 'display',
1485
                        'urlvars' => [
1486
                            'action'  => 'confselectrows',
1487
                            'return'  => 'schema',
1488
                            'subject' => 'view',
1489
                            'view'    => Decorator::field('view'),
1490
                        ],
1491
                        'branch'  => true,
1492
                    ],
1493
                    'select'     => [
1494
                        'title'   => $lang['strselect'],
1495
                        'icon'    => 'Search',
1496
                        'url'     => 'views',
1497
                        'urlvars' => ['action' => 'confselectrows', 'view' => Decorator::field('view')],
1498
                        'help'    => 'pg.sql.select',
1499
                    ],
1500
                    'definition' => [
1501
                        'title'   => $lang['strdefinition'],
1502
                        'url'     => 'viewproperties',
1503
                        'urlvars' => ['subject' => 'view', 'view' => Decorator::field('view'), 'action' => 'definition'],
1504
                        'icon'    => 'Definition',
1505
                    ],
1506
                    'rules'      => [
1507
                        'title'   => $lang['strrules'],
1508
                        'url'     => 'rules',
1509
                        'urlvars' => ['subject' => 'view', 'view' => Decorator::field('view')],
1510
                        'help'    => 'pg.rule',
1511
                        'icon'    => 'Rules',
1512
                        'branch'  => true,
1513
                    ],
1514
                    'privileges' => [
1515
                        'title'   => $lang['strprivileges'],
1516
                        'url'     => 'privileges',
1517
                        'urlvars' => ['subject' => 'view', 'view' => Decorator::field('view')],
1518
                        'help'    => 'pg.privilege',
1519
                        'icon'    => 'Privileges',
1520
                    ],
1521
                    'export'     => [
1522
                        'title'   => $lang['strexport'],
1523
                        'url'     => 'viewproperties',
1524
                        'urlvars' => ['subject' => 'view', 'view' => Decorator::field('view'), 'action' => 'export'],
1525
                        'icon'    => 'Export',
1526
                        'hide'    => false,
1527
                    ],
1528
                ];
1529
1530
                break;
1531
            case 'matview':
1532
                $tabs = [
1533
                    'columns'    => [
1534
                        'title'   => $lang['strcolumns'],
1535
                        'url'     => 'materializedviewproperties',
1536
                        'urlvars' => ['subject' => 'matview', 'matview' => Decorator::field('matview')],
1537
                        'icon'    => 'Columns',
1538
                        'branch'  => true,
1539
                    ],
1540
                    'browse'     => [
1541
                        'title'   => $lang['strbrowse'],
1542
                        'icon'    => 'Columns',
1543
                        'url'     => 'display',
1544
                        'urlvars' => [
1545
                            'action'  => 'confselectrows',
1546
                            'return'  => 'schema',
1547
                            'subject' => 'matview',
1548
                            'matview' => Decorator::field('matview'),
1549
                        ],
1550
                        'branch'  => true,
1551
                    ],
1552
                    'select'     => [
1553
                        'title'   => $lang['strselect'],
1554
                        'icon'    => 'Search',
1555
                        'url'     => 'materializedviews',
1556
                        'urlvars' => ['action' => 'confselectrows', 'matview' => Decorator::field('matview')],
1557
                        'help'    => 'pg.sql.select',
1558
                    ],
1559
                    'definition' => [
1560
                        'title'   => $lang['strdefinition'],
1561
                        'url'     => 'materializedviewproperties',
1562
                        'urlvars' => ['subject' => 'matview', 'matview' => Decorator::field('matview'), 'action' => 'definition'],
1563
                        'icon'    => 'Definition',
1564
                    ],
1565
                    'indexes'    => [
1566
                        'title'   => $lang['strindexes'],
1567
                        'url'     => 'indexes',
1568
                        'urlvars' => ['subject' => 'matview', 'matview' => Decorator::field('matview')],
1569
                        'help'    => 'pg.index',
1570
                        'icon'    => 'Indexes',
1571
                        'branch'  => true,
1572
                    ],
1573
                    /*'constraints' => [
1574
                    'title' => $lang['strconstraints'],
1575
                    'url' => 'constraints',
1576
                    'urlvars' => ['subject' => 'matview', 'matview' => Decorator::field('matview')],
1577
                    'help' => 'pg.constraint',
1578
                    'icon' => 'Constraints',
1579
                    'branch' => true,
1580
                     */
1581
1582
                    'rules'      => [
1583
                        'title'   => $lang['strrules'],
1584
                        'url'     => 'rules',
1585
                        'urlvars' => ['subject' => 'matview', 'matview' => Decorator::field('matview')],
1586
                        'help'    => 'pg.rule',
1587
                        'icon'    => 'Rules',
1588
                        'branch'  => true,
1589
                    ],
1590
                    'privileges' => [
1591
                        'title'   => $lang['strprivileges'],
1592
                        'url'     => 'privileges',
1593
                        'urlvars' => ['subject' => 'matview', 'matview' => Decorator::field('matview')],
1594
                        'help'    => 'pg.privilege',
1595
                        'icon'    => 'Privileges',
1596
                    ],
1597
                    'export'     => [
1598
                        'title'   => $lang['strexport'],
1599
                        'url'     => 'materializedviewproperties',
1600
                        'urlvars' => ['subject' => 'matview', 'matview' => Decorator::field('matview'), 'action' => 'export'],
1601
                        'icon'    => 'Export',
1602
                        'hide'    => false,
1603
                    ],
1604
                ];
1605
1606
                break;
1607
            case 'function':
1608
                $tabs = [
1609
                    'definition' => [
1610
                        'title'   => $lang['strdefinition'],
1611
                        'url'     => 'functions',
1612
                        'urlvars' => [
1613
                            'subject'      => 'function',
1614
                            'function'     => Decorator::field('function'),
1615
                            'function_oid' => Decorator::field('function_oid'),
1616
                            'action'       => 'properties',
1617
                        ],
1618
                        'icon'    => 'Definition',
1619
                    ],
1620
                    'privileges' => [
1621
                        'title'   => $lang['strprivileges'],
1622
                        'url'     => 'privileges',
1623
                        'urlvars' => [
1624
                            'subject'      => 'function',
1625
                            'function'     => Decorator::field('function'),
1626
                            'function_oid' => Decorator::field('function_oid'),
1627
                        ],
1628
                        'icon'    => 'Privileges',
1629
                    ],
1630
                ];
1631
1632
                break;
1633
            case 'aggregate':
1634
                $tabs = [
1635
                    'definition' => [
1636
                        'title'   => $lang['strdefinition'],
1637
                        'url'     => 'aggregates',
1638
                        'urlvars' => [
1639
                            'subject'  => 'aggregate',
1640
                            'aggrname' => Decorator::field('aggrname'),
1641
                            'aggrtype' => Decorator::field('aggrtype'),
1642
                            'action'   => 'properties',
1643
                        ],
1644
                        'icon'    => 'Definition',
1645
                    ],
1646
                ];
1647
1648
                break;
1649
            case 'role':
1650
                $tabs = [
1651
                    'definition' => [
1652
                        'title'   => $lang['strdefinition'],
1653
                        'url'     => 'roles',
1654
                        'urlvars' => [
1655
                            'subject'  => 'role',
1656
                            'rolename' => Decorator::field('rolename'),
1657
                            'action'   => 'properties',
1658
                        ],
1659
                        'icon'    => 'Definition',
1660
                    ],
1661
                ];
1662
1663
                break;
1664
            case 'popup':
1665
                $tabs = [
1666
                    'sql'  => [
1667
                        'title'   => $lang['strsql'],
1668
                        'url'     => '/src/views/sqledit',
1669
                        'urlvars' => ['action' => 'sql', 'subject' => 'schema'],
1670
                        'help'    => 'pg.sql',
1671
                        'icon'    => 'SqlEditor',
1672
                    ],
1673
                    'find' => [
1674
                        'title'   => $lang['strfind'],
1675
                        'url'     => '/src/views/sqledit',
1676
                        'urlvars' => ['action' => 'find', 'subject' => 'schema'],
1677
                        'icon'    => 'Search',
1678
                    ],
1679
                ];
1680
1681
                break;
1682
            case 'column':
1683
                $tabs = [
1684
                    'properties' => [
1685
                        'title'   => $lang['strcolprop'],
1686
                        'url'     => 'colproperties',
1687
                        'urlvars' => [
1688
                            'subject' => 'column',
1689
                            'table'   => Decorator::field('table'),
1690
                            'column'  => Decorator::field('column'),
1691
                        ],
1692
                        'icon'    => 'Column',
1693
                    ],
1694
                    'privileges' => [
1695
                        'title'   => $lang['strprivileges'],
1696
                        'url'     => 'privileges',
1697
                        'urlvars' => [
1698
                            'subject' => 'column',
1699
                            'table'   => Decorator::field('table'),
1700
                            'column'  => Decorator::field('column'),
1701
                        ],
1702
                        'help'    => 'pg.privilege',
1703
                        'icon'    => 'Privileges',
1704
                    ],
1705
                ];
1706
1707
                break;
1708
            case 'fulltext':
1709
                $tabs = [
1710
                    'ftsconfigs' => [
1711
                        'title'   => $lang['strftstabconfigs'],
1712
                        'url'     => 'fulltext',
1713
                        'urlvars' => ['subject' => 'schema'],
1714
                        'hide'    => !$data->hasFTS(),
1715
                        'help'    => 'pg.ftscfg',
1716
                        'tree'    => true,
1717
                        'icon'    => 'FtsCfg',
1718
                    ],
1719
                    'ftsdicts'   => [
1720
                        'title'   => $lang['strftstabdicts'],
1721
                        'url'     => 'fulltext',
1722
                        'urlvars' => ['subject' => 'schema', 'action' => 'viewdicts'],
1723
                        'hide'    => !$data->hasFTS(),
1724
                        'help'    => 'pg.ftsdict',
1725
                        'tree'    => true,
1726
                        'icon'    => 'FtsDict',
1727
                    ],
1728
                    'ftsparsers' => [
1729
                        'title'   => $lang['strftstabparsers'],
1730
                        'url'     => 'fulltext',
1731
                        'urlvars' => ['subject' => 'schema', 'action' => 'viewparsers'],
1732
                        'hide'    => !$data->hasFTS(),
1733
                        'help'    => 'pg.ftsparser',
1734
                        'tree'    => true,
1735
                        'icon'    => 'FtsParser',
1736
                    ],
1737
                ];
1738
1739
                break;
1740
        }
1741
1742
        // Tabs hook's place
1743
        $plugin_functions_parameters = [
1744
            'tabs'    => &$tabs,
1745
            'section' => $section,
1746
        ];
1747
        $plugin_manager->doHook('tabs', $plugin_functions_parameters);
1748
1749
        return $tabs;
1750
    }
1751
1752
    /**
1753
     * Get the URL for the last active tab of a particular tab bar.
1754
     *
1755
     * @param string $section
1756
     *
1757
     * @return null|mixed
1758
     */
1759
    public function getLastTabURL($section)
1760
    {
1761
        //$data = $this->getDatabaseAccessor();
1762
1763
        $tabs = $this->getNavTabs($section);
1764
        if (isset($_SESSION['webdbLastTab'][$section])) {
1765
            $tab = $tabs[$_SESSION['webdbLastTab'][$section]];
1766
        } else {
1767
            $tab = reset($tabs);
1768
        }
1769
        //$this->prtrace(['section' => $section, 'tabs' => $tabs, 'tab' => $tab]);
1770
        return isset($tab['url']) ? $tab : null;
1771
    }
1772
1773
    /**
1774
     * Converts a PHP.INI size variable to bytes.  Taken from publically available
1775
     * function by Chris DeRose, here: http://www.php.net/manual/en/configuration.directives.php#ini.file-uploads.
1776
     *
1777
     * @param mixed $strIniSize The PHP.INI variable
1778
     *
1779
     * @return bool|float|int size in bytes, false on failure
1780
     */
1781
    public function inisizeToBytes($strIniSize)
1782
    {
1783
        // This function will take the string value of an ini 'size' parameter,
1784
        // and return a double (64-bit float) representing the number of bytes
1785
        // that the parameter represents. Or false if $strIniSize is unparseable.
1786
        $a_IniParts = [];
1787
1788
        if (!is_string($strIniSize)) {
1789
            return false;
1790
        }
1791
1792
        if (!preg_match('/^(\d+)([bkm]*)$/i', $strIniSize, $a_IniParts)) {
1793
            return false;
1794
        }
1795
1796
        $nSize   = (float) $a_IniParts[1];
1797
        $strUnit = strtolower($a_IniParts[2]);
1798
1799
        switch ($strUnit) {
1800
            case 'm':
1801
                return $nSize * (float) 1048576;
1802
            case 'k':
1803
                return $nSize * (float) 1024;
1804
            case 'b':
1805
            default:
1806
                return $nSize;
1807
        }
1808
    }
1809
1810
    public function getRequestVars($subject = '')
1811
    {
1812
        $v = [];
1813
        if (!empty($subject)) {
1814
            $v['subject'] = $subject;
1815
        }
1816
1817
        if ($this->_server_id !== null && $subject != 'root') {
1818
            $v['server'] = $this->_server_id;
1819
            if ($this->_database !== null && $subject != 'server') {
1820
                $v['database'] = $this->_database;
1821
                if (isset($_REQUEST['schema']) && $subject != 'database') {
1822
                    $v['schema'] = $_REQUEST['schema'];
1823
                }
1824
            }
1825
        }
1826
        //$this->prtrace($v);
1827
        return $v;
1828
    }
1829
1830
    public function icon($icon)
1831
    {
1832
        if (is_string($icon)) {
1833
            $path = "/assets/images/themes/{$this->conf['theme']}/{$icon}";
1834
            if (file_exists(\BASE_PATH.$path.'.png')) {
1835
                return SUBFOLDER.$path.'.png';
1836
            }
1837
1838
            if (file_exists(\BASE_PATH.$path.'.gif')) {
1839
                return SUBFOLDER.$path.'.gif';
1840
            }
1841
1842
            if (file_exists(\BASE_PATH.$path.'.ico')) {
1843
                return SUBFOLDER.$path.'.ico';
1844
            }
1845
1846
            $path = "/assets/images/themes/default/{$icon}";
1847
            if (file_exists(\BASE_PATH.$path.'.png')) {
1848
                return SUBFOLDER.$path.'.png';
1849
            }
1850
1851
            if (file_exists(\BASE_PATH.$path.'.gif')) {
1852
                return SUBFOLDER.$path.'.gif';
1853
            }
1854
1855
            if (file_exists(\BASE_PATH.$path.'.ico')) {
1856
                return SUBFOLDER.$path.'.ico';
1857
            }
1858
        } else {
1859
            // Icon from plugins
1860
            $path = "/plugins/{$icon[0]}/images/{$icon[1]}";
1861
            if (file_exists(\BASE_PATH.$path.'.png')) {
1862
                return SUBFOLDER.$path.'.png';
1863
            }
1864
1865
            if (file_exists(\BASE_PATH.$path.'.gif')) {
1866
                return SUBFOLDER.$path.'.gif';
1867
            }
1868
1869
            if (file_exists(\BASE_PATH.$path.'.ico')) {
1870
                return SUBFOLDER.$path.'.ico';
1871
            }
1872
        }
1873
1874
        return '';
1875
    }
1876
1877
    /**
1878
     * Function to escape command line parameters.
1879
     *
1880
     * @param string $str The string to escape
1881
     *
1882
     * @return string The escaped string
1883
     */
1884
    public function escapeShellArg($str)
1885
    {
1886
        //$data = $this->getDatabaseAccessor();
1887
        $lang = $this->lang;
1888
1889
        if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
1890
            // Due to annoying PHP bugs, shell arguments cannot be escaped
1891
            // (command simply fails), so we cannot allow complex objects
1892
            // to be dumped.
1893
            if (preg_match('/^[_.[:alnum:]]+$/', $str)) {
1894
                return $str;
1895
            }
1896
1897
            return $this->halt($lang['strcannotdumponwindows']);
1898
        }
1899
1900
        return escapeshellarg($str);
1901
    }
1902
1903
    /**
1904
     * Function to escape command line programs.
1905
     *
1906
     * @param string $str The string to escape
1907
     *
1908
     * @return string The escaped string
1909
     */
1910
    public function escapeShellCmd($str)
1911
    {
1912
        $data = $this->getDatabaseAccessor();
1913
1914
        if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
1915
            $data->fieldClean($str);
1916
1917
            return '"'.$str.'"';
1918
        }
1919
1920
        return escapeshellcmd($str);
1921
    }
1922
1923
    /**
1924
     * Save the given SQL script in the history
1925
     * of the database and server.
1926
     *
1927
     * @param string $script the SQL script to save
1928
     */
1929
    public function saveScriptHistory($script)
1930
    {
1931
        list($usec, $sec)                                                           = explode(' ', microtime());
1932
        $time                                                                       = ((float) $usec + (float) $sec);
1933
        $_SESSION['history'][$_REQUEST['server']][$_REQUEST['database']]["${time}"] = [
1934
            'query'    => $script,
1935
            'paginate' => !isset($_REQUEST['paginate']) ? 'f' : 't',
1936
            'queryid'  => $time,
1937
        ];
1938
    }
1939
1940
    /**
1941
     * Returns an array representing FKs definition for a table, sorted by fields
1942
     * or by constraint.
1943
     *
1944
     * @param string $table The table to retrieve FK contraints from
1945
     *
1946
     * @return array|bool the array of FK definition:
1947
     *                    array(
1948
     *                    'byconstr' => array(
1949
     *                    constrain id => array(
1950
     *                    confrelid => foreign relation oid
1951
     *                    f_schema => foreign schema name
1952
     *                    f_table => foreign table name
1953
     *                    pattnums => array of parent's fields nums
1954
     *                    pattnames => array of parent's fields names
1955
     *                    fattnames => array of foreign attributes names
1956
     *                    )
1957
     *                    ),
1958
     *                    'byfield' => array(
1959
     *                    attribute num => array (constraint id, ...)
1960
     *                    ),
1961
     *                    'code' => HTML/js code to include in the page for auto-completion
1962
     *                    )
1963
     */
1964
    public function getAutocompleteFKProperties($table)
1965
    {
1966
        $data = $this->getDatabaseAccessor();
1967
1968
        $fksprops = [
1969
            'byconstr' => [],
1970
            'byfield'  => [],
1971
            'code'     => '',
1972
        ];
1973
1974
        $constrs = $data->getConstraintsWithFields($table);
1975
1976
        if (!$constrs->EOF) {
1977
            //$conrelid = $constrs->fields['conrelid'];
1978
            while (!$constrs->EOF) {
1979
                if ($constrs->fields['contype'] == 'f') {
1980
                    if (!isset($fksprops['byconstr'][$constrs->fields['conid']])) {
1981
                        $fksprops['byconstr'][$constrs->fields['conid']] = [
1982
                            'confrelid' => $constrs->fields['confrelid'],
1983
                            'f_table'   => $constrs->fields['f_table'],
1984
                            'f_schema'  => $constrs->fields['f_schema'],
1985
                            'pattnums'  => [],
1986
                            'pattnames' => [],
1987
                            'fattnames' => [],
1988
                        ];
1989
                    }
1990
1991
                    $fksprops['byconstr'][$constrs->fields['conid']]['pattnums'][]  = $constrs->fields['p_attnum'];
1992
                    $fksprops['byconstr'][$constrs->fields['conid']]['pattnames'][] = $constrs->fields['p_field'];
1993
                    $fksprops['byconstr'][$constrs->fields['conid']]['fattnames'][] = $constrs->fields['f_field'];
1994
1995
                    if (!isset($fksprops['byfield'][$constrs->fields['p_attnum']])) {
1996
                        $fksprops['byfield'][$constrs->fields['p_attnum']] = [];
1997
                    }
1998
1999
                    $fksprops['byfield'][$constrs->fields['p_attnum']][] = $constrs->fields['conid'];
2000
                }
2001
                $constrs->moveNext();
2002
            }
2003
2004
            $fksprops['code'] = "<script type=\"text/javascript\">\n";
2005
            $fksprops['code'] .= "var constrs = {};\n";
2006
            foreach ($fksprops['byconstr'] as $conid => $props) {
2007
                $fksprops['code'] .= "constrs.constr_{$conid} = {\n";
2008
                $fksprops['code'] .= 'pattnums: ['.implode(',', $props['pattnums'])."],\n";
2009
                $fksprops['code'] .= "f_table:'".addslashes(htmlentities($props['f_table'], ENT_QUOTES, 'UTF-8'))."',\n";
2010
                $fksprops['code'] .= "f_schema:'".addslashes(htmlentities($props['f_schema'], ENT_QUOTES, 'UTF-8'))."',\n";
2011
                $_ = '';
2012
                foreach ($props['pattnames'] as $n) {
2013
                    $_ .= ",'".htmlentities($n, ENT_QUOTES, 'UTF-8')."'";
2014
                }
2015
                $fksprops['code'] .= 'pattnames: ['.substr($_, 1)."],\n";
2016
2017
                $_ = '';
2018
                foreach ($props['fattnames'] as $n) {
2019
                    $_ .= ",'".htmlentities($n, ENT_QUOTES, 'UTF-8')."'";
2020
                }
2021
2022
                $fksprops['code'] .= 'fattnames: ['.substr($_, 1)."]\n";
2023
                $fksprops['code'] .= "};\n";
2024
            }
2025
2026
            $fksprops['code'] .= "var attrs = {};\n";
2027
            foreach ($fksprops['byfield'] as $attnum => $cstrs) {
2028
                $fksprops['code'] .= "attrs.attr_{$attnum} = [".implode(',', $fksprops['byfield'][$attnum])."];\n";
2029
            }
2030
2031
            $fksprops['code'] .= "var table='".addslashes(htmlentities($table, ENT_QUOTES, 'UTF-8'))."';";
2032
            $fksprops['code'] .= "var server='".htmlentities($_REQUEST['server'], ENT_QUOTES, 'UTF-8')."';";
2033
            $fksprops['code'] .= "var database='".addslashes(htmlentities($_REQUEST['database'], ENT_QUOTES, 'UTF-8'))."';";
2034
            $fksprops['code'] .= "var subfolder='".SUBFOLDER."';";
2035
            $fksprops['code'] .= "</script>\n";
2036
2037
            $fksprops['code'] .= '<div id="fkbg"></div>';
2038
            $fksprops['code'] .= '<div id="fklist"></div>';
2039
            $fksprops['code'] .= '<script src="'.SUBFOLDER.'/assets/js/ac_insert_row.js" type="text/javascript"></script>';
2040
        } else {
2041
            /* we have no foreign keys on this table */
2042
            return false;
2043
        }
2044
2045
        return $fksprops;
2046
    }
2047
}
2048