Till Brehm
2014-10-27 0e34bade9cc2fa831f9c8a344b2ebfdf4047848c
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 {
7fe908 32     private $dbHost = '';  // hostname of the MySQL server
MC 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 = false; // false in server, true in interface
48     private $isConnected = false; // needed to know if we have a valid mysqli object from the constructor
b5a2f8 49
7fe908 50     // constructor
MC 51     public function __construct($prefix = '') {
52         global $conf;
53         if($prefix != '') $prefix .= '_';
54         $this->dbHost = $conf[$prefix.'db_host'];
55         $this->dbName = $conf[$prefix.'db_database'];
56         $this->dbUser = $conf[$prefix.'db_user'];
57         $this->dbPass = $conf[$prefix.'db_password'];
58         $this->dbCharset = $conf[$prefix.'db_charset'];
59         $this->dbNewLink = $conf[$prefix.'db_new_link'];
60         $this->dbClientFlags = $conf[$prefix.'db_client_flags'];
61         parent::__construct($conf[$prefix.'db_host'], $conf[$prefix.'db_user'], $conf[$prefix.'db_password'], $conf[$prefix.'db_database']);
62         $try = 0;
63         //while(!is_null($this->connect_error) && $try < 5) {
64         while(mysqli_connect_error() && $try < 5) {
65             if($try > 0) sleep(1);
f5b0ca 66
7fe908 67             $try++;
MC 68             $this->updateError('DB::__construct');
f5b0ca 69
7fe908 70             parent::__construct($conf[$prefix.'db_host'], $conf[$prefix.'db_user'], $conf[$prefix.'db_password'], $conf[$prefix.'db_database']);
MC 71         }
f5b0ca 72
7fe908 73         //if(is_null($this->connect_error)) $this->isConnected = true;
MC 74         //else return false;
75         if(!mysqli_connect_error()) $this->isConnected = true;
76         else return false;
77
78         $this->setCharacterEncoding();
79     }
80
81     public function __destruct() {
82         $this->close(); // helps avoid memory leaks, and persitent connections that don't go away.
83     }
84
85     // error handler
86     public function updateError($location) {
87         global $app, $conf;
88
89         /*
72695f 90     if(!is_null($this->connect_error)) {
f5b0ca 91       $this->errorNumber = $this->connect_errno;
N 92       $this->errorMessage = $this->connect_error;
93     } else {
94       $this->errorNumber = $this->errno;
95       $this->errorMessage = $this->error;
e6c1c4 96     }
cc6568 97     */
7fe908 98         if(mysqli_connect_error()) {
MC 99             $this->errorNumber = mysqli_connect_errno();
100             $this->errorMessage = mysqli_connect_error();
101         } else {
102             $this->errorNumber = mysqli_errno($this);
103             $this->errorMessage = mysqli_error($this);
104         }
cc6568 105
f5b0ca 106
7fe908 107         $this->errorLocation = $location;
MC 108         if($this->errorNumber) {
109             $error_msg = $this->errorLocation .' '. $this->errorMessage;
110             // This right here will allow us to use the same file for server & interface
111             if($this->show_error_messages && $conf['demo_mode'] === false) {
112                 echo $error_msg;
113             } else if(is_object($app) && method_exists($app, 'log')) {
114                     $app->log($error_msg, LOGLEVEL_WARN);
115                 }
116         }
f5b0ca 117     }
7fe908 118
MC 119     private function setCharacterEncoding() {
120         if($this->isConnected == false) return false;
121         parent::query( 'SET NAMES '.$this->dbCharset);
122         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."'");
f5b0ca 123     }
cb1221 124     
TB 125     private function securityScan($string) {
126         global $app, $conf;
127         
128         // get security config
129         if(isset($app)) {
130             $app->uses('getconf');
131             $ids_config = $app->getconf->get_security_config('ids');
132             
133             if($ids_config['sql_scan_enabled'] == 'yes') {
134                 
0e34ba 135                 // Remove whitespace
TB 136                 $string = trim($string);
137                 if(substr($string,-1) == ';') $string = substr($string,0,-1);
138                 
139                 // Save original string
cb1221 140                 $string_orig = $string;
TB 141                 
142                 //echo $string;
68b146 143                 $chars = array(';', '#', '/*', '*/', '--', '\\\'', '\\"');
cb1221 144         
TB 145                 $string = str_replace('\\\\', '', $string);
f986a3 146                 $string = preg_replace('/(^|[^\\\])([\'"])\\2/is', '$1', $string);
MC 147                 $string = preg_replace('/(^|[^\\\])([\'"])(.*?[^\\\])\\2/is', '$1', $string);
cb1221 148                 $ok = true;
TB 149
150                 if(substr_count($string, "`") % 2 != 0 || substr_count($string, "'") % 2 != 0 || substr_count($string, '"') % 2 != 0) {
151                     $app->log("SQL injection warning (" . $string_orig . ")",2);
152                     $ok = false;
153                 } else {
154                     foreach($chars as $char) {
155                         if(strpos($string, $char) !== false) {
156                             $ok = false;
157                             $app->log("SQL injection warning (" . $string_orig . ")",2);
158                             break;
159                         }
160                     }
161                 }
162                 if($ok == true) {
163                     return true;
164                 } else {
165                     if($ids_config['sql_scan_action'] == 'warn') {
166                         // we return false in warning level.
167                         return false;
168                     } else {
169                         // if sql action = 'block' or anything else then stop here.
170                         $app->error('Possible SQL injection. All actions have been logged.');
171                     }
172                 }
173             }
174         }
175     }
f5b0ca 176
7fe908 177     public function query($queryString) {
MC 178         global $conf;
179         if($this->isConnected == false) return false;
180         $try = 0;
181         do {
182             $try++;
183             $ok = $this->ping();
184             if(!$ok) {
185                 if(!$this->real_connect($this->dbHost, $this->dbUser, $this->dbPass, $this->dbName)) {
186                     if($try > 4) {
187                         $this->updateError('DB::query -> reconnect');
188                         return false;
189                     } else {
190                         sleep(1);
191                     }
192                 } else {
193                     $this->setCharacterEncoding();
194                     $ok = true;
195                 }
196             }
197         } while($ok == false);
cb1221 198         $this->securityScan($queryString);
7fe908 199         $this->queryId = parent::query($queryString);
MC 200         $this->updateError('DB::query('.$queryString.') -> mysqli_query');
201         if($this->errorNumber && $conf['demo_mode'] === false) debug_print_backtrace();
202         if(!$this->queryId) {
203             return false;
204         }
205         $this->currentRow = 0;
206         return $this->queryId;
207     }
f5b0ca 208
7fe908 209     // returns all records in an array
MC 210     public function queryAllRecords($queryString) {
211         if(!$this->query($queryString))
212         {
213             return false;
214         }
215         $ret = array();
216         while($line = $this->nextRecord())
217         {
218             $ret[] = $line;
219         }
220         return $ret;
221     }
f5b0ca 222
7fe908 223     // returns one record in an array
MC 224     public function queryOneRecord($queryString) {
225         if(!$this->query($queryString) || $this->numRows() == 0)
226         {
227             return false;
228         }
229         return $this->nextRecord();
230     }
f5b0ca 231
7fe908 232     // returns the next record in an array
MC 233     public function nextRecord() {
234         $this->record = $this->queryId->fetch_assoc();
235         $this->updateError('DB::nextRecord()-> mysql_fetch_array');
236         if(!$this->record || !is_array($this->record))
237         {
238             return false;
239         }
240         $this->currentRow++;
241         return $this->record;
242     }
243
244     // returns number of rows returned by the last select query
245     public function numRows() {
246         return intval($this->queryId->num_rows);
247     }
248
249     public function affectedRows() {
250         return intval($this->queryId->affected_rows);
251     }
252
253     // returns mySQL insert id
254     public function insertID() {
255         return $this->insert_id;
256     }
257
258
259     //* Function to quote strings
260     public function quote($formfield) {
261         return $this->escape_string($formfield);
262     }
263
264     //* Function to unquotae strings
265     public function unquote($formfield) {
266         return stripslashes($formfield);
267     }
268
269     public function toLower($record) {
270         if(is_array($record)) {
271             foreach($record as $key => $val) {
272                 $key = strtolower($key);
273                 $out[$key] = $val;
274             }
275         }
276         return $out;
277     }
278
279     public function diffrec($record_old, $record_new) {
280         $diffrec_full = array();
281         $diff_num = 0;
282
283         if(is_array($record_old) && count($record_old) > 0) {
284             foreach($record_old as $key => $val) {
285                 // if(!isset($record_new[$key]) || $record_new[$key] != $val) {
286                 if(@$record_new[$key] != $val) {
287                     // Record has changed
288                     $diffrec_full['old'][$key] = $val;
289                     $diffrec_full['new'][$key] = @$record_new[$key];
290                     $diff_num++;
291                 } else {
292                     $diffrec_full['old'][$key] = $val;
293                     $diffrec_full['new'][$key] = $val;
294                 }
295             }
296         } elseif(is_array($record_new)) {
297             foreach($record_new as $key => $val) {
298                 if(isset($record_new[$key]) && @$record_old[$key] != $val) {
299                     // Record has changed
300                     $diffrec_full['new'][$key] = $val;
301                     $diffrec_full['old'][$key] = @$record_old[$key];
302                     $diff_num++;
303                 } else {
304                     $diffrec_full['new'][$key] = $val;
305                     $diffrec_full['old'][$key] = $val;
306                 }
307             }
308         }
309
310         return array('diff_num' => $diff_num, 'diff_rec' => $diffrec_full);
311
312     }
313
314     //** Function to fill the datalog with a full differential record.
315     public function datalogSave($db_table, $action, $primary_field, $primary_id, $record_old, $record_new, $force_update = false) {
316         global $app, $conf;
317
94b44c 318         // Check fields
7272e4 319         if(!preg_match('/^[a-zA-Z0-9\-\_\.]{1,64}$/',$db_table)) $app->error('Invalid table name '.$db_table);
cd48c7 320         if(!preg_match('/^[a-zA-Z0-9\-\_]{1,64}$/',$primary_field)) $app->error('Invalid primary field '.$primary_field.' in table '.$db_table);
94b44c 321         
TB 322         $primary_field = $this->quote($primary_field);
323         $primary_id = intval($primary_id);
f5b0ca 324
b0eb45 325         if($force_update == true) {
T 326             //* We force a update even if no record has changed
7fe908 327             $diffrec_full = array('new' => $record_new, 'old' => $record_old);
b0eb45 328             $diff_num = count($record_new);
T 329         } else {
330             //* get the difference record between old and new record
331             $tmp = $this->diffrec($record_old, $record_new);
332             $diffrec_full = $tmp['diff_rec'];
333             $diff_num = $tmp['diff_num'];
334             unset($tmp);
335         }
f5b0ca 336
7fe908 337         // Insert the server_id, if the record has a server_id
MC 338         $server_id = (isset($record_old['server_id']) && $record_old['server_id'] > 0)?$record_old['server_id']:0;
339         if(isset($record_new['server_id'])) $server_id = $record_new['server_id'];
e9a57d 340         $server_id = intval($server_id);
f5b0ca 341
7fe908 342         if($diff_num > 0) {
MC 343             //print_r($diff_num);
344             //print_r($diffrec_full);
345             $diffstr = $app->db->quote(serialize($diffrec_full));
346             $username = $app->db->quote($_SESSION['s']['user']['username']);
347             $dbidx = $primary_field.':'.$primary_id;
f5b0ca 348
7fe908 349             if($action == 'INSERT') $action = 'i';
MC 350             if($action == 'UPDATE') $action = 'u';
351             if($action == 'DELETE') $action = 'd';
352             $sql = "INSERT INTO sys_datalog (dbtable,dbidx,server_id,action,tstamp,user,data) VALUES ('".$db_table."','$dbidx','$server_id','$action','".time()."','$username','$diffstr')";
353             $app->db->query($sql);
354         }
f5b0ca 355
7fe908 356         return true;
MC 357     }
f5b0ca 358
7fe908 359     //** Inserts a record and saves the changes into the datalog
MC 360     public function datalogInsert($tablename, $insert_data, $index_field) {
361         global $app;
e9a57d 362         
94b44c 363         // Check fields
7272e4 364         if(!preg_match('/^[a-zA-Z0-9\-\_\.]{1,64}$/',$tablename)) $app->error('Invalid table name '.$tablename);
cd48c7 365         if(!preg_match('/^[a-zA-Z0-9\-\_]{1,64}$/',$index_field)) $app->error('Invalid index field '.$index_field.' in table '.$tablename);
94b44c 366         
TB 367         if(strpos($tablename, '.') !== false) {
7272e4 368             $tablename_escaped = preg_replace('/^(.+)\.(.+)$/', '`$1`.`$2`', $tablename);
94b44c 369         } else {
7272e4 370             $tablename_escaped = '`' . $tablename . '`';
94b44c 371         }
TB 372         
e9a57d 373         $index_field = $this->quote($index_field);
7fe908 374
MC 375         if(is_array($insert_data)) {
ee260d 376             $key_str = '';
T 377             $val_str = '';
378             foreach($insert_data as $key => $val) {
379                 $key_str .= "`".$key ."`,";
380                 $val_str .= "'".$this->quote($val)."',";
381             }
7fe908 382             $key_str = substr($key_str, 0, -1);
MC 383             $val_str = substr($val_str, 0, -1);
ee260d 384             $insert_data_str = '('.$key_str.') VALUES ('.$val_str.')';
T 385         } else {
386             $insert_data_str = $insert_data;
387         }
f5b0ca 388
7fe908 389         $old_rec = array();
7272e4 390         $this->query("INSERT INTO $tablename_escaped $insert_data_str");
7fe908 391         $index_value = $this->insertID();
7272e4 392         $new_rec = $this->queryOneRecord("SELECT * FROM $tablename_escaped WHERE $index_field = '$index_value'");
7fe908 393         $this->datalogSave($tablename, 'INSERT', $index_field, $index_value, $old_rec, $new_rec);
f5b0ca 394
7fe908 395         return $index_value;
MC 396     }
f5b0ca 397
7fe908 398     //** Updates a record and saves the changes into the datalog
MC 399     public function datalogUpdate($tablename, $update_data, $index_field, $index_value, $force_update = false) {
ee260d 400         global $app;
e9a57d 401         
94b44c 402         // Check fields
7272e4 403         if(!preg_match('/^[a-zA-Z0-9\-\_\.]{1,64}$/',$tablename)) $app->error('Invalid table name '.$tablename);
cd48c7 404         if(!preg_match('/^[a-zA-Z0-9\-\_]{1,64}$/',$index_field)) $app->error('Invalid index field '.$index_field.' in table '.$tablename);
94b44c 405         
TB 406         if(strpos($tablename, '.') !== false) {
7272e4 407             $tablename_escaped = preg_replace('/^(.+)\.(.+)$/', '`$1`.`$2`', $tablename);
94b44c 408         } else {
7272e4 409             $tablename_escaped = '`' . $tablename . '`';
94b44c 410         }
TB 411         
e9a57d 412         $index_field = $this->quote($index_field);
TB 413         $index_value = $this->quote($index_value);
7fe908 414
7272e4 415         $old_rec = $this->queryOneRecord("SELECT * FROM $tablename_escaped WHERE $index_field = '$index_value'");
7fe908 416
MC 417         if(is_array($update_data)) {
ee260d 418             $update_data_str = '';
T 419             foreach($update_data as $key => $val) {
420                 $update_data_str .= "`".$key ."` = '".$this->quote($val)."',";
421             }
7fe908 422             $update_data_str = substr($update_data_str, 0, -1);
ee260d 423         } else {
T 424             $update_data_str = $update_data;
425         }
f5b0ca 426
7272e4 427         $this->query("UPDATE $tablename_escaped SET $update_data_str WHERE $index_field = '$index_value'");
TB 428         $new_rec = $this->queryOneRecord("SELECT * FROM $tablename_escaped WHERE $index_field = '$index_value'");
7fe908 429         $this->datalogSave($tablename, 'UPDATE', $index_field, $index_value, $old_rec, $new_rec, $force_update);
f5b0ca 430
7fe908 431         return true;
MC 432     }
f5b0ca 433
7fe908 434     //** Deletes a record and saves the changes into the datalog
MC 435     public function datalogDelete($tablename, $index_field, $index_value) {
436         global $app;
e9a57d 437         
94b44c 438         // Check fields
7272e4 439         if(!preg_match('/^[a-zA-Z0-9\-\_\.]{1,64}$/',$tablename)) $app->error('Invalid table name '.$tablename);
cd48c7 440         if(!preg_match('/^[a-zA-Z0-9\-\_]{1,64}$/',$index_field)) $app->error('Invalid index field '.$index_field.' in table '.$tablename);
94b44c 441         
TB 442         if(strpos($tablename, '.') !== false) {
7272e4 443             $tablename_escaped = preg_replace('/^(.+)\.(.+)$/', '`$1`.`$2`', $tablename);
94b44c 444         } else {
7272e4 445             $tablename_escaped = '`' . $tablename . '`';
94b44c 446         }
TB 447         
e9a57d 448         $index_field = $this->quote($index_field);
TB 449         $index_value = $this->quote($index_value);
f5b0ca 450
7272e4 451         $old_rec = $this->queryOneRecord("SELECT * FROM $tablename_escaped WHERE $index_field = '$index_value'");
TB 452         $this->query("DELETE FROM $tablename_escaped WHERE $index_field = '$index_value'");
7fe908 453         $new_rec = array();
MC 454         $this->datalogSave($tablename, 'DELETE', $index_field, $index_value, $old_rec, $new_rec);
455
456         return true;
457     }
458
459     //* get the current datalog status for the specified login (or currently logged in user)
460     public function datalogStatus($login = '') {
461         global $app;
462
463         $return = array('count' => 0, 'entries' => array());
464         if($_SESSION['s']['user']['typ'] == 'admin') return $return; // these information should not be displayed to admin users
465
466         if($login == '' && isset($_SESSION['s']['user'])) {
467             $login = $_SESSION['s']['user']['username'];
468         }
469
470         $result = $this->queryAllRecords("SELECT COUNT( * ) AS cnt, sys_datalog.action, sys_datalog.dbtable FROM sys_datalog, server WHERE server.server_id = sys_datalog.server_id AND sys_datalog.user = '" . $this->quote($login) . "' AND sys_datalog.datalog_id > server.updated GROUP BY sys_datalog.dbtable, sys_datalog.action");
471         foreach($result as $row) {
472             if(!$row['dbtable'] || in_array($row['dbtable'], array('aps_instances', 'aps_instances_settings', 'mail_access', 'mail_content_filter'))) continue; // ignore some entries, maybe more to come
473             $return['entries'][] = array('table' => $row['dbtable'], 'action' => $row['action'], 'count' => $row['cnt'], 'text' => $app->lng('datalog_status_' . $row['action'] . '_' . $row['dbtable']));
474             $return['count'] += $row['cnt'];
475         }
476         unset($result);
477
478         return $return;
479     }
f5b0ca 480
N 481
7fe908 482     public function freeResult($query)
MC 483     {
484         if(is_object($query) && (get_class($query) == "mysqli_result")) {
485             $query->free();
486             return true;
487         } else {
488             return false;
489         }
490     }
12fcb2 491
7fe908 492     /* TODO: Does anything use this? */
MC 493     public function delete() {
b5a2f8 494
7fe908 495     }
f5b0ca 496
7fe908 497     /* TODO: Does anything use this? */
MC 498     public function Transaction($action) {
499         //action = begin, commit oder rollback
f5b0ca 500
7fe908 501     }
f5b0ca 502
7fe908 503     /*
f5b0ca 504        $columns = array(action =>   add | alter | drop
N 505        name =>     Spaltenname
506        name_new => neuer Spaltenname, nur bei 'alter' belegt
507        type =>     42go-Meta-Type: int16, int32, int64, double, char, varchar, text, blob
508        typeValue => Wert z.B. bei Varchar
509        defaultValue =>  Default Wert
510        notNull =>   true | false
511        autoInc =>   true | false
512        option =>   unique | primary | index)
513
514
515      */
516
7fe908 517     public function createTable($table_name, $columns) {
MC 518         $index = '';
519         $sql = "CREATE TABLE $table_name (";
520         foreach($columns as $col){
521             $sql .= $col['name'].' '.$this->mapType($col['type'], $col['typeValue']).' ';
f5b0ca 522
7fe908 523             if($col['defaultValue'] != '') $sql .= "DEFAULT '".$col['defaultValue']."' ";
MC 524             if($col['notNull'] == true) {
525                 $sql .= 'NOT NULL ';
526             } else {
527                 $sql .= 'NULL ';
528             }
529             if($col['autoInc'] == true) $sql .= 'auto_increment ';
530             $sql.= ',';
531             // key Definitionen
532             if($col['option'] == 'primary') $index .= 'PRIMARY KEY ('.$col['name'].'),';
533             if($col['option'] == 'index') $index .= 'INDEX ('.$col['name'].'),';
534             if($col['option'] == 'unique') $index .= 'UNIQUE ('.$col['name'].'),';
535         }
536         $sql .= $index;
537         $sql = substr($sql, 0, -1);
538         $sql .= ')';
539         $this->query($sql);
540         return true;
f5b0ca 541     }
N 542
7fe908 543     /*
f5b0ca 544        $columns = array(action =>   add | alter | drop
N 545        name =>     Spaltenname
546        name_new => neuer Spaltenname, nur bei 'alter' belegt
547        type =>     42go-Meta-Type: int16, int32, int64, double, char, varchar, text, blob
548        typeValue => Wert z.B. bei Varchar
549        defaultValue =>  Default Wert
550        notNull =>   true | false
551        autoInc =>   true | false
552        option =>   unique | primary | index)
553
554
555      */
7fe908 556     public function alterTable($table_name, $columns) {
MC 557         $index = '';
558         $sql = "ALTER TABLE $table_name ";
559         foreach($columns as $col){
560             if($col['action'] == 'add') {
561                 $sql .= 'ADD '.$col['name'].' '.$this->mapType($col['type'], $col['typeValue']).' ';
562             } elseif ($col['action'] == 'alter') {
563                 $sql .= 'CHANGE '.$col['name'].' '.$col['name_new'].' '.$this->mapType($col['type'], $col['typeValue']).' ';
564             } elseif ($col['action'] == 'drop') {
565                 $sql .= 'DROP '.$col['name'].' ';
566             }
567             if($col['action'] != 'drop') {
568                 if($col['defaultValue'] != '') $sql .= "DEFAULT '".$col['defaultValue']."' ";
569                 if($col['notNull'] == true) {
570                     $sql .= 'NOT NULL ';
571                 } else {
572                     $sql .= 'NULL ';
573                 }
574                 if($col['autoInc'] == true) $sql .= 'auto_increment ';
575                 $sql.= ',';
576                 // Index definitions
577                 if($col['option'] == 'primary') $index .= 'PRIMARY KEY ('.$col['name'].'),';
578                 if($col['option'] == 'index') $index .= 'INDEX ('.$col['name'].'),';
579                 if($col['option'] == 'unique') $index .= 'UNIQUE ('.$col['name'].'),';
580             }
581         }
582         $sql .= $index;
583         $sql = substr($sql, 0, -1);
584
585         //die($sql);
586         $this->query($sql);
587         return true;
f5b0ca 588     }
7fe908 589
MC 590     public function dropTable($table_name) {
591         $this->check($table_name);
592         $sql = "DROP TABLE '". $table_name."'";
593         return $this->query($sql);
f5b0ca 594     }
N 595
7fe908 596     // gibt Array mit Tabellennamen zur�ck
MC 597     public function getTables($database_name = '') {
598         if($this->isConnected == false) return false;
599         if($database_name == '') $database_name = $this->dbName;
600         $result = parent::query("SHOW TABLES FROM $database_name");
601         for ($i = 0; $i < $result->num_rows; $i++) {
602             $tb_names[$i] = (($result->data_seek( $i) && (($___mysqli_tmp = $result->fetch_row()) !== NULL)) ? array_shift($___mysqli_tmp) : false);
603         }
604         return $tb_names;
605     }
f5b0ca 606
7fe908 607     // gibt Feldinformationen zur Tabelle zur�ck
MC 608     /*
f5b0ca 609        $columns = array(action =>   add | alter | drop
N 610        name =>     Spaltenname
611        name_new => neuer Spaltenname, nur bei 'alter' belegt
612        type =>     42go-Meta-Type: int16, int32, int64, double, char, varchar, text, blob
613        typeValue => Wert z.B. bei Varchar
614        defaultValue =>  Default Wert
615        notNull =>   true | false
616        autoInc =>   true | false
617        option =>   unique | primary | index)
618
619
620      */
621
7fe908 622     function tableInfo($table_name) {
f5b0ca 623
7fe908 624         global $go_api, $go_info, $app;
MC 625         // Tabellenfelder einlesen
f5b0ca 626
7fe908 627         if($rows = $app->db->queryAllRecords('SHOW FIELDS FROM '.$table_name)){
MC 628             foreach($rows as $row) {
629                 /*
f5b0ca 630       $name = $row[0];
N 631       $default = $row[4];
632       $key = $row[3];
633       $extra = $row[5];
634       $isnull = $row[2];
635       $type = $row[1];
bfcdef 636       */
7fe908 637
MC 638                 $name = $row['Field'];
639                 $default = $row['Default'];
640                 $key = $row['Key'];
641                 $extra = $row['Extra'];
642                 $isnull = $row['Null'];
643                 $type = $row['Type'];
f5b0ca 644
N 645
7fe908 646                 $column = array();
f5b0ca 647
7fe908 648                 $column['name'] = $name;
MC 649                 //$column['type'] = $type;
650                 $column['defaultValue'] = $default;
651                 if(stristr($key, 'PRI')) $column['option'] = 'primary';
652                 if(stristr($isnull, 'YES')) {
653                     $column['notNull'] = false;
654                 } else {
655                     $column['notNull'] = true;
656                 }
657                 if($extra == 'auto_increment') $column['autoInc'] = true;
f5b0ca 658
N 659
7fe908 660                 // Type in Metatype umsetzen
f5b0ca 661
7fe908 662                 if(stristr($type, 'int(')) $metaType = 'int32';
MC 663                 if(stristr($type, 'bigint')) $metaType = 'int64';
664                 if(stristr($type, 'char')) {
665                     $metaType = 'char';
666                     $tmp_typeValue = explode('(', $type);
667                     $column['typeValue'] = substr($tmp_typeValue[1], 0, -1);
668                 }
669                 if(stristr($type, 'varchar')) {
670                     $metaType = 'varchar';
671                     $tmp_typeValue = explode('(', $type);
672                     $column['typeValue'] = substr($tmp_typeValue[1], 0, -1);
673                 }
674                 if(stristr($type, 'text')) $metaType = 'text';
675                 if(stristr($type, 'double')) $metaType = 'double';
676                 if(stristr($type, 'blob')) $metaType = 'blob';
f5b0ca 677
N 678
7fe908 679                 $column['type'] = $metaType;
f5b0ca 680
7fe908 681                 $columns[] = $column;
MC 682             }
683             return $columns;
684         } else {
685             return false;
686         }
f5b0ca 687
N 688
7fe908 689         //$this->createTable('tester',$columns);
f5b0ca 690
7fe908 691         /*
f5b0ca 692      $result = mysql_list_fields($go_info["server"]["db_name"],$table_name);
N 693      $fields = mysql_num_fields ($result);
694      $i = 0;
695      $table = mysql_field_table ($result, $i);
696      while ($i < $fields) {
697      $name  = mysql_field_name  ($result, $i);
698      $type  = mysql_field_type  ($result, $i);
699      $len   = mysql_field_len   ($result, $i);
700      $flags = mysql_field_flags ($result, $i);
701      print_r($flags);
702
703      $columns = array(name => $name,
704      type =>     "",
705      defaultValue =>  "",
706      isnull =>   1,
707      option =>   "");
708      $returnvar[] = $columns;
709
710      $i++;
711      }
712        */
713
714
715
7fe908 716     }
f5b0ca 717
7fe908 718     public function mapType($metaType, $typeValue) {
MC 719         global $go_api;
720         $metaType = strtolower($metaType);
721         switch ($metaType) {
722         case 'int16':
723             return 'smallint';
724             break;
725         case 'int32':
726             return 'int';
727             break;
728         case 'int64':
729             return 'bigint';
730             break;
731         case 'double':
732             return 'double';
733             break;
734         case 'char':
735             return 'char';
736             break;
737         case 'varchar':
738             if($typeValue < 1) die('Database failure: Lenght required for these data types.');
739             return 'varchar('.$typeValue.')';
740             break;
741         case 'text':
742             return 'text';
743             break;
744         case 'blob':
745             return 'blob';
746             break;
8748b3 747         case 'date':
TB 748             return 'date';
749             break;
7fe908 750         }
MC 751     }
f5b0ca 752
7fe908 753 }
f5b0ca 754
7fe908 755 ?>