PageRenderTime 56ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/libraries/joomla/user/helper.php

https://bitbucket.org/asosso/joomla15
PHP | 391 lines | 221 code | 40 blank | 130 comment | 32 complexity | 5052d37d8cba669b7c883e0cf7484fa1 MD5 | raw file
Possible License(s): LGPL-2.1, Apache-2.0
  1. <?php
  2. /**
  3. * @version $Id:helper.php 6961 2007-03-15 16:06:53Z tcp $
  4. * @package Joomla.Framework
  5. * @subpackage User
  6. * @copyright Copyright (C) 2005 - 2012 Open Source Matters. All rights reserved.
  7. * @license GNU/GPL, see LICENSE.php
  8. * Joomla! is free software. This version may have been modified pursuant
  9. * to the GNU General Public License, and as distributed it includes or
  10. * is derivative of works licensed under the GNU General Public License or
  11. * other free or open source software licenses.
  12. * See COPYRIGHT.php for copyright notices and details.
  13. */
  14. defined('JPATH_BASE') or die();
  15. /**
  16. * Authorization helper class, provides static methods to perform various tasks relevant
  17. * to the Joomla user and authorization classes
  18. *
  19. * This class has influences and some method logic from the Horde Auth package
  20. *
  21. * @static
  22. * @package Joomla.Framework
  23. * @subpackage User
  24. * @since 1.5
  25. */
  26. class JUserHelper
  27. {
  28. /**
  29. * Method to activate a user
  30. *
  31. * @param string $activation Activation string
  32. * @return boolean True on success
  33. * @since 1.5
  34. */
  35. function activateUser($activation)
  36. {
  37. //Initialize some variables
  38. $db = & JFactory::getDBO();
  39. // Lets get the id of the user we want to activate
  40. $query = 'SELECT id'
  41. . ' FROM #__users'
  42. . ' WHERE activation = '.$db->Quote($activation)
  43. . ' AND block = 1'
  44. . ' AND lastvisitDate = '.$db->Quote('0000-00-00 00:00:00');
  45. ;
  46. $db->setQuery( $query );
  47. $id = intval( $db->loadResult() );
  48. // Is it a valid user to activate?
  49. if ($id)
  50. {
  51. $user =& JUser::getInstance( (int) $id );
  52. $user->set('block', '0');
  53. $user->set('activation', '');
  54. // Time to take care of business.... store the user.
  55. if (!$user->save())
  56. {
  57. JError::raiseWarning( "SOME_ERROR_CODE", $user->getError() );
  58. return false;
  59. }
  60. }
  61. else
  62. {
  63. JError::raiseWarning( "SOME_ERROR_CODE", JText::_('UNABLE TO FIND A USER WITH GIVEN ACTIVATION STRING') );
  64. return false;
  65. }
  66. return true;
  67. }
  68. /**
  69. * Returns userid if a user exists
  70. *
  71. * @param string The username to search on
  72. * @return int The user id or 0 if not found
  73. */
  74. function getUserId($username)
  75. {
  76. // Initialize some variables
  77. $db = & JFactory::getDBO();
  78. $query = 'SELECT id FROM #__users WHERE username = ' . $db->Quote( $username );
  79. $db->setQuery($query, 0, 1);
  80. return $db->loadResult();
  81. }
  82. /**
  83. * Formats a password using the current encryption.
  84. *
  85. * @access public
  86. * @param string $plaintext The plaintext password to encrypt.
  87. * @param string $salt The salt to use to encrypt the password. []
  88. * If not present, a new salt will be
  89. * generated.
  90. * @param string $encryption The kind of pasword encryption to use.
  91. * Defaults to md5-hex.
  92. * @param boolean $show_encrypt Some password systems prepend the kind of
  93. * encryption to the crypted password ({SHA},
  94. * etc). Defaults to false.
  95. *
  96. * @return string The encrypted password.
  97. */
  98. function getCryptedPassword($plaintext, $salt = '', $encryption = 'md5-hex', $show_encrypt = false)
  99. {
  100. // Get the salt to use.
  101. $salt = JUserHelper::getSalt($encryption, $salt, $plaintext);
  102. // Encrypt the password.
  103. switch ($encryption)
  104. {
  105. case 'plain' :
  106. return $plaintext;
  107. case 'sha' :
  108. $encrypted = base64_encode(mhash(MHASH_SHA1, $plaintext));
  109. return ($show_encrypt) ? '{SHA}'.$encrypted : $encrypted;
  110. case 'crypt' :
  111. case 'crypt-des' :
  112. case 'crypt-md5' :
  113. case 'crypt-blowfish' :
  114. return ($show_encrypt ? '{crypt}' : '').crypt($plaintext, $salt);
  115. case 'md5-base64' :
  116. $encrypted = base64_encode(mhash(MHASH_MD5, $plaintext));
  117. return ($show_encrypt) ? '{MD5}'.$encrypted : $encrypted;
  118. case 'ssha' :
  119. $encrypted = base64_encode(mhash(MHASH_SHA1, $plaintext.$salt).$salt);
  120. return ($show_encrypt) ? '{SSHA}'.$encrypted : $encrypted;
  121. case 'smd5' :
  122. $encrypted = base64_encode(mhash(MHASH_MD5, $plaintext.$salt).$salt);
  123. return ($show_encrypt) ? '{SMD5}'.$encrypted : $encrypted;
  124. case 'aprmd5' :
  125. $length = strlen($plaintext);
  126. $context = $plaintext.'$apr1$'.$salt;
  127. $binary = JUserHelper::_bin(md5($plaintext.$salt.$plaintext));
  128. for ($i = $length; $i > 0; $i -= 16) {
  129. $context .= substr($binary, 0, ($i > 16 ? 16 : $i));
  130. }
  131. for ($i = $length; $i > 0; $i >>= 1) {
  132. $context .= ($i & 1) ? chr(0) : $plaintext[0];
  133. }
  134. $binary = JUserHelper::_bin(md5($context));
  135. for ($i = 0; $i < 1000; $i ++) {
  136. $new = ($i & 1) ? $plaintext : substr($binary, 0, 16);
  137. if ($i % 3) {
  138. $new .= $salt;
  139. }
  140. if ($i % 7) {
  141. $new .= $plaintext;
  142. }
  143. $new .= ($i & 1) ? substr($binary, 0, 16) : $plaintext;
  144. $binary = JUserHelper::_bin(md5($new));
  145. }
  146. $p = array ();
  147. for ($i = 0; $i < 5; $i ++) {
  148. $k = $i +6;
  149. $j = $i +12;
  150. if ($j == 16) {
  151. $j = 5;
  152. }
  153. $p[] = JUserHelper::_toAPRMD5((ord($binary[$i]) << 16) | (ord($binary[$k]) << 8) | (ord($binary[$j])), 5);
  154. }
  155. return '$apr1$'.$salt.'$'.implode('', $p).JUserHelper::_toAPRMD5(ord($binary[11]), 3);
  156. case 'md5-hex' :
  157. default :
  158. $encrypted = ($salt) ? md5($plaintext.$salt) : md5($plaintext);
  159. return ($show_encrypt) ? '{MD5}'.$encrypted : $encrypted;
  160. }
  161. }
  162. /**
  163. * Returns a salt for the appropriate kind of password encryption.
  164. * Optionally takes a seed and a plaintext password, to extract the seed
  165. * of an existing password, or for encryption types that use the plaintext
  166. * in the generation of the salt.
  167. *
  168. * @access public
  169. * @param string $encryption The kind of pasword encryption to use.
  170. * Defaults to md5-hex.
  171. * @param string $seed The seed to get the salt from (probably a
  172. * previously generated password). Defaults to
  173. * generating a new seed.
  174. * @param string $plaintext The plaintext password that we're generating
  175. * a salt for. Defaults to none.
  176. *
  177. * @return string The generated or extracted salt.
  178. */
  179. function getSalt($encryption = 'md5-hex', $seed = '', $plaintext = '')
  180. {
  181. // Encrypt the password.
  182. switch ($encryption)
  183. {
  184. case 'crypt' :
  185. case 'crypt-des' :
  186. if ($seed) {
  187. return substr(preg_replace('|^{crypt}|i', '', $seed), 0, 2);
  188. } else {
  189. return substr(md5(mt_rand()), 0, 2);
  190. }
  191. break;
  192. case 'crypt-md5' :
  193. if ($seed) {
  194. return substr(preg_replace('|^{crypt}|i', '', $seed), 0, 12);
  195. } else {
  196. return '$1$'.substr(md5(mt_rand()), 0, 8).'$';
  197. }
  198. break;
  199. case 'crypt-blowfish' :
  200. if ($seed) {
  201. return substr(preg_replace('|^{crypt}|i', '', $seed), 0, 16);
  202. } else {
  203. return '$2$'.substr(md5(mt_rand()), 0, 12).'$';
  204. }
  205. break;
  206. case 'ssha' :
  207. if ($seed) {
  208. return substr(preg_replace('|^{SSHA}|', '', $seed), -20);
  209. } else {
  210. return mhash_keygen_s2k(MHASH_SHA1, $plaintext, substr(pack('h*', md5(mt_rand())), 0, 8), 4);
  211. }
  212. break;
  213. case 'smd5' :
  214. if ($seed) {
  215. return substr(preg_replace('|^{SMD5}|', '', $seed), -16);
  216. } else {
  217. return mhash_keygen_s2k(MHASH_MD5, $plaintext, substr(pack('h*', md5(mt_rand())), 0, 8), 4);
  218. }
  219. break;
  220. case 'aprmd5' :
  221. /* 64 characters that are valid for APRMD5 passwords. */
  222. $APRMD5 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
  223. if ($seed) {
  224. return substr(preg_replace('/^\$apr1\$(.{8}).*/', '\\1', $seed), 0, 8);
  225. } else {
  226. $salt = '';
  227. for ($i = 0; $i < 8; $i ++) {
  228. $salt .= $APRMD5 {
  229. rand(0, 63)
  230. };
  231. }
  232. return $salt;
  233. }
  234. break;
  235. default :
  236. $salt = '';
  237. if ($seed) {
  238. $salt = $seed;
  239. }
  240. return $salt;
  241. break;
  242. }
  243. }
  244. /**
  245. * Generate a random password on PHP4
  246. * The password is not truely random, but the best we can do for PHP4.
  247. * To get a stronger random number, use PHP5.
  248. *
  249. * @static
  250. * @param int $length Length of the password to generate
  251. * @return string Random Password
  252. * @since 1.5.26
  253. */
  254. function genRandomPasswordPHP4($length = 8)
  255. {
  256. $salt = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
  257. $len = strlen($salt);
  258. $makepass = '';
  259. for ($i = 0; $i < $length; $i ++) {
  260. $makepass .= $salt[mt_rand(0, $len -1)];
  261. }
  262. return $makepass;
  263. }
  264. /**
  265. * Generate a random password
  266. * This method is secure.
  267. *
  268. * @static
  269. * @param int $length Length of the password to generate
  270. * @return string Random Password
  271. * @since 1.5.26
  272. */
  273. function genRandomPasswordPHP5($length = 8)
  274. {
  275. $salt = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
  276. $base = strlen($salt);
  277. $makepass = '';
  278. /*
  279. * Start with a cryptographic strength random string, then convert it to
  280. * a string with the numeric base of the salt.
  281. * Shift the base conversion on each character so the character
  282. * distribution is even, and randomize the start shift so it's not
  283. * predictable.
  284. */
  285. jimport('joomla.crypt.crypt');
  286. $random = JCrypt::genRandomBytes($length + 1);
  287. $shift = ord($random[0]);
  288. for ($i = 1; $i <= $length; ++$i)
  289. {
  290. $makepass .= $salt[($shift + ord($random[$i])) % $base];
  291. $shift += ord($random[$i]);
  292. }
  293. return $makepass;
  294. }
  295. /**
  296. * Generate a random password
  297. *
  298. * @static
  299. * @param int $length Length of the password to generate
  300. * @return string Random Password
  301. * @since 1.5
  302. */
  303. function genRandomPassword($length = 8)
  304. {
  305. if (version_compare(PHP_VERSION, '5.0.0', '<')) {
  306. return $makepass = JUserHelper::genRandomPasswordPHP4($length);
  307. }
  308. else {
  309. return $makepass = JUserHelper::genRandomPasswordPHP5($length);
  310. }
  311. }
  312. /**
  313. * Converts to allowed 64 characters for APRMD5 passwords.
  314. *
  315. * @access private
  316. * @param string $value
  317. * @param integer $count
  318. * @return string $value converted to the 64 MD5 characters.
  319. * @since 1.5
  320. */
  321. function _toAPRMD5($value, $count)
  322. {
  323. /* 64 characters that are valid for APRMD5 passwords. */
  324. $APRMD5 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
  325. $aprmd5 = '';
  326. $count = abs($count);
  327. while (-- $count) {
  328. $aprmd5 .= $APRMD5[$value & 0x3f];
  329. $value >>= 6;
  330. }
  331. return $aprmd5;
  332. }
  333. /**
  334. * Converts hexadecimal string to binary data.
  335. *
  336. * @access private
  337. * @param string $hex Hex data.
  338. * @return string Binary data.
  339. * @since 1.5
  340. */
  341. function _bin($hex)
  342. {
  343. $bin = '';
  344. $length = strlen($hex);
  345. for ($i = 0; $i < $length; $i += 2) {
  346. $tmp = sscanf(substr($hex, $i, 2), '%x');
  347. $bin .= chr(array_shift($tmp));
  348. }
  349. return $bin;
  350. }
  351. }