1. //FROM SKYPILOT ON STACK OVERFLOW
  2.  
  3. <?php
  4.  
  5. class Bcrypt {
  6. private $rounds;
  7. public function __construct($rounds = 12) {
  8. if(CRYPT_BLOWFISH != 1) {
  9. throw new Exception("bcrypt not supported in this installation. See http://php.net/crypt");
  10. }
  11.  
  12. $this->rounds = $rounds;
  13. }
  14.  
  15. public function hash($input) {
  16. $hash = crypt($input, $this->getSalt());
  17.  
  18. if(strlen($hash) > 13)
  19. return $hash;
  20.  
  21. return false;
  22. }
  23.  
  24. public function verify($input, $existingHash) {
  25. $hash = crypt($input, $existingHash);
  26.  
  27. return $hash === $existingHash;
  28. }
  29.  
  30. private function getSalt() {
  31. $salt = sprintf('$2a$%02d$', $this->rounds);
  32.  
  33. $bytes = $this->getRandomBytes(16);
  34.  
  35. $salt .= $this->encodeBytes($bytes);
  36.  
  37. return $salt;
  38. }
  39.  
  40. private $randomState;
  41. private function getRandomBytes($count) {
  42. $bytes = '';
  43.  
  44. if(function_exists('openssl_random_pseudo_bytes') &&
  45. (strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN')) { // OpenSSL slow on Win
  46. $bytes = openssl_random_pseudo_bytes($count);
  47. }
  48.  
  49. if($bytes === '' && is_readable('/dev/urandom') &&
  50. ($hRand = @fopen('/dev/urandom', 'rb')) !== FALSE) {
  51. $bytes = fread($hRand, $count);
  52. fclose($hRand);
  53. }
  54.  
  55. if(strlen($bytes) < $count) {
  56. $bytes = '';
  57.  
  58. if($this->randomState === null) {
  59. $this->randomState = microtime();
  60. if(function_exists('getmypid')) {
  61. $this->randomState .= getmypid();
  62. }
  63. }
  64.  
  65. for($i = 0; $i < $count; $i += 16) {
  66. $this->randomState = md5(microtime() . $this->randomState);
  67.  
  68. if (PHP_VERSION >= '5') {
  69. $bytes .= md5($this->randomState, true);
  70. } else {
  71. $bytes .= pack('H*', md5($this->randomState));
  72. }
  73. }
  74.  
  75. $bytes = substr($bytes, 0, $count);
  76. }
  77.  
  78. return $bytes;
  79. }
  80.  
  81. private function encodeBytes($input) {
  82. // The following is code from the PHP Password Hashing Framework
  83. $itoa64 = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
  84.  
  85. $output = '';
  86. $i = 0;
  87. do {
  88. $c1 = ord($input[$i++]);
  89. $output .= $itoa64[$c1 >> 2];
  90. $c1 = ($c1 & 0x03) << 4;
  91. if ($i >= 16) {
  92. $output .= $itoa64[$c1];
  93. break;
  94. }
  95.  
  96. $c2 = ord($input[$i++]);
  97. $c1 |= $c2 >> 4;
  98. $output .= $itoa64[$c1];
  99. $c1 = ($c2 & 0x0f) << 2;
  100.  
  101. $c2 = ord($input[$i++]);
  102. $c1 |= $c2 >> 6;
  103. $output .= $itoa64[$c1];
  104. $output .= $itoa64[$c2 & 0x3f];
  105. } while (1);
  106.  
  107. return $output;
  108. }
  109. }
  110.  
  111. class Register
  112. {
  113. // Protect the information from the public.
  114. private $username;
  115. private $password;
  116. private $passmd5;
  117. private $email;
  118. private $mii;
  119. private $vr;
  120. private $character;
  121. private $track;
  122. private $course;
  123. private $kart;
  124. private $wheel;
  125. private $glider;
  126. private $rank;
  127. private $fc;
  128.  
  129. private $errors;
  130. private $token;
  131.  
  132. // Tell the server to store the values from the following input field names.
  133. public function __construct()
  134. {
  135. $this->errors = array();
  136.  
  137. $this->username = $this->filter($_POST['ruser']);
  138. $this->password = $this->filter($_POST['rpass']);
  139. $this->email = $this->filter($_POST['remail']);
  140. $this->mii = $this->filter($_POST['rmii']);
  141. $this->vr = $this->filter($_POST['rvr']);
  142. $this->character = $this->filter($_POST['rcharacter']);
  143. $this->track = $this->filter($_POST['rtrack']);
  144. $this->course = $this->filter($_POST['rcourse']);
  145. $this->kart = $this->filter($_POST['rkart']);
  146. $this->wheel = $this->filter($_POST['rwheel']);
  147. $this->glider = $this->filter($_POST['rglider']);
  148. $this->rank = $this->filter($_POST['rrank']);
  149. $this->fc = $this->filter($_POST['rfc']);
  150. $this->token = $_POST['token'];
  151.  
  152. // $this->passmd5 = $bcrypt($this->password); Old method, still have for backup purposes.
  153. $bcrypt = new Bcrypt(15);
  154.  
  155. $hash = $bcrypt->hash($this->password);
  156. $isGood = $bcrypt->verify($this->password, $hash);
  157.  
  158. }
  159.  
  160. // Process the information.
  161. public function process()
  162. {
  163. if($this->valid_token() && $this->valid_data())
  164. $this->register();
  165.  
  166. return count($this->errors)? 0 : 1;
  167. }
  168.  
  169. public function filter($var)
  170. {
  171. return preg_replace('/[^a-zA-Z0-9@.]/','',$var);
  172. }
  173.  
  174. // Actually transfer the information from the form to the database.
  175. public function register()
  176. {
  177. mysql_connect("localhost","root","") or die(mysql_error());
  178. mysql_select_db("mk7") or die (mysql_error());
  179.  
  180. mysql_query("INSERT INTO users(username,password,email,mii,vr,character,track,course,kart,wheel,glider,rank,fc) VALUES ('{$this->username}','{$isGood}','{$this->email}','{$this->mii}','{$this->vr}','{$this->character}','{$this->track}','{$this->course}','{$this->kart}','{$this->wheel}','{$this->rank}','{$this->fc}')");
  181.  
  182. if(mysql_affected_rows()< 1)
  183. $this->errors[] = '&bull; Could not process form.';
  184. }
  185.  
  186. // Insert an ID based off of the username, and check to see if the user already exists.
  187. public function user_exists()
  188. {
  189. mysql_connect("localhost","root","") or die(mysql_error());
  190. mysql_select_db("mk7") or die (mysql_error());
  191.  
  192. $data = mysql_query("SELECT ID FROM users WHERE username = '{$this->username}'");
  193.  
  194. return mysql_num_rows($data)? 1 : 0;
  195. }
  196.  
  197. // Show the errors.
  198. public function show_errors()
  199. {
  200. echo "<h3>Errors</h3>";
  201.  
  202. foreach($this->errors as $key=>$value)
  203. echo $value."<br>";
  204. }
  205.  
  206. // Errors to show.
  207. public function valid_data()
  208. {
  209. if($this->user_exists())
  210. $this->errors[] = '&bull; Username already taken.';
  211. if(empty($this->username))
  212. $this->errors[] = '&bull; Invalid username.';
  213. if(empty($this->password))
  214. $this->errors[] = '&bull; Invalid password.';
  215. if(empty($this->email) || !preg_match('/^([a-zA-Z0-9])+([a-zA-Z0-9\._-])*@([a-zA-Z0-9_-])+([a-zA-Z0-9\._-]+)+$/',$this->email))
  216. $this->errors[] = '&bull; Invalid email.';
  217.  
  218. return count($this->errors)? 0 : 1;
  219. }
  220.  
  221. // If everything is okay go through with the form.
  222. public function valid_token()
  223. {
  224. if(!isset($_SESSION['token']) || $this->token != $_SESSION['token'])
  225. $this->errors[] = '&bull; Invalid submission.';
  226.  
  227. return count($this->errors)? 0 : 1;
  228. }
  229. }
  230.  
  231. ?>