Skip to content

Commit 92e34e1

Browse files
committed
New simple error template for early errors such as PDO driver missing or DB non-existent. Fixes #142
1 parent 87425b1 commit 92e34e1

File tree

7 files changed

+92
-19
lines changed

7 files changed

+92
-19
lines changed

featherbb/Core/Database.php

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
use InvalidArgumentException;
4646
use IteratorAggregate;
4747
use PDO;
48+
use PDOException;
4849
use Serializable;
4950

5051
{
@@ -245,7 +246,7 @@ public static function reset_config()
245246
* this will normally be the first method called in a chain.
246247
* @param string $table_name
247248
* @param string $connection_name Which connection to use
248-
* @return DB
249+
* @return Database
249250
*/
250251
public static function for_table($table_name, $connection_name = self::DEFAULT_CONNECTION)
251252
{
@@ -267,15 +268,19 @@ protected static function _setup_db($connection_name = self::DEFAULT_CONNECTION)
267268
) {
268269
self::_setup_db_config($connection_name);
269270

270-
$db = new PDO(
271-
self::$_config[$connection_name]['connection_string'],
272-
self::$_config[$connection_name]['username'],
273-
self::$_config[$connection_name]['password'],
274-
self::$_config[$connection_name]['driver_options']
275-
);
276-
277-
$db->setAttribute(PDO::ATTR_ERRMODE, self::$_config[$connection_name]['error_mode']);
278-
self::set_db($db, $connection_name);
271+
try {
272+
$db = new PDO(
273+
self::$_config[$connection_name]['connection_string'],
274+
self::$_config[$connection_name]['username'],
275+
self::$_config[$connection_name]['password'],
276+
self::$_config[$connection_name]['driver_options']
277+
);
278+
279+
$db->setAttribute(PDO::ATTR_ERRMODE, self::$_config[$connection_name]['error_mode']);
280+
self::set_db($db, $connection_name);
281+
} catch (\Exception $e) {
282+
throw new Error($e->getMessage(), 500, false, false, true);
283+
}
279284
}
280285
}
281286

@@ -719,7 +724,7 @@ protected function _find_many()
719724
* Tell the DB that you are expecting multiple results
720725
* from your query, and execute it. Will return a result set object
721726
* containing instances of the DB class.
722-
* @return \IdiormResultSet
727+
* @return IdiormResultSet
723728
*/
724729
public function find_result_set()
725730
{

featherbb/Core/Error.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,14 @@ class Error extends \Exception
1515

1616
protected $html;
1717

18-
public function __construct($message, $code = 400, $backlink = true, $html = false)
18+
protected $simpleError;
19+
20+
public function __construct($message, $code = 400, $backlink = true, $html = false, $simpleError = false)
1921
{
2022
parent::__construct(Utils::escape($message), $code);
2123
$this->backlink = (bool) $backlink;
2224
$this->html = (bool) $html;
25+
$this->simpleError = (bool) $simpleError;
2326
}
2427

2528
public function hasBacklink()
@@ -31,4 +34,9 @@ public function displayHtml()
3134
{
3235
return $this->html;
3336
}
37+
38+
public function isSimpleError()
39+
{
40+
return $this->simpleError;
41+
}
3442
}

featherbb/Core/Interfaces/User.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ public static function getPref($pref = null, $user = null)
5555
/**
5656
* Check if the given user has the required permissions
5757
* @param string $permission The name of the action to check
58-
* @param int $id Optionnal user id
58+
* @param int $id Optional user id
5959
* @return boolval True if user is allowed to do this
6060
*/
6161
public static function can($permission = null, $id = null)
@@ -66,7 +66,7 @@ public static function can($permission = null, $id = null)
6666

6767
/**
6868
* Check if user is in admin group
69-
* @param int $id Optionnal user id
69+
* @param int $id Optional user id
7070
* @return boolean Is user in admin group ?
7171
*/
7272
public static function isAdmin($id = null)
@@ -76,7 +76,7 @@ public static function isAdmin($id = null)
7676

7777
/**
7878
* Check if user is admin or modo
79-
* @param int $id Optionnal user id
79+
* @param int $id Optional user id
8080
* @return boolean Is user in admin/mod group ?
8181
*/
8282
public static function isAdminMod($id = null)

featherbb/Core/View.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ public function setStyle($style)
223223
return $this;
224224
}
225225

