Completed
Pull Request — develop (#209)
by Felipe
26:08 queued 36s
created

lib.inc.php ➔ maybeRenderIframes()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 17
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 10
nc 3
nop 4
dl 0
loc 17
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * Function library read in upon startup
5
 *
6
 * Release: lib.inc.php,v 1.123 2008/04/06 01:10:35 xzilla Exp $
7
 */
8
9
defined('BASE_PATH') or define('BASE_PATH', dirname(__DIR__));
10
11
define('THEME_PATH', BASE_PATH . '/assets/themes');
12
// Enforce PHP environment
13
ini_set('arg_separator.output', '&amp;');
14
15
if (!is_writable(BASE_PATH . '/temp')) {
16
    die('Your temp folder must have write permissions (use chmod 777 temp -R on linux)');
17
}
18
19
// Check to see if the configuration file exists, if not, explain
20
if (file_exists(BASE_PATH . '/config.inc.php')) {
21
    $conf = [];
22
    include BASE_PATH . '/config.inc.php';
23
} else {
24
    die('Configuration error: Copy config.inc.php-dist to config.inc.php and edit appropriately.');
25
}
26
27
if (isset($conf['error_log'])) {
28
    ini_set('error_log', BASE_PATH . '/' . $conf['error_log']);
29
}
30
31
$debugmode = (!isset($conf['debugmode'])) ? false : boolval($conf['debugmode']);
32
define('DEBUGMODE', $debugmode);
33
34
require_once BASE_PATH . '/vendor/autoload.php';
35
36
if (!defined('ADODB_ERROR_HANDLER_TYPE')) {
37
    define('ADODB_ERROR_HANDLER_TYPE', E_USER_ERROR);
38
}
39
40
if (!defined('ADODB_ERROR_HANDLER')) {
41
    define('ADODB_ERROR_HANDLER', '\PHPPgAdmin\ADOdbException::adodb_throw');
42
}
43
44
// Start session (if not auto-started)
45
if (!ini_get('session.auto_start')) {
46
    session_name('PPA_ID');
47
    session_start();
48
}
49
50
function maybeRenderIframes($c, $response, $subject, $query_string)
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
51
{
52
    $in_test = $c->view->offsetGet('in_test');
53
54
    if ($in_test === '1') {
55
        $className  = '\PHPPgAdmin\Controller\\' . ucfirst($subject) . 'Controller';
56
        $controller = new $className($c);
57
        return $controller->render();
58
    }
59
60
    $viewVars = [
61
        'url'            => '/src/views/' . $subject . ($query_string ? '?' . $query_string : ''),
62
        'headertemplate' => 'header.twig',
63
    ];
64
65
    return $c->view->render($response, 'iframe_view.twig', $viewVars);
66
};
67
68
$handler             = PhpConsole\Handler::getInstance();
69
\Kint::$enabled_mode = DEBUGMODE;
70
ini_set('display_errors', intval(DEBUGMODE));
71
ini_set('display_startup_errors', intval(DEBUGMODE));
72
if (DEBUGMODE) {
73
    error_reporting(E_ALL);
74
}
75
76
if (isset($_SERVER['HTTP_USER_AGENT'])) {
77
    $useragent = $_SERVER['HTTP_USER_AGENT'];
78
    if (strpos($useragent, 'Chrome') === false) {
79
        $conf['php_console'] = false;
80
    }
81
}
82
83
if (!isset($conf['php_console']) || $conf['php_console'] !== true) {
84
    $handler->setHandleErrors(false); // disable errors handling
85
    $handler->setHandleExceptions(false); // disable exceptions handling
86
    $handler->setCallOldHandlers(true); // disable passing errors & exceptions to prviously defined handlers
87
}
88
89
$composerinfo = json_decode(file_get_contents(BASE_PATH . '/composer.json'));
90
$appVersion   = $composerinfo->version;
91
92
$config = [
93
    'msg'       => '',
94
    'appThemes' => [
95
        'default'    => 'Default',
96
        'cappuccino' => 'Cappuccino',
97
        'gotar'      => 'Blue/Green',
98
        'bootstrap'  => 'Bootstrap3',
99
    ],
100
    'settings'  => [
101
        'displayErrorDetails'               => DEBUGMODE,
102
        'determineRouteBeforeAppMiddleware' => true,
103
        'base_path'                         => BASE_PATH,
104
        'debug'                             => DEBUGMODE,
105
106
        'routerCacheFile'                   => BASE_PATH . '/temp/route.cache.php',
107
108
        // Configuration file version.  If this is greater than that in config.inc.php, then
109
        // the app will refuse to run.  This and $conf['version'] should be incremented whenever
110
        // backwards incompatible changes are made to config.inc.php-dist.
111
        'base_version'                      => 60,
112
        // Application version
113
        'appVersion'                        => 'v' . $appVersion,
114
        // Application name
115
        'appName'                           => 'phpPgAdmin6',
116
117
        // PostgreSQL and PHP minimum version
118
        'postgresqlMinVer'                  => '9.3',
119
        'phpMinVer'                         => '5.6',
120
        'displayErrorDetails'               => DEBUGMODE,
121
        'addContentLengthHeader'            => false,
122
    ],
123
];
124
125
$app = new \Slim\App($config);
126
127
// Fetch DI Container
128
$container = $app->getContainer();
129
130
if ($container instanceof \Psr\Container\ContainerInterface) {
131
    \PhpConsole\Helper::register(); // it will register global PC class
132
    if (PHP_SAPI == 'cli-server') {
133
        $subfolder = '/index.php';
134
    } elseif (isset($conf['subfolder']) && is_string($conf['subfolder'])) {
135
        $subfolder = $conf['subfolder'];
136
    } else {
137
        $normalized_php_self = str_replace('/src/views', '', $container->environment->get('PHP_SELF'));
0 ignored issues
show
Bug introduced by
Accessing environment on the interface Psr\Container\ContainerInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
138
        $subfolder           = str_replace('/' . basename($normalized_php_self), '', $normalized_php_self);
139
    }
140
    define('SUBFOLDER', $subfolder);
141
} else {
142
    trigger_error("App Container must be an instance of \Psr\Container\ContainerInterface", E_USER_ERROR);
143
}
144
145
$container['version']     = 'v' . $appVersion;
146
$container['errors']      = [];
147
$container['requestobj']  = $container['request'];
148
$container['responseobj'] = $container['response'];
149
$container['php_console'] = $handler;
150
151
// This should be deprecated once we're sure no php scripts are required directly
152
$container->offsetSet('server', isset($_REQUEST['server']) ? $_REQUEST['server'] : null);
153
$container->offsetSet('database', isset($_REQUEST['database']) ? $_REQUEST['database'] : null);
154
$container->offsetSet('schema', isset($_REQUEST['schema']) ? $_REQUEST['schema'] : null);
155
156
$container['flash'] = function () {
157
    return new \Slim\Flash\Messages();
158
};
159
160
$container['utils'] = function ($c) {
161
    $utils = new \PHPPgAdmin\ContainerUtils($c);
162
    return $utils;
163
};
164
165
$container['conf'] = function ($c) use ($conf) {
0 ignored issues
show
Unused Code introduced by
The parameter $c is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
166
167
    //\Kint::dump($conf);
168
    // Plugins are removed
169
    $conf['plugins'] = [];
170
171
    foreach ($conf['servers'] as &$server) {
172
        if (!isset($server['port'])) {
173
            $server['port'] = 5432;
174
        }
175
        if (!isset($server['sslmode'])) {
176
            $server['sslmode'] = 'unspecified';
177
        }
178
    }
179
    return $conf;
180
};
181
182
$container['lang'] = function ($c) {
183
    $translations = new \PHPPgAdmin\Translations($c);
184
185
    return $translations->lang;
186
};
187
188
$container['plugin_manager'] = function ($c) {
189
    $plugin_manager = new \PHPPgAdmin\PluginManager($c);
190
    return $plugin_manager;
191
};
192
193
$container['serializer'] = function ($c) {
194
    $serializerbuilder = \JMS\Serializer\SerializerBuilder::create();
195
    $serializer        = $serializerbuilder
196
        ->setCacheDir(BASE_PATH . '/temp/jms')
197
        ->setDebug($c->get('settings')['debug'])
198
        ->build();
199
    return $serializer;
200
};
201
202
// Create Misc class references
203
$container['misc'] = function ($c) {
204
    $misc = new \PHPPgAdmin\Misc($c);
205
206
    $conf = $c->get('conf');
207
208
    // 4. Check for theme by server/db/user
209
    $_server_info = $misc->getServerInfo();
210
211
    //\PC::debug($_server_info, 'server info');
212
213
    /* starting with PostgreSQL 9.0, we can set the application name */
214
    if (isset($_server_info['pgVersion']) && $_server_info['pgVersion'] >= 9) {
215
        putenv('PGAPPNAME=' . $c->get('settings')['appName'] . '_' . $c->get('settings')['appVersion']);
216
    }
217
218
    $themefolders = [];
219
    if ($gestor = opendir(THEME_PATH)) {
220
221
        /* This is the right way to iterate on a folder */
222
        while (false !== ($foldername = readdir($gestor))) {
223
            if ($foldername == '.' || $foldername == '..') {
224
                continue;
225
            }
226
227
            $folderpath = THEME_PATH . DIRECTORY_SEPARATOR . $foldername;
228
229
            // if $folderpath if indeed a folder and contains a global.css file, then it's a theme
230
            if (is_dir($folderpath) && is_file($folderpath . DIRECTORY_SEPARATOR . 'global.css')) {
231
                $themefolders[$foldername] = $folderpath;
232
            }
233
        }
234
235
        closedir($gestor);
236
    }
237
238
    //\PC::debug($themefolders, 'themefolders');
239
    /* select the theme */
240
    unset($_theme);
241
242
    // List of themes
243
    if (!isset($conf['theme'])) {
244
        $conf['theme'] = 'default';
245
    }
246
    // 1. Check for the theme from a request var.
247
    // This happens when you use the selector in the intro screen
248
    if (isset($_REQUEST['theme']) && array_key_exists($_REQUEST['theme'], $themefolders)) {
249
        $_theme = $_REQUEST['theme'];
250
    } elseif (!isset($_theme) && isset($_SESSION['ppaTheme']) && array_key_exists($_SESSION['ppaTheme'], $themefolders)) {
0 ignored issues
show
Bug introduced by
The variable $_theme seems only to be defined at a later point. As such the call to isset() seems to always evaluate to false.

This check marks calls to isset(...) or empty(...) that are found before the variable itself is defined. These will always have the same result.

This is likely the result of code being shifted around. Consider removing these calls.

Loading history...
251
        // 2. Check for theme session var
252
        $_theme = $_SESSION['ppaTheme'];
253
    } elseif (!isset($_theme) && isset($_COOKIE['ppaTheme']) && array_key_exists($_COOKIE['ppaTheme'], $themefolders)) {
254
        // 3. Check for theme in cookie var
255
        $_theme = $_COOKIE['ppaTheme'];
256
    }
257
258
    if (!isset($_theme) && !is_null($_server_info) && array_key_exists('theme', $_server_info)) {
259
        $server_theme = $_server_info['theme'];
260
261
        if (isset($server_theme['default']) && array_key_exists($server_theme['default'], $themefolders)) {
262
            $_theme = $server_theme['default'];
263
        }
264
265 View Code Duplication
        if (isset($_REQUEST['database'])
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
266
            && isset($server_theme['db'][$_REQUEST['database']])
267
            && array_key_exists($server_theme['db'][$_REQUEST['database']], $themefolders)
268
        ) {
269
            $_theme = $server_theme['db'][$_REQUEST['database']];
270
        }
271
272 View Code Duplication
        if (isset($_server_info['username'])
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
273
            && isset($server_theme['user'][$_server_info['username']])
274
            && array_key_exists($server_theme['user'][$_server_info['username']], $themefolders)
275
        ) {
276
            $_theme = $server_theme['user'][$_server_info['username']];
277
        }
278
    }
279
    // if any of the above conditions had set the $_theme variable
280
    // then we store it in the session and a cookie
281
    // and we overwrite $conf['theme'] with its value
282
    if (isset($_theme)) {
283
        /* save the selected theme in cookie for a year */
284
        setcookie('ppaTheme', $_theme, time() + 31536000, '/');
285
        $_SESSION['ppaTheme'] = $_theme;
286
        $conf['theme']        = $_theme;
287
    }
288
289
    $misc->setConf('theme', $conf['theme']);
290
291
    return $misc;
292
};
293
294
// Register Twig View helper
295
$container['view'] = function ($c) {
296
    $conf = $c->get('conf');
0 ignored issues
show
Unused Code introduced by
$conf is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
297
    $misc = $c->misc;
298
299
    $view = new \Slim\Views\Twig(BASE_PATH . '/assets/templates', [
300
        'cache'       => BASE_PATH . '/temp/twigcache',
301
        'auto_reload' => $c->get('settings')['debug'],
302
        'debug'       => $c->get('settings')['debug'],
303
    ]);
304
    $environment              = $c->get('environment');
305
    $base_script_trailing_str = substr($environment['SCRIPT_NAME'], 1);
306
    $request_basepath         = $c['request']->getUri()->getBasePath();
307
    // Instantiate and add Slim specific extension
308
    $basePath = rtrim(str_ireplace($base_script_trailing_str, '', $request_basepath), '/');
309
310
    $view->addExtension(new Slim\Views\TwigExtension($c['router'], $basePath));
311
312
    $view->offsetSet('subfolder', SUBFOLDER);
313
    $view->offsetSet('theme', $c->misc->getConf('theme'));
314
    $view->offsetSet('Favicon', $c->misc->icon('Favicon'));
315
    $view->offsetSet('Introduction', $c->misc->icon('Introduction'));
316
    $view->offsetSet('lang', $c->lang);
317
318
    $view->offsetSet('applangdir', $c->lang['applangdir']);
319
320
    $view->offsetSet('appName', $c->get('settings')['appName']);
321
322
    $misc->setView($view);
323
324
    //\PC::debug($c->conf, 'conf');
325
    //\PC::debug($c->view->offsetGet('subfolder'), 'subfolder');
326
    //\PC::debug($c->view->offsetGet('theme'), 'theme');
327
328
    return $view;
329
};
330
331
$container['haltHandler'] = function ($c) {
332
    return function ($request, $response, $exits, $status = 500) use ($c) {
333
        $title = 'PHPPgAdmin Error';
334
335
        $html = '<p>The application could not run because of the following error:</p>';
336
337
        $output = sprintf(
338
            "<html><head><meta http-equiv='Content-Type' content='text/html; charset=utf-8'>" .
339
            '<title>%s</title><style>' .
340
            'body{margin:0;padding:30px;font:12px/1.5 Helvetica,Arial,Verdana,sans-serif;}' .
341
            'h3{margin:0;font-size:28px;font-weight:normal;line-height:30px;}' .
342
            'span{display:inline-block;font-size:16px;}' .
343
            '</style></head><body><h3>%s</h3><p>%s</p><span>%s</span></body></html>',
344
            $title,
345
            $title,
346
            $html,
347
            implode('<br>', $exits)
348
        );
349
350
        $body = $response->getBody(); //new \Slim\Http\Body(fopen('php://temp', 'r+'));
351
        $body->write($output);
352
353
        return $response
354
            ->withStatus($status)
355
            ->withHeader('Content-type', 'text/html')
356
            ->withBody($body);
357
    };
358
};
359
360
// Set the requestobj and responseobj properties of the container
361
// as the value of $request and $response, which already contain the route
362
$app->add(
363
    function ($request, $response, $next) use ($handler) {
364
        $handler->start(); // initialize handlers*/
365
366
        $this['requestobj']  = $request;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$this was never initialized. Although not strictly required by PHP, it is generally a good practice to add $this = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
367
        $this['responseobj'] = $response;
368
369
        $this['server']   = $request->getParam('server');
370
        $this['database'] = $request->getParam('database');
371
        $this['schema']   = $request->getParam('schema');
372
        $misc             = $this->get('misc');
373
374
        $misc->setHREF();
375
        $misc->setForm();
376
377
        $this->view->offsetSet('METHOD', $request->getMethod());
378
        if ($request->getAttribute('route')) {
379
            $this->view->offsetSet('subject', $request->getAttribute('route')->getArgument('subject'));
380
        }
381
382
        $query_string = $request->getUri()->getQuery();
383
        $this->view->offsetSet('query_string', $query_string);
384
        $path = (SUBFOLDER ? (SUBFOLDER . '/') : '') . $request->getUri()->getPath() . ($query_string ? '?' . $query_string : '');
385
        $this->view->offsetSet('path', $path);
386
387
        $params = $request->getParams();
388
389
        $viewparams = [];
390
391
        foreach ($params as $key => $value) {
392
            if (is_scalar($value)) {
393
                $viewparams[$key] = $value;
394
            }
395
        }
396
397
        if (isset($_COOKIE['IN_TEST'])) {
398
            $in_test = (string) $_COOKIE['IN_TEST'];
399
        } else {
400
            $in_test = '0';
401
        }
402
403
        // remove tabs and linebreaks from query
404
        if (isset($params['query'])) {
405
            $viewparams['query'] = str_replace(["\r", "\n", "\t"], ' ', $params['query']);
406
        }
407
        $this->view->offsetSet('params', $viewparams);
408
        $this->view->offsetSet('in_test', $in_test);
409
410
        if (count($this['errors']) > 0) {
411
            return ($this->haltHandler)($this->requestobj, $this->responseobj, $this['errors'], 412);
412
        }
413
414
        $messages = $this->flash->getMessages();
415
        if (!empty($messages)) {
416
            foreach ($messages as $key => $message) {
417
                \PC::debug($message, 'Flash: ' . $key);
418
            }
419
        }
420
        // First execute anything else
421
        $response = $next($request, $response);
422
423
        // Any other request, pass on current response
424
        return $response;
425
    }
426
);
427
428
$container['action'] = isset($_REQUEST['action']) ? $_REQUEST['action'] : '';
429
430
if (!isset($msg)) {
431
    $msg = '';
432
}
433
434
$container['msg'] = $msg;
435