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