From dd589f53330d7015b2394e95eeabad1a2803ee72 Mon Sep 17 00:00:00 2001 From: Tim Otten Date: Fri, 25 Jun 2021 15:12:14 -0700 Subject: [PATCH] dev/core#2663 - Setup - Consistently handle special characters per URL conventions Overview -------- This addresses a problem with the setup UI when installing CiviCRM with certain database credentials. Specifically, it handles special characters more correctly. https://lab.civicrm.org/dev/core/-/issues/2663 Before ------ If the database password requires any special characters (e.g. "#" or "&"), then they cannot correctly entered. There are two ways you might try to enter a password (e.g. plain `mysql://myuser:top#secret...`or URL-encoded `mysql://myuser:top%23secret...`). Neither of these work. (The plain notation might pass the validator, but it won't be written correctly to disk. The URL-encoded notation won't pass the validator.) After ----- You may use special characters, as long as the URL is properly encoded, e.g. `mysql://myuser:top%23secret...` --- setup/plugins/blocks/advanced.tpl.php | 5 +++-- .../InstallSettingsFile.civi-setup.php | 16 ++++++++-------- setup/src/Setup/DbUtil.php | 16 +++++++++------- 3 files changed, 20 insertions(+), 17 deletions(-) diff --git a/setup/plugins/blocks/advanced.tpl.php b/setup/plugins/blocks/advanced.tpl.php index 52665827de..12531bed4b 100644 --- a/setup/plugins/blocks/advanced.tpl.php +++ b/setup/plugins/blocks/advanced.tpl.php @@ -12,14 +12,14 @@ endif; ?> - cmsDb['username'] . ':HIDDEN@' . $model->cmsDb['server'] . '/' . $model->cmsDb['database']); ?> + cmsDb, ['password' => 'HIDDEN']))); ?>
- db['username'] . ':HIDDEN@' . $model->db['server'] . '/' . $model->db['database']); ?> + db, ['password' => 'HIDDEN']))); ?>
diff --git a/setup/plugins/installFiles/InstallSettingsFile.civi-setup.php b/setup/plugins/installFiles/InstallSettingsFile.civi-setup.php index 447889a873..8140f5d48d 100644 --- a/setup/plugins/installFiles/InstallSettingsFile.civi-setup.php +++ b/setup/plugins/installFiles/InstallSettingsFile.civi-setup.php @@ -74,10 +74,10 @@ if (!defined('CIVI_SETUP')) { // ??why is frontEnd=0?? $params['frontEnd'] = 0; $params['baseURL'] = addslashes(rtrim($m->cmsBaseUrl, '/')); - $params['dbUser'] = addslashes($m->db['username']); - $params['dbPass'] = addslashes($m->db['password']); - $params['dbHost'] = addslashes($m->db['server']); - $params['dbName'] = addslashes($m->db['database']); + $params['dbUser'] = addslashes(urlencode($m->db['username'])); + $params['dbPass'] = addslashes(urlencode($m->db['password'])); + $params['dbHost'] = addslashes(implode(':', array_map('urlencode', explode(':', $m->db['server'])))); + $params['dbName'] = addslashes(urlencode($m->db['database'])); // The '&' prefix is awkward, but we don't know what's already in the file. // At the time of writing, it has ?new_link=true. If that is removed, // then need to update this. @@ -86,10 +86,10 @@ if (!defined('CIVI_SETUP')) { // need to use %20 for spaces. $params['dbSSL'] = empty($m->db['ssl_params']) ? '' : addslashes('&' . http_build_query($m->db['ssl_params'], '', '&', PHP_QUERY_RFC3986)); $params['cms'] = addslashes($m->cms); - $params['CMSdbUser'] = addslashes($m->cmsDb['username']); - $params['CMSdbPass'] = addslashes($m->cmsDb['password']); - $params['CMSdbHost'] = addslashes($m->cmsDb['server']); - $params['CMSdbName'] = addslashes($m->cmsDb['database']); + $params['CMSdbUser'] = addslashes(urlencode($m->cmsDb['username'])); + $params['CMSdbPass'] = addslashes(urlencode($m->cmsDb['password'])); + $params['CMSdbHost'] = addslashes(implode(':', array_map('urlencode', explode(':', $m->cmsDb['server'])))); + $params['CMSdbName'] = addslashes(urlencode($m->cmsDb['database'])); // The '&' prefix is awkward, but we don't know what's already in the file. // At the time of writing, it has ?new_link=true. If that is removed, // then need to update this. diff --git a/setup/src/Setup/DbUtil.php b/setup/src/Setup/DbUtil.php index 6c23c25165..438fb708c9 100644 --- a/setup/src/Setup/DbUtil.php +++ b/setup/src/Setup/DbUtil.php @@ -10,7 +10,7 @@ class DbUtil { * @return array */ public static function parseDsn($dsn) { - $parsed = parse_url($dsn); + $parsed = array_map('urldecode', parse_url($dsn)); // parse_url parses 'mysql://admin:secret@unix(/var/lib/mysql/mysql.sock)/otherdb' like: // [ // 'host' => 'unix(', @@ -37,18 +37,20 @@ class DbUtil { } /** - * @todo Is this used anywhere? It doesn't support SSL as-is. - * Convert an datasource from array notation to URL notation. + * Convert a datasource from array notation to URL notation. + * + * FIXME: Doesn't support SSL * * @param array $db * @return string */ public static function encodeDsn($db) { + $escapedHostPort = implode(':', array_map('urlencode', explode(':', $db['server']))); return sprintf('mysql://%s:%s@%s/%s', - $db['username'], - $db['password'], - $db['server'], - $db['database'] + urlencode($db['username']), + urlencode($db['password']), + $escapedHostPort, + urlencode($db['database']) ); } -- 2.25.1