From 0aa4efbc0b79ba9ab8a66e8facfda8cb16b7c427 Mon Sep 17 00:00:00 2001
From: tbrehm <t.brehm@ispconfig.org>
Date: Mon, 07 May 2012 11:01:19 -0400
Subject: [PATCH] Improved mysql db library.

---
 interface/lib/classes/db_mysql.inc.php |  328 +++++++++++++++++++++++++++++++++++++++++-------------
 1 files changed, 246 insertions(+), 82 deletions(-)

diff --git a/interface/lib/classes/db_mysql.inc.php b/interface/lib/classes/db_mysql.inc.php
index 09297c7..7cee46e 100644
--- a/interface/lib/classes/db_mysql.inc.php
+++ b/interface/lib/classes/db_mysql.inc.php
@@ -1,14 +1,6 @@
 <?php
-/**
- * mySQL Database class
- * 
- * @author Till Brehm
- * @copyright  2005, Till Brehm, projektfarm Gmbh
- * @version 0.1
- * @package ISPConfig
- */
 /*
-Copyright (c) 2005, Till Brehm, projektfarm Gmbh
+Copyright (c) 2007-2012, Till Brehm, projektfarm Gmbh, ISPConfig UG
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without modification,
@@ -35,21 +27,23 @@
 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-class db
-{
-	private $dbHost = '';		// hostname of the MySQL server
-	private $dbName = '';		// logical database name on that server
-	private $dbUser = '';		// database authorized user
-	private $dbPass = '';		// user's password
-	private $linkId = 0;		// last result of mysql_connect()
-	private $queryId = 0;		// last result of mysql_query()
-	private $record	= array();	// last record fetched
-    private $autoCommit = 1;    // Autocommit Transactions
-	private $currentRow;		// current row number
-	private $errorNumber = 0;	// last error number
-	private $errorMessage = '';	// last error message
-	private $errorLocation = '';// last error location
-	private $show_error_messages = false;
+class db {
+	private $dbHost = '';		   // hostname of the MySQL server
+	private $dbName = '';		   // logical database name on that server
+	private $dbUser = '';		   // database authorized user
+	private $dbPass = '';		   // user's password
+	private $dbCharset = '';	   // what charset comes and goes to mysql: utf8 / latin1
+	private $dbNewLink = false;    // Return a new linkID when connect is called again
+	private $dbClientFlags = 0;    // MySQL Client falgs
+	private $linkId = 0;		   // last result of mysql_connect()
+	private $queryId = 0;		   // last result of mysql_query()
+	private $record	= array();	   // last record fetched
+	private $autoCommit = 1;	    // Autocommit Transactions
+	private $currentRow;		   // current row number
+	private $errorNumber = 0;	   // last error number
+	public $errorMessage = '';	   // last error message
+	private $errorLocation = '';   // last error location
+	public $show_error_messages = false;
 
 	public function __construct()
     {
@@ -58,6 +52,9 @@
 		$this->dbName = $conf['db_database'];
 		$this->dbUser = $conf['db_user'];
 		$this->dbPass = $conf['db_password'];
+		$this->dbCharset = $conf['db_charset'];
+		$this->dbNewLink = $conf['db_new_link'];
+		$this->dbClientFlags = $conf['db_client_flags'];
 		//$this->connect();
 	}
 
@@ -74,19 +71,21 @@
 	}
 
 	public function connect()
-    {
+	{
 		if($this->linkId == 0){
-			$this->linkId = mysql_connect($this->dbHost, $this->dbUser, $this->dbPass);
+			$this->linkId = mysql_connect($this->dbHost, $this->dbUser, $this->dbPass, $this->dbNewLink, $this->dbClientFlags);
 			if(!$this->linkId){
 				$this->updateError('DB::connect()<br />mysql_connect');
 				return false;
 			}
+    		$this->queryId = @mysql_query('SET NAMES '.$this->dbCharset, $this->linkId);
+			$this->queryId = @mysql_query("SET character_set_results = '".$this->dbCharset."', character_set_client = '".$this->dbCharset."', character_set_connection = '".$this->dbCharset."', character_set_database = '".$this->dbCharset."', character_set_server = '".$this->dbCharset."'", $this->linkId);
 		}
 		return true;
 	}
 
 	public function query($queryString)
-    {
+	{
 		if(!$this->connect()){
 			return false;
 		}
@@ -105,7 +104,7 @@
 
 	/** Returns all records as an array */
 	public function queryAllRecords($queryString)
