Cancelled
Pull Request — develop (#267)
by Felipe
06:23
created

Misc::getContainer()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 3
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
1
<?php
2
3
/**
4
 * PHPPgAdmin v6.0.0-RC9
5
 */
6
7
namespace PHPPgAdmin;
8
9
/**
10
 * @file
11
 * Class to hold various commonly used functions
12
 *
13
 * Id: Misc.php,v 1.171 2008/03/17 21:35:48 ioguix Exp $
14
 */
15
16
/**
17
 * Class to hold various commonly used functions.
18
 *
19
 * Release: Misc.php,v 1.171 2008/03/17 21:35:48 ioguix Exp $
20
 */
21
class Misc
22
{
23
    use \PHPPgAdmin\Traits\HelperTrait;
24
    use \PHPPgAdmin\Traits\MiscTrait;
25
26
    /**
27
     * @var string
28
     */
29
    const BASE_PATH = ContainerUtils::BASE_PATH;
30
    /**
31
     * @var string
32
     */
33
    const SUBFOLDER = ContainerUtils::SUBFOLDER;
34
    /**
35
     * @var string
36
     */
37
    const DEBUGMODE = ContainerUtils::DEBUGMODE;
38
39
    public $appLangFiles = [];
40
41
    public $appName = '';
42
43
    public $appVersion = '';
44
45
    public $form = '';
46
47
    public $href = '';
48
49
    public $lang = [];
50
51
    public $conf;
52
53
    public $phpMinVer;
54
55
    public $postgresqlMinVer;
56
57
    public $view;
58
59
    protected $container;
60
61
    private $_connection;
62
63
    private $_no_db_connection = false;
64
65
    private $_reload_browser = false;
66
67
    private $_data;
68
69
    private $_database;
70
71
    private $_server_id;
72
73
    private $_server_info;
74
75
    private $_error_msg = '';
76
77
    /**
78
     * @param \Slim\Container $container The container
79
     */
80
    public function __construct(\Slim\Container $container)
81
    {
82
        $this->container = $container;
83
84
        $this->lang = $container->get('lang');
85
        $this->conf = $container->get('conf');
86
87
        //$this->view           = $container->get('view');
88
89
        $this->appLangFiles = $container->get('appLangFiles');
90
91
        $this->appName          = $container->get('settings')['appName'];
92
        $this->appVersion       = $container->get('settings')['appVersion'];
93
        $this->postgresqlMinVer = $container->get('settings')['postgresqlMinVer'];
94
        $this->phpMinVer        = $container->get('settings')['phpMinVer'];
95
96
        $base_version = $container->get('settings')['base_version'];
97
98
        // Check for config file version mismatch
99
        if (!isset($this->conf['version']) || $base_version > $this->conf['version']) {
100
            $container->get('utils')->addError($this->lang['strbadconfig']);
101
        }
102
103
        // Check database support is properly compiled in
104
        if (!\function_exists('pg_connect')) {
105
            $container->get('utils')->addError($this->lang['strnotloaded']);
106
        }
107
108
        // Check the version of PHP
109
        if (\version_compare(\PHP_VERSION, $this->phpMinVer, '<')) {
110
            $container->get('utils')->addError(\sprintf('Version of PHP not supported. Please upgrade to version %s or later.', $this->phpMinVer));
111
        }
112
        //$this->dumpAndDie($this);
113
114
        $this->getServerId();
115
    }
116
117
    /**
118
     * Gets the value of a config property, or the array of all config properties.
119
     *
120
     * @param null|string $key value of the key to be retrieved. If null, the full array is returnes
121
     *
122
     * @return null|array|string the whole $conf array, the value of $conf[key] or null if said key does not exist
123
     */
124
    public function getConf($key = null)
125
    {
126
        if (null === $key) {
127
            return $this->conf;
128
        }
129
130
        if (\array_key_exists($key, $this->conf)) {
131
            return $this->conf[$key];
132
        }
133
134
        return null;
135
    }
136
137
    /**
138
     * Adds or modifies a key in the $conf instance property of this class.
139
     *
140
     * @param string $key   name of the key to set
141
     * @param mixed  $value value of the key to set
142
     *
143
     * @return \PHPPgAdmin\Misc this class instance
144
     */
145
    public function setConf($key, $value)
146
    {
147
        $this->conf[$key] = $value;
148
149
        return $this;
150
    }
151
152
    public function serverToSha()
153
    {
154
        $request_server = $this->container->requestobj->getParam('server');
155
156
        if (null === $request_server) {
157
            return null;
158
        }
159
        $srv_array = \explode(':', $request_server);
160
161
        if (3 === \count($srv_array)) {
162
            return \sha1($request_server);
163
        }
164
165
        return $request_server;
166
    }
167
168
    public function getServerId()
169
    {
170
        if ($this->_server_id) {
171
            return $this->_server_id;
172
        }
173
174
        $request_server = $this->serverToSha();
175
176
        if (1 === \count($this->conf['servers'])) {
177
            $info             = $this->conf['servers'][0];
178
            $this->_server_id = \sha1($info['host'] . ':' . $info['port'] . ':' . $info['sslmode']);
179
        } elseif (null !== $request_server) {
180
            $this->_server_id = $request_server;
181
        } elseif (isset($_SESSION['webdbLogin']) && 0 < \count($_SESSION['webdbLogin'])) {
182
            $this->_server_id = \array_keys($_SESSION['webdbLogin'])[0];
183
        }
184
185
        return $this->_server_id;
186
    }
187
188
    /**
189
     * Sets the view instance property of this class.
190
     *
191
     * @param \Slim\Views\Twig $view view instance
192
     *
193
     * @return \PHPPgAdmin\Misc this class instance
194
     */
195
    public function setView(\Slim\Views\Twig $view)
196
    {
197
        $this->view = $view;
198
199
        return $this;
200
    }
201
202
    /**
203
     * Internally sets the reload browser property.
204
     *
205
     * @param bool $flag sets internal $_reload_browser var which will be passed to the footer methods
206
     *
207
     * @return \PHPPgAdmin\Misc this class instance
208
     */
209
    public function setReloadBrowser($flag)
210
    {
211
        $this->_reload_browser = (bool) $flag;
212
213
        return $this;
214
    }
215
216
    public function getReloadBrowser()
217
    {
218
        return $this->_reload_browser;
219
    }
220
221
    public function getContainer()
222
    {
223
        return $this->container;
224
    }
225
226
    /**
227
     * Sets $_no_db_connection boolean value, allows to render scripts that do not need an active session.
228
     *
229
     * @param bool $flag true or false to allow unconnected clients to access the view
230
     *
231
     * @return \PHPPgAdmin\Misc this class instance
232
     */
233
    public function setNoDBConnection($flag)
234
    {
235
        $this->_no_db_connection = (bool) $flag;
236
237
        return $this;
238
    }
239
240
    /**
241
     * Gets member variable $_no_db_connection.
242
     *
243
     * @return bool value of member variable $_no_db_connection
244
     */
245
    public function getNoDBConnection()
246
    {
247
        return $this->_no_db_connection;
248
    }
249
250
    /**
251
     * Sets the last error message to display afterwards instead of just dying with the error msg.
252
     *
253
     * @param string $msg error message string
254
     *
255
     * @return \PHPPgAdmin\Misc this class instance
256
     */
257
    public function setErrorMsg($msg)
258
    {
259
        $this->_error_msg = $msg;
260
261
        return $this;
262
    }
263
264
    /**
265
     * Returns the error messages stored in member variable $_error_msg.
266
     *
267
     * @return string the error message
268
     */
269
    public function getErrorMsg()
270
    {
271
        return $this->_error_msg;
272
    }
273
274
    /**
275
     * Creates a database accessor.
276
     *
277
     * @param string $database  the name of the database
278
     * @param mixed  $server_id the id of the server
279
     *
280
     * @internal mixed $plaform placeholder that will receive the value of the platform
281
     *
282
     * @return null|\PHPPgAdmin\Database\ADOdbBase the database accessor instance
283
     */
284
    public function getDatabaseAccessor($database = '', $server_id = null):  ? \PHPPgAdmin\Database\ADOdbBase
285
    {
286
        $lang = $this->lang;
287
288
        if (null !== $server_id) {
289
            $this->_server_id = $server_id;
290
        }
291
292
        $server_info = $this->getServerInfo($this->_server_id);
293
294
        if ($this->_no_db_connection || !isset($server_info['username'])) {
295
            return null;
296
        }
297
298
        if (null === $this->_data) {
299
            try {
300
                $_connection = $this->getConnection($database, $this->_server_id);
301
            } catch (\Exception $e) {
302
                $this->setServerInfo(null, null, $this->_server_id);
303
                $this->setNoDBConnection(true);
304
                $this->setErrorMsg($e->getMessage());
305
306
                return null;
307
            }
308
309
            if (!$_connection) {
310
                $this->container->utils->addError($lang['strloginfailed']);
311
                $this->setErrorMsg($lang['strloginfailed']);
312
313
                return null;
314
            }
315
            $platform = '';
316
            // Get the name of the database driver we need to use.
317
            // The description of the server is returned in $platform.
318
            $_type = $_connection->getDriver($platform);
319
320
            if (null === $_type) {
321
                $errormsg = \sprintf($lang['strpostgresqlversionnotsupported'], $this->postgresqlMinVer);
322
                $this->container->utils->addError($errormsg);
323
                $this->setErrorMsg($errormsg);
324
325
                return null;
326
            }
327
            $_type = '\PHPPgAdmin\Database\\' . $_type;
328
329
            $this->setServerInfo('platform', $platform, $this->_server_id);
330
            $this->setServerInfo('pgVersion', $_connection->conn->pgVersion, $this->_server_id);
331
332
            // Create a database wrapper class for easy manipulation of the
333
            // connection.
334
335
            $this->_data           = new $_type($_connection->conn, $this->container, $server_info);
336
            $this->_data->platform = $_connection->platform;
337
338
            //$this->_data->getHelpPages();
339
340
            /* we work on UTF-8 only encoding */
341
            $this->_data->execute("SET client_encoding TO 'UTF-8'");
342
343
            if ($this->_data->hasByteaHexDefault()) {
344
                $this->_data->execute('SET bytea_output TO escape');
345
            }
346
        }
347
348
        if (false === $this->_no_db_connection &&
349
            null !== $this->getDatabase() &&
350
            isset($_REQUEST['schema'])
351
        ) {
352
            $status = $this->_data->setSchema($_REQUEST['schema']);
353
354
            if (0 !== $status) {
355
                $this->container->utils->addError($this->lang['strbadschema']);
356
                $this->setErrorMsg($this->lang['strbadschema']);
357
358
                return null;
359
            }
360
        }
361
362
        return $this->_data;
363
    }
364
365
    public function getConnection(string $database = '', $server_id = null)
366
    {
367
        $lang = $this->lang;
368
369
        if (null === $this->_connection) {
370
            if (null !== $server_id) {
371
                $this->_server_id = $server_id;
372
            }
373
            $server_info     = $this->getServerInfo($this->_server_id);
374
            $database_to_use = $this->getDatabase($database);
375
376
            // Perform extra security checks if this config option is set
377
            if ($this->conf['extra_login_security']) {
378
                // Disallowed logins if extra_login_security is enabled.
379
                // These must be lowercase.
380
                $bad_usernames = [
381
                    'pgsql'         => 'pgsql',
382
                    'postgres'      => 'postgres',
383
                    'root'          => 'root',
384
                    'administrator' => 'administrator',
385
                ];
386
387
                if (isset($server_info['username']) &&
388
                    \array_key_exists(\mb_strtolower($server_info['username']), $bad_usernames)
389
                ) {
390
                    $msg = $lang['strlogindisallowed'];
391
392
                    throw new \Exception($msg);
393
                }
394
395
                if (!isset($server_info['password']) ||
396
                    '' === $server_info['password']
397
                ) {
398
                    $msg = $lang['strlogindisallowed'];
399
400
                    throw new \Exception($msg);
401
                }
402
            }
403
404
            try {
405
                // Create the connection object and make the connection
406
                $this->_connection = new \PHPPgAdmin\Database\Connection(
407
                    $server_info,
408
                    $database_to_use,
409
                    $this->container
410
                );
411
            } catch (\PHPPgAdmin\ADOdbException $e) {
412
                throw new \Exception($lang['strloginfailed']);
413
            }
414
        }
415
416
        return $this->_connection;
417
    }
418
419
    /**
420
     * Validate and retrieve information on a server. If the parameter isn't supplied then the currently connected
421
     * server is returned.
422
     *
423
     * @param string $server_id A server identifier (host:port)
424
     *
425
     * @return null|array An associative array of server properties
426
     */
427
    public function getServerInfo($server_id = null)
428
    {
429
        if (null !== $server_id) {
430
            $this->_server_id = $server_id;
431
        } elseif (null !== $this->_server_info) {
432
            return $this->_server_info;
433
        }
434
435
        // Check for the server in the logged-in list
436
        if (isset($_SESSION['webdbLogin'][$this->_server_id])) {
437
            $this->_server_info = $_SESSION['webdbLogin'][$this->_server_id];
438
439
            return $this->_server_info;
440
        }
441
442
        // Otherwise, look for it in the conf file
443
        foreach ($this->conf['servers'] as $idx => $info) {
444
            $server_string = $info['host'] . ':' . $info['port'] . ':' . $info['sslmode'];
445
            $server_sha    = \sha1($server_string);
446
447
            if ($this->_server_id === $server_string ||
448
                $this->_server_id === $server_sha
449
            ) {
450
                if (isset($info['username'])) {
451
                    $this->setServerInfo(null, $info, $this->_server_id);
452
                } elseif (isset($_SESSION['sharedUsername'])) {
453
                    $info['username'] = $_SESSION['sharedUsername'];
454
                    $info['password'] = $_SESSION['sharedPassword'];
455
                    $this->setReloadBrowser(true);
456
                    $this->setServerInfo(null, $info, $this->_server_id);
457
                }
458
                $this->_server_info = $info;
459
460
                return $this->_server_info;
461
            }
462
        }
463
464
        if (null === $server_id) {
465
            $this->_server_info = null;
466
467
            return $this->_server_info;
468
        }
469
470
//      //$this->prtrace('Invalid server param');
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected at least 8 spaces, found 0
Loading history...
471
        $this->_server_info = null;
472
        // Unable to find a matching server, are we being hacked?
473
        $this->halt($this->lang['strinvalidserverparam']);
474
475
        return $this->_server_info;
476
    }
477
478
    /**
479
     * Set server information.
480
     *
481
     * @param null|string $key       parameter name to set, or null to replace all
482
     *                               params with the assoc-array in $value
483
     * @param mixed       $value     the new value, or null to unset the parameter
484
     * @param null|string $server_id the server identifier, or null for current server
485
     */
486
    public function setServerInfo($key, $value, $server_id = null) : void
487
    {
488
        if (null === $server_id) {
489
            $server_id = $this->container->requestobj->getParam('server');
490
        }
491
492
        if (null === $key) {
493
            if (null === $value) {
494
                unset($_SESSION['webdbLogin'][$server_id]);
495
            } else {
496
                $_SESSION['webdbLogin'][$server_id] = $value;
497
            }
498
        } else {
499
            if (null === $value) {
500
                unset($_SESSION['webdbLogin'][$server_id][$key]);
501
            } else {
502
                $_SESSION['webdbLogin'][$server_id][$key] = $value;
503
            }
504
        }
505
    }
506
507
    public function getDatabase(string $database = '')
508
    {
509
        if (null === $this->_server_id && !isset($_REQUEST['database'])) {
510
            return null;
511
        }
512
513
        $server_info = $this->getServerInfo($this->_server_id);
514
515
        if (null !== $this->_server_id &&
516
            isset($server_info['useonlydefaultdb']) &&
517
            true === $server_info['useonlydefaultdb'] &&
518
            isset($server_info['defaultdb'])
519
        ) {
520
            $this->_database = $server_info['defaultdb'];
521
        } elseif ('' !== $database) {
522
            $this->_database = $database;
523
        } elseif (isset($_REQUEST['database'])) {
524
            // Connect to the current database
525
            $this->_database = $_REQUEST['database'];
526
        } elseif (isset($server_info['defaultdb'])) {
527
            // or if one is not specified then connect to the default database.
528
            $this->_database = $server_info['defaultdb'];
529
        } else {
530
            return null;
531
        }
532
533
        return $this->_database;
534
    }
535
536
    /**
537
     * Set the current schema.
538
     *
539
     * @param string $schema The schema name
540
     *
541
     * @return int 0 on success
542
     */
543
    public function setCurrentSchema($schema)
544
    {
545
        $data = $this->getDatabaseAccessor();
546
547
        $status = $data->setSchema($schema);
0 ignored issues
show
introduced by
The method setSchema() does not exist on PHPPgAdmin\Database\ADOdbBase. Maybe you want to declare this class abstract? ( Ignorable by Annotation )

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

547
        /** @scrutinizer ignore-call */ 
548
        $status = $data->setSchema($schema);
Loading history...
548
549
        if (0 !== $status) {
550
            return $status;
551
        }
552
553
        $_REQUEST['schema'] = $schema;
554
        $this->container->offsetSet('schema', $schema);
555
        $this->setHREF();
556
557
        return 0;
558
    }
559
560
    /**
561
     * Checks if dumps are properly set up.
562
     *
563
     * @param bool $all (optional) True to check pg_dumpall, false to just check pg_dump
564
     *
565
     * @return bool True, dumps are set up, false otherwise
566
     */
567
    public function isDumpEnabled($all = false)
568
    {
569
        $info = $this->getServerInfo();
570
571
        return !empty($info[$all ? 'pg_dumpall_path' : 'pg_dump_path']);
572
    }
573
574
    /**
575
     * Sets the href tracking variable.
576
     *
577
     * @return \PHPPgAdmin\Misc this class instance
578
     */
579
    public function setHREF()
580
    {
581
        $this->href = $this->getHREF();
582
583
        return $this;
584
    }
585
586
    /**
587
     * Get a href query string, excluding objects below the given object type (inclusive).
588
     *
589
     * @param null|string $exclude_from
590
     *
591
     * @return string
592
     */
593
    public function getHREF($exclude_from = null)
594
    {
595
        $href = [];
596
597
        $server   = $this->container->server || isset($_REQUEST['server']) ? $_REQUEST['server'] : null;
598
        $database = $this->container->database || isset($_REQUEST['database']) ? $_REQUEST['database'] : null;
599
        $schema   = $this->container->schema || isset($_REQUEST['schema']) ? $_REQUEST['schema'] : null;
600
601
        if ($server && 'server' !== $exclude_from) {
602
            $href[] = 'server=' . \urlencode($server);
603
        }
604
605
        if ($database && 'database' !== $exclude_from) {
606
            $href[] = 'database=' . \urlencode($database);
607
        }
608
609
        if ($schema && 'schema' !== $exclude_from) {
610
            $href[] = 'schema=' . \urlencode($schema);
611
        }
612
613
        $this->href = \htmlentities(\implode('&', $href));
614
615
        return $this->href;
616
    }
617
618
    /**
619
     * A function to recursively strip slashes.  Used to
620
     * enforce magic_quotes_gpc being off.
621
     *
622
     * @param mixed $var The variable to strip (passed by reference)
623
     */
624
    public function stripVar(&$var): void
625
    {
626
        if (\is_array($var)) {
627
            foreach ($var as $k => $v) {
628
                $this->stripVar($var[$k]);
629
630
                /* magic_quotes_gpc escape keys as well ...*/
631
                if (\is_string($k)) {
632
                    $ek = \stripslashes($k);
633
634
                    if ($ek !== $k) {
635
                        $var[$ek] = $var[$k];
636
                        unset($var[$k]);
637
                    }
638
                }
639
            }
640
        } else {
641
            $var = \stripslashes($var);
642
        }
643
    }
644
645
    /**
646
     * Converts a PHP.INI size variable to bytes.  Taken from publically available
647
     * function by Chris DeRose, here: http://www.php.net/manual/en/configuration.directives.php#ini.file-uploads.
648
     *
649
     * @param mixed $strIniSize The PHP.INI variable
650
     *
651
     * @return bool|float|int size in bytes, false on failure
652
     */
653
    public function inisizeToBytes($strIniSize)
654
    {
655
        // This function will take the string value of an ini 'size' parameter,
656
        // and return a double (64-bit float) representing the number of bytes
657
        // that the parameter represents. Or false if $strIniSize is unparseable.
658
        $a_IniParts = [];
659
660
        if (!\is_string($strIniSize)) {
661
            return false;
662
        }
663
664
        if (!\preg_match('/^(\d+)([bkm]*)$/i', $strIniSize, $a_IniParts)) {
665
            return false;
666
        }
667
668
        $nSize   = (float) $a_IniParts[1];
669
        $strUnit = \mb_strtolower($a_IniParts[2]);
670
671
        switch ($strUnit) {
672
            case 'm':
673
                return $nSize * (float) 1048576;
674
            case 'k':
675
                return $nSize * (float) 1024;
676
            case 'b':
677
            default:
678
                return $nSize;
679
        }
680
    }
681
682
    public function getRequestVars($subject = '')
683
    {
684
        $v = [];
685
686
        if (!empty($subject)) {
687
            $v['subject'] = $subject;
688
        }
689
690
        if (null !== $this->_server_id && 'root' !== $subject) {
691
            $v['server'] = $this->_server_id;
692
693
            if (null !== $this->_database && 'server' !== $subject) {
694
                $v['database'] = $this->_database;
695
696
                if (isset($_REQUEST['schema']) && 'database' !== $subject) {
697
                    $v['schema'] = $_REQUEST['schema'];
698
                }
699
            }
700
        }
701
702
        return $v;
703
    }
704
705
    /**
706
     * Function to escape command line parameters.
707
     *
708
     * @param string $str The string to escape
709
     *
710
     * @return null|string The escaped string
711
     */
712
    public function escapeShellArg($str):  ? string
713
    {
714
        //$data = $this->getDatabaseAccessor();
715
        $lang = $this->lang;
716
717
        if ('WIN' === \mb_strtoupper(\mb_substr(\PHP_OS, 0, 3))) {
718
            // Due to annoying PHP bugs, shell arguments cannot be escaped
719
            // (command simply fails), so we cannot allow complex objects
720
            // to be dumped.
721
            if (\preg_match('/^[_.[:alnum:]]+$/', $str)) {
722
                return $str;
723
            }
724
725
            return $this->halt($lang['strcannotdumponwindows']);
726
        }
727
728
        return \escapeshellarg($str);
729
    }
730
731
    /**
732
     * Function to escape command line programs.
733
     *
734
     * @param string $str The string to escape
735
     *
736
     * @return string The escaped string
737
     */
738
    public function escapeShellCmd($str)
739
    {
740
        $data = $this->getDatabaseAccessor();
741
742
        if ('WIN' === \mb_strtoupper(\mb_substr(\PHP_OS, 0, 3))) {
743
            $data->fieldClean($str);
744
745
            return '"' . $str . '"';
746
        }
747
748
        return \escapeshellcmd($str);
749
    }
750
751
    /**
752
     * Save the given SQL script in the history
753
     * of the database and server.
754
     *
755
     * @param string $script the SQL script to save
756
     */
757
    public function saveScriptHistory($script) : void
758
    {
759
        [$usec, $sec] = \explode(' ', \microtime());
760
        $time         = ((float) $usec + (float) $sec);
761
762
        $server   = $this->container->server ? $this->container->server : $_REQUEST['server'];
763
        $database = $this->container->database ? $this->container->database : $_REQUEST['database'];
764
765
        $_SESSION['history'][$server][$database]["{$time}"] = [
766
            'query'    => $script,
767
            'paginate' => !isset($_REQUEST['paginate']) ? 'f' : 't',
768
            'queryid'  => $time,
769
        ];
770
    }
771
}
772