]> git.mxchange.org Git - friendica.git/blob - include/dba.php
Merge pull request #526 from zzottel/master
[friendica.git] / include / dba.php
1 <?php
2
3 require_once('include/datetime.php');
4
5 /**
6  *
7  * MySQL database class
8  *
9  * For debugging, insert 'dbg(1);' anywhere in the program flow.
10  * dbg(0); will turn it off. Logging is performed at LOGGER_DATA level.
11  * When logging, all binary info is converted to text and html entities are escaped so that 
12  * the debugging stream is safe to view within both terminals and web pages.
13  *
14  */
15  
16 if(! class_exists('dba')) { 
17 class dba {
18
19         private $debug = 0;
20         private $db;
21         public  $mysqli = true;
22         public  $connected = false;
23         public  $error = false;
24
25         function __construct($server,$user,$pass,$db,$install = false) {
26
27                 $server = trim($server);
28                 $user = trim($user);
29                 $pass = trim($pass);
30                 $db = trim($db);
31
32                 if (!(strlen($server) && strlen($user))){
33                         $this->connected = false;
34                         $this->db = null;
35                         return;
36                 }
37
38                 if($install) {
39                         if(strlen($server) && ($server !== 'localhost') && ($server !== '127.0.0.1')) {
40                                 if(! dns_get_record($server, DNS_A + DNS_CNAME + DNS_PTR)) {
41                                         $this->error = sprintf( t('Cannot locate DNS info for database server \'%s\''), $server);
42                                         $this->connected = false;
43                                         $this->db = null;
44                                         return;
45                                 }
46                         }
47                 }
48
49                 if(class_exists('mysqli')) {
50                         $this->db = @new mysqli($server,$user,$pass,$db);
51                         if(! mysqli_connect_errno()) {
52                                 $this->connected = true;
53                         }
54                 }
55                 else {
56                         $this->mysqli = false;
57                         $this->db = mysql_connect($server,$user,$pass);
58                         if($this->db && mysql_select_db($db,$this->db)) {
59                                 $this->connected = true;
60                         }
61                 }
62                 if(! $this->connected) {
63                         $this->db = null;
64                         if(! $install)
65                                 system_unavailable();
66                 }
67         }
68
69         public function getdb() {
70                 return $this->db;
71         }
72
73         public function q($sql) {
74                 global $a;
75
76                 if((! $this->db) || (! $this->connected))
77                         return false;
78
79                 $this->error = '';
80
81                 if(x($a->config,'system') && x($a->config['system'],'db_log'))
82                         $stamp1 = microtime(true);
83
84                 if($this->mysqli)
85                         $result = @$this->db->query($sql);
86                 else
87                         $result = @mysql_query($sql,$this->db);
88
89                 if(x($a->config,'system') && x($a->config['system'],'db_log')) {
90                         $stamp2 = microtime(true);
91                         $duration = round($stamp2-$stamp1, 3);
92                         if ($duration > $a->config["system"]["db_loglimit"]) {
93                                 $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
94                                 @file_put_contents($a->config["system"]["db_log"], $duration."\t".
95                                                 basename($backtrace[1]["file"])."\t".
96                                                 $backtrace[1]["line"]."\t".$backtrace[2]["function"]."\t".
97                                                 substr($sql, 0, 2000)."\n", FILE_APPEND);
98                         }
99                 }
100
101                 if($this->mysqli) {
102                         if($this->db->errno)
103                                 $this->error = $this->db->error;
104                 }
105                 elseif(mysql_errno($this->db))
106                                 $this->error = mysql_error($this->db);
107
108                 if(strlen($this->error)) {
109                         logger('dba: ' . $this->error);
110                 }
111
112                 if($this->debug) {
113
114                         $mesg = '';
115
116                         if($result === false)
117                                 $mesg = 'false';
118                         elseif($result === true)
119                                 $mesg = 'true';
120                         else {
121                                 if($this->mysqli)
122                                         $mesg = $result->num_rows . ' results' . EOL;
123                         else
124                                         $mesg = mysql_num_rows($result) . ' results' . EOL;
125                         }
126
127                         $str =  'SQL = ' . printable($sql) . EOL . 'SQL returned ' . $mesg
128                                 . (($this->error) ? ' error: ' . $this->error : '')
129                                 . EOL;
130
131                         logger('dba: ' . $str );
132                 }
133
134                 /**
135                  * If dbfail.out exists, we will write any failed calls directly to it,
136                  * regardless of any logging that may or may nor be in effect.
137                  * These usually indicate SQL syntax errors that need to be resolved.
138                  */
139
140                 if($result === false) {
141                         logger('dba: ' . printable($sql) . ' returned false.' . "\n" . $this->error);
142                         if(file_exists('dbfail.out'))
143                                 file_put_contents('dbfail.out', datetime_convert() . "\n" . printable($sql) . ' returned false' . "\n" . $this->error . "\n", FILE_APPEND);
144                 }
145
146                 if(($result === true) || ($result === false))
147                         return $result;
148
149                 $r = array();
150                 if($this->mysqli) {
151                         if($result->num_rows) {
152                                 while($x = $result->fetch_array(MYSQLI_ASSOC))
153                                         $r[] = $x;
154                                 $result->free_result();
155                         }
156                 }
157                 else {
158                         if(mysql_num_rows($result)) {
159                                 while($x = mysql_fetch_array($result, MYSQL_ASSOC))
160                                         $r[] = $x;
161                                 mysql_free_result($result);
162                         }
163                 }
164
165
166                 if($this->debug)
167                         logger('dba: ' . printable(print_r($r, true)));
168                 return($r);
169         }
170
171         public function dbg($dbg) {
172                 $this->debug = $dbg;
173         }
174
175         public function escape($str) {
176                 if($this->db && $this->connected) {
177                         if($this->mysqli)
178                                 return @$this->db->real_escape_string($str);
179                         else
180                                 return @mysql_real_escape_string($str,$this->db);
181                 }
182         }
183
184         function __destruct() {
185                 if ($this->db) 
186                         if($this->mysqli)
187                                 $this->db->close();
188                         else
189                                 mysql_close($this->db);
190         }
191 }}
192
193 if(! function_exists('printable')) {
194 function printable($s) {
195         $s = preg_replace("~([\x01-\x08\x0E-\x0F\x10-\x1F\x7F-\xFF])~",".", $s);
196         $s = str_replace("\x00",'.',$s);
197         if(x($_SERVER,'SERVER_NAME'))
198                 $s = escape_tags($s);
199         return $s;
200 }}
201
202 // Procedural functions
203 if(! function_exists('dbg')) { 
204 function dbg($state) {
205         global $db;
206         if($db)
207         $db->dbg($state);
208 }}
209
210 if(! function_exists('dbesc')) { 
211 function dbesc($str) {
212         global $db;
213         if($db && $db->connected)
214                 return($db->escape($str));
215         else
216                 return(str_replace("'","\\'",$str));
217 }}
218
219
220
221 // Function: q($sql,$args);
222 // Description: execute SQL query with printf style args.
223 // Example: $r = q("SELECT * FROM `%s` WHERE `uid` = %d",
224 //                   'user', 1);
225
226 if(! function_exists('q')) { 
227 function q($sql) {
228
229         global $db;
230         $args = func_get_args();
231         unset($args[0]);
232
233         if($db && $db->connected) {
234                 $stmt = vsprintf($sql,$args);
235                 //logger("dba: q: $stmt", LOGGER_ALL);
236                 if($stmt === false)
237                         logger('dba: vsprintf error: ' . print_r(debug_backtrace(),true), LOGGER_DEBUG);
238                 return $db->q($stmt);
239         }
240
241         /**
242          *
243          * This will happen occasionally trying to store the 
244          * session data after abnormal program termination 
245          *
246          */
247         logger('dba: no database: ' . print_r($args,true));
248         return false; 
249
250 }}
251
252 /**
253  *
254  * Raw db query, no arguments
255  *
256  */
257
258 if(! function_exists('dbq')) { 
259 function dbq($sql) {
260
261         global $db;
262         if($db && $db->connected)
263                 $ret = $db->q($sql);
264         else
265                 $ret = false;
266         return $ret;
267 }}
268
269
270 // Caller is responsible for ensuring that any integer arguments to 
271 // dbesc_array are actually integers and not malformed strings containing
272 // SQL injection vectors. All integer array elements should be specifically 
273 // cast to int to avoid trouble. 
274
275
276 if(! function_exists('dbesc_array_cb')) {
277 function dbesc_array_cb(&$item, $key) {
278         if(is_string($item))
279                 $item = dbesc($item);
280 }}
281
282
283 if(! function_exists('dbesc_array')) {
284 function dbesc_array(&$arr) {
285         if(is_array($arr) && count($arr)) {
286                 array_walk($arr,'dbesc_array_cb');
287         }
288 }}
289
290
291 function dba_timer() {
292         return microtime(true);
293 }
294