Advertisement
Guest User

Untitled

a guest
Apr 14th, 2019
134
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.75 KB | None | 0 0
  1. <?php
  2.  
  3. /**
  4. * This file is part of SimpleUsers.
  5. *
  6. */
  7.  
  8. /**
  9. * SimpleUsers is a small-scale and flexible way of adding
  10. * user management to your website or web applications.
  11. */
  12.  
  13. class SimpleUsers
  14. {
  15.  
  16. private $mysqli, $stmt;
  17. private $sessionName = "SimpleUsers";
  18. public $logged_in = false;
  19. public $userdata;
  20.  
  21. /**
  22. * Object construct verifies that a session has been started and that a MySQL connection can be established.
  23. * It takes no parameters.
  24. *
  25. * @exception Exception If a session id can't be returned.
  26. */
  27.  
  28. public function __construct()
  29. {
  30. $sessionId = session_id();
  31. if( strlen($sessionId) == 0)
  32. throw new Exception("No session has been started.\n<br />Please add `session_start();` initially in your file before any output.");
  33.  
  34. $this->mysqli = new mysqli($GLOBALS["mysql_hostname"], $GLOBALS["mysql_username"], $GLOBALS["mysql_password"], $GLOBALS["mysql_database"]);
  35. if( $this->mysqli->connect_error )
  36. throw new Exception("MySQL connection could not be established: ".$this->mysqli->connect_error);
  37.  
  38. $this->_validateUser();
  39. $this->_populateUserdata();
  40. $this->_updateActivity();
  41. }
  42.  
  43. /**
  44. * Returns a (int)user id, if the user was created succesfully.
  45. * If not, it returns (bool)false.
  46. *
  47. * @param username The desired username
  48. * @param password The desired password
  49. * @return The user id or (bool)false (if the user already exists)
  50. */
  51.  
  52. public function createUser( $username, $password )
  53. {
  54. $salt = $this->_generateSalt();
  55. $password = $salt.$password;
  56.  
  57. $sql = "INSERT INTO users VALUES (NULL, ?, SHA1(?), ?, NOW(), NOW())";
  58. if( !$this->stmt = $this->mysqli->prepare($sql) )
  59. throw new Exception("MySQL Prepare statement failed: ".$this->mysqli->error);
  60.  
  61. $this->stmt->bind_param("sss", $username, $password, $salt);
  62. if( $this->stmt->execute() )
  63. return $this->stmt->insert_id;
  64.  
  65. return false;
  66. }
  67.  
  68. /**
  69. * Pairs up username and password as registrered in the database.
  70. * If the username and password is correct, it will return (int)user id of
  71. * the user which credentials has been passed and set the session, for
  72. * use by the user validating.
  73. *
  74. * @param username The username
  75. * @param password The password
  76. * @return The (int)user id or (bool)false
  77. */
  78.  
  79. public function loginUser( $username, $password )
  80. {
  81. $sql = "SELECT userId FROM users WHERE uUsername=? AND SHA1(CONCAT(uSalt, ?))=uPassword LIMIT 1";
  82. if( !$this->stmt = $this->mysqli->prepare($sql) )
  83. throw new Exception("MySQL Prepare statement failed: ".$this->mysqli->error);
  84.  
  85. $this->stmt->bind_param("ss", $username, $password);
  86. $this->stmt->execute();
  87. $this->stmt->store_result();
  88.  
  89. if( $this->stmt->num_rows == 0)
  90. return false;
  91.  
  92. $this->stmt->bind_result($userId);
  93. $this->stmt->fetch();
  94.  
  95. $_SESSION[$this->sessionName]["userId"] = $userId;
  96. $this->logged_in = true;
  97. $_SESSION[$this->sessionName]["isAdmin"] = $username == "admin";
  98.  
  99. return $userId;
  100. }
  101.  
  102. /**
  103. * Sets an information pair, consisting of a key name and that keys value.
  104. * The information can be retrieved with this objects getInfo() method.
  105. *
  106. * @param key The name of the key
  107. * @param value The keys value
  108. * @param userId Can be used if administrative control is needed
  109. * @return This returns (bool)true or false.
  110. */
  111.  
  112. public function setInfo( $key, $value, $userId = null)
  113. {
  114. if($userId == null)
  115. {
  116. if( !$this->logged_in )
  117. return false;
  118. }
  119.  
  120. $reservedKeys = array("userId", "uUsername", "uActivity", "uCreated", "uLevel");
  121. if( in_array($key, $reservedKeys) )
  122. throw new Exception("User information key \"".$key."\" is reserved for internal use!");
  123.  
  124. if( $userId == null )
  125. $userId = $_SESSION[$this->sessionName]["userId"];
  126.  
  127. if( $this->getInfo($key, $userId) )
  128. {
  129. $sql = "UPDATE users_information SET infoValue=? WHERE infoKey=? AND userId=? LIMIT 1";
  130. if( !$this->stmt = $this->mysqli->prepare($sql) )
  131. throw new Exception("MySQL Prepare statement failed: ".$this->mysqli->error);
  132.  
  133. $this->stmt->bind_param("ssi", $value, $key, $userId);
  134. $this->stmt->execute();
  135. }
  136. else
  137. {
  138. $sql = "INSERT INTO users_information VALUES (?, ?, ?)";
  139. if( !$this->stmt = $this->mysqli->prepare($sql) )
  140. throw new Exception("MySQL Prepare statement failed: ".$this->mysqli->error);
  141.  
  142. $this->stmt->bind_param("iss", $userId, $key, $value);
  143. $this->stmt->execute();
  144. }
  145.  
  146. return true;
  147. }
  148.  
  149. /**
  150. * Use this function to retrieve user information attached to a certain user
  151. * that has been set by using this objects setInfo() method.
  152. *
  153. * @param key The name of the key you wan't the value from
  154. * @param userId Can be used if administrative control is needed
  155. * @return String with a given keys value or (bool) false if the user isn't logged in.
  156. */
  157.  
  158. public function getInfo( $key, $userId = null )
  159. {
  160.  
  161. if( $userId == null )
  162. {
  163. if( !$this->logged_in )
  164. return false;
  165.  
  166. $userId = $_SESSION[$this->sessionName]["userId"];
  167. }
  168.  
  169. $sql = "SELECT infoValue FROM users_information WHERE userId=? AND infoKey=? LIMIT 1";
  170. if( !$this->stmt = $this->mysqli->prepare($sql) )
  171. throw new Exception("MySQL Prepare statement failed: ".$this->mysqli->error);
  172.  
  173. $this->stmt->bind_param("is", $userId, $key);
  174. $this->stmt->execute();
  175. $this->stmt->store_result();
  176.  
  177. if( $this->stmt->num_rows == 0)
  178. return "";
  179.  
  180. $this->stmt->bind_result($value);
  181. $this->stmt->fetch();
  182.  
  183. return $value;
  184.  
  185. }
  186.  
  187. /**
  188. * Use this function to permanently remove information attached to a certain user
  189. * that has been set by using this objects setInfo() method.
  190. *
  191. * @param key The name of the key you wan't the value from
  192. * @param userId Can be used if administrative control is needed
  193. * @return (bool) true on success or (bool) false if the user isn't logged in.
  194. */
  195.  
  196. public function removeInfo( $key, $userId = null )
  197. {
  198.  
  199. if( $userId == null )
  200. {
  201. if( !$this->logged_in )
  202. return false;
  203.  
  204. $userId = $_SESSION[$this->sessionName]["userId"];
  205. }
  206.  
  207. $sql = "DELETE FROM users_information WHERE userId=? AND infoKey=? LIMIT 1";
  208. if( !$this->stmt = $this->mysqli->prepare($sql) )
  209. throw new Exception("MySQL Prepare statement failed: ".$this->mysqli->error);
  210.  
  211. $this->stmt->bind_param("is", $userId, $key);
  212. $this->stmt->execute();
  213.  
  214. if( $this->stmt->affected_rows > 0)
  215. return true;
  216.  
  217. return false;
  218. }
  219.  
  220.  
  221. /**
  222. * Use this function to retrieve all user information attached to a certain user
  223. * that has been set by using this objects setInfo() method into an array.
  224. *
  225. * @param userId Can be used if administrative control is needed
  226. * @return An associative array with all stored information
  227. */
  228.  
  229. public function getInfoArray( $userId = null )
  230. {
  231. if( $userId == null )
  232. $userId = $_SESSION[$this->sessionName]["userId"];
  233.  
  234. $sql = "SELECT infoKey, infoValue FROM users_information WHERE userId=? ORDER BY infoKey ASC";
  235. if( !$this->stmt = $this->mysqli->prepare($sql) )
  236. throw new Exception("MySQL Prepare statement failed: ".$this->mysqli->error);
  237.  
  238. $this->stmt->bind_param("i", $userId);
  239. $this->stmt->execute();
  240. $this->stmt->store_result();
  241.  
  242. $userInfo = array();
  243. if( $this->stmt->num_rows > 0)
  244. {
  245. $this->stmt->bind_result($key, $value);
  246. while( $this->stmt->fetch() )
  247. $userInfo[$key] = $value;
  248. }
  249.  
  250. $user = $this->getSingleUser($userId);
  251. $userInfo = array_merge($userInfo, $user);
  252. asort($userInfo);
  253.  
  254. return $userInfo;
  255. }
  256.  
  257. /**
  258. * Logout the active user, unsetting the userId session.
  259. * This is a void function
  260. */
  261.  
  262. public function logoutUser()
  263. {
  264. if( isset($_SESSION[$this->sessionName]) )
  265. unset($_SESSION[$this->sessionName]);
  266.  
  267. $this->logged_in = false;
  268. $_SESSION[$this->sessionName]["isAdmin"] = false;
  269. }
  270.  
  271. /**
  272. * Update the users password with this function.
  273. * Generates a new salt and a sets the users password with the given parameter
  274. *
  275. * @param password The new password
  276. * @param userId Can be used if administrative control is needed
  277. */
  278.  
  279. public function setPassword( $password, $userId = null )
  280. {
  281.  
  282. if( $userId == null )
  283. $userId = $_SESSION[$this->sessionName]["userId"];
  284.  
  285. $salt = $this->_generateSalt();
  286. $password = $salt.$password;
  287.  
  288. $sql = "UPDATE users SET uPassword=SHA1(?), uSalt=? WHERE userId=? LIMIT 1";
  289. if( !$this->stmt = $this->mysqli->prepare($sql) )
  290. throw new Exception("MySQL Prepare statement failed: ".$this->mysqli->error);
  291.  
  292. $this->stmt->bind_param("ssi", $password, $salt, $userId);
  293. return $this->stmt->execute();
  294. }
  295.  
  296. /**
  297. * Returns an array with each user in the database.
  298. *
  299. * @return An array with user information
  300. */
  301.  
  302. public function getUsers()
  303. {
  304.  
  305. $sql = "SELECT DISTINCT userId, uUsername, uActivity, uCreated FROM users ORDER BY uUsername ASC";
  306.  
  307. if( !$this->stmt = $this->mysqli->prepare($sql) )
  308. throw new Exception("MySQL Prepare statement failed: ".$this->mysqli->error);
  309.  
  310. $this->stmt->execute();
  311. $this->stmt->store_result();
  312.  
  313. if( $this->stmt->num_rows == 0)
  314. return array();
  315.  
  316. $this->stmt->bind_result($userId, $username, $activity, $created);
  317.  
  318. $users = array();
  319.  
  320. $i = 0;
  321. while( $this->stmt->fetch() )
  322. {
  323. $users[$i]["userId"] = $userId;
  324. $users[$i]["uUsername"] = $username;
  325. $users[$i]["uActivity"] = $activity;
  326. $users[$i]["uCreated"] = $created;
  327.  
  328. $i++;
  329. }
  330.  
  331. return $users;
  332.  
  333. }
  334.  
  335. /**
  336. * Gets the basic info for a single user based on the userId
  337. *
  338. * @param userId The users id
  339. * @return An array with the result or (bool)false.
  340. */
  341.  
  342. public function getSingleUser( $userId = null )
  343. {
  344.  
  345. if( $userId == null )
  346. $userId = $_SESSION[$this->sessionName]["userId"];
  347.  
  348. $sql = "SELECT userId, uUsername, uActivity, uCreated FROM users WHERE userId=? LIMIT 1";
  349. if( !$this->stmt = $this->mysqli->prepare($sql) )
  350. throw new Exception("MySQL Prepare statement failed: ".$this->mysqli->error);
  351.  
  352. $this->stmt->bind_param("i", $userId);
  353. $this->stmt->execute();
  354. $this->stmt->store_result();
  355.  
  356. if( $this->stmt->num_rows == 0)
  357. return false;
  358.  
  359. $this->stmt->bind_result($userId, $username, $activity, $created);
  360. $this->stmt->fetch();
  361.  
  362. $user["userId"] = $userId;
  363. $user["uUsername"] = $username;
  364. $user["uActivity"] = $activity;
  365. $user["uCreated"] = $created;
  366.  
  367. return $user;
  368.  
  369. }
  370.  
  371. /**
  372. * Deletes all information regarding a user.
  373. * This is a void function.
  374. *
  375. * @param userId The userId of the user you wan't to delete
  376. */
  377.  
  378. public function deleteUser( $userId )
  379. {
  380. $sql = "DELETE FROM users WHERE userId=?";
  381. if( !$this->stmt = $this->mysqli->prepare($sql) )
  382. throw new Exception("MySQL Prepare statement failed: ".$this->mysqli->error);
  383.  
  384. $this->stmt->bind_param("i", $userId);
  385. $this->stmt->execute();
  386.  
  387. $sql = "DELETE FROM users_information WHERE userId=?";
  388. if( !$this->stmt = $this->mysqli->prepare($sql) )
  389. throw new Exception("MySQL Prepare statement failed: ".$this->mysqli->error);
  390.  
  391. $this->stmt->bind_param("i", $userId);
  392. $this->stmt->execute();
  393.  
  394. return;
  395. }
  396.  
  397. /**
  398. * Returns a hidden input field with a unique token value
  399. * for CSRF to be used with post data.
  400. * The token is saved in a session for later validation.
  401. *
  402. * @param xhtml set to (bool) true for xhtml output
  403. * @return Returns a string with a HTML element and attributes
  404. */
  405.  
  406. public function getToken( $xhtml = true )
  407. {
  408. $token = $this->_generateSalt();
  409. $name = "token_".md5($token);
  410.  
  411. $_SESSION[$this->sessionName]["csrf_name"] = $name;
  412. $_SESSION[$this->sessionName]["csrf_token"] = $token;
  413.  
  414. $string = "<input type=\"hidden\" name=\"".$name."\" value=\"".$token."\"";
  415. if($xhtml)
  416. $string .= " />";
  417. else
  418. $string .= ">";
  419.  
  420. return $string;
  421. }
  422.  
  423. /**
  424. * Use this method when you wish to validate the CSRF token from your post data.
  425. * The method returns true upon validation, otherwise false.
  426. *
  427. * @return bool true or false
  428. */
  429.  
  430. public function validateToken()
  431. {
  432. $name = $_SESSION[$this->sessionName]["csrf_name"];
  433. $token = $_SESSION[$this->sessionName]["csrf_token"];
  434. unset($_SESSION[$this->sessionName]["csrf_token"]);
  435. unset($_SESSION[$this->sessionName]["csrf_name"]);
  436.  
  437. if($_POST[$name] == $token)
  438. return true;
  439.  
  440. return false;
  441. }
  442.  
  443. /**
  444. * This function updates the users last activity time
  445. * This is a void function.
  446. */
  447.  
  448. private function _updateActivity()
  449. {
  450. if( !$this->logged_in )
  451. return;
  452.  
  453. $userId = $_SESSION[$this->sessionName]["userId"];
  454.  
  455. $sql = "UPDATE users SET uActivity=NOW() WHERE userId=? LIMIT 1";
  456. if( !$this->stmt = $this->mysqli->prepare($sql) )
  457. throw new Exception("MySQL Prepare statement failed: ".$this->mysqli->error);
  458.  
  459. $this->stmt->bind_param("i", $userId);
  460. $this->stmt->execute();
  461. return;
  462. }
  463.  
  464. /**
  465. * Validates if the user is logged in or not.
  466. * This is a void function.
  467. */
  468.  
  469. private function _validateUser()
  470. {
  471. if( !isset($_SESSION[$this->sessionName]["userId"]) )
  472. return;
  473.  
  474. if( !$this->_validateUserId() )
  475. return;
  476.  
  477. $this->logged_in = true;
  478. }
  479.  
  480. /**
  481. * Validates if the user id, in the session is still valid.
  482. *
  483. * @return Returns (bool)true or false
  484. */
  485.  
  486. private function _validateUserId()
  487. {
  488. $userId = $_SESSION[$this->sessionName]["userId"];
  489.  
  490. $sql = "SELECT userId FROM users WHERE userId=? LIMIT 1";
  491. if( !$this->stmt = $this->mysqli->prepare($sql) )
  492. throw new Exception("MySQL Prepare statement failed: ".$this->mysqli->error);
  493.  
  494. $this->stmt->bind_param("i", $userId);
  495. $this->stmt->execute();
  496. $this->stmt->store_result();
  497.  
  498. if( $this->stmt->num_rows == 1)
  499. return true;
  500.  
  501. $this->logoutUser();
  502.  
  503. return false;
  504. }
  505.  
  506. /**
  507. * Populates the current users data information for
  508. * quick access as an object.
  509. *
  510. * @return void
  511. */
  512.  
  513. private function _populateUserdata()
  514. {
  515. $this->userdata = array();
  516.  
  517. if( $this->logged_in )
  518. {
  519. $userId = $_SESSION[$this->sessionName]["userId"];
  520. $data = $this->getInfoArray();
  521. foreach($data as $key => $value)
  522. $this->userdata[$key] = $value;
  523.  
  524. }
  525. }
  526.  
  527. /**
  528. * Generates a 128 len string used as a random salt for
  529. * securing you oneway encrypted password
  530. *
  531. * @return String with 128 characters
  532. */
  533.  
  534. private function _generateSalt()
  535. {
  536. $salt = null;
  537.  
  538. while( strlen($salt) < 128 )
  539. $salt = $salt.uniqid(null, true);
  540.  
  541. return substr($salt, 0, 128);
  542. }
  543.  
  544.  
  545. }
  546.  
  547. ?>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement