]> git.mxchange.org Git - friendica.git/blob - include/dba.php
diabook-themes: small fix
[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
12  * text and html entities are escaped so that
13  * the debugging stream is safe to view
14  * within both terminals and web pages.
15  *
16  */
17
18 if(! class_exists('dba')) {
19
20         class dba {
21
22                 private $debug = 0;
23                 private $db;
24                 private $exceptions; 
25                 
26                 public  $mysqli = true;
27                 public  $connected = false;
28                 public  $error = false;
29
30                 function __construct($server,$user,$pass,$db,$install = false) {
31
32                         $server = trim($server);
33                         $user = trim($user);
34                         $pass = trim($pass);
35                         $db = trim($db);
36
37                         //we need both, server and username, so fail if one is missing
38                         if (!(strlen($server) && strlen($user))){
39                                 $this->connected = false;
40                                 $this->db = null;
41                                 throw new InvalidArgumentException(t("Server name of user name are missing. "));
42                         }
43
44                         //when we are installing
45                         if($install) {
46                                 if(strlen($server) && ($server !== 'localhost') && ($server !== '127.0.0.1')) {
47                                         if(! dns_get_record($server, DNS_A + DNS_CNAME + DNS_PTR)) {
48                                                 $this->connected = false;
49                                                 $this->db = null;
50                                                 throw new InvalidArgumentException( t('Cannot locate DNS info for database server \'%s\''), $server);
51                                         }
52                                 }
53                         }
54
55                         if(class_exists('mysqli')) {
56                                 $this->db = new mysqli($server,$user,$pass,$db);
57                                 if(NULL === $this->db->connect_error) {
58                                         $this->connected = true;
59                                 } else {
60                                         throw new RuntimeException($this->db->connect_error);
61                                 }
62                         } else {
63                                 $this->mysqli = false;
64                                 $this->db = mysql_connect($server,$user,$pass);
65                                 if($this->db && mysql_select_db($db,$this->db)) {
66                                         $this->connected = true;
67                                 } else {
68                                         throw new RuntimeException(mysql_error());
69                                 }
70                         }
71                 }
72
73                 public function excep($excep) {
74                         $this->exceptions=$excep; 
75                 }
76                 
77                 public function getdb() {
78                         return $this->db;
79                 }
80
81                 public function q($sql) {
82
83                         if((! $this->db) || (! $this->connected)) {
84                                 $this->throwOrLog(new RuntimeException(t("There is no db connection. ")));
85                                 return;
86                         }
87
88                         if($this->mysqli) {
89                                 $result = $this->db->query($sql);
90                         } else {
91                                 $result = mysql_query($sql,$this->db);
92                         }
93
94                         //on debug mode or fail, the query is written to the log.
95                         //this won't work if logger can not read it's logging level
96                         //from the db.
97                         if($this->debug || FALSE === $result) {
98
99                                 $mesg = '';
100
101                                 if($result === false) {
102                                         $mesg = 'false '.$this->error();
103                                 } elseif($result === true) {
104                                         $mesg = 'true';
105                                 } else {
106                                         if($this->mysqli) {
107                                                 $mesg = $result->num_rows . t(' results') . EOL;
108                                         } else {
109                                                 $mesg = mysql_num_rows($result) . t(' results') . EOL;
110                                         }
111                                 }
112
113                                 $str =  'SQL = ' . printable($sql) . EOL . t('SQL returned ') . $mesg . EOL;
114
115
116                          // If dbfail.out exists, we will write any failed calls directly to it,
117                          // regardless of any logging that may or may nor be in effect.
118                          // These usually indicate SQL syntax errors that need to be resolved.
119                                 if(file_exists('dbfail.out')) {\r
120                                         file_put_contents('dbfail.out', datetime_convert() . "\n" . $str . "\n", FILE_APPEND);
121                                 }
122                                 logger('dba: ' . $str );
123                                 if(FALSE===$result) {
124                                         $this->throwOrLog(new RuntimeException('dba: ' . $str));
125                                         return; 
126                                 }
127                         }
128                                 
129
130                         if($result === true) {
131                                 return $result;
132                         }
133
134                         $r = array();
135                         if($this->mysqli) {
136                                 if($result->num_rows) {
137                                         while($x = $result->fetch_array(MYSQLI_ASSOC)) {
138                                                 $r[] = $x;
139                                         }
140                                         $result->free_result();
141                                 }
142                         } else {
143                                 if(mysql_num_rows($result)) {
144                                         while($x = mysql_fetch_array($result, MYSQL_ASSOC)) {
145                                                 $r[] = $x;
146                                         }
147                                         mysql_free_result($result);
148                                 }
149                         }
150
151
152                         if($this->debug) {
153                                 logger('dba: ' . printable(print_r($r, true)));
154                         }
155                         return($r);
156                 }
157
158                 private function error() {
159                         if($this->mysqli) {
160                                 return $this->db->error;
161                         } else {
162                                 return mysql_error($this->db);
163                         }
164                 }
165                 
166                 private function throwOrLog(Exception $ex) {
167                         if($this->exceptions) {
168                                 throw $ex; 
169                         } else {
170                                 logger('dba: '.$ex->getMessage()); 
171                         }
172                 }
173                 
174                 /**
175                  * starts a transaction. Transactions need to be finished with 
176                  * commit() or rollback(). Please mind that the db table engine may
177                  * not support this. 
178                  */
179                 public function beginTransaction() {\r
180                         if($this->mysqli) {\r
181                                 return $this->db->autocommit(false);\r
182                         } else {\r
183                                 //no transaction support in mysql module...
184                                 mysql_query('SET AUTOCOMMIT = 0;', $db); \r
185                         }\r
186                 }
187                 
188                 /**
189                  * rollback a transaction. So, rollback anything that was done since the last call 
190                  * to beginTransaction(). 
191                  */
192                 public function rollback() {\r
193                         if($this->mysqli) {\r
194                                 return $this->db->rollback();\r
195                         } else {\r
196                                 //no transaction support in mysql module...
197                                 mysql_query('ROLLBACK;', $db);\r
198                         }
199                         $this->stopTransaction(); \r
200                 }
201
202                 /**
203                  * commit a transaction. So, write any query to the database. 
204                  */
205                 public function commit() {\r
206                         if($this->mysqli) {\r
207                                 return $this->db->commit();\r
208                         } else {\r
209                                 //no transaction support in mysql module...\r
210                                 mysql_query('COMMIT;', $db);\r
211                         }\r
212                         $this->stopTransaction();\r
213                 }
214                 
215                 private function stopTransaction() {\r
216                         if($this->mysqli) {\r
217                                 return $this->db->autocommit(true);\r
218                         } else {\r
219                                 //no transaction support in mysql module...\r
220                                 mysql_query('SET AUTOCOMMIT = 1;', $db);\r
221                         }\r
222                 }
223                 
224                 public function dbg($dbg) {
225                         $this->debug = $dbg;
226                 }
227
228                 public function escape($str) {
229                         if($this->db && $this->connected) {
230                                 if($this->mysqli) {
231                                         return $this->db->real_escape_string($str);
232                                 } else {
233                                         return mysql_real_escape_string($str,$this->db);
234                                 }
235                         }
236                 }
237
238                 function __destruct() {
239                         if ($this->db) {
240                                 if($this->mysqli) {
241                                         $this->db->close();
242                                 }
243                         } else {
244                                 mysql_close($this->db);
245                         }
246                 }
247         }
248 }
249
250 if(! function_exists('printable')) {
251         function printable($s) {
252                 $s = preg_replace("~([\x01-\x08\x0E-\x0F\x10-\x1F\x7F-\xFF])~",".", $s);
253                 $s = str_replace("\x00",'.',$s);
254                 if(x($_SERVER,'SERVER_NAME'))
255                         $s = escape_tags($s);
256                 return $s;
257         }
258 }
259
260 // Procedural functions
261 if(! function_exists('dbg')) {
262         function dbg($state) {
263                 global $db;
264                 if($db)
265                         $db->dbg($state);
266         }
267 }
268
269 if(! function_exists('dbesc')) {
270         function dbesc($str) {
271                 global $db;
272                 if($db && $db->connected)
273                         return($db->escape($str));
274                 else
275                         return(str_replace("'","\\'",$str));
276         }
277 }
278
279
280
281 // Function: q($sql,$args);
282 // Description: execute SQL query with printf style args.
283 // Example: $r = q("SELECT * FROM `%s` WHERE `uid` = %d",
284 //                   'user', 1);
285
286 if(! function_exists('q')) {
287         function q($sql) {
288
289                 global $db;
290                 $args = func_get_args();
291                 unset($args[0]);
292
293                 if($db && $db->connected) {
294                         $stmt = vsprintf($sql,$args);
295                         if($stmt === false)
296                                 logger('dba: vsprintf error: ' . print_r(debug_backtrace(),true));
297                         return $db->q($stmt);
298                 }
299
300                 /**
301                  *
302                  * This will happen occasionally trying to store the
303                  * session data after abnormal program termination
304                  *
305                  */
306                 logger('dba: no database: ' . print_r($args,true));
307                 return false;
308
309         }
310 }
311
312 /**
313  *
314  * Raw db query, no arguments
315  *
316  */
317
318 if(! function_exists('dbq')) {
319         function dbq($sql) {
320
321                 global $db;
322                 if($db && $db->connected)
323                         $ret = $db->q($sql);
324                 else
325                         $ret = false;
326                 return $ret;
327         }
328 }
329
330
331 // Caller is responsible for ensuring that any integer arguments to
332 // dbesc_array are actually integers and not malformed strings containing
333 // SQL injection vectors. All integer array elements should be specifically
334 // cast to int to avoid trouble.
335
336
337 if(! function_exists('dbesc_array_cb')) {
338         function dbesc_array_cb(&$item, $key) {
339                 if(is_string($item))
340                         $item = dbesc($item);
341         }
342 }
343
344
345 if(! function_exists('dbesc_array')) {
346         function dbesc_array(&$arr) {
347                 if(is_array($arr) && count($arr)) {
348                         array_walk($arr,'dbesc_array_cb');
349                 }
350         }
351 }
352
353