PluginProbe
ShiftController Employee Shift Scheduling / 4.9.66
ShiftController Employee Shift Scheduling v4.9.66
4.9.97 4.9.96 4.9.95 4.9.74 4.9.75 4.9.76 4.9.77 4.9.78 4.9.84 4.9.85 4.9.87 4.9.91 4.9.92 trunk 2.1.0 2.1.1 2.1.2 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 3.2.4 All 38 releases
shiftcontroller / hc3 / session.php

session.php in ShiftController Employee Shift Scheduling 4.9.66, at hc3/session.php

619 lines 15.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php if (! defined('ABSPATH')) exit; // Exit if accessed directly
2 interface HC3_Session_
3 {
4 public function getFlashdata( $key );
5 public function setFlashdata( $key, $value, $append = FALSE );
6
7 public function getUserdata( $key );
8 public function setUserdata( $key, $value, $append = FALSE );
9 public function unsetUserdata( $key );
10 }
11
12 class HC3_Session implements HC3_Session_
13 {
14 protected $_started = FALSE;
15
16 protected $_prefix = 'hitcode_';
17 protected $request = NULL;
18 protected $encrypt = NULL;
19
20 protected $encryption_key = NULL;
21
22 protected $sess_encrypt_cookie = FALSE;
23 protected $sess_expiration = 7200;
24 protected $sess_expire_on_close = FALSE;
25 protected $sess_match_ip = FALSE;
26 protected $sess_match_useragent = FALSE;
27 protected $sess_cookie_name = 'hc3_session';
28 protected $cookie_prefix = '';
29 protected $cookie_path = '';
30 protected $cookie_domain = '';
31 protected $cookie_secure = FALSE;
32 protected $sess_time_to_update = 300;
33 protected $flashdata_key = 'flash';
34 protected $time_reference = 'time';
35 protected $userdata = array();
36 protected $now;
37
38 protected $builtin_props = array(
39 'session_id',
40 'ip_address',
41 'user_agent',
42 'last_activity',
43 'user_data'
44 );
45
46 /**
47 * Session Constructor
48 *
49 * The constructor runs the session routines automatically
50 * whenever the class is instantiated.
51 */
52
53 public static function instance()
54 {
55 static $ret = NULL;
56 if( NULL === $ret ){
57 $ret = new static;
58 }
59 return $ret;
60 }
61
62 public static function start()
63 {
64 $sessionId = session_id();
65 if( ! $sessionId ){
66 $sessionOptions = array();
67 // $sessionOptions = array( 'read_and_close' => TRUE );
68 @session_start( $sessionOptions );
69 }
70 }
71
72 public function __construct( $prefix = 'shiftcontroller4' )
73 {
74 // $this->request = $request;
75 $this->_prefix = $prefix;
76
77 $this->encryption_key = md5(__FILE__);
78
79 static::start();
80
81 // Set the "now" time. Can either be GMT or server time, based on the
82 // config prefs. We use this to set the "last activity" time
83 $this->now = $this->_get_time();
84
85 // Set the session length. If the session expiration is
86 // set to zero we'll set the expiration two years from now.
87 if ($this->sess_expiration == 0){
88 $this->sess_expiration = (60*60*24*365*2);
89 }
90
91 // Set the cookie name
92 // $this->sess_cookie_name = $this->cookie_prefix . $this->sess_cookie_name . '_' . $this->_prefix;
93 $this->sess_cookie_name = $this->cookie_prefix . $this->sess_cookie_name;
94
95 // Run the Session routine. If a session doesn't exist we'll
96 // create a new one. If it does, we'll update it.
97 if ( ! $this->sess_read()){
98 $this->sess_create();
99 }
100 else {
101 $this->sess_update();
102 }
103
104 // Delete 'old' flashdata (from last request)
105 $this->_flashdata_sweep();
106
107 // Mark all new flashdata as old (data will be deleted before next request)
108 $this->_flashdata_mark();
109 }
110
111 // --------------------------------------------------------------------
112
113 /**
114 * Fetch the current session data if it exists
115 *
116 * @access public
117 * @return bool
118 */
119 function sess_read()
120 {
121 // Fetch the cookie
122 $session = array_key_exists($this->sess_cookie_name, $_COOKIE) ? $_COOKIE[$this->sess_cookie_name] : FALSE;
123
124 // No cookie? Goodbye cruel world!...
125 if ($session === FALSE)
126 {
127 // log_message('debug', 'A session cookie was not found.');
128 return FALSE;
129 }
130
131 // Decrypt the cookie data
132 if( $this->encrypt ){
133 $session = $this->encrypt->decode($session);
134 }
135 else {
136 // encryption was not used, so we need to check the md5 hash
137 $hash = substr($session, strlen($session)-32); // get last 32 chars
138 $session = substr($session, 0, strlen($session)-32);
139
140 // Does the md5 hash match? This is to prevent manipulation of session data in userspace
141 if ($hash !== md5($session.$this->encryption_key)){
142 // echo 'The session cookie data did not match what was expected. This could be a possible malicious attempt.';
143 $this->sess_destroy();
144 return FALSE;
145 }
146 }
147
148 // Unserialize the session array
149 $session = $this->_unserialize($session);
150
151 // Is the session data we unserialized an array with the correct format?
152 if ( ! is_array($session) OR ! isset($session['session_id']) OR ! isset($session['ip_address']) OR ! isset($session['user_agent']) OR ! isset($session['last_activity'])){
153 $this->sess_destroy();
154 return FALSE;
155 }
156
157 // Is the session current?
158 if (($session['last_activity'] + $this->sess_expiration) < $this->now){
159 $this->sess_destroy();
160 return FALSE;
161 }
162
163 // Session is valid!
164 $this->userdata = $session;
165 unset($session);
166
167 return TRUE;
168 }
169
170 // --------------------------------------------------------------------
171
172 /**
173 * Write the session data
174 *
175 * @access public
176 * @return void
177 */
178 function sess_write()
179 {
180 $this->_set_cookie();
181 }
182
183 // --------------------------------------------------------------------
184
185 /**
186 * Create a new session
187 *
188 * @access public
189 * @return void
190 */
191 function sess_create()
192 {
193 $sessid = '';
194 while (strlen($sessid) < 32){
195 $sessid .= mt_rand(0, mt_getrandmax());
196 }
197
198 // To make the session ID even more secure we'll combine it with the user's IP
199 // $sessid .= $this->request->getIpAddress();
200
201 $this->userdata = array(
202 'session_id' => md5(uniqid($sessid, TRUE)),
203 // 'ip_address' => $this->request->getIpAddress(),
204 // 'user_agent' => substr($this->request->getUserAgent(), 0, 120),
205 'last_activity' => $this->now,
206 'user_data' => ''
207 );
208
209 // Write the cookie
210 $this->_set_cookie();
211 }
212
213 // --------------------------------------------------------------------
214
215 /**
216 * Update an existing session
217 *
218 * @access public
219 * @return void
220 */
221 function sess_update()
222 {
223 // We only update the session every five minutes by default
224 if (($this->userdata['last_activity'] + $this->sess_time_to_update) >= $this->now)
225 {
226 return;
227 }
228
229 // Save the old session id so we know which record to
230 // update in the database if we need it
231 $old_sessid = $this->userdata['session_id'];
232 $new_sessid = '';
233 while (strlen($new_sessid) < 32)
234 {
235 $new_sessid .= mt_rand(0, mt_getrandmax());
236 }
237
238 // To make the session ID even more secure we'll combine it with the user's IP
239 // $new_sessid .= $this->request->getIpAddress();
240
241 // Turn it into a hash
242 $new_sessid = md5(uniqid($new_sessid, TRUE));
243
244 // Update the session data in the session data array
245 $this->userdata['session_id'] = $new_sessid;
246 $this->userdata['last_activity'] = $this->now;
247
248 // _set_cookie() will handle this for us if we aren't using database sessions
249 // by pushing all userdata to the cookie.
250 $cookie_data = NULL;
251
252 // Write the cookie
253 $this->_set_cookie($cookie_data);
254 }
255
256 // --------------------------------------------------------------------
257
258 /**
259 * Destroy the current session
260 *
261 * @access public
262 * @return void
263 */
264 function sess_destroy()
265 {
266 // Kill the cookie
267 @setcookie(
268 $this->sess_cookie_name,
269 // addslashes(serialize(array())),
270 addslashes(json_encode(array())),
271 ($this->now - 31500000),
272 $this->cookie_path,
273 $this->cookie_domain,
274 0
275 );
276
277 // Kill session data
278 $this->userdata = array();
279 }
280
281 public function getUserdata($item)
282 {
283 if( function_exists('get_user_meta') && function_exists('get_current_user_id') && ($currentUserId = get_current_user_id()) ){
284 $prefix = $this->getPrefix();
285 $userMetaName = $prefix . $item;
286 return get_user_meta( $currentUserId, $userMetaName, true );
287 }
288 else {
289 $my_key = $this->getPrefix() . $item;
290 if( isset($_SESSION[$my_key]) ){
291 return $_SESSION[$my_key];
292 }
293 return ( ! isset($this->userdata[$item])) ? FALSE : $this->userdata[$item];
294 }
295 }
296
297 // --------------------------------------------------------------------
298
299 /**
300 * Fetch all session data
301 *
302 * @access public
303 * @return array
304 */
305 function all_userdata()
306 {
307 $ret = array();
308 if( ! isset($_SESSION) ) return $ret;
309
310 $prefix = $this->getPrefix();
311
312 /* get flash data we store in _SESSION */
313 foreach( $_SESSION as $key => $v ){
314 if( ! (substr($key, 0, strlen($prefix)) == $prefix) )
315 continue;
316 $my_key = substr($key, strlen($prefix) );
317 $ret[ $my_key ] = $v;
318 }
319
320 $parent_ret = $this->userdata;
321 $ret = array_merge( $ret, $parent_ret );
322 return $ret;
323 }
324
325 public function getPrefix()
326 {
327 $ret = $this->_prefix;
328
329 $isWpAdmin = FALSE;
330
331 if( defined('WPINC') && is_admin() ){
332 $isWpAdmin = TRUE;
333 }
334 else {
335 if( isset($_GET['hca']) && ('admin' == substr($_GET['hca'], 0, strlen('admin'))) ){
336 $isWpAdmin = TRUE;
337 }
338 }
339
340 if( $isWpAdmin ){
341 $ret .= '_wpadmin_';
342 }
343
344 return $ret;
345 }
346
347 public function setUserdata( $key, $value, $append = FALSE )
348 {
349 // use user meta
350 if( function_exists('update_user_meta') && function_exists('get_current_user_id') && ($currentUserId = get_current_user_id()) ){
351 $prefix = $this->getPrefix();
352 $userMetaName = $prefix . $key;
353 update_user_meta( $currentUserId, $userMetaName, $value );
354 }
355 else {
356 static::start();
357 $prefix = $this->getPrefix();
358
359 $newdata = array( $key => $value );
360
361 $parent_newdata = array();
362 if (count($newdata) > 0){
363 $parent_newdata = array();
364 foreach ($newdata as $key => $val){
365 if( ! in_array($key, $this->builtin_props) ){
366 $my_key = $prefix . $key;
367 if( $append ){
368 if( ! isset($_SESSION[$my_key]) )
369 $_SESSION[$my_key] = array();
370 if( ! is_array($_SESSION[$my_key]) )
371 $_SESSION[$my_key] = array( $_SESSION[$my_key] );
372 $_SESSION[$my_key][] = $val;
373 }
374 else {
375 $_SESSION[$my_key] = $val;
376 }
377 }
378 else {
379 $parent_newdata[ $key ] = $val;
380 }
381 }
382 }
383
384 if( $parent_newdata ){
385 if (count($parent_newdata) > 0){
386 foreach( $parent_newdata as $key => $val){
387 $this->userdata[$key] = $val;
388 }
389 }
390 $this->sess_write();
391 }
392 }
393
394 return $this;
395 }
396
397 // --------------------------------------------------------------------
398
399 /**
400 * Delete a session variable from the "userdata" array
401 *
402 * @access array
403 * @return void
404 */
405 public function unsetUserdata( $key )
406 {
407 if( function_exists('delete_user_meta') && function_exists('get_current_user_id') && ($currentUserId = get_current_user_id()) ){
408 $prefix = $this->getPrefix();
409 $userMetaName = $prefix . $key;
410 delete_user_meta( $currentUserId, $userMetaName );
411 }
412 else {
413 static::start();
414 $parent_newdata = array();
415
416 if( ! in_array($key, $this->builtin_props) ){
417 $my_key = $this->getPrefix() . $key;
418 unset($_SESSION[$my_key]);
419 }
420 else {
421 $parent_newdata[ $key ] = $val;
422 }
423
424 if( $parent_newdata ){
425 foreach ($parent_newdata as $key => $val){
426 unset($this->userdata[$key]);
427 }
428 $this->sess_write();
429 }
430 }
431
432 return $this;
433 }
434
435 public function setFlashdata( $name, $value, $append = FALSE )
436 {
437 // use transients
438 if( function_exists('set_transient') && function_exists('get_current_user_id') && ($currentUserId = get_current_user_id()) ){
439 $prefix = $this->getPrefix();
440 $prefix = $prefix . $currentUserId . '_';
441 $transientName = $prefix . $name;
442 set_transient( $transientName, $value, 60 );
443 }
444 else {
445 $newdata = array( $name => $value );
446 foreach( $newdata as $key => $val ){
447 $flashdata_key = $this->flashdata_key.':new:'.$key;
448 $this->setUserdata( $flashdata_key, $val, $append );
449 }
450 }
451
452 return $this;
453 }
454
455 function getFlashdata( $key )
456 {
457 static $cache = array();
458 if( array_key_exists($key, $cache) ){
459 return $cache[$key];
460 }
461
462 if( function_exists('get_transient') && function_exists('get_current_user_id') && ($currentUserId = get_current_user_id()) ){
463 $prefix = $this->getPrefix();
464 $prefix = $prefix . $currentUserId . '_';
465 $transientName = $prefix . $key;
466 $ret = get_transient( $transientName );
467 delete_transient( $transientName );
468 }
469 else {
470 $flashdata_key = $this->flashdata_key.':old:'.$key;
471 $ret = $this->getUserdata($flashdata_key);
472 }
473
474 $cache[ $key ] = $ret;
475 return $ret;
476 }
477
478 // ------------------------------------------------------------------------
479
480 /**
481 * Identifies flashdata as 'old' for removal
482 * when _flashdata_sweep() runs.
483 *
484 * @access private
485 * @return void
486 */
487 protected function _flashdata_mark()
488 {
489 $userdata = $this->all_userdata();
490 foreach ($userdata as $name => $value)
491 {
492 $parts = explode(':new:', $name);
493 if (is_array($parts) && count($parts) === 2)
494 {
495 $new_name = $this->flashdata_key.':old:'.$parts[1];
496 $this->setUserdata($new_name, $value);
497 $this->unsetUserdata($name);
498 }
499 }
500 }
501
502 // ------------------------------------------------------------------------
503
504 /**
505 * Removes all flashdata marked as 'old'
506 *
507 * @access private
508 * @return void
509 */
510
511 protected function _flashdata_sweep()
512 {
513 $userdata = $this->all_userdata();
514 foreach ($userdata as $key => $value){
515 if (strpos($key, ':old:')){
516 $this->unsetUserdata($key);
517 }
518 }
519 }
520
521 protected function _get_time()
522 {
523 if (strtolower($this->time_reference) == 'gmt'){
524 $now = time();
525 $time = mktime(gmdate("H", $now), gmdate("i", $now), gmdate("s", $now), gmdate("m", $now), gmdate("d", $now), gmdate("Y", $now));
526 }
527 else {
528 $time = time();
529 }
530
531 return $time;
532 }
533
534 // --------------------------------------------------------------------
535
536 /**
537 * Write the session cookie
538 *
539 * @access public
540 * @return void
541 */
542 function _set_cookie($cookie_data = NULL)
543 {
544 if (is_null($cookie_data)){
545 $cookie_data = $this->userdata;
546 }
547
548 // Serialize the userdata for the cookie
549 $cookie_data = $this->_serialize($cookie_data);
550
551 if( $this->encrypt ){
552 $cookie_data = $this->encrypt->encode($cookie_data);
553 }
554 else {
555 // if encryption is not used, we provide an md5 hash to prevent userside tampering
556 $cookie_data = $cookie_data.md5($cookie_data.$this->encryption_key);
557 }
558
559 $expire = ($this->sess_expire_on_close === TRUE) ? 0 : $this->sess_expiration + time();
560 // Set the cookie
561 @setcookie(
562 $this->sess_cookie_name,
563 $cookie_data,
564 $expire,
565 $this->cookie_path,
566 $this->cookie_domain,
567 $this->cookie_secure
568 );
569 }
570
571 protected function _serialize($data)
572 {
573 if (is_array($data)){
574 foreach ($data as $key => $val){
575 if (is_string($val)){
576 $data[$key] = str_replace('\\', '{{slash}}', $val);
577 }
578 }
579 }
580 else {
581 if (is_string($data)){
582 $data = str_replace('\\', '{{slash}}', $data);
583 }
584 }
585 // return serialize($data);
586 $ret = json_encode( $data );
587 return $ret;
588 }
589
590 protected function _unserialize($data)
591 {
592 // $data = @unserialize( $this->strip_slashes($data) );
593 $data = @json_decode( $this->strip_slashes($data), true );
594
595 if (is_array($data)){
596 foreach ($data as $key => $val){
597 if (is_string($val)){
598 $data[$key] = str_replace('{{slash}}', '\\', $val);
599 }
600 }
601 return $data;
602 }
603
604 return (is_string($data)) ? str_replace('{{slash}}', '\\', $data) : $data;
605 }
606
607 function strip_slashes($str)
608 {
609 if (is_array($str)){
610 foreach ($str as $key => $val){
611 $str[$key] = $this->strip_slashes($val);
612 }
613 }
614 else {
615 $str = stripslashes($str);
616 }
617 return $str;
618 }
619 }