-    {
+	{
 		if(!$this->query($queryString)){
 			return false;
 		}
@@ -118,7 +117,7 @@
 
 	/** Returns one row as an array */
 	public function queryOneRecord($queryString)
-    {
+	{
 		if(!$this->query($queryString) || $this->numRows() == 0){
 			return false;
 		}
@@ -127,8 +126,8 @@
 
 	/** Returns the next record as an array */
 	public function nextRecord()
-    {
-        $this->record = mysql_fetch_assoc($this->queryId);
+	{
+	$this->record = mysql_fetch_assoc($this->queryId);
 		$this->updateError('DB::nextRecord()<br />mysql_fetch_array');
 		if(!$this->record || !is_array($this->record)){
 			return false;
@@ -150,7 +149,7 @@
 		
 	/** Returns the last mySQL insert_id() */
 	public function insertID()
-    {
+	{
 		return mysql_insert_id($this->linkId);
 	}
         
@@ -160,10 +159,14 @@
         return $this->quote($formfield);
     }
 		
-	/** Escapes quotes in variable. addslashes() */
+	/** Escapes quotes in variable. mysql_real_escape_string() */
     public function quote($formfield)
-    {
-        return addslashes($formfield);
+    {	
+		if(!$this->connect()){
+			$this->updateError('WARNING: mysql_connect: Used addslashes instead of mysql_real_escape_string');
+			return addslashes($formfield);
+		}
+        return mysql_real_escape_string($formfield, $this->linkId);
     }
 		
 	/** Unquotes a variable, strip_slashes() */
@@ -183,7 +186,8 @@
 	    return $out;
 	}
        
-       
+    // deprecated
+	/*
     public function insert($tablename, $form, $debug = 0)
     {
         if(is_array($form)){
@@ -200,7 +204,8 @@
             if($debug == 1){ echo 'mySQL Error Message: '.$this->errorMessage; }
         }
     }
-       
+    
+	// Deprecated
     public function update($tablename, $form, $bedingung, $debug = 0)
     {
 	    if(is_array($form)){
@@ -214,23 +219,181 @@
             if($debug == 1){ echo 'mySQL Error Message: '.$this->errorMessage; }
         }
     }
+	*/
+
+	public function diffrec($record_old, $record_new) {
+		$diffrec_full = array();
+		$diff_num = 0;
+
+		if(is_array($record_old) && count($record_old) > 0) {
+			foreach($record_old as $key => $val) {
+				// if(!isset($record_new[$key]) || $record_new[$key] != $val) {
+				if($record_new[$key] != $val) {
+					// Record has changed
+					$diffrec_full['old'][$key] = $val;
+					$diffrec_full['new'][$key] = $record_new[$key];
+					$diff_num++;
+				} else {
+					$diffrec_full['old'][$key] = $val;
+					$diffrec_full['new'][$key] = $val;
+				}
+			}
+		} elseif(is_array($record_new)) {
+			foreach($record_new as $key => $val) {
+				if(isset($record_new[$key]) && @$record_old[$key] != $val) {
+					// Record has changed
+					$diffrec_full['new'][$key] = $val;
+					$diffrec_full['old'][$key] = @$record_old[$key];
+					$diff_num++;
+				} else {
+					$diffrec_full['new'][$key] = $val;
+					$diffrec_full['old'][$key] = $val;
+				}
+			}
+		}
+		
+		return array('diff_num' => $diff_num, 'diff_rec' => $diffrec_full);
+		
+	}
+	
+	//** Function to fill the datalog with a full differential record.
+	public function datalogSave($db_table, $action, $primary_field, $primary_id, $record_old, $record_new, $force_update = false) {
+		global $app,$conf;
+
+		//* Insert backticks only for incomplete table names.
+		if(stristr($db_table,'.')) {
+			$escape = '';
+		} else {
+			$escape = '`';
+		}
+		
+		if($force_update == true) {
+			//* We force a update even if no record has changed
+			$diffrec_full = array('new' => $record_new, 'old' => $record_old);
+			$diff_num = count($record_new);
+		} else {
+			//* get the difference record between old and new record
+			$tmp = $this->diffrec($record_old, $record_new);
+			$diffrec_full = $tmp['diff_rec'];
+			$diff_num = $tmp['diff_num'];
+			unset($tmp);
+		}
+		
+		//* Insert the server_id, if the record has a server_id
+		$server_id = (isset($record_old['server_id']) && $record_old['server_id'] > 0)?$record_old['server_id']:0;
+		if(isset($record_new['server_id'])) $server_id = $record_new['server_id'];
+		
+
+		if($diff_num > 0) {
+			$diffstr = $app->db->quote(serialize($diffrec_full));
+			$username = $app->db->quote($_SESSION['s']['user']['username']);
+			$dbidx = $primary_field.':'.$primary_id;
+						
+			if($action == 'INSERT') $action = 'i';
+			if($action == 'UPDATE') $action = 'u';
+			if($action == 'DELETE') $action = 'd';
+			$sql = "INSERT INTO sys_datalog (dbtable,dbidx,server_id,action,tstamp,user,data) VALUES ('".$db_table."','$dbidx','$server_id','$action','".time()."','$username','$diffstr')";
+			$app->db->query($sql);
+		}
+
+		return true;
+	}
+	
+	//** Inserts a record and saves the changes into the datalog
+	public function datalogInsert($tablename, $insert_data, $index_field) {
+		global $app;
+		
+		if(is_array($insert_data)) {
+			$key_str = '';
+			$val_str = '';
+			foreach($insert_data as $key => $val) {
+				$key_str .= "`".$key ."`,";
+				$val_str .= "'".$this->quote($val)."',";
+			}
+			$key_str = substr($key_str,0,-1);
+			$val_str = substr($val_str,0,-1);
+			$insert_data_str = '('.$key_str.') VALUES ('.$val_str.')';
+		} else {
+			$insert_data_str = $insert_data;
+		}
+		
+		$old_rec = array();
+		$this->query("INSERT INTO $tablename $insert_data_str");
+		$index_value = $this->insertID();
+		$new_rec = $this->queryOneRecord("SELECT * FROM $tablename WHERE $index_field = '$index_value'");
+		$this->datalogSave($tablename, 'INSERT', $index_field, $index_value, $old_rec, $new_rec);
+		
+		return $index_value;
+	}
+	
+	//** Updates a record and saves the changes into the datalog
+	public function datalogUpdate($tablename, $update_data, $index_field, $index_value, $force_update = false) {
+		global $app;
+		
+		$old_rec = $this->queryOneRecord("SELECT * FROM $tablename WHERE $index_field = '$index_value'");
+		
+		if(is_array($update_data)) {
+			$update_data_str = '';
+			foreach($update_data as $key => $val) {
+				$update_data_str .= "`".$key ."` = '".$this->quote($val)."',";
+			}
+			$update_data_str = substr($update_data_str,0,-1);
+		} else {
+			$update_data_str = $update_data;
+		}
+		
+		$this->query("UPDATE $tablename SET $update_data_str WHERE $index_field = '$index_value'");
+		$new_rec = $this->queryOneRecord("SELECT * FROM $tablename WHERE $index_field = '$index_value'");
+		$this->datalogSave($tablename, 'UPDATE', $index_field, $index_value, $old_rec, $new_rec, $force_update);
+		
+		return true;
+	}
+	
+	//** Deletes a record and saves the changes into the datalog
+	public function datalogDelete($tablename, $index_field, $index_value) {
+		global $app;
+		
+		$old_rec = $this->queryOneRecord("SELECT * FROM $tablename WHERE $index_field = '$index_value'");
+		$this->query("DELETE FROM $tablename WHERE $index_field = '$index_value'");
+		$new_rec = array();
+		$this->datalogSave($tablename, 'DELETE', $index_field, $index_value, $old_rec, $new_rec);
+		
+		return true;
+	}
+
+
        
     public function closeConn()
     {
+    	if($this->linkId)
+    	{
+    		mysql_close($this->linkId);
+    		return true;
+    	} else { return false; }
     }
-       
-    public function freeResult() 
+    
+    public function freeResult($query) 
     {
+    	if(mysql_free_result($query))
+    	{
+    		return true;
+    	} else {
+    		return false;
+    	}
     }
-       
+    
+	/*
     public function delete()
     {
     }
-       
+	*/
+    
+	/*
     public function Transaction($action)
     {
         //action = begin, commit oder rollback
     }
+	*/
     
     /** Creates a database table with the following format for the $columns array   
     * <code>
@@ -245,6 +408,8 @@
     *                  option =>   unique | primary | index)
     * </code>   
     */
+	
+	
     public function createTable($table_name, $columns)
     {
         $index = '';
@@ -252,7 +417,7 @@
         foreach($columns as $col){
             $sql .= $col['name'].' '.$this->mapType($col['type'], $col['typeValue']).' ';
             //* Set default value
-            if($col['defaultValue'] != '') {
+            if(isset($col['defaultValue']) && $col['defaultValue'] != '') {
 			    if($col['defaultValue'] == 'NULL' or $col['defaultValue'] == 'NOT NULL') {
 				    $sql .= 'DEFAULT '.$col['defaultValue'].' ';
 			    } else {
@@ -261,23 +426,23 @@
 		    } elseif($col['defaultValue'] != false) {
 			    $sql .= "DEFAULT '' ";
 		    }
-		    if($col['defaultValue'] != 'NULL' && $col['defaultValue'] != 'NOT NULL') {
+		    if(isset($col['defaultValue']) && $col['defaultValue'] != 'NULL' && $col['defaultValue'] != 'NOT NULL') {
                 if($col['notNull'] == true) {
                     $sql .= 'NOT NULL ';
                 } else {
                     $sql .= 'NULL ';
                 }
 		    }
-            if($col['autoInc'] == true){ $sql .= 'auto_increment '; }
+            if(isset($col['autoInc']) && $col['autoInc'] == true){ $sql .= 'auto_increment '; }
             $sql.= ',';
             //* Index Definitions
-            if($col['option'] == 'primary'){ $index .= 'PRIMARY KEY ('.$col['name'].'),'; }
-            if($col['option'] == 'index'){   $index .= 'INDEX ('.$col['name'].'),'; }
-            if($col['option'] == 'unique'){  $index .= 'UNIQUE ('.$col['name'].'),'; }
-        }
+            if(isset($col['option']) && $col['option'] == 'primary'){ $index .= 'PRIMARY KEY ('.$col['name'].'),'; }
+            if(isset($col['option']) && $col['option'] == 'index'){   $index .= 'INDEX ('.$col['name'].'),'; }
+            if(isset($col['option']) && $col['option'] == 'unique'){  $index .= 'UNIQUE ('.$col['name'].'),'; }
+       }
        $sql .= $index;
        $sql = substr($sql,0,-1);
-       $sql .= ')';  
+       $sql .= ')';
        $this->query($sql);
        return true;
     }
@@ -296,36 +461,36 @@
     */
     public function alterTable($table_name,$columns)
     {
-        $index = '';
-        $sql = "ALTER TABLE $table_name ";
-        foreach($columns as $col){
+       $index = '';
+       $sql = "ALTER TABLE $table_name ";
+       foreach($columns as $col){
             if($col['action'] == 'add'){
-                $sql .= 'ADD '.$col['name'].' '.$this->mapType($col['type'], $col['typeValue']).' ';
+                $sql .= 'ADD '.$col['name'].' '.$this->mapType($col['type'],$col['typeValue']).' ';
             }elseif($col['action'] == 'alter') {
                 $sql .= 'CHANGE '.$col['name'].' '.$col['name_new'].' '.$this->mapType($col['type'],$col['typeValue']).' ';
             }elseif($col['action'] == 'drop') {
                 $sql .= 'DROP '.$col['name'].' ';
             }
-            if($col["action"] != 'drop') {  
-            if($col["defaultValue"] != "") $sql .= "DEFAULT '".$col["defaultValue"]."' ";
-            if($col["notNull"] == true) {
-                $sql .= "NOT NULL ";
+            if($col['action'] != 'drop') {  
+            if($col['defaultValue'] != '') $sql .= "DEFAULT '".$col['defaultValue']."' ";
+            if($col['notNull'] == true) {
+                $sql .= 'NOT NULL ';
             } else {
-                $sql .= "NULL ";
+                $sql .= 'NULL ';
             }
-            if($col["autoInc"] == true) $sql .= "auto_increment ";
-            $sql.= ",";
+            if($col['autoInc'] == true) $sql .= 'auto_increment ';
+            $sql.= ',';
             //* Index definitions
             if($col['option'] == 'primary') $index .= 'PRIMARY KEY ('.$col['name'].'),';
             if($col['option'] == 'index') $index .= 'INDEX ('.$col['name'].'),';
             if($col['option'] == 'unique') $index .= 'UNIQUE ('.$col['name'].'),';
             }
-        }
-        $sql .= $index;
-        $sql = substr($sql,0,-1);
-        //die($sql);
-        $this->query($sql);
-        return true;
+       }
+       $sql .= $index;
+       $sql = substr($sql,0,-1);
+       //die($sql);
+       $this->query($sql);
+       return true;
     }
        
     public function dropTable($table_name) 
@@ -341,26 +506,25 @@
 		if($database_name == ''){
             $database_name = $this->dbName;
         }
-        $result = mysql_list_tables($database_name);
+        $result = @mysql_list_tables($database_name);
         $tb_names = array();
-        for ($i = 0; $i < mysql_num_rows($result); $i++) {
-            $tb_names[$i] = mysql_tablename($result, $i);
+        for ($i = 0; $i < @mysql_num_rows($result); $i++) {
+            $tb_names[$i] = @mysql_tablename($result, $i);
         }
         return $tb_names;       
     }
        
        
     public function tableInfo($table_name) {
-        global $go_api,$go_info;
         //* Tabellenfelder einlesen ?
-        if($rows = $go_api->db->queryAllRecords("SHOW FIELDS FROM $table_name")){
+        if($rows = $this->queryAllRecords('SHOW FIELDS FROM '.$table_name)){
         foreach($rows as $row) {
-            $name    = $row[0];
-            $default = $row[4];
-            $key     = $row[3];
-            $extra   = $row[5];
-            $isnull  = $row[2];
-            $type    = $row[1];
+            $name    = $row['Field'];
+            $default = $row['Default'];
+            $key     = $row['Key'];
+            $extra   = $row['Extra'];
+            $isnull  = $row['Null'];
+            $type    = $row['Type'];
         
             $column = array('name' => $name, 'defaultValue' => $default);
             //$column["type"] = $type;
@@ -381,9 +545,9 @@
                 $tmp_typeValue = explode('(',$type);
                 $column['typeValue'] = substr($tmp_typeValue[1], 0, -1);  
             }
-            if(stristr($type, 'text'))   $metaType = 'text';
-            if(stristr($type, 'double')) $metaType = 'double';
-            if(stristr($type, 'blob'))   $metaType = 'blob';
+            if(stristr($type,'text'))   $metaType = 'text';
+            if(stristr($type,'double')) $metaType = 'double';
+            if(stristr($type,'blob'))   $metaType = 'blob';
             
             $column['type'] = $metaType;
             $columns[] = $column;
@@ -417,7 +581,7 @@
             return 'blob';
         }
     }
-	
+
 }
 
-?>
\ No newline at end of file
+?>

--
Gitblit v1.9.1