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