PageRenderTime 63ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 0ms

/libraries/joomla/user/helper.php

https://bitbucket.org/ankursaxena_2/joomla-platform
PHP | 529 lines | 298 code | 70 blank | 161 comment | 49 complexity | dfc0de4e70bd642813cc0b867203178e MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, BSD-3-Clause
  1. <?php
  2. /**
  3. * @package Joomla.Platform
  4. * @subpackage User
  5. *
  6. * @copyright Copyright (C) 2005 - 2011 Open Source Matters, Inc. All rights reserved.
  7. * @license GNU General Public License version 2 or later; see LICENSE
  8. */
  9. defined('JPATH_PLATFORM') or die;
  10. /**
  11. * Authorization helper class, provides static methods to perform various tasks relevant
  12. * to the Joomla user and authorization classes
  13. *
  14. * This class has influences and some method logic from the Horde Auth package
  15. *
  16. * @static
  17. * @package Joomla.Platform
  18. * @subpackage User
  19. * @since 11.1
  20. */
  21. abstract class JUserHelper
  22. {
  23. /**
  24. * Method to add a user to a group.
  25. *
  26. * @param integer $userId The id of the user.
  27. * @param integer $groupId The id of the group.
  28. *
  29. * @return mixed Boolean true on success, JException on error.
  30. * @since 11.1
  31. */
  32. public static function addUserToGroup($userId, $groupId)
  33. {
  34. // Get the user object.
  35. $user = new JUser((int) $userId);
  36. // Add the user to the group if necessary.
  37. if (!in_array($groupId, $user->groups))
  38. {
  39. // Get the title of the group.
  40. $db = JFactory::getDbo();
  41. $db->setQuery(
  42. 'SELECT `title`' .
  43. ' FROM `#__usergroups`' .
  44. ' WHERE `id` = '. (int) $groupId
  45. );
  46. $title = $db->loadResult();
  47. // Check for a database error.
  48. if ($db->getErrorNum()) {
  49. return new JException($db->getErrorMsg());
  50. }
  51. // If the group does not exist, return an exception.
  52. if (!$title) {
  53. return new JException(JText::_('JLIB_USER_EXCEPTION_ACCESS_USERGROUP_INVALID'));
  54. }
  55. // Add the group data to the user object.
  56. $user->groups[$title] = $groupId;
  57. // Store the user object.
  58. if (!$user->save()) {
  59. return new JException($user->getError());
  60. }
  61. }
  62. // Set the group data for any preloaded user objects.
  63. $temp = JFactory::getUser((int) $userId);
  64. $temp->groups = $user->groups;
  65. // Set the group data for the user object in the session.
  66. $temp = JFactory::getUser();
  67. if ($temp->id == $userId) {
  68. $temp->groups = $user->groups;
  69. }
  70. return true;
  71. }
  72. /**
  73. * Method to get a list of groups a user is in.
  74. *
  75. * @param integer $userId The id of the user.
  76. * @return mixed Array on success, JException on error.
  77. * @since 11.1
  78. */
  79. public static function getUserGroups($userId)
  80. {
  81. // Get the user object.
  82. $user = JUser::getInstance((int) $userId);
  83. return isset($user->groups) ? $user->groups : array();
  84. }
  85. /**
  86. * Method to remove a user from a group.
  87. *
  88. * @param integer $userId The id of the user.
  89. * @param integer $groupId The id of the group.
  90. * @return mixed Boolean true on success, JException on error.
  91. * @since 11.1
  92. */
  93. public static function removeUserFromGroup($userId, $groupId)
  94. {
  95. // Get the user object.
  96. $user = JUser::getInstance((int) $userId);
  97. // Remove the user from the group if necessary.
  98. if (in_array($groupId, $user->groups))
  99. {
  100. // Remove the user from the group.
  101. unset($user->groups[$groupId]);
  102. // Store the user object.
  103. if (!$user->save()) {
  104. return new JException($user->getError());
  105. }
  106. }
  107. // Set the group data for any preloaded user objects.
  108. $temp = JFactory::getUser((int) $userId);
  109. $temp->groups = $user->groups;
  110. // Set the group data for the user object in the session.
  111. $temp = JFactory::getUser();
  112. if ($temp->id == $userId) {
  113. $temp->groups = $user->groups;
  114. }
  115. return true;
  116. }
  117. /**
  118. * Method to set the groups for a user.
  119. *
  120. * @param integer $userId The id of the user.
  121. * @param array $groups An array of group ids to put the user in.
  122. *
  123. * @return mixed Boolean true on success, JException on error.
  124. * @since 11.1
  125. */
  126. public static function setUserGroups($userId, $groups)
  127. {
  128. // Get the user object.
  129. $user = JUser::getInstance((int) $userId);
  130. // Set the group ids.
  131. JArrayHelper::toInteger($groups);
  132. $user->groups = $groups;
  133. // Get the titles for the user groups.
  134. $db = JFactory::getDbo();
  135. $db->setQuery(
  136. 'SELECT `id`, `title`' .
  137. ' FROM `#__usergroups`' .
  138. ' WHERE `id` = '.implode(' OR `id` = ', $user->groups)
  139. );
  140. $results = $db->loadObjectList();
  141. // Check for a database error.
  142. if ($db->getErrorNum()) {
  143. return new JException($db->getErrorMsg());
  144. }
  145. // Set the titles for the user groups.
  146. for ($i = 0, $n = count($results); $i < $n; $i++) {
  147. $user->groups[$results[$i]->id] = $results[$i]->title;
  148. }
  149. // Store the user object.
  150. if (!$user->save()) {
  151. return new JException($user->getError());
  152. }
  153. // Set the group data for any preloaded user objects.
  154. $temp = JFactory::getUser((int) $userId);
  155. $temp->groups = $user->groups;
  156. // Set the group data for the user object in the session.
  157. $temp = JFactory::getUser();
  158. if ($temp->id == $userId) {
  159. $temp->groups = $user->groups;
  160. }
  161. return true;
  162. }
  163. /**
  164. * Gets the user profile information
  165. */
  166. function getProfile($userId = 0)
  167. {
  168. if ($userId == 0) {
  169. $user = JFactory::getUser();
  170. $userId = $user->id;
  171. }
  172. else {
  173. $user = JFactory::getUser((int) $userId);
  174. }
  175. // Get the dispatcher and load the user's plugins.
  176. $dispatcher = JDispatcher::getInstance();
  177. JPluginHelper::importPlugin('user');
  178. $data = new JObject;
  179. // Trigger the data preparation event.
  180. $results = $dispatcher->trigger('onPrepareUserProfileData', array($userId, &$data));
  181. return $data;
  182. }
  183. /**
  184. * Method to activate a user
  185. *
  186. * @param string $activation Activation string
  187. *
  188. * @return boolean True on success
  189. * @since 11.1
  190. */
  191. public static function activateUser($activation)
  192. {
  193. // Initialize some variables.
  194. $db = JFactory::getDbo();
  195. // Let's get the id of the user we want to activate
  196. $query = 'SELECT id'
  197. . ' FROM #__users'
  198. . ' WHERE activation = '.$db->Quote($activation)
  199. . ' AND block = 1'
  200. . ' AND lastvisitDate = '.$db->Quote('0000-00-00 00:00:00');
  201. ;
  202. $db->setQuery($query);
  203. $id = intval($db->loadResult());
  204. // Is it a valid user to activate?
  205. if ($id)
  206. {
  207. $user = JUser::getInstance((int) $id);
  208. $user->set('block', '0');
  209. $user->set('activation', '');
  210. // Time to take care of business.... store the user.
  211. if (!$user->save())
  212. {
  213. JError::raiseWarning("SOME_ERROR_CODE", $user->getError());
  214. return false;
  215. }
  216. }
  217. else
  218. {
  219. JError::raiseWarning("SOME_ERROR_CODE", JText::_('JLIB_USER_ERROR_UNABLE_TO_FIND_USER'));
  220. return false;
  221. }
  222. return true;
  223. }
  224. /**
  225. * Returns userid if a user exists
  226. *
  227. * @param string The username to search on
  228. *
  229. * @return int The user id or 0 if not found
  230. */
  231. public static function getUserId($username)
  232. {
  233. // Initialise some variables
  234. $db = JFactory::getDbo();
  235. $query = 'SELECT id FROM #__users WHERE username = ' . $db->Quote($username);
  236. $db->setQuery($query, 0, 1);
  237. return $db->loadResult();
  238. }
  239. /**
  240. * Formats a password using the current encryption.
  241. *
  242. * @param string $plaintext The plaintext password to encrypt.
  243. * @param string $salt The salt to use to encrypt the password. []
  244. * If not present, a new salt will be
  245. * generated.
  246. * @param string $encryption The kind of pasword encryption to use.
  247. * Defaults to md5-hex.
  248. * @param boolean $show_encrypt Some password systems prepend the kind of
  249. * encryption to the crypted password ({SHA},
  250. * etc). Defaults to false.
  251. *
  252. * @return string The encrypted password.
  253. */
  254. public static function getCryptedPassword($plaintext, $salt = '', $encryption = 'md5-hex', $show_encrypt = false)
  255. {
  256. // Get the salt to use.
  257. $salt = JUserHelper::getSalt($encryption, $salt, $plaintext);
  258. // Encrypt the password.
  259. switch ($encryption)
  260. {
  261. case 'plain' :
  262. return $plaintext;
  263. case 'sha' :
  264. $encrypted = base64_encode(mhash(MHASH_SHA1, $plaintext));
  265. return ($show_encrypt) ? '{SHA}'.$encrypted : $encrypted;
  266. case 'crypt' :
  267. case 'crypt-des' :
  268. case 'crypt-md5' :
  269. case 'crypt-blowfish' :
  270. return ($show_encrypt ? '{crypt}' : '').crypt($plaintext, $salt);
  271. case 'md5-base64' :
  272. $encrypted = base64_encode(mhash(MHASH_MD5, $plaintext));
  273. return ($show_encrypt) ? '{MD5}'.$encrypted : $encrypted;
  274. case 'ssha' :
  275. $encrypted = base64_encode(mhash(MHASH_SHA1, $plaintext.$salt).$salt);
  276. return ($show_encrypt) ? '{SSHA}'.$encrypted : $encrypted;
  277. case 'smd5' :
  278. $encrypted = base64_encode(mhash(MHASH_MD5, $plaintext.$salt).$salt);
  279. return ($show_encrypt) ? '{SMD5}'.$encrypted : $encrypted;
  280. case 'aprmd5' :
  281. $length = strlen($plaintext);
  282. $context = $plaintext.'$apr1$'.$salt;
  283. $binary = JUserHelper::_bin(md5($plaintext.$salt.$plaintext));
  284. for ($i = $length; $i > 0; $i -= 16) {
  285. $context .= substr($binary, 0, ($i > 16 ? 16 : $i));
  286. }
  287. for ($i = $length; $i > 0; $i >>= 1) {
  288. $context .= ($i & 1) ? chr(0) : $plaintext[0];
  289. }
  290. $binary = JUserHelper::_bin(md5($context));
  291. for ($i = 0; $i < 1000; $i ++) {
  292. $new = ($i & 1) ? $plaintext : substr($binary, 0, 16);
  293. if ($i % 3) {
  294. $new .= $salt;
  295. }
  296. if ($i % 7) {
  297. $new .= $plaintext;
  298. }
  299. $new .= ($i & 1) ? substr($binary, 0, 16) : $plaintext;
  300. $binary = JUserHelper::_bin(md5($new));
  301. }
  302. $p = array ();
  303. for ($i = 0; $i < 5; $i ++) {
  304. $k = $i +6;
  305. $j = $i +12;
  306. if ($j == 16) {
  307. $j = 5;
  308. }
  309. $p[] = JUserHelper::_toAPRMD5((ord($binary[$i]) << 16) | (ord($binary[$k]) << 8) | (ord($binary[$j])), 5);
  310. }
  311. return '$apr1$'.$salt.'$'.implode('', $p).JUserHelper::_toAPRMD5(ord($binary[11]), 3);
  312. case 'md5-hex' :
  313. default :
  314. $encrypted = ($salt) ? md5($plaintext.$salt) : md5($plaintext);
  315. return ($show_encrypt) ? '{MD5}'.$encrypted : $encrypted;
  316. }
  317. }
  318. /**
  319. * Returns a salt for the appropriate kind of password encryption.
  320. * Optionally takes a seed and a plaintext password, to extract the seed
  321. * of an existing password, or for encryption types that use the plaintext
  322. * in the generation of the salt.
  323. *
  324. * @param string $encryption The kind of pasword encryption to use.
  325. * Defaults to md5-hex.
  326. * @param string $seed The seed to get the salt from (probably a
  327. * previously generated password). Defaults to
  328. * generating a new seed.
  329. * @param string $plaintext The plaintext password that we're generating
  330. * a salt for. Defaults to none.
  331. *
  332. * @return string The generated or extracted salt.
  333. */
  334. public static function getSalt($encryption = 'md5-hex', $seed = '', $plaintext = '')
  335. {
  336. // Encrypt the password.
  337. switch ($encryption)
  338. {
  339. case 'crypt' :
  340. case 'crypt-des' :
  341. if ($seed) {
  342. return substr(preg_replace('|^{crypt}|i', '', $seed), 0, 2);
  343. } else {
  344. return substr(md5(mt_rand()), 0, 2);
  345. }
  346. break;
  347. case 'crypt-md5' :
  348. if ($seed) {
  349. return substr(preg_replace('|^{crypt}|i', '', $seed), 0, 12);
  350. } else {
  351. return '$1$'.substr(md5(mt_rand()), 0, 8).'$';
  352. }
  353. break;
  354. case 'crypt-blowfish' :
  355. if ($seed) {
  356. return substr(preg_replace('|^{crypt}|i', '', $seed), 0, 16);
  357. } else {
  358. return '$2$'.substr(md5(mt_rand()), 0, 12).'$';
  359. }
  360. break;
  361. case 'ssha' :
  362. if ($seed) {
  363. return substr(preg_replace('|^{SSHA}|', '', $seed), -20);
  364. } else {
  365. return mhash_keygen_s2k(MHASH_SHA1, $plaintext, substr(pack('h*', md5(mt_rand())), 0, 8), 4);
  366. }
  367. break;
  368. case 'smd5' :
  369. if ($seed) {
  370. return substr(preg_replace('|^{SMD5}|', '', $seed), -16);
  371. } else {
  372. return mhash_keygen_s2k(MHASH_MD5, $plaintext, substr(pack('h*', md5(mt_rand())), 0, 8), 4);
  373. }
  374. break;
  375. case 'aprmd5' :
  376. /* 64 characters that are valid for APRMD5 passwords. */
  377. $APRMD5 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
  378. if ($seed) {
  379. return substr(preg_replace('/^\$apr1\$(.{8}).*/', '\\1', $seed), 0, 8);
  380. } else {
  381. $salt = '';
  382. for ($i = 0; $i < 8; $i ++) {
  383. $salt .= $APRMD5 {
  384. rand(0, 63)
  385. };
  386. }
  387. return $salt;
  388. }
  389. break;
  390. default :
  391. $salt = '';
  392. if ($seed) {
  393. $salt = $seed;
  394. }
  395. return $salt;
  396. break;
  397. }
  398. }
  399. /**
  400. * Generate a random password
  401. *
  402. * @static
  403. * @param int $length Length of the password to generate
  404. * @return string Random Password
  405. * @since 11.1
  406. */
  407. public static function genRandomPassword($length = 8)
  408. {
  409. $salt = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
  410. $len = strlen($salt);
  411. $makepass = '';
  412. $stat = @stat(__FILE__);
  413. if (empty($stat) || !is_array($stat)) $stat = array(php_uname());
  414. mt_srand(crc32(microtime() . implode('|', $stat)));
  415. for ($i = 0; $i < $length; $i ++) {
  416. $makepass .= $salt[mt_rand(0, $len -1)];
  417. }
  418. return $makepass;
  419. }
  420. /**
  421. * Converts to allowed 64 characters for APRMD5 passwords.
  422. *
  423. * @param string $value
  424. * @param integer $count
  425. *
  426. * @return string $value converted to the 64 MD5 characters.
  427. * @since 11.1
  428. */
  429. private static function _toAPRMD5($value, $count)
  430. {
  431. /* 64 characters that are valid for APRMD5 passwords. */
  432. $APRMD5 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
  433. $aprmd5 = '';
  434. $count = abs($count);
  435. while (-- $count) {
  436. $aprmd5 .= $APRMD5[$value & 0x3f];
  437. $value >>= 6;
  438. }
  439. return $aprmd5;
  440. }
  441. /**
  442. * Converts hexadecimal string to binary data.
  443. *
  444. * @param string $hex Hex data.
  445. *
  446. * @return string Binary data.
  447. * @since 11.1
  448. */
  449. private static function _bin($hex)
  450. {
  451. $bin = '';
  452. $length = strlen($hex);
  453. for ($i = 0; $i < $length; $i += 2) {
  454. $tmp = sscanf(substr($hex, $i, 2), '%x');
  455. $bin .= chr(array_shift($tmp));
  456. }
  457. return $bin;
  458. }
  459. }