226-
public function setPageInfo(array $data)
226+
public function setPageInfo($data)
227227
{
228228
foreach ($data as $key => $value) {
229229
list($key, $value) = $this->validate($key, $value);

featherbb/Middleware/Core.php

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use FeatherBB\Controller\Install;
1717
use FeatherBB\Core\Database as DB;
1818
use FeatherBB\Core\Email;
19+
use FeatherBB\Core\Error;
1920
use FeatherBB\Core\Hooks;
2021
use FeatherBB\Core\Parser;
2122
use FeatherBB\Core\Plugin as PluginManager;
@@ -33,7 +34,7 @@ class Core
3334
'Content-type' => 'text/html',
3435
'X-Frame-Options' => 'deny');
3536

36-
public function __construct(array $data)
37+
public function __construct($data)
3738
{
3839
// Handle empty values in data
3940
$data = array_merge(array('config_file' => 'featherbb/config.php',
@@ -43,7 +44,7 @@ public function __construct(array $data)
4344
$this->forum_env['FEATHER_ROOT'] = realpath(dirname(__FILE__).'/../../').'/';
4445
$this->forum_env['FORUM_CACHE_DIR'] = is_writable($this->forum_env['FEATHER_ROOT'].$data['cache_dir']) ? realpath($this->forum_env['FEATHER_ROOT'].$data['cache_dir']).'/' : null;
4546
$this->forum_env['FORUM_CONFIG_FILE'] = $this->forum_env['FEATHER_ROOT'].$data['config_file'];
46-
$this->forum_env['FEATHER_DEBUG'] = $this->forum_env['FEATHER_SHOW_QUERIES'] = ($data['debug'] == 'all' || $data['debug'] == true);
47+
$this->forum_env['FEATHER_DEBUG'] = $this->forum_env['FEATHER_SHOW_QUERIES'] = ($data['debug'] == 'all' || filter_var($data['debug'], FILTER_VALIDATE_BOOLEAN) == true);
4748
$this->forum_env['FEATHER_SHOW_INFO'] = ($data['debug'] == 'info' || $data['debug'] == 'all');
4849

4950
// Populate forum_env
@@ -105,14 +106,23 @@ public static function init_db(array $config, $log_queries = false)
105106
$config['db_prefix'] = (!empty($config['db_prefix'])) ? $config['db_prefix'] : '';
106107
switch ($config['db_type']) {
107108
case 'mysql':
109+
if (!extension_loaded('pdo_mysql')) {
110+
throw new Error('Driver pdo_mysql not installed.', 500, false, false, true);
111+
}
108112
DB::configure('mysql:host='.$config['db_host'].';dbname='.$config['db_name']);
109113
DB::configure('driver_options', array(\PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'));
110114
break;
111115
case 'sqlite';
112116
case 'sqlite3';
117+
if (!extension_loaded('pdo_sqlite')) {
118+
throw new Error('Driver pdo_mysql not installed.', 500, false, false, true);
119+
}
113120
DB::configure('sqlite:./'.$config['db_name']);
114121
break;
115122
case 'pgsql':
123+
if (!extension_loaded('pdo_pgsql')) {
124+
throw new Error('Driver pdo_mysql not installed.', 500, false, false, true);
125+
}
116126
DB::configure('pgsql:host='.$config['db_host'].'dbname='.$config['db_name']);
117127
break;
118128
}
@@ -258,6 +268,11 @@ public function __invoke($req, $res, $next)
258268
// Define time formats and add them to the container
259269
Container::set('forum_time_formats', array(ForumSettings::get('time_format'), 'H:i:s', 'H:i', 'g:i:s a', 'g:i a'));
260270
Container::set('forum_date_formats', array(ForumSettings::get('date_format'), 'Y-m-d', 'Y-d-m', 'd-m-Y', 'm-d-Y', 'M j Y', 'jS M Y'));
271+
272+
// Check if we have DOM support (not installed by default in PHP >= 7.0, results in utf8_decode not defined
273+
if (!function_exists('utf8_decode')) {
274+
throw new Error('Please install the php7.0-xml package.', 500, false, false, true);
275+
}
261276

262277
return $next($req, $res);
263278
}

featherbb/View/errorSimple.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2+
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr">
3+
<head>
4+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5+
<title>Error / FeatherBB</title>
6+
<style type="text/css">
7+
<!--
8+
BODY {margin: 10% 20% auto 20%; font: 10px Verdana, Arial, Helvetica, sans-serif; background-color: #f9f9f9}
9+
#errorbox {border: 1px solid #029be5}
10+
H2 {margin: 0; color: #fff; background-color: #029be5; font-size: 1.1em; padding: 5px 4px}
11+
#errorbox DIV {padding: 6px 5px; background-color: #fff}
12+
-->
13+
</style>
14+
</head>
15+
<body>
16+
17+
<div id="errorbox">
18+
<h2>An error was encountered</h2>
19+
<div>
20+
<?php if (!$error['hide']) : ?>
21+
<strong>File:</strong> <?= $e->getFile() ?><br />
22+
<strong>Line:</strong> <?= $e->getLine() ?><br /><br />
23+
<?php endif; ?>
24+
<strong>FeatherBB reported</strong>: <?= $error['message'] ?>
25+
</div>
26+
</div>
27+
28+
</body>
29+
</html>

featherbb/routes.php

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,11 +208,27 @@
208208
'message' => $e->getMessage(),
209209
'back' => true,
210210
'html' => false,
211+
'hide' => false,
211212
);
212213

213214
// Hide internal mechanism
214-
if (!in_array(get_class($e), array('FeatherBB\Core\Error')) && ForumEnv::get('FEATHER_DEBUG') != 'all') {
215+
if (!ForumEnv::get('FEATHER_DEBUG')) {
215216
$error['message'] = __('Error');
217+
$error['hide'] = true;
218+
}
219+
220+
// Display a simple error page that does not require heavy user-specific methods like permissions
221+
if (method_exists($e, 'isSimpleError') && $e->isSimpleError()) {
222+
ob_end_clean();
223+
224+
// ob_start to avoid an extra "1" returned by PHP with a successful inclusion
225+
ob_start();
226+
include(ForumEnv::get('FEATHER_ROOT') . 'featherbb/View/errorSimple.php');
227+
$include = ob_get_clean();
228+
229+
$response->write($include);
230+
231+
return $response;
216232
}
217233

218234
if (method_exists($e, 'hasBacklink')) {

0 commit comments

Comments
 (0)