/**
* Verifies database connection
*
* @param array $options Options array
*
* @return boolean|\Joomla\Database\DatabaseInterface
*
* @since 4.0.0
* @throws \Exception
*/
public function checkDb($options) : bool
{
// Ensure a database type was selected.
if (empty($options['dbtype'])) {
$this->ioStyle->error(Text::_('INSTL_DATABASE_INVALID_TYPE'));
return false;
}
// Ensure that a hostname and user name were input.
if (empty($options['host']) || empty($options['user'])) {
$this->ioStyle->error(Text::_('INSTL_DATABASE_INVALID_DB_DETAILS'));
return false;
}
// Validate database table prefix.
if (isset($options['dbprefix']) && !preg_match('#^[a-zA-Z]+[a-zA-Z0-9_]*$#', $options['dbprefix'])) {
$this->ioStyle->error(Text::_('INSTL_DATABASE_PREFIX_MSG'));
return false;
}
// Validate length of database table prefix.
if (isset($options['dbprefix']) && strlen($options['dbprefix']) > 15) {
$this->ioStyle->error(Text::_('INSTL_DATABASE_FIX_TOO_LONG'), 'warning');
return false;
}
// Validate length of database name.
if (strlen($options['db']) > 64) {
$this->ioStyle->error(Text::_('INSTL_DATABASE_NAME_TOO_LONG'));
return false;
}
// Validate database name.
if (in_array($options['dbtype'], ['pgsql', 'postgresql'], true) && !preg_match('#^[a-zA-Z_][0-9a-zA-Z_$]*$#', $options['db'])) {
$this->ioStyle->error(Text::_('INSTL_DATABASE_NAME_MSG_POSTGRES'));
return false;
}
if (in_array($options['dbtype'], ['mysql', 'mysqli']) && preg_match('#[\\\\\\/]#', $options['db'])) {
$this->ioStyle->error(Text::_('INSTL_DATABASE_NAME_MSG_MYSQL'));
return false;
}
// Workaround for UPPERCASE table prefix for PostgreSQL
if (in_array($options['dbtype'], ['pgsql', 'postgresql'])) {
if (isset($options['dbprefix']) && strtolower($options['dbprefix']) !== $options['dbprefix']) {
$this->ioStyle->error(Text::_('INSTL_DATABASE_FIX_LOWERCASE'));
return false;
}
}
$app = $this->getApplication();
// Check db connection encryption properties
$model = $app->bootComponent('com_config')->getMVCFactory($app)->createModel('Application', 'Administrator');
if (!$model->validateDbConnection($options)) {
$this->ioStyle->error(Text::_('Failed to validate the db connection encryption properties'));
return false;
}
// Build the connection options array.
$settings = ['driver' => $options['dbtype'], 'host' => $options['host'], 'user' => $options['user'], 'password' => $options['password'], 'database' => $options['db'], 'prefix' => $options['dbprefix']];
if ((int) $options['dbencryption'] !== 0) {
$settings['ssl'] = ['enable' => true, 'verify_server_cert' => (bool) $options['dbsslverifyservercert']];
foreach (['cipher', 'ca', 'key', 'cert'] as $value) {
$confVal = trim($options['dbssl' . $value]);
if ($confVal !== '') {
$settings['ssl'][$value] = $confVal;
}
}
}
// Get a database object.
try {
$db = DatabaseDriver::getInstance($settings);
$db->getVersion();
} catch (\Exception $e) {
$this->ioStyle->error(Text::sprintf('Cannot connect to database, verify that you specified the correct database details %s', $e->getMessage()));
return false;
}
if ((int) $options['dbencryption'] !== 0 && empty($db->getConnectionEncryption())) {
if ($db->isConnectionEncryptionSupported()) {
$this->ioStyle->error(Text::_('COM_CONFIG_ERROR_DATABASE_ENCRYPTION_CONN_NOT_ENCRYPT'));
} else {
$this->ioStyle->error(Text::_('COM_CONFIG_ERROR_DATABASE_ENCRYPTION_SRV_NOT_SUPPORTS'));
}
return false;
}
return true;
}