PageRenderTime 27ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/application/libraries/joomla/user/helper.php

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