PageRenderTime 43ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/code/web/private_php/ams/autoload/users.php

https://bitbucket.org/ryzom/ryzomcore
PHP | 509 lines | 323 code | 43 blank | 143 comment | 77 complexity | d6ad011f0b87fca286fdc2538a9ab658 MD5 | raw file
Possible License(s): Apache-2.0, AGPL-3.0, GPL-3.0, LGPL-2.1
  1. <?php
  2. /**
  3. * handles basic user registration & management functions (shard related).
  4. * The Users class is the basis class of WebUsers, this class provides functions being used by all CMS's and our own www version. The WebUsers class however needs to be reimplemented
  5. * by using the CMS's it's funcionality. This class handles the writing to the shard db mainly, and in case it's offline: writing to the ams_querycache.
  6. * @author Daan Janssens, mentored by Matthew Lagoe
  7. */
  8. class Users{
  9. /**
  10. * checks if entered values before registering are valid.
  11. * @param $values array with Username,Password, ConfirmPass and Email.
  12. * @return string Info: Returns a string, if input data is valid then "success" is returned, else an array with errors
  13. */
  14. public function check_Register($values){
  15. // check values
  16. if ( isset( $values["Username"] ) and isset( $values["Password"] ) and isset( $values["ConfirmPass"] ) and isset( $values["Email"] ) ){
  17. $user = Users::checkUser( $values["Username"] );
  18. $pass = Users::checkPassword( $values["Password"] );
  19. $cpass = Users::confirmPassword($pass,$values["Password"],$values["ConfirmPass"]);
  20. $email = Users::checkEmail( $values["Email"] );
  21. }else{
  22. $user = "";
  23. $pass = "";
  24. $cpass = "";
  25. $email = "";
  26. }
  27. if ( helpers :: check_if_game_client() or isset($FORCE_INGAME) ) {
  28. if ( isset( $_POST["TaC"] )) {
  29. $tac="success";
  30. }
  31. } else {
  32. $tac="success";
  33. }
  34. if ( ( $user == "success" ) and ( $pass == "success" ) and ( $cpass == "success" ) and ( $email == "success" ) and ($tac=="success") ){
  35. return "success";
  36. }else{
  37. global $TOS_URL;
  38. $pageElements = array(
  39. //'GAME_NAME' => $GAME_NAME,
  40. // 'WELCOME_MESSAGE' => $WELCOME_MESSAGE,
  41. 'USERNAME' => $user,
  42. 'PASSWORD' => $pass,
  43. 'CPASSWORD' => $cpass,
  44. 'EMAIL' => $email,
  45. 'TOS_URL' => $TOS_URL
  46. );
  47. if ( $user != "success" ){
  48. $pageElements['USERNAME_ERROR'] = 'TRUE';
  49. }else{
  50. $pageElements['USERNAME_ERROR'] = 'FALSE';
  51. }
  52. if ( $pass != "success" ){
  53. $pageElements['PASSWORD_ERROR'] = 'TRUE';
  54. }else{
  55. $pageElements['PASSWORD_ERROR'] = 'FALSE';
  56. }
  57. if ( $cpass != "success" ){
  58. $pageElements['CPASSWORD_ERROR'] = 'TRUE';
  59. }else{
  60. $pageElements['CPASSWORD_ERROR'] = 'FALSE';
  61. }
  62. if ( $email != "success" ){
  63. $pageElements['EMAIL_ERROR'] = 'TRUE';
  64. }else{
  65. $pageElements['EMAIL_ERROR'] = 'FALSE';
  66. }
  67. if ( isset( $_POST["TaC"] ) ){
  68. $pageElements['TAC_ERROR'] = 'FALSE';
  69. }else{
  70. $pageElements['TAC_ERROR'] = 'TRUE';
  71. }
  72. return $pageElements;
  73. }
  74. }
  75. /**
  76. * checks if entered username is valid.
  77. * @param $username the username that the user wants to use.
  78. * @return string Info: Returns a string based on if the username is valid, if valid then "success" is returned
  79. */
  80. public function checkUser( $username )
  81. {
  82. if ( isset( $username ) ){
  83. if ( strlen( $username ) > 12 ){
  84. return "Username must be no more than 12 characters.";
  85. }else if ( strlen( $username ) < 5 ){
  86. return "Username must be 5 or more characters.";
  87. }else if ( !preg_match( '/^[a-z0-9\.]*$/', $username ) ){
  88. return "Username can only contain numbers and letters.";
  89. }else if ( $username == "" ){
  90. return "You have to fill in a username";
  91. }elseif ($this->checkUserNameExists($username)){
  92. return "Username " . $username . " is in use.";
  93. }else{
  94. return "success";
  95. }
  96. }
  97. return "fail";
  98. }
  99. /**
  100. * check if username already exists.
  101. * This is the base function, it should be overwritten by the WebUsers class.
  102. * @param $username the username
  103. * @return string Info: Returns true or false if the user is in the www db.
  104. */
  105. protected function checkUserNameExists($username){
  106. //You should overwrite this method with your own version!
  107. print('this is the base class!');
  108. }
  109. /**
  110. * checks if the password is valid.
  111. * @param $pass the password willing to be used.
  112. * @return string Info: Returns a string based on if the password is valid, if valid then "success" is returned
  113. */
  114. public function checkPassword( $pass )
  115. {
  116. if ( isset( $pass ) ){
  117. if ( strlen( $pass ) > 20 ){
  118. return "Password must be no more than 20 characters.";
  119. }elseif ( strlen( $pass ) < 5 ){
  120. return "Password must be more than 5 characters.";
  121. }elseif ( $pass == ""){
  122. return "You have to fill in a password";
  123. }else{
  124. return "success";
  125. }
  126. }
  127. return "fail";
  128. }
  129. /**
  130. * checks if the confirmPassword matches the original.
  131. * @param $pass_result the result of the previous password check.
  132. * @param $pass the original pass.
  133. * @param $confirmpass the confirmation password.
  134. * @return string Info: Verify's $_POST["Password"] is the same as $_POST["ConfirmPass"]
  135. */
  136. private function confirmPassword($pass_result,$pass,$confirmpass)
  137. {
  138. if ($confirmpass==""){
  139. return "You have to fill in the confirmation password.";
  140. }
  141. else if ( ( $pass ) != ( $confirmpass ) ){
  142. return "Passwords do not match.";
  143. }else if($pass_result != "success"){
  144. return;
  145. }else{
  146. return "success";
  147. }
  148. return "fail";
  149. }
  150. /**
  151. * wrapper to check if the email address is valid.
  152. * @param $email the email address
  153. * @return "success", else in case it isn't valid an error will be returned.
  154. */
  155. public function checkEmail( $email )
  156. {
  157. if ( isset( $email ) ){
  158. if ( !Users::validEmail( $email ) ){
  159. return "Email address is not valid.";
  160. }else if($email == ""){
  161. return "You have to fill in an email address";
  162. }else if ($this->checkEmailExists($email)){
  163. return "Email is in use.";
  164. }else{
  165. return "success";
  166. }
  167. }
  168. return "fail";
  169. }
  170. /**
  171. * check if email already exists.
  172. * This is the base function, it should be overwritten by the WebUsers class.
  173. * @param $email the email address
  174. * @return string Info: Returns true or false if the email is in the www db.
  175. */
  176. protected function checkEmailExists($email){
  177. //TODO: You should overwrite this method with your own version!
  178. print('this is the base class!');
  179. }
  180. /**
  181. * check if the emailaddress structure is valid.
  182. * @param $email the email address
  183. * @return true or false
  184. */
  185. public static function validEmail( $email ){
  186. $isValid = true;
  187. $atIndex = strrpos( $email, "@" );
  188. if ( is_bool( $atIndex ) && !$atIndex ){
  189. $isValid = false;
  190. }else{
  191. $domain = substr( $email, $atIndex + 1 );
  192. $local = substr( $email, 0, $atIndex );
  193. $localLen = strlen( $local );
  194. $domainLen = strlen( $domain );
  195. if ( $localLen < 1 || $localLen > 64 ){
  196. // local part length exceeded
  197. $isValid = false;
  198. }else if ( $domainLen < 1 || $domainLen > 255 ){
  199. // domain part length exceeded
  200. $isValid = false;
  201. }else if ( $local[0] == '.' || $local[$localLen - 1] == '.' ){
  202. // local part starts or ends with '.'
  203. $isValid = false;
  204. }else if ( preg_match( '/\\.\\./', $local ) ){
  205. // local part has two consecutive dots
  206. $isValid = false;
  207. }else if ( !preg_match( '/^[A-Za-z0-9\\-\\.]+$/', $domain ) ){
  208. // character not valid in domain part
  209. $isValid = false;
  210. }else if ( preg_match( '/\\.\\./', $domain ) ){
  211. // domain part has two consecutive dots
  212. $isValid = false;
  213. }else if ( !preg_match( '/^(\\\\.|[A-Za-z0-9!#%&`_=\\/$\'*+?^{}|~.-])+$/', str_replace( "\\\\", "", $local ) ) ){
  214. // character not valid in local part unless
  215. // local part is quoted
  216. if ( !preg_match( '/^"(\\\\"|[^"])+"$/', str_replace( "\\\\", "", $local ) ) ){
  217. $isValid = false;
  218. }
  219. }
  220. if ( $isValid && !( checkdnsrr( $domain, "MX" ) || checkdnsrr( $domain, "A" ) ) ){
  221. // domain not found in DNS
  222. $isValid = false;
  223. }
  224. }
  225. return $isValid;
  226. }
  227. /**
  228. * generate a SALT.
  229. * @param $length the length of the SALT which is by default 2
  230. * @return a random salt of 2 chars
  231. */
  232. public static function generateSALT( $length = 16 )
  233. {
  234. // start with a blank salt
  235. $salt = "";
  236. // define possible characters - any character in this string can be
  237. // picked for use in the salt, so if you want to put vowels back in
  238. // or add special characters such as exclamation marks, this is where
  239. // you should do it
  240. $possible = "2346789bcdfghjkmnpqrtvwxyzBCDFGHJKLMNPQRTVWXYZ";
  241. // we refer to the length of $possible a few times, so let's grab it now
  242. $maxlength = strlen( $possible );
  243. // check for length overflow and truncate if necessary
  244. if ( $length > $maxlength ){
  245. $length = $maxlength;
  246. }
  247. // set up a counter for how many characters are in the salt so far
  248. $i = 0;
  249. // add random characters to $salt until $length is reached
  250. while ( $i < $length ){
  251. // pick a random character from the possible ones
  252. $char = substr( $possible, mt_rand( 0, $maxlength - 1 ), 1 );
  253. // have we already used this character in $salt?
  254. if ( !strstr( $salt, $char ) ){
  255. // no, so it's OK to add it onto the end of whatever we've already got...
  256. $salt .= $char;
  257. // ... and increase the counter by one
  258. $i++;
  259. }
  260. }
  261. // done!
  262. if ($length > 2)
  263. {
  264. $salt = '$6$'.$salt;
  265. }
  266. return $salt;
  267. }
  268. /**
  269. * creates a user in the shard.
  270. * incase the shard is offline it will place it in the ams_querycache. You have to create a user first in the CMS/WWW and use the id for this function.
  271. * @param $values with name,pass and mail
  272. * @param $user_id the extern id of the user (the id given by the www/CMS)
  273. * @return ok if it's get correctly added to the shard, else return lib offline and put in libDB, if libDB is also offline return liboffline.
  274. */
  275. public static function createUser($values, $user_id) {
  276. ticket_user::createTicketUser($user_id, 1);
  277. try {
  278. //make connection with and put into shard db
  279. $values["UId"] = $user_id;
  280. $dbs = new DBLayer("shard");
  281. $dbs->insert("user", $values);
  282. /*
  283. $dbr = new DBLayer("ring");
  284. $valuesRing['user_id'] =$user_id;
  285. $valuesRing['user_name'] = $values['Login'];
  286. $valuesRing['user_type'] = 'ut_pioneer';
  287. $dbr->insert("ring_users", $valuesRing);
  288. */
  289. return "ok";
  290. }
  291. catch (PDOException $e) {
  292. //oh noooz, the shard is offline! Put in query queue at ams_lib db!
  293. try {
  294. $dbl = new DBLayer("lib");
  295. $dbl->insert("ams_querycache", array("type" => "createUser",
  296. "query" => json_encode(array($values["Login"], $values["Password"], $values["Email"])), "db" => "shard"));
  297. return "shardoffline";
  298. } catch (PDOException $e) {
  299. print_r($e);
  300. return "liboffline";
  301. }
  302. }
  303. }
  304. /**
  305. * creates permissions in the shard db for a user.
  306. * incase the shard is offline it will place it in the ams_querycache.
  307. * @param $pvalues with username
  308. */
  309. public static function createPermissions($pvalues) {
  310. try {
  311. $values = array('username' => $pvalues[0]);
  312. $dbs = new DBLayer("shard");
  313. $sth = $dbs->selectWithParameter("UId", "user", $values, "Login= :username");
  314. $result = $sth->fetchAll();
  315. $dbl = new DBLayer("lib");
  316. $UId = $result['0']['UId'];
  317. $statement = $dbl->execute("SELECT * FROM `settings` WHERE `Setting` = :setting", Array('setting' => 'Domain_Auto_Add'));
  318. $json = $statement->fetch();
  319. $json = json_decode($json['Value'],true);
  320. $db = new DBLayer( 'shard' );
  321. // get all domains
  322. $statement = $db -> executeWithoutParams( "SELECT * FROM domain" );
  323. $rows = $statement -> fetchAll();
  324. //error_log(print_r($rows,true));
  325. //error_log(print_r($result,true));
  326. //error_log(print_r($json,true));
  327. foreach ($json as $key => $value) {
  328. //error_log(print_r($key,true));
  329. //error_log(print_r($value,true));
  330. $ins_values = array('UId' => $UId, 'DomainId' => $key, 'AccessPrivilege' => $value['1']);
  331. error_log(print_r($ins_values,true));
  332. $dbs = new DBLayer("shard");
  333. $dbs->insert("permission", $ins_values);
  334. }
  335. }
  336. catch (PDOException $e) {
  337. //oh noooz, the shard is offline! Put it in query queue at ams_lib db!
  338. $dbl = new DBLayer("lib");
  339. $dbl->insert("ams_querycache", array("type" => "createPermissions",
  340. "query" => json_encode(array($pvalues[0])), "db" => "shard"));
  341. }
  342. return true;
  343. }
  344. /**
  345. * check if username and password matches.
  346. * This is the base function, it should be overwritten by the WebUsers class.
  347. * @param $user the inserted username
  348. * @param $pass the inserted password
  349. */
  350. protected static function checkLoginMatch($user,$pass){
  351. print('This is the base class!');
  352. }
  353. /**
  354. * check if the changing of a password is valid.
  355. * a mod/admin doesn't has to fill in the previous password when he wants to change the password, however for changing his own password he has to fill it in.
  356. * @param $values an array containing the CurrentPass, ConfirmNewPass, NewPass and adminChangesOthers
  357. * @return if it is valid "success will be returned, else an array with errors will be returned.
  358. */
  359. public function check_change_password($values){
  360. //if admin isn't changing others
  361. if(!$values['adminChangesOther']){
  362. if ( isset( $values["user"] ) and isset( $values["CurrentPass"] ) and isset( $values["ConfirmNewPass"] ) and isset( $values["NewPass"] ) ){
  363. $match = $this->checkLoginMatch($values["user"],$values["CurrentPass"]);
  364. $newpass = $this->checkPassword($values["NewPass"]);
  365. $confpass = $this->confirmPassword($newpass,$values["NewPass"],$values["ConfirmNewPass"]);
  366. }else{
  367. $match = "";
  368. $newpass = "";
  369. $confpass = "";
  370. }
  371. }else{
  372. //if admin is indeed changing someone!
  373. if ( isset( $values["user"] ) and isset( $values["ConfirmNewPass"] ) and isset( $values["NewPass"] ) ){
  374. $newpass = $this->checkPassword($values["NewPass"]);
  375. $confpass = $this->confirmPassword($newpass,$values["NewPass"],$values["ConfirmNewPass"]);
  376. }else{
  377. $newpass = "";
  378. $confpass = "";
  379. }
  380. }
  381. if ( !$values['adminChangesOther'] and ( $match != "fail" ) and ( $newpass == "success" ) and ( $confpass == "success" ) ){
  382. return "success";
  383. }else if($values['adminChangesOther'] and ( $newpass == "success" ) and ( $confpass == "success" ) ){
  384. return "success";
  385. }else{
  386. $pageElements = array(
  387. 'newpass_error_message' => $newpass,
  388. 'confirmnewpass_error_message' => $confpass
  389. );
  390. if(!$values['adminChangesOther']){
  391. $pageElements['match_error_message'] = $match;
  392. if ( $match != "fail" ){
  393. $pageElements['MATCH_ERROR'] = 'FALSE';
  394. }else{
  395. $pageElements['MATCH_ERROR'] = 'TRUE';
  396. }
  397. }
  398. if ( $newpass != "success" ){
  399. $pageElements['NEWPASSWORD_ERROR'] = 'TRUE';
  400. }else{
  401. $pageElements['NEWPASSWORD_ERROR'] = 'FALSE';
  402. }
  403. if ( $confpass != "success" ){
  404. $pageElements['CNEWPASSWORD_ERROR'] = 'TRUE';
  405. }else{
  406. $pageElements['CNEWPASSWORD_ERROR'] = 'FALSE';
  407. }
  408. return $pageElements;
  409. }
  410. }
  411. /**
  412. * sets the shards password.
  413. * in case the shard is offline, the entry will be stored in the ams_querycache.
  414. * @param $user the usersname of the account of which we want to change the password.
  415. * @param $pass the new password.
  416. * @return ok if it worked, if the lib or shard is offline it will return liboffline or shardoffline.
  417. */
  418. protected static function setAmsPassword($user, $pass){
  419. $values = Array('Password' => $pass);
  420. try {
  421. //make connection with and put into shard db
  422. $dbs = new DBLayer("shard");
  423. $dbs->update("user", $values, "Login = '$user'");
  424. return "ok";
  425. }
  426. catch (PDOException $e) {
  427. //oh noooz, the shard is offline! Put in query queue at ams_lib db!
  428. try {
  429. $dbl = new DBLayer("lib");
  430. $dbl->insert("ams_querycache", array("type" => "change_pass",
  431. "query" => json_encode(array($user,$pass)), "db" => "shard"));
  432. return "shardoffline";
  433. }catch (PDOException $e) {
  434. return "liboffline";
  435. }
  436. }
  437. }
  438. /**
  439. * sets the shards email.
  440. * in case the shard is offline, the entry will be stored in the ams_querycache.
  441. * @param $user the usersname of the account of which we want to change the emailaddress.
  442. * @param $mail the new email address
  443. * @return ok if it worked, if the lib or shard is offline it will return liboffline or shardoffline.
  444. */
  445. protected static function setAmsEmail($user, $mail){
  446. $values = Array('Email' => $mail);
  447. try {
  448. //make connection with and put into shard db
  449. $dbs = new DBLayer("shard");
  450. $dbs->update("user", $values, "Login = '$user'");
  451. return "ok";
  452. }
  453. catch (PDOException $e) {
  454. //oh noooz, the shard is offline! Put in query queue at ams_lib db!
  455. try {
  456. error_log($e);
  457. $dbl = new DBLayer("lib");
  458. $dbl->insert("ams_querycache", array("type" => "change_mail",
  459. "query" => json_encode(array($user,$mail)), "db" => "shard"));
  460. return "shardoffline";
  461. }catch (PDOException $e) {
  462. return "liboffline";
  463. }
  464. }
  465. }
  466. }