PageRenderTime 75ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/core/user_api.php

https://github.com/markkimsal/mantisbt
PHP | 1391 lines | 832 code | 263 blank | 296 comment | 160 complexity | 13fdf1b4e7f96a5b35c971bc3124e24f MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1
  1. <?php
  2. # MantisBT - A PHP based bugtracking system
  3. # MantisBT is free software: you can redistribute it and/or modify
  4. # it under the terms of the GNU General Public License as published by
  5. # the Free Software Foundation, either version 2 of the License, or
  6. # (at your option) any later version.
  7. #
  8. # MantisBT is distributed in the hope that it will be useful,
  9. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. # GNU General Public License for more details.
  12. #
  13. # You should have received a copy of the GNU General Public License
  14. # along with MantisBT. If not, see <http://www.gnu.org/licenses/>.
  15. /**
  16. * User API
  17. *
  18. * @package CoreAPI
  19. * @subpackage UserAPI
  20. * @copyright Copyright (C) 2000 - 2002 Kenzaburo Ito - kenito@300baud.org
  21. * @copyright Copyright (C) 2002 - 2010 MantisBT Team - mantisbt-dev@lists.sourceforge.net
  22. * @link http://www.mantisbt.org
  23. *
  24. * @uses access_api.php
  25. * @uses authentication_api.php
  26. * @uses config_api.php
  27. * @uses constant_inc.php
  28. * @uses database_api.php
  29. * @uses email_api.php
  30. * @uses error_api.php
  31. * @uses filter_api.php
  32. * @uses helper_api.php
  33. * @uses lang_api.php
  34. * @uses ldap_api.php
  35. * @uses project_api.php
  36. * @uses project_hierarchy_api.php
  37. * @uses string_api.php
  38. * @uses user_pref_api.php
  39. * @uses utility_api.php
  40. */
  41. require_api( 'access_api.php' );
  42. require_api( 'authentication_api.php' );
  43. require_api( 'config_api.php' );
  44. require_api( 'constant_inc.php' );
  45. require_api( 'database_api.php' );
  46. require_api( 'email_api.php' );
  47. require_api( 'error_api.php' );
  48. require_api( 'filter_api.php' );
  49. require_api( 'helper_api.php' );
  50. require_api( 'lang_api.php' );
  51. require_api( 'ldap_api.php' );
  52. require_api( 'project_api.php' );
  53. require_api( 'project_hierarchy_api.php' );
  54. require_api( 'string_api.php' );
  55. require_api( 'user_pref_api.php' );
  56. require_api( 'utility_api.php' );
  57. # ===================================
  58. # Caching
  59. # ===================================
  60. # ########################################
  61. # SECURITY NOTE: cache globals are initialized here to prevent them
  62. # being spoofed if register_globals is turned on
  63. $g_cache_user = array();
  64. # --------------------
  65. # Cache a user row if necessary and return the cached copy
  66. # If the second parameter is true (default), trigger an error
  67. # if the user can't be found. If the second parameter is
  68. # false, return false if the user can't be found.
  69. function user_cache_row( $p_user_id, $p_trigger_errors = true ) {
  70. global $g_cache_user;
  71. if( isset( $g_cache_user[$p_user_id] ) ) {
  72. return $g_cache_user[$p_user_id];
  73. }
  74. $t_user_table = db_get_table( 'user' );
  75. $query = "SELECT *
  76. FROM $t_user_table
  77. WHERE id=" . db_param();
  78. $result = db_query_bound( $query, Array( $p_user_id ) );
  79. if( 0 == db_num_rows( $result ) ) {
  80. $g_cache_user[$p_user_id] = false;
  81. if( $p_trigger_errors ) {
  82. error_parameters( (integer)$p_user_id );
  83. trigger_error( ERROR_USER_BY_ID_NOT_FOUND, ERROR );
  84. }
  85. return false;
  86. }
  87. $row = db_fetch_array( $result );
  88. $g_cache_user[$p_user_id] = $row;
  89. return $row;
  90. }
  91. function user_cache_array_rows( $p_user_id_array ) {
  92. global $g_cache_user;
  93. $c_user_id_array = array();
  94. foreach( $p_user_id_array as $t_user_id ) {
  95. if( !isset( $g_cache_user[(int) $t_user_id] ) ) {
  96. $c_user_id_array[] = (int) $t_user_id;
  97. }
  98. }
  99. if( empty( $c_user_id_array ) ) {
  100. return;
  101. }
  102. $t_user_table = db_get_table( 'user' );
  103. $query = "SELECT *
  104. FROM $t_user_table
  105. WHERE id IN (" . implode( ',', $c_user_id_array ) . ')';
  106. $result = db_query_bound( $query );
  107. while( $row = db_fetch_array( $result ) ) {
  108. $g_cache_user[(int) $row['id']] = $row;
  109. }
  110. return;
  111. }
  112. # --------------------
  113. # Cache an object as a bug.
  114. function user_cache_database_result( $p_user_database_result ) {
  115. global $g_cache_user;
  116. if( isset( $g_cache_user[$p_user_database_result['id']] ) ) {
  117. return $g_cache_user[$p_user_database_result['id']];
  118. }
  119. $g_cache_user[$p_user_database_result['id']] = $p_user_database_result;
  120. }
  121. # --------------------
  122. # Clear the user cache (or just the given id if specified)
  123. function user_clear_cache( $p_user_id = null ) {
  124. global $g_cache_user;
  125. if( null === $p_user_id ) {
  126. $g_cache_user = array();
  127. } else {
  128. unset( $g_cache_user[$p_user_id] );
  129. }
  130. return true;
  131. }
  132. function user_update_cache( $p_user_id, $p_field, $p_value ) {
  133. global $g_cache_user;
  134. if( isset( $g_cache_user[$p_user_id] ) && isset( $g_cache_user[$p_user_id][$p_field] ) ) {
  135. $g_cache_user[$p_user_id][$p_field] = $p_value;
  136. } else {
  137. user_clear_cache( $p_user_id );
  138. }
  139. }
  140. function user_search_cache( $p_field, $p_value ) {
  141. global $g_cache_user;
  142. if( isset( $g_cache_user ) ) {
  143. foreach( $g_cache_user as $t_user ) {
  144. if( $t_user[$p_field] == $p_value ) {
  145. return $t_user;
  146. }
  147. }
  148. }
  149. return false;
  150. }
  151. # ===================================
  152. # Boolean queries and ensures
  153. # ===================================
  154. # --------------------
  155. # check to see if user exists by id
  156. # return true if it does, false otherwise
  157. #
  158. # Use user_cache_row() to benefit from caching if called multiple times
  159. # and because if the user does exist the data may well be wanted
  160. function user_exists( $p_user_id ) {
  161. $row = user_cache_row( $p_user_id, false );
  162. if( false === $row ) {
  163. return false;
  164. } else {
  165. return true;
  166. }
  167. }
  168. # --------------------
  169. # check to see if project exists by id
  170. # if it doesn't exist then error
  171. # otherwise let execution continue undisturbed
  172. function user_ensure_exists( $p_user_id ) {
  173. $c_user_id = (integer)$p_user_id;
  174. if ( !user_exists( $c_user_id ) ) {
  175. error_parameters( $c_user_id );
  176. trigger_error( ERROR_USER_BY_ID_NOT_FOUND, ERROR );
  177. }
  178. }
  179. # --------------------
  180. # return true if the username is unique, false if there is already a user
  181. # with that username
  182. function user_is_name_unique( $p_username ) {
  183. $t_user_table = db_get_table( 'user' );
  184. $query = "SELECT username
  185. FROM $t_user_table
  186. WHERE username=" . db_param();
  187. $result = db_query_bound( $query, Array( $p_username ), 1 );
  188. if( db_num_rows( $result ) > 0 ) {
  189. return false;
  190. } else {
  191. return true;
  192. }
  193. }
  194. # --------------------
  195. # Check if the username is unique and trigger an ERROR if it isn't
  196. function user_ensure_name_unique( $p_username ) {
  197. if( !user_is_name_unique( $p_username ) ) {
  198. trigger_error( ERROR_USER_NAME_NOT_UNIQUE, ERROR );
  199. }
  200. }
  201. # --------------------
  202. # Check if the realname is a valid username (does not account for uniqueness)
  203. # Return 0 if it is invalid, The number of matches + 1
  204. function user_is_realname_unique( $p_username, $p_realname ) {
  205. if( is_blank( $p_realname ) ) {
  206. # don't bother checking if realname is blank
  207. return 1;
  208. }
  209. $p_username = trim( $p_username );
  210. $p_realname = trim( $p_realname );
  211. # allow realname to match username
  212. $t_count = 0;
  213. if( $p_realname <> $p_username ) {
  214. # check realname does not match an existing username
  215. # but allow it to match the current user
  216. $t_target_user = user_get_id_by_name( $p_username );
  217. $t_other_user = user_get_id_by_name( $p_realname );
  218. if( ( 0 != $t_other_user ) && ( $t_target_user != $t_other_user ) ) {
  219. return 0;
  220. }
  221. # check to see if the realname is unique
  222. $t_user_table = db_get_table( 'user' );
  223. $query = "SELECT id
  224. FROM $t_user_table
  225. WHERE realname=" . db_param();
  226. $result = db_query_bound( $query, Array( $p_realname ) );
  227. $t_count = db_num_rows( $result );
  228. if( $t_count > 0 ) {
  229. # set flags for non-unique realnames
  230. if( config_get( 'differentiate_duplicates' ) ) {
  231. for( $i = 0;$i < $t_count;$i++ ) {
  232. $t_user_id = db_result( $result, $i );
  233. user_set_field( $t_user_id, 'duplicate_realname', ON );
  234. }
  235. }
  236. }
  237. }
  238. return $t_count + 1;
  239. }
  240. # --------------------
  241. # Check if the realname is a unique
  242. # Trigger an error if the username is not valid
  243. function user_ensure_realname_unique( $p_username, $p_realname ) {
  244. if( 1 > user_is_realname_unique( $p_username, $p_realname ) ) {
  245. trigger_error( ERROR_USER_REAL_MATCH_USER, ERROR );
  246. }
  247. }
  248. # --------------------
  249. # Check if the realname is a valid (does not account for uniqueness)
  250. # true: valid, false: not valid
  251. function user_is_realname_valid( $p_realname ) {
  252. return( !string_contains_scripting_chars( $p_realname ) );
  253. }
  254. # --------------------
  255. # Check if the realname is a valid (does not account for uniqueness), if not, trigger an error
  256. function user_ensure_realname_valid( $p_realname ) {
  257. if( !user_is_realname_valid( $p_realname ) ) {
  258. trigger_error( ERROR_USER_REAL_NAME_INVALID, ERROR );
  259. }
  260. }
  261. # --------------------
  262. # Check if the username is a valid username (does not account for uniqueness)
  263. # realname can match
  264. # Return true if it is, false otherwise
  265. function user_is_name_valid( $p_username ) {
  266. # The DB field is hard-coded. USERLEN should not be modified.
  267. if( utf8_strlen( $p_username ) > USERLEN ) {
  268. return false;
  269. }
  270. # username must consist of at least one character
  271. if( is_blank( $p_username ) ) {
  272. return false;
  273. }
  274. # Only allow a basic set of characters
  275. if( 0 == preg_match( config_get( 'user_login_valid_regex' ), $p_username ) ) {
  276. return false;
  277. }
  278. # We have a valid username
  279. return true;
  280. }
  281. # --------------------
  282. # Check if the username is a valid username (does not account for uniqueness)
  283. # Trigger an error if the username is not valid
  284. function user_ensure_name_valid( $p_username ) {
  285. if( !user_is_name_valid( $p_username ) ) {
  286. trigger_error( ERROR_USER_NAME_INVALID, ERROR );
  287. }
  288. }
  289. # --------------------
  290. # return whether user is monitoring bug for the user id and bug id
  291. function user_is_monitoring_bug( $p_user_id, $p_bug_id ) {
  292. $c_user_id = db_prepare_int( $p_user_id );
  293. $c_bug_id = db_prepare_int( $p_bug_id );
  294. $t_bug_monitor_table = db_get_table( 'bug_monitor' );
  295. $query = "SELECT COUNT(*)
  296. FROM $t_bug_monitor_table
  297. WHERE user_id=" . db_param() . " AND bug_id=" . db_param();
  298. $result = db_query_bound( $query, Array( $c_user_id, $c_bug_id ) );
  299. if( 0 == db_result( $result ) ) {
  300. return false;
  301. } else {
  302. return true;
  303. }
  304. }
  305. # --------------------
  306. # return true if the user has access of ADMINISTRATOR or higher, false otherwise
  307. function user_is_administrator( $p_user_id ) {
  308. $t_access_level = user_get_field( $p_user_id, 'access_level' );
  309. if( $t_access_level >= config_get_global( 'admin_site_threshold' ) ) {
  310. return true;
  311. } else {
  312. return false;
  313. }
  314. }
  315. /*
  316. * Check if a user has a protected user account.
  317. * Protected user accounts cannot be updated without manage_user_threshold
  318. * permission. If the user ID supplied is that of the anonymous user, this
  319. * function will always return true. The anonymous user account is always
  320. * considered to be protected.
  321. *
  322. * @param int $p_user_id
  323. * @return true: user is protected; false: user is not protected.
  324. * @access public
  325. */
  326. function user_is_protected( $p_user_id ) {
  327. if( user_is_anonymous( $p_user_id ) || ON == user_get_field( $p_user_id, 'protected' ) ) {
  328. return true;
  329. }
  330. return false;
  331. }
  332. /*
  333. * Check if a user is the anonymous user account.
  334. * When anonymous logins are disabled this function will always return false.
  335. *
  336. * @param int $p_user_id
  337. * @return true: user is the anonymous user; false: user is not the anonymous user.
  338. * @access public
  339. */
  340. function user_is_anonymous( $p_user_id ) {
  341. if( ON == config_get( 'allow_anonymous_login' ) && user_get_field( $p_user_id, 'username' ) == config_get( 'anonymous_account' ) ) {
  342. return true;
  343. }
  344. return false;
  345. }
  346. # --------------------
  347. # Trigger an ERROR if the user account is protected
  348. function user_ensure_unprotected( $p_user_id ) {
  349. if( user_is_protected( $p_user_id ) ) {
  350. trigger_error( ERROR_PROTECTED_ACCOUNT, ERROR );
  351. }
  352. }
  353. # --------------------
  354. # return true is the user account is enabled, false otherwise
  355. function user_is_enabled( $p_user_id ) {
  356. if( ON == user_get_field( $p_user_id, 'enabled' ) ) {
  357. return true;
  358. } else {
  359. return false;
  360. }
  361. }
  362. # --------------------
  363. # count the number of users at or greater than a specific level
  364. function user_count_level( $p_level = ANYBODY ) {
  365. $t_level = db_prepare_int( $p_level );
  366. $t_user_table = db_get_table( 'user' );
  367. $query = "SELECT COUNT(id) FROM $t_user_table WHERE access_level>=" . db_param();
  368. $result = db_query_bound( $query, Array( $t_level ) );
  369. # Get the list of connected users
  370. $t_users = db_result( $result );
  371. return $t_users;
  372. }
  373. # --------------------
  374. # Return an array of user ids that are logged in.
  375. # A user is considered logged in if the last visit timestamp is within the
  376. # specified session duration.
  377. # If the session duration is 0, then no users will be returned.
  378. function user_get_logged_in_user_ids( $p_session_duration_in_minutes ) {
  379. $t_session_duration_in_minutes = (integer) $p_session_duration_in_minutes;
  380. # if session duration is 0, then there is no logged in users.
  381. if( $t_session_duration_in_minutes == 0 ) {
  382. return array();
  383. }
  384. # Generate timestamp
  385. $t_last_timestamp_threshold = mktime( date( 'H' ), date( 'i' ) - 1 * $t_session_duration_in_minutes, date( 's' ), date( 'm' ), date( 'd' ), date( 'Y' ) );
  386. $t_user_table = db_get_table( 'user' );
  387. # Execute query
  388. $query = 'SELECT id FROM ' . $t_user_table . ' WHERE last_visit > ' . db_param();
  389. $result = db_query_bound( $query, array( $c_last_timestamp_threshold ), 1 );
  390. # Get the list of connected users
  391. $t_users_connected = array();
  392. while( $row = db_fetch_array( $result ) ) {
  393. $t_users_connected[] = $row['id'];
  394. }
  395. return $t_users_connected;
  396. }
  397. # ===================================
  398. # Creation / Deletion / Updating
  399. # ===================================
  400. # --------------------
  401. # Create a user.
  402. # returns false if error, the generated cookie string if ok
  403. function user_create( $p_username, $p_password, $p_email = '',
  404. $p_access_level = null, $p_protected = false, $p_enabled = true,
  405. $p_realname = '', $p_admin_name = '' ) {
  406. if( null === $p_access_level ) {
  407. $p_access_level = config_get( 'default_new_account_access_level' );
  408. }
  409. $t_password = auth_process_plain_password( $p_password );
  410. $c_access_level = db_prepare_int( $p_access_level );
  411. $c_protected = db_prepare_bool( $p_protected );
  412. $c_enabled = db_prepare_bool( $p_enabled );
  413. user_ensure_name_valid( $p_username );
  414. user_ensure_name_unique( $p_username );
  415. user_ensure_realname_valid( $p_realname );
  416. user_ensure_realname_unique( $p_username, $p_realname );
  417. email_ensure_valid( $p_email );
  418. $t_seed = $p_email . $p_username;
  419. $t_cookie_string = auth_generate_unique_cookie_string( $t_seed );
  420. $t_user_table = db_get_table( 'user' );
  421. $query = "INSERT INTO $t_user_table
  422. ( username, email, password, date_created, last_visit,
  423. enabled, access_level, login_count, cookie_string, realname )
  424. VALUES
  425. ( " . db_param() . ', ' . db_param() . ', ' . db_param() . ', ' . db_param() . ', ' . db_param() . ",
  426. " . db_param() . ',' . db_param() . ',' . db_param() . ',' . db_param() . ', ' . db_param() . ')';
  427. db_query_bound( $query, Array( $p_username, $p_email, $t_password, db_now(), db_now(), $c_enabled, $c_access_level, 0, $t_cookie_string, $p_realname ) );
  428. # Create preferences for the user
  429. $t_user_id = db_insert_id( $t_user_table );
  430. # Users are added with protected set to FALSE in order to be able to update
  431. # preferences. Now set the real value of protected.
  432. if( $c_protected ) {
  433. user_set_field( $t_user_id, 'protected', 1 );
  434. }
  435. # Send notification email
  436. if( !is_blank( $p_email ) ) {
  437. $t_confirm_hash = auth_generate_confirm_hash( $t_user_id );
  438. email_signup( $t_user_id, $p_password, $t_confirm_hash, $p_admin_name );
  439. }
  440. return $t_cookie_string;
  441. }
  442. # --------------------
  443. # Signup a user.
  444. # If the use_ldap_email config option is on then tries to find email using
  445. # ldap. $p_email may be empty, but the user wont get any emails.
  446. # returns false if error, the generated cookie string if ok
  447. function user_signup( $p_username, $p_email = null ) {
  448. if( null === $p_email ) {
  449. $p_email = '';
  450. # @@@ I think the ldap_email stuff is a bit borked
  451. # Where is it being set? When is it being used?
  452. # Shouldn't we override an email that is passed in here?
  453. # If the user doesn't exist in ldap, is the account created?
  454. # If so, there password won't get set anywhere... (etc)
  455. # RJF: I was going to check for the existence of an LDAP email.
  456. # however, since we can't create an LDAP account at the moment,
  457. # and we don't know the user password in advance, we may not be able
  458. # to retrieve it anyway.
  459. # I'll re-enable this once a plan has been properly formulated for LDAP
  460. # account management and creation.
  461. /* $t_email = '';
  462. if ( ON == config_get( 'use_ldap_email' ) ) {
  463. $t_email = ldap_email_from_username( $p_username );
  464. }
  465. if ( !is_blank( $t_email ) ) {
  466. $p_email = $t_email;
  467. }
  468. */
  469. }
  470. $p_email = trim( $p_email );
  471. $t_seed = $p_email . $p_username;
  472. # Create random password
  473. $t_password = auth_generate_random_password( $t_seed );
  474. return user_create( $p_username, $t_password, $p_email );
  475. }
  476. # --------------------
  477. # delete project-specific user access levels.
  478. # returns true when successfully deleted
  479. function user_delete_project_specific_access_levels( $p_user_id ) {
  480. $c_user_id = db_prepare_int( $p_user_id );
  481. user_ensure_unprotected( $p_user_id );
  482. $t_project_user_list_table = db_get_table( 'project_user_list' );
  483. $query = "DELETE FROM $t_project_user_list_table
  484. WHERE user_id=" . db_param();
  485. db_query_bound( $query, Array( $c_user_id ) );
  486. user_clear_cache( $p_user_id );
  487. return true;
  488. }
  489. # --------------------
  490. # delete profiles for the specified user
  491. # returns true when successfully deleted
  492. function user_delete_profiles( $p_user_id ) {
  493. $c_user_id = db_prepare_int( $p_user_id );
  494. user_ensure_unprotected( $p_user_id );
  495. $t_user_profile_table = db_get_table( 'user_profile' );
  496. # Remove associated profiles
  497. $query = "DELETE FROM $t_user_profile_table
  498. WHERE user_id=" . db_param();
  499. db_query_bound( $query, Array( $c_user_id ) );
  500. user_clear_cache( $p_user_id );
  501. return true;
  502. }
  503. # --------------------
  504. # delete a user account (account, profiles, preferences, project-specific access levels)
  505. # returns true when the account was successfully deleted
  506. function user_delete( $p_user_id ) {
  507. $c_user_id = db_prepare_int( $p_user_id );
  508. $t_user_table = db_get_table( 'user' );
  509. user_ensure_unprotected( $p_user_id );
  510. # Remove associated profiles
  511. user_delete_profiles( $p_user_id );
  512. # Remove associated preferences
  513. user_pref_delete_all( $p_user_id );
  514. # Remove project specific access levels
  515. user_delete_project_specific_access_levels( $p_user_id );
  516. # unset non-unique realname flags if necessary
  517. if( config_get( 'differentiate_duplicates' ) ) {
  518. $c_realname = user_get_field( $p_user_id, 'realname' );
  519. $query = "SELECT id
  520. FROM $t_user_table
  521. WHERE realname=" . db_param();
  522. $result = db_query_bound( $query, Array( $c_realname ) );
  523. $t_count = db_num_rows( $result );
  524. if( $t_count == 2 ) {
  525. # unset flags if there are now only 2 unique names
  526. for( $i = 0;$i < $t_count;$i++ ) {
  527. $t_user_id = db_result( $result, $i );
  528. user_set_field( $t_user_id, 'duplicate_realname', OFF );
  529. }
  530. }
  531. }
  532. user_clear_cache( $p_user_id );
  533. # Remove account
  534. $query = "DELETE FROM $t_user_table
  535. WHERE id=" . db_param();
  536. db_query_bound( $query, Array( $c_user_id ) );
  537. return true;
  538. }
  539. # ===================================
  540. # Data Access
  541. # ===================================
  542. # --------------------
  543. # get a user id from a username
  544. # return false if the username does not exist
  545. function user_get_id_by_name( $p_username ) {
  546. global $g_cache_user;
  547. if( $t_user = user_search_cache( 'username', $p_username ) ) {
  548. return $t_user['id'];
  549. }
  550. $t_user_table = db_get_table( 'user' );
  551. $query = "SELECT *
  552. FROM $t_user_table
  553. WHERE username=" . db_param();
  554. $result = db_query_bound( $query, Array( $p_username ) );
  555. if( 0 == db_num_rows( $result ) ) {
  556. return false;
  557. } else {
  558. $row = db_fetch_array( $result );
  559. user_cache_database_result( $row );
  560. return $row['id'];
  561. }
  562. }
  563. # Get a user id from an email address
  564. function user_get_id_by_email( $p_email ) {
  565. global $g_cache_user;
  566. if( $t_user = user_search_cache( 'email', $p_email ) ) {
  567. return $t_user['id'];
  568. }
  569. $t_user_table = db_get_table( 'user' );
  570. $query = "SELECT *
  571. FROM $t_user_table
  572. WHERE email=" . db_param();
  573. $result = db_query_bound( $query, Array( $p_email ) );
  574. if( 0 == db_num_rows( $result ) ) {
  575. return false;
  576. } else {
  577. $row = db_fetch_array( $result );
  578. user_cache_database_result( $row );
  579. return $row['id'];
  580. }
  581. }
  582. # Get a user id from their real name
  583. function user_get_id_by_realname( $p_realname ) {
  584. global $g_cache_user;
  585. if( $t_user = user_search_cache( 'realname', $p_realname ) ) {
  586. return $t_user['id'];
  587. }
  588. $t_user_table = db_get_table( 'user' );
  589. $query = "SELECT *
  590. FROM $t_user_table
  591. WHERE realname=" . db_param();
  592. $result = db_query_bound( $query, Array( $p_realname ) );
  593. if( 0 == db_num_rows( $result ) ) {
  594. return false;
  595. } else {
  596. $row = db_fetch_array( $result );
  597. user_cache_database_result( $row );
  598. return $row['id'];
  599. }
  600. }
  601. # --------------------
  602. # return all data associated with a particular user name
  603. # return false if the username does not exist
  604. function user_get_row_by_name( $p_username ) {
  605. $t_user_id = user_get_id_by_name( $p_username );
  606. if( false === $t_user_id ) {
  607. return false;
  608. }
  609. $row = user_get_row( $t_user_id );
  610. return $row;
  611. }
  612. # --------------------
  613. # return a user row
  614. function user_get_row( $p_user_id ) {
  615. return user_cache_row( $p_user_id );
  616. }
  617. # --------------------
  618. # return the specified user field for the user id
  619. function user_get_field( $p_user_id, $p_field_name ) {
  620. if( NO_USER == $p_user_id ) {
  621. trigger_error( 'user_get_field() for NO_USER', WARNING );
  622. return '@null@';
  623. }
  624. $row = user_get_row( $p_user_id );
  625. if( isset( $row[$p_field_name] ) ) {
  626. return $row[$p_field_name];
  627. } else {
  628. error_parameters( $p_field_name );
  629. trigger_error( ERROR_DB_FIELD_NOT_FOUND, WARNING );
  630. return '';
  631. }
  632. }
  633. # --------------------
  634. # lookup the user's email in LDAP or the db as appropriate
  635. function user_get_email( $p_user_id ) {
  636. $t_email = '';
  637. if( ON == config_get( 'use_ldap_email' ) ) {
  638. $t_email = ldap_email( $p_user_id );
  639. }
  640. if( is_blank( $t_email ) ) {
  641. $t_email = user_get_field( $p_user_id, 'email' );
  642. }
  643. return $t_email;
  644. }
  645. # --------------------
  646. # lookup the user's realname
  647. function user_get_realname( $p_user_id ) {
  648. $t_realname = '';
  649. if ( ON == config_get( 'use_ldap_realname' ) ) {
  650. $t_realname = ldap_realname( $p_user_id );
  651. }
  652. if ( is_blank( $t_realname ) ) {
  653. $t_realname = user_get_field( $p_user_id, 'realname' );
  654. }
  655. return $t_realname;
  656. }
  657. # --------------------
  658. # return the username or a string "user<id>" if the user does not exist
  659. # if $g_show_realname is set and real name is not empty, return it instead
  660. function user_get_name( $p_user_id ) {
  661. $row = user_cache_row( $p_user_id, false );
  662. if( false == $row ) {
  663. return lang_get( 'prefix_for_deleted_users' ) . (int) $p_user_id;
  664. } else {
  665. if( ON == config_get( 'show_realname' ) ) {
  666. if( is_blank( $row['realname'] ) ) {
  667. return $row['username'];
  668. } else {
  669. if( isset( $row['duplicate_realname'] ) && ( ON == $row['duplicate_realname'] ) ) {
  670. return $row['realname'] . ' (' . $row['username'] . ')';
  671. } else {
  672. return $row['realname'];
  673. }
  674. }
  675. } else {
  676. return $row['username'];
  677. }
  678. }
  679. }
  680. /**
  681. * Return the user avatar image URL
  682. * in this first implementation, only gravatar.com avatars are supported
  683. * @return array|bool an array( URL, width, height ) or false when the given user has no avatar
  684. */
  685. function user_get_avatar( $p_user_id, $p_size = 80 ) {
  686. $t_email = utf8_strtolower( user_get_email( $p_user_id ) );
  687. if( is_blank( $t_email ) ) {
  688. $t_result = false;
  689. } else {
  690. $t_default_image = config_get( 'default_avatar' );
  691. $t_size = $p_size;
  692. $t_use_ssl = false;
  693. if( isset( $_SERVER['HTTPS'] ) && ( utf8_strtolower( $_SERVER['HTTPS'] ) != 'off' ) ) {
  694. $t_use_ssl = true;
  695. }
  696. if( !$t_use_ssl ) {
  697. $t_gravatar_domain = 'http://www.gravatar.com/';
  698. } else {
  699. $t_gravatar_domain = 'https://secure.gravatar.com/';
  700. }
  701. $t_avatar_url = $t_gravatar_domain . 'avatar.php?gravatar_id=' . md5( $t_email ) . '&default=' . urlencode( $t_default_image ) . '&size=' . $t_size . '&rating=G';
  702. $t_result = array(
  703. $t_avatar_url,
  704. $t_size,
  705. $t_size,
  706. );
  707. }
  708. return $t_result;
  709. }
  710. # --------------------
  711. # return the user's access level
  712. # account for private project and the project user lists
  713. function user_get_access_level( $p_user_id, $p_project_id = ALL_PROJECTS ) {
  714. $t_access_level = user_get_field( $p_user_id, 'access_level' );
  715. if( user_is_administrator( $p_user_id ) ) {
  716. return $t_access_level;
  717. }
  718. $t_project_access_level = project_get_local_user_access_level( $p_project_id, $p_user_id );
  719. if( false === $t_project_access_level ) {
  720. return $t_access_level;
  721. } else {
  722. return $t_project_access_level;
  723. }
  724. }
  725. $g_user_accessible_projects_cache = null;
  726. # --------------------
  727. # retun an array of project IDs to which the user has access
  728. function user_get_accessible_projects( $p_user_id, $p_show_disabled = false ) {
  729. global $g_user_accessible_projects_cache;
  730. if( null !== $g_user_accessible_projects_cache && auth_get_current_user_id() == $p_user_id && false == $p_show_disabled ) {
  731. return $g_user_accessible_projects_cache;
  732. }
  733. if( access_has_global_level( config_get( 'private_project_threshold' ), $p_user_id ) ) {
  734. $t_projects = project_hierarchy_get_subprojects( ALL_PROJECTS, $p_show_disabled );
  735. } else {
  736. $t_project_table = db_get_table( 'project' );
  737. $t_project_user_list_table = db_get_table( 'project_user_list' );
  738. $t_project_hierarchy_table = db_get_table( 'project_hierarchy' );
  739. $t_public = VS_PUBLIC;
  740. $t_private = VS_PRIVATE;
  741. $result = null;
  742. $query = "SELECT p.id, p.name, ph.parent_id
  743. FROM $t_project_table p
  744. LEFT JOIN $t_project_user_list_table u
  745. ON p.id=u.project_id AND u.user_id=" . db_param() . "
  746. LEFT JOIN $t_project_hierarchy_table ph
  747. ON ph.child_id = p.id
  748. WHERE " . ( $p_show_disabled ? '' : ( 'p.enabled = ' . db_param() . ' AND ' ) ) . "
  749. ( p.view_state=" . db_param() . "
  750. OR (p.view_state=" . db_param() . "
  751. AND
  752. u.user_id=" . db_param() . " )
  753. )
  754. ORDER BY p.name";
  755. $result = db_query_bound( $query, ( $p_show_disabled ? Array( $p_user_id, $t_public, $t_private, $p_user_id ) : Array( $p_user_id, true, $t_public, $t_private, $p_user_id ) ) );
  756. $row_count = db_num_rows( $result );
  757. $t_projects = array();
  758. for( $i = 0;$i < $row_count;$i++ ) {
  759. $row = db_fetch_array( $result );
  760. $t_projects[(int)$row['id']] = ( $row['parent_id'] === NULL ) ? 0 : (int)$row['parent_id'];
  761. }
  762. # prune out children where the parents are already listed. Make the list
  763. # first, then prune to avoid pruning a parent before the child is found.
  764. $t_prune = array();
  765. foreach( $t_projects as $t_id => $t_parent ) {
  766. if(( $t_parent !== 0 ) && isset( $t_projects[$t_parent] ) ) {
  767. $t_prune[] = $t_id;
  768. }
  769. }
  770. foreach( $t_prune as $t_id ) {
  771. unset( $t_projects[$t_id] );
  772. }
  773. $t_projects = array_keys( $t_projects );
  774. }
  775. if( auth_get_current_user_id() == $p_user_id ) {
  776. $g_user_accessible_projects_cache = $t_projects;
  777. }
  778. return $t_projects;
  779. }
  780. $g_user_accessible_subprojects_cache = null;
  781. # --------------------
  782. # retun an array of subproject IDs of a certain project to which the user has access
  783. function user_get_accessible_subprojects( $p_user_id, $p_project_id, $p_show_disabled = false ) {
  784. global $g_user_accessible_subprojects_cache;
  785. if( null !== $g_user_accessible_subprojects_cache && auth_get_current_user_id() == $p_user_id && false == $p_show_disabled ) {
  786. if( isset( $g_user_accessible_subprojects_cache[$p_project_id] ) ) {
  787. return $g_user_accessible_subprojects_cache[$p_project_id];
  788. } else {
  789. return Array();
  790. }
  791. }
  792. $t_project_table = db_get_table( 'project' );
  793. $t_project_user_list_table = db_get_table( 'project_user_list' );
  794. $t_project_hierarchy_table = db_get_table( 'project_hierarchy' );
  795. $t_public = VS_PUBLIC;
  796. $t_private = VS_PRIVATE;
  797. if( access_has_global_level( config_get( 'private_project_threshold' ), $p_user_id ) ) {
  798. $t_enabled_clause = $p_show_disabled ? '' : 'p.enabled = ' . db_param() . ' AND';
  799. $query = "SELECT DISTINCT p.id, p.name, ph.parent_id
  800. FROM $t_project_table p
  801. LEFT JOIN $t_project_hierarchy_table ph
  802. ON ph.child_id = p.id
  803. WHERE $t_enabled_clause
  804. ph.parent_id IS NOT NULL
  805. ORDER BY p.name";
  806. $result = db_query_bound( $query, ( $p_show_disabled ? null : Array( true ) ) );
  807. } else {
  808. $query = "SELECT DISTINCT p.id, p.name, ph.parent_id
  809. FROM $t_project_table p
  810. LEFT JOIN $t_project_user_list_table u
  811. ON p.id = u.project_id AND u.user_id=" . db_param() . "
  812. LEFT JOIN $t_project_hierarchy_table ph
  813. ON ph.child_id = p.id
  814. WHERE " . ( $p_show_disabled ? '' : ( 'p.enabled = ' . db_param() . ' AND ' ) ) . '
  815. ph.parent_id IS NOT NULL AND
  816. ( p.view_state=' . db_param() . '
  817. OR (p.view_state=' . db_param() . '
  818. AND
  819. u.user_id=' . db_param() . ' )
  820. )
  821. ORDER BY p.name';
  822. $result = db_query_bound( $query, ( $p_show_disabled ? Array( $p_user_id, $t_public, $t_private, $p_user_id ) : Array( $p_user_id, 1, $t_public, $t_private, $p_user_id ) ) );
  823. }
  824. $row_count = db_num_rows( $result );
  825. $t_projects = array();
  826. for( $i = 0;$i < $row_count;$i++ ) {
  827. $row = db_fetch_array( $result );
  828. if( !isset( $t_projects[(int)$row['parent_id']] ) ) {
  829. $t_projects[(int)$row['parent_id']] = array();
  830. }
  831. array_push( $t_projects[(int)$row['parent_id']], (int)$row['id'] );
  832. }
  833. if( auth_get_current_user_id() == $p_user_id ) {
  834. $g_user_accessible_subprojects_cache = $t_projects;
  835. }
  836. if( !isset( $t_projects[(int)$p_project_id] ) ) {
  837. $t_projects[(int)$p_project_id] = array();
  838. }
  839. return $t_projects[(int)$p_project_id];
  840. }
  841. # --------------------
  842. function user_get_all_accessible_subprojects( $p_user_id, $p_project_id ) {
  843. /** @todo (thraxisp) Should all top level projects be a sub-project of ALL_PROJECTS implicitly?
  844. * affects how news and some summaries are generated
  845. */
  846. $t_todo = user_get_accessible_subprojects( $p_user_id, $p_project_id );
  847. $t_subprojects = Array();
  848. while( $t_todo ) {
  849. $t_elem = (int)array_shift( $t_todo );
  850. if( !in_array( $t_elem, $t_subprojects ) ) {
  851. array_push( $t_subprojects, $t_elem );
  852. $t_todo = array_merge( $t_todo, user_get_accessible_subprojects( $p_user_id, $t_elem ) );
  853. }
  854. }
  855. return $t_subprojects;
  856. }
  857. function user_get_all_accessible_projects( $p_user_id, $p_project_id ) {
  858. if( ALL_PROJECTS == $p_project_id ) {
  859. $t_topprojects = $t_project_ids = user_get_accessible_projects( $p_user_id );
  860. foreach( $t_topprojects as $t_project ) {
  861. $t_project_ids = array_merge( $t_project_ids, user_get_all_accessible_subprojects( $p_user_id, $t_project ) );
  862. }
  863. $t_project_ids = array_unique( $t_project_ids );
  864. } else {
  865. access_ensure_project_level( VIEWER, $p_project_id );
  866. $t_project_ids = user_get_all_accessible_subprojects( $p_user_id, $p_project_id );
  867. array_unshift( $t_project_ids, $p_project_id );
  868. }
  869. return $t_project_ids;
  870. }
  871. # --------------------
  872. # return the number of open assigned bugs to a user in a project
  873. function user_get_assigned_open_bug_count( $p_user_id, $p_project_id = ALL_PROJECTS ) {
  874. $t_bug_table = db_get_table( 'bug' );
  875. $t_where_prj = helper_project_specific_where( $p_project_id, $p_user_id ) . ' AND';
  876. $t_resolved = config_get( 'bug_resolved_status_threshold' );
  877. $query = "SELECT COUNT(*)
  878. FROM $t_bug_table
  879. WHERE $t_where_prj
  880. status<'$t_resolved' AND
  881. handler_id=" . db_param();
  882. $result = db_query_bound( $query, Array( $p_user_id ) );
  883. return db_result( $result );
  884. }
  885. # --------------------
  886. # return the number of open reported bugs by a user in a project
  887. function user_get_reported_open_bug_count( $p_user_id, $p_project_id = ALL_PROJECTS ) {
  888. $t_bug_table = db_get_table( 'bug' );
  889. $t_where_prj = helper_project_specific_where( $p_project_id, $p_user_id ) . ' AND';
  890. $t_resolved = config_get( 'bug_resolved_status_threshold' );
  891. $query = "SELECT COUNT(*)
  892. FROM $t_bug_table
  893. WHERE $t_where_prj
  894. status<'$t_resolved' AND
  895. reporter_id=" . db_param();
  896. $result = db_query_bound( $query, Array( $p_user_id ) );
  897. return db_result( $result );
  898. }
  899. # --------------------
  900. # return a profile row
  901. function user_get_profile_row( $p_user_id, $p_profile_id ) {
  902. $c_user_id = db_prepare_int( $p_user_id );
  903. $c_profile_id = db_prepare_int( $p_profile_id );
  904. $t_user_profile_table = db_get_table( 'user_profile' );
  905. $query = "SELECT *
  906. FROM $t_user_profile_table
  907. WHERE id=" . db_param() . " AND
  908. user_id=" . db_param();
  909. $result = db_query_bound( $query, Array( $c_profile_id, $c_user_id ) );
  910. if( 0 == db_num_rows( $result ) ) {
  911. trigger_error( ERROR_USER_PROFILE_NOT_FOUND, ERROR );
  912. }
  913. $row = db_fetch_array( $result );
  914. return $row;
  915. }
  916. # --------------------
  917. # Get failed login attempts
  918. function user_is_login_request_allowed( $p_user_id ) {
  919. $t_max_failed_login_count = config_get( 'max_failed_login_count' );
  920. $t_failed_login_count = user_get_field( $p_user_id, 'failed_login_count' );
  921. return( $t_failed_login_count < $t_max_failed_login_count || OFF == $t_max_failed_login_count );
  922. }
  923. # --------------------
  924. # Get 'lost password' in progress attempts
  925. function user_is_lost_password_request_allowed( $p_user_id ) {
  926. if( OFF == config_get( 'lost_password_feature' ) ) {
  927. return false;
  928. }
  929. $t_max_lost_password_in_progress_count = config_get( 'max_lost_password_in_progress_count' );
  930. $t_lost_password_in_progress_count = user_get_field( $p_user_id, 'lost_password_request_count' );
  931. return( $t_lost_password_in_progress_count < $t_max_lost_password_in_progress_count || OFF == $t_max_lost_password_in_progress_count );
  932. }
  933. # --------------------
  934. # return the bug filter parameters for the specified user
  935. function user_get_bug_filter( $p_user_id, $p_project_id = null ) {
  936. if( null === $p_project_id ) {
  937. $t_project_id = helper_get_current_project();
  938. } else {
  939. $t_project_id = $p_project_id;
  940. }
  941. $t_view_all_cookie_id = filter_db_get_project_current( $t_project_id, $p_user_id );
  942. $t_view_all_cookie = filter_db_get_filter( $t_view_all_cookie_id, $p_user_id );
  943. $t_cookie_detail = explode( '#', $t_view_all_cookie, 2 );
  944. if( !isset( $t_cookie_detail[1] ) ) {
  945. return false;
  946. }
  947. $t_filter = unserialize( $t_cookie_detail[1] );
  948. $t_filter = filter_ensure_valid_filter( $t_filter );
  949. return $t_filter;
  950. }
  951. # ===================================
  952. # Data Modification
  953. # ===================================
  954. # --------------------
  955. # Update the last_visited field to be now
  956. function user_update_last_visit( $p_user_id ) {
  957. $c_user_id = db_prepare_int( $p_user_id );
  958. $c_value = db_now();
  959. $t_user_table = db_get_table( 'user' );
  960. $query = "UPDATE $t_user_table
  961. SET last_visit= " . db_param() . "
  962. WHERE id=" . db_param();
  963. db_query_bound( $query, Array( $c_value, $c_user_id ) );
  964. user_update_cache( $p_user_id, 'last_visit', $c_value );
  965. # db_query errors on failure so:
  966. return true;
  967. }
  968. # --------------------
  969. # Increment the number of times the user has logegd in
  970. # This function is only called from the login.php script
  971. function user_increment_login_count( $p_user_id ) {
  972. $t_user_table = db_get_table( 'user' );
  973. $query = "UPDATE $t_user_table
  974. SET login_count=login_count+1
  975. WHERE id=" . db_param();
  976. db_query_bound( $query, Array( $p_user_id ) );
  977. user_clear_cache( $p_user_id );
  978. # db_query errors on failure so:
  979. return true;
  980. }
  981. # --------------------
  982. # Reset to zero the failed login attempts
  983. function user_reset_failed_login_count_to_zero( $p_user_id ) {
  984. $t_user_table = db_get_table( 'user' );
  985. $query = "UPDATE $t_user_table
  986. SET failed_login_count=0
  987. WHERE id=" . db_param();
  988. db_query_bound( $query, Array( $p_user_id ) );
  989. user_clear_cache( $p_user_id );
  990. return true;
  991. }
  992. # --------------------
  993. # Increment the failed login count by 1
  994. function user_increment_failed_login_count( $p_user_id ) {
  995. $t_user_table = db_get_table( 'user' );
  996. $query = "UPDATE $t_user_table
  997. SET failed_login_count=failed_login_count+1
  998. WHERE id=" . db_param();
  999. db_query_bound( $query, Array( $p_user_id ) );
  1000. user_clear_cache( $p_user_id );
  1001. return true;
  1002. }
  1003. # --------------------
  1004. # Reset to zero the 'lost password' in progress attempts
  1005. function user_reset_lost_password_in_progress_count_to_zero( $p_user_id ) {
  1006. $t_user_table = db_get_table( 'user' );
  1007. $query = "UPDATE $t_user_table
  1008. SET lost_password_request_count=0
  1009. WHERE id=" . db_param();
  1010. db_query_bound( $query, Array( $p_user_id ) );
  1011. user_clear_cache( $p_user_id );
  1012. return true;
  1013. }
  1014. # --------------------
  1015. # Increment the failed login count by 1
  1016. function user_increment_lost_password_in_progress_count( $p_user_id ) {
  1017. $t_user_table = db_get_table( 'user' );
  1018. $query = "UPDATE $t_user_table
  1019. SET lost_password_request_count=lost_password_request_count+1
  1020. WHERE id=" . db_param();
  1021. db_query_bound( $query, Array( $p_user_id ) );
  1022. user_clear_cache( $p_user_id );
  1023. return true;
  1024. }
  1025. # --------------------
  1026. # Set a user field
  1027. function user_set_field( $p_user_id, $p_field_name, $p_field_value ) {
  1028. $c_user_id = db_prepare_int( $p_user_id );
  1029. $c_field_name = db_prepare_string( $p_field_name );
  1030. if( $p_field_name != 'protected' ) {
  1031. user_ensure_unprotected( $p_user_id );
  1032. }
  1033. $t_user_table = db_get_table( 'user' );
  1034. $query = 'UPDATE ' . $t_user_table .
  1035. ' SET ' . $c_field_name . '=' . db_param() .
  1036. ' WHERE id=' . db_param();
  1037. db_query_bound( $query, Array( $p_field_value, $c_user_id ) );
  1038. user_clear_cache( $p_user_id );
  1039. # db_query errors on failure so:
  1040. return true;
  1041. }
  1042. # --------------------
  1043. # Set the user's default project
  1044. function user_set_default_project( $p_user_id, $p_project_id ) {
  1045. return user_pref_set_pref( $p_user_id, 'default_project', (int) $p_project_id );
  1046. }
  1047. # --------------------
  1048. # Set the user's password to the given string, encoded as appropriate
  1049. function user_set_password( $p_user_id, $p_password, $p_allow_protected = false ) {
  1050. if( !$p_allow_protected ) {
  1051. user_ensure_unprotected( $p_user_id );
  1052. }
  1053. $t_email = user_get_field( $p_user_id, 'email' );
  1054. $t_username = user_get_field( $p_user_id, 'username' );
  1055. # When the password is changed, invalidate the cookie to expire sessions that
  1056. # may be active on all browsers.
  1057. $t_seed = $t_email . $t_username;
  1058. $c_cookie_string = auth_generate_unique_cookie_string( $t_seed );
  1059. $c_user_id = db_prepare_int( $p_user_id );
  1060. $c_password = auth_process_plain_password( $p_password );
  1061. $c_user_table = db_get_table( 'user' );
  1062. $query = "UPDATE $c_user_table
  1063. SET password=" . db_param() . ",
  1064. cookie_string=" . db_param() . "
  1065. WHERE id=" . db_param();
  1066. db_query_bound( $query, Array( $c_password, $c_cookie_string, $c_user_id ) );
  1067. # db_query errors on failure so:
  1068. return true;
  1069. }
  1070. # --------------------
  1071. # Set the user's email to the given string after checking that it is a valid email
  1072. function user_set_email( $p_user_id, $p_email ) {
  1073. email_ensure_valid( $p_email );
  1074. return user_set_field( $p_user_id, 'email', $p_email );
  1075. }
  1076. # --------------------
  1077. # Set the user's realname to the given string after checking validity
  1078. function user_set_realname( $p_user_id, $p_realname ) {
  1079. /** @todo ensure_realname_valid( $p_realname ); */
  1080. return user_set_field( $p_user_id, 'realname', $p_realname );
  1081. }
  1082. # --------------------
  1083. # Set the user's username to the given string after checking that it is valid
  1084. function user_set_name( $p_user_id, $p_username ) {
  1085. user_ensure_name_valid( $p_username );
  1086. user_ensure_name_unique( $p_username );
  1087. return user_set_field( $p_user_id, 'username', $p_username );
  1088. }
  1089. # --------------------
  1090. # Reset the user's password
  1091. # Take into account the 'send_reset_password' setting
  1092. # - if it is ON, generate a random password and send an email
  1093. # (unless the second parameter is false)
  1094. # - if it is OFF, set the password to blank
  1095. # Return false if the user is protected, true if the password was
  1096. # successfully reset
  1097. function user_reset_password( $p_user_id, $p_send_email = true ) {
  1098. $t_protected = user_get_field( $p_user_id, 'protected' );
  1099. # Go with random password and email it to the user
  1100. if( ON == $t_protected ) {
  1101. return false;
  1102. }
  1103. # @@@ do we want to force blank password instead of random if
  1104. # email notifications are turned off?
  1105. # How would we indicate that we had done this with a return value?
  1106. # Should we just have two functions? (user_reset_password_random()
  1107. # and user_reset_password() )?
  1108. if(( ON == config_get( 'send_reset_password' ) ) && ( ON == config_get( 'enable_email_notification' ) ) ) {
  1109. # Create random password
  1110. $t_email = user_get_field( $p_user_id, 'email' );
  1111. $t_password = auth_generate_random_password( $t_email );
  1112. $t_password2 = auth_process_plain_password( $t_password );
  1113. user_set_field( $p_user_id, 'password', $t_password2 );
  1114. # Send notification email
  1115. if( $p_send_email ) {
  1116. $t_confirm_hash = auth_generate_confirm_hash( $p_user_id );
  1117. email_send_confirm_hash_url( $p_user_id, $t_confirm_hash );
  1118. }
  1119. } else {
  1120. # use blank password, no emailing
  1121. $t_password = auth_process_plain_password( '' );
  1122. user_set_field( $p_user_id, 'password', $t_password );
  1123. # reset the failed login count because in this mode there is no emailing
  1124. user_reset_failed_login_count_to_zero( $p_user_id );
  1125. }
  1126. return true;
  1127. }