ADOdb.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. <?php
  2. /*
  3. @version v5.20.17 31-Mar-2020
  4. @copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
  5. @copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
  6. Released under both BSD license and Lesser GPL library license.
  7. Whenever there is any discrepancy between the two licenses,
  8. the BSD license will take precedence. See License.txt.
  9. Set tabs to 4 for best viewing.
  10. Latest version is available at http://adodb.org/
  11. Original Authors: Martin Jansen <mj#php.net>
  12. Richard Tango-Lowy <richtl#arscognita.com>
  13. */
  14. require_once 'Auth/Container.php';
  15. require_once 'adodb.inc.php';
  16. require_once 'adodb-pear.inc.php';
  17. require_once 'adodb-errorpear.inc.php';
  18. /**
  19. * Storage driver for fetching login data from a database using ADOdb-PHP.
  20. *
  21. * This storage driver can use all databases which are supported
  22. * by the ADBdb DB abstraction layer to fetch login data.
  23. * See http://adodb.org/ for information on ADOdb.
  24. * NOTE: The ADOdb directory MUST be in your PHP include_path!
  25. *
  26. * @author Richard Tango-Lowy <richtl@arscognita.com>
  27. * @package Auth
  28. * @version $Revision: 1.3 $
  29. */
  30. class Auth_Container_ADOdb extends Auth_Container
  31. {
  32. /**
  33. * Additional options for the storage container
  34. * @var array
  35. */
  36. var $options = array();
  37. /**
  38. * DB object
  39. * @var object
  40. */
  41. var $db = null;
  42. var $dsn = '';
  43. /**
  44. * User that is currently selected from the DB.
  45. * @var string
  46. */
  47. var $activeUser = '';
  48. // {{{ Constructor
  49. /**
  50. * Constructor of the container class
  51. *
  52. * Initate connection to the database via PEAR::ADOdb
  53. *
  54. * @param string Connection data or DB object
  55. * @return object Returns an error object if something went wrong
  56. */
  57. function __construct($dsn)
  58. {
  59. $this->_setDefaults();
  60. if (is_array($dsn)) {
  61. $this->_parseOptions($dsn);
  62. if (empty($this->options['dsn'])) {
  63. PEAR::raiseError('No connection parameters specified!');
  64. }
  65. } else {
  66. // Extract db_type from dsn string.
  67. $this->options['dsn'] = $dsn;
  68. }
  69. }
  70. // }}}
  71. // {{{ _connect()
  72. /**
  73. * Connect to database by using the given DSN string
  74. *
  75. * @access private
  76. * @param string DSN string
  77. * @return mixed Object on error, otherwise bool
  78. */
  79. function _connect($dsn)
  80. {
  81. if (is_string($dsn) || is_array($dsn)) {
  82. if(!$this->db) {
  83. $this->db = ADONewConnection($dsn);
  84. if( $err = ADODB_Pear_error() ) {
  85. return PEAR::raiseError($err);
  86. }
  87. }
  88. } else {
  89. return PEAR::raiseError('The given dsn was not valid in file ' . __FILE__ . ' at line ' . __LINE__,
  90. 41,
  91. PEAR_ERROR_RETURN,
  92. null,
  93. null
  94. );
  95. }
  96. if(!$this->db) {
  97. return PEAR::raiseError(ADODB_Pear_error());
  98. } else {
  99. return true;
  100. }
  101. }
  102. // }}}
  103. // {{{ _prepare()
  104. /**
  105. * Prepare database connection
  106. *
  107. * This function checks if we have already opened a connection to
  108. * the database. If that's not the case, a new connection is opened.
  109. *
  110. * @access private
  111. * @return mixed True or a DB error object.
  112. */
  113. function _prepare()
  114. {
  115. if(!$this->db) {
  116. $res = $this->_connect($this->options['dsn']);
  117. }
  118. return true;
  119. }
  120. // }}}
  121. // {{{ query()
  122. /**
  123. * Prepare query to the database
  124. *
  125. * This function checks if we have already opened a connection to
  126. * the database. If that's not the case, a new connection is opened.
  127. * After that the query is passed to the database.
  128. *
  129. * @access public
  130. * @param string Query string
  131. * @return mixed a DB_result object or DB_OK on success, a DB
  132. * or PEAR error on failure
  133. */
  134. function query($query)
  135. {
  136. $err = $this->_prepare();
  137. if ($err !== true) {
  138. return $err;
  139. }
  140. return $this->db->query($query);
  141. }
  142. // }}}
  143. // {{{ _setDefaults()
  144. /**
  145. * Set some default options
  146. *
  147. * @access private
  148. * @return void
  149. */
  150. function _setDefaults()
  151. {
  152. $this->options['db_type'] = 'mysql';
  153. $this->options['table'] = 'auth';
  154. $this->options['usernamecol'] = 'username';
  155. $this->options['passwordcol'] = 'password';
  156. $this->options['dsn'] = '';
  157. $this->options['db_fields'] = '';
  158. $this->options['cryptType'] = 'md5';
  159. }
  160. // }}}
  161. // {{{ _parseOptions()
  162. /**
  163. * Parse options passed to the container class
  164. *
  165. * @access private
  166. * @param array
  167. */
  168. function _parseOptions($array)
  169. {
  170. foreach ($array as $key => $value) {
  171. if (isset($this->options[$key])) {
  172. $this->options[$key] = $value;
  173. }
  174. }
  175. /* Include additional fields if they exist */
  176. if(!empty($this->options['db_fields'])){
  177. if(is_array($this->options['db_fields'])){
  178. $this->options['db_fields'] = join(', ', $this->options['db_fields']);
  179. }
  180. $this->options['db_fields'] = ', '.$this->options['db_fields'];
  181. }
  182. }
  183. // }}}
  184. // {{{ fetchData()
  185. /**
  186. * Get user information from database
  187. *
  188. * This function uses the given username to fetch
  189. * the corresponding login data from the database
  190. * table. If an account that matches the passed username
  191. * and password is found, the function returns true.
  192. * Otherwise it returns false.
  193. *
  194. * @param string Username
  195. * @param string Password
  196. * @return mixed Error object or boolean
  197. */
  198. function fetchData($username, $password)
  199. {
  200. // Prepare for a database query
  201. $err = $this->_prepare();
  202. if ($err !== true) {
  203. return PEAR::raiseError($err->getMessage(), $err->getCode());
  204. }
  205. // Find if db_fields contains a *, i so assume all col are selected
  206. if(strstr($this->options['db_fields'], '*')){
  207. $sql_from = "*";
  208. }
  209. else{
  210. $sql_from = $this->options['usernamecol'] . ", ".$this->options['passwordcol'].$this->options['db_fields'];
  211. }
  212. $query = "SELECT ".$sql_from.
  213. " FROM ".$this->options['table'].
  214. " WHERE ".$this->options['usernamecol']." = " . $this->db->Quote($username);
  215. $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
  216. $rset = $this->db->Execute( $query );
  217. $res = $rset->fetchRow();
  218. if (DB::isError($res)) {
  219. return PEAR::raiseError($res->getMessage(), $res->getCode());
  220. }
  221. if (!is_array($res)) {
  222. $this->activeUser = '';
  223. return false;
  224. }
  225. if ($this->verifyPassword(trim($password, "\r\n"),
  226. trim($res[$this->options['passwordcol']], "\r\n"),
  227. $this->options['cryptType'])) {
  228. // Store additional field values in the session
  229. foreach ($res as $key => $value) {
  230. if ($key == $this->options['passwordcol'] ||
  231. $key == $this->options['usernamecol']) {
  232. continue;
  233. }
  234. // Use reference to the auth object if exists
  235. // This is because the auth session variable can change so a static call to setAuthData does not make sence
  236. if(is_object($this->_auth_obj)){
  237. $this->_auth_obj->setAuthData($key, $value);
  238. } else {
  239. Auth::setAuthData($key, $value);
  240. }
  241. }
  242. return true;
  243. }
  244. $this->activeUser = $res[$this->options['usernamecol']];
  245. return false;
  246. }
  247. // }}}
  248. // {{{ listUsers()
  249. function listUsers()
  250. {
  251. $err = $this->_prepare();
  252. if ($err !== true) {
  253. return PEAR::raiseError($err->getMessage(), $err->getCode());
  254. }
  255. $retVal = array();
  256. // Find if db_fileds contains a *, i so assume all col are selected
  257. if(strstr($this->options['db_fields'], '*')){
  258. $sql_from = "*";
  259. }
  260. else{
  261. $sql_from = $this->options['usernamecol'] . ", ".$this->options['passwordcol'].$this->options['db_fields'];
  262. }
  263. $query = sprintf("SELECT %s FROM %s",
  264. $sql_from,
  265. $this->options['table']
  266. );
  267. $res = $this->db->getAll($query, null, DB_FETCHMODE_ASSOC);
  268. if (DB::isError($res)) {
  269. return PEAR::raiseError($res->getMessage(), $res->getCode());
  270. } else {
  271. foreach ($res as $user) {
  272. $user['username'] = $user[$this->options['usernamecol']];
  273. $retVal[] = $user;
  274. }
  275. }
  276. return $retVal;
  277. }
  278. // }}}
  279. // {{{ addUser()
  280. /**
  281. * Add user to the storage container
  282. *
  283. * @access public
  284. * @param string Username
  285. * @param string Password
  286. * @param mixed Additional information that are stored in the DB
  287. *
  288. * @return mixed True on success, otherwise error object
  289. */
  290. function addUser($username, $password, $additional = "")
  291. {
  292. if (function_exists($this->options['cryptType'])) {
  293. $cryptFunction = $this->options['cryptType'];
  294. } else {
  295. $cryptFunction = 'md5';
  296. }
  297. $additional_key = '';
  298. $additional_value = '';
  299. if (is_array($additional)) {
  300. foreach ($additional as $key => $value) {
  301. $additional_key .= ', ' . $key;
  302. $additional_value .= ", '" . $value . "'";
  303. }
  304. }
  305. $query = sprintf("INSERT INTO %s (%s, %s%s) VALUES ('%s', '%s'%s)",
  306. $this->options['table'],
  307. $this->options['usernamecol'],
  308. $this->options['passwordcol'],
  309. $additional_key,
  310. $username,
  311. $cryptFunction($password),
  312. $additional_value
  313. );
  314. $res = $this->query($query);
  315. if (DB::isError($res)) {
  316. return PEAR::raiseError($res->getMessage(), $res->getCode());
  317. } else {
  318. return true;
  319. }
  320. }
  321. // }}}
  322. // {{{ removeUser()
  323. /**
  324. * Remove user from the storage container
  325. *
  326. * @access public
  327. * @param string Username
  328. *
  329. * @return mixed True on success, otherwise error object
  330. */
  331. function removeUser($username)
  332. {
  333. $query = sprintf("DELETE FROM %s WHERE %s = '%s'",
  334. $this->options['table'],
  335. $this->options['usernamecol'],
  336. $username
  337. );
  338. $res = $this->query($query);
  339. if (DB::isError($res)) {
  340. return PEAR::raiseError($res->getMessage(), $res->getCode());
  341. } else {
  342. return true;
  343. }
  344. }
  345. // }}}
  346. }
  347. function showDbg( $string ) {
  348. print "
  349. -- $string</P>";
  350. }
  351. function dump( $var, $str, $vardump = false ) {
  352. print "<H4>$str</H4><pre>";
  353. ( !$vardump ) ? ( print_r( $var )) : ( var_dump( $var ));
  354. print "</pre>";
  355. }