A Qcodo based CMS/ecommerce framework
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.

374 lines
13 KiB

13 years ago
  1. <?php
  2. /**
  3. * QuasiMysql - driver class for a MySQL database server.
  4. * This class inherits QuasiDBI, implementing the actual
  5. * connection and query methods. Do _not_ use this class
  6. * directly! Use QuasiDBI::getInstance() to retrieve a dbi object
  7. * or QuasiDBI::getInstance()->method().
  8. *
  9. * Note: We use the newer mysqli functions so this requires PHP5
  10. * and MySQL 4.1 and above.
  11. *
  12. * @author Erik Winn <ewinn@erikwinn.com>
  13. *
  14. * $Id: QuasiMysql.class.php 97 2008-08-29 21:36:11Z erikwinn $
  15. *
  16. *@version 0.2
  17. *
  18. * @copyright Erik Winn 2008
  19. * @license GPL v.2
  20. * @class
  21. */
  22. class QuasiMysql extends QuasiDBI
  23. {
  24. /** connect()
  25. * Connects to the db server, setting $objDatabaseHandle to the current link to db
  26. *@access public
  27. * @return boolean true on success or false
  28. */
  29. public function connect()
  30. {
  31. // We don't handle persistent connections. Yet, at least.
  32. // if( defined(USE_PCONNECT) && USE_PCONNECT == true );
  33. $this->objDatabaseHandle = mysqli_init();
  34. /* If DB_USE_SSL is defined, we attempt to set some parameters. A client key,
  35. client certificate, and CA certificate matching the one on the server
  36. must be available on the local filesystem. */
  37. if ( defined('DB_USE_SSL') && true === DB_USE_SSL )
  38. $this->objDatabaseHandle->ssl_set(DB_SSL_KEY, DB_SSL_CERT, DB_SSL_CA_CERT, null, null);
  39. $this->objDatabaseHandle->real_connect($this->strDatabaseServer,
  40. $this->strUsername,
  41. $this->strPassword,
  42. $this->strDatabase);
  43. /* make sure we are connected */
  44. if (mysqli_connect_errno())
  45. {
  46. $this->strErrors .= "Connection to database failed in QuasiMysql: " . mysqli_connect_error() . "\n";
  47. $this->blnIsConnected = false;
  48. return false;
  49. }
  50. $this->blnIsConnected = true;
  51. return true;
  52. }
  53. /** disconnect()
  54. * Closes current connection.
  55. *@access public
  56. *
  57. */
  58. public function disconnect()
  59. {
  60. if($this->objDatabaseHandle)
  61. $this->objDatabaseHandle->close();
  62. $this->blnIsConnected = false;
  63. }
  64. /** getInsertId()
  65. * Returns the insert id of the most recent insert action.
  66. *@access public
  67. * @return integer insert id of last query.
  68. */
  69. public function getInsertId()
  70. {
  71. if($this->objDatabaseHandle)
  72. return $this->objDatabaseHandle->insert_id;
  73. return 0;
  74. }
  75. /** doQuery()
  76. * Send a preformatted (i.e. complete) query to the server.
  77. * NOTE:With out the second parameter, this stores the result in
  78. * $objResultSet which we manage internally -- CAUTION: if you
  79. * intend to conduct new queries in a loop based on data from rows in the
  80. * first result set, you MUST accept the result set handle and pass
  81. * it to nextRow or else the rows from the first query _will_ be overwritten!!
  82. *
  83. *@access public
  84. *@param string strQuery string
  85. *@param boolean blnReturnResultSet - return a copy of the result set
  86. *@param boolean blnUnbuffered - use MYSQLI_USE_RESULT, ie. do not buffer results on the server
  87. * @return mixed mysqli_result on success or false
  88. */
  89. public function doQuery($strQuery, $blnReturnResultSet=false, $blnUnbuffered=true )
  90. {// todo - optionally use MYSQLI_USE_RESULT, set in config?
  91. if(! $this->objDatabaseHandle)
  92. return false;
  93. // clean up the string
  94. if($this->isBad($strQuery))
  95. return false;
  96. $objResultSet = $this->objDatabaseHandle->query($strQuery);
  97. if($objResultSet === false)
  98. { //query of any kind failed ..
  99. $this->strDbErrors .= $this->objDatabaseHandle->error;
  100. return false;
  101. }
  102. if($blnReturnResultSet)
  103. return $objResultSet;
  104. else
  105. $this->objResultSet =& $objResultSet;
  106. return $this->objResultSet;
  107. }
  108. /** nextRow()
  109. * Fetches the next row of most recent result set as an associative array,
  110. * where $key = column name and $value = column value.
  111. * Optionally, you may provide the parameter false to return a simple
  112. * numerically indexed array of column values.
  113. * Returns 0 after last row.
  114. *
  115. * You may optionally provide the result set through which to iterate
  116. * as the first parameter - by default we use the result set internal
  117. * to this class.
  118. *
  119. *@access public
  120. *@param object $objResultSet - object of type mysqli_result
  121. *@param boolean $blnReturnAssocArray=true returns an associative array, or false for numerical index keys
  122. * @return mixed object|integer
  123. */
  124. public function nextRow($objResultSet=NULL,$blnReturnAssocArray=true)
  125. {
  126. if(!$this->getNumRows() && ! $objResultSet)
  127. return 0;
  128. if( ! $objResultSet)
  129. {
  130. if($blnReturnAssocArray)
  131. return $this->objResultSet->fetch_assoc();
  132. else // numerical indices ..
  133. return $this->objResultSet->fetch_array();
  134. }
  135. //use provided result set ..
  136. if($blnReturnAssocArray)
  137. return $objResultSet->fetch_assoc();
  138. else // numerical indices ..
  139. return $objResultSet->fetch_array();
  140. }
  141. /** getDbError()
  142. *Returns a string containing the db error from the last query
  143. * including errorno...
  144. *@access public
  145. * @return string errors
  146. */
  147. public function getDbError()
  148. {
  149. //erm, this is confused ..todo: work out sensible error reporting ..
  150. if($this->objDatabaseHandle->errorno)
  151. $this->strDbErrors = $this->objDatabaseHandle->error . "\n Error No.:" . $this->objDatabaseHandle->errorno ;
  152. return $this->strDbErrors;
  153. }
  154. /** insertArray
  155. * Perform a simple insert or update on a specified table with
  156. * an array - adds a where clause filter when using UPDATE,
  157. * eg. $where = "name like 'joe' ", or $where = " id = $idno ".
  158. *
  159. * $aryValues must be an associative array in the format:
  160. * 'columname' = 'columnvalue'
  161. * Examples:
  162. insertArray($tablename, array('col1'=>'bar', 'col2' = 'baz') )
  163. insertArray($tablename, array('col1'=>'bar', 'col2' = 'baz'), 'update', $where )
  164. *
  165. *
  166. *@access public
  167. *@param string $strTable - which table to address
  168. *@param object $aryValues - assoc array of values to insert|update
  169. *@param string $strAction - may be either INSERT or UPDATE (case insensitive)
  170. *@param string $where - optional WHERE [conditions]
  171. *
  172. * @return boolean true on success or false
  173. */
  174. public function insertArray( $strTable, $aryValues, $strAction = "INSERT", $where = '')
  175. {
  176. if(!is_array($aryValues) || !isset($aryValues))
  177. {
  178. $this->strErrors .= "insertArray called with bad array ..";
  179. return false;
  180. }
  181. $strAction = trim(strtoupper($strAction));
  182. $numcols = count($aryValues);
  183. $strQuery = '';
  184. if($strAction == 'INSERT')
  185. {
  186. $strQuery = 'INSERT INTO ' . $strTable;
  187. $cols = ' (';
  188. $vals = ' VALUES (';
  189. $i=0;
  190. foreach($aryValues as $col => $val)
  191. {
  192. $i++;
  193. $end = $i < $numcols ? ", " : ") ";
  194. //if(empty($val)) continue;
  195. $cols .= $col . $end;
  196. if(trim(strtoupper($val)) === "NOW()" || trim(strtoupper($val)) === "NULL")
  197. $vals .= $val;
  198. else
  199. $vals .= " '" . $val . "' ";
  200. $vals .= $end;
  201. }
  202. $strQuery .= $cols . $vals;
  203. }
  204. elseif($strAction == 'UPDATE')
  205. {
  206. $strQuery = 'UPDATE ' . $strTable . ' SET ';
  207. $cols = '';
  208. $i=0;
  209. foreach($aryValues as $col => $val)
  210. {
  211. $i++;
  212. $end = $i < $numcols ? ", " : " ";
  213. //if(empty($val)) continue;
  214. $cols .= $col . ' = ';
  215. if(trim(strtoupper($val)) === "NOW()" || trim(strtoupper($val)) === "NULL")
  216. $vals = $val;
  217. else
  218. $vals = " '" . $val . "' ";
  219. $cols .= $vals . $end;
  220. }
  221. $strQuery .= $cols;
  222. }
  223. if(!empty($where))
  224. $strQuery .= ' WHERE ' . $where;
  225. return $this->doQuery($strQuery);
  226. }
  227. /** getNumRows()
  228. * Returns the number of rows in the most recent result set.
  229. * Note: if you are using a returned objResultSet from doQuery($strQuery,true)
  230. * you _must_ provide it as a parameter to get an accurate count.
  231. *
  232. *@access public
  233. *
  234. *@param object $objResultSet - object of type mysqli_result
  235. * @return integer number of rows
  236. */
  237. public function getNumRows($objResultSet=NULL)
  238. {
  239. if($objResultSet)
  240. return $objResultSet->num_rows;
  241. if(!$this->objDatabaseHandle || !$this->objResultSet)
  242. return 0;
  243. return $this->objResultSet->num_rows;
  244. }
  245. /** getAffectedRows()
  246. * Returns the number of rows affected by the most recent query.
  247. * Note: if you are using a returned objResultSet from doQuery($strQuery,true)
  248. * you _must_ provide it as a parameter to get an accurate count.
  249. *
  250. *@access public
  251. *
  252. *@param object $objResultSet - object of type mysqli_result
  253. * @return integer number of rows
  254. */
  255. public function getAffectedRows($objResultSet=NULL)
  256. {
  257. if($objResultSet)
  258. return $objResultSet->affected_rows;
  259. if(!$this->objDatabaseHandle || !$this->objResultSet)
  260. return 0;
  261. return $this->objResultSet->affected_rows;
  262. }
  263. /** prepInput()
  264. * Returns a string suitable for database input with escaped
  265. * single quotes, slashes, etc.. Use this to clean up a string or
  266. * array of strings from the outside world before constructing
  267. * a query. Note: do not use this on the whole query esp. if you have
  268. * single quotes in eg. the where clause - that will cause a mysql error.
  269. * Note also that we trim whitespace from input string.
  270. * Example:
  271. * $safe = $dbi->prepInput($_GET[unsafe]);
  272. * $query = 'SELECT foo FROM table WHERE bar LIKE \'' . $safe . '\' [AND other conditions ] ';
  273. * Wrong: $dbi->prepare($query);
  274. * Characters escaped are NUL (ASCII 0), \n, \r, \, ', ", and Control-Z.
  275. *
  276. * !! RUDENESS ALERT !! If input has MySQL injection attempts like LOAD DATA
  277. * ( see QuasiDBI::BADNESS ) this will return an empty string!!!
  278. *
  279. *@access public
  280. *@param string | array $input string or array to process
  281. * @return mixed string|array query safe string or array
  282. */
  283. public function prepInput($input)
  284. {
  285. if(!$this->objDatabaseHandle ) //shouldn't happen but momma's don't need objDatabaseHandle so ..
  286. return parent::prepInput($input);
  287. if(is_string($input))
  288. {
  289. // remove magic quotes and let mysqli escape the string below
  290. if(get_magic_quotes_gpc())
  291. $t_input = trim(stripslashes($input));
  292. else
  293. $t_input = trim($input);
  294. // check for prohibited SQL ..
  295. if($this->isBad($t_input))
  296. {//TODO: - error msg ..
  297. $t_input = "";
  298. return $t_input;
  299. }
  300. return $this->objDatabaseHandle->escape_string( $t_input);
  301. }
  302. elseif (is_array($input))
  303. {
  304. foreach($input as $key => &$value)
  305. $input[$key] = $this->prepInput($value);
  306. return $input;
  307. } else
  308. return $input;
  309. }
  310. /**changeDatabase
  311. *Resets the default database for queries and ensures that there
  312. * is a valid connection. returns false if this fails or if there
  313. * is not a valid objDatabaseHandle, or if connect fails ..
  314. *@access public
  315. *@param string $strNewDatabase - new database name
  316. * @return boolean true on success or false
  317. */
  318. public function changeDatabase($strNewDatabase)
  319. {
  320. if(!$this->objDatabaseHandle )
  321. {
  322. $this->strDbErrors .= "Change database called with no objDatabaseHandle!!";
  323. return false;
  324. }
  325. $this->setDbName($strNewDatabase);
  326. if(!$this->isConnected())
  327. return $this->connect();
  328. else
  329. return $this->objDatabaseHandle->select_db($strNewDatabase);
  330. }
  331. /**
  332. *just a comment template - ignore at will ..
  333. *@access public
  334. *@param string foo
  335. * @return boolean true on success or false
  336. */
  337. }
  338. ?>