PluginProbe
ShiftController Employee Shift Scheduling / 4.9.85
ShiftController Employee Shift Scheduling v4.9.85
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.85, at hc3/session.php

644 lines 16.2 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 // --------------------------------------------------------------------
282
283 /**
284 * Fetch all session data
285 *
286 * @access public
287 * @return array
288 */
289 function all_userdata()
290 {
291 $ret = array();
292 if( ! isset($_SESSION) ) return $ret;
293
294 $prefix = $this->getPrefix();
295
296 /* get flash data we store in _SESSION */
297 foreach( $_SESSION as $key => $v ){
298 if( ! (substr($key, 0, strlen($prefix)) == $prefix) )
299 continue;
300 $my_key = substr($key, strlen($prefix) );
301 $ret[ $my_key ] = $v;
302 }
303
304 $parent_ret = $this->userdata;
305 $ret = array_merge( $ret, $parent_ret );
306 return $ret;
307 }
308
309 public function getPrefix()
310 {
311 $ret = $this->_prefix;
312
313 $isWpAdmin = FALSE;
314
315 if( defined('WPINC') && is_admin() ){
316 $isWpAdmin = TRUE;
317 }
318 else {
319 if( isset($_GET['hca']) && ('admin' == substr($_GET['hca'], 0, strlen('admin'))) ){
320 $isWpAdmin = TRUE;
321 }
322 }
323
324 if( $isWpAdmin ){
325 $ret .= '_wpadmin_';
326 }
327
328 return $ret;
329 }
330
331 public function getUserdata($item)
332 {
333 if( function_exists('get_user_meta') && function_exists('get_current_user_id') && ($currentUserId = get_current_user_id()) ){
334 $prefix = $this->getPrefix();
335
336 if( ( false === strpos($prefix, '_wpadmin_')) && ('scheduleView' == substr($item, 0, strlen('scheduleView'))) ){
337 if( function_exists('get_the_ID') ){
338 $pageId = get_the_ID();
339 $prefix .= '_' . $pageId . '_';
340 }
341 }
342
343 $userMetaName = $prefix . $item;
344 // echo "GET USER DATA '$item' AS META '$userMetaName'<br>";
345 return get_user_meta( $currentUserId, $userMetaName, true );
346 }
347 else {
348 $my_key = $this->getPrefix() . $item;
349 if( isset($_SESSION[$my_key]) ){
350 return $_SESSION[$my_key];
351 }
352 return ( ! isset($this->userdata[$item])) ? FALSE : $this->userdata[$item];
353 }
354 }
355
356 public function setUserdata( $key, $value, $append = FALSE )
357 {
358 // use user meta
359 if( function_exists('update_user_meta') && function_exists('get_current_user_id') && ($currentUserId = get_current_user_id()) ){
360 $prefix = $this->getPrefix();
361
362 if( ( false === strpos($prefix, '_wpadmin_')) && ('scheduleView' == substr($key, 0, strlen('scheduleView'))) ){
363 if( function_exists('get_the_ID') ){
364 $pageId = get_the_ID();
365 $prefix .= '_' . $pageId . '_';
366 }
367 }
368
369 $userMetaName = $prefix . $key;
370 update_user_meta( $currentUserId, $userMetaName, $value );
371 }
372 else {
373 static::start();
374 $prefix = $this->getPrefix();
375
376 $newdata = array( $key => $value );
377
378 $parent_newdata = array();
379 if (count($newdata) > 0){
380 $parent_newdata = array();
381 foreach ($newdata as $key => $val){
382 if( ! in_array($key, $this->builtin_props) ){
383 $my_key = $prefix . $key;
384 if( $append ){
385 if( ! isset($_SESSION[$my_key]) )
386 $_SESSION[$my_key] = array();
387 if( ! is_array($_SESSION[$my_key]) )
388 $_SESSION[$my_key] = array( $_SESSION[$my_key] );
389 $_SESSION[$my_key][] = $val;
390 }
391 else {
392 $_SESSION[$my_key] = $val;
393 }
394 }
395 else {
396 $parent_newdata[ $key ] = $val;
397 }
398 }
399 }
400
401 if( $parent_newdata ){
402 if (count($parent_newdata) > 0){
403 foreach( $parent_newdata as $key => $val){
404 $this->userdata[$key] = $val;
405 }
406 }
407 $this->sess_write();
408 }
409 }
410
411 return $this;
412 }
413
414 // --------------------------------------------------------------------
415
416 /**
417 * Delete a session variable from the "userdata" array
418 *
419 * @access array
420 * @return void
421 */
422 public function unsetUserdata( $key )
423 {
424 if( function_exists('delete_user_meta') && function_exists('get_current_user_id') && ($currentUserId = get_current_user_id()) ){
425 $prefix = $this->getPrefix();
426
427 if( ( false === strpos($prefix, '_wpadmin_')) && ('scheduleView' == substr($key, 0, strlen('scheduleView'))) ){
428 if( function_exists('get_the_ID') ){
429 $pageId = get_the_ID();
430 $prefix .= '_' . $pageId . '_';
431 }
432 }
433
434 $userMetaName = $prefix . $key;
435 delete_user_meta( $currentUserId, $userMetaName );
436 }
437 else {
438 static::start();
439 $parent_newdata = array();
440
441 if( ! in_array($key, $this->builtin_props) ){
442 $my_key = $this->getPrefix() . $key;
443 unset($_SESSION[$my_key]);
444 }
445 else {
446 $parent_newdata[ $key ] = $val;
447 }
448
449 if( $parent_newdata ){
450 foreach ($parent_newdata as $key => $val){
451 unset($this->userdata[$key]);
452 }
453 $this->sess_write();
454 }
455 }
456
457 return $this;
458 }
459
460 public function setFlashdata( $name, $value, $append = FALSE )
461 {
462 // use transients
463 if( function_exists('set_transient') && function_exists('get_current_user_id') && ($currentUserId = get_current_user_id()) ){
464 $prefix = $this->getPrefix();
465 $prefix = $prefix . $currentUserId . '_';
466 $transientName = $prefix . $name;
467 set_transient( $transientName, $value, 60 );
468 }
469 else {
470 $newdata = array( $name => $value );
471 foreach( $newdata as $key => $val ){
472 $flashdata_key = $this->flashdata_key.':new:'.$key;
473 $this->setUserdata( $flashdata_key, $val, $append );
474 }
475 }
476
477 return $this;
478 }
479
480 function getFlashdata( $key )
481 {
482 static $cache = array();
483 if( array_key_exists($key, $cache) ){
484 return $cache[$key];
485 }
486
487 if( function_exists('get_transient') && function_exists('get_current_user_id') && ($currentUserId = get_current_user_id()) ){
488 $prefix = $this->getPrefix();
489 $prefix = $prefix . $currentUserId . '_';
490 $transientName = $prefix . $key;
491 $ret = get_transient( $transientName );
492 delete_transient( $transientName );
493 }
494 else {
495 $flashdata_key = $this->flashdata_key.':old:'.$key;
496 $ret = $this->getUserdata($flashdata_key);
497 }
498
499 $cache[ $key ] = $ret;
500 return $ret;
501 }
502
503 // ------------------------------------------------------------------------
504
505 /**
506 * Identifies flashdata as 'old' for removal
507 * when _flashdata_sweep() runs.
508 *
509 * @access private
510 * @return void
511 */
512 protected function _flashdata_mark()
513 {
514 $userdata = $this->all_userdata();
515 foreach ($userdata as $name => $value)
516 {
517 $parts = explode(':new:', $name);
518 if (is_array($parts) && count($parts) === 2)
519 {
520 $new_name = $this->flashdata_key.':old:'.$parts[1];
521 $this->setUserdata($new_name, $value);
522 $this->unsetUserdata($name);
523 }
524 }
525 }
526
527 // ------------------------------------------------------------------------
528
529 /**
530 * Removes all flashdata marked as 'old'
531 *
532 * @access private
533 * @return void
534 */
535
536 protected function _flashdata_sweep()
537 {
538 $userdata = $this->all_userdata();
539 foreach ($userdata as $key => $value){
540 if (strpos($key, ':old:')){
541 $this->unsetUserdata($key);
542 }
543 }
544 }
545
546 protected function _get_time()
547 {
548 if (strtolower($this->time_reference) == 'gmt'){
549 $now = time();
550 $time = mktime(gmdate("H", $now), gmdate("i", $now), gmdate("s", $now), gmdate("m", $now), gmdate("d", $now), gmdate("Y", $now));
551 }
552 else {
553 $time = time();
554 }
555
556 return $time;
557 }
558
559 // --------------------------------------------------------------------
560
561 /**
562 * Write the session cookie
563 *
564 * @access public
565 * @return void
566 */
567 function _set_cookie($cookie_data = NULL)
568 {
569 if (is_null($cookie_data)){
570 $cookie_data = $this->userdata;
571 }
572
573 // Serialize the userdata for the cookie
574 $cookie_data = $this->_serialize($cookie_data);
575
576 if( $this->encrypt ){
577 $cookie_data = $this->encrypt->encode($cookie_data);
578 }
579 else {
580 // if encryption is not used, we provide an md5 hash to prevent userside tampering
581 $cookie_data = $cookie_data.md5($cookie_data.$this->encryption_key);
582 }
583
584 $expire = ($this->sess_expire_on_close === TRUE) ? 0 : $this->sess_expiration + time();
585 // Set the cookie
586 @setcookie(
587 $this->sess_cookie_name,
588 $cookie_data,
589 $expire,
590 $this->cookie_path,
591 $this->cookie_domain,
592 $this->cookie_secure
593 );
594 }
595
596 protected function _serialize($data)
597 {
598 if (is_array($data)){
599 foreach ($data as $key => $val){
600 if (is_string($val)){
601 $data[$key] = str_replace('\\', '{{slash}}', $val);
602 }
603 }
604 }
605 else {
606 if (is_string($data)){
607 $data = str_replace('\\', '{{slash}}', $data);
608 }
609 }
610 // return serialize($data);
611 $ret = json_encode( $data );
612 return $ret;
613 }
614
615 protected function _unserialize($data)
616 {
617 // $data = @unserialize( $this->strip_slashes($data) );
618 $data = @json_decode( $this->strip_slashes($data), true );
619
620 if (is_array($data)){
621 foreach ($data as $key => $val){
622 if (is_string($val)){
623 $data[$key] = str_replace('{{slash}}', '\\', $val);
624 }
625 }
626 return $data;
627 }
628
629 return (is_string($data)) ? str_replace('{{slash}}', '\\', $data) : $data;
630 }
631
632 function strip_slashes($str)
633 {
634 if (is_array($str)){
635 foreach ($str as $key => $val){
636 $str[$key] = $this->strip_slashes($val);
637 }
638 }
639 else {
640 $str = stripslashes($str);
641 }
642 return $str;
643 }
644 }