Advertisement
Guest User

Untitled

a guest
Jul 16th, 2018
257
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 55.39 KB | None | 0 0
  1. <?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
  2. /**
  3. * Name:  Ion Auth Model
  4. *
  5. * Version: 2.5.2
  6. *
  7. * Author:  Ben Edmunds
  8. *          ben.edmunds@gmail.com
  9. *          @benedmunds
  10. *
  11. * Added Awesomeness: Phil Sturgeon
  12. *
  13. * Location: http://github.com/benedmunds/CodeIgniter-Ion-Auth
  14. *
  15. * Created:  10.01.2009
  16. *
  17. * Last Change: 3.22.13
  18. *
  19. * Changelog:
  20. * * 3-22-13 - Additional entropy added - 52aa456eef8b60ad6754b31fbdcc77bb
  21. *
  22. * Description:  Modified auth system based on redux_auth with extensive customization.  This is basically what Redux Auth 2 should be.
  23. * Original Author name has been kept but that does not mean that the method has not been modified.
  24. *
  25. * Requirements: PHP5 or above
  26. *
  27. */
  28.  
  29. class Ion_auth_model extends CI_Model
  30. {
  31.     /**
  32.      * Holds an array of tables used
  33.      *
  34.      * @var array
  35.      **/
  36.     public $tables = array();
  37.  
  38.     /**
  39.      * activation code
  40.      *
  41.      * @var string
  42.      **/
  43.     public $activation_code;
  44.  
  45.     /**
  46.      * forgotten password key
  47.      *
  48.      * @var string
  49.      **/
  50.     public $forgotten_password_code;
  51.  
  52.     /**
  53.      * new password
  54.      *
  55.      * @var string
  56.      **/
  57.     public $new_password;
  58.  
  59.     /**
  60.      * Identity
  61.      *
  62.      * @var string
  63.      **/
  64.     public $identity;
  65.  
  66.     /**
  67.      * Where
  68.      *
  69.      * @var array
  70.      **/
  71.     public $_ion_where = array();
  72.  
  73.     /**
  74.      * Select
  75.      *
  76.      * @var array
  77.      **/
  78.     public $_ion_select = array();
  79.  
  80.     /**
  81.      * Like
  82.      *
  83.      * @var array
  84.      **/
  85.     public $_ion_like = array();
  86.  
  87.     /**
  88.      * Limit
  89.      *
  90.      * @var string
  91.      **/
  92.     public $_ion_limit = NULL;
  93.  
  94.     /**
  95.      * Offset
  96.      *
  97.      * @var string
  98.      **/
  99.     public $_ion_offset = NULL;
  100.  
  101.     /**
  102.      * Order By
  103.      *
  104.      * @var string
  105.      **/
  106.     public $_ion_order_by = NULL;
  107.  
  108.     /**
  109.      * Order
  110.      *
  111.      * @var string
  112.      **/
  113.     public $_ion_order = NULL;
  114.  
  115.     /**
  116.      * Hooks
  117.      *
  118.      * @var object
  119.      **/
  120.     protected $_ion_hooks;
  121.  
  122.     /**
  123.      * Response
  124.      *
  125.      * @var string
  126.      **/
  127.     protected $response = NULL;
  128.  
  129.     /**
  130.      * message (uses lang file)
  131.      *
  132.      * @var string
  133.      **/
  134.     protected $messages;
  135.  
  136.     /**
  137.      * error message (uses lang file)
  138.      *
  139.      * @var string
  140.      **/
  141.     protected $errors;
  142.  
  143.     /**
  144.      * error start delimiter
  145.      *
  146.      * @var string
  147.      **/
  148.     protected $error_start_delimiter;
  149.  
  150.     /**
  151.      * error end delimiter
  152.      *
  153.      * @var string
  154.      **/
  155.     protected $error_end_delimiter;
  156.  
  157.     /**
  158.      * caching of users and their groups
  159.      *
  160.      * @var array
  161.      **/
  162.     public $_cache_user_in_group = array();
  163.  
  164.     /**
  165.      * caching of groups
  166.      *
  167.      * @var array
  168.      **/
  169.     protected $_cache_groups = array();
  170.  
  171.     public function __construct()
  172.     {
  173.         parent::__construct();
  174.         $this->load->database();
  175.         $this->load->config('ion_auth', TRUE);
  176.         $this->load->helper('cookie');
  177.         $this->load->helper('date');
  178.         $this->lang->load('ion_auth');
  179.  
  180.         // initialize db tables data
  181.         $this->tables  = $this->config->item('tables', 'ion_auth');
  182.  
  183.         //initialize data
  184.         $this->identity_column = $this->config->item('identity', 'ion_auth');
  185.         $this->store_salt      = $this->config->item('store_salt', 'ion_auth');
  186.         $this->salt_length     = $this->config->item('salt_length', 'ion_auth');
  187.         $this->join            = $this->config->item('join', 'ion_auth');
  188.  
  189.  
  190.         // initialize hash method options (Bcrypt)
  191.         $this->hash_method = $this->config->item('hash_method', 'ion_auth');
  192.         $this->default_rounds = $this->config->item('default_rounds', 'ion_auth');
  193.         $this->random_rounds = $this->config->item('random_rounds', 'ion_auth');
  194.         $this->min_rounds = $this->config->item('min_rounds', 'ion_auth');
  195.         $this->max_rounds = $this->config->item('max_rounds', 'ion_auth');
  196.  
  197.  
  198.         // initialize messages and error
  199.         $this->messages    = array();
  200.         $this->errors      = array();
  201.         $delimiters_source = $this->config->item('delimiters_source', 'ion_auth');
  202.  
  203.         // load the error delimeters either from the config file or use what's been supplied to form validation
  204.         if ($delimiters_source === 'form_validation')
  205.         {
  206.             // load in delimiters from form_validation
  207.             // to keep this simple we'll load the value using reflection since these properties are protected
  208.             $this->load->library('form_validation');
  209.             $form_validation_class = new ReflectionClass("CI_Form_validation");
  210.  
  211.             $error_prefix = $form_validation_class->getProperty("_error_prefix");
  212.             $error_prefix->setAccessible(TRUE);
  213.             $this->error_start_delimiter = $error_prefix->getValue($this->form_validation);
  214.             $this->message_start_delimiter = $this->error_start_delimiter;
  215.  
  216.             $error_suffix = $form_validation_class->getProperty("_error_suffix");
  217.             $error_suffix->setAccessible(TRUE);
  218.             $this->error_end_delimiter = $error_suffix->getValue($this->form_validation);
  219.             $this->message_end_delimiter = $this->error_end_delimiter;
  220.         }
  221.         else
  222.         {
  223.             // use delimiters from config
  224.             $this->message_start_delimiter = $this->config->item('message_start_delimiter', 'ion_auth');
  225.             $this->message_end_delimiter   = $this->config->item('message_end_delimiter', 'ion_auth');
  226.             $this->error_start_delimiter   = $this->config->item('error_start_delimiter', 'ion_auth');
  227.             $this->error_end_delimiter     = $this->config->item('error_end_delimiter', 'ion_auth');
  228.         }
  229.  
  230.  
  231.         // initialize our hooks object
  232.         $this->_ion_hooks = new stdClass;
  233.  
  234.         // load the bcrypt class if needed
  235.         if ($this->hash_method == 'bcrypt') {
  236.             if ($this->random_rounds)
  237.             {
  238.                 $rand = rand($this->min_rounds,$this->max_rounds);
  239.                 $params = array('rounds' => $rand);
  240.             }
  241.             else
  242.             {
  243.                 $params = array('rounds' => $this->default_rounds);
  244.             }
  245.  
  246.             $params['salt_prefix'] = $this->config->item('salt_prefix', 'ion_auth');
  247.             $this->load->library('bcrypt',$params);
  248.         }
  249.  
  250.         $this->trigger_events('model_constructor');
  251.     }
  252.  
  253.     /**
  254.      * Misc functions
  255.      *
  256.      * Hash password : Hashes the password to be stored in the database.
  257.      * Hash password db : This function takes a password and validates it
  258.      * against an entry in the users table.
  259.      * Salt : Generates a random salt value.
  260.      *
  261.      * @author Mathew
  262.      */
  263.  
  264.     /**
  265.      * Hashes the password to be stored in the database.
  266.      *
  267.      * @return void
  268.      * @author Mathew
  269.      **/
  270.     public function hash_password($password, $salt=false, $use_sha1_override=FALSE)
  271.     {
  272.         if (empty($password))
  273.         {
  274.             return FALSE;
  275.         }
  276.  
  277.         // bcrypt
  278.         if ($use_sha1_override === FALSE && $this->hash_method == 'bcrypt')
  279.         {
  280.             return $this->bcrypt->hash($password);
  281.         }
  282.  
  283.  
  284.         if ($this->store_salt && $salt)
  285.         {
  286.             return  sha1($password . $salt);
  287.         }
  288.         else
  289.         {
  290.             $salt = $this->salt();
  291.             return  $salt . substr(sha1($salt . $password), 0, -$this->salt_length);
  292.         }
  293.     }
  294.  
  295.     /**
  296.      * This function takes a password and validates it
  297.      * against an entry in the users table.
  298.      *
  299.      * @return void
  300.      * @author Mathew
  301.      **/
  302.     public function hash_password_db($id, $password, $use_sha1_override=FALSE)
  303.     {
  304.         if (empty($id) || empty($password))
  305.         {
  306.             return FALSE;
  307.         }
  308.  
  309.         $this->trigger_events('extra_where');
  310.  
  311.         $query = $this->db->select('password, salt')
  312.                           ->where('id', $id)
  313.                           ->limit(1)
  314.                           ->order_by('id', 'desc')
  315.                           ->get($this->tables['users']);
  316.  
  317.         $hash_password_db = $query->row();
  318.  
  319.         if ($query->num_rows() !== 1)
  320.         {
  321.             return FALSE;
  322.         }
  323.  
  324.         // bcrypt
  325.         if ($use_sha1_override === FALSE && $this->hash_method == 'bcrypt')
  326.         {
  327.             if ($this->bcrypt->verify($password,$hash_password_db->password))
  328.             {
  329.                 return TRUE;
  330.             }
  331.  
  332.             return FALSE;
  333.         }
  334.  
  335.         // sha1
  336.         if ($this->store_salt)
  337.         {
  338.             $db_password = sha1($password . $hash_password_db->salt);
  339.         }
  340.         else
  341.         {
  342.             $salt = substr($hash_password_db->password, 0, $this->salt_length);
  343.  
  344.             $db_password =  $salt . substr(sha1($salt . $password), 0, -$this->salt_length);
  345.         }
  346.  
  347.         if($db_password == $hash_password_db->password)
  348.         {
  349.             return TRUE;
  350.         }
  351.         else
  352.         {
  353.             return FALSE;
  354.         }
  355.     }
  356.  
  357.     /**
  358.      * Generates a random salt value for forgotten passwords or any other keys. Uses SHA1.
  359.      *
  360.      * @return void
  361.      * @author Mathew
  362.      **/
  363.     public function hash_code($password)
  364.     {
  365.         return $this->hash_password($password, FALSE, TRUE);
  366.     }
  367.  
  368.     /**
  369.      * Generates a random salt value.
  370.      *
  371.      * Salt generation code taken from https://github.com/ircmaxell/password_compat/blob/master/lib/password.php
  372.      *
  373.      * @return void
  374.      * @author Anthony Ferrera
  375.      **/
  376.     public function salt()
  377.     {
  378.  
  379.         $raw_salt_len = 16;
  380.  
  381.         $buffer = '';
  382.         $buffer_valid = false;
  383.  
  384.         if (function_exists('mcrypt_create_iv') && !defined('PHALANGER')) {
  385.             $buffer = mcrypt_create_iv($raw_salt_len, MCRYPT_DEV_URANDOM);
  386.             if ($buffer) {
  387.                 $buffer_valid = true;
  388.             }
  389.         }
  390.  
  391.         if (!$buffer_valid && function_exists('openssl_random_pseudo_bytes')) {
  392.             $buffer = openssl_random_pseudo_bytes($raw_salt_len);
  393.             if ($buffer) {
  394.                 $buffer_valid = true;
  395.             }
  396.         }
  397.  
  398.         if (!$buffer_valid && @is_readable('/dev/urandom')) {
  399.             $f = fopen('/dev/urandom', 'r');
  400.             $read = strlen($buffer);
  401.             while ($read < $raw_salt_len) {
  402.                 $buffer .= fread($f, $raw_salt_len - $read);
  403.                 $read = strlen($buffer);
  404.             }
  405.             fclose($f);
  406.             if ($read >= $raw_salt_len) {
  407.                 $buffer_valid = true;
  408.             }
  409.         }
  410.  
  411.         if (!$buffer_valid || strlen($buffer) < $raw_salt_len) {
  412.             $bl = strlen($buffer);
  413.             for ($i = 0; $i < $raw_salt_len; $i++) {
  414.                 if ($i < $bl) {
  415.                     $buffer[$i] = $buffer[$i] ^ chr(mt_rand(0, 255));
  416.                 } else {
  417.                     $buffer .= chr(mt_rand(0, 255));
  418.                 }
  419.             }
  420.         }
  421.  
  422.         $salt = $buffer;
  423.  
  424.         // encode string with the Base64 variant used by crypt
  425.         $base64_digits   = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
  426.         $bcrypt64_digits = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
  427.         $base64_string   = base64_encode($salt);
  428.         $salt = strtr(rtrim($base64_string, '='), $base64_digits, $bcrypt64_digits);
  429.  
  430.         $salt = substr($salt, 0, $this->salt_length);
  431.  
  432.  
  433.         return $salt;
  434.  
  435.     }
  436.  
  437.     /**
  438.      * Activation functions
  439.      *
  440.      * Activate : Validates and removes activation code.
  441.      * Deactivae : Updates a users row with an activation code.
  442.      *
  443.      * @author Mathew
  444.      */
  445.  
  446.     /**
  447.      * activate
  448.      *
  449.      * @return void
  450.      * @author Mathew
  451.      **/
  452.     public function activate($id, $code = false)
  453.     {
  454.         $this->trigger_events('pre_activate');
  455.  
  456.         if ($code !== FALSE)
  457.         {
  458.             $query = $this->db->select($this->identity_column)
  459.                               ->where('activation_code', $code)
  460.                               ->where('id', $id)
  461.                               ->limit(1)
  462.                               ->order_by('id', 'desc')
  463.                               ->get($this->tables['users']);
  464.  
  465.             $result = $query->row();
  466.  
  467.             if ($query->num_rows() !== 1)
  468.             {
  469.                 $this->trigger_events(array('post_activate', 'post_activate_unsuccessful'));
  470.                 $this->set_error('activate_unsuccessful');
  471.                 return FALSE;
  472.             }
  473.  
  474.             $data = array(
  475.                 'activation_code' => NULL,
  476.                 'active'          => 1
  477.             );
  478.  
  479.             $this->trigger_events('extra_where');
  480.             $this->db->update($this->tables['users'], $data, array('id' => $id));
  481.         }
  482.         else
  483.         {
  484.             $data = array(
  485.                 'activation_code' => NULL,
  486.                 'active'          => 1
  487.             );
  488.  
  489.  
  490.             $this->trigger_events('extra_where');
  491.             $this->db->update($this->tables['users'], $data, array('id' => $id));
  492.         }
  493.  
  494.  
  495.         $return = $this->db->affected_rows() == 1;
  496.         if ($return)
  497.         {
  498.             $this->trigger_events(array('post_activate', 'post_activate_successful'));
  499.             $this->set_message('activate_successful');
  500.         }
  501.         else
  502.         {
  503.             $this->trigger_events(array('post_activate', 'post_activate_unsuccessful'));
  504.             $this->set_error('activate_unsuccessful');
  505.         }
  506.  
  507.  
  508.         return $return;
  509.     }
  510.  
  511.  
  512.     /**
  513.      * Deactivate
  514.      *
  515.      * @return void
  516.      * @author Mathew
  517.      **/
  518.     public function deactivate($id = NULL)
  519.     {
  520.         $this->trigger_events('deactivate');
  521.  
  522.         if (!isset($id))
  523.         {
  524.             $this->set_error('deactivate_unsuccessful');
  525.             return FALSE;
  526.         }
  527.  
  528.         $activation_code       = sha1(md5(microtime()));
  529.         $this->activation_code = $activation_code;
  530.  
  531.         $data = array(
  532.             'activation_code' => $activation_code,
  533.             'active'          => 0
  534.         );
  535.  
  536.         $this->trigger_events('extra_where');
  537.         $this->db->update($this->tables['users'], $data, array('id' => $id));
  538.  
  539.         $return = $this->db->affected_rows() == 1;
  540.         if ($return)
  541.             $this->set_message('deactivate_successful');
  542.         else
  543.             $this->set_error('deactivate_unsuccessful');
  544.  
  545.         return $return;
  546.     }
  547.  
  548.     public function clear_forgotten_password_code($code) {
  549.  
  550.         if (empty($code))
  551.         {
  552.             return FALSE;
  553.         }
  554.  
  555.         $this->db->where('forgotten_password_code', $code);
  556.  
  557.         if ($this->db->count_all_results($this->tables['users']) > 0)
  558.         {
  559.             $data = array(
  560.                 'forgotten_password_code' => NULL,
  561.                 'forgotten_password_time' => NULL
  562.             );
  563.  
  564.             $this->db->update($this->tables['users'], $data, array('forgotten_password_code' => $code));
  565.  
  566.             return TRUE;
  567.         }
  568.  
  569.         return FALSE;
  570.     }
  571.  
  572.     /**
  573.      * reset password
  574.      *
  575.      * @return bool
  576.      * @author Mathew
  577.      **/
  578.     public function reset_password($identity, $new) {
  579.         $this->trigger_events('pre_change_password');
  580.  
  581.         if (!$this->identity_check($identity)) {
  582.             $this->trigger_events(array('post_change_password', 'post_change_password_unsuccessful'));
  583.             return FALSE;
  584.         }
  585.  
  586.         $this->trigger_events('extra_where');
  587.  
  588.         $query = $this->db->select('id, password, salt')
  589.                           ->where($this->identity_column, $identity)
  590.                           ->limit(1)
  591.                           ->order_by('id', 'desc')
  592.                           ->get($this->tables['users']);
  593.  
  594.         if ($query->num_rows() !== 1)
  595.         {
  596.             $this->trigger_events(array('post_change_password', 'post_change_password_unsuccessful'));
  597.             $this->set_error('password_change_unsuccessful');
  598.             return FALSE;
  599.         }
  600.  
  601.         $result = $query->row();
  602.  
  603.         $new = $this->hash_password($new, $result->salt);
  604.  
  605.         // store the new password and reset the remember code so all remembered instances have to re-login
  606.         // also clear the forgotten password code
  607.         $data = array(
  608.             'password' => $new,
  609.             'remember_code' => NULL,
  610.             'forgotten_password_code' => NULL,
  611.             'forgotten_password_time' => NULL,
  612.         );
  613.  
  614.         $this->trigger_events('extra_where');
  615.         $this->db->update($this->tables['users'], $data, array($this->identity_column => $identity));
  616.  
  617.         $return = $this->db->affected_rows() == 1;
  618.         if ($return)
  619.         {
  620.             $this->trigger_events(array('post_change_password', 'post_change_password_successful'));
  621.             $this->set_message('password_change_successful');
  622.         }
  623.         else
  624.         {
  625.             $this->trigger_events(array('post_change_password', 'post_change_password_unsuccessful'));
  626.             $this->set_error('password_change_unsuccessful');
  627.         }
  628.  
  629.         return $return;
  630.     }
  631.  
  632.     /**
  633.      * change password
  634.      *
  635.      * @return bool
  636.      * @author Mathew
  637.      **/
  638.     public function change_password($identity, $old, $new)
  639.     {
  640.         $this->trigger_events('pre_change_password');
  641.  
  642.         $this->trigger_events('extra_where');
  643.  
  644.         $query = $this->db->select('id, password, salt')
  645.                           ->where($this->identity_column, $identity)
  646.                           ->limit(1)
  647.                           ->order_by('id', 'desc')
  648.                           ->get($this->tables['users']);
  649.  
  650.         if ($query->num_rows() !== 1)
  651.         {
  652.             $this->trigger_events(array('post_change_password', 'post_change_password_unsuccessful'));
  653.             $this->set_error('password_change_unsuccessful');
  654.             return FALSE;
  655.         }
  656.  
  657.         $user = $query->row();
  658.  
  659.         $old_password_matches = $this->hash_password_db($user->id, $old);
  660.  
  661.         if ($old_password_matches === TRUE)
  662.         {
  663.             // store the new password and reset the remember code so all remembered instances have to re-login
  664.             $hashed_new_password  = $this->hash_password($new, $user->salt);
  665.             $data = array(
  666.                 'password' => $hashed_new_password,
  667.                 'remember_code' => NULL,
  668.             );
  669.  
  670.             $this->trigger_events('extra_where');
  671.  
  672.             $successfully_changed_password_in_db = $this->db->update($this->tables['users'], $data, array($this->identity_column => $identity));
  673.             if ($successfully_changed_password_in_db)
  674.             {
  675.                 $this->trigger_events(array('post_change_password', 'post_change_password_successful'));
  676.                 $this->set_message('password_change_successful');
  677.             }
  678.             else
  679.             {
  680.                 $this->trigger_events(array('post_change_password', 'post_change_password_unsuccessful'));
  681.                 $this->set_error('password_change_unsuccessful');
  682.             }
  683.  
  684.             return $successfully_changed_password_in_db;
  685.         }
  686.  
  687.         $this->set_error('password_change_unsuccessful');
  688.         return FALSE;
  689.     }
  690.  
  691.     /**
  692.      * Checks username
  693.      *
  694.      * @return bool
  695.      * @author Mathew
  696.      **/
  697.     public function username_check($username = '')
  698.     {
  699.         $this->trigger_events('username_check');
  700.  
  701.         if (empty($username))
  702.         {
  703.             return FALSE;
  704.         }
  705.  
  706.         $this->trigger_events('extra_where');
  707.  
  708.         return $this->db->where('username', $username)
  709.                                         ->group_by("id")
  710.                                         ->order_by("id", "ASC")
  711.                                         ->limit(1)
  712.                         ->count_all_results($this->tables['users']) > 0;
  713.     }
  714.  
  715.     /**
  716.      * Checks email
  717.      *
  718.      * @return bool
  719.      * @author Mathew
  720.      **/
  721.     public function email_check($email = '')
  722.     {
  723.         $this->trigger_events('email_check');
  724.  
  725.         if (empty($email))
  726.         {
  727.             return FALSE;
  728.         }
  729.  
  730.         $this->trigger_events('extra_where');
  731.  
  732.         return $this->db->where('email', $email)
  733.                                         ->group_by("id")
  734.                                         ->order_by("id", "ASC")
  735.                                         ->limit(1)
  736.                         ->count_all_results($this->tables['users']) > 0;
  737.     }
  738.  
  739.     /**
  740.      * Identity check
  741.      *
  742.      * @return bool
  743.      * @author Mathew
  744.      **/
  745.     public function identity_check($identity = '')
  746.     {
  747.         $this->trigger_events('identity_check');
  748.  
  749.         if (empty($identity))
  750.         {
  751.             return FALSE;
  752.         }
  753.  
  754.         return $this->db->where($this->identity_column, $identity)
  755.                         ->count_all_results($this->tables['users']) > 0;
  756.     }
  757.  
  758.     /**
  759.      * Insert a forgotten password key.
  760.      *
  761.      * @return bool
  762.      * @author Mathew
  763.      * @updated Ryan
  764.      * @updated 52aa456eef8b60ad6754b31fbdcc77bb
  765.      **/
  766.     public function forgotten_password($identity)
  767.     {
  768.         if (empty($identity))
  769.         {
  770.             $this->trigger_events(array('post_forgotten_password', 'post_forgotten_password_unsuccessful'));
  771.             return FALSE;
  772.         }
  773.  
  774.         // All some more randomness
  775.         $activation_code_part = "";
  776.         if(function_exists("openssl_random_pseudo_bytes")) {
  777.             $activation_code_part = openssl_random_pseudo_bytes(128);
  778.         }
  779.  
  780.         for($i=0;$i<1024;$i++) {
  781.             $activation_code_part = sha1($activation_code_part . mt_rand() . microtime());
  782.         }
  783.  
  784.         $key = $this->hash_code($activation_code_part.$identity);
  785.  
  786.         // If enable query strings is set, then we need to replace any unsafe characters so that the code can still work
  787.         if ($key != '' && $this->config->item('permitted_uri_chars') != '' && $this->config->item('enable_query_strings') == FALSE)
  788.         {
  789.             // preg_quote() in PHP 5.3 escapes -, so the str_replace() and addition of - to preg_quote() is to maintain backwards
  790.             // compatibility as many are unaware of how characters in the permitted_uri_chars will be parsed as a regex pattern
  791.             if ( ! preg_match("|^[".str_replace(array('\\-', '\-'), '-', preg_quote($this->config->item('permitted_uri_chars'), '-'))."]+$|i", $key))
  792.             {
  793.                 $key = preg_replace("/[^".$this->config->item('permitted_uri_chars')."]+/i", "-", $key);
  794.             }
  795.         }
  796.  
  797.         $this->forgotten_password_code = $key;
  798.  
  799.         $this->trigger_events('extra_where');
  800.  
  801.         $update = array(
  802.             'forgotten_password_code' => $key,
  803.             'forgotten_password_time' => time()
  804.         );
  805.  
  806.         $this->db->update($this->tables['users'], $update, array($this->identity_column => $identity));
  807.  
  808.         $return = $this->db->affected_rows() == 1;
  809.  
  810.         if ($return)
  811.             $this->trigger_events(array('post_forgotten_password', 'post_forgotten_password_successful'));
  812.         else
  813.             $this->trigger_events(array('post_forgotten_password', 'post_forgotten_password_unsuccessful'));
  814.  
  815.         return $return;
  816.     }
  817.  
  818.     /**
  819.      * Forgotten Password Complete
  820.      *
  821.      * @return string
  822.      * @author Mathew
  823.      **/
  824.     public function forgotten_password_complete($code, $salt=FALSE)
  825.     {
  826.         $this->trigger_events('pre_forgotten_password_complete');
  827.  
  828.         if (empty($code))
  829.         {
  830.             $this->trigger_events(array('post_forgotten_password_complete', 'post_forgotten_password_complete_unsuccessful'));
  831.             return FALSE;
  832.         }
  833.  
  834.         $profile = $this->where('forgotten_password_code', $code)->users()->row(); //pass the code to profile
  835.  
  836.         if ($profile) {
  837.  
  838.             if ($this->config->item('forgot_password_expiration', 'ion_auth') > 0) {
  839.                 //Make sure it isn't expired
  840.                 $expiration = $this->config->item('forgot_password_expiration', 'ion_auth');
  841.                 if (time() - $profile->forgotten_password_time > $expiration) {
  842.                     //it has expired
  843.                     $this->set_error('forgot_password_expired');
  844.                     $this->trigger_events(array('post_forgotten_password_complete', 'post_forgotten_password_complete_unsuccessful'));
  845.                     return FALSE;
  846.                 }
  847.             }
  848.  
  849.             $password = $this->salt();
  850.  
  851.             $data = array(
  852.                 'password'                => $this->hash_password($password, $salt),
  853.                 'forgotten_password_code' => NULL,
  854.                 'active'                  => 1,
  855.              );
  856.  
  857.             $this->db->update($this->tables['users'], $data, array('forgotten_password_code' => $code));
  858.  
  859.             $this->trigger_events(array('post_forgotten_password_complete', 'post_forgotten_password_complete_successful'));
  860.             return $password;
  861.         }
  862.  
  863.         $this->trigger_events(array('post_forgotten_password_complete', 'post_forgotten_password_complete_unsuccessful'));
  864.         return FALSE;
  865.     }
  866.  
  867.     /**
  868.      * register
  869.      *
  870.      * @return bool
  871.      * @author Mathew
  872.      **/
  873.     public function register($identity, $password, $email, $additional_data = array(), $groups = array())
  874.     {
  875.         $this->trigger_events('pre_register');
  876.  
  877.         $manual_activation = $this->config->item('manual_activation', 'ion_auth');
  878.  
  879.         if ($this->identity_check($identity))
  880.         {
  881.             $this->set_error('account_creation_duplicate_identity');
  882.             return FALSE;
  883.         }
  884.         elseif ( !$this->config->item('default_group', 'ion_auth') && empty($groups) )
  885.         {
  886.             $this->set_error('account_creation_missing_default_group');
  887.             return FALSE;
  888.         }
  889.  
  890.         // check if the default set in config exists in database
  891.         $query = $this->db->get_where($this->tables['groups'],array('name' => $this->config->item('default_group', 'ion_auth')),1)->row();
  892.         if( !isset($query->id) && empty($groups) )
  893.         {
  894.             $this->set_error('account_creation_invalid_default_group');
  895.             return FALSE;
  896.         }
  897.  
  898.         // capture default group details
  899.         $default_group = $query;
  900.  
  901.         // IP Address
  902.         $ip_address = $this->_prepare_ip($this->input->ip_address());
  903.         $salt       = $this->store_salt ? $this->salt() : FALSE;
  904.         $password   = $this->hash_password($password, $salt);
  905.  
  906.         // Users table.
  907.         $data = array(
  908.             $this->identity_column   => $identity,
  909.             'password'   => $password,
  910.             'email'      => $email,
  911.             'ip_address' => $ip_address,
  912.             'created_on' => time(),
  913.             'active'     => ($manual_activation === false ? 1 : 0)
  914.         );
  915.  
  916.         if ($this->store_salt)
  917.         {
  918.             $data['salt'] = $salt;
  919.         }
  920.  
  921.         // filter out any data passed that doesnt have a matching column in the users table
  922.         // and merge the set user data and the additional data
  923.         $user_data = array_merge($this->_filter_data($this->tables['users'], $additional_data), $data);
  924.  
  925.         $this->trigger_events('extra_set');
  926.  
  927.         $this->db->insert($this->tables['users'], $user_data);
  928.  
  929.         $id = $this->db->insert_id();
  930.  
  931.         // add in groups array if it doesn't exits and stop adding into default group if default group ids are set
  932.         if( isset($default_group->id) && empty($groups) )
  933.         {
  934.             $groups[] = $default_group->id;
  935.         }
  936.  
  937.         if (!empty($groups))
  938.         {
  939.             // add to groups
  940.             foreach ($groups as $group)
  941.             {
  942.                 $this->add_to_group($group, $id);
  943.             }
  944.         }
  945.  
  946.         $this->trigger_events('post_register');
  947.  
  948.         return (isset($id)) ? $id : FALSE;
  949.     }
  950.  
  951.     /**
  952.      * login
  953.      *
  954.      * @return bool
  955.      * @author Mathew
  956.      **/
  957.     public function login($identity, $password, $remember=FALSE)
  958.     {
  959.         $this->trigger_events('pre_login');
  960.  
  961.         if (empty($identity) || empty($password))
  962.         {
  963.             $this->set_error('login_unsuccessful');
  964.             return FALSE;
  965.         }
  966.  
  967.         $this->trigger_events('extra_where');
  968.  
  969.         $query = $this->db->select($this->identity_column . ', email, id, password, active, last_login')
  970.                           ->where($this->identity_column, $identity)
  971.                           ->limit(1)
  972.                           ->order_by('id', 'desc')
  973.                           ->get($this->tables['users']);
  974.  
  975.         if($this->is_time_locked_out($identity))
  976.         {
  977.             // Hash something anyway, just to take up time
  978.             $this->hash_password($password);
  979.  
  980.             $this->trigger_events('post_login_unsuccessful');
  981.             $this->set_error('login_timeout');
  982.  
  983.             return FALSE;
  984.         }
  985.  
  986.         if ($query->num_rows() === 1)
  987.         {
  988.             $user = $query->row();
  989.  
  990.             $password = $this->hash_password_db($user->id, $password);
  991.  
  992.             if ($password === TRUE)
  993.             {
  994.                 if ($user->active == 0)
  995.                 {
  996.                     $this->trigger_events('post_login_unsuccessful');
  997.                     $this->set_error('login_unsuccessful_not_active');
  998.  
  999.                     return FALSE;
  1000.                 }
  1001.  
  1002.                 $this->set_session($user);
  1003.  
  1004.                 $this->update_last_login($user->id);
  1005.  
  1006.                 $this->clear_login_attempts($identity);
  1007.  
  1008.                 if ($remember && $this->config->item('remember_users', 'ion_auth'))
  1009.                 {
  1010.                     $this->remember_user($user->id);
  1011.                 }
  1012.  
  1013.                 $this->trigger_events(array('post_login', 'post_login_successful'));
  1014.                 $this->set_message('login_successful');
  1015.  
  1016.                 return TRUE;
  1017.             }
  1018.         }
  1019.  
  1020.         // Hash something anyway, just to take up time
  1021.         $this->hash_password($password);
  1022.  
  1023.         $this->increase_login_attempts($identity);
  1024.  
  1025.         $this->trigger_events('post_login_unsuccessful');
  1026.         $this->set_error('login_unsuccessful');
  1027.  
  1028.         return FALSE;
  1029.     }
  1030.  
  1031.     /**
  1032.      * is_max_login_attempts_exceeded
  1033.      * Based on code from Tank Auth, by Ilya Konyukhov (https://github.com/ilkon/Tank-Auth)
  1034.      *
  1035.      * @param string $identity
  1036.      * @return boolean
  1037.      **/
  1038.     public function is_max_login_attempts_exceeded($identity) {
  1039.         if ($this->config->item('track_login_attempts', 'ion_auth')) {
  1040.             $max_attempts = $this->config->item('maximum_login_attempts', 'ion_auth');
  1041.             if ($max_attempts > 0) {
  1042.                 $attempts = $this->get_attempts_num($identity);
  1043.                 return $attempts >= $max_attempts;
  1044.             }
  1045.         }
  1046.         return FALSE;
  1047.     }
  1048.  
  1049.     /**
  1050.      * Get number of attempts to login occured from given IP-address or identity
  1051.      * Based on code from Tank Auth, by Ilya Konyukhov (https://github.com/ilkon/Tank-Auth)
  1052.      *
  1053.      * @param   string $identity
  1054.      * @return  int
  1055.      */
  1056.     function get_attempts_num($identity)
  1057.     {
  1058.         if ($this->config->item('track_login_attempts', 'ion_auth')) {
  1059.             $ip_address = $this->_prepare_ip($this->input->ip_address());
  1060.             $this->db->select('1', FALSE);
  1061.             if ($this->config->item('track_login_ip_address', 'ion_auth')) {
  1062.                 $this->db->where('ip_address', $ip_address);
  1063.                 $this->db->where('login', $identity);
  1064.             } else if (strlen($identity) > 0) $this->db->or_where('login', $identity);
  1065.             $qres = $this->db->get($this->tables['login_attempts']);
  1066.             return $qres->num_rows();
  1067.         }
  1068.         return 0;
  1069.     }
  1070.     /**
  1071.      * Get a boolean to determine if an account should be locked out due to
  1072.      * exceeded login attempts within a given period
  1073.      *
  1074.      * @return  boolean
  1075.      */
  1076.     public function is_time_locked_out($identity) {
  1077.  
  1078.         return $this->is_max_login_attempts_exceeded($identity) && $this->get_last_attempt_time($identity) > time() - $this->config->item('lockout_time', 'ion_auth');
  1079.     }
  1080.  
  1081.     /**
  1082.      * Get the time of the last time a login attempt occured from given IP-address or identity
  1083.      *
  1084.      * @param   string $identity
  1085.      * @return  int
  1086.      */
  1087.     public function get_last_attempt_time($identity) {
  1088.         if ($this->config->item('track_login_attempts', 'ion_auth')) {
  1089.             $ip_address = $this->_prepare_ip($this->input->ip_address());
  1090.  
  1091.             $this->db->select_max('time');
  1092.             if ($this->config->item('track_login_ip_address', 'ion_auth')) $this->db->where('ip_address', $ip_address);
  1093.             else if (strlen($identity) > 0) $this->db->or_where('login', $identity);
  1094.             $qres = $this->db->get($this->tables['login_attempts'], 1);
  1095.  
  1096.             if($qres->num_rows() > 0) {
  1097.                 return $qres->row()->time;
  1098.             }
  1099.         }
  1100.  
  1101.         return 0;
  1102.     }
  1103.  
  1104.     /**
  1105.      * increase_login_attempts
  1106.      * Based on code from Tank Auth, by Ilya Konyukhov (https://github.com/ilkon/Tank-Auth)
  1107.      *
  1108.      * @param string $identity
  1109.      **/
  1110.     public function increase_login_attempts($identity) {
  1111.         if ($this->config->item('track_login_attempts', 'ion_auth')) {
  1112.             $ip_address = $this->_prepare_ip($this->input->ip_address());
  1113.             return $this->db->insert($this->tables['login_attempts'], array('ip_address' => $ip_address, 'login' => $identity, 'time' => time()));
  1114.         }
  1115.         return FALSE;
  1116.     }
  1117.  
  1118.     /**
  1119.      * clear_login_attempts
  1120.      * Based on code from Tank Auth, by Ilya Konyukhov (https://github.com/ilkon/Tank-Auth)
  1121.      *
  1122.      * @param string $identity
  1123.      **/
  1124.     public function clear_login_attempts($identity, $expire_period = 86400) {
  1125.         if ($this->config->item('track_login_attempts', 'ion_auth')) {
  1126.             $ip_address = $this->_prepare_ip($this->input->ip_address());
  1127.  
  1128.             $this->db->where(array('ip_address' => $ip_address, 'login' => $identity));
  1129.             // Purge obsolete login attempts
  1130.             $this->db->or_where('time <', time() - $expire_period, FALSE);
  1131.  
  1132.             return $this->db->delete($this->tables['login_attempts']);
  1133.         }
  1134.         return FALSE;
  1135.     }
  1136.  
  1137.     public function limit($limit)
  1138.     {
  1139.         $this->trigger_events('limit');
  1140.         $this->_ion_limit = $limit;
  1141.  
  1142.         return $this;
  1143.     }
  1144.  
  1145.     public function offset($offset)
  1146.     {
  1147.         $this->trigger_events('offset');
  1148.         $this->_ion_offset = $offset;
  1149.  
  1150.         return $this;
  1151.     }
  1152.  
  1153.     public function where($where, $value = NULL)
  1154.     {
  1155.         $this->trigger_events('where');
  1156.  
  1157.         if (!is_array($where))
  1158.         {
  1159.             $where = array($where => $value);
  1160.         }
  1161.  
  1162.         array_push($this->_ion_where, $where);
  1163.  
  1164.         return $this;
  1165.     }
  1166.  
  1167.     public function like($like, $value = NULL, $position = 'both')
  1168.     {
  1169.         $this->trigger_events('like');
  1170.  
  1171.         if (!is_array($like))
  1172.         {
  1173.             $like = array($like => array(
  1174.                 'value'    => $value,
  1175.                 'position' => $position,
  1176.             ));
  1177.         }
  1178.  
  1179.         array_push($this->_ion_like, $like);
  1180.  
  1181.         return $this;
  1182.     }
  1183.  
  1184.     public function select($select)
  1185.     {
  1186.         $this->trigger_events('select');
  1187.  
  1188.         $this->_ion_select[] = $select;
  1189.  
  1190.         return $this;
  1191.     }
  1192.  
  1193.     public function order_by($by, $order='desc')
  1194.     {
  1195.         $this->trigger_events('order_by');
  1196.  
  1197.         $this->_ion_order_by = $by;
  1198.         $this->_ion_order    = $order;
  1199.  
  1200.         return $this;
  1201.     }
  1202.  
  1203.     public function row()
  1204.     {
  1205.         $this->trigger_events('row');
  1206.  
  1207.         $row = $this->response->row();
  1208.  
  1209.         return $row;
  1210.     }
  1211.  
  1212.     public function row_array()
  1213.     {
  1214.         $this->trigger_events(array('row', 'row_array'));
  1215.  
  1216.         $row = $this->response->row_array();
  1217.  
  1218.         return $row;
  1219.     }
  1220.  
  1221.     public function result()
  1222.     {
  1223.         $this->trigger_events('result');
  1224.  
  1225.         $result = $this->response->result();
  1226.  
  1227.         return $result;
  1228.     }
  1229.  
  1230.     public function result_array()
  1231.     {
  1232.         $this->trigger_events(array('result', 'result_array'));
  1233.  
  1234.         $result = $this->response->result_array();
  1235.  
  1236.         return $result;
  1237.     }
  1238.  
  1239.     public function num_rows()
  1240.     {
  1241.         $this->trigger_events(array('num_rows'));
  1242.  
  1243.         $result = $this->response->num_rows();
  1244.  
  1245.         return $result;
  1246.     }
  1247.  
  1248.     /**
  1249.      * users
  1250.      *
  1251.      * @return object Users
  1252.      * @author Ben Edmunds
  1253.      **/
  1254.     public function users($groups = NULL)
  1255.     {
  1256.         $this->trigger_events('users');
  1257.  
  1258.         if (isset($this->_ion_select) && !empty($this->_ion_select))
  1259.         {
  1260.             foreach ($this->_ion_select as $select)
  1261.             {
  1262.                 $this->db->select($select);
  1263.             }
  1264.  
  1265.             $this->_ion_select = array();
  1266.         }
  1267.         else
  1268.         {
  1269.             //default selects
  1270.             $this->db->select(array(
  1271.                 $this->tables['users'].'.*',
  1272.                 $this->tables['users'].'.id as id',
  1273.                 $this->tables['users'].'.id as user_id'
  1274.             ));
  1275.         }
  1276.  
  1277.         // filter by group id(s) if passed
  1278.         if (isset($groups))
  1279.         {
  1280.             // build an array if only one group was passed
  1281.             if (!is_array($groups))
  1282.             {
  1283.                 $groups = Array($groups);
  1284.             }
  1285.  
  1286.             // join and then run a where_in against the group ids
  1287.             if (isset($groups) && !empty($groups))
  1288.             {
  1289.                 $this->db->distinct();
  1290.                 $this->db->join(
  1291.                     $this->tables['users_groups'],
  1292.                     $this->tables['users_groups'].'.'.$this->join['users'].'='.$this->tables['users'].'.id',
  1293.                     'inner'
  1294.                 );
  1295.             }
  1296.  
  1297.             // verify if group name or group id was used and create and put elements in different arrays
  1298.             $group_ids = array();
  1299.             $group_names = array();
  1300.             foreach($groups as $group)
  1301.             {
  1302.                 if(is_numeric($group)) $group_ids[] = $group;
  1303.                 else $group_names[] = $group;
  1304.             }
  1305.             $or_where_in = (!empty($group_ids) && !empty($group_names)) ? 'or_where_in' : 'where_in';
  1306.             // if group name was used we do one more join with groups
  1307.             if(!empty($group_names))
  1308.             {
  1309.                 $this->db->join($this->tables['groups'], $this->tables['users_groups'] . '.' . $this->join['groups'] . ' = ' . $this->tables['groups'] . '.id', 'inner');
  1310.                 $this->db->where_in($this->tables['groups'] . '.name', $group_names);
  1311.             }
  1312.             if(!empty($group_ids))
  1313.             {
  1314.                 $this->db->{$or_where_in}($this->tables['users_groups'].'.'.$this->join['groups'], $group_ids);
  1315.             }
  1316.         }
  1317.  
  1318.         $this->trigger_events('extra_where');
  1319.  
  1320.         // run each where that was passed
  1321.         if (isset($this->_ion_where) && !empty($this->_ion_where))
  1322.         {
  1323.             foreach ($this->_ion_where as $where)
  1324.             {
  1325.                 $this->db->where($where);
  1326.             }
  1327.  
  1328.             $this->_ion_where = array();
  1329.         }
  1330.  
  1331.         if (isset($this->_ion_like) && !empty($this->_ion_like))
  1332.         {
  1333.             foreach ($this->_ion_like as $like)
  1334.             {
  1335.                 $this->db->or_like($like);
  1336.             }
  1337.  
  1338.             $this->_ion_like = array();
  1339.         }
  1340.  
  1341.         if (isset($this->_ion_limit) && isset($this->_ion_offset))
  1342.         {
  1343.             $this->db->limit($this->_ion_limit, $this->_ion_offset);
  1344.  
  1345.             $this->_ion_limit  = NULL;
  1346.             $this->_ion_offset = NULL;
  1347.         }
  1348.         else if (isset($this->_ion_limit))
  1349.         {
  1350.             $this->db->limit($this->_ion_limit);
  1351.  
  1352.             $this->_ion_limit  = NULL;
  1353.         }
  1354.  
  1355.         // set the order
  1356.         if (isset($this->_ion_order_by) && isset($this->_ion_order))
  1357.         {
  1358.             $this->db->order_by($this->_ion_order_by, $this->_ion_order);
  1359.  
  1360.             $this->_ion_order    = NULL;
  1361.             $this->_ion_order_by = NULL;
  1362.         }
  1363.  
  1364.         $this->response = $this->db->get($this->tables['users']);
  1365.  
  1366.         return $this;
  1367.     }
  1368.  
  1369.     /**
  1370.      * user
  1371.      *
  1372.      * @return object
  1373.      * @author Ben Edmunds
  1374.      **/
  1375.     public function user($id = NULL)
  1376.     {
  1377.         $this->trigger_events('user');
  1378.  
  1379.         // if no id was passed use the current users id
  1380.         $id || $id = $this->session->userdata('user_id');
  1381.  
  1382.         $this->limit(1);
  1383.         $this->order_by($this->tables['users'].'.id', 'desc');
  1384.         $this->where($this->tables['users'].'.id', $id);
  1385.  
  1386.         $this->users();
  1387.  
  1388.         return $this;
  1389.     }
  1390.  
  1391.     /**
  1392.      * get_users_groups
  1393.      *
  1394.      * @return array
  1395.      * @author Ben Edmunds
  1396.      **/
  1397.     public function get_users_groups($id=FALSE)
  1398.     {
  1399.         $this->trigger_events('get_users_group');
  1400.  
  1401.         // if no id was passed use the current users id
  1402.         $id || $id = $this->session->userdata('user_id');
  1403.  
  1404.         //return $this->db->select($this->tables['users_groups'].'.'.$this->join['groups'].' as id, '.$this->tables['groups'].'.name, '.$this->tables['groups'].'.description')
  1405.         /* ADD => , '.$this->tables['groups'].'.bgcolor' */
  1406.         return $this->db->select($this->tables['users_groups'].'.'.$this->join['groups'].' as id, '.$this->tables['groups'].'.name, '.$this->tables['groups'].'.description, '.$this->tables['groups'].'.bgcolor')
  1407.                         ->where($this->tables['users_groups'].'.'.$this->join['users'], $id)
  1408.                         ->join($this->tables['groups'], $this->tables['users_groups'].'.'.$this->join['groups'].'='.$this->tables['groups'].'.id')
  1409.                         ->get($this->tables['users_groups']);
  1410.     }
  1411.  
  1412.     /**
  1413.      * add_to_group
  1414.      *
  1415.      * @return bool
  1416.      * @author Ben Edmunds
  1417.      **/
  1418.     public function add_to_group($group_ids, $user_id=false)
  1419.     {
  1420.         $this->trigger_events('add_to_group');
  1421.  
  1422.         // if no id was passed use the current users id
  1423.         $user_id || $user_id = $this->session->userdata('user_id');
  1424.  
  1425.         if(!is_array($group_ids))
  1426.         {
  1427.             $group_ids = array($group_ids);
  1428.         }
  1429.  
  1430.         $return = 0;
  1431.  
  1432.         // Then insert each into the database
  1433.         foreach ($group_ids as $group_id)
  1434.         {
  1435.             if ($this->db->insert($this->tables['users_groups'], array( $this->join['groups'] => (float)$group_id, $this->join['users'] => (float)$user_id)))
  1436.             {
  1437.                 if (isset($this->_cache_groups[$group_id])) {
  1438.                     $group_name = $this->_cache_groups[$group_id];
  1439.                 }
  1440.                 else {
  1441.                     $group = $this->group($group_id)->result();
  1442.                     $group_name = $group[0]->name;
  1443.                     $this->_cache_groups[$group_id] = $group_name;
  1444.                 }
  1445.                 $this->_cache_user_in_group[$user_id][$group_id] = $group_name;
  1446.  
  1447.                 // Return the number of groups added
  1448.                 $return += 1;
  1449.             }
  1450.         }
  1451.  
  1452.         return $return;
  1453.     }
  1454.  
  1455.     /**
  1456.      * remove_from_group
  1457.      *
  1458.      * @return bool
  1459.      * @author Ben Edmunds
  1460.      **/
  1461.     public function remove_from_group($group_ids=false, $user_id=false)
  1462.     {
  1463.         $this->trigger_events('remove_from_group');
  1464.  
  1465.         // user id is required
  1466.         if(empty($user_id))
  1467.         {
  1468.             return FALSE;
  1469.         }
  1470.  
  1471.         // if group id(s) are passed remove user from the group(s)
  1472.         if( ! empty($group_ids))
  1473.         {
  1474.             if(!is_array($group_ids))
  1475.             {
  1476.                 $group_ids = array($group_ids);
  1477.             }
  1478.  
  1479.             foreach($group_ids as $group_id)
  1480.             {
  1481.                 $this->db->delete($this->tables['users_groups'], array($this->join['groups'] => (float)$group_id, $this->join['users'] => (float)$user_id));
  1482.                 if (isset($this->_cache_user_in_group[$user_id]) && isset($this->_cache_user_in_group[$user_id][$group_id]))
  1483.                 {
  1484.                     unset($this->_cache_user_in_group[$user_id][$group_id]);
  1485.                 }
  1486.             }
  1487.  
  1488.             $return = TRUE;
  1489.         }
  1490.         // otherwise remove user from all groups
  1491.         else
  1492.         {
  1493.             if ($return = $this->db->delete($this->tables['users_groups'], array($this->join['users'] => (float)$user_id))) {
  1494.                 $this->_cache_user_in_group[$user_id] = array();
  1495.             }
  1496.         }
  1497.         return $return;
  1498.     }
  1499.  
  1500.     /**
  1501.      * groups
  1502.      *
  1503.      * @return object
  1504.      * @author Ben Edmunds
  1505.      **/
  1506.     public function groups()
  1507.     {
  1508.         $this->trigger_events('groups');
  1509.  
  1510.         // run each where that was passed
  1511.         if (isset($this->_ion_where) && !empty($this->_ion_where))
  1512.         {
  1513.             foreach ($this->_ion_where as $where)
  1514.             {
  1515.                 $this->db->where($where);
  1516.             }
  1517.             $this->_ion_where = array();
  1518.         }
  1519.  
  1520.         if (isset($this->_ion_limit) && isset($this->_ion_offset))
  1521.         {
  1522.             $this->db->limit($this->_ion_limit, $this->_ion_offset);
  1523.  
  1524.             $this->_ion_limit  = NULL;
  1525.             $this->_ion_offset = NULL;
  1526.         }
  1527.         else if (isset($this->_ion_limit))
  1528.         {
  1529.             $this->db->limit($this->_ion_limit);
  1530.  
  1531.             $this->_ion_limit  = NULL;
  1532.         }
  1533.  
  1534.         // set the order
  1535.         if (isset($this->_ion_order_by) && isset($this->_ion_order))
  1536.         {
  1537.             $this->db->order_by($this->_ion_order_by, $this->_ion_order);
  1538.         }
  1539.  
  1540.         $this->response = $this->db->get($this->tables['groups']);
  1541.  
  1542.         return $this;
  1543.     }
  1544.  
  1545.     /**
  1546.      * group
  1547.      *
  1548.      * @return object
  1549.      * @author Ben Edmunds
  1550.      **/
  1551.     public function group($id = NULL)
  1552.     {
  1553.         $this->trigger_events('group');
  1554.  
  1555.         if (isset($id))
  1556.         {
  1557.             $this->where($this->tables['groups'].'.id', $id);
  1558.         }
  1559.  
  1560.         $this->limit(1);
  1561.         $this->order_by('id', 'desc');
  1562.  
  1563.         return $this->groups();
  1564.     }
  1565.  
  1566.     /**
  1567.      * update
  1568.      *
  1569.      * @return bool
  1570.      * @author Phil Sturgeon
  1571.      **/
  1572.     public function update($id, array $data)
  1573.     {
  1574.         $this->trigger_events('pre_update_user');
  1575.  
  1576.         $user = $this->user($id)->row();
  1577.  
  1578.         $this->db->trans_begin();
  1579.  
  1580.         if (array_key_exists($this->identity_column, $data) && $this->identity_check($data[$this->identity_column]) && $user->{$this->identity_column} !== $data[$this->identity_column])
  1581.         {
  1582.             $this->db->trans_rollback();
  1583.             $this->set_error('account_creation_duplicate_identity');
  1584.  
  1585.             $this->trigger_events(array('post_update_user', 'post_update_user_unsuccessful'));
  1586.             $this->set_error('update_unsuccessful');
  1587.  
  1588.             return FALSE;
  1589.         }
  1590.  
  1591.         // Filter the data passed
  1592.         $data = $this->_filter_data($this->tables['users'], $data);
  1593.  
  1594.         if (array_key_exists($this->identity_column, $data) || array_key_exists('password', $data) || array_key_exists('email', $data))
  1595.         {
  1596.             if (array_key_exists('password', $data))
  1597.             {
  1598.                 if( ! empty($data['password']))
  1599.                 {
  1600.                     $data['password'] = $this->hash_password($data['password'], $user->salt);
  1601.                 }
  1602.                 else
  1603.                 {
  1604.                     // unset password so it doesn't effect database entry if no password passed
  1605.                     unset($data['password']);
  1606.                 }
  1607.             }
  1608.         }
  1609.  
  1610.         $this->trigger_events('extra_where');
  1611.         $this->db->update($this->tables['users'], $data, array('id' => $user->id));
  1612.  
  1613.         if ($this->db->trans_status() === FALSE)
  1614.         {
  1615.             $this->db->trans_rollback();
  1616.  
  1617.             $this->trigger_events(array('post_update_user', 'post_update_user_unsuccessful'));
  1618.             $this->set_error('update_unsuccessful');
  1619.             return FALSE;
  1620.         }
  1621.  
  1622.         $this->db->trans_commit();
  1623.  
  1624.         $this->trigger_events(array('post_update_user', 'post_update_user_successful'));
  1625.         $this->set_message('update_successful');
  1626.         return TRUE;
  1627.     }
  1628.  
  1629.     /**
  1630.     * delete_user
  1631.     *
  1632.     * @return bool
  1633.     * @author Phil Sturgeon
  1634.     **/
  1635.     public function delete_user($id)
  1636.     {
  1637.         $this->trigger_events('pre_delete_user');
  1638.  
  1639.         $this->db->trans_begin();
  1640.  
  1641.         // remove user from groups
  1642.         $this->remove_from_group(NULL, $id);
  1643.  
  1644.         // delete user from users table should be placed after remove from group
  1645.         $this->db->delete($this->tables['users'], array('id' => $id));
  1646.  
  1647.         // if user does not exist in database then it returns FALSE else removes the user from groups
  1648.         if ($this->db->affected_rows() == 0)
  1649.         {
  1650.             return FALSE;
  1651.         }
  1652.  
  1653.         if ($this->db->trans_status() === FALSE)
  1654.         {
  1655.             $this->db->trans_rollback();
  1656.             $this->trigger_events(array('post_delete_user', 'post_delete_user_unsuccessful'));
  1657.             $this->set_error('delete_unsuccessful');
  1658.             return FALSE;
  1659.         }
  1660.  
  1661.         $this->db->trans_commit();
  1662.  
  1663.         $this->trigger_events(array('post_delete_user', 'post_delete_user_successful'));
  1664.         $this->set_message('delete_successful');
  1665.         return TRUE;
  1666.     }
  1667.  
  1668.     /**
  1669.      * update_last_login
  1670.      *
  1671.      * @return bool
  1672.      * @author Ben Edmunds
  1673.      **/
  1674.     public function update_last_login($id)
  1675.     {
  1676.         $this->trigger_events('update_last_login');
  1677.  
  1678.         $this->load->helper('date');
  1679.  
  1680.         $this->trigger_events('extra_where');
  1681.  
  1682.         $this->db->update($this->tables['users'], array('last_login' => time()), array('id' => $id));
  1683.  
  1684.         return $this->db->affected_rows() == 1;
  1685.     }
  1686.  
  1687.     /**
  1688.      * set_lang
  1689.      *
  1690.      * @return bool
  1691.      * @author Ben Edmunds
  1692.      **/
  1693.     public function set_lang($lang = 'en')
  1694.     {
  1695.         $this->trigger_events('set_lang');
  1696.  
  1697.         // if the user_expire is set to zero we'll set the expiration two years from now.
  1698.         if($this->config->item('user_expire', 'ion_auth') === 0)
  1699.         {
  1700.             $expire = (60*60*24*365*2);
  1701.         }
  1702.         // otherwise use what is set
  1703.         else
  1704.         {
  1705.             $expire = $this->config->item('user_expire', 'ion_auth');
  1706.         }
  1707.  
  1708.         set_cookie(array(
  1709.             'name'   => 'lang_code',
  1710.             'value'  => $lang,
  1711.             'expire' => $expire
  1712.         ));
  1713.  
  1714.         return TRUE;
  1715.     }
  1716.  
  1717.     /**
  1718.      * set_session
  1719.      *
  1720.      * @return bool
  1721.      * @author jrmadsen67
  1722.      **/
  1723.     public function set_session($user)
  1724.     {
  1725.  
  1726.         $this->trigger_events('pre_set_session');
  1727.  
  1728.         $session_data = array(
  1729.             'identity'             => $user->{$this->identity_column},
  1730.             $this->identity_column             => $user->{$this->identity_column},
  1731.             'email'                => $user->email,
  1732.             'user_id'              => $user->id, //everyone likes to overwrite id so we'll use user_id
  1733.             'old_last_login'       => $user->last_login
  1734.         );
  1735.  
  1736.         $this->session->set_userdata($session_data);
  1737.  
  1738.         $this->trigger_events('post_set_session');
  1739.  
  1740.         return TRUE;
  1741.     }
  1742.  
  1743.     /**
  1744.      * remember_user
  1745.      *
  1746.      * @return bool
  1747.      * @author Ben Edmunds
  1748.      **/
  1749.     public function remember_user($id)
  1750.     {
  1751.         $this->trigger_events('pre_remember_user');
  1752.  
  1753.         if (!$id)
  1754.         {
  1755.             return FALSE;
  1756.         }
  1757.  
  1758.         $user = $this->user($id)->row();
  1759.  
  1760.         $salt = $this->salt();
  1761.  
  1762.         $this->db->update($this->tables['users'], array('remember_code' => $salt), array('id' => $id));
  1763.  
  1764.         if ($this->db->affected_rows() > -1)
  1765.         {
  1766.             // if the user_expire is set to zero we'll set the expiration two years from now.
  1767.             if($this->config->item('user_expire', 'ion_auth') === 0)
  1768.             {
  1769.                 $expire = (60*60*24*365*2);
  1770.             }
  1771.             // otherwise use what is set
  1772.             else
  1773.             {
  1774.                 $expire = $this->config->item('user_expire', 'ion_auth');
  1775.             }
  1776.  
  1777.             set_cookie(array(
  1778.                 'name'   => $this->config->item('identity_cookie_name', 'ion_auth'),
  1779.                 'value'  => $user->{$this->identity_column},
  1780.                 'expire' => $expire
  1781.             ));
  1782.  
  1783.             set_cookie(array(
  1784.                 'name'   => $this->config->item('remember_cookie_name', 'ion_auth'),
  1785.                 'value'  => $salt,
  1786.                 'expire' => $expire
  1787.             ));
  1788.  
  1789.             $this->trigger_events(array('post_remember_user', 'remember_user_successful'));
  1790.             return TRUE;
  1791.         }
  1792.  
  1793.         $this->trigger_events(array('post_remember_user', 'remember_user_unsuccessful'));
  1794.         return FALSE;
  1795.     }
  1796.  
  1797.     /**
  1798.      * login_remembed_user
  1799.      *
  1800.      * @return bool
  1801.      * @author Ben Edmunds
  1802.      **/
  1803.     public function login_remembered_user()
  1804.     {
  1805.         $this->trigger_events('pre_login_remembered_user');
  1806.  
  1807.         // check for valid data
  1808.         if (!get_cookie($this->config->item('identity_cookie_name', 'ion_auth'))
  1809.             || !get_cookie($this->config->item('remember_cookie_name', 'ion_auth'))
  1810.             || !$this->identity_check(get_cookie($this->config->item('identity_cookie_name', 'ion_auth'))))
  1811.         {
  1812.             $this->trigger_events(array('post_login_remembered_user', 'post_login_remembered_user_unsuccessful'));
  1813.             return FALSE;
  1814.         }
  1815.  
  1816.         // get the user
  1817.         $this->trigger_events('extra_where');
  1818.         $query = $this->db->select($this->identity_column.', id, email, last_login')
  1819.                           ->where($this->identity_column, get_cookie($this->config->item('identity_cookie_name', 'ion_auth')))
  1820.                           ->where('remember_code', get_cookie($this->config->item('remember_cookie_name', 'ion_auth')))
  1821.                           ->limit(1)
  1822.                           ->order_by('id', 'desc')
  1823.                           ->get($this->tables['users']);
  1824.  
  1825.         // if the user was found, sign them in
  1826.         if ($query->num_rows() == 1)
  1827.         {
  1828.             $user = $query->row();
  1829.  
  1830.             $this->update_last_login($user->id);
  1831.  
  1832.             $this->set_session($user);
  1833.  
  1834.             // extend the users cookies if the option is enabled
  1835.             if ($this->config->item('user_extend_on_login', 'ion_auth'))
  1836.             {
  1837.                 $this->remember_user($user->id);
  1838.             }
  1839.  
  1840.             $this->trigger_events(array('post_login_remembered_user', 'post_login_remembered_user_successful'));
  1841.             return TRUE;
  1842.         }
  1843.  
  1844.         $this->trigger_events(array('post_login_remembered_user', 'post_login_remembered_user_unsuccessful'));
  1845.         return FALSE;
  1846.     }
  1847.  
  1848.  
  1849.     /**
  1850.      * create_group
  1851.      *
  1852.      * @author aditya menon
  1853.     */
  1854.     public function create_group($group_name = FALSE, $group_description = '', $additional_data = array())
  1855.     {
  1856.         // bail if the group name was not passed
  1857.         if(!$group_name)
  1858.         {
  1859.             $this->set_error('group_name_required');
  1860.             return FALSE;
  1861.         }
  1862.  
  1863.         // bail if the group name already exists
  1864.         $existing_group = $this->db->get_where($this->tables['groups'], array('name' => $group_name))->num_rows();
  1865.         if($existing_group !== 0)
  1866.         {
  1867.             $this->set_error('group_already_exists');
  1868.             return FALSE;
  1869.         }
  1870.  
  1871.         $data = array('name'=>$group_name,'description'=>$group_description);
  1872.  
  1873.         // filter out any data passed that doesnt have a matching column in the groups table
  1874.         // and merge the set group data and the additional data
  1875.         if (!empty($additional_data)) $data = array_merge($this->_filter_data($this->tables['groups'], $additional_data), $data);
  1876.  
  1877.         $this->trigger_events('extra_group_set');
  1878.  
  1879.         // insert the new group
  1880.         $this->db->insert($this->tables['groups'], $data);
  1881.         $group_id = $this->db->insert_id();
  1882.  
  1883.         // report success
  1884.         $this->set_message('group_creation_successful');
  1885.         // return the brand new group id
  1886.         return $group_id;
  1887.     }
  1888.  
  1889.     /**
  1890.      * update_group
  1891.      *
  1892.      * @return bool
  1893.      * @author aditya menon
  1894.      **/
  1895.     public function update_group($group_id = FALSE, $group_name = FALSE, $additional_data = array())
  1896.     {
  1897.         if (empty($group_id)) return FALSE;
  1898.  
  1899.         $data = array();
  1900.  
  1901.         if (!empty($group_name))
  1902.         {
  1903.             // we are changing the name, so do some checks
  1904.  
  1905.             // bail if the group name already exists
  1906.             $existing_group = $this->db->get_where($this->tables['groups'], array('name' => $group_name))->row();
  1907.             if(isset($existing_group->id) && $existing_group->id != $group_id)
  1908.             {
  1909.                 $this->set_error('group_already_exists');
  1910.                 return FALSE;
  1911.             }
  1912.  
  1913.             $data['name'] = $group_name;
  1914.         }
  1915.  
  1916.         // restrict change of name of the admin group
  1917.         $group = $this->db->get_where($this->tables['groups'], array('id' => $group_id))->row();
  1918.         if($this->config->item('admin_group', 'ion_auth') === $group->name && $group_name !== $group->name)
  1919.         {
  1920.             $this->set_error('group_name_admin_not_alter');
  1921.             return FALSE;
  1922.         }
  1923.  
  1924.  
  1925.         // IMPORTANT!! Third parameter was string type $description; this following code is to maintain backward compatibility
  1926.         // New projects should work with 3rd param as array
  1927.         if (is_string($additional_data)) $additional_data = array('description' => $additional_data);
  1928.  
  1929.  
  1930.         // filter out any data passed that doesnt have a matching column in the groups table
  1931.         // and merge the set group data and the additional data
  1932.         if (!empty($additional_data)) $data = array_merge($this->_filter_data($this->tables['groups'], $additional_data), $data);
  1933.  
  1934.  
  1935.         $this->db->update($this->tables['groups'], $data, array('id' => $group_id));
  1936.  
  1937.         $this->set_message('group_update_successful');
  1938.  
  1939.         return TRUE;
  1940.     }
  1941.  
  1942.     /**
  1943.     * delete_group
  1944.     *
  1945.     * @return bool
  1946.     * @author aditya menon
  1947.     **/
  1948.     public function delete_group($group_id = FALSE)
  1949.     {
  1950.         // bail if mandatory param not set
  1951.         if(!$group_id || empty($group_id))
  1952.         {
  1953.             return FALSE;
  1954.         }
  1955.         $group = $this->group($group_id)->row();
  1956.         if($group->name == $this->config->item('admin_group', 'ion_auth'))
  1957.         {
  1958.             $this->trigger_events(array('post_delete_group', 'post_delete_group_notallowed'));
  1959.             $this->set_error('group_delete_notallowed');
  1960.             return FALSE;
  1961.         }
  1962.  
  1963.         $this->trigger_events('pre_delete_group');
  1964.  
  1965.         $this->db->trans_begin();
  1966.  
  1967.         // remove all users from this group
  1968.         $this->db->delete($this->tables['users_groups'], array($this->join['groups'] => $group_id));
  1969.         // remove the group itself
  1970.         $this->db->delete($this->tables['groups'], array('id' => $group_id));
  1971.  
  1972.         if ($this->db->trans_status() === FALSE)
  1973.         {
  1974.             $this->db->trans_rollback();
  1975.             $this->trigger_events(array('post_delete_group', 'post_delete_group_unsuccessful'));
  1976.             $this->set_error('group_delete_unsuccessful');
  1977.             return FALSE;
  1978.         }
  1979.  
  1980.         $this->db->trans_commit();
  1981.  
  1982.         $this->trigger_events(array('post_delete_group', 'post_delete_group_successful'));
  1983.         $this->set_message('group_delete_successful');
  1984.         return TRUE;
  1985.     }
  1986.  
  1987.     public function set_hook($event, $name, $class, $method, $arguments)
  1988.     {
  1989.         $this->_ion_hooks->{$event}[$name] = new stdClass;
  1990.         $this->_ion_hooks->{$event}[$name]->class     = $class;
  1991.         $this->_ion_hooks->{$event}[$name]->method    = $method;
  1992.         $this->_ion_hooks->{$event}[$name]->arguments = $arguments;
  1993.     }
  1994.  
  1995.     public function remove_hook($event, $name)
  1996.     {
  1997.         if (isset($this->_ion_hooks->{$event}[$name]))
  1998.         {
  1999.             unset($this->_ion_hooks->{$event}[$name]);
  2000.         }
  2001.     }
  2002.  
  2003.     public function remove_hooks($event)
  2004.     {
  2005.         if (isset($this->_ion_hooks->$event))
  2006.         {
  2007.             unset($this->_ion_hooks->$event);
  2008.         }
  2009.     }
  2010.  
  2011.     protected function _call_hook($event, $name)
  2012.     {
  2013.         if (isset($this->_ion_hooks->{$event}[$name]) && method_exists($this->_ion_hooks->{$event}[$name]->class, $this->_ion_hooks->{$event}[$name]->method))
  2014.         {
  2015.             $hook = $this->_ion_hooks->{$event}[$name];
  2016.  
  2017.             return call_user_func_array(array($hook->class, $hook->method), $hook->arguments);
  2018.         }
  2019.  
  2020.         return FALSE;
  2021.     }
  2022.  
  2023.     public function trigger_events($events)
  2024.     {
  2025.         if (is_array($events) && !empty($events))
  2026.         {
  2027.             foreach ($events as $event)
  2028.             {
  2029.                 $this->trigger_events($event);
  2030.             }
  2031.         }
  2032.         else
  2033.         {
  2034.             if (isset($this->_ion_hooks->$events) && !empty($this->_ion_hooks->$events))
  2035.             {
  2036.                 foreach ($this->_ion_hooks->$events as $name => $hook)
  2037.                 {
  2038.                     $this->_call_hook($events, $name);
  2039.                 }
  2040.             }
  2041.         }
  2042.     }
  2043.  
  2044.     /**
  2045.      * set_message_delimiters
  2046.      *
  2047.      * Set the message delimiters
  2048.      *
  2049.      * @return void
  2050.      * @author Ben Edmunds
  2051.      **/
  2052.     public function set_message_delimiters($start_delimiter, $end_delimiter)
  2053.     {
  2054.         $this->message_start_delimiter = $start_delimiter;
  2055.         $this->message_end_delimiter   = $end_delimiter;
  2056.  
  2057.         return TRUE;
  2058.     }
  2059.  
  2060.     /**
  2061.      * set_error_delimiters
  2062.      *
  2063.      * Set the error delimiters
  2064.      *
  2065.      * @return void
  2066.      * @author Ben Edmunds
  2067.      **/
  2068.     public function set_error_delimiters($start_delimiter, $end_delimiter)
  2069.     {
  2070.         $this->error_start_delimiter = $start_delimiter;
  2071.         $this->error_end_delimiter   = $end_delimiter;
  2072.  
  2073.         return TRUE;
  2074.     }
  2075.  
  2076.     /**
  2077.      * set_message
  2078.      *
  2079.      * Set a message
  2080.      *
  2081.      * @return void
  2082.      * @author Ben Edmunds
  2083.      **/
  2084.     public function set_message($message)
  2085.     {
  2086.         $this->messages[] = $message;
  2087.  
  2088.         return $message;
  2089.     }
  2090.  
  2091.  
  2092.  
  2093.     /**
  2094.      * messages
  2095.      *
  2096.      * Get the messages
  2097.      *
  2098.      * @return void
  2099.      * @author Ben Edmunds
  2100.      **/
  2101.     public function messages()
  2102.     {
  2103.         $_output = '';
  2104.         foreach ($this->messages as $message)
  2105.         {
  2106.             $messageLang = $this->lang->line($message) ? $this->lang->line($message) : '##' . $message . '##';
  2107.             $_output .= $this->message_start_delimiter . $messageLang . $this->message_end_delimiter;
  2108.         }
  2109.  
  2110.         return $_output;
  2111.     }
  2112.  
  2113.     /**
  2114.      * messages as array
  2115.      *
  2116.      * Get the messages as an array
  2117.      *
  2118.      * @return array
  2119.      * @author Raul Baldner Junior
  2120.      **/
  2121.     public function messages_array($langify = TRUE)
  2122.     {
  2123.         if ($langify)
  2124.         {
  2125.             $_output = array();
  2126.             foreach ($this->messages as $message)
  2127.             {
  2128.                 $messageLang = $this->lang->line($message) ? $this->lang->line($message) : '##' . $message . '##';
  2129.                 $_output[] = $this->message_start_delimiter . $messageLang . $this->message_end_delimiter;
  2130.             }
  2131.             return $_output;
  2132.         }
  2133.         else
  2134.         {
  2135.             return $this->messages;
  2136.         }
  2137.     }
  2138.  
  2139.  
  2140.     /**
  2141.      * clear_messages
  2142.      *
  2143.      * Clear messages
  2144.      *
  2145.      * @return void
  2146.      * @author Ben Edmunds
  2147.      **/
  2148.     public function clear_messages()
  2149.     {
  2150.         $this->messages = array();
  2151.  
  2152.         return TRUE;
  2153.     }
  2154.  
  2155.  
  2156.     /**
  2157.      * set_error
  2158.      *
  2159.      * Set an error message
  2160.      *
  2161.      * @return void
  2162.      * @author Ben Edmunds
  2163.      **/
  2164.     public function set_error($error)
  2165.     {
  2166.         $this->errors[] = $error;
  2167.  
  2168.         return $error;
  2169.     }
  2170.  
  2171.     /**
  2172.      * errors
  2173.      *
  2174.      * Get the error message
  2175.      *
  2176.      * @return void
  2177.      * @author Ben Edmunds
  2178.      **/
  2179.     public function errors()
  2180.     {
  2181.         $_output = '';
  2182.         foreach ($this->errors as $error)
  2183.         {
  2184.             $errorLang = $this->lang->line($error) ? $this->lang->line($error) : '##' . $error . '##';
  2185.             $_output .= $this->error_start_delimiter . $errorLang . $this->error_end_delimiter;
  2186.         }
  2187.  
  2188.         return $_output;
  2189.     }
  2190.  
  2191.     /**
  2192.      * errors as array
  2193.      *
  2194.      * Get the error messages as an array
  2195.      *
  2196.      * @return array
  2197.      * @author Raul Baldner Junior
  2198.      **/
  2199.     public function errors_array($langify = TRUE)
  2200.     {
  2201.         if ($langify)
  2202.         {
  2203.             $_output = array();
  2204.             foreach ($this->errors as $error)
  2205.             {
  2206.                 $errorLang = $this->lang->line($error) ? $this->lang->line($error) : '##' . $error . '##';
  2207.                 $_output[] = $this->error_start_delimiter . $errorLang . $this->error_end_delimiter;
  2208.             }
  2209.             return $_output;
  2210.         }
  2211.         else
  2212.         {
  2213.             return $this->errors;
  2214.         }
  2215.     }
  2216.  
  2217.  
  2218.     /**
  2219.      * clear_errors
  2220.      *
  2221.      * Clear Errors
  2222.      *
  2223.      * @return void
  2224.      * @author Ben Edmunds
  2225.      **/
  2226.     public function clear_errors()
  2227.     {
  2228.         $this->errors = array();
  2229.  
  2230.         return TRUE;
  2231.     }
  2232.  
  2233.  
  2234.  
  2235.     protected function _filter_data($table, $data)
  2236.     {
  2237.         $filtered_data = array();
  2238.         $columns = $this->db->list_fields($table);
  2239.  
  2240.         if (is_array($data))
  2241.         {
  2242.             foreach ($columns as $column)
  2243.             {
  2244.                 if (array_key_exists($column, $data))
  2245.                     $filtered_data[$column] = $data[$column];
  2246.             }
  2247.         }
  2248.  
  2249.         return $filtered_data;
  2250.     }
  2251.  
  2252.     protected function _prepare_ip($ip_address) {
  2253.         // just return the string IP address now for better compatibility
  2254.         return $ip_address;
  2255.     }
  2256. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement