All in one PHP user class - uFlex


/ Published in: PHP
Save to your folder(s)

uFlex or userFlex is an all in one PHP user class that provides developers with a simple yet secured, reliable and flexible framework like structure to authenticate their sites and applications. The purpose of uFlex is to handle the tedious processes involved in authenticating users.


Copy this code and paste it in your HTML
  1. <?php
  2. // For Support visit http://crusthq.com/projects/uFlex/
  3. // ---------------------------------------------------------------------------
  4. // uFlex - An all in one authentication system PHP class
  5. // Copyright (C) 2011 Pablo Tejada
  6. //
  7. // This program is free software: you can redistribute it and/or modify
  8. // it under the terms of the GNU General Public License as published by
  9. // the Free Software Foundation, either version 3 of the License, or
  10. // (at your option) any later version.
  11. //
  12. // This program is distributed in the hope that it will be useful,
  13. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. // GNU General Public License for more details.
  16. //
  17. // You should have received a copy of the GNU General Public License
  18. // along with this program. If not, see http://www.gnu.org/licenses/gpl-3.0.html.
  19. // ---------------------------------------------------------------------------
  20.  
  21. /*Thought the Class Official name is userFlex the object is simply named uFlex*/
  22. class uFlex {
  23. //Constants
  24. const debug = true; //Logs extra bits of errors for developers
  25. const version = 0.75;
  26. const salt = "sd5a4"; //IMPORTANT: Please change this value as it will make this copy unique and secured
  27. //End of constants\\\\
  28. var $id; //Signed user ID
  29. var $sid; //Current User Session ID
  30. var $username; //Signed username
  31. var $pass; //Holds the user password hash
  32. var $signed; //Boolean, true = user is signed-in
  33. var $data; //Holds entire user database row
  34. var $console; //Cotainer for errors and reports
  35. var $log; //Used for traking errors and reports
  36. var $confirm; //Holds the hash for any type of comfirmation
  37. var $tmp_data; //Holds the temporary user information during registration
  38. var $opt = array( //Array of Internal options
  39. "table_name" => "users",
  40. "cookie_time" => "+30 days",
  41. "cookie_name" => "auto",
  42. "cookie_path" => "/",
  43. "cookie_host" => false,
  44. "user_session" => "userData",
  45. "default_user" => array(
  46. "username" => "Guest",
  47. "user_id" => 0,
  48. "password" => 0,
  49. "signed" => false
  50. )
  51. );
  52. var $validations = array( //Array for default field validations
  53. "username" => array(
  54. "limit" => "3-15",
  55. "regEx" => '/^([a-zA-Z0-9_])+$/'
  56. ),
  57. "password" => array(
  58. "limit" => "3-15",
  59. "regEx" => false
  60. ),
  61. "email" => array(
  62. "limit" => "4-35",
  63. "regEx" => '/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$/'
  64. )
  65. );
  66.  
  67. var $encoder = array(
  68. "a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z",
  69. "A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z",
  70. 0,2,3,4,5,6,7,8,9
  71. );
  72.  
  73. //Array of errors
  74. var $errorList = array(
  75. //Database Error while caling register functions
  76. 1 => "New User Registration Failed",
  77. //Database Error while calling update functions
  78. 2 => "The Changes Could not be made",
  79. //Database Error while calling activate function
  80. 3 => "Account could not be activated",
  81. //When calling pass_reset and the given email doesn't exist in database
  82. 4 => "We don't have an account with this email",
  83. //When calling new_pass, the confirmation hash did not match the one in database
  84. 5 => "Password could not be changed. The request can't be validated",
  85. 6 => "Logging with cookies failed",
  86. 7 => "No Username or Password provided",
  87. 8 => "Your Account has not been Activated. Check your Email for instructions",
  88. 9 => "Your account has been deactivated. Please contact Administrator",
  89. 10 => "Wrong Username or Password",
  90. //When calling check_hash with invalid hash
  91. 11 => "Confirmation hash is invalid",
  92. //Calling check_hash hash failed database match test
  93. 12 => "Your identification could not be confirmed",
  94. //When saving hash to database fails
  95. 13 => "Failed to save confirmation request",
  96. 14 => "You need to reset your password to login"
  97. );
  98.  
  99.  
  100. /** EDITS BELOW THIS LINE WILL NOT BE KEPT WHEN UPDATING CLASS USING THE UPDATER SCRIPT **/
  101.  
  102. /**
  103. * Public function to initiate a login request at any time
  104. *
  105. * @access public
  106. * @param string $user username or email
  107. * @param string $pass password
  108. * @param bool|int $auto boolean to remember or not the user
  109. */
  110. function login($user=false,$pass=false,$auto=false){
  111. //reconstruct object
  112. self::__construct($user,$pass,$auto);
  113. }
  114.  
  115. ///////////////////////////////////////////////////////////////////////////////////////////////////////
  116. /*
  117. Register A New User
  118. -Takes two parameters, the first being required
  119. @info = array object (takes an associatve array,
  120. the index being the fieldname(column in database)
  121. and the value its content(value)
  122. +optional second parameter
  123. @activation = boolean(true/false)
  124. default = false
  125. Returns activation hash if second parameter @activation is true
  126. Returns true if second parameter @activation is false
  127. Returns false on Error
  128. */
  129. ///////////////////////////////////////////////////////////////////////////////////////////////////////
  130. function register($info,$activation = false){
  131. $this->logger("registration"); //Index for Errors and Reports
  132.  
  133. //Saves Registration Data in Class
  134. $this->tmp_data = $info;
  135.  
  136. //Validate All Fields
  137. if(!$this->validateAll()) return false; //There are validations error
  138.  
  139. //Built in actions for special fields
  140. //Hash Password
  141. if(isset($info['password'])){
  142. $this->hash_pass($info['password']);
  143. $info['password'] = $this->pass;
  144. }
  145. //Check for Email in database
  146. if(isset($info['email']))
  147. if($this->check_field('email',$info['email'],"This Email is Already in Use"))
  148. return false;
  149.  
  150. //Check for username in database
  151. if(isset($info['username']))
  152. if($this->check_field('username',$info['username'], "This Username is not available"))
  153. return false;
  154.  
  155. //Check for errors
  156. if($this->has_error()) return false;
  157.  
  158. //Set Registration Date
  159. $info['reg_date'] = time();
  160.  
  161. //User Activation
  162. if(!$activation){ //Activates user upon registration
  163. $info['activated'] = 1;
  164. }
  165.  
  166. //Prepare Info for SQL Insertion
  167. foreach($info as $index => $val){
  168. if(!preg_match("/2$/",$index)){ //Skips double fields
  169. $into[] = $index;
  170. $values[] = "'".mysql_real_escape_string($val)."'";
  171. }
  172. }
  173.  
  174. $into = implode(", ",$into);
  175. $values = implode(",",$values);
  176.  
  177. //Prepare New User Query
  178. $sql = "INSERT INTO {$this->opt['table_name']} ($into)
  179. VALUES($values)";
  180. //exit($sql);
  181.  
  182. //Enter New user to Database
  183. if($this->check_sql($sql)){
  184. $this->report("New User \"{$info['username']}\" has been registered");
  185. $this->id = mysql_insert_id();
  186. if($activation){
  187. //Insert Validation Hash
  188. $this->make_hash($this->id);
  189. $this->save_hash();
  190. return $this->confirm;
  191. }
  192. return true;
  193. }else{
  194. $this->error(1);
  195. return false;
  196. }
  197. }
  198.  
  199. ///////////////////////////////////////////////////////////////////////////////////////////////////////
  200. /*
  201. Similar to the register method function in structure
  202. This Method validates and updates any field in the database
  203. -Takes one parameter
  204. @info = array object (takes an associatve array,
  205. the index being the fieldname(column in database)
  206. and the value its content(value)
  207. On Success returns true
  208. On Failure return false
  209. */
  210. ///////////////////////////////////////////////////////////////////////////////////////////////////////
  211. function update($info){
  212. $this->logger("update"); //Index for Errors and Reports
  213.  
  214. //Saves Updates Data in Class
  215. $this->tmp_data = $info;
  216.  
  217. //Validate All Fields
  218. if(!$this->validateAll())
  219. return false; //There are validations error
  220.  
  221. //Built in actions for special fields
  222. //Hash Password
  223. if(isset($info['password'])){
  224. $this->hash_pass($info['password']);
  225. $info['password'] = $this->pass;
  226. }
  227. //Check for Email in database
  228. if(isset($info['email']))
  229. if($this->check_field('email',$info['email'],"This Email is Already in Use"))
  230. return false;
  231.  
  232. //Check for errors
  233. if($this->has_error()) return false;
  234.  
  235. //Prepare Info for SQL Insertion
  236. foreach($info as $index => $val){
  237. if(!preg_match("/2$/",$index)){ //Skips double fields
  238. $value = "'".mysql_real_escape_string($val)."'";
  239. $set[] = "{$index}={$value}";
  240. }
  241. }
  242.  
  243. $set = implode(", ",$set);
  244.  
  245. //Prepare User Update Query
  246. $sql = "UPDATE {$this->opt['table_name']} SET $set
  247. WHERE user_id='{$this->id}'";
  248. //exit($sql);
  249.  
  250. //Check for Changes
  251. if($this->check_sql($sql)){
  252. $this->report("Information Updated");
  253. $_SESSION['uFlex']['update'] = true;
  254. return true;
  255. }else{
  256. $this->error(2);
  257. return false;
  258. }
  259. }
  260.  
  261. ///////////////////////////////////////////////////////////////////////////////////////////////////////
  262. /*
  263. Adds validation to queue for either the Registration or Update Method
  264. Single Entry:
  265. Requires the first two parameters
  266. @name = string (name of the field to be validated)
  267. @limit = string (range in the format of "5-10")
  268. *to make a field optional start with 0 (Ex. "0-10")
  269. Optional third paramenter
  270. @regEx = string (Regular Expresion to test the field)
  271. _____________________________________________________________________________________________________
  272.  
  273. Multiple Entry:
  274. Takes only the first argument
  275. @name = Array Object (takes an object in the following format:
  276. array(
  277. "username" => array(
  278. "limit" => "3-15",
  279. "regEx" => "/^([a-zA-Z0-9_])+$/"
  280. ),
  281. "password" => array(
  282. "limit" => "3-15",
  283. "regEx" => false
  284. )
  285. );
  286. */
  287. ///////////////////////////////////////////////////////////////////////////////////////////////////////
  288. function addValidation($name,$limit = "0-1",$regEx = false){
  289. $this->logger("registration");
  290. if(is_array($name)){
  291. if(!is_array($this->validations))
  292. $this->validations = array(); //If is not an array yet, make it one
  293. $new = array_merge($this->validations,$name);
  294. $this->validations = $new;
  295. $this->report("New Validation Object added");
  296. }else{
  297. $this->validations[$name]['limit'] = $limit;
  298. $this->validations[$name]['regEx'] = $regEx;
  299. $this->report("The $name field has been added for validation");
  300. }
  301. }
  302.  
  303. ///////////////////////////////////////////////////////////////////////////////////////////////////////
  304. /*
  305. Activates Account with hash
  306. Takes Only and Only the URL parameter of the confirmation page
  307. @hash = string
  308. Returns true on account activation and false on failure
  309. */
  310. ///////////////////////////////////////////////////////////////////////////////////////////////////////
  311. function activate($hash){
  312. $this->logger("activation");
  313.  
  314. if(!$this->check_hash($hash)) return false;
  315.  
  316. $sql = "UPDATE {$this->opt['table_name']} SET activated=1, confirmation='' WHERE confirmation='{$hash}' AND user_id='{$this->id}'";
  317.  
  318. if($this->check_sql($sql)){
  319. $this->report("Account has been Activated");
  320. return true;
  321. }else{
  322. $this->error(3);
  323. return false;
  324. }
  325. }
  326.  
  327. ///////////////////////////////////////////////////////////////////////////////////////////////////////
  328. /*
  329. Method to reset password, Returns confirmation code to reset password
  330. -Takes one parameter and is required
  331. @email = string(user email to reset password)
  332. On Success it returns an array(email,username,user_id,hash) which could then be use to
  333.  construct the confirmation URL and Email
  334. On Failure it returns false
  335. */
  336. ///////////////////////////////////////////////////////////////////////////////////////////////////////
  337. function pass_reset($email){
  338. $this->logger("pass_reset");
  339. $sql = "SELECT * FROM {$this->opt['table_name']} WHERE email='{$email}'";
  340.  
  341. $user = $this->getRow($sql);
  342.  
  343. if($user){
  344. if(!$user['activated'] and !$user['confirmation']){
  345. //The Account has been manually disabled and can't reset password
  346. $this->error(9);
  347. return false;
  348. }
  349.  
  350. $this->make_hash($user['user_id']);
  351. $this->id = $user['user_id'];
  352. $this->save_hash();
  353.  
  354. $data = array(
  355. "email" => $email,
  356. "username" => $user['username'],
  357. "user_id" => $user['user_id'],
  358. "hash" => $this->confirm
  359. );
  360. return $data;
  361. }else{
  362. $this->error(4);
  363. return false;
  364. }
  365. }
  366.  
  367. ///////////////////////////////////////////////////////////////////////////////////////////////////////
  368. /*
  369. Changes a Password with a Confirmation hash from the pass_reset method
  370. *this is for users that forget their passwords to change the signed user password use ->update()
  371. -Takes two parameters
  372. @hash = string (pass_reset method hash)
  373. @new = array (an array with indexes 'password' and 'password2')
  374. Example:
  375. array(
  376. [password] => pass123
  377. [password2] => pass123
  378. )
  379. *use ->addValidation('password', ...) to validate password
  380. Returns true on a successful password change
  381. Returns false on error
  382. */
  383. ///////////////////////////////////////////////////////////////////////////////////////////////////////
  384. function new_pass($hash,$newPass){
  385. $this->logger("new_pass");
  386.  
  387. if(!$this->check_hash($hash)) return false;
  388.  
  389. $this->tmp_data = $newPass;
  390. if(!$this->validateAll()) return false; //There are validations error
  391.  
  392. $pass = $this->hash_pass($newPass['password']);
  393.  
  394. $sql = "UPDATE {$this->opt['table_name']} SET password='{$pass}', confirmation='', activated=1 WHERE confirmation='{$hash}' AND user_id='{$this->id}'";
  395. if($this->check_sql($sql)){
  396. $this->report("Password has been changed");
  397. return true;
  398. }else{
  399. //Error
  400. $this->error(5);
  401. return false;
  402. }
  403. }
  404.  
  405. /*////////////////////////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*\
  406. ////////Private and Secondary Methods below this line\\\\\\\\\\\\\
  407.  \*\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\/////////////////////////////////////////////*/
  408. /*Object Constructor*/
  409. function __construct($user = false,$pass = false,$auto = false){
  410. $this->logger("login"); //Index for Reports and Errors;
  411.  
  412. if(!isset($_SESSION) and !headers_sent()){
  413. $this->report("Session is been started...");
  414. }elseif(isset($_SESSION)){
  415. $this->report("Session has already been started");
  416. }else{
  417. $this->error("Session could not be started");
  418. return; //Finish Execution
  419. }
  420.  
  421. $this->sid = session_id();
  422.  
  423. $result = $this->loginUser($user,$pass,$auto);
  424. if($result == false){
  425. $this->session($this->opt['default_user']);
  426. $this->update_from_session();
  427. $this->report("User is " + $this->username);
  428. }else{
  429. if(!$auto and isset($_SESSION['uFlex']['remember'])){
  430. unset($_SESSION['uFlex']['remember']);
  431. $this->setCookie();
  432. }
  433. }
  434. return true;
  435. }
  436.  
  437. /**
  438. * Private Login proccesor function
  439. *
  440. */
  441. private function loginUser($user = false,$pass = false,$auto = false){
  442. //Session Login
  443. if($this->session("signed")){
  444. $this->report("User Is signed in from session");
  445. $this->update_from_session();
  446. if(isset($_SESSION['uFlex']['update'])){
  447. $this->report("Updating Session from database");
  448. //Get User From database because its info has change during current session
  449. $update = $this->getRow("SELECT * FROM {$this->opt['table_name']} WHERE user_id='{$this->id}'");
  450. $this->update_session($update);
  451. $this->log_login(); //Update last_login
  452. }
  453. return true;
  454. }
  455. //Cookies Login
  456. if(isset($_COOKIE[$this->opt['cookie_name']]) and !$user and !$pass){
  457. $c = $_COOKIE[$this->opt['cookie_name']];
  458. $this->report("Attemping Login with cookies");
  459. if($this->check_hash($c,true)){
  460. $auto = true;
  461. $cond = "username='{$this->username}'";
  462. }else{
  463. $this->error(6);
  464. $this->logout();
  465. return false;
  466. }
  467. }else{
  468. //Credentials Login
  469. if($user && $pass){
  470. if(preg_match($this->validations['email']['regEx'],$user)){
  471. //Login using email
  472. $cond = "email='{$user}'";
  473. }else{
  474. //Login using username
  475. $cond = "username='{$user}'";
  476.  
  477. }
  478. $this->hash_pass($pass);
  479. $this->report("Credentials received");
  480. }else{
  481. $this->error(7);
  482. return false;
  483. }
  484. }
  485.  
  486. $this->report("Querying Database to authenticate user");
  487. //Query Database and check login
  488. $sql = "SELECT * FROM {$this->opt['table_name']} WHERE {$cond} AND password='{$this->pass}'";
  489. $userFile = $this->getRow($sql);
  490. if($userFile){
  491. //If Account is not Activated
  492. if($userFile['activated'] == 0){
  493. if($userFile['last_login'] == 0){
  494. //Account has not been activated
  495. $this->error(8);
  496. }else if(!$userFile['confirmation']){
  497. //Account has been deactivated
  498. $this->error(9);
  499. }else{
  500. //Account deativated due to a password reset or reactivation request
  501. $this->error(14);
  502. }
  503. return false;
  504. }
  505. //Account is Activated and user is logged in
  506. $this->update_session($userFile);
  507.  
  508. //If auto Remember User
  509. if($auto){
  510. $this->setCookie();
  511. }
  512. $this->log_login(); //Update last_login
  513. //Done
  514. $this->report("User Logged in Successfully");
  515. return true;
  516. }else{
  517. if(isset($_COOKIE[$this->opt['cookie_name']])){
  518. $this->logout();
  519. }
  520. $this->error(10);
  521. return false;
  522. }
  523. }
  524.  
  525. function logout(){
  526. $this->logger("login");
  527. $deleted = setcookie($this->opt['cookie_name'],"",time() - 3600,"/"); //Deletes the Auto Coookie
  528. $this->signed = 0;
  529. //Import default user object
  530. $this->data = $_SESSION[$this->opt['user_session']] = $this->opt['default_user'];
  531. if(!$deleted){
  532. $this->report("The Autologin cookie could not be deleted");
  533. }
  534. $this->report("User Logged out");
  535. }
  536.  
  537. private function log_login(){
  538. //Update last_login
  539. $time = time();
  540. $sql = "UPDATE {$this->opt['table_name']} SET last_login='{$time}' WHERE user_id='{$this->id}'";
  541. if($this->check_sql($sql))
  542. $this->report("Last Login updated");
  543. }
  544.  
  545. function setCookie(){
  546. if($this->pass and $this->id){
  547.  
  548. $code = $this->make_hash($this->id,$this->pass);
  549.  
  550. if(!headers_sent()){
  551. //echo "PHP";
  552. setcookie($this->opt['cookie_name'],$code,strtotime($this->opt['cookie_time']),
  553. $this->opt['cookie_path'],$this->opt['cookie_host']);
  554. }else{
  555. //Headers have been sent use JavaScript to set cookie
  556. $time = intval($this->opt['cookie_time']);
  557. echo "<script>";
  558. echo '
  559. function setCookie(c_name,value,expiredays){
  560. var exdate=new Date();
  561. exdate.setDate(exdate.getDate()+expiredays);
  562. document.cookie=c_name+ "=" +escape(value)+((expiredays==null) ? "" : "; expires="+exdate.toUTCString()); path=escape("'.
  563. $this->opt["cookie_path"].'");
  564. }
  565. ';
  566. echo "setCookie('{$this->opt['cookie_name']}','{$code}',{$time})";
  567. echo "</script>";
  568. }
  569.  
  570. $this->report("Cookies have been updated for auto login");
  571. }else{
  572. $this->error("Info required to set the cookie {$this->opt['cookie_name']} is not available");
  573. }
  574. }
  575.  
  576. private function session($index=false, $val=false){
  577. if(is_string($index) and !$val){
  578. return @$_SESSION[$this->opt['user_session']][$index];
  579. }
  580.  
  581. if(is_string($index) and $val){
  582. $_SESSION[$this->opt['user_session']][$index] = $val;
  583. return;
  584. }
  585.  
  586. if(is_array($index) and !$val){
  587. $_SESSION[$this->opt['user_session']] = $index;
  588. return;
  589. }
  590. //return full session user data
  591. return $_SESSION[$this->opt['user_session']];
  592. }
  593.  
  594. private function update_session($d){
  595. unset($_SESSION['uFlex']['update']);
  596.  
  597. $this->session($d);
  598. $this->session("signed",1);
  599.  
  600. $this->report("Session updated");
  601. $this->update_from_session();
  602. }
  603.  
  604. private function update_from_session(){
  605. $d = $this->session();
  606.  
  607. $this->id = $d['user_id'];
  608. $this->data = $d;
  609. $this->username = $d['username'];
  610. $this->pass = $d['password'];
  611. $this->signed = $d['signed'];
  612.  
  613. $this->report("Session has been imported to the object");
  614. }
  615.  
  616. function hash_pass($pass){
  617. $salt = uFlex::salt;
  618. $this->pass = md5($salt.$pass.$salt);
  619. return $this->pass;
  620. }
  621.  
  622. function logger($log){
  623. $this->log = $log;
  624. unset($this->console['errors'][$log]);
  625. unset($this->console['form'][$log]);
  626. $this->report(">>Startting new $log request");
  627. }
  628.  
  629. function report($str = false){
  630. $index = $this->log;
  631. if($str){
  632. $str = ucfirst($str);
  633. $this->console['reports'][$index][] = $str; //Strore Report
  634. }else{
  635. if($index){
  636. return $this->console['reports'][$index]; //Return the $index Reports Array
  637. }else{
  638. return $this->console['reports']; //Return the Full Reports Array
  639. }
  640. }
  641. }
  642.  
  643. function error($str = false){
  644. $index = $this->log;
  645. if($str){
  646. $err = is_int($str) ? $this->errorList[$str] : $str;
  647. $this->console['errors'][$index][] = $err; //Store Error
  648. if(is_int($str)){
  649. $this->report("Error[{$str}]: {$err}"); //Report The error
  650. }else{
  651. $this->report("Error: {$str}"); //Report The error
  652. }
  653. }else{
  654. if($index){
  655. if(!isset($this->console['errors'][$index]))
  656. return false;
  657. return $this->console['errors'][$index]; //Return the $index Errors Array
  658. }else{
  659. return $this->console['errors']; //Return the Full Error Array
  660. }
  661. }
  662. }
  663.  
  664. //Adds fields with errors to the console
  665. function form_error($field = false,$error = false){
  666. $index = $this->log;
  667. if($field){
  668. if($error){
  669. $this->console['form'][$index][$field] = $error;
  670. $this->error($error);
  671. }else{
  672. $this->console['form'][$index][] = $field;
  673. }
  674. }else{
  675. if($index){
  676. if(!isset($this->console['form'][$index]))
  677. return false;
  678. return $this->console['form'][$index]; //Return the $index Errors Array
  679. }else{
  680. return $this->console['form']; //Return the Full form Array
  681. }
  682. }
  683. }
  684.  
  685. //Check for errors in the console
  686. function has_error($index = false){
  687. //Check for errors
  688. $index = $index?$index:$this->log;
  689. $count = @count($this->console['errors'][$index]);
  690. if($count){
  691. $this->report("$count Error(s) Found!");
  692. return true;
  693. }else{
  694. $this->report("No Error Found!");
  695. return false;
  696. }
  697. }
  698.  
  699. //Generates a unique comfirm hash
  700. function make_hash($uid,$hash = false){
  701. $e_uid = $this->encode($uid);
  702. $e_uid_length = strlen($e_uid);
  703. $e_uid_length = str_pad($e_uid_length,2,0,STR_PAD_LEFT);
  704. $e_uid_pos = rand(10,32 - $e_uid_length - 1);
  705.  
  706. if(!$hash){
  707. $hash = md5(uniqid(rand(),true));
  708. }
  709. //$code = substr($code, 0, $length);
  710. $code = $e_uid_pos.$e_uid_length;
  711. $code .= substr($hash,0,$e_uid_pos - strlen($code));
  712. $code .= $e_uid;
  713. $code .= substr($hash,strlen($code));
  714.  
  715. $this->confirm = $code;
  716. return $code;
  717. }
  718.  
  719. //Validates a confirmation hash
  720. function check_hash($hash,$bypass = false){
  721. if(strlen($hash) != 32 || !preg_match("/^[0-9]{4}/",$hash)){
  722. $this->error(11);
  723. return;
  724. }
  725.  
  726. $e_uid_pos = substr($hash,0,2);
  727. $e_uid_length = substr($hash,2,2);
  728. $e_uid = substr($hash,$e_uid_pos,$e_uid_length);
  729.  
  730. $uid = $this->decode($e_uid);
  731.  
  732. $sql = "SELECT * FROM {$this->opt['table_name']} WHERE user_id={$uid} AND confirmation='{$hash}'";
  733.  
  734. //Bypass hash confirmation and get the user by partially matching its password
  735. if($bypass){
  736. preg_match("/^([0-9]{4})(.{2,".($e_uid_pos - 4)."})(".$e_uid.")/",$hash,$exerpt);
  737. $pass = $exerpt[2];
  738. $sql = "SELECT * FROM {$this->opt['table_name']} WHERE user_id={$uid} AND password LIKE '{$pass}%'";
  739. }
  740.  
  741. $result = $this->getRow($sql);
  742.  
  743. if(!$result){
  744. $this->report("The user ID and the confirmation hash did not match");
  745. $this->error(12);
  746. return false;
  747. }
  748. if($this->signed and $this->id == $result['user_id']){
  749. $this->logout();
  750. }
  751.  
  752. //Hash is valid import user's info to object
  753. $this->data = $result;
  754. $this->id = $result['user_id'];
  755. $this->username = $result['username'];
  756. $this->pass = $result['password'];
  757.  
  758. $this->report("Hash successfully validated");
  759. return true;
  760. }
  761.  
  762. //Saves the confirmation hash in the database
  763. function save_hash(){
  764. if($this->confirm and $this->id){
  765. $sql = "UPDATE {$this->opt['table_name']} SET confirmation='{$this->confirm}', activated=0 WHERE user_id='{$this->id}'";
  766. if(!$this->check_sql($sql)){
  767. $this->error(13);
  768. return false;
  769. }else{
  770. $this->report("Confirmation hash has been saved");
  771. }
  772. }else{
  773. $this->report("Can't save Confirmation hash");
  774. return false;
  775. }
  776. return true;
  777. }
  778.  
  779. //Test field in database for a value
  780. function check_field($field,$val,$err = false){
  781. $query = mysql_query("SELECT {$field} FROM {$this->opt['table_name']} WHERE {$field}='{$val}' ");
  782. if(mysql_num_rows($query) >= 1){
  783. if($err){
  784. $this->form_error($field,$err);
  785. }else{
  786. $this->form_error($field,"The $field $val exists in database");
  787. }
  788. $this->report("There was a match for $field = $val");
  789. return true;
  790. }else{
  791. $this->report("No Match for $field = $val");
  792. return false;
  793. }
  794. }
  795.  
  796. //Executes SQL query and checks for success
  797. function check_sql($sql,$debug = false){
  798. $this->report("SQL: {$sql}"); //Log the SQL Query
  799. if(!mysql_query($sql)){
  800. if(self::debug){
  801. $this->error(mysql_error());
  802. }
  803. return false;
  804. }else{
  805. if($rows > 0){
  806. //Good, Rows where affected
  807. $this->report("$rows row(s) where Affected");
  808. return true;
  809. }else{
  810. //Bad, No Rows where Affected
  811. $this->report("No rows were Affected");
  812. return false;
  813. }
  814. }
  815. }
  816.  
  817. //Executes SQL query and returns an associate array of results
  818. function getRow($sql){
  819. $this->report("SQL: {$sql}"); //Log the SQL Query first
  820. $query = mysql_query($sql);
  821. if(mysql_error() and self::debug){
  822. $this->error(mysql_error());
  823. }
  824.  
  825. if(@mysql_num_rows($query)){
  826. while($row = mysql_fetch_array($query,MYSQL_ASSOC)){
  827. $rows[] = $row;
  828. }
  829. }else{
  830. $this->report("Query returned empty");
  831. return false;
  832. }
  833. return $rows[0];
  834. }
  835.  
  836.  
  837. //Validates All fields in ->tmp_data array
  838. private function validateAll(){
  839. $info = $this->tmp_data;
  840. foreach($info as $field => $val){
  841. //Match double fields
  842. if(isset($info[$field.(2)])){
  843. if($val != $info[$field.(2)]){
  844. $this->form_error($field, ucfirst($field) . "s did not match");
  845. //return false;
  846. }else{
  847. $this->report(ucfirst($field) . "s matched");
  848. }
  849. }
  850.  
  851. $this->tmp_data[$field] = trim($val); //Trim white spaces at end and start
  852.  
  853. //Validate field
  854. if(!isset($this->validations[$field]))
  855. continue;
  856. $opt = $this->validations[$field];
  857. $this->validate($field,$opt['limit'],$opt['regEx']);
  858. }
  859. return $this->has_error() ? false : true;
  860. }
  861.  
  862. //Validates field($name) in tmp_data
  863. private function validate($name,$limit,$regEx = false){
  864. $Name = ucfirst($name);
  865. $str = $this->tmp_data[$name];
  866. $l = explode("-",$limit);
  867. $min = intval($l[0]);
  868. $max = intval($l[1]);
  869. if(!$max and !$min){
  870. $this->error("Invalid second paramater for the $name validation");
  871. return false;
  872. }
  873. if(!$str){
  874. if(!isset($this->tmp_data[$name])){
  875. $this->report("missing index $name from the POST array");
  876. }
  877. if(strlen($str) == $min){
  878. $this->report("$Name is blank and optional - skipped");
  879. return true;
  880. }
  881. $this->form_error($name,"$Name is required.");
  882. return false;
  883. }
  884. if(strlen($str) > $max){
  885. $this->form_error($name,"The $Name is larger than $max characters.");
  886. return false;
  887. }
  888. if(strlen($str) < $min){
  889. $this->form_error($name,"The $Name is too short. it should at least be $min characters long");
  890. return false;
  891. }
  892. if($regEx){
  893. preg_match_all($regEx,$str,$match);
  894. if(count($match[0]) != 1){
  895. $this->form_error($name,"The $Name \"{$str}\" is not valid");
  896. return false;
  897. }
  898. }
  899.  
  900. $this->report("The $name is Valid");
  901. return true;
  902. }
  903.  
  904. //Encoder
  905. function encode($d){
  906. $k=$this->encoder;preg_match_all("/[1-9][0-9]|[0-9]/",$d,$a);$n="";$o=count($k);foreach($a[0]as$i){if($i<$o){
  907. $n.=$k[$i];}else{$n.="1".$k[$i-$o];}}
  908. return $n;
  909. }
  910. //Decoder
  911. function decode($d){
  912. $k=$this->encoder;preg_match_all("/[1][a-zA-Z]|[2-9]|[a-zA-Z]|[0]/",$d,$a);$n="";$o=count($k);foreach($a[0]as$i){
  913. $f=preg_match("/1([a-zA-Z])/",$i,$v);if($f==true){ $i=$o+array_search($v[1],$k);}else{$i=array_search($i,$k);}$n.=$i;}
  914. return $n;
  915. }
  916. }
  917. ?>

URL: http://crusthq.com/projects/uflex/

Report this snippet


Comments

RSS Icon Subscribe to comments

You need to login to post a comment.