xaver
2012-01-29 819fd7f2aafd138ed484672a67d72de7640fc856
commit | author | age
b5a2f8 1 <?php
T 2 /*
f5b0ca 3    Copyright (c) 2005, Till Brehm, projektfarm Gmbh
N 4    All rights reserved.
b5a2f8 5
f5b0ca 6    Redistribution and use in source and binary forms, with or without modification,
N 7    are permitted provided that the following conditions are met:
b5a2f8 8
f5b0ca 9  * Redistributions of source code must retain the above copyright notice,
N 10  this list of conditions and the following disclaimer.
11  * Redistributions in binary form must reproduce the above copyright notice,
12  this list of conditions and the following disclaimer in the documentation
13  and/or other materials provided with the distribution.
14  * Neither the name of ISPConfig nor the names of its contributors
15  may be used to endorse or promote products derived from this software without
16  specific prior written permission.
b5a2f8 17
f5b0ca 18  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
N 19  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
22  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
25  OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
27  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
b5a2f8 29
f5b0ca 30 class db extends mysqli
N 31 {
32   private $dbHost = '';        // hostname of the MySQL server
33   private $dbName = '';        // logical database name on that server
34   private $dbUser = '';        // database authorized user
35   private $dbPass = '';        // user's password
36   private $dbCharset = 'utf8';// Database charset
37   private $dbNewLink = false; // Return a new linkID when connect is called again
38   private $dbClientFlags = 0; // MySQL Client falgs
39   private $linkId = 0;        // last result of mysqli_connect()
40   private $queryId = 0;        // last result of mysqli_query()
41   private $record    = array();    // last record fetched
42   private $autoCommit = 1;    // Autocommit Transactions
43   private $currentRow;        // current row number
44   private $errorNumber = 0;    // last error number
45   public $errorMessage = '';    // last error message
46   private $errorLocation = '';// last error location
47   public $show_error_messages = true; // false in server, true in interface
b5a2f8 48
f5b0ca 49   // constructor
N 50   public function __construct() {
51     global $conf;
52     $this->dbHost = $conf['db_host'];
53     $this->dbName = $conf['db_database'];
54     $this->dbUser = $conf['db_user'];
55     $this->dbPass = $conf['db_password'];
56     $this->dbCharset = $conf['db_charset'];
57     $this->dbNewLink = $conf['db_new_link'];
58     $this->dbClientFlags = $conf['db_client_flags'];
59     parent::__construct($conf['db_host'], $conf['db_user'],$conf['db_password'],$conf['db_database']);
60     if ($this->connect_error) {
61       $this->updateError('DB::__construct');
62       return false;
e6c1c4 63     }
f5b0ca 64     parent::query( 'SET NAMES '.$this->dbCharset); 
N 65     parent::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."'");
66
67   }
68
69   public function __destruct() {
70     $this->close(); // helps avoid memory leaks, and persitent connections that don't go away.
71   }
72
73   // error handler
74   public function updateError($location) {
75     global $app;
76
77     if($this->connect_error) {
78       $this->errorNumber = $this->connect_errno;
79       $this->errorMessage = $this->connect_error;
80     } else {
81       $this->errorNumber = $this->errno;
82       $this->errorMessage = $this->error;
e6c1c4 83     }
f5b0ca 84
N 85     $this->errorLocation = $location;
86     if($this->errorNumber) {
87       $error_msg = $this->errorLocation .' '. $this->errorMessage;
88       // This right here will allow us to use the samefile for server & interface
89       if($this->show_error_messages) {
90     echo $error_msg;
91       } else if(method_exists($app, 'log')) {
92     $app->log($error_msg, LOGLEVEL_WARN);
93       }
e6c1c4 94     }
f5b0ca 95   }
N 96
97   public function query($queryString) {
98     $this->queryId = parent::query($queryString);
99     $this->updateError('DB::query('.$queryString.') -> mysqli_query');
100     if(!$this->queryId) {
101       return false;
e6c1c4 102     }
f5b0ca 103     $this->currentRow = 0;
N 104     return $this->queryId;
105   }
106
107   // returns all records in an array
108   public function queryAllRecords($queryString) {
109     if(!$this->query($queryString))
e6c1c4 110     {
f5b0ca 111       return false;
e6c1c4 112     }
f5b0ca 113     $ret = array();
N 114     while($line = $this->nextRecord())
e6c1c4 115     {
f5b0ca 116       $ret[] = $line;
e6c1c4 117     }
f5b0ca 118     return $ret;
N 119   }
120
121   // returns one record in an array
122   public function queryOneRecord($queryString) {
123     if(!$this->query($queryString) || $this->numRows() == 0)
124     {
125       return false;
126     }
127     return $this->nextRecord();
128   }
129
130   // returns the next record in an array
131   public function nextRecord() {
132     $this->record = $this->queryId->fetch_assoc();
133     $this->updateError('DB::nextRecord()-> mysql_fetch_array');
134     if(!$this->record || !is_array($this->record))
135     {
136       return false;
137     }
138     $this->currentRow++;
139     return $this->record;
140   }
141
142   // returns number of rows returned by the last select query
143   public function numRows() {
144     return $this->queryId->num_rows;
145   }
146
147   // returns mySQL insert id
148   public function insertID() {
149     return $this->insert_id;
150   }
151
152
153   // Check der variablen
154   // Really.. using quote should be phased out in favor of using bind_param's.  Though, for legacy code..
155   // here's the equivalent
156   public function quote($formfield) {
157     return $this->escape_string($formfield);
158   }
159
160   // Check der variablen
161   public function unquote($formfield) {
162     return stripslashes($formfield);
163   }
164
165 public function toLower($record) {
166     if(is_array($record)) {
167       foreach($record as $key => $val) {
168     $key = strtolower($key);
169     $out[$key] = $val;
170       }
171     }
172     return $out;
173   }
174
175   /*
176   //* These functions are deprecated and will be removed.
177   function insert($tablename,$form,$debug = 0)
178   {
179   if(is_array($form)){
180   foreach($form as $key => $value) 
181   {
182   $sql_key .= "$key, ";
183   $sql_value .= "'".$this->check($value)."', ";
184   }
185   $sql_key = substr($sql_key,0,strlen($sql_key) - 2);
186   $sql_value = substr($sql_value,0,strlen($sql_value) - 2);
187
188   $sql = "INSERT INTO $tablename (" . $sql_key . ") VALUES (" . $sql_value .")";
189
190   if($debug == 1) echo "SQL-Statement: ".$sql."<br><br>";
191   $this->query($sql);
192   if($debug == 1) echo "mySQL Error Message: ".$this->errorMessage;
193   }
194   }
195
196   function update($tablename,$form,$bedingung,$debug = 0)
197   {
198
199   if(is_array($form)){
200   foreach($form as $key => $value) 
201   {
202   $insql .= "$key = '".$this->check($value)."', ";
203   }
204   $insql = substr($insql,0,strlen($insql) - 2);
205   $sql = "UPDATE $tablename SET " . $insql . " WHERE $bedingung";
206   if($debug == 1) echo "SQL-Statement: ".$sql."<br><br>";
207   $this->query($sql);
208   if($debug == 1) echo "mySQL Error Message: ".$this->errorMessage;
209   }
210   }
211    */
212
213   public function diffrec($record_old, $record_new) {
214     $diffrec_full = array();
215     $diff_num = 0;
216
217     if(is_array($record_old) && count($record_old) > 0) {
218       foreach($record_old as $key => $val) {
219     // if(!isset($record_new[$key]) || $record_new[$key] != $val) {
220     if($record_new[$key] != $val) {
221       // Record has changed
222       $diffrec_full['old'][$key] = $val;
223       $diffrec_full['new'][$key] = $record_new[$key];
224       $diff_num++;
225     } else {
226       $diffrec_full['old'][$key] = $val;
227       $diffrec_full['new'][$key] = $val;
228     }
229       }
230       } elseif(is_array($record_new)) {
231     foreach($record_new as $key => $val) {
232       if(isset($record_new[$key]) && @$record_old[$key] != $val) {
233         // Record has changed
234         $diffrec_full['new'][$key] = $val;
235         $diffrec_full['old'][$key] = @$record_old[$key];
236         $diff_num++;
237       } else {
238         $diffrec_full['new'][$key] = $val;
239         $diffrec_full['old'][$key] = $val;
240       }
241     }
242       }
243
244       return array('diff_num' => $diff_num, 'diff_rec' => $diffrec_full);
245
246     }
247
248     //** Function to fill the datalog with a full differential record.
249     public function datalogSave($db_table, $action, $primary_field, $primary_id, $record_old, $record_new) {
250       global $app,$conf;
251
252       // Insert backticks only for incomplete table names.
253       if(stristr($db_table,'.')) {
254     $escape = '';
255       } else {
256     $escape = '`';
257       }
258
259       $tmp = $this->diffrec($record_old, $record_new);
260       $diffrec_full = $tmp['diff_rec'];
261       $diff_num = $tmp['diff_num'];
262       unset($tmp);
263
264       // Insert the server_id, if the record has a server_id
265       $server_id = (isset($record_old['server_id']) && $record_old['server_id'] > 0)?$record_old['server_id']:0;
266       if(isset($record_new['server_id'])) $server_id = $record_new['server_id'];
267
268
269       if($diff_num > 0) {
270     //print_r($diff_num);
271     //print_r($diffrec_full);
272     $diffstr = $app->db->quote(serialize($diffrec_full));
273     $username = $app->db->quote($_SESSION['s']['user']['username']);
274     $dbidx = $primary_field.':'.$primary_id;
275
276     if($action == 'INSERT') $action = 'i';
277     if($action == 'UPDATE') $action = 'u';
278     if($action == 'DELETE') $action = 'd';
279     $sql = "INSERT INTO sys_datalog (dbtable,dbidx,server_id,action,tstamp,user,data) VALUES ('".$db_table."','$dbidx','$server_id','$action','".time()."','$username','$diffstr')";
280     $app->db->query($sql);
281       }
282
283       return true;
284     }
285
286     //** Inserts a record and saves the changes into the datalog
287     public function datalogInsert($tablename, $insert_data, $index_field) {
288       global $app;
289
290       $old_rec = array();
291       $this->query("INSERT INTO $tablename $insert_data");
292       $index_value = $this->insertID();
293       $new_rec = $this->queryOneRecord("SELECT * FROM $tablename WHERE $index_field = '$index_value'");
294       $this->datalogSave($tablename, 'INSERT', $index_field, $index_value, $old_rec, $new_rec);
295
296       return $index_value;
297     }
298
299     //** Updates a record and saves the changes into the datalog
300     public function datalogUpdate($tablename, $update_data, $index_field, $index_value) {
301       global $app;
302
303       $old_rec = $this->queryOneRecord("SELECT * FROM $tablename WHERE $index_field = '$index_value'");
304       $this->query("UPDATE $tablename SET $update_data WHERE $index_field = '$index_value'");
305       $new_rec = $this->queryOneRecord("SELECT * FROM $tablename WHERE $index_field = '$index_value'");
306       $this->datalogSave($tablename, 'UPDATE', $index_field, $index_value, $old_rec, $new_rec);
307
308       return true;
309     }
310
311     //** Deletes a record and saves the changes into the datalog
312     public function datalogDelete($tablename, $index_field, $index_value) {
313       global $app;
314
315       $old_rec = $this->queryOneRecord("SELECT * FROM $tablename WHERE $index_field = '$index_value'");
316       $this->query("DELETE FROM $tablename WHERE $index_field = '$index_value'");
317       $new_rec = array();
318       $this->datalogSave($tablename, 'DELETE', $index_field, $index_value, $old_rec, $new_rec);
319
320       return true;
321     }
322
323
55da90 324     public function freeResult($query) 
e6c1c4 325     {
f5b0ca 326       if(is_object($query) && (get_class($query) == "mysqli_result")) {
N 327     $query->free();
328     return true;
329       } else {
330     return false;
331       }
e6c1c4 332     }
12fcb2 333
f5b0ca 334     /* TODO: Does anything use this? */
N 335     public function delete() {
b5a2f8 336
f5b0ca 337     }
N 338
339     /* TODO: Does anything use this? */
340     public function Transaction($action) {
341       //action = begin, commit oder rollback
342
343     }
344
345     /*
346        $columns = array(action =>   add | alter | drop
347        name =>     Spaltenname
348        name_new => neuer Spaltenname, nur bei 'alter' belegt
349        type =>     42go-Meta-Type: int16, int32, int64, double, char, varchar, text, blob
350        typeValue => Wert z.B. bei Varchar
351        defaultValue =>  Default Wert
352        notNull =>   true | false
353        autoInc =>   true | false
354        option =>   unique | primary | index)
355
356
357      */
358
359     public function createTable($table_name,$columns) {
360       $index = '';
361       $sql = "CREATE TABLE $table_name (";
362       foreach($columns as $col){
363     $sql .= $col['name'].' '.$this->mapType($col['type'],$col['typeValue']).' ';
364
365     if($col['defaultValue'] != '') $sql .= "DEFAULT '".$col['defaultValue']."' ";
366     if($col['notNull'] == true) {
367       $sql .= 'NOT NULL ';
368     } else {
369       $sql .= 'NULL ';
370     }
371     if($col['autoInc'] == true) $sql .= 'auto_increment ';
372     $sql.= ',';
373     // key Definitionen
374     if($col['option'] == 'primary') $index .= 'PRIMARY KEY ('.$col['name'].'),';
375     if($col['option'] == 'index') $index .= 'INDEX ('.$col['name'].'),';
376     if($col['option'] == 'unique') $index .= 'UNIQUE ('.$col['name'].'),';
377       }
378       $sql .= $index;
379       $sql = substr($sql,0,-1);
380       $sql .= ')';
381       $this->query($sql);
382       return true;
383     }
384
385     /*
386        $columns = array(action =>   add | alter | drop
387        name =>     Spaltenname
388        name_new => neuer Spaltenname, nur bei 'alter' belegt
389        type =>     42go-Meta-Type: int16, int32, int64, double, char, varchar, text, blob
390        typeValue => Wert z.B. bei Varchar
391        defaultValue =>  Default Wert
392        notNull =>   true | false
393        autoInc =>   true | false
394        option =>   unique | primary | index)
395
396
397      */
398     public function alterTable($table_name,$columns) {
399       $index = '';
400       $sql = "ALTER TABLE $table_name ";
401       foreach($columns as $col){
402     if($col['action'] == 'add') {
403       $sql .= 'ADD '.$col['name'].' '.$this->mapType($col['type'],$col['typeValue']).' ';
404     } elseif ($col['action'] == 'alter') {
405       $sql .= 'CHANGE '.$col['name'].' '.$col['name_new'].' '.$this->mapType($col['type'],$col['typeValue']).' ';
406     } elseif ($col['action'] == 'drop') {
407       $sql .= 'DROP '.$col['name'].' ';
408     }
409     if($col['action'] != 'drop') {  
410       if($col['defaultValue'] != '') $sql .= "DEFAULT '".$col['defaultValue']."' ";
411       if($col['notNull'] == true) {
412         $sql .= 'NOT NULL ';
413       } else {
414         $sql .= 'NULL ';
415       }
416       if($col['autoInc'] == true) $sql .= 'auto_increment ';
417       $sql.= ',';
418       // Index definitions
419       if($col['option'] == 'primary') $index .= 'PRIMARY KEY ('.$col['name'].'),';
420       if($col['option'] == 'index') $index .= 'INDEX ('.$col['name'].'),';
421       if($col['option'] == 'unique') $index .= 'UNIQUE ('.$col['name'].'),';
422     }
423       }
424       $sql .= $index;
425       $sql = substr($sql,0,-1);
426
427       //die($sql);
428       $this->query($sql);
429       return true;
430     }
431
432     public function dropTable($table_name) {
433       $this->check($table_name);
434       $sql = "DROP TABLE '". $table_name."'";
435       return $this->query($sql);
436     }
437
438     // gibt Array mit Tabellennamen zur�ck
439     public function getTables($database_name = '') {
440
441       if($database_name == '') $database_name = $this->dbName;
442       $result = parent::query("SHOW TABLES FROM $database_name");
443       for ($i = 0; $i < $result->num_rows; $i++) {
444     $tb_names[$i] = (($result->data_seek( $i) && (($___mysqli_tmp = $result->fetch_row()) !== NULL)) ? array_shift($___mysqli_tmp) : false);
445       }
446       return $tb_names;       
447     }
448
449     // gibt Feldinformationen zur Tabelle zur�ck
450     /*
451        $columns = array(action =>   add | alter | drop
452        name =>     Spaltenname
453        name_new => neuer Spaltenname, nur bei 'alter' belegt
454        type =>     42go-Meta-Type: int16, int32, int64, double, char, varchar, text, blob
455        typeValue => Wert z.B. bei Varchar
456        defaultValue =>  Default Wert
457        notNull =>   true | false
458        autoInc =>   true | false
459        option =>   unique | primary | index)
460
461
462      */
463
464     function tableInfo($table_name) {
465
466       global $go_api,$go_info;
467       // Tabellenfelder einlesen
468
469       if($rows = $go_api->db->queryAllRecords('SHOW FIELDS FROM '.$table_name)){
470     foreach($rows as $row) {
471       $name = $row[0];
472       $default = $row[4];
473       $key = $row[3];
474       $extra = $row[5];
475       $isnull = $row[2];
476       $type = $row[1];
477
478
479       $column = array();
480
481       $column['name'] = $name;
482       //$column['type'] = $type;
483       $column['defaultValue'] = $default;
484       if(stristr($key,'PRI')) $column['option'] = 'primary';
485       if(stristr($isnull,'YES')) {
486         $column['notNull'] = false;
487       } else {
488         $column['notNull'] = true; 
489       }
490       if($extra == 'auto_increment') $column['autoInc'] = true;
491
492
493       // Type in Metatype umsetzen
494
495       if(stristr($type,'int(')) $metaType = 'int32';
496           if(stristr($type,'bigint')) $metaType = 'int64';
497           if(stristr($type,'char')) {
498           $metaType = 'char';
499           $tmp_typeValue = explode('(',$type);
500           $column['typeValue'] = substr($tmp_typeValue[1],0,-1);  
501           }
502           if(stristr($type,'varchar')) {
503           $metaType = 'varchar';
504           $tmp_typeValue = explode('(',$type);
505           $column['typeValue'] = substr($tmp_typeValue[1],0,-1);  
506           }
507           if(stristr($type,'text')) $metaType = 'text';
508           if(stristr($type,'double')) $metaType = 'double';
509           if(stristr($type,'blob')) $metaType = 'blob';
510
511
512           $column['type'] = $metaType;
513
514           $columns[] = $column;
515           }
516     return $columns;
517       } else {
518     return false;
519       }
520
521
522       //$this->createTable('tester',$columns);
523
524       /*
525      $result = mysql_list_fields($go_info["server"]["db_name"],$table_name);
526      $fields = mysql_num_fields ($result);
527      $i = 0;
528      $table = mysql_field_table ($result, $i);
529      while ($i < $fields) {
530      $name  = mysql_field_name  ($result, $i);
531      $type  = mysql_field_type  ($result, $i);
532      $len   = mysql_field_len   ($result, $i);
533      $flags = mysql_field_flags ($result, $i);
534      print_r($flags);
535
536      $columns = array(name => $name,
537      type =>     "",
538      defaultValue =>  "",
539      isnull =>   1,
540      option =>   "");
541      $returnvar[] = $columns;
542
543      $i++;
544      }
545        */
546
547
548
549     }
550
551     public function mapType($metaType,$typeValue) {
552       global $go_api;
553       $metaType = strtolower($metaType);
554       switch ($metaType) {
555     case 'int16':
556       return 'smallint';
557       break;
558     case 'int32':
559       return 'int';
560       break;
561     case 'int64':
562       return 'bigint';
563       break;
564     case 'double':
565       return 'double';
566       break;
567     case 'char':
568       return 'char';
569       break;
570     case 'varchar':
571       if($typeValue < 1) die('Database failure: Lenght required for these data types.');
572       return 'varchar('.$typeValue.')';
573           break;
574           case 'text':
575           return 'text';
576           break;
577           case 'blob':
578           return 'blob';
579           break;
580           }
581           }
582
583           }
584
819fd7 585           ?>