fixing PDO for MySQL class and spoolsize (adding exec() for direct queries, manage properly query() call without arguments (no prepare, allow show database)

This commit is contained in:
Benjamin Sonntag 2016-05-18 18:00:04 +02:00
parent 8392c1d84f
commit b1ca1d88ae
3 changed files with 86 additions and 78 deletions

View File

@ -119,7 +119,7 @@ class DB_Sql {
* @param arguments is an optionnal array for future use with PDO parametrized requests * @param arguments is an optionnal array for future use with PDO parametrized requests
* @return the $Query_ID class variable (null if fails) * @return the $Query_ID class variable (null if fails)
*/ */
function query($Query_String, $arguments = False) { function query($Query_String, $arguments = false) {
global $debug_alternc; global $debug_alternc;
if (empty($Query_String) || !$this->is_connected()) if (empty($Query_String) || !$this->is_connected())
@ -131,16 +131,29 @@ class DB_Sql {
$debug_chrono_start = microtime(true); $debug_chrono_start = microtime(true);
$this->pdo_query = $this->pdo_instance->prepare($this->Query_String); if ($arguments===false) {
$exec_state = ($arguments) ? $this->pdo_query->execute($arguments) $this->pdo_query = $this->pdo_instance->query($Query_String);
: $this->pdo_query->execute(); $exec_state = is_object($this->pdo_query);
} else {
$this->pdo_query = $this->pdo_instance->prepare($this->Query_String);
$exec_state = ($arguments) ? $this->pdo_query->execute($arguments)
: $this->pdo_query->execute();
// WARNING: this ternary is when we pass array() as $arguments
}
$debug_chrono_start = (microtime(true) - $debug_chrono_start)*1000; $debug_chrono_start = (microtime(true) - $debug_chrono_start)*1000;
$this->Row = 0; $this->Row = 0;
if ($exec_state == FALSE) { if ($exec_state == FALSE) {
if (is_object($this->pdo_query)) {
$this->Errno = $this->pdo_query->errorCode(); $this->Errno = $this->pdo_query->errorCode();
$this->Error = $this->pdo_query->errorInfo(); $this->Error = $this->pdo_query->errorInfo();
} else {
$this->Errno = $this->pdo_instance->errorCode();
$this->Error = $this->pdo_instance->errorInfo();
}
if( defined("THROW_EXCEPTIONS") && THROW_EXCEPTIONS ){ if( defined("THROW_EXCEPTIONS") && THROW_EXCEPTIONS ){
throw new \Exception("Mysql query failed : $this->Error"); throw new \Exception("Mysql query failed : $this->Error");
@ -280,6 +293,17 @@ class DB_Sql {
return $this->pdo_instance->quote($string); return $this->pdo_instance->quote($string);
} }
/**
* Execute a direct query, not getting any result back
* @param query string query to execute
* @return integer the number of affected rows
*/
function exec($query) {
return $this->pdo_instance->exec($query);
}
/* public: sequence numbers */ /* public: sequence numbers */
function nextid($seq_name) { function nextid($seq_name) {
if (!$this->is_connected()) if (!$this->is_connected())

View File

@ -42,34 +42,25 @@ class DB_users extends DB_Sql {
/** /**
* Creator * Creator
*/ */
function DB_users($empty = false) { // Sometimes we need to create this object with empty parameters, but by default we fill them with those of the current user's DB function __construct() { // Sometimes we need to create this object with empty parameters, but by default we fill them with those of the current user's DB
global $cuid, $db, $err; global $cuid, $db, $err;
$db->query("select db_servers.* from db_servers, membres where membres.uid= ? and membres.db_server_id=db_servers.id;", array($cuid));
if (!$db->next_record()) {
$err->raise('db_user', _("There are no databases in db_servers for this user. Please contact your administrator."));
die();
}
if (!$empty) { # Create the object
$db->query("select db_servers.* from db_servers, membres where membres.uid= ? and membres.db_server_id=db_servers.id;", array($cuid)); $this->HumanHostname = $db->f('name');
if (!$db->next_record()) { $this->Host = $db->f('host');
$err->raise('db_user', _("There are no databases in db_servers for this user. Please contact your administrator.")); $this->User = $db->f('login');
die(); $this->Password = $db->f('password');
} $this->Client = $db->f('client');
$this->Database = "mysql";
# Create the object
$this->HumanHostname = $db->f('name'); parent::__construct("mysql", $db->f('host'), $db->f('login'), $db->f('password') );
$this->Host = $db->f('host');
$this->User = $db->f('login');
$this->Password = $db->f('password');
$this->Client = $db->f('client');
$this->Database = "mysql"; # We have to define a dabatase when we connect, and the database must exist.
} else {
# Create the object without any parameter
$this->HumanHostname = "";
$this->Host = "";
$this->User = "";
$this->Password = "";
$this->Client = "";
$this->Database = "mysql"; # We have to define a dabatase when we connect, and the database must exist.
}
} }
} }
@ -288,7 +279,7 @@ class m_mysql {
} }
//Grant the special user every rights. //Grant the special user every rights.
if ($this->dbus->query("CREATE DATABASE ? ;", array($dbname))) { if ($this->dbus->exec("CREATE DATABASE $dbname;")) { // secured: dbname is checked against ^[0-9a-z]*$
$err->log("mysql", "add_db_succes", $dbn); $err->log("mysql", "add_db_succes", $dbn);
// Ok, database does not exist, quota is ok and dbname is compliant. Let's proceed // Ok, database does not exist, quota is ok and dbname is compliant. Let's proceed
$db->query("INSERT INTO db (uid,login,pass,db,bck_mode) VALUES (?, ?, ?, ? ,0)", array($cuid, $myadm, $password, $dbname)); $db->query("INSERT INTO db (uid,login,pass,db,bck_mode) VALUES (?, ?, ?, ? ,0)", array($cuid, $myadm, $password, $dbname));
@ -310,30 +301,29 @@ class m_mysql {
/* --------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------- */
/** Delete a database for the current user. /** Delete a database for the current user.
* @param $dbn string Name of the database to delete. The db name is $user_$dbn * @param $dbname string Name of the database to delete. The db name is $user_$dbn
* @return boolean if the database $user_$db has been successfully deleted, or FALSE if * @return boolean if the database $user_$db has been successfully deleted, or FALSE if
* an error occured, such as db does not exist. * an error occured, such as db does not exist.
*/ */
function del_db($dbn) { function del_db($dbname) {
global $db, $err, $cuid; global $db, $err, $cuid;
$err->log("mysql", "del_db", $dbn); $err->log("mysql", "del_db", $dbname);
$db->query("SELECT uid FROM db WHERE db= ?;", array($dbname)); $db->query("SELECT uid FROM db WHERE db= ?;", array($dbname));
if (!$db->num_rows()) { if (!$db->next_record()) {
$err->raise("mysql", _("The database was not found. I can't delete it")); $err->raise("mysql", _("The database was not found. I can't delete it"));
return false; return false;
} }
$db->next_record();
// Ok, database exists and dbname is compliant. Let's proceed // Ok, database exists and dbname is compliant. Let's proceed
$db->query("DELETE FROM size_db WHERE db ?;", array($dbname)); $db->query("DELETE FROM size_db WHERE db ?;", array($dbname));
$db->query("DELETE FROM db WHERE uid= ? AND db= ? ;", array($cuid, $dbname)); $db->query("DELETE FROM db WHERE uid= ? AND db= ? ;", array($cuid, $dbname));
$this->dbus->query("DROP DATABASE ? ;", array($dbname)); $this->dbus->query("DROP DATABASE $dbname;");
$db_esc = str_replace('_', '\_', $dbname); $db_esc = str_replace('_', '\_', $dbname);
$this->dbus->query("DELETE FROM mysql.db WHERE Db= ? ;", array($db_esc)); $this->dbus->query("DELETE FROM mysql.db WHERE Db= ? ;", array($db_esc));
#We test if the user created with the database is associated with more than 1 database. #We test if the user created with the database is associated with more than 1 database.
$this->dbus->query("select User from mysql.db where User= ? and (Select_priv='Y' or Insert_priv='Y' or Update_priv='Y' or Delete_priv='Y' or Create_priv='Y' or Drop_priv='Y' or References_priv='Y' or Index_priv='Y' or Alter_priv='Y' or Create_tmp_table_priv='Y' or Lock_tables_priv='Y');", array($dbname)); $this->dbus->query("select User from mysql.db where User= ? ;", array($dbname));
if (($this->dbus->num_rows()) == 0) { if (($this->dbus->num_rows()) == 0) {
#If not we can delete it. #If not we can delete it.
$this->del_user($dbname); $this->del_user($dbname);
@ -479,11 +469,7 @@ class m_mysql {
return false; return false;
} }
# Protect database name if not wildcard $grant = "grant " . $rights . " on " . $base . "." . $table . " to " . $db->quote($user) . "@" . $db->quote($this->dbus->Client);
if ($base != '*') {
$base = $db->quote($base);
}
$grant = "grant " . $db->quote($rights) . " on " . $base . "." . $db->quote($table) . " to " . $db->quote($user) . "@" . $db->quote($this->dbus->Client);
if ($pass) { if ($pass) {
$grant .= " identified by " . $db->quote($pass) . ";"; $grant .= " identified by " . $db->quote($pass) . ";";
@ -555,7 +541,7 @@ class m_mysql {
* @access private * @access private
*/ */
function get_db_size($dbname) { function get_db_size($dbname) {
$this->dbus->query("SHOW TABLE STATUS FROM ". $db->quote($dbname) .";"); $this->dbus->query("SHOW TABLE STATUS FROM $dbname;");
$size = 0; $size = 0;
while ($this->dbus->next_record()) { while ($this->dbus->next_record()) {
$size += $this->dbus->f('Data_length') + $this->dbus->f('Index_length'); $size += $this->dbus->f('Data_length') + $this->dbus->f('Index_length');
@ -695,7 +681,7 @@ class m_mysql {
$usern = trim($usern); $usern = trim($usern);
$login = $mem->user["login"]; $login = $mem->user["login"];
if ($login != $usern) { if ($login != $usern) {
$user = addslashes($login . "_" . $usern); $user = $login . "_" . $usern;
} else { } else {
$user = $usern; $user = $usern;
} }
@ -704,7 +690,7 @@ class m_mysql {
$err->raise("mysql", _("The username is mandatory")); $err->raise("mysql", _("The username is mandatory"));
return false; return false;
} }
if (!$pass) { if (!$password) {
$err->raise("mysql", _("The password is mandatory")); $err->raise("mysql", _("The password is mandatory"));
return false; return false;
} }
@ -714,7 +700,7 @@ class m_mysql {
} }
// We check the length of the COMPLETE username, not only the part after _ // We check the length of the COMPLETE username, not only the part after _
$len=variable_get("sql_max_username_length", 16); $len=variable_get("sql_max_username_length", 16);
if (strlen($user) > $len) { if (strlen($user) > $len) {
$err->raise("mysql", _("MySQL username cannot exceed %d characters"), $len); $err->raise("mysql", _("MySQL username cannot exceed %d characters"), $len);
return false; return false;
@ -781,7 +767,7 @@ class m_mysql {
* @param integer $all * @param integer $all
* @return boolean if the user has been deleted in MySQL or FALSE if an error occurred * @return boolean if the user has been deleted in MySQL or FALSE if an error occurred
* */ * */
function del_user($user, $all = null) { function del_user($user, $all = false) {
global $db, $err, $cuid; global $db, $err, $cuid;
$err->log("mysql", "del_user", $user); $err->log("mysql", "del_user", $user);
if (!preg_match("#^[0-9a-z]#", $user)) { if (!preg_match("#^[0-9a-z]#", $user)) {
@ -933,10 +919,8 @@ class m_mysql {
// We reset all user rights on this DB : // We reset all user rights on this DB :
$this->dbus->query("SELECT * FROM mysql.db WHERE User = ? AND Db = ?;", array($user, $dbn)); $this->dbus->query("SELECT * FROM mysql.db WHERE User = ? AND Db = ?;", array($user, $dbn));
// @TODO:EM: This has to be verified, and maybe we should use another way to escape those requests
if ($this->dbus->num_rows()) { if ($this->dbus->num_rows()) {
$this->dbus->query("REVOKE ALL PRIVILEGES ON ".$db->quote($dbn).".* FROM ".$db->quote($user)."@" . $db->quote($this->dbus->Client) . ";"); $this->dbus->query("REVOKE ALL PRIVILEGES ON ".$dbn.".* FROM ".$db->quote($user)."@" . $db->quote($this->dbus->Client) . ";");
} }
if ($strrights) { if ($strrights) {
$strrights = substr($strrights, 0, strlen($strrights) - 1); $strrights = substr($strrights, 0, strlen($strrights) - 1);
@ -1005,7 +989,6 @@ class m_mysql {
$password = create_pass(8); $password = create_pass(8);
} }
$db->query("INSERT INTO dbusers (uid,name,password,enable) VALUES (?, ?, ?, 'ADMIN');", array($cuid, $myadm, $password)); $db->query("INSERT INTO dbusers (uid,name,password,enable) VALUES (?, ?, ?, 'ADMIN');", array($cuid, $myadm, $password));
return true; return true;
@ -1119,24 +1102,20 @@ class m_mysql {
global $err; global $err;
$err->log("mysql", "get_dbus_size", $db_host); $err->log("mysql", "get_dbus_size", $db_host);
# We create the object with empty parameters $this->dbus = new DB_Sql("mysql",$db_host,$db_login,$db_password);
$this->dbus = new DB_users(true);
# Modify the object with right parameters
$this->dbus->HumanHostname = $db_name;
$this->dbus->Host = $db_host;
$this->dbus->User = $db_login;
$this->dbus->Password = $db_password;
$this->dbus->Client = $db_client;
$this->dbus->query("show databases;"); $this->dbus->query("SHOW DATABASES;");
$res = array(); $alldb=array();
//@TODO: this has to be done in another way
while ($this->dbus->next_record()) { while ($this->dbus->next_record()) {
$dbname = $this->dbus->f("Database"); $alldb[] = $this->dbus->f("Database");
$c = mysql_query("SHOW TABLE STATUS FROM $dbname;"); }
$res = array();
foreach($alldb as $dbname) {
$c = $this->dbus->query("SHOW TABLE STATUS FROM $dbname;");
$size = 0; $size = 0;
while ($d = mysql_fetch_array($c)) { while ($this->dbus->next_record()) {
$size+=$d["Data_length"] + $d["Index_length"]; $size+=$this->dbus->f("Data_length") + $this->dbus->f("Index_length");
} }
$res["$dbname"] = "$size"; $res["$dbname"] = "$size";
} }

View File

@ -26,17 +26,22 @@ if ($db->query("SELECT uid,login FROM membres;")) {
echo "\n---------------------------\n Generating size-cache for MySQL databases\n\n"; echo "\n---------------------------\n Generating size-cache for MySQL databases\n\n";
// We get all hosts on which sql users' DB are // We get all hosts on which sql users' DB are
$r=mysql_query("select * from db_servers;"); $r=$db->query("select * from db_servers;");
$tab=array(); $allsrv=array();
while ($c=mysql_fetch_array($r)) { while ($db->next_record()) {
$tab=$mysql->get_dbus_size($c["name"],$c["host"],$c["login"],$c["password"],$c["client"]); $allsrv[] = $db->Record;
echo "++ Processing ".$c["name"]." ++\n"; }
foreach ($tab as $dbname=>$size) {
$db->query("REPLACE INTO size_db SET db=?,size=?;",array($dbname,$size)); $tab=array();
echo " $dbname done ($size B) \n"; flush(); foreach($allsrv as $c) {
} $tab=$mysql->get_dbus_size($c["name"],$c["host"],$c["login"],$c["password"],$c["client"]);
echo "\n"; echo "++ Processing ".$c["name"]." ++\n";
foreach ($tab as $dbname=>$size) {
$db->query("REPLACE INTO size_db SET db=?,size=?;",array($dbname,$size));
echo " $dbname done ($size B) \n"; flush();
} }
echo "\n";
}
echo "---------------------------\n Generating size-cache for mailman\n\n"; echo "---------------------------\n Generating size-cache for mailman\n\n";
if ($db->query("SELECT uid, name FROM mailman;")) { if ($db->query("SELECT uid, name FROM mailman;")) {