Friendica Communications Platform (please note that this is a clone of the repository at github, issues are handled there) https://friendi.ca
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

dba.php 8.4KB

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