PageRenderTime 52ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/html/AppCode/expressionengine/libraries/Session.php

https://github.com/w3bg/www.hsifin.com
PHP | 1217 lines | 705 code | 226 blank | 286 comment | 159 complexity | f1ce7d9cdaf65a6d5f48a4e545d537f9 MD5 | raw file
Possible License(s): AGPL-3.0
  1. <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
  2. /**
  3. * ExpressionEngine - by EllisLab
  4. *
  5. * @package ExpressionEngine
  6. * @author ExpressionEngine Dev Team
  7. * @copyright Copyright (c) 2003 - 2010, EllisLab, Inc.
  8. * @license http://expressionengine.com/user_guide/license.html
  9. * @link http://expressionengine.com
  10. * @since Version 2.0
  11. * @filesource
  12. */
  13. // ------------------------------------------------------------------------
  14. /**
  15. * ExpressionEngine Core Session Class
  16. *
  17. * @package ExpressionEngine
  18. * @subpackage Core
  19. * @category Core
  20. * @author ExpressionEngine Dev Team
  21. * @link http://expressionengine.com
  22. */
  23. // ------------------------------------------------------------------------
  24. /*
  25. There are three validation types, set in the config file:
  26. 1. User cookies AND session ID (cs)
  27. This is the most secure way to run a site. Three cookies are set:
  28. 1. Session ID - This is a unique hash that is randomly generated when someone logs in.
  29. 2. Password hash - The encrypted password of the current user
  30. 3. Unique ID - The permanent unique ID hash associated with the account.
  31. All three cookies expire when you close your browser OR when you have been
  32. inactive longer than two hours (one hour in the control panel).
  33. Using this setting does NOT allow 'stay logged-in' capability, as each session has a finite lifespan.
  34. 2. Cookies only - no session ID (c)
  35. With this validation type, a session is not generated, therefore
  36. users can remain permanently logged in.
  37. This setting is obviously less secure because it does not provide a safety net
  38. if you share your computer or access your site from a public computer. It relies
  39. solely on the password/unique_id cookies.
  40. 3. Session ID only (s).
  41. Most compatible as it does not rely on cookies at all. Instead, a URL query string ID
  42. is used.
  43. No stay-logged in capability. The session will expire after one hour of inactivity, so
  44. in terms of security, it is preferable to number 2.
  45. NOTE: The control panel and public pages can each have their own session preference.
  46. */
  47. class EE_Session {
  48. var $user_session_len = 7200; // User sessions expire in two hours
  49. var $cpan_session_len = 3600; // Admin sessions expire in one hour
  50. var $c_session = 'sessionid';
  51. var $c_uniqueid = 'uniqueid';
  52. var $c_password = 'userhash';
  53. var $c_expire = 'expiration';
  54. var $c_anon = 'anon';
  55. var $c_prefix = '';
  56. var $sdata = array();
  57. var $userdata = array();
  58. var $tracker = array();
  59. var $flashdata = array();
  60. var $sess_crypt_key = '';
  61. var $validation_type = '';
  62. var $session_length = '';
  63. var $cookies_exist = FALSE;
  64. var $session_exists = FALSE;
  65. var $access_cp = FALSE;
  66. var $gc_probability = 5; // Garbage collection probability. Used to kill expired sessions.
  67. var $cache = array(); // Store data for just this page load. Multi-dimensional array with module/class name, e.g. $SESS->cache['module']['var_name']
  68. /**
  69. * Session Class Constructor
  70. */
  71. function EE_Session()
  72. {
  73. // Make a local reference to the ExpressionEngine super object
  74. $this->EE =& get_instance();
  75. // Is the user banned?
  76. // We only look for banned IPs if it's not a control panel request.
  77. // We test for banned admins separately in the front controller
  78. $ban_status = FALSE;
  79. if (REQ != 'CP')
  80. {
  81. if ($this->ban_check('ip'))
  82. {
  83. switch ($this->EE->config->item('ban_action'))
  84. {
  85. case 'message' : return $this->EE->output->fatal_error($this->EE->config->item('ban_message'), 0);
  86. break;
  87. case 'bounce' : $this->EE->functions->redirect($this->EE->config->item('ban_destination')); exit;
  88. break;
  89. default : $ban_status = TRUE;
  90. break;
  91. }
  92. }
  93. }
  94. /** --------------------------------------
  95. /** Set session length.
  96. /** --------------------------------------*/
  97. $this->session_length = (REQ == 'CP') ? $this->cpan_session_len : $this->user_session_len;
  98. /** --------------------------------------
  99. /** Set Default Session Values
  100. /** --------------------------------------*/
  101. // Set USER-DATA as GUEST until proven otherwise
  102. $this->userdata = array(
  103. 'username' => $this->EE->input->cookie('my_name'),
  104. 'screen_name' => '',
  105. 'email' => $this->EE->input->cookie('my_email'),
  106. 'url' => $this->EE->input->cookie('my_url'),
  107. 'location' => $this->EE->input->cookie('my_location'),
  108. 'language' => '',
  109. 'timezone' => ($this->EE->config->item('default_site_timezone') && $this->EE->config->item('default_site_timezone') != '') ? $this->EE->config->item('default_site_timezone') : $this->EE->config->item('server_timezone'),
  110. 'daylight_savings' => ($this->EE->config->item('default_site_dst') && $this->EE->config->item('default_site_dst') != '') ? $this->EE->config->item('default_site_dst') : $this->EE->config->item('daylight_savings'),
  111. 'time_format' => ($this->EE->config->item('time_format') && $this->EE->config->item('time_format') != '') ? $this->EE->config->item('time_format') : 'us',
  112. 'group_id' => '3',
  113. 'access_cp' => 0,
  114. 'last_visit' => 0,
  115. 'is_banned' => $ban_status,
  116. 'ignore_list' => array()
  117. );
  118. // Set SESSION data as GUEST until proven otherwise
  119. $this->sdata = array(
  120. 'session_id' => 0,
  121. 'member_id' => 0,
  122. 'admin_sess' => 0,
  123. 'ip_address' => $this->EE->input->ip_address(),
  124. 'user_agent' => substr($this->EE->input->user_agent(), 0, 50),
  125. 'last_activity' => 0
  126. );
  127. // -------------------------------------------
  128. // 'sessions_start' hook.
  129. // - Reset any session class variable
  130. // - Override the whole session check
  131. // - Modify default/guest settings
  132. //
  133. $edata = $this->EE->extensions->universal_call('sessions_start', $this);
  134. if ($this->EE->extensions->end_script === TRUE) return;
  135. //
  136. // -------------------------------------------
  137. /** --------------------------------------
  138. /** Fetch the Session ID
  139. /** --------------------------------------*/
  140. // A session ID can either come from a cookie or GET data
  141. if ( ! $this->EE->input->cookie($this->c_session))
  142. {
  143. if ( ! $this->EE->input->get('S'))
  144. {
  145. // If session IDs are being used in public pages the session will be found here
  146. if ($this->EE->input->SID != '')
  147. {
  148. $this->sdata['session_id'] = $this->EE->input->SID;
  149. }
  150. }
  151. else
  152. {
  153. $this->sdata['session_id'] = $this->EE->input->get('S');
  154. }
  155. }
  156. else
  157. {
  158. $this->sdata['session_id'] = $this->EE->input->cookie($this->c_session);
  159. }
  160. /** --------------------------------------
  161. /** Fetch password and unique_id cookies
  162. /** --------------------------------------*/
  163. if ($this->EE->input->cookie($this->c_uniqueid) AND $this->EE->input->cookie($this->c_password))
  164. {
  165. $this->cookies_exist = TRUE;
  166. }
  167. /** --------------------------------------
  168. /** Set the Validation Type
  169. /** --------------------------------------*/
  170. if (REQ == 'CP')
  171. {
  172. $this->validation = ( ! in_array($this->EE->config->item('admin_session_type'), array('cs', 'c', 's'))) ? 'cs' : $this->EE->config->item('admin_session_type');
  173. }
  174. else
  175. {
  176. $this->validation = ( ! in_array($this->EE->config->item('user_session_type'), array('cs', 'c', 's'))) ? 'cs' : $this->EE->config->item('user_session_type');
  177. }
  178. /** --------------------------------------
  179. /** Do session IDs exist?
  180. /** --------------------------------------*/
  181. switch ($this->validation)
  182. {
  183. case 'cs' : $session_id = ($this->sdata['session_id'] != '0' AND $this->cookies_exist == TRUE) ? TRUE : FALSE;
  184. break;
  185. case 'c' : $session_id = ($this->cookies_exist) ? TRUE : FALSE;
  186. break;
  187. case 's' : $session_id = ($this->sdata['session_id'] != '0') ? TRUE : FALSE;
  188. break;
  189. }
  190. /** --------------------------------------
  191. /** Fetch Session Data
  192. /** --------------------------------------*/
  193. // IMPORTANT: The session data must be fetched before the member data so don't move this.
  194. if ($session_id === TRUE)
  195. {
  196. if ($this->fetch_session_data() === TRUE)
  197. {
  198. $this->session_exists = TRUE;
  199. }
  200. }
  201. /** --------------------------------------
  202. /** Fetch Member Data
  203. /** --------------------------------------*/
  204. $member_data_exists = ($this->fetch_member_data() === TRUE) ? TRUE : FALSE;
  205. /** --------------------------------------
  206. /** Update/Create Session
  207. /** --------------------------------------*/
  208. if ($session_id === FALSE OR $member_data_exists === FALSE)
  209. {
  210. $this->fetch_guest_data();
  211. }
  212. else
  213. {
  214. if ($this->session_exists === TRUE)
  215. {
  216. $this->update_session();
  217. }
  218. else
  219. {
  220. if ($this->validation == 'c')
  221. {
  222. $this->create_new_session($this->userdata['member_id']);
  223. }
  224. else
  225. {
  226. $this->fetch_guest_data();
  227. }
  228. }
  229. }
  230. /** --------------------------------------
  231. /** Update cookies
  232. /** --------------------------------------*/
  233. $this->update_cookies();
  234. $this->_prep_flashdata();
  235. // Fetch "tracker" cookie
  236. if (REQ != 'CP')
  237. {
  238. $this->tracker = $this->tracker();
  239. }
  240. /** --------------------------------------
  241. /** Kill old sessions
  242. /** --------------------------------------*/
  243. $this->delete_old_sessions();
  244. /** --------------------------------------
  245. /** Merge Session and User Data Arrays
  246. /** --------------------------------------*/
  247. // We merge these into into one array for portability
  248. $this->userdata = array_merge($this->userdata, $this->sdata);
  249. // -------------------------------------------
  250. // 'sessions_end' hook.
  251. // - Modify the user's session/member data.
  252. // - Additional Session or Login methods (ex: log in to other system)
  253. //
  254. $edata = $this->EE->extensions->universal_call('sessions_end', $this);
  255. if ($this->EE->extensions->end_script === TRUE) return;
  256. //
  257. // -------------------------------------------
  258. // Garbage collection
  259. unset($this->sdata);
  260. unset($session_id);
  261. unset($ban_status);
  262. unset($member_data_exists);
  263. }
  264. // --------------------------------------------------------------------
  265. /**
  266. * Fetch session data
  267. *
  268. * @return boolean
  269. */
  270. function fetch_session_data()
  271. {
  272. // Look for session. Match the user's IP address and browser for added security.
  273. $this->EE->db->select('member_id, admin_sess, last_activity');
  274. $this->EE->db->where('session_id', $this->sdata['session_id']);
  275. $this->EE->db->where('ip_address', $this->sdata['ip_address']);
  276. $this->EE->db->where('user_agent', $this->sdata['user_agent']);
  277. if (REQ != 'CP') // Each 'Site' has own Sessions
  278. {
  279. $this->EE->db->where('site_id', $this->EE->config->item('site_id'));
  280. }
  281. $query = $this->EE->db->get('sessions');
  282. if ($query->num_rows() == 0 OR $query->row('member_id') == 0)
  283. {
  284. $this->initialize_session();
  285. return FALSE;
  286. }
  287. // Assign member ID to session array
  288. $this->sdata['member_id'] = $query->row('member_id') ;
  289. // Is this an admin session?
  290. $this->sdata['admin_sess'] = ($query->row('admin_sess') == 1) ? 1 : 0;
  291. // Log last activity
  292. $this->sdata['last_activity'] = $query->row('last_activity') ;
  293. // If session has expired, delete it and set session data to GUEST
  294. if ($this->validation != 'c')
  295. {
  296. if ($query->row('last_activity') < ($this->EE->localize->now - $this->session_length))
  297. {
  298. $this->EE->db->delete('sessions', array(
  299. 'session_id' => $this->sdata['session_id']));
  300. $this->initialize_session();
  301. return FALSE;
  302. }
  303. }
  304. return TRUE;
  305. }
  306. // --------------------------------------------------------------------
  307. /**
  308. * Fetch guest data
  309. */
  310. function fetch_guest_data()
  311. {
  312. $this->EE->db->where('site_id', $this->EE->config->item('site_id'));
  313. $this->EE->db->where('group_id', '3');
  314. $query = $this->EE->db->get('member_groups');
  315. foreach ($query->row_array() as $key => $val)
  316. {
  317. $this->userdata[$key] = $val;
  318. }
  319. $this->userdata['total_comments'] = 0;
  320. $this->userdata['total_entries'] = 0;
  321. $this->userdata['private_messages'] = 0;
  322. $this->userdata['total_forum_posts'] = 0;
  323. $this->userdata['total_forum_topics'] = 0;
  324. $this->userdata['total_forum_replies'] = 0;
  325. $this->userdata['display_signatures'] = 'y';
  326. $this->userdata['display_avatars'] = 'y';
  327. $this->userdata['display_photos'] = 'y';
  328. $this->userdata['parse_smileys'] = 'y';
  329. // The following cookie info is only used with the forum module.
  330. // It enables us to track "read topics" with users who are not
  331. // logged in.
  332. // Cookie expiration: One year
  333. $expire = (60*60*24*365);
  334. // Has the user been active before? If not we set the "last_activity" to the current time.
  335. $this->sdata['last_activity'] = ( ! $this->EE->input->cookie('last_activity')) ? $this->EE->localize->now : $this->EE->input->cookie('last_activity');
  336. // Is the "last_visit" cookie set? If not, we set the last visit date to ten years ago.
  337. // This is a kind of funky thing to do but it enables the forum to show all topics as unread.
  338. // Since the last_visit stats are only available for logged-in members it doesn't hurt anything to set it this way for guests.
  339. if ( ! $this->EE->input->cookie('last_visit'))
  340. {
  341. $this->userdata['last_visit'] = $this->EE->localize->now-($expire*10);
  342. $this->EE->functions->set_cookie('last_visit', $this->userdata['last_visit'], $expire);
  343. }
  344. else
  345. {
  346. $this->userdata['last_visit'] = $this->EE->input->cookie('last_visit');
  347. }
  348. // If the user has been inactive longer than the session length we'll
  349. // set the "last_visit" cooke with the "last_activity" date.
  350. if (($this->sdata['last_activity'] + $this->session_length) < $this->EE->localize->now)
  351. {
  352. $this->userdata['last_visit'] = $this->sdata['last_activity'];
  353. $this->EE->functions->set_cookie('last_visit', $this->userdata['last_visit'], $expire);
  354. }
  355. // Update the last activity with each page load
  356. $this->EE->functions->set_cookie('last_activity', $this->EE->localize->now, $expire);
  357. }
  358. // --------------------------------------------------------------------
  359. /**
  360. * Fetch member data
  361. */
  362. function fetch_member_data()
  363. {
  364. if ($this->EE->config->item('enable_db_caching') == 'y' AND REQ == 'PAGE')
  365. {
  366. $this->EE->db->cache_off();
  367. }
  368. // Query DB for member data. Depending on the validation type we'll
  369. // either use the cookie data or the member ID gathered with the session query.
  370. $select = 'm.username, m.screen_name, m.member_id, m.email, m.url, m.location, m.join_date, m.last_visit,
  371. m.last_activity, m.total_entries, m.total_comments, m.total_forum_posts, m.total_forum_topics,
  372. m.last_forum_post_date, m.language, m.timezone, m.daylight_savings, m.time_format,
  373. m.profile_theme, m.forum_theme, m.private_messages, m.accept_messages, m.last_view_bulletins,
  374. m.last_bulletin_date, m.display_signatures, m.display_avatars, m.parse_smileys,
  375. m.last_email_date, m.notify_by_default, m.ignore_list, m.crypt_key';
  376. if (REQ == 'CP')
  377. {
  378. $select .= ', m.cp_theme, m.quick_links, m.quick_tabs, m.template_size';
  379. }
  380. $select .= ', g.*';
  381. $this->EE->db->select($select);
  382. $this->EE->db->from(array('members m', 'member_groups g'));
  383. if ($this->validation == 'c' OR $this->validation == 'cs')
  384. {
  385. $this->EE->db->where('g.site_id', $this->EE->config->item('site_id'));
  386. $this->EE->db->where('unique_id', (string) $this->EE->input->cookie($this->c_uniqueid));
  387. $this->EE->db->where('password', (string) $this->EE->input->cookie($this->c_password));
  388. $this->EE->db->where('m.group_id', ' g.group_id', FALSE);
  389. }
  390. else
  391. {
  392. $this->EE->db->where('g.site_id', $this->EE->config->item('site_id'));
  393. $this->EE->db->where('member_id', $this->sdata['member_id']);
  394. $this->EE->db->where('m.group_id', ' g.group_id', FALSE);
  395. }
  396. $query = $this->EE->db->get();
  397. if ($query->num_rows() == 0)
  398. {
  399. $this->initialize_session();
  400. return FALSE;
  401. }
  402. // Turn the query rows into array values
  403. foreach ($query->row_array() as $key => $val)
  404. {
  405. if ($key != 'crypt_key')
  406. {
  407. $this->userdata[$key] = $val;
  408. }
  409. else
  410. {
  411. // we don't add the session encryption key to userdata, to avoid accidental disclosure
  412. if ($val == '')
  413. {
  414. // not set yet, so let's create one and udpate it for this user
  415. $this->sess_crypt_key = $this->EE->functions->random('encrypt', 16);
  416. $this->EE->db->update('members', array('crypt_key' => $this->sess_crypt_key), array('member_id' => $query->row('member_id')));
  417. }
  418. else
  419. {
  420. $this->sess_crypt_key = $val;
  421. }
  422. }
  423. }
  424. // Create the array for the Ignore List
  425. $this->userdata['ignore_list'] = ($this->userdata['ignore_list'] == '') ? array() : explode('|', $this->userdata['ignore_list']);
  426. // Fix the values for forum posts and replies
  427. $this->userdata['total_forum_posts'] = $query->row('total_forum_topics') + $query->row('total_forum_posts') ;
  428. $this->userdata['total_forum_replies'] = $query->row('total_forum_posts') ;
  429. $this->userdata['display_photos'] = $this->userdata['display_avatars'];
  430. /** -----------------------------------------------------
  431. /** Are users allowed to localize?
  432. /** -----------------------------------------------------*/
  433. if ($this->EE->config->item('allow_member_localization') == 'n')
  434. {
  435. $this->userdata['timezone'] = ($this->EE->config->item('default_site_timezone') && $this->EE->config->item('default_site_timezone') != '') ? $this->EE->config->item('default_site_timezone') : $this->EE->config->item('server_timezone');
  436. $this->userdata['daylight_savings'] = ($this->EE->config->item('default_site_dst') && $this->EE->config->item('default_site_dst') != '') ? $this->EE->config->item('default_site_dst') : $this->EE->config->item('daylight_savings');
  437. $this->userdata['time_format'] = ($this->EE->config->item('time_format') && $this->EE->config->item('time_format') != '') ? $this->EE->config->item('time_format') : 'us';
  438. }
  439. /** -----------------------------------------------------
  440. /** Assign Sites, Channel, Template, and Module Access Privs
  441. /** -----------------------------------------------------*/
  442. if (REQ == 'CP')
  443. {
  444. // Fetch channel privileges
  445. $assigned_channels = array();
  446. if ($this->userdata['group_id'] == 1)
  447. {
  448. $this->EE->db->select('channel_id, channel_title');
  449. $this->EE->db->order_by('channel_title');
  450. $result = $this->EE->db->get_where('channels',
  451. array('site_id' => $this->EE->config->item('site_id')));
  452. }
  453. else
  454. {
  455. $result = $this->EE->db->query("SELECT ew.channel_id, ew.channel_title FROM exp_channel_member_groups ewmg, exp_channels ew
  456. WHERE ew.channel_id = ewmg.channel_id
  457. AND ewmg.group_id = '".$this->EE->db->escape_str($this->userdata['group_id'])."'
  458. AND site_id = '".$this->EE->db->escape_str($this->EE->config->item('site_id'))."'
  459. ORDER BY ew.channel_title");
  460. }
  461. if ($result->num_rows() > 0)
  462. {
  463. foreach ($result->result_array() as $row)
  464. {
  465. $assigned_channels[$row['channel_id']] = $row['channel_title'];
  466. }
  467. }
  468. $this->userdata['assigned_channels'] = $assigned_channels;
  469. // Fetch module privileges
  470. $assigned_modules = array();
  471. $this->EE->db->select('module_id');
  472. $result = $this->EE->db->get_where('module_member_groups',
  473. array('group_id' => $this->userdata['group_id']));
  474. if ($result->num_rows() > 0)
  475. {
  476. foreach ($result->result_array() as $row)
  477. {
  478. $assigned_modules[$row['module_id']] = TRUE;
  479. }
  480. }
  481. $this->userdata['assigned_modules'] = $assigned_modules;
  482. // Fetch template group privileges
  483. $assigned_template_groups = array();
  484. $this->EE->db->select('template_group_id');
  485. $result = $this->EE->db->get_where('template_member_groups',
  486. array('group_id' => $this->userdata['group_id']));
  487. if ($result->num_rows() > 0)
  488. {
  489. foreach ($result->result_array() as $row)
  490. {
  491. $assigned_template_groups[$row['template_group_id']] = TRUE;
  492. }
  493. }
  494. $this->userdata['assigned_template_groups'] = $assigned_template_groups;
  495. // Fetch Assigned Sites Available to User
  496. $assigned_sites = array();
  497. if ($this->userdata['group_id'] == 1)
  498. {
  499. $this->EE->db->select('site_id, site_label');
  500. $this->EE->db->order_by('site_label');
  501. $result = $this->EE->db->get('sites');
  502. }
  503. else
  504. {
  505. // Those groups that can access the Site's CP, see the site in the 'Sites' pulldown
  506. $this->EE->db->select('es.site_id, es.site_label');
  507. $this->EE->db->from(array('sites es', 'member_groups mg'));
  508. $this->EE->db->where('mg.site_id', ' es.site_id', FALSE);
  509. $this->EE->db->where('mg.group_id', $this->userdata['group_id']);
  510. $this->EE->db->where('mg.can_access_cp', 'y');
  511. $this->EE->db->order_by('es.site_label');
  512. $result = $this->EE->db->get();
  513. }
  514. if ($result->num_rows() > 0)
  515. {
  516. foreach ($result->result_array() as $row)
  517. {
  518. $assigned_sites[$row['site_id']] = $row['site_label'];
  519. }
  520. }
  521. $this->userdata['assigned_sites'] = $assigned_sites;
  522. }
  523. // Does the member have admin privileges?
  524. if ($query->row('can_access_cp') == 'y')
  525. {
  526. $this->access_cp = TRUE;
  527. }
  528. else
  529. {
  530. $this->sdata['admin_sess'] = 0;
  531. }
  532. // Update the session array with the member_id
  533. if ($this->validation == 'c')
  534. {
  535. $this->sdata['member_id'] = $query->row('member_id') ;
  536. }
  537. // If the user has been inactive for longer than the session length
  538. // we'll update their last_visit item so that it contains the last_activity
  539. // date. That way, we can show the exact time they were last visitng the site.
  540. if (($this->userdata['last_visit'] == 0) OR
  541. (($query->row('last_activity') + $this->session_length) < $this->EE->localize->now))
  542. {
  543. $last_act = ($query->row('last_activity') > 0) ? $query->row('last_activity') : $this->EE->localize->now;
  544. $this->EE->db->where('member_id', $this->sdata['member_id']);
  545. $this->EE->db->update('members', array('last_visit' => $last_act,
  546. 'last_activity' => $this->EE->localize->now));
  547. $this->userdata['last_visit'] = $query->row('last_activity') ;
  548. }
  549. // Update member 'last activity' date field for this member.
  550. // We update this ever 5 minutes. It's used with the session table
  551. // so we can update sessions
  552. if (($query->row('last_activity') + 300) < $this->EE->localize->now)
  553. {
  554. $this->EE->db->where('member_id', $this->sdata['member_id']);
  555. $this->EE->db->update('members', array('last_activity' => $this->EE->localize->now));
  556. }
  557. if ($this->EE->config->item('enable_db_caching') == 'y' AND REQ == 'PAGE')
  558. {
  559. $this->EE->db->cache_on();
  560. }
  561. return TRUE;
  562. }
  563. // --------------------------------------------------------------------
  564. /**
  565. * Update Member session
  566. */
  567. function update_session()
  568. {
  569. $this->sdata['last_activity'] = $this->EE->localize->now;
  570. $this->EE->db->query($this->EE->db->update_string('exp_sessions', $this->sdata, "session_id ='".$this->EE->db->escape_str($this->sdata['session_id'])."'"));
  571. // Update session ID cookie
  572. if ($this->validation == 'cs')
  573. {
  574. $this->EE->functions->set_cookie($this->c_session , $this->sdata['session_id'], $this->session_length);
  575. }
  576. // If we only require cookies for validation, set admin session.
  577. if ($this->validation == 'c' AND $this->access_cp == TRUE)
  578. {
  579. $this->sdata['admin_sess'] = 1;
  580. }
  581. // We'll unset the "last activity" item from the session data array.
  582. // We do this to avoid a conflict with the "last_activity" item in the
  583. // userdata array since we'll be merging the two arrays in a later step
  584. unset($this->sdata['last_activity']);
  585. }
  586. // --------------------------------------------------------------------
  587. /**
  588. * Create New Session
  589. */
  590. function create_new_session($member_id, $admin_session = FALSE)
  591. {
  592. if ($this->validation == 'c' AND $this->access_cp == TRUE)
  593. {
  594. $this->sdata['admin_sess'] = 1;
  595. }
  596. else
  597. {
  598. $this->sdata['admin_sess'] = ($admin_session == FALSE) ? 0 : 1;
  599. }
  600. $this->sdata['session_id'] = $this->EE->functions->random();
  601. $this->sdata['last_activity'] = $this->EE->localize->now;
  602. $this->sdata['user_agent'] = substr($this->EE->input->user_agent(), 0, 50);
  603. $this->sdata['ip_address'] = $this->EE->input->ip_address();
  604. $this->sdata['member_id'] = $member_id;
  605. $this->sdata['site_id'] = $this->EE->config->item('site_id');
  606. $this->userdata['member_id'] = $member_id;
  607. $this->userdata['session_id'] = $this->sdata['session_id'];
  608. $this->userdata['site_id'] = $this->EE->config->item('site_id');
  609. if ($this->validation != 's')
  610. {
  611. $this->EE->functions->set_cookie($this->c_session , $this->sdata['session_id'], $this->session_length);
  612. }
  613. $this->EE->db->query($this->EE->db->insert_string('exp_sessions', $this->sdata));
  614. return $this->sdata['session_id'];
  615. }
  616. // --------------------------------------------------------------------
  617. /**
  618. * Reset session data as GUEST
  619. */
  620. function initialize_session()
  621. {
  622. $this->sdata['session_id'] = 0;
  623. $this->sdata['admin_sess'] = 0;
  624. $this->sdata['member_id'] = 0;
  625. }
  626. // --------------------------------------------------------------------
  627. /**
  628. * Update Cookies
  629. */
  630. function update_cookies()
  631. {
  632. if ($this->cookies_exist == TRUE AND $this->EE->input->cookie($this->c_expire))
  633. {
  634. $now = time() + 300;
  635. $expire = 60*60*24*365;
  636. if ($this->EE->input->cookie($this->c_expire) > $now)
  637. {
  638. $this->EE->functions->set_cookie($this->c_expire , time()+$expire, $expire);
  639. $this->EE->functions->set_cookie($this->c_uniqueid , $this->EE->input->cookie($this->c_uniqueid), $expire);
  640. $this->EE->functions->set_cookie($this->c_password , $this->EE->input->cookie($this->c_password), $expire);
  641. }
  642. }
  643. }
  644. // --------------------------------------------------------------------
  645. /**
  646. * Fetch a session item
  647. */
  648. function userdata($which)
  649. {
  650. return ( ! isset($this->userdata[$which])) ? FALSE : $this->userdata[$which];
  651. }
  652. // --------------------------------------------------------------------
  653. /**
  654. * Tracker
  655. *
  656. * This functions lets us store the visitor's last five pages viewed
  657. * in a cookie. We use this to facilitate redirection after logging-in,
  658. * or other form submissions
  659. */
  660. function tracker()
  661. {
  662. $tracker = $this->EE->input->cookie('tracker');
  663. if ($tracker != FALSE)
  664. {
  665. if (preg_match("#(http:\/\/|https:\/\/|www\.|[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})#i", $tracker))
  666. {
  667. return array();
  668. }
  669. if (stristr($tracker, ':') !== FALSE)
  670. {
  671. $tracker_parts = explode(':', $tracker);
  672. if (current($tracker_parts) != 'a' OR count($tracker_parts) < 3 OR ! is_numeric(next($tracker_parts)))
  673. {
  674. return array();
  675. }
  676. }
  677. $tracker = unserialize(stripslashes($tracker));
  678. }
  679. if ( ! is_array($tracker))
  680. {
  681. $tracker = array();
  682. }
  683. $URI = ($this->EE->uri->uri_string == '') ? 'index' : $this->EE->uri->uri_string;
  684. $URI = str_replace("\\", "/", $URI);
  685. // If someone is messing with the URI we won't set the cookie
  686. if ( ! isset($_GET['ACT']) && preg_match('/[^a-z0-9\%\_\/\-]/i', $URI))
  687. {
  688. return array();
  689. }
  690. if ( ! isset($_GET['ACT']))
  691. {
  692. if ( ! isset($tracker['0']))
  693. {
  694. $tracker[] = $URI;
  695. }
  696. else
  697. {
  698. if (count($tracker) == 5)
  699. {
  700. array_pop($tracker);
  701. }
  702. if ($tracker['0'] != $URI)
  703. {
  704. array_unshift($tracker, $URI);
  705. }
  706. }
  707. }
  708. if (REQ == 'PAGE')
  709. {
  710. $this->EE->functions->set_cookie('tracker', serialize($tracker), '0');
  711. }
  712. return $tracker;
  713. }
  714. // --------------------------------------------------------------------
  715. /**
  716. * Get flashdata by key
  717. *
  718. * @access private
  719. * @param string
  720. * @return mixed
  721. */
  722. function flashdata($key = '')
  723. {
  724. return isset($this->flashdata[$key]) ? $this->flashdata[$key] : FALSE;
  725. }
  726. // --------------------------------------------------------------------
  727. /**
  728. * Set flashdata
  729. *
  730. * @access private
  731. * @param mixed
  732. * @return mixed
  733. */
  734. function set_flashdata($key, $val = '')
  735. {
  736. if ( ! is_array($key))
  737. {
  738. $key = array($key => $val);
  739. }
  740. foreach($key as $k => $v)
  741. {
  742. $this->flashdata[':new:'.$k] = $v;
  743. }
  744. $this->_set_flash_cookie();
  745. }
  746. // --------------------------------------------------------------------
  747. /**
  748. * Prep flashdata
  749. *
  750. * Grabs the cookie and validates the signature
  751. *
  752. * @access private
  753. * @return void
  754. */
  755. function _prep_flashdata()
  756. {
  757. if ($cookie = $this->EE->input->cookie('flash'))
  758. {
  759. if (strlen($cookie) > 32)
  760. {
  761. $signature = substr($cookie, -32);
  762. $payload = substr($cookie, 0, -32);
  763. if (md5($payload.$this->sess_crypt_key) == $signature)
  764. {
  765. $this->flashdata = unserialize(stripslashes($payload));
  766. $this->_age_flashdata();
  767. return;
  768. }
  769. }
  770. }
  771. $this->flashdata = array();
  772. }
  773. // --------------------------------------------------------------------
  774. /**
  775. * Age flashdata
  776. *
  777. * Removes old, marks current as old, etc
  778. *
  779. * @access private
  780. * @return void
  781. */
  782. function _age_flashdata()
  783. {
  784. foreach($this->flashdata as $key => $val)
  785. {
  786. if (strpos($key, ':old:') !== 0)
  787. {
  788. if (strpos($key, ':new:') === 0)
  789. {
  790. $this->flashdata[substr($key, 5)] = $val;
  791. }
  792. else
  793. {
  794. $this->flashdata[':old:'.$key] = $val;
  795. }
  796. }
  797. unset($this->flashdata[$key]);
  798. }
  799. $this->_set_flash_cookie();
  800. }
  801. // --------------------------------------------------------------------
  802. /**
  803. * Set signed flashdata cookie
  804. *
  805. * @access private
  806. * @return void
  807. */
  808. function _set_flash_cookie()
  809. {
  810. // Don't want to hash the crypt key by itself
  811. $payload = '';
  812. if (count($this->flashdata) > 0)
  813. {
  814. $payload = serialize($this->flashdata);
  815. $payload = $payload.md5($payload.$this->sess_crypt_key);
  816. }
  817. $this->EE->functions->set_cookie('flash' , $payload, 86500);
  818. }
  819. // --------------------------------------------------------------------
  820. /**
  821. * Check for banned data
  822. */
  823. function ban_check($type = 'ip', $match = '')
  824. {
  825. switch ($type)
  826. {
  827. case 'ip' : $ban = $this->EE->config->item('banned_ips');
  828. $match = $this->EE->input->ip_address();
  829. break;
  830. case 'email' : $ban = $this->EE->config->item('banned_emails');
  831. break;
  832. case 'username' : $ban = $this->EE->config->item('banned_usernames');
  833. break;
  834. case 'screen_name' : $ban = $this->EE->config->item('banned_screen_names');
  835. break;
  836. }
  837. if ($ban == '')
  838. {
  839. return FALSE;
  840. }
  841. foreach (explode('|', $ban) as $val)
  842. {
  843. if ($val == '*') continue;
  844. if (substr($val, -1 == '*'))
  845. {
  846. $val = str_replace('*', '', $val);
  847. if (strncmp($match, $val, strlen($val)) == 0)
  848. {
  849. return TRUE;
  850. }
  851. }
  852. elseif (strncmp($val, '*', 1) == 0)
  853. {
  854. $val = str_replace('*', '', $val);
  855. if (substr($match, - strlen($val)) == $val)
  856. {
  857. return TRUE;
  858. }
  859. }
  860. elseif ($val == $match)
  861. {
  862. return TRUE;
  863. }
  864. }
  865. return FALSE;
  866. }
  867. // --------------------------------------------------------------------
  868. /**
  869. * Is the nation banned?
  870. */
  871. function nation_ban_check($show_error = TRUE)
  872. {
  873. if ($this->EE->config->item('require_ip_for_posting') != 'y' OR $this->EE->config->item('ip2nation') != 'y')
  874. {
  875. return;
  876. }
  877. $query = $this->EE->db->query("SELECT country FROM exp_ip2nation WHERE ip < INET_ATON('".$this->EE->db->escape_str($this->EE->input->ip_address())."') ORDER BY ip DESC LIMIT 0,1");
  878. if ($query->num_rows() == 1)
  879. {
  880. $result = $this->EE->db->query("SELECT COUNT(*) AS count FROM exp_ip2nation_countries WHERE code = '".$query->row('country') ."' AND banned = 'y'");
  881. if ($result->row('count') > 0)
  882. {
  883. if ($show_error == TRUE)
  884. return $this->EE->output->fatal_error($this->EE->config->item('ban_message'), 0);
  885. else
  886. return FALSE;
  887. }
  888. }
  889. }
  890. // --------------------------------------------------------------------
  891. /**
  892. * Delete old sessions if probability is met
  893. *
  894. * By default, the probablility is set to 10 percent.
  895. * That means sessions will only be deleted one
  896. * out of ten times a page is loaded.
  897. */
  898. function delete_old_sessions()
  899. {
  900. $expire = $this->EE->localize->now - $this->session_length;
  901. srand(time());
  902. if ((rand() % 100) < $this->gc_probability)
  903. {
  904. $this->EE->db->query("DELETE FROM exp_sessions WHERE last_activity < $expire");
  905. }
  906. }
  907. // --------------------------------------------------------------------
  908. /**
  909. * Save password lockout
  910. */
  911. function save_password_lockout($username = '')
  912. {
  913. if ($this->EE->config->item('password_lockout') == 'n')
  914. {
  915. return;
  916. }
  917. $data = array(
  918. 'login_date' => time(),
  919. 'ip_address' => $this->EE->input->ip_address(),
  920. 'user_agent' => $this->userdata['user_agent'],
  921. 'username' => $username
  922. );
  923. $this->EE->db->insert('password_lockout', $data);
  924. }
  925. // --------------------------------------------------------------------
  926. /**
  927. * Check password lockout
  928. */
  929. function check_password_lockout($username = '')
  930. {
  931. if ($this->EE->config->item('password_lockout') == 'n')
  932. {
  933. return FALSE;
  934. }
  935. if ($this->EE->config->item('password_lockout_interval') == '')
  936. {
  937. return FALSE;
  938. }
  939. $interval = $this->EE->config->item('password_lockout_interval') * 60;
  940. $expire = time() - $interval;
  941. $sql = "SELECT count(*) AS count
  942. FROM exp_password_lockout
  943. WHERE login_date > $expire
  944. AND ip_address = '".$this->EE->db->escape_str($this->EE->input->ip_address())."'
  945. AND (user_agent = '".$this->EE->db->escape_str($this->userdata['user_agent'])."'
  946. OR username = '".$this->EE->db->escape_str($username)."'
  947. )";
  948. $query = $this->EE->db->query($sql);
  949. if ($query->row('count') >= 4)
  950. {
  951. return TRUE;
  952. }
  953. else
  954. {
  955. return FALSE;
  956. }
  957. }
  958. // --------------------------------------------------------------------
  959. /**
  960. * Delete old password lockout data
  961. */
  962. function delete_password_lockout()
  963. {
  964. if ($this->EE->config->item('password_lockout') == 'n')
  965. {
  966. return FALSE;
  967. }
  968. $interval = $this->EE->config->item('password_lockout_interval') * 60;
  969. $expire = time() - $interval;
  970. srand(time());
  971. if ((rand() % 100) < $this->gc_probability)
  972. {
  973. $this->EE->db->query("DELETE FROM exp_password_lockout WHERE login_date < $expire");
  974. }
  975. }
  976. }
  977. // END CLASS
  978. /* End of file Session.php */
  979. /* Location: ./system/expressionengine/libraries/Session.php */