Advertisement
Guest User

Untitled

a guest
Jun 25th, 2017
74
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 17.48 KB | None | 0 0
  1. <?php
  2.  
  3. class CI_Session
  4. {
  5.     var $sess_table_name            = '';
  6.     var $sess_expiration            = 7200;
  7.     var $sess_match_ip                = FALSE;
  8.     var $sess_match_useragent        = TRUE;
  9.     var $sess_time_to_update        = 300;
  10.     var $encryption_key                = '';
  11.     var $flashdata_key                 = 'flash';
  12.     var $time_reference                = 'time';
  13.     var $gc_probability                = 5;
  14.     var $userdata                    = array();
  15.     var $CI;
  16.     var $now;
  17.  
  18.     /**
  19.      * Session Constructor
  20.      *
  21.      * The constructor runs the session routines automatically
  22.      * whenever the class is instantiated.
  23.      */
  24.     function CI_Session($params = array())
  25.     {                
  26.         log_message('debug', "Session Class Initialized");
  27.  
  28.         // Set the super object to a local variable for use throughout the class
  29.         $this->CI =& get_instance();
  30.  
  31.         // Set all the session preferences, which can either be set
  32.         // manually via the $params array above or via the config file
  33.         foreach (array('sess_table_name', 'sess_expiration', 'sess_match_ip', 'sess_match_useragent', 'sess_time_to_update', 'time_reference', 'encryption_key') as $key)
  34.         {
  35.             $this->$key = (isset($params[$key])) ? $params[$key] : $this->CI->config->item($key);
  36.         }
  37.  
  38.         // Sessions, start your engines!
  39.         ini_set("session.gc_maxlifetime", $this->sess_expiration);
  40.         session_start();
  41.        
  42.         // Load the string helper so we can use the strip_slashes() function
  43.         $this->CI->load->helper('string');
  44.  
  45.         // Are we using a database?  If so, load it
  46.         if( !$this->sess_table_name ) {
  47.             die('Session class database table name not configured');
  48.         }
  49.        
  50.         $this->CI->load->database();
  51.  
  52.         // Set the "now" time.  Can either be GMT or server time, based on the
  53.         // config prefs.  We use this to set the "last activity" time
  54.         $this->now = $this->_get_time();
  55.  
  56.         // Set the session length. If the session expiration is
  57.         // set to zero we'll set the expiration two years from now.
  58.         if ($this->sess_expiration == 0)
  59.         {
  60.             $this->sess_expiration = (60*60*24*365*2);
  61.         }
  62.  
  63.         // Run the Session routine. If a session doesn't exist we'll
  64.         // create a new one.  If it does, we'll update it.
  65.         if ( ! $this->sess_read())
  66.         {
  67.             $this->sess_create();
  68.         }
  69.         else
  70.         {
  71.             $this->sess_update();
  72.         }
  73.  
  74.         // Delete 'old' flashdata (from last request)
  75.            $this->_flashdata_sweep();
  76.  
  77.         // Mark all new flashdata as old (data will be deleted before next request)
  78.            $this->_flashdata_mark();
  79.  
  80.         // Delete expired sessions if necessary
  81.         $this->_sess_gc();
  82.  
  83.         log_message('debug', "Session routines successfully run");
  84.     }
  85.  
  86.     // --------------------------------------------------------------------
  87.  
  88.     /**
  89.      * Fetch the current session data if it exists
  90.      *
  91.      * @access    public
  92.      * @return    bool
  93.      */
  94.     function sess_read()
  95.     {
  96.         // Unserialize the session array
  97.         // $session = $this->_unserialize($session);
  98.        
  99.         $session = array();
  100.        
  101.         foreach( array('session_id', 'ip_address', 'user_agent', 'last_activity') as $key )
  102.         {
  103.             if( !isset($_SESSION[$key]) ) {
  104.                 $this->sess_destroy();
  105.                 return FALSE;
  106.             }
  107.            
  108.             $session[$key] = $_SESSION[$key];
  109.         }    
  110.            
  111.         // Is the session current?
  112.         if (($session['last_activity'] + $this->sess_expiration) < $this->now)
  113.         {
  114.             $this->sess_destroy();
  115.             return FALSE;
  116.         }
  117.  
  118.         // Does the IP Match?
  119.         if ($this->sess_match_ip == TRUE AND $session['ip_address'] != $this->CI->input->ip_address())
  120.         {
  121.             $this->sess_destroy();
  122.             return FALSE;
  123.         }
  124.  
  125.         // Does the User Agent Match?
  126.         if ($this->sess_match_useragent == TRUE AND trim($session['user_agent']) != trim(substr($this->CI->input->user_agent(), 0, 50)))
  127.         {
  128.             $this->sess_destroy();
  129.             return FALSE;
  130.         }
  131.  
  132.         $this->CI->db->where('session_id', $session['session_id']);
  133.  
  134.         if ($this->sess_match_ip == TRUE)
  135.         {
  136.             $this->CI->db->where('ip_address', $session['ip_address']);
  137.         }
  138.  
  139.         if ($this->sess_match_useragent == TRUE)
  140.         {
  141.             $this->CI->db->where('user_agent', $session['user_agent']);
  142.         }
  143.  
  144.         $query = $this->CI->db->get($this->sess_table_name);
  145.  
  146.         // No result?  Kill it!
  147.         if ($query->num_rows() == 0)
  148.         {
  149.             $this->sess_destroy();
  150.             return FALSE;
  151.         }
  152.  
  153.         // Is there custom data?  If so, add it to the main session array
  154.         $row = $query->row();
  155.         if (isset($row->user_data) AND $row->user_data != '')
  156.         {
  157.             $custom_data = $this->_unserialize($row->user_data);
  158.  
  159.             if (is_array($custom_data))
  160.             {
  161.                 foreach ($custom_data as $key => $val)
  162.                 {
  163.                     $session[$key] = $val;
  164.                 }
  165.             }
  166.         }
  167.  
  168.         // Session is valid!
  169.         $this->userdata = $session;
  170.  
  171.         return TRUE;
  172.     }
  173.  
  174.     // --------------------------------------------------------------------
  175.  
  176.     /**
  177.      * Write the session data
  178.      *
  179.      * @access    public
  180.      * @return    void
  181.      */
  182.     function sess_write()
  183.     {
  184.         // set the custom userdata, the session data we will set in a second
  185.         $custom_userdata = $this->userdata;
  186.  
  187.         // Before continuing, we need to determine if there is any custom data to deal with.
  188.         // Let's determine this by removing the default indexes to see if there's anything left in the array
  189.         // and set the session data while we're at it
  190.         foreach (array('session_id','ip_address','user_agent','last_activity') as $val)
  191.         {
  192.             unset($custom_userdata[$val]);
  193.         }
  194.  
  195.         // Did we find any custom data?  If not, we turn the empty array into a string
  196.         // since there's no reason to serialize and store an empty array in the DB
  197.         if (count($custom_userdata) === 0)
  198.         {
  199.             $custom_userdata = '';
  200.         }
  201.         else
  202.         {
  203.             // Serialize the custom data array so we can store it
  204.             $custom_userdata = $this->_serialize($custom_userdata);
  205.         }
  206.  
  207.         // Run the update query
  208.         $this->CI->db->where('session_id', $this->userdata['session_id']);
  209.         $this->CI->db->update($this->sess_table_name, array('last_activity' => $this->userdata['last_activity'], 'user_data' => $custom_userdata));
  210.     }
  211.  
  212.     // --------------------------------------------------------------------
  213.  
  214.     /**
  215.      * Create a new session
  216.      *
  217.      * @access    public
  218.      * @return    void
  219.      */
  220.     function sess_create()
  221.     {
  222.         $sessid = '';
  223.         while (strlen($sessid) < 32)
  224.         {
  225.             $sessid .= mt_rand(0, mt_getrandmax());
  226.         }
  227.  
  228.         // To make the session ID even more secure we'll combine it with the user's IP
  229.         $sessid .= $this->CI->input->ip_address();
  230.  
  231.         $this->userdata = array(
  232.             'session_id'     => md5(uniqid($sessid, TRUE)),
  233.             'ip_address'     => $this->CI->input->ip_address(),
  234.             'user_agent'     => substr($this->CI->input->user_agent(), 0, 50),
  235.             'last_activity'    => $this->now
  236.         );
  237.        
  238.         $_SESSION['session_id'] = $this->userdata['session_id'];
  239.         $_SESSION['ip_address'] = $this->userdata['ip_address'];
  240.         $_SESSION['user_agent'] = $this->userdata['user_agent'];
  241.         $_SESSION['last_activity'] = $this->userdata['last_activity'];
  242.  
  243.         $this->CI->db->query($this->CI->db->insert_string($this->sess_table_name, $this->userdata));
  244.     }
  245.  
  246.     // --------------------------------------------------------------------
  247.  
  248.     /**
  249.      * Update an existing session
  250.      *
  251.      * @access    public
  252.      * @return    void
  253.      */
  254.     function sess_update()
  255.     {
  256.         // We only update the session every five minutes by default
  257.         if (($this->userdata['last_activity'] + $this->sess_time_to_update) >= $this->now)
  258.         {
  259.             return;
  260.         }
  261.  
  262.         // Save the old session id so we know which record to
  263.         // update in the database if we need it
  264.         $old_sessid = $this->userdata['session_id'];
  265.         $new_sessid = '';
  266.         while (strlen($new_sessid) < 32)
  267.         {
  268.             $new_sessid .= mt_rand(0, mt_getrandmax());
  269.         }
  270.  
  271.         // To make the session ID even more secure we'll combine it with the user's IP
  272.         $new_sessid .= $this->CI->input->ip_address();
  273.  
  274.         // Turn it into a hash
  275.         $new_sessid = md5(uniqid($new_sessid, TRUE));
  276.  
  277.         // Update the session data in the session data array
  278.         $_SESSION['session_id'] = $this->userdata['session_id'] = $new_sessid;
  279.         $_SESSION['last_activity'] = $this->userdata['last_activity'] = $this->now;
  280.  
  281.         $this->CI->db->query($this->CI->db->update_string($this->sess_table_name, array('last_activity' => $this->now, 'session_id' => $new_sessid), array('session_id' => $old_sessid)));
  282.     }
  283.  
  284.     // --------------------------------------------------------------------
  285.  
  286.     /**
  287.      * Destroy the current session
  288.      *
  289.      * @access    public
  290.      * @return    void
  291.      */
  292.     function sess_destroy()
  293.     {
  294.         // Kill the session DB row
  295.         if( isset($this->userdata['session_id']) )
  296.         {
  297.             $this->CI->db->where('session_id', $this->userdata['session_id']);
  298.             $this->CI->db->delete($this->sess_table_name);
  299.         }
  300.     }
  301.  
  302.     // --------------------------------------------------------------------
  303.  
  304.     /**
  305.      * Fetch a specific item from the session array
  306.      *
  307.      * @access    public
  308.      * @param    string
  309.      * @return    string
  310.      */
  311.     function userdata($item)
  312.     {
  313.         return ( isset($this->userdata[$item]) ? $this->userdata[$item] : FALSE );
  314.     }
  315.  
  316.     // --------------------------------------------------------------------
  317.  
  318.     /**
  319.      * Fetch all session data
  320.      *
  321.      * @access    public
  322.      * @return    mixed
  323.      */
  324.     function all_userdata()
  325.     {
  326.         return ( isset($this->userdata) ? $this->userdata : FALSE );
  327.     }
  328.  
  329.     // --------------------------------------------------------------------
  330.  
  331.     /**
  332.      * Add or change data in the "userdata" array
  333.      *
  334.      * @access    public
  335.      * @param    mixed
  336.      * @param    string
  337.      * @return    void
  338.      */
  339.     function set_userdata($newdata = array(), $newval = '')
  340.     {
  341.         if (is_string($newdata))
  342.         {
  343.             $newdata = array($newdata => $newval);
  344.         }
  345.  
  346.         if (count($newdata) > 0)
  347.         {
  348.             foreach ($newdata as $key => $val)
  349.             {
  350.                 $this->userdata[$key] = $val;
  351.             }
  352.         }
  353.  
  354.         $this->sess_write();
  355.     }
  356.  
  357.     // --------------------------------------------------------------------
  358.  
  359.     /**
  360.      * Delete a session variable from the "userdata" array
  361.      *
  362.      * @access    array
  363.      * @return    void
  364.      */
  365.     function unset_userdata($newdata = array())
  366.     {
  367.         if (is_string($newdata))
  368.         {
  369.             $newdata = array($newdata => '');
  370.         }
  371.  
  372.         if (count($newdata) > 0)
  373.         {
  374.             foreach ($newdata as $key => $val)
  375.             {
  376.                 unset($this->userdata[$key]);
  377.             }
  378.         }
  379.  
  380.         $this->sess_write();
  381.     }
  382.  
  383.     // ------------------------------------------------------------------------
  384.  
  385.     /**
  386.      * Add or change flashdata, only available
  387.      * until the next request
  388.      *
  389.      * @access    public
  390.      * @param    mixed
  391.      * @param    string
  392.      * @return    void
  393.      */
  394.     function set_flashdata($newdata = array(), $newval = '')
  395.     {
  396.         if (is_string($newdata))
  397.         {
  398.             $newdata = array($newdata => $newval);
  399.         }
  400.  
  401.         if (count($newdata) > 0)
  402.         {
  403.             foreach ($newdata as $key => $val)
  404.             {
  405.                 $flashdata_key = $this->flashdata_key.':new:'.$key;
  406.                 $this->set_userdata($flashdata_key, $val);
  407.             }
  408.         }
  409.     }
  410.  
  411.     // ------------------------------------------------------------------------
  412.  
  413.     /**
  414.      * Keeps existing flashdata available to next request.
  415.      *
  416.      * @access    public
  417.      * @param    string
  418.      * @return    void
  419.      */
  420.     function keep_flashdata($key)
  421.     {
  422.         // 'old' flashdata gets removed.  Here we mark all
  423.         // flashdata as 'new' to preserve it from _flashdata_sweep()
  424.         // Note the function will return FALSE if the $key
  425.         // provided cannot be found
  426.         $old_flashdata_key = $this->flashdata_key.':old:'.$key;
  427.         $value = $this->userdata($old_flashdata_key);
  428.  
  429.         $new_flashdata_key = $this->flashdata_key.':new:'.$key;
  430.         $this->set_userdata($new_flashdata_key, $value);
  431.     }
  432.  
  433.     // ------------------------------------------------------------------------
  434.  
  435.     /**
  436.      * Fetch a specific flashdata item from the session array
  437.      *
  438.      * @access    public
  439.      * @param    string
  440.      * @return    string
  441.      */
  442.     function flashdata($key)
  443.     {
  444.         $flashdata_key = $this->flashdata_key.':old:'.$key;
  445.         return $this->userdata($flashdata_key);
  446.     }
  447.  
  448.     // ------------------------------------------------------------------------
  449.  
  450.     /**
  451.      * Identifies flashdata as 'old' for removal
  452.      * when _flashdata_sweep() runs.
  453.      *
  454.      * @access    private
  455.      * @return    void
  456.      */
  457.     function _flashdata_mark()
  458.     {
  459.         $userdata = $this->all_userdata();
  460.         foreach ($userdata as $name => $value)
  461.         {
  462.             $parts = explode(':new:', $name);
  463.             if (is_array($parts) && count($parts) === 2)
  464.             {
  465.                 $new_name = $this->flashdata_key.':old:'.$parts[1];
  466.                 $this->set_userdata($new_name, $value);
  467.                 $this->unset_userdata($name);
  468.             }
  469.         }
  470.     }
  471.  
  472.     // ------------------------------------------------------------------------
  473.  
  474.     /**
  475.      * Removes all flashdata marked as 'old'
  476.      *
  477.      * @access    private
  478.      * @return    void
  479.      */
  480.  
  481.     function _flashdata_sweep()
  482.     {
  483.         $userdata = $this->all_userdata();
  484.         foreach ($userdata as $key => $value)
  485.         {
  486.             if (strpos($key, ':old:'))
  487.             {
  488.                 $this->unset_userdata($key);
  489.             }
  490.         }
  491.  
  492.     }
  493.  
  494.     // --------------------------------------------------------------------
  495.  
  496.     /**
  497.      * Get the "now" time
  498.      *
  499.      * @access    private
  500.      * @return    string
  501.      */
  502.     function _get_time()
  503.     {
  504.         if (strtolower($this->time_reference) == 'gmt')
  505.         {
  506.             $now = time();
  507.             $time = mktime(gmdate("H", $now), gmdate("i", $now), gmdate("s", $now), gmdate("m", $now), gmdate("d", $now), gmdate("Y", $now));
  508.         }
  509.         else
  510.         {
  511.             $time = time();
  512.         }
  513.  
  514.         return $time;
  515.     }
  516.  
  517.  
  518.     // --------------------------------------------------------------------
  519.  
  520.     /**
  521.      * Serialize an array
  522.      *
  523.      * This function first converts any slashes found in the array to a temporary
  524.      * marker, so when it gets unserialized the slashes will be preserved
  525.      *
  526.      * @access    private
  527.      * @param    array
  528.      * @return    string
  529.      */
  530.     function _serialize($data)
  531.     {
  532.         if (is_array($data))
  533.         {
  534.             foreach ($data as $key => $val)
  535.             {
  536.                 $data[$key] = str_replace('\\', '{{slash}}', $val);
  537.             }
  538.         }
  539.         else
  540.         {
  541.             $data = str_replace('\\', '{{slash}}', $data);
  542.         }
  543.  
  544.         return serialize($data);
  545.     }
  546.  
  547.     // --------------------------------------------------------------------
  548.  
  549.     /**
  550.      * Unserialize
  551.      *
  552.      * This function unserializes a data string, then converts any
  553.      * temporary slash markers back to actual slashes
  554.      *
  555.      * @access    private
  556.      * @param    array
  557.      * @return    string
  558.      */
  559.     function _unserialize($data)
  560.     {
  561.         $data = @unserialize(strip_slashes($data));
  562.  
  563.         if (is_array($data))
  564.         {
  565.             foreach ($data as $key => $val)
  566.             {
  567.                 $data[$key] = str_replace('{{slash}}', '\\', $val);
  568.             }
  569.  
  570.             return $data;
  571.         }
  572.  
  573.         return str_replace('{{slash}}', '\\', $data);
  574.     }
  575.  
  576.     // --------------------------------------------------------------------
  577.  
  578.     /**
  579.      * Garbage collection
  580.      *
  581.      * This deletes expired session rows from database
  582.      * if the probability percentage is met
  583.      *
  584.      * @access    public
  585.      * @return    void
  586.      */
  587.     function _sess_gc()
  588.     {
  589.         srand(time());
  590.         if ((rand() % 100) < $this->gc_probability)
  591.         {
  592.             $expire = $this->now - $this->sess_expiration;
  593.  
  594.             $this->CI->db->where("last_activity < {$expire}");
  595.             $this->CI->db->delete($this->sess_table_name);
  596.  
  597.             log_message('debug', 'Session garbage collection performed.');
  598.         }
  599.     }
  600.  
  601.  
  602. }
  603. // END Session Class
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement