Advertisement
Guest User

MY_Session

a guest
Apr 24th, 2012
159
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 28.18 KB | None | 0 0
  1. <?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
  2. /**
  3.  * ExiteCMS Core Session Class
  4.  *
  5.  * This library replaces the CodeIgniter Session class. While providing the
  6.  * same functionality, it provides several improvements over the original:
  7.  * - fixed session id rotation race condition with parallel requests
  8.  * - only writes a session when explicitly asked to
  9.  * - fixed flashdata bug that destroyed custom flashdata keys
  10.  * - replaced 'last_update' by 'last_rotate' and 'last_write' for more accuracy
  11.  *
  12.  * @package     ExiteCMS
  13.  * @subpackage  Libraries
  14.  * @category    Libraries
  15.  * @author      ExiteCMS Dev Team
  16.  * @link        http://www.exitecms.org
  17.  */
  18.  
  19. // ------------------------------------------------------------------------
  20.  
  21. /**
  22.  * This session library requires a database table with this layout:
  23.  *
  24. * CREATE TABLE IF NOT EXISTS  `ci_sessions` (session_id VARCHAR(40) DEFAULT '0' NOT NULL, previous_id VARCHAR(40) DEFAULT '0' NOT NULL, ip_address VARCHAR(16) DEFAULT '0' NOT NULL, user_agent VARCHAR(50) NOT NULL, last_rotate INT(10) unsigned DEFAULT 0 NOT NULL, last_write INT(10) unsigned DEFAULT 0 NOT NULL, user_data TEXT DEFAULT NULL NULL, PRIMARY KEY (session_id,previous_id));
  25.  */
  26.  
  27. // ------------------------------------------------------------------------
  28.  
  29. /**
  30.  * Session Class
  31.  *
  32.  * @package     CodeIgniter
  33.  * @subpackage  Libraries
  34.  * @category    Sessions
  35.  * @author      ExpressionEngine Dev Team
  36.  * @link        http://codeigniter.com/user_guide/libraries/sessions.html
  37.  */
  38. class MY_Session extends CI_Session {
  39.  
  40.     var $sess_encrypt_cookie        = FALSE;
  41.     var $sess_use_database          = FALSE;
  42.     var $sess_table_name            = '';
  43.     var $sess_expiration            = 7200;
  44.     var $sess_expire_on_close       = FALSE;
  45.     var $sess_match_ip              = FALSE;
  46.     var $sess_match_useragent       = FALSE;
  47.     var $sess_cookie_name           = 'cisession';
  48.     var $cookie_prefix              = '';
  49.     var $cookie_path                = '';
  50.     var $cookie_domain              = '';
  51.     var $cookie_secure              = FALSE;
  52.     var $sess_time_to_update        = 300;
  53.     var $encryption_key             = '';
  54.     var $flashdata_key              = 'flash';
  55.     var $time_reference             = 'time';
  56.     var $gc_probability             = 5;
  57.     var $userdata                   = array();
  58.     var $CI;
  59.     var $now;
  60.  
  61.  
  62.  
  63.  
  64.     /**
  65.      * Session Constructor
  66.      *
  67.      * The constructor runs the session routines automatically
  68.      * whenever the class is instantiated.
  69.      */
  70.     function CI_Session($params = array('encryption_key' => 'x'))
  71.     {
  72.         log_message('debug', "Session Class Initialized");
  73.  
  74.         // Set the super object to a local variable for use throughout the class
  75.         $this->CI =& get_instance();
  76.  
  77.         // Set all the session preferences, which can either be set
  78.         // manually via the $params array above or via the config file
  79.         foreach (array('sess_encrypt_cookie', 'sess_use_database', 'sess_table_name', 'sess_expiration', 'sess_expire_on_close', 'sess_match_ip', 'sess_match_useragent', 'sess_cookie_name', 'cookie_path', 'cookie_domain', 'sess_time_to_update', 'time_reference', 'cookie_prefix', 'encryption_key') as $key)
  80.         {
  81.             $this->$key = (isset($params[$key])) ? $params[$key] : $this->CI->config->item($key);
  82.         }
  83.  
  84.         if ($this->encryption_key == '')
  85.         {
  86.             show_error('In order to use the Session class you are required to set an encryption key in your config file.');
  87.         }
  88.  
  89.         // Load the string helper so we can use the strip_slashes() function
  90.         $this->CI->load->helper('string');
  91.  
  92.         // Do we need encryption? If so, load the encryption class
  93.         if ($this->sess_encrypt_cookie == TRUE)
  94.         {
  95.             $this->CI->load->library('encrypt');
  96.         }
  97.  
  98.         // Are we using a database?  If so, load it
  99.         if ($this->sess_use_database === TRUE AND $this->sess_table_name != '')
  100.         {
  101.             $this->CI->load->database();
  102.         }
  103.  
  104.         // Set the "now" time.  Can either be GMT or server time, based on the
  105.         // config prefs.  We use this to set the "last activity" time
  106.         $this->now = $this->_get_time();
  107.  
  108.         // Set the session length. If the session expiration is
  109.         // set to zero we'll set the expiration two years from now.
  110.         if ($this->sess_expiration == 0)
  111.         {
  112.             $this->sess_expiration = (60*60*24*365*2);
  113.         }
  114.  
  115.         // Set the cookie name
  116.         $this->sess_cookie_name = $this->cookie_prefix.$this->sess_cookie_name;
  117.  
  118.         // Run the Session routine. If a session doesn't exist we'll
  119.         // create a new one.  If it does, we'll update it.
  120.         if ( ! $this->sess_read())
  121.         {
  122.             $this->sess_create();
  123.         }
  124.         else
  125.         {
  126.             $this->sess_update();
  127.         }
  128.  
  129.         // Delete 'old' flashdata (from last request)
  130.         $this->_flashdata_sweep();
  131.  
  132.         // Mark all new flashdata as old (data will be deleted before next request)
  133.         $this->_flashdata_mark();
  134.  
  135.         // Delete expired sessions if necessary
  136.         $this->_sess_gc();
  137.  
  138.         log_message('debug', "Session routines successfully run");
  139.     }
  140.  
  141.     // --------------------------------------------------------------------
  142.  
  143.     /**
  144.      * Fetch the current session data if it exists
  145.      *
  146.      * @access  public
  147.      * @return  bool
  148.      */
  149.     function sess_read()
  150.     {
  151.         // Fetch the cookie
  152.         $session = $this->CI->input->cookie($this->sess_cookie_name);
  153.  
  154.         // No cookie?  Goodbye cruel world!...
  155.         if ($session === FALSE)
  156.         {
  157.             log_message('debug', 'A session cookie was not found.');
  158.             return FALSE;
  159.         }
  160.  
  161.         // Decrypt the cookie data
  162.         if ($this->sess_encrypt_cookie == TRUE)
  163.         {
  164.             $session = $this->CI->encrypt->decode($session, $this->encryption_key);
  165.         }
  166.         else
  167.         {
  168.             // encryption was not used, so we need to check the md5 hash
  169.             $hash    = substr($session, strlen($session)-32); // get last 32 chars
  170.             $session = substr($session, 0, strlen($session)-32);
  171.  
  172.             // Does the md5 hash match?  This is to prevent manipulation of session data in userspace
  173.             if ($hash !==  md5($session.$this->encryption_key))
  174.             {
  175.                 log_message('error', 'The session cookie data did not match what was expected. This could be a possible hacking attempt.');
  176.                 $this->sess_destroy();
  177.                 return FALSE;
  178.             }
  179.         }
  180.  
  181.         // Unserialize the session array
  182.         $session = $this->_unserialize($session);
  183.  
  184.         // Is the session data we unserialized an array with the correct format?
  185.         if ( ! is_array($session) OR ! isset($session['session_id']) OR ! isset($session['previous_id']) OR ! isset($session['ip_address']) OR ! isset($session['user_agent']) OR ! isset($session['last_rotate']) OR ! isset($session['last_write']))
  186.         {
  187.             $this->sess_destroy();
  188.             return FALSE;
  189.         }
  190.  
  191.         // Is the session current?
  192.         if (($session['last_rotate'] + $this->sess_expiration) < $this->now)
  193.         {
  194.             $this->sess_destroy();
  195.             return FALSE;
  196.         }
  197.  
  198.         // Does the IP Match?
  199.         if ($this->sess_match_ip == TRUE AND $session['ip_address'] != $this->CI->input->ip_address())
  200.         {
  201.             $this->sess_destroy();
  202.             return FALSE;
  203.         }
  204.  
  205.         // Does the User Agent Match?
  206.         if ($this->sess_match_useragent == TRUE AND trim($session['user_agent']) != trim(substr($this->CI->input->user_agent(), 0, 50)))
  207.         {
  208.             $this->sess_destroy();
  209.             return FALSE;
  210.         }
  211.  
  212.         // Is there a corresponding session in the DB?
  213.         if ($this->sess_use_database === TRUE)
  214.         {
  215.             $this->CI->db->where('( session_id = "'.$session['session_id'].'" OR previous_id = "'.$session['session_id'].'")', NULL, FALSE);
  216.  
  217.             if ($this->sess_match_ip == TRUE)
  218.             {
  219.                 $this->CI->db->where('ip_address', $session['ip_address']);
  220.             }
  221.  
  222.             if ($this->sess_match_useragent == TRUE)
  223.             {
  224.                 $this->CI->db->where('user_agent', $session['user_agent']);
  225.             }
  226.  
  227.             $query = $this->CI->db->get($this->sess_table_name);
  228.  
  229.             // No result?  Kill it!
  230.             if ($query->num_rows() == 0)
  231.             {
  232.                 $this->sess_destroy();
  233.                 return FALSE;
  234.             }
  235.  
  236.             // Is there custom data?  If so, add it to the main session array
  237.             $row = $query->row();
  238.             if ( isset($row->user_data) )
  239.             {
  240.                 if (  $row->user_data != '' )
  241.                 {
  242.                     $custom_data = $this->_unserialize($row->user_data);
  243.  
  244.                     if (is_array($custom_data))
  245.                     {
  246.                         foreach ($custom_data as $key => $val)
  247.                         {
  248.                             $session[$key] = $val;
  249.                         }
  250.                     }
  251.                 }
  252.                 $session['last_write'] = $row->last_write;
  253.             }
  254.         }
  255.  
  256.         // Session is valid!
  257.         $this->userdata = $session;
  258.         unset($session);
  259.  
  260.         return TRUE;
  261.     }
  262.  
  263.     // --------------------------------------------------------------------
  264.  
  265.     /**
  266.      * Write the session data
  267.      *
  268.      * @access  public
  269.      * @return  void
  270.      */
  271.     function sess_write($write = TRUE)
  272.     {
  273.         // Only write if specifically asked
  274.         if ( ! $write )
  275.         {
  276.             return;
  277.         }
  278.  
  279.         // Are we saving custom data to the DB?  If not, all we do is update the cookie
  280.         if ($this->sess_use_database === FALSE)
  281.         {
  282.             $this->_set_cookie();
  283.             return;
  284.         }
  285.  
  286.         // set the custom userdata, the session data we will set in a second
  287.         $custom_userdata = $this->userdata;
  288.         $cookie_userdata = array();
  289.  
  290.         // Before continuing, we need to determine if there is any custom data to deal with.
  291.         // Let's determine this by removing the default indexes to see if there's anything left in the array
  292.         // and set the session data while we're at it
  293.         foreach (array('session_id','previous_id','ip_address','user_agent','last_rotate', 'last_write') as $val)
  294.         {
  295.             unset($custom_userdata[$val]);
  296.             $cookie_userdata[$val] = $this->userdata[$val];
  297.         }
  298.  
  299.         // Did we find any custom data?  If not, we turn the empty array into a string
  300.         // since there's no reason to serialize and store an empty array in the DB
  301.         if (count($custom_userdata) === 0)
  302.         {
  303.             $custom_userdata = '';
  304.         }
  305.         else
  306.         {
  307.             // Serialize the custom data array so we can store it
  308.             $custom_userdata = $this->_serialize($custom_userdata);
  309.         }
  310.  
  311.         // Run the update query
  312.         $this->CI->db->where('session_id', $this->userdata['session_id']);
  313.         $this->CI->db->update($this->sess_table_name, array('last_rotate' => $this->userdata['last_rotate'], 'last_write' => $this->now, 'user_data' => $custom_userdata));
  314.  
  315.         // Write the cookie.  Notice that we manually pass the cookie data array to the
  316.         // _set_cookie() function. Normally that function will store $this->userdata, but
  317.         // in this case that array contains custom data, which we do not want in the cookie.
  318.         if ( $this->CI->db->affected_rows() )
  319.         {
  320.             $this->_set_cookie($cookie_userdata);
  321.         }
  322.     }
  323.  
  324.     // --------------------------------------------------------------------
  325.  
  326.     /**
  327.      * Create a new session
  328.      *
  329.      * @access  public
  330.      * @return  void
  331.      */
  332.     function sess_create()
  333.     {
  334.         $sessid = '';
  335.  
  336.         for($i = 0; $i < 32; $i++)
  337.         {
  338.             $sessid .= mt_rand(0, mt_getrandmax());
  339.         }
  340.  
  341.         // To make the session ID even more secure we'll combine it with the user's IP
  342.         $sessid .= $this->CI->input->ip_address();
  343.  
  344.         $this->userdata = array(
  345.                             'session_id'    => md5(uniqid($sessid, TRUE)),
  346.                             'previous_id'   => '',
  347.                             'ip_address'    => $this->CI->input->ip_address(),
  348.                             'user_agent'    => substr($this->CI->input->user_agent(), 0, 50),
  349.                             'last_rotate'   => $this->now,
  350.                             'last_write'    => $this->now
  351.                             );
  352.  
  353.         // Save the data to the DB if needed
  354.         if ($this->sess_use_database === TRUE)
  355.         {
  356.             $this->CI->db->query($this->CI->db->insert_string($this->sess_table_name, $this->userdata));
  357.         }
  358.  
  359.         // Write the cookie
  360.         $this->_set_cookie();
  361.     }
  362.  
  363.     // --------------------------------------------------------------------
  364.  
  365.     /**
  366.      * Update an existing session
  367.      *
  368.      * @access  public
  369.      * @return  void
  370.      */
  371.     function sess_update()
  372.     {
  373.  
  374.         // We only update the session every five minutes by default
  375.         if (($this->userdata['last_rotate'] + $this->sess_time_to_update) >= $this->now)
  376.         {
  377.             return;
  378.         }
  379.  
  380.         // Save the old session id so we know which record to
  381.         // update in the database if we need it
  382.         $old_sessid = $this->userdata['session_id'];
  383.         $new_sessid = '';
  384.         for($i = 0; $i < 32; $i++)
  385.         {
  386.             $new_sessid .= mt_rand(0, mt_getrandmax());
  387.         }
  388.  
  389.         // To make the session ID even more secure we'll combine it with the user's IP
  390.         $new_sessid .= $this->CI->input->ip_address();
  391.  
  392.         // Turn it into a hash
  393.         $new_sessid = md5(uniqid($new_sessid, TRUE));
  394.  
  395.         // Update the session data in the session data array
  396.         $this->userdata['previous_id'] = $old_sessid;
  397.         $this->userdata['session_id'] = $new_sessid;
  398.         $this->userdata['last_rotate'] = $this->now;
  399.  
  400.         // _set_cookie() will handle this for us if we aren't using database sessions
  401.         // by pushing all userdata to the cookie.
  402.         $cookie_data = NULL;
  403.  
  404.         // Update the session ID and last_activity field in the DB if needed
  405.         if ($this->sess_use_database === TRUE)
  406.         {
  407.             // set cookie explicitly to only have our session data
  408.             $cookie_data = array();
  409.             foreach (array('session_id','previous_id','ip_address','user_agent','last_rotate', 'last_write') as $val)
  410.             {
  411.                 $cookie_data[$val] = $this->userdata[$val];
  412.             }
  413.  
  414.             $this->CI->db->query($this->CI->db->update_string($this->sess_table_name, array('last_rotate' => $this->now, 'last_write' => $this->now, 'session_id' => $new_sessid, 'previous_id' => $old_sessid), array('session_id' => $old_sessid)));
  415.         }
  416.  
  417.         // Write the cookie
  418.         $this->_set_cookie($cookie_data);
  419.     }
  420.  
  421.     // --------------------------------------------------------------------
  422.  
  423.     /**
  424.      * Destroy the current session
  425.      *
  426.      * @access  public
  427.      * @return  void
  428.      */
  429.     function sess_destroy()
  430.     {
  431.         // Kill the session DB row
  432.         if ($this->sess_use_database === TRUE AND isset($this->userdata['session_id']))
  433.         {
  434.             $this->CI->db->where('( session_id = "'.$this->userdata['session_id'].'" OR previous_id = "'.$this->userdata['session_id'].'")', NULL, FALSE);
  435.             $this->CI->db->delete($this->sess_table_name);
  436.         }
  437.  
  438.         // erase the userdata loaded
  439.         $this->userdata = array();
  440.  
  441.         // Kill the cookie
  442.         setcookie(
  443.                     $this->sess_cookie_name,
  444.                     addslashes(serialize(array())),
  445.                     ($this->now - 31500000),
  446.                     $this->cookie_path,
  447.                     $this->cookie_domain,
  448.                     0
  449.                 );
  450.     }
  451.  
  452.     // --------------------------------------------------------------------
  453.  
  454.     /**
  455.      * Fetch a specific item from the session array
  456.      *
  457.      * Our version supports multi-arrays as session data
  458.      *
  459.      * @access  public
  460.      * @param   string
  461.      * @return  string
  462.      */
  463.     function userdata($item, $subitem = NULL)
  464.     {
  465.         if ( is_null($subitem) )
  466.         {
  467.             return ( ! isset($this->userdata[$item])) ? FALSE : $this->userdata[$item];
  468.         }
  469.         else
  470.         {
  471.             return ( ! isset($this->userdata[$item][$subitem])) ? FALSE : $this->userdata[$item][$subitem];
  472.         }
  473.     }
  474.  
  475.     // --------------------------------------------------------------------
  476.  
  477.     /**
  478.      * Fetch all session data
  479.      *
  480.      * @access  public
  481.      * @return  mixed
  482.      */
  483.     function all_userdata()
  484.     {
  485.         return ( ! isset($this->userdata)) ? FALSE : $this->userdata;
  486.     }
  487.  
  488.     // --------------------------------------------------------------------
  489.  
  490.     /**
  491.      * Add or change data in the "userdata" array
  492.      *
  493.      * @access  public
  494.      * @param   mixed
  495.      * @param   string
  496.      * @return  void
  497.      */
  498.     function set_userdata($newdata = array(), $newval = '')
  499.     {
  500.         if (is_string($newdata))
  501.         {
  502.             $newdata = array($newdata => $newval);
  503.         }
  504.  
  505.         if (count($newdata) > 0)
  506.         {
  507.             foreach ($newdata as $key => $val)
  508.             {
  509.                 $this->userdata[$key] = $val;
  510.             }
  511.         }
  512.  
  513.         if ( ! (isset($this->userdata['session_id'])))
  514.         {
  515.             log_message('error', "userdata: ".print_r($this->userdata, TRUE));
  516.             log_message('error', "newdata: ".print_r($newdata, TRUE));
  517.             log_message('error', "newval: ".$newval);
  518.         }
  519.         $this->sess_write();
  520.     }
  521.  
  522.     // --------------------------------------------------------------------
  523.  
  524.     /**
  525.      * Add or change data in the "userdata" array
  526.      *
  527.      * set_userdata method with support for multi-dimensional arrays
  528.      *
  529.      * @access  public
  530.      * @param   string
  531.      * @param   array
  532.      * @return  void
  533.      */
  534.     function set_userdata_array($arrayname = NULL, $newdata = array())
  535.     {
  536.         if ( ! is_null($arrayname) && is_array($newdata) )
  537.         {
  538.             if ( !isset($this->userdata[$arrayname]) )
  539.             {
  540.                 $this->userdata[$arrayname] = array();
  541.             }
  542.  
  543.             if (count($newdata) > 0)
  544.             {
  545.                 foreach ($newdata as $key => $val)
  546.                 {
  547.                     $this->userdata[$arrayname][$key] = $val;
  548.                 }
  549.             }
  550.         }
  551.     }
  552.  
  553.     // --------------------------------------------------------------------
  554.  
  555.     /**
  556.      * Delete a session variable from the "userdata" array
  557.      *
  558.      * Our version supports multi-arrays as session data
  559.      *
  560.      * @access  public
  561.      * @param   string
  562.      * @return  string
  563.      */
  564.     function unset_userdata($item, $subitem = NULL)
  565.     {
  566.         if ( is_null($subitem) )
  567.         {
  568.             if (is_string($item))
  569.             {
  570.                 $item = array($item => '');
  571.             }
  572.  
  573.             if (count($item) > 0)
  574.             {
  575.                 foreach ($item as $key => $val)
  576.                 {
  577.                     unset($this->userdata[$key]);
  578.                 }
  579.             }
  580.         }
  581.         else
  582.         {
  583.             unset($this->userdata[$item][$subitem]);
  584.         }
  585.  
  586.         if ( ! (isset($this->userdata['session_id'])))
  587.         {
  588.  
  589.             log_message('error', "userdata: ".print_r($this->userdata, TRUE));
  590.             log_message('error', "item: ".print_r($item, TRUE));
  591.             log_message('error', "subitem: ".$subitem);
  592.         }
  593.         $this->sess_write();
  594.     }
  595.  
  596.     // ------------------------------------------------------------------------
  597.  
  598.     /**
  599.      * Add or change flashdata, only available
  600.      * until the next request
  601.      *
  602.      * @access  public
  603.      * @param   mixed
  604.      * @param   string
  605.      * @return  void
  606.      */
  607.     function set_flashdata($newdata = array(), $newval = '')
  608.     {
  609.         if (is_string($newdata))
  610.         {
  611.             $newdata = array($newdata => $newval);
  612.         }
  613.  
  614.         if (count($newdata) > 0)
  615.         {
  616.             foreach ($newdata as $key => $val)
  617.             {
  618.                 $flashdata_key = $this->flashdata_key.':new:'.$key;
  619.                 $this->set_userdata($flashdata_key, $val);
  620.             }
  621.         }
  622.     }
  623.  
  624.     // ------------------------------------------------------------------------
  625.  
  626.     /**
  627.      * Keeps existing flashdata available to next request.
  628.      *
  629.      * Our version supports keeping all flashdata by not passing a key value
  630.      *
  631.      * @access    public
  632.      * @param    string
  633.      * @return    void
  634.      */
  635.     function keep_flashdata($key = NULL)
  636.     {
  637.         // Mark individual flashdata as 'new' to preserve it from _flashdata_sweep()
  638.         if ($key !== NULL)
  639.         {
  640.             // 'old' flashdata gets removed.  Here we mark all
  641.             // flashdata as 'new' to preserve it from _flashdata_sweep()
  642.             // Note the function will return FALSE if the $key
  643.             // provided cannot be found
  644.             $old_flashdata_key = $this->flashdata_key.':old:'.$key;
  645.             $value = $this->userdata($old_flashdata_key);
  646.  
  647.             $new_flashdata_key = $this->flashdata_key.':new:'.$key;
  648.             $this->set_userdata($new_flashdata_key, $value);
  649.         }
  650.         else
  651.         {
  652.             // Mark all 'old' flashdata as 'new' (keep data from being deleted during next request)
  653.             $userdata = $this->all_userdata();
  654.             foreach ($userdata as $name => $value)
  655.             {
  656.                 $parts = explode(':old:', $name);
  657.                 if (is_array($parts) && count($parts) === 2)
  658.                 {
  659.                     $new_name = $parts[0].':new:'.$parts[1];
  660.                     $this->set_userdata($new_name, $value);
  661.                     $this->unset_userdata($name);
  662.                 }
  663.             }
  664.         }
  665.     }
  666.  
  667.     // ------------------------------------------------------------------------
  668.  
  669.     /**
  670.      * Fetch a specific flashdata item from the session array
  671.      *
  672.      * @access  public
  673.      * @param   string
  674.      * @return  string
  675.      */
  676.     function flashdata($key)
  677.     {
  678.         $flashdata_key = $this->flashdata_key.':old:'.$key;
  679.         return $this->userdata($flashdata_key);
  680.     }
  681.  
  682.     // ------------------------------------------------------------------------
  683.  
  684.     /**
  685.      * Identifies flashdata as 'old' for removal
  686.      * when _flashdata_sweep() runs.
  687.      *
  688.      * Fix for a bug in the CI library (hardcoded use of $this->flashdata_key)
  689.      *
  690.      * @access  private
  691.      * @return  void
  692.      */
  693.     function _flashdata_mark()
  694.     {
  695.         $userdata = $this->all_userdata();
  696.         foreach ($userdata as $name => $value)
  697.         {
  698.             $parts = explode(':new:', $name);
  699.             if (is_array($parts) && count($parts) === 2)
  700.             {
  701.                 $new_name = $parts[0].':old:'.$parts[1];
  702.                 $this->set_userdata($new_name, $value);
  703.                 $this->unset_userdata($name);
  704.             }
  705.         }
  706.     }
  707.  
  708.     // ------------------------------------------------------------------------
  709.  
  710.     /**
  711.      * Removes all flashdata marked as 'old'
  712.      *
  713.      * @access  private
  714.      * @return  void
  715.      */
  716.  
  717.     function _flashdata_sweep()
  718.     {
  719.         $userdata = $this->all_userdata();
  720.         foreach ($userdata as $key => $value)
  721.         {
  722.             if (strpos($key, ':old:'))
  723.             {
  724.                 $this->unset_userdata($key);
  725.             }
  726.         }
  727.  
  728.     }
  729.  
  730.  
  731.     // --------------------------------------------------------------------
  732.  
  733.     /**
  734.      * Get the "now" time
  735.      *
  736.      * @access  private
  737.      * @return  string
  738.      */
  739.     function _get_time()
  740.     {
  741.         if (strtolower($this->time_reference) == 'gmt')
  742.         {
  743.             $now = time();
  744.             $time = mktime(gmdate("H", $now), gmdate("i", $now), gmdate("s", $now), gmdate("m", $now), gmdate("d", $now), gmdate("Y", $now));
  745.         }
  746.         else
  747.         {
  748.             $time = time();
  749.         }
  750.  
  751.         return $time;
  752.     }
  753.  
  754.     // --------------------------------------------------------------------
  755.  
  756.     /**
  757.      * Write the session cookie
  758.      *
  759.      * @access  public
  760.      * @return  void
  761.      */
  762.     function _set_cookie($cookie_data = NULL)
  763.     {
  764.  
  765.         if (is_null($cookie_data))
  766.         {
  767.             $cookie_data = $this->userdata;
  768.         }
  769.  
  770.  
  771.         // update the last write timestamp
  772.         $cookie_userdata['last_write'] = $this->now;
  773.  
  774.         // Serialize the userdata for the cookie
  775.         $cookie_data = $this->_serialize($cookie_data);
  776.  
  777.         if ($this->sess_encrypt_cookie == TRUE)
  778.         {
  779.             $cookie_data = $this->CI->encrypt->encode($cookie_data, $this->encryption_key);
  780.         }
  781.         else
  782.         {
  783.             // if encryption is not used, we provide an md5 hash to prevent userside tampering
  784.             $cookie_data = $cookie_data.md5($cookie_data.$this->encryption_key);
  785.         }
  786.  
  787.         $expire = ($this->sess_expire_on_close === TRUE) ? 0 : $this->sess_expiration + time();
  788.  
  789.         // Set the cookie
  790.         setcookie(
  791.                     $this->sess_cookie_name,
  792.                     $cookie_data,
  793.                     $expire,
  794.                     $this->cookie_path,
  795.                     $this->cookie_domain,
  796.                     0
  797.                 );
  798.     }
  799.  
  800.     // --------------------------------------------------------------------
  801.  
  802.     /**
  803.      * Serialize an array
  804.      *
  805.      * This function first converts any slashes found in the array to a temporary
  806.      * marker, so when it gets unserialized the slashes will be preserved
  807.      *
  808.      * @access  private
  809.      * @param   array
  810.      * @return  string
  811.      */
  812.     function _serialize($data)
  813.     {
  814.         if (is_array($data))
  815.         {
  816.             foreach ($data as $key => $val)
  817.             {
  818.                 if (is_string($val))
  819.                 {
  820.                     $data[$key] = str_replace('\\', '{{slash}}', $val);
  821.                 }
  822.             }
  823.         }
  824.         else
  825.         {
  826.             if (is_string($data))
  827.             {
  828.                 $data = str_replace('\\', '{{slash}}', $data);
  829.             }
  830.         }
  831.  
  832.         return serialize($data);
  833.     }
  834.  
  835.     // --------------------------------------------------------------------
  836.  
  837.     /**
  838.      * Unserialize
  839.      *
  840.      * This function unserializes a data string, then converts any
  841.      * temporary slash markers back to actual slashes
  842.      *
  843.      * @access  private
  844.      * @param   array
  845.      * @return  string
  846.      */
  847.     function _unserialize($data)
  848.     {
  849.         $data = @unserialize(strip_slashes($data));
  850.  
  851.         if (is_array($data))
  852.         {
  853.             foreach ($data as $key => $val)
  854.             {
  855.                 if (is_string($val))
  856.                 {
  857.                     $data[$key] = str_replace('{{slash}}', '\\', $val);
  858.                 }
  859.             }
  860.  
  861.             return $data;
  862.         }
  863.  
  864.         return (is_string($data)) ? str_replace('{{slash}}', '\\', $data) : $data;
  865.     }
  866.  
  867.     // --------------------------------------------------------------------
  868.  
  869.     /**
  870.      * Garbage collection
  871.      *
  872.      * This deletes expired session rows from database
  873.      * if the probability percentage is met
  874.      *
  875.      * @access  public
  876.      * @return  void
  877.      */
  878.     function _sess_gc()
  879.     {
  880.         if ($this->sess_use_database != TRUE)
  881.         {
  882.             return;
  883.         }
  884.  
  885.         srand(time());
  886.         if ((rand() % 100) < $this->gc_probability)
  887.         {
  888.             $expire = $this->now - $this->sess_expiration;
  889.  
  890.             $this->CI->db->where("last_write < {$expire}");
  891.             $this->CI->db->delete($this->sess_table_name);
  892.  
  893.             log_message('debug', 'Session garbage collection performed.');
  894.         }
  895.     }
  896.  
  897.  
  898. }
  899. // END Session Class
  900.  
  901. /* End of file Session.php */
  902. /* Location: ./exitecms/libraries/Session.php */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement