3 require_once('include/datetime.php');
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.
18 if(! class_exists('dba')) {
24 public $mysqli = true;
25 public $connected = false;
26 public $error = false;
28 function __construct($server,$user,$pass,$db,$install = false) {
30 $server = trim($server);
35 //we need both, server and username, so fail if one is missing
36 if (!(strlen($server) && strlen($user))){
37 $this->connected = false;
39 throw new InvalidArgumentException(t("Server name of user name are missing. "));
42 //when we are installing
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;
48 throw new InvalidArgumentException( t('Cannot locate DNS info for database server \'%s\''), $server);
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;
58 throw new RuntimeException($this->db->connect_error());
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;
66 throw new RuntimeException(mysql_error());
71 public function getdb() {
75 public function q($sql) {
77 if((! $this->db) || (! $this->connected)) {
78 throw new RuntimeException(t("There is no db connection. "));
82 $result = $this->db->query($sql);
84 $result = mysql_query($sql,$this->db);
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
90 if($this->debug || FALSE === $result) {
94 if($result === false) {
95 $mesg = 'false '.$this->error();
96 } elseif($result === true) {
100 $mesg = $result->num_rows . t(' results') . EOL;
102 $mesg = mysql_num_rows($result) . t(' results') . EOL;
106 $str = 'SQL = ' . printable($sql) . EOL . t('SQL returned ') . $mesg . EOL;
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);
115 logger('dba: ' . $str );
116 if(FALSE===$result) {
117 throw new RuntimeException('dba: ' . $str);
122 if($result === true) {
128 if($result->num_rows) {
129 while($x = $result->fetch_array(MYSQLI_ASSOC)) {
132 $result->free_result();
135 if(mysql_num_rows($result)) {
136 while($x = mysql_fetch_array($result, MYSQL_ASSOC)) {
139 mysql_free_result($result);
145 logger('dba: ' . printable(print_r($r, true)));
150 private function error() {
152 return $this->db->error;
154 return mysql_error($this->db);
158 public function beginTransaction() {
\r
159 if($this->mysqli) {
\r
160 return $this->db->autocommit(false);
\r
162 //no transaction support in mysql module...
163 mysql_query('SET AUTOCOMMIT = 0;', $db);
\r
167 public function rollback() {
\r
168 if($this->mysqli) {
\r
169 return $this->db->rollback();
\r
171 //no transaction support in mysql module...
172 mysql_query('ROLLBACK;', $db);
\r
174 $this->stopTransaction();
\r
177 public function commit() {
\r
178 if($this->mysqli) {
\r
179 return $this->db->commit();
\r
181 //no transaction support in mysql module...
\r
182 mysql_query('COMMIT;', $db);
\r
184 $this->stopTransaction();
\r
187 private function stopTransaction() {
\r
188 if($this->mysqli) {
\r
189 return $this->db->autocommit(true);
\r
191 //no transaction support in mysql module...
\r
192 mysql_query('SET AUTOCOMMIT = 1;', $db);
\r
196 public function dbg($dbg) {
200 public function escape($str) {
201 if($this->db && $this->connected) {
203 return $this->db->real_escape_string($str);
205 return mysql_real_escape_string($str,$this->db);
210 function __destruct() {
216 mysql_close($this->db);
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);
232 // Procedural functions
233 if(! function_exists('dbg')) {
234 function dbg($state) {
241 if(! function_exists('dbesc')) {
242 function dbesc($str) {
244 if($db && $db->connected)
245 return($db->escape($str));
247 return(str_replace("'","\\'",$str));
253 // Function: q($sql,$args);
254 // Description: execute SQL query with printf style args.
255 // Example: $r = q("SELECT * FROM `%s` WHERE `uid` = %d",
258 if(! function_exists('q')) {
262 $args = func_get_args();
265 if($db && $db->connected) {
266 $stmt = vsprintf($sql,$args);
268 logger('dba: vsprintf error: ' . print_r(debug_backtrace(),true));
269 return $db->q($stmt);
274 * This will happen occasionally trying to store the
275 * session data after abnormal program termination
278 logger('dba: no database: ' . print_r($args,true));
286 * Raw db query, no arguments
290 if(! function_exists('dbq')) {
294 if($db && $db->connected)
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.
309 if(! function_exists('dbesc_array_cb')) {
310 function dbesc_array_cb(&$item, $key) {
312 $item = dbesc($item);
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');