From 114f128fc302cb65a85937e197d2ff2215e8164c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Wed, 29 Jul 2015 18:09:23 +0200 Subject: [PATCH] Moving mysql setup code over to Doctrine --- lib/private/setup.php | 2 +- lib/private/setup/abstractdatabase.php | 37 ++++++----- lib/private/setup/mysql.php | 87 ++++++++++++++------------ lib/private/setup/oci.php | 38 +++++------ lib/private/setup/postgresql.php | 40 ++++++------ 5 files changed, 109 insertions(+), 95 deletions(-) diff --git a/lib/private/setup.php b/lib/private/setup.php index 870480feaa..c862429fd2 100644 --- a/lib/private/setup.php +++ b/lib/private/setup.php @@ -249,7 +249,7 @@ class Setup { $class = self::$dbSetupClasses[$dbType]; /** @var \OC\Setup\AbstractDatabase $dbSetup */ - $dbSetup = new $class($l, 'db_structure.xml'); + $dbSetup = new $class($l, 'db_structure.xml', $this->config); $error = array_merge($error, $dbSetup->validate($options)); // validate the data directory diff --git a/lib/private/setup/abstractdatabase.php b/lib/private/setup/abstractdatabase.php index 13daf1782f..928af0568b 100644 --- a/lib/private/setup/abstractdatabase.php +++ b/lib/private/setup/abstractdatabase.php @@ -22,22 +22,31 @@ */ namespace OC\Setup; +use OCP\IConfig; + abstract class AbstractDatabase { - /** - * @var \OC_L10N - */ + /** @var \OC_L10N */ protected $trans; + /** @var string */ protected $dbDefinitionFile; - protected $dbuser; - protected $dbpassword; - protected $dbname; - protected $dbhost; - protected $tableprefix; + /** @var string */ + protected $dbUser; + /** @var string */ + protected $dbPassword; + /** @var string */ + protected $dbName; + /** @var string */ + protected $dbHost; + /** @var string */ + protected $tablePrefix; + /** @var IConfig */ + protected $config; - public function __construct($trans, $dbDefinitionFile) { + public function __construct($trans, $dbDefinitionFile, IConfig $config) { $this->trans = $trans; $this->dbDefinitionFile = $dbDefinitionFile; + $this->config = $config; } public function validate($config) { @@ -67,11 +76,11 @@ abstract class AbstractDatabase { 'dbtableprefix' => $dbTablePrefix, ]); - $this->dbuser = $dbUser; - $this->dbpassword = $dbPass; - $this->dbname = $dbName; - $this->dbhost = $dbHost; - $this->tableprefix = $dbTablePrefix; + $this->dbUser = $dbUser; + $this->dbPassword = $dbPass; + $this->dbName = $dbName; + $this->dbHost = $dbHost; + $this->tablePrefix = $dbTablePrefix; } abstract public function setupDatabase($userName); diff --git a/lib/private/setup/mysql.php b/lib/private/setup/mysql.php index 9cf102393b..906b9f1b6c 100644 --- a/lib/private/setup/mysql.php +++ b/lib/private/setup/mysql.php @@ -23,21 +23,19 @@ */ namespace OC\Setup; +use OC\DB\ConnectionFactory; + class MySQL extends AbstractDatabase { public $dbprettyname = 'MySQL/MariaDB'; public function setupDatabase($username) { //check if the database user has admin right - $connection = @mysql_connect($this->dbhost, $this->dbuser, $this->dbpassword); - if(!$connection) { - throw new \OC\DatabaseSetupException($this->trans->t('MySQL/MariaDB username and/or password not valid'), - $this->trans->t('You need to enter either an existing account or the administrator.')); - } + $connection = $this->connect(); //user already specified in config $oldUser=\OC_Config::getValue('dbuser', false); //we don't have a dbuser specified in config - if($this->dbuser!=$oldUser) { + if($this->dbUser!=$oldUser) { //add prefix to the admin username to prevent collisions $adminUser=substr('oc_'.$username, 0, 16); @@ -45,18 +43,18 @@ class MySQL extends AbstractDatabase { while(true) { //this should be enough to check for admin rights in mysql $query="SELECT user FROM mysql.user WHERE user='$adminUser'"; - - $result = mysql_query($query, $connection); + $result = $connection->executeQuery($query); //current dbuser has admin rights if($result) { + $data = $result->fetchAll(); //new dbuser does not exist - if(mysql_num_rows($result) === 0) { + if(count($data) === 0) { //use the admin login data for the new database user - $this->dbuser=$adminUser; + $this->dbUser=$adminUser; //create a random password so we don't need to store the admin password in the config file - $this->dbpassword=\OC_Util::generateRandomBytes(30); + $this->dbPassword=\OC_Util::generateRandomBytes(30); $this->createDBUser($connection); @@ -73,8 +71,8 @@ class MySQL extends AbstractDatabase { }; \OC_Config::setValues([ - 'dbuser' => $this->dbuser, - 'dbpassword' => $this->dbpassword, + 'dbuser' => $this->dbUser, + 'dbpassword' => $this->dbPassword, ]); } @@ -83,50 +81,57 @@ class MySQL extends AbstractDatabase { //fill the database if needed $query='select count(*) from information_schema.tables' - ." where table_schema='".$this->dbname."' AND table_name = '".$this->tableprefix."users';"; - $result = mysql_query($query, $connection); - if($result) { - $row=mysql_fetch_row($result); - } + ." where table_schema='".$this->dbName."' AND table_name = '".$this->tablePrefix."users';"; + $result = $connection->executeQuery($query); + $row = $result->fetch(); if(!$result or $row[0]==0) { \OC_DB::createDbFromStructure($this->dbDefinitionFile); } - mysql_close($connection); } + /** + * @param \OC\DB\Connection $connection + */ private function createDatabase($connection) { - $name = $this->dbname; - $user = $this->dbuser; + $name = $this->dbName; + $user = $this->dbUser; //we cant use OC_BD functions here because we need to connect as the administrative user. $query = "CREATE DATABASE IF NOT EXISTS `$name` CHARACTER SET utf8 COLLATE utf8_bin;"; - $result = mysql_query($query, $connection); - if(!$result) { - $entry = $this->trans->t('DB Error: "%s"', array(mysql_error($connection))) . '
'; - $entry .= $this->trans->t('Offending command was: "%s"', array($query)) . '
'; - \OCP\Util::writeLog('setup.mysql', $entry, \OCP\Util::WARN); - } - $query="GRANT ALL PRIVILEGES ON `$name` . * TO '$user'"; + $connection->executeUpdate($query); //this query will fail if there aren't the right permissions, ignore the error - mysql_query($query, $connection); + $query="GRANT ALL PRIVILEGES ON `$name` . * TO '$user'"; + $connection->executeUpdate($query); } + /** + * @param \OC\DB\Connection $connection + * @throws \OC\DatabaseSetupException + */ private function createDBUser($connection) { - $name = $this->dbuser; - $password = $this->dbpassword; + $name = $this->dbUser; + $password = $this->dbPassword; // we need to create 2 accounts, one for global use and one for local user. if we don't specify the local one, // the anonymous user would take precedence when there is one. $query = "CREATE USER '$name'@'localhost' IDENTIFIED BY '$password'"; - $result = mysql_query($query, $connection); - if (!$result) { - throw new \OC\DatabaseSetupException($this->trans->t("MySQL/MariaDB user '%s'@'localhost' exists already.", array($name)), - $this->trans->t("Drop this user from MySQL/MariaDB", array($name))); - } + $connection->executeUpdate($query); $query = "CREATE USER '$name'@'%' IDENTIFIED BY '$password'"; - $result = mysql_query($query, $connection); - if (!$result) { - throw new \OC\DatabaseSetupException($this->trans->t("MySQL/MariaDB user '%s'@'%%' already exists", array($name)), - $this->trans->t("Drop this user from MySQL/MariaDB.")); - } + $connection->executeUpdate($query); + } + + /** + * @return \OC\DB\Connection + * @throws \OC\DatabaseSetupException + */ + private function connect() { + $type = 'mysql'; + $connectionParams = array( + 'host' => $this->dbHost, + 'user' => $this->dbUser, + 'password' => $this->dbPassword, + 'tablePrefix' => $this->tablePrefix, + ); + $cf = new ConnectionFactory(); + return $cf->getConnection($type, $connectionParams); } } diff --git a/lib/private/setup/oci.php b/lib/private/setup/oci.php index d46d5529da..1e1eb1ff54 100644 --- a/lib/private/setup/oci.php +++ b/lib/private/setup/oci.php @@ -38,10 +38,10 @@ class OCI extends AbstractDatabase { $this->dbtablespace = 'USERS'; } // allow empty hostname for oracle - $this->dbhost = $config['dbhost']; + $this->dbHost = $config['dbhost']; \OC_Config::setValues([ - 'dbhost' => $this->dbhost, + 'dbhost' => $this->dbHost, 'dbtablespace' => $this->dbtablespace, ]); } @@ -58,8 +58,8 @@ class OCI extends AbstractDatabase { } public function setupDatabase($username) { - $e_host = addslashes($this->dbhost); - $e_dbname = addslashes($this->dbname); + $e_host = addslashes($this->dbHost); + $e_dbname = addslashes($this->dbName); //check if the database user has admin right if ($e_host == '') { $easy_connect_string = $e_dbname; // use dbname as easy connect name @@ -67,7 +67,7 @@ class OCI extends AbstractDatabase { $easy_connect_string = '//'.$e_host.'/'.$e_dbname; } \OCP\Util::writeLog('setup oracle', 'connect string: ' . $easy_connect_string, \OCP\Util::DEBUG); - $connection = @oci_connect($this->dbuser, $this->dbpassword, $easy_connect_string); + $connection = @oci_connect($this->dbUser, $this->dbPassword, $easy_connect_string); if(!$connection) { $errorMessage = $this->getLastError(); if ($errorMessage) { @@ -103,23 +103,23 @@ class OCI extends AbstractDatabase { //use the admin login data for the new database user //add prefix to the oracle user name to prevent collisions - $this->dbuser='oc_'.$username; + $this->dbUser='oc_'.$username; //create a new password so we don't need to store the admin config in the config file - $this->dbpassword=\OC_Util::generateRandomBytes(30); + $this->dbPassword=\OC_Util::generateRandomBytes(30); //oracle passwords are treated as identifiers: // must start with alphanumeric char // needs to be shortened to 30 bytes, as the two " needed to escape the identifier count towards the identifier length. - $this->dbpassword=substr($this->dbpassword, 0, 30); + $this->dbPassword=substr($this->dbPassword, 0, 30); $this->createDBUser($connection); } } \OC_Config::setValues([ - 'dbuser' => $this->dbuser, - 'dbname' => $this->dbname, - 'dbpassword' => $this->dbpassword, + 'dbuser' => $this->dbUser, + 'dbname' => $this->dbName, + 'dbpassword' => $this->dbPassword, ]); //create the database not necessary, oracle implies user = schema @@ -131,26 +131,26 @@ class OCI extends AbstractDatabase { oci_close($connection); // connect to the oracle database (schema=$this->dbuser) an check if the schema needs to be filled - $this->dbuser = \OC_Config::getValue('dbuser'); + $this->dbUser = \OC_Config::getValue('dbuser'); //$this->dbname = \OC_Config::getValue('dbname'); - $this->dbpassword = \OC_Config::getValue('dbpassword'); + $this->dbPassword = \OC_Config::getValue('dbpassword'); - $e_host = addslashes($this->dbhost); - $e_dbname = addslashes($this->dbname); + $e_host = addslashes($this->dbHost); + $e_dbname = addslashes($this->dbName); if ($e_host == '') { $easy_connect_string = $e_dbname; // use dbname as easy connect name } else { $easy_connect_string = '//'.$e_host.'/'.$e_dbname; } - $connection = @oci_connect($this->dbuser, $this->dbpassword, $easy_connect_string); + $connection = @oci_connect($this->dbUser, $this->dbPassword, $easy_connect_string); if(!$connection) { throw new \OC\DatabaseSetupException($this->trans->t('Oracle username and/or password not valid'), $this->trans->t('You need to enter either an existing account or the administrator.')); } $query = "SELECT count(*) FROM user_tables WHERE table_name = :un"; $stmt = oci_parse($connection, $query); - $un = $this->tableprefix.'users'; + $un = $this->tablePrefix.'users'; oci_bind_by_name($stmt, ':un', $un); if (!$stmt) { $entry = $this->trans->t('DB Error: "%s"', array($this->getLastError($connection))) . '
'; @@ -171,8 +171,8 @@ class OCI extends AbstractDatabase { * @param resource $connection */ private function createDBUser($connection) { - $name = $this->dbuser; - $password = $this->dbpassword; + $name = $this->dbUser; + $password = $this->dbPassword; $query = "SELECT * FROM all_users WHERE USERNAME = :un"; $stmt = oci_parse($connection, $query); if (!$stmt) { diff --git a/lib/private/setup/postgresql.php b/lib/private/setup/postgresql.php index c8fd3b98fe..319b6676ef 100644 --- a/lib/private/setup/postgresql.php +++ b/lib/private/setup/postgresql.php @@ -27,9 +27,9 @@ class PostgreSQL extends AbstractDatabase { public $dbprettyname = 'PostgreSQL'; public function setupDatabase($username) { - $e_host = addslashes($this->dbhost); - $e_user = addslashes($this->dbuser); - $e_password = addslashes($this->dbpassword); + $e_host = addslashes($this->dbHost); + $e_user = addslashes($this->dbUser); + $e_password = addslashes($this->dbPassword); // Fix database with port connection if(strpos($e_host, ':')) { @@ -43,7 +43,7 @@ class PostgreSQL extends AbstractDatabase { $connection = @pg_connect($connection_string); if(!$connection) { // Try if we can connect to the DB with the specified name - $e_dbname = addslashes($this->dbname); + $e_dbname = addslashes($this->dbName); $connection_string = "host='$e_host' dbname='$e_dbname' user='$e_user' port='$port' password='$e_password'"; $connection = @pg_connect($connection_string); @@ -51,7 +51,7 @@ class PostgreSQL extends AbstractDatabase { throw new \OC\DatabaseSetupException($this->trans->t('PostgreSQL username and/or password not valid'), $this->trans->t('You need to enter either an existing account or the administrator.')); } - $e_user = pg_escape_string($this->dbuser); + $e_user = pg_escape_string($this->dbUser); //check for roles creation rights in postgresql $query="SELECT 1 FROM pg_roles WHERE rolcreaterole=TRUE AND rolname='$e_user'"; $result = pg_query($connection, $query); @@ -59,16 +59,16 @@ class PostgreSQL extends AbstractDatabase { //use the admin login data for the new database user //add prefix to the postgresql user name to prevent collisions - $this->dbuser='oc_'.$username; + $this->dbUser='oc_'.$username; //create a new password so we don't need to store the admin config in the config file - $this->dbpassword=\OC_Util::generateRandomBytes(30); + $this->dbPassword=\OC_Util::generateRandomBytes(30); $this->createDBUser($connection); } \OC_Config::setValues([ - 'dbuser' => $this->dbuser, - 'dbpassword' => $this->dbpassword, + 'dbuser' => $this->dbUser, + 'dbpassword' => $this->dbPassword, ]); //create the database @@ -78,13 +78,13 @@ class PostgreSQL extends AbstractDatabase { pg_close($connection); // connect to the ownCloud database (dbname=$this->dbname) and check if it needs to be filled - $this->dbuser = \OC_Config::getValue('dbuser'); - $this->dbpassword = \OC_Config::getValue('dbpassword'); + $this->dbUser = \OC_Config::getValue('dbuser'); + $this->dbPassword = \OC_Config::getValue('dbpassword'); - $e_host = addslashes($this->dbhost); - $e_dbname = addslashes($this->dbname); - $e_user = addslashes($this->dbuser); - $e_password = addslashes($this->dbpassword); + $e_host = addslashes($this->dbHost); + $e_dbname = addslashes($this->dbName); + $e_user = addslashes($this->dbUser); + $e_password = addslashes($this->dbPassword); // Fix database with port connection if(strpos($e_host, ':')) { @@ -99,7 +99,7 @@ class PostgreSQL extends AbstractDatabase { throw new \OC\DatabaseSetupException($this->trans->t('PostgreSQL username and/or password not valid'), $this->trans->t('You need to enter either an existing account or the administrator.')); } - $query = "select count(*) FROM pg_class WHERE relname='".$this->tableprefix."users' limit 1"; + $query = "select count(*) FROM pg_class WHERE relname='".$this->tablePrefix."users' limit 1"; $result = pg_query($connection, $query); if($result) { $row = pg_fetch_row($result); @@ -111,8 +111,8 @@ class PostgreSQL extends AbstractDatabase { private function createDatabase($connection) { //we cant use OC_BD functions here because we need to connect as the administrative user. - $e_name = pg_escape_string($this->dbname); - $e_user = pg_escape_string($this->dbuser); + $e_name = pg_escape_string($this->dbName); + $e_user = pg_escape_string($this->dbUser); $query = "select datname from pg_database where datname = '$e_name'"; $result = pg_query($connection, $query); if(!$result) { @@ -137,8 +137,8 @@ class PostgreSQL extends AbstractDatabase { } private function createDBUser($connection) { - $e_name = pg_escape_string($this->dbuser); - $e_password = pg_escape_string($this->dbpassword); + $e_name = pg_escape_string($this->dbUser); + $e_password = pg_escape_string($this->dbPassword); $query = "select * from pg_roles where rolname='$e_name';"; $result = pg_query($connection, $query); if(!$result) {