Source for file helper.php

Documentation is available at helper.php

  1. <?php
  2. /**
  3.  * @package     Joomla.Platform
  4.  * @subpackage  User
  5.  *
  6.  * @copyright   Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
  7.  * @license     GNU General Public License version 2 or later; see LICENSE
  8.  */
  9.  
  10. defined('JPATH_PLATFORM') or die;
  11.  
  12. // Always make sure that the password hashing API has been defined.
  13. // include_once JPATH_ROOT . '/libraries/compat/password/lib/password.php';
  14.  
  15. /**
  16.  * Authorisation helper class, provides static methods to perform various tasks relevant
  17.  * to the Joomla user and authorisation classes
  18.  *
  19.  * This class has influences and some method logic from the Horde Auth package
  20.  *
  21.  * @package     Joomla.Platform
  22.  * @subpackage  User
  23.  * @since       11.1
  24.  */
  25. abstract class JUserHelper
  26. {
  27.     /**
  28.      * Method to add a user to a group.
  29.      *
  30.      * @param   integer  $userId   The id of the user.
  31.      * @param   integer  $groupId  The id of the group.
  32.      *
  33.      * @return  boolean  True on success
  34.      *
  35.      * @since   11.1
  36.      * @throws  RuntimeException
  37.      */
  38.     public static function addUserToGroup($userId, $groupId)
  39.     {
  40.         // Get the user object.
  41.         $user = new JUser((int) $userId);
  42.  
  43.         // Add the user to the group if necessary.
  44.         if (!in_array($groupId, $user->groups))
  45.         {
  46.             // Get the title of the group.
  47.             $db = JFactory::getDbo();
  48.             $query = $db->getQuery(true)
  49.                 ->select($db->quoteName('title'))
  50.                 ->from($db->quoteName('#__usergroups'))
  51.                 ->where($db->quoteName('id') . ' = ' . (int) $groupId);
  52.             $db->setQuery($query);
  53.             $title = $db->loadResult();
  54.  
  55.             // If the group does not exist, return an exception.
  56.             if (!$title)
  57.             {
  58.                 throw new RuntimeException('Access Usergroup Invalid');
  59.             }
  60.  
  61.             // Add the group data to the user object.
  62.             $user->groups[$title] = $groupId;
  63.  
  64.             // Store the user object.
  65.             $user->save();
  66.         }
  67.  
  68.         if (session_id())
  69.         {
  70.             // Set the group data for any preloaded user objects.
  71.             $temp = JFactory::getUser((int) $userId);
  72.             $temp->groups = $user->groups;
  73.  
  74.             // Set the group data for the user object in the session.
  75.             $temp = JFactory::getUser();
  76.  
  77.             if ($temp->id == $userId)
  78.             {
  79.                 $temp->groups = $user->groups;
  80.             }
  81.         }
  82.  
  83.         return true;
  84.     }
  85.  
  86.     /**
  87.      * Method to get a list of groups a user is in.
  88.      *
  89.      * @param   integer  $userId  The id of the user.
  90.      *
  91.      * @return  array    List of groups
  92.      *
  93.      * @since   11.1
  94.      */
  95.     public static function getUserGroups($userId)
  96.     {
  97.         // Get the user object.
  98.         $user = JUser::getInstance((int) $userId);
  99.  
  100.         return isset($user->groups) ? $user->groups : array();
  101.     }
  102.  
  103.     /**
  104.      * Method to remove a user from a group.
  105.      *
  106.      * @param   integer  $userId   The id of the user.
  107.      * @param   integer  $groupId  The id of the group.
  108.      *
  109.      * @return  boolean  True on success
  110.      *
  111.      * @since   11.1
  112.      */
  113.     public static function removeUserFromGroup($userId, $groupId)
  114.     {
  115.         // Get the user object.
  116.         $user = JUser::getInstance((int) $userId);
  117.  
  118.         // Remove the user from the group if necessary.
  119.         $key = array_search($groupId, $user->groups);
  120.  
  121.         if ($key !== false)
  122.         {
  123.             // Remove the user from the group.
  124.             unset($user->groups[$key]);
  125.  
  126.             // Store the user object.
  127.             $user->save();
  128.         }
  129.  
  130.         // Set the group data for any preloaded user objects.
  131.         $temp = JFactory::getUser((int) $userId);
  132.         $temp->groups = $user->groups;
  133.  
  134.         // Set the group data for the user object in the session.
  135.         $temp = JFactory::getUser();
  136.  
  137.         if ($temp->id == $userId)
  138.         {
  139.             $temp->groups = $user->groups;
  140.         }
  141.  
  142.         return true;
  143.     }
  144.  
  145.     /**
  146.      * Method to set the groups for a user.
  147.      *
  148.      * @param   integer  $userId  The id of the user.
  149.      * @param   array    $groups  An array of group ids to put the user in.
  150.      *
  151.      * @return  boolean  True on success
  152.      *
  153.      * @since   11.1
  154.      */
  155.     public static function setUserGroups($userId, $groups)
  156.     {
  157.         // Get the user object.
  158.         $user = JUser::getInstance((int) $userId);
  159.  
  160.         // Set the group ids.
  161.         JArrayHelper::toInteger($groups);
  162.         $user->groups = $groups;
  163.  
  164.         // Get the titles for the user groups.
  165.         $db = JFactory::getDbo();
  166.         $query = $db->getQuery(true)
  167.             ->select($db->quoteName('id') . ', ' . $db->quoteName('title'))
  168.             ->from($db->quoteName('#__usergroups'))
  169.             ->where($db->quoteName('id') . ' = ' . implode(' OR ' . $db->quoteName('id') . ' = ', $user->groups));
  170.         $db->setQuery($query);
  171.         $results = $db->loadObjectList();
  172.  
  173.         // Set the titles for the user groups.
  174.         for ($i = 0, $n = count($results); $i < $n; $i++)
  175.         {
  176.             $user->groups[$results[$i]->id] = $results[$i]->id;
  177.         }
  178.  
  179.         // Store the user object.
  180.         $user->save();
  181.  
  182.         if (session_id())
  183.         {
  184.             // Set the group data for any preloaded user objects.
  185.             $temp = JFactory::getUser((int) $userId);
  186.             $temp->groups = $user->groups;
  187.  
  188.             // Set the group data for the user object in the session.
  189.             $temp = JFactory::getUser();
  190.  
  191.             if ($temp->id == $userId)
  192.             {
  193.                 $temp->groups = $user->groups;
  194.             }
  195.         }
  196.  
  197.         return true;
  198.     }
  199.  
  200.     /**
  201.      * Gets the user profile information
  202.      *
  203.      * @param   integer  $userId  The id of the user.
  204.      *
  205.      * @return  object 
  206.      *
  207.      * @since   11.1
  208.      */
  209.     public static function getProfile($userId = 0)
  210.     {
  211.         if ($userId == 0)
  212.         {
  213.             $user    = JFactory::getUser();
  214.             $userId    = $user->id;
  215.         }
  216.  
  217.         // Get the dispatcher and load the user's plugins.
  218.         $dispatcher    = JEventDispatcher::getInstance();
  219.         JPluginHelper::importPlugin('user');
  220.  
  221.         $data = new JObject;
  222.         $data->id = $userId;
  223.  
  224.         // Trigger the data preparation event.
  225.         $dispatcher->trigger('onContentPrepareData', array('com_users.profile', &$data));
  226.  
  227.         return $data;
  228.     }
  229.  
  230.     /**
  231.      * Method to activate a user
  232.      *
  233.      * @param   string  $activation  Activation string
  234.      *
  235.      * @return  boolean  True on success
  236.      *
  237.      * @since   11.1
  238.      */
  239.     public static function activateUser($activation)
  240.     {
  241.         $db = JFactory::getDbo();
  242.  
  243.         // Let's get the id of the user we want to activate
  244.         $query = $db->getQuery(true)
  245.             ->select($db->quoteName('id'))
  246.             ->from($db->quoteName('#__users'))
  247.             ->where($db->quoteName('activation') . ' = ' . $db->quote($activation))
  248.             ->where($db->quoteName('block') . ' = 1')
  249.             ->where($db->quoteName('lastvisitDate') . ' = ' . $db->quote('0000-00-00 00:00:00'));
  250.         $db->setQuery($query);
  251.         $id = (int) $db->loadResult();
  252.  
  253.         // Is it a valid user to activate?
  254.         if ($id)
  255.         {
  256.             $user = JUser::getInstance((int) $id);
  257.  
  258.             $user->set('block', '0');
  259.             $user->set('activation', '');
  260.  
  261.             // Time to take care of business.... store the user.
  262.             if (!$user->save())
  263.             {
  264.                 JLog::add($user->getError(), JLog::WARNING, 'jerror');
  265.  
  266.                 return false;
  267.             }
  268.         }
  269.         else
  270.         {
  271.             JLog::add(JText::_('JLIB_USER_ERROR_UNABLE_TO_FIND_USER'), JLog::WARNING, 'jerror');
  272.  
  273.             return false;
  274.         }
  275.  
  276.         return true;
  277.     }
  278.  
  279.     /**
  280.      * Returns userid if a user exists
  281.      *
  282.      * @param   string  $username  The username to search on.
  283.      *
  284.      * @return  integer  The user id or 0 if not found.
  285.      *
  286.      * @since   11.1
  287.      */
  288.     public static function getUserId($username)
  289.     {
  290.         // Initialise some variables
  291.         $db = JFactory::getDbo();
  292.         $query = $db->getQuery(true)
  293.             ->select($db->quoteName('id'))
  294.             ->from($db->quoteName('#__users'))
  295.             ->where($db->quoteName('username') . ' = ' . $db->quote($username));
  296.         $db->setQuery($query, 0, 1);
  297.  
  298.         return $db->loadResult();
  299.     }
  300.  
  301.     /**
  302.      * Formats a password using the current encryption.
  303.      *
  304.      * @param   string   $plaintext     The plaintext password to encrypt.
  305.      * @param   string   $salt          The salt to use to encrypt the password. []
  306.      *                                   If not present, a new salt will be
  307.      *                                   generated.
  308.      * @param   string   $encryption    The kind of password encryption to use.
  309.      *                                   Defaults to md5-hex.
  310.      * @param   boolean  $show_encrypt  Some password systems prepend the kind of
  311.      *                                   encryption to the crypted password ({SHA},
  312.      *                                   etc). Defaults to false.
  313.      *
  314.      * @return  string  The encrypted password.
  315.      *
  316.      * @since   11.1
  317.      * @note    In Joomla! CMS 3.2 the default encrytion has been changed to bcrypt. When PHP 5.5 is the minimum
  318.      *           supported version it will be changed to the PHP PASSWORD_DEFAULT constant.
  319.      */
  320.     public static function getCryptedPassword($plaintext, $salt = '', $encryption = 'bcrypt', $show_encrypt = false)
  321.     {
  322.         $app = JFactory::getApplication();
  323.  
  324.         if ($app->getClientId() != 2)
  325.         {
  326.             $joomlaPluginEnabled = JPluginHelper::isEnabled('user', 'joomla');
  327.         }
  328.  
  329.         // The Joomla user plugin allows you to use weaker passwords if necessary.
  330.         if (!empty($joomlaPluginEnabled))
  331.         {
  332.             JPluginHelper::importPlugin('user', 'joomla');
  333.             $userPlugin = JPluginHelper::getPlugin('user', 'joomla');
  334.             $userPluginParams = new JRegistry($userPlugin->params);
  335.             PlgUserJoomla::setDefaultEncryption($userPluginParams);
  336.         }
  337.  
  338.         // Not all controllers check the length, although they should to avoid DOS attacks.
  339.         // The maximum password length for bcrypt is 55:
  340.         if (strlen($plaintext) > 55)
  341.         {
  342.             $app->enqueueMessage(JText::_('JLIB_USER_ERROR_PASSWORD_TOO_LONG'), 'error');
  343.  
  344.             return false;
  345.         }
  346.  
  347.         // Get the salt to use.
  348.         if (empty($salt))
  349.         {
  350.             $salt = self::getSalt($encryption, $salt, $plaintext);
  351.         }
  352.  
  353.         // Encrypt the password.
  354.         switch ($encryption)
  355.         {
  356.             case 'plain':
  357.                 return $plaintext;
  358.  
  359.             case 'sha':
  360.                 $encrypted = base64_encode(mhash(MHASH_SHA1, $plaintext));
  361.  
  362.                 return ($show_encrypt) ? '{SHA}' . $encrypted : $encrypted;
  363.  
  364.             case 'crypt':
  365.             case 'crypt-des':
  366.             case 'crypt-md5':
  367.             case 'crypt-blowfish':
  368.                 return ($show_encrypt ? '{crypt}' : '') . crypt($plaintext, $salt);
  369.  
  370.             case 'md5-base64':
  371.                 $encrypted = base64_encode(mhash(MHASH_MD5, $plaintext));
  372.  
  373.                 return ($show_encrypt) ? '{MD5}' . $encrypted : $encrypted;
  374.  
  375.             case 'ssha':
  376.                 $encrypted = base64_encode(mhash(MHASH_SHA1, $plaintext . $salt) . $salt);
  377.  
  378.                 return ($show_encrypt) ? '{SSHA}' . $encrypted : $encrypted;
  379.  
  380.             case 'smd5':
  381.                 $encrypted = base64_encode(mhash(MHASH_MD5, $plaintext . $salt) . $salt);
  382.  
  383.                 return ($show_encrypt) ? '{SMD5}' . $encrypted : $encrypted;
  384.  
  385.             case 'aprmd5':
  386.                 $length = strlen($plaintext);
  387.                 $context = $plaintext . '$apr1$' . $salt;
  388.                 $binary = self::_bin(md5($plaintext . $salt . $plaintext));
  389.  
  390.                 for ($i = $length; $i > 0; $i -= 16)
  391.                 {
  392.                     $context .= substr($binary, 0, ($i > 16 ? 16 : $i));
  393.                 }
  394.                 for ($i = $length; $i > 0; $i >>= 1)
  395.                 {
  396.                     $context .= ($i & 1) ? chr(0) : $plaintext[0];
  397.                 }
  398.  
  399.                 $binary = self::_bin(md5($context));
  400.  
  401.                 for ($i = 0; $i < 1000; $i++)
  402.                 {
  403.                     $new = ($i & 1) ? $plaintext : substr($binary, 0, 16);
  404.  
  405.                     if ($i % 3)
  406.                     {
  407.                         $new .= $salt;
  408.                     }
  409.                     if ($i % 7)
  410.                     {
  411.                         $new .= $plaintext;
  412.                     }
  413.                     $new .= ($i & 1) ? substr($binary, 0, 16) : $plaintext;
  414.                     $binary = self::_bin(md5($new));
  415.                 }
  416.  
  417.                 $p = array();
  418.  
  419.                 for ($i = 0; $i < 5; $i++)
  420.                 {
  421.                     $k = $i + 6;
  422.                     $j = $i + 12;
  423.  
  424.                     if ($j == 16)
  425.                     {
  426.                         $j = 5;
  427.                     }
  428.                     $p[] = self::_toAPRMD5((ord($binary[$i]) << 16) | (ord($binary[$k]) << 8) | (ord($binary[$j])), 5);
  429.                 }
  430.  
  431.                 return '$apr1$' . $salt . '$' . implode('', $p) . self::_toAPRMD5(ord($binary[11]), 3);
  432.  
  433.             case 'md5-hex':
  434.                 $encrypted = ($salt) ? md5($plaintext . $salt) : md5($plaintext);
  435.  
  436.                 return ($show_encrypt) ? '{MD5}' . $encrypted : $encrypted;
  437.  
  438.             case 'sha256':
  439.                 $encrypted = ($salt) ? hash('sha256', $plaintext . $salt) . ':' . $salt : hash('sha256', $plaintext);
  440.  
  441.                 return ($show_encrypt) ? '{SHA256}' . $encrypted : '{SHA256}' . $encrypted;
  442.  
  443.             // 'bcrypt' is the default case starting in CMS 3.2.
  444.             case 'bcrypt':
  445.             default:
  446.                 $useStrongEncryption = JCrypt::hasStrongPasswordSupport();
  447.  
  448.                 if ($useStrongEncryption === true)
  449.                 {
  450.                     $encrypted = password_hash($plaintext, PASSWORD_BCRYPT);
  451.  
  452.                     if (!$encrypted)
  453.                     {
  454.                         // Something went wrong fall back to sha256.
  455.                             return static::getCryptedPassword($plaintext, '', 'sha256', false);
  456.                     }
  457.  
  458.                     return ($show_encrypt) ? '{BCRYPT}' . $encrypted : $encrypted;
  459.                 }
  460.                 else
  461.                 {
  462.                     // BCrypt isn't available but we want strong passwords, fall back to sha256.
  463.                     return static::getCryptedPassword($plaintext, '', 'sha256', false);
  464.                 }
  465.         }
  466.     }
  467.  
  468.     /**
  469.      * Returns a salt for the appropriate kind of password encryption.
  470.      * Optionally takes a seed and a plaintext password, to extract the seed
  471.      * of an existing password, or for encryption types that use the plaintext
  472.      * in the generation of the salt.
  473.      *
  474.      * @param   string  $encryption  The kind of password encryption to use.
  475.      *                                Defaults to md5-hex.
  476.      * @param   string  $seed        The seed to get the salt from (probably a
  477.      *                                previously generated password). Defaults to
  478.      *                                generating a new seed.
  479.      * @param   string  $plaintext   The plaintext password that we're generating
  480.      *                                a salt for. Defaults to none.
  481.      *
  482.      * @return  string  The generated or extracted salt.
  483.      *
  484.      * @since   11.1
  485.      * @note    Default $encryption will be changed to 'bcrypt' in CMS 3.2 and will at
  486.      *           the type used by the PHP PASSWORD_DEFAULT constant until 5.5 is the minimum
  487.      *           version required. At that point the default will be PASSWORD_DEFAULT.
  488.      */
  489.     public static function getSalt($encryption = 'md5-hex', $seed = '', $plaintext = '')
  490.     {
  491.         // Encrypt the password.
  492.         switch ($encryption)
  493.         {
  494.             case 'crypt':
  495.             case 'crypt-des':
  496.                 if ($seed)
  497.                 {
  498.                     return substr(preg_replace('|^{crypt}|i', '', $seed), 0, 2);
  499.                 }
  500.                 else
  501.                 {
  502.                     return substr(md5(mt_rand()), 0, 2);
  503.                 }
  504.                 break;
  505.  
  506.                 case 'sha256':
  507.                     if ($seed)
  508.                     {
  509.                         return preg_replace('|^{sha256}|i', '', $seed);
  510.                     }
  511.                     else
  512.                     {
  513.                         return static::genRandomPassword(16);
  514.                     }
  515.                     break;
  516.  
  517.                 case 'crypt-md5':
  518.                 if ($seed)
  519.                 {
  520.                     return substr(preg_replace('|^{crypt}|i', '', $seed), 0, 12);
  521.                 }
  522.                 else
  523.                 {
  524.                     return '$1$' . substr(md5(mt_rand()), 0, 8) . '$';
  525.                 }
  526.                 break;
  527.  
  528.             case 'crypt-blowfish':
  529.                 if ($seed)
  530.                 {
  531.                     return substr(preg_replace('|^{crypt}|i', '', $seed), 0, 16);
  532.                 }
  533.                 else
  534.                 {
  535.                     return '$2$' . substr(md5(mt_rand()), 0, 12) . '$';
  536.                 }
  537.                 break;
  538.  
  539.             case 'ssha':
  540.                 if ($seed)
  541.                 {
  542.                     return substr(preg_replace('|^{SSHA}|', '', $seed), -20);
  543.                 }
  544.                 else
  545.                 {
  546.                     return mhash_keygen_s2k(MHASH_SHA1, $plaintext, substr(pack('h*', md5(mt_rand())), 0, 8), 4);
  547.                 }
  548.                 break;
  549.  
  550.             case 'smd5':
  551.                 if ($seed)
  552.                 {
  553.                     return substr(preg_replace('|^{SMD5}|', '', $seed), -16);
  554.                 }
  555.                 else
  556.                 {
  557.                     return mhash_keygen_s2k(MHASH_MD5, $plaintext, substr(pack('h*', md5(mt_rand())), 0, 8), 4);
  558.                 }
  559.                 break;
  560.  
  561.             case 'aprmd5': /* 64 characters that are valid for APRMD5 passwords. */
  562.                 $APRMD5 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
  563.  
  564.                 if ($seed)
  565.                 {
  566.                     return substr(preg_replace('/^\$apr1\$(.{8}).*/', '\\1', $seed), 0, 8);
  567.                 }
  568.                 else
  569.                 {
  570.                     $salt = '';
  571.  
  572.                     for ($i = 0; $i < 8; $i++)
  573.                     {
  574.                         $salt .= $APRMD5{rand(0, 63)};
  575.                     }
  576.  
  577.                     return $salt;
  578.                 }
  579.                 break;
  580.  
  581.             // BCrypt is aliased because a BCrypt has may be requested when it is not present, and so it falls back to
  582.             // the default behavior of generating a salt.
  583.             case 'bcrypt';
  584.             default:
  585.                 $salt = '';
  586.  
  587.                 if ($seed)
  588.                 {
  589.                     $salt = $seed;
  590.                 }
  591.  
  592.                 return $salt;
  593.                 break;
  594.         }
  595.     }
  596.  
  597.     /**
  598.      * Generate a random password
  599.      *
  600.      * @param   integer  $length  Length of the password to generate
  601.      *
  602.      * @return  string  Random Password
  603.      *
  604.      * @since   11.1
  605.      */
  606.     public static function genRandomPassword($length = 16)
  607.     {
  608.         $salt = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
  609.         $base = strlen($salt);
  610.         $makepass = '';
  611.  
  612.         /*
  613.          * Start with a cryptographic strength random string, then convert it to
  614.          * a string with the numeric base of the salt.
  615.          * Shift the base conversion on each character so the character
  616.          * distribution is even, and randomize the start shift so it's not
  617.          * predictable.
  618.          */
  619.         $random = JCrypt::genRandomBytes($length + 1);
  620.         $shift = ord($random[0]);
  621.  
  622.         for ($i = 1; $i <= $length; ++$i)
  623.         {
  624.             $makepass .= $salt[($shift + ord($random[$i])) % $base];
  625.             $shift += ord($random[$i]);
  626.         }
  627.  
  628.         return $makepass;
  629.     }
  630.  
  631.     /**
  632.      * Converts to allowed 64 characters for APRMD5 passwords.
  633.      *
  634.      * @param   string   $value  The value to convert.
  635.      * @param   integer  $count  The number of characters to convert.
  636.      *
  637.      * @return  string  $value converted to the 64 MD5 characters.
  638.      *
  639.      * @since   11.1
  640.      */
  641.     protected static function _toAPRMD5($value, $count)
  642.     {
  643.         /* 64 characters that are valid for APRMD5 passwords. */
  644.         $APRMD5 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
  645.  
  646.         $aprmd5 = '';
  647.         $count = abs($count);
  648.  
  649.         while (--$count)
  650.         {
  651.             $aprmd5 .= $APRMD5[$value & 0x3f];
  652.             $value >>= 6;
  653.         }
  654.         return $aprmd5;
  655.     }
  656.  
  657.     /**
  658.      * Converts hexadecimal string to binary data.
  659.      *
  660.      * @param   string  $hex  Hex data.
  661.      *
  662.      * @return  string  Binary data.
  663.      *
  664.      * @since   11.1
  665.      */
  666.     private static function _bin($hex)
  667.     {
  668.         $bin = '';
  669.         $length = strlen($hex);
  670.  
  671.         for ($i = 0; $i < $length; $i += 2)
  672.         {
  673.             $tmp = sscanf(substr($hex, $i, 2), '%x');
  674.             $bin .= chr(array_shift($tmp));
  675.         }
  676.         return $bin;
  677.     }
  678.  
  679.     /**
  680.      * Method to remove a cookie record from the database and the browser
  681.      *
  682.      * @param   string  $userId      User ID for this user
  683.      * @param   string  $cookieName  Series id (cookie name decoded)
  684.      *
  685.      * @return  boolean  True on success
  686.      *
  687.      * @since   3.2
  688.      * @see     JInput::setCookie for more details
  689.      */
  690.     public static function invalidateCookie($userId, $cookieName)
  691.     {
  692.         $db = JFactory::getDbo();
  693.         $query = $db->getQuery(true);
  694.  
  695.         // Invalidate cookie in the database
  696.         $query
  697.             ->update($db->quoteName('#__user_keys'))
  698.             ->set($db->quoteName('invalid') . ' = 1')
  699.             ->where($db->quotename('user_id') . ' = ' . $db->quote($userId));
  700.  
  701.         $db->setQuery($query)->execute();
  702.  
  703.         // Destroy the cookie in the browser.
  704.         $app = JFactory::getApplication();
  705.         $app->input->cookie->set($cookieName, false, time() - 42000, $app->get('cookie_path'), $app->get('cookie_domain'), false, true);
  706.  
  707.         return true;
  708.     }
  709.  
  710.     /**
  711.      * Clear all expired tokens for all users.
  712.      *
  713.      * @return  mixed  Database query result
  714.      *
  715.      * @since   3.2
  716.      */
  717.     public static function clearExpiredTokens()
  718.     {
  719.         $now = time();
  720.  
  721.         $db = JFactory::getDbo();
  722.         $query = $db->getQuery(true)
  723.         ->delete('#__user_keys')
  724.         ->where($db->quoteName('time') . ' < ' . $db->quote($now));
  725.  
  726.         return $db->setQuery($query)->execute();
  727.     }
  728.  
  729.     /**
  730.      * Method to get the remember me cookie data
  731.      *
  732.      * @return  mixed  An array of information from an authentication cookie or false if there is no cookie
  733.      *
  734.      * @since   3.2
  735.      */
  736.     public static function getRememberCookieData()
  737.     {
  738.         // Create the cookie name
  739.         $cookieName = static::getShortHashedUserAgent();
  740.  
  741.         // Fetch the cookie value
  742.         $app = JFactory::getApplication();
  743.         $cookieValue = $app->input->cookie->get($cookieName);
  744.  
  745.         if (!empty($cookieValue))
  746.         {
  747.             return explode('.', $cookieValue);
  748.         }
  749.         else
  750.         {
  751.             return false;
  752.         }
  753.     }
  754.  
  755.     /**
  756.      * Method to get a hashed user agent string that does not include browser version.
  757.      * Used when frequent version changes cause problems.
  758.      *
  759.      * @return  string  A hashed user agent string with version replaced by 'abcd'
  760.      *
  761.      * @since   3.2
  762.      */
  763.     public static function getShortHashedUserAgent()
  764.     {
  765.         $ua = JFactory::getApplication()->client;
  766.         $uaString = $ua->userAgent;
  767.         $browserVersion = $ua->browserVersion;
  768.         $uaShort = str_replace($browserVersion, 'abcd', $uaString);
  769.  
  770.         return md5(JUri::base() . $uaShort);
  771.     }
  772. }

Documentation generated on Tue, 19 Nov 2013 15:04:36 +0100 by phpDocumentor 1.4.3