Mercurial > hg > rc2
annotate program/lib/Roundcube/rcube_session.php @ 17:dd5ed6ef69c9
Slowly cleaning up more php8 Warnings/deprecations
| author | Charlie Root |
|---|---|
| date | Mon, 06 Oct 2025 12:20:32 -0400 |
| parents | 4681f974d28b |
| children | b6a96bdd6b29 |
| rev | line source |
|---|---|
| 0 | 1 <?php |
| 2 | |
| 3 /** | |
| 4 +-----------------------------------------------------------------------+ | |
| 5 | This file is part of the Roundcube Webmail client | | |
| 6 | Copyright (C) 2005-2014, The Roundcube Dev Team | | |
| 7 | Copyright (C) 2011, Kolab Systems AG | | |
| 8 | | | |
| 9 | Licensed under the GNU General Public License version 3 or | | |
| 10 | any later version with exceptions for skins & plugins. | | |
| 11 | See the README file for a full license statement. | | |
| 12 | | | |
| 13 | PURPOSE: | | |
| 14 | Provide database supported session management | | |
| 15 +-----------------------------------------------------------------------+ | |
| 16 | Author: Thomas Bruederli <roundcube@gmail.com> | | |
| 17 | Author: Aleksander Machniak <alec@alec.pl> | | |
| 18 | Author: Cor Bosman <cor@roundcu.be> | | |
| 19 +-----------------------------------------------------------------------+ | |
| 20 */ | |
| 21 | |
| 22 /** | |
| 23 * Abstract class to provide database supported session storage | |
| 24 * | |
| 25 * @package Framework | |
| 26 * @subpackage Core | |
| 27 * @author Thomas Bruederli <roundcube@gmail.com> | |
| 28 * @author Aleksander Machniak <alec@alec.pl> | |
| 29 */ | |
| 30 abstract class rcube_session | |
| 31 { | |
| 32 protected $config; | |
| 33 protected $key; | |
| 34 protected $ip; | |
| 35 protected $changed; | |
| 36 protected $start; | |
| 37 protected $vars; | |
| 38 protected $now; | |
|
17
dd5ed6ef69c9
Slowly cleaning up more php8 Warnings/deprecations
Charlie Root
parents:
0
diff
changeset
|
39 protected $cookie; |
|
dd5ed6ef69c9
Slowly cleaning up more php8 Warnings/deprecations
Charlie Root
parents:
0
diff
changeset
|
40 protected $lifetime; |
| 0 | 41 protected $time_diff = 0; |
| 42 protected $reloaded = false; | |
| 43 protected $appends = array(); | |
| 44 protected $unsets = array(); | |
| 45 protected $gc_enabled = 0; | |
| 46 protected $gc_handlers = array(); | |
| 47 protected $cookiename = 'roundcube_sessauth'; | |
| 48 protected $ip_check = false; | |
| 49 protected $logging = false; | |
| 50 | |
| 51 | |
| 52 /** | |
| 53 * Blocks session data from being written to database. | |
| 54 * Can be used if write-race conditions are to be expected | |
| 55 * @var boolean | |
| 56 */ | |
| 57 public $nowrite = false; | |
| 58 | |
| 59 /** | |
| 60 * Factory, returns driver-specific instance of the class | |
| 61 * | |
| 62 * @param object $config | |
| 63 * @return Object rcube_session | |
| 64 */ | |
| 65 public static function factory($config) | |
| 66 { | |
| 67 // get session storage driver | |
| 68 $storage = $config->get('session_storage', 'db'); | |
| 69 | |
| 70 // class name for this storage | |
| 71 $class = "rcube_session_" . $storage; | |
| 72 | |
| 73 // try to instantiate class | |
| 74 if (class_exists($class)) { | |
| 75 return new $class($config); | |
| 76 } | |
| 77 | |
| 78 // no storage found, raise error | |
| 79 rcube::raise_error(array('code' => 604, 'type' => 'session', | |
| 80 'line' => __LINE__, 'file' => __FILE__, | |
| 81 'message' => "Failed to find session driver. Check session_storage config option"), | |
| 82 true, true); | |
| 83 } | |
| 84 | |
| 85 /** | |
| 86 * @param Object $config | |
| 87 */ | |
| 88 public function __construct($config) | |
| 89 { | |
| 90 $this->config = $config; | |
| 91 | |
| 92 // set ip check | |
| 93 $this->set_ip_check($this->config->get('ip_check')); | |
| 94 | |
| 95 // set cookie name | |
| 96 if ($this->config->get('session_auth_name')) { | |
| 97 $this->set_cookiename($this->config->get('session_auth_name')); | |
| 98 } | |
| 99 } | |
| 100 | |
| 101 /** | |
| 102 * register session handler | |
| 103 */ | |
| 104 public function register_session_handler() | |
| 105 { | |
| 106 ini_set('session.serialize_handler', 'php'); | |
| 107 | |
| 108 // set custom functions for PHP session management | |
| 109 session_set_save_handler( | |
| 110 array($this, 'open'), | |
| 111 array($this, 'close'), | |
| 112 array($this, 'read'), | |
| 113 array($this, 'sess_write'), | |
| 114 array($this, 'destroy'), | |
| 115 array($this, 'gc') | |
| 116 ); | |
| 117 } | |
| 118 | |
| 119 /** | |
| 120 * Wrapper for session_start() | |
| 121 */ | |
| 122 public function start() | |
| 123 { | |
| 124 $this->start = microtime(true); | |
| 125 $this->ip = rcube_utils::remote_addr(); | |
| 126 $this->logging = $this->config->get('log_session', false); | |
| 127 | |
| 128 $lifetime = $this->config->get('session_lifetime', 1) * 60; | |
| 129 $this->set_lifetime($lifetime); | |
| 130 | |
| 131 session_start(); | |
| 132 } | |
| 133 | |
| 134 /** | |
| 135 * Abstract methods should be implemented by driver classes | |
| 136 */ | |
| 137 abstract function open($save_path, $session_name); | |
| 138 abstract function close(); | |
| 139 abstract function destroy($key); | |
| 140 abstract function read($key); | |
| 141 abstract function write($key, $vars); | |
| 142 abstract function update($key, $newvars, $oldvars); | |
| 143 | |
| 144 /** | |
| 145 * session write handler. This calls the implementation methods for write/update after some initial checks. | |
| 146 * | |
| 147 * @param $key | |
| 148 * @param $vars | |
| 149 * | |
| 150 * @return bool | |
| 151 */ | |
| 152 public function sess_write($key, $vars) | |
| 153 { | |
| 154 if ($this->nowrite) { | |
| 155 return true; | |
| 156 } | |
| 157 | |
| 158 // check cache | |
| 159 $oldvars = $this->get_cache($key); | |
| 160 | |
| 161 // if there are cached vars, update store, else insert new data | |
| 162 if ($oldvars) { | |
| 163 $newvars = $this->_fixvars($vars, $oldvars); | |
| 164 return $this->update($key, $newvars, $oldvars); | |
| 165 } | |
| 166 else { | |
| 167 return $this->write($key, $vars); | |
| 168 } | |
| 169 } | |
| 170 | |
| 171 /** | |
| 172 * Wrapper for session_write_close() | |
| 173 */ | |
| 174 public function write_close() | |
| 175 { | |
| 176 session_write_close(); | |
| 177 | |
| 178 // write_close() is called on script shutdown, see rcube::shutdown() | |
| 179 // execute cleanup functionality if enabled by session gc handler | |
| 180 // we do this after closing the session for better performance | |
| 181 $this->gc_shutdown(); | |
| 182 } | |
| 183 | |
| 184 /** | |
| 185 * Creates a new (separate) session | |
| 186 * | |
| 187 * @param array Session data | |
| 188 * | |
| 189 * @return string Session identifier (on success) | |
| 190 */ | |
| 191 public function create($data) | |
| 192 { | |
| 193 $length = strlen(session_id()); | |
| 194 $key = rcube_utils::random_bytes($length); | |
| 195 | |
| 196 // create new session | |
| 197 if ($this->write($key, $this->serialize($data))) { | |
| 198 return $key; | |
| 199 } | |
| 200 } | |
| 201 | |
| 202 /** | |
| 203 * Merge vars with old vars and apply unsets | |
| 204 */ | |
| 205 protected function _fixvars($vars, $oldvars) | |
| 206 { | |
| 207 if ($oldvars !== null) { | |
| 208 $a_oldvars = $this->unserialize($oldvars); | |
| 209 if (is_array($a_oldvars)) { | |
| 210 // remove unset keys on oldvars | |
| 211 foreach ((array)$this->unsets as $var) { | |
| 212 if (isset($a_oldvars[$var])) { | |
| 213 unset($a_oldvars[$var]); | |
| 214 } | |
| 215 else { | |
| 216 $path = explode('.', $var); | |
| 217 $k = array_pop($path); | |
| 218 $node = &$this->get_node($path, $a_oldvars); | |
| 219 unset($node[$k]); | |
| 220 } | |
| 221 } | |
| 222 | |
| 223 $newvars = $this->serialize(array_merge( | |
| 224 (array)$a_oldvars, (array)$this->unserialize($vars))); | |
| 225 } | |
| 226 else { | |
| 227 $newvars = $vars; | |
| 228 } | |
| 229 } | |
| 230 | |
| 231 $this->unsets = array(); | |
| 232 return $newvars; | |
| 233 } | |
| 234 | |
| 235 /** | |
| 236 * Execute registered garbage collector routines | |
| 237 */ | |
| 238 public function gc($maxlifetime) | |
| 239 { | |
| 240 // move gc execution to the script shutdown function | |
| 241 // see rcube::shutdown() and rcube_session::write_close() | |
| 242 $this->gc_enabled = $maxlifetime; | |
| 243 | |
| 244 return true; | |
| 245 } | |
| 246 | |
| 247 /** | |
| 248 * Register additional garbage collector functions | |
| 249 * | |
| 250 * @param mixed Callback function | |
| 251 */ | |
| 252 public function register_gc_handler($func) | |
| 253 { | |
| 254 foreach ($this->gc_handlers as $handler) { | |
| 255 if ($handler == $func) { | |
| 256 return; | |
| 257 } | |
| 258 } | |
| 259 | |
| 260 $this->gc_handlers[] = $func; | |
| 261 } | |
| 262 | |
| 263 /** | |
| 264 * Garbage collector handler to run on script shutdown | |
| 265 */ | |
| 266 protected function gc_shutdown() | |
| 267 { | |
| 268 if ($this->gc_enabled) { | |
| 269 foreach ($this->gc_handlers as $fct) { | |
| 270 call_user_func($fct); | |
| 271 } | |
| 272 } | |
| 273 } | |
| 274 | |
| 275 /** | |
| 276 * Generate and set new session id | |
| 277 * | |
| 278 * @param boolean $destroy If enabled the current session will be destroyed | |
| 279 * @return bool | |
| 280 */ | |
| 281 public function regenerate_id($destroy=true) | |
| 282 { | |
| 283 session_regenerate_id($destroy); | |
| 284 | |
| 285 $this->vars = null; | |
| 286 $this->key = session_id(); | |
| 287 | |
| 288 return true; | |
| 289 } | |
| 290 | |
| 291 /** | |
| 292 * See if we have vars of this key already cached, and if so, return them. | |
| 293 * | |
| 294 * @param string $key Session ID | |
| 295 * | |
| 296 * @return string | |
| 297 */ | |
| 298 protected function get_cache($key) | |
| 299 { | |
| 300 // no session data in cache (read() returns false) | |
| 301 if (!$this->key) { | |
| 302 $cache = null; | |
| 303 } | |
| 304 // use internal data for fast requests (up to 0.5 sec.) | |
| 305 else if ($key == $this->key && (!$this->vars || $ts - $this->start < 0.5)) { | |
| 306 $cache = $this->vars; | |
| 307 } | |
| 308 else { // else read data again | |
| 309 $cache = $this->read($key); | |
| 310 } | |
| 311 | |
| 312 return $cache; | |
| 313 } | |
| 314 | |
| 315 /** | |
| 316 * Append the given value to the certain node in the session data array | |
| 317 * | |
| 318 * Warning: Do not use if you already modified $_SESSION in the same request (#1490608) | |
| 319 * | |
| 320 * @param string Path denoting the session variable where to append the value | |
| 321 * @param string Key name under which to append the new value (use null for appending to an indexed list) | |
| 322 * @param mixed Value to append to the session data array | |
| 323 */ | |
| 324 public function append($path, $key, $value) | |
| 325 { | |
| 326 // re-read session data from DB because it might be outdated | |
| 327 if (!$this->reloaded && microtime(true) - $this->start > 0.5) { | |
| 328 $this->reload(); | |
| 329 $this->reloaded = true; | |
| 330 $this->start = microtime(true); | |
| 331 } | |
| 332 | |
| 333 $node = &$this->get_node(explode('.', $path), $_SESSION); | |
| 334 | |
| 335 if ($key !== null) { | |
| 336 $node[$key] = $value; | |
| 337 $path .= '.' . $key; | |
| 338 } | |
| 339 else { | |
| 340 $node[] = $value; | |
| 341 } | |
| 342 | |
| 343 $this->appends[] = $path; | |
| 344 | |
| 345 // when overwriting a previously unset variable | |
| 346 if ($this->unsets[$path]) { | |
| 347 unset($this->unsets[$path]); | |
| 348 } | |
| 349 } | |
| 350 | |
| 351 /** | |
| 352 * Unset a session variable | |
| 353 * | |
| 354 * @param string Variable name (can be a path denoting a certain node in the session array, e.g. compose.attachments.5) | |
| 355 * @return boolean True on success | |
| 356 */ | |
| 357 public function remove($var=null) | |
| 358 { | |
| 359 if (empty($var)) { | |
| 360 return $this->destroy(session_id()); | |
| 361 } | |
| 362 | |
| 363 $this->unsets[] = $var; | |
| 364 | |
| 365 if (isset($_SESSION[$var])) { | |
| 366 unset($_SESSION[$var]); | |
| 367 } | |
| 368 else { | |
| 369 $path = explode('.', $var); | |
| 370 $key = array_pop($path); | |
| 371 $node = &$this->get_node($path, $_SESSION); | |
| 372 unset($node[$key]); | |
| 373 } | |
| 374 | |
| 375 return true; | |
| 376 } | |
| 377 | |
| 378 /** | |
| 379 * Kill this session | |
| 380 */ | |
| 381 public function kill() | |
| 382 { | |
| 383 $this->vars = null; | |
| 384 $this->ip = rcube_utils::remote_addr(); // update IP (might have changed) | |
| 385 $this->destroy(session_id()); | |
| 386 rcube_utils::setcookie($this->cookiename, '-del-', time() - 60); | |
| 387 } | |
| 388 | |
| 389 /** | |
| 390 * Re-read session data from storage backend | |
| 391 */ | |
| 392 public function reload() | |
| 393 { | |
| 394 // collect updated data from previous appends | |
| 395 $merge_data = array(); | |
| 396 foreach ((array)$this->appends as $var) { | |
| 397 $path = explode('.', $var); | |
| 398 $value = $this->get_node($path, $_SESSION); | |
| 399 $k = array_pop($path); | |
| 400 $node = &$this->get_node($path, $merge_data); | |
| 401 $node[$k] = $value; | |
| 402 } | |
| 403 | |
| 404 if ($this->key) { | |
| 405 $data = $this->read($this->key); | |
| 406 } | |
| 407 | |
| 408 if ($data) { | |
| 409 session_decode($data); | |
| 410 | |
| 411 // apply appends and unsets to reloaded data | |
| 412 $_SESSION = array_merge_recursive($_SESSION, $merge_data); | |
| 413 | |
| 414 foreach ((array)$this->unsets as $var) { | |
| 415 if (isset($_SESSION[$var])) { | |
| 416 unset($_SESSION[$var]); | |
| 417 } | |
| 418 else { | |
| 419 $path = explode('.', $var); | |
| 420 $k = array_pop($path); | |
| 421 $node = &$this->get_node($path, $_SESSION); | |
| 422 unset($node[$k]); | |
| 423 } | |
| 424 } | |
| 425 } | |
| 426 } | |
| 427 | |
| 428 /** | |
| 429 * Returns a reference to the node in data array referenced by the given path. | |
| 430 * e.g. ['compose','attachments'] will return $_SESSION['compose']['attachments'] | |
| 431 */ | |
| 432 protected function &get_node($path, &$data_arr) | |
| 433 { | |
| 434 $node = &$data_arr; | |
| 435 if (!empty($path)) { | |
| 436 foreach ((array)$path as $key) { | |
| 437 if (!isset($node[$key])) | |
| 438 $node[$key] = array(); | |
| 439 $node = &$node[$key]; | |
| 440 } | |
| 441 } | |
| 442 | |
| 443 return $node; | |
| 444 } | |
| 445 | |
| 446 /** | |
| 447 * Serialize session data | |
| 448 */ | |
| 449 protected function serialize($vars) | |
| 450 { | |
| 451 $data = ''; | |
| 452 if (is_array($vars)) { | |
| 453 foreach ($vars as $var=>$value) | |
| 454 $data .= $var.'|'.serialize($value); | |
| 455 } | |
| 456 else { | |
| 457 $data = 'b:0;'; | |
| 458 } | |
| 459 | |
| 460 return $data; | |
| 461 } | |
| 462 | |
| 463 /** | |
| 464 * Unserialize session data | |
| 465 * http://www.php.net/manual/en/function.session-decode.php#56106 | |
| 466 */ | |
| 467 protected function unserialize($str) | |
| 468 { | |
| 469 $str = (string)$str; | |
| 470 $endptr = strlen($str); | |
| 471 $p = 0; | |
| 472 | |
| 473 $serialized = ''; | |
| 474 $items = 0; | |
| 475 $level = 0; | |
| 476 | |
| 477 while ($p < $endptr) { | |
| 478 $q = $p; | |
| 479 while ($str[$q] != '|') | |
| 480 if (++$q >= $endptr) | |
| 481 break 2; | |
| 482 | |
| 483 if ($str[$p] == '!') { | |
| 484 $p++; | |
| 485 $has_value = false; | |
| 486 } | |
| 487 else { | |
| 488 $has_value = true; | |
| 489 } | |
| 490 | |
| 491 $name = substr($str, $p, $q - $p); | |
| 492 $q++; | |
| 493 | |
| 494 $serialized .= 's:' . strlen($name) . ':"' . $name . '";'; | |
| 495 | |
| 496 if ($has_value) { | |
| 497 for (;;) { | |
| 498 $p = $q; | |
| 499 switch (strtolower($str[$q])) { | |
| 500 case 'n': // null | |
| 501 case 'b': // boolean | |
| 502 case 'i': // integer | |
| 503 case 'd': // decimal | |
| 504 do $q++; | |
| 505 while ( ($q < $endptr) && ($str[$q] != ';') ); | |
| 506 $q++; | |
| 507 $serialized .= substr($str, $p, $q - $p); | |
| 508 if ($level == 0) | |
| 509 break 2; | |
| 510 break; | |
| 511 case 'r': // reference | |
| 512 $q+= 2; | |
| 513 for ($id = ''; ($q < $endptr) && ($str[$q] != ';'); $q++) | |
| 514 $id .= $str[$q]; | |
| 515 $q++; | |
| 516 // increment pointer because of outer array | |
| 517 $serialized .= 'R:' . ($id + 1) . ';'; | |
| 518 if ($level == 0) | |
| 519 break 2; | |
| 520 break; | |
| 521 case 's': // string | |
| 522 $q+=2; | |
| 523 for ($length=''; ($q < $endptr) && ($str[$q] != ':'); $q++) | |
| 524 $length .= $str[$q]; | |
| 525 $q+=2; | |
| 526 $q+= (int)$length + 2; | |
| 527 $serialized .= substr($str, $p, $q - $p); | |
| 528 if ($level == 0) | |
| 529 break 2; | |
| 530 break; | |
| 531 case 'a': // array | |
| 532 case 'o': // object | |
| 533 do $q++; | |
| 534 while ($q < $endptr && $str[$q] != '{'); | |
| 535 $q++; | |
| 536 $level++; | |
| 537 $serialized .= substr($str, $p, $q - $p); | |
| 538 break; | |
| 539 case '}': // end of array|object | |
| 540 $q++; | |
| 541 $serialized .= substr($str, $p, $q - $p); | |
| 542 if (--$level == 0) | |
| 543 break 2; | |
| 544 break; | |
| 545 default: | |
| 546 return false; | |
| 547 } | |
| 548 } | |
| 549 } | |
| 550 else { | |
| 551 $serialized .= 'N;'; | |
| 552 $q += 2; | |
| 553 } | |
| 554 $items++; | |
| 555 $p = $q; | |
| 556 } | |
| 557 | |
| 558 return unserialize( 'a:' . $items . ':{' . $serialized . '}' ); | |
| 559 } | |
| 560 | |
| 561 /** | |
| 562 * Setter for session lifetime | |
| 563 */ | |
| 564 public function set_lifetime($lifetime) | |
| 565 { | |
| 566 $this->lifetime = max(120, $lifetime); | |
| 567 | |
| 568 // valid time range is now - 1/2 lifetime to now + 1/2 lifetime | |
| 569 $now = time(); | |
| 570 $this->now = $now - ($now % ($this->lifetime / 2)); | |
| 571 } | |
| 572 | |
| 573 /** | |
| 574 * Getter for remote IP saved with this session | |
| 575 */ | |
| 576 public function get_ip() | |
| 577 { | |
| 578 return $this->ip; | |
| 579 } | |
| 580 | |
| 581 /** | |
| 582 * Setter for cookie encryption secret | |
| 583 */ | |
| 584 function set_secret($secret = null) | |
| 585 { | |
| 586 // generate random hash and store in session | |
| 587 if (!$secret) { | |
| 588 if (!empty($_SESSION['auth_secret'])) { | |
| 589 $secret = $_SESSION['auth_secret']; | |
| 590 } | |
| 591 else { | |
| 592 $secret = rcube_utils::random_bytes(strlen($this->key)); | |
| 593 } | |
| 594 } | |
| 595 | |
| 596 $_SESSION['auth_secret'] = $secret; | |
| 597 } | |
| 598 | |
| 599 /** | |
| 600 * Enable/disable IP check | |
| 601 */ | |
| 602 function set_ip_check($check) | |
| 603 { | |
| 604 $this->ip_check = $check; | |
| 605 } | |
| 606 | |
| 607 /** | |
| 608 * Setter for the cookie name used for session cookie | |
| 609 */ | |
| 610 function set_cookiename($cookiename) | |
| 611 { | |
| 612 if ($cookiename) { | |
| 613 $this->cookiename = $cookiename; | |
| 614 } | |
| 615 } | |
| 616 | |
| 617 /** | |
| 618 * Check session authentication cookie | |
| 619 * | |
| 620 * @return boolean True if valid, False if not | |
| 621 */ | |
| 622 function check_auth() | |
| 623 { | |
| 624 $this->cookie = $_COOKIE[$this->cookiename]; | |
| 625 $result = $this->ip_check ? rcube_utils::remote_addr() == $this->ip : true; | |
| 626 | |
| 627 if (!$result) { | |
| 628 $this->log("IP check failed for " . $this->key . "; expected " . $this->ip . "; got " . rcube_utils::remote_addr()); | |
| 629 } | |
| 630 | |
| 631 if ($result && $this->_mkcookie($this->now) != $this->cookie) { | |
| 632 $this->log("Session auth check failed for " . $this->key . "; timeslot = " . date('Y-m-d H:i:s', $this->now)); | |
| 633 $result = false; | |
| 634 | |
| 635 // Check if using id from a previous time slot | |
| 636 for ($i = 1; $i <= 2; $i++) { | |
| 637 $prev = $this->now - ($this->lifetime / 2) * $i; | |
| 638 if ($this->_mkcookie($prev) == $this->cookie) { | |
| 639 $this->log("Send new auth cookie for " . $this->key . ": " . $this->cookie); | |
| 640 $this->set_auth_cookie(); | |
| 641 $result = true; | |
| 642 } | |
| 643 } | |
| 644 } | |
| 645 | |
| 646 if (!$result) { | |
| 647 $this->log("Session authentication failed for " . $this->key | |
| 648 . "; invalid auth cookie sent; timeslot = " . date('Y-m-d H:i:s', $prev)); | |
| 649 } | |
| 650 | |
| 651 return $result; | |
| 652 } | |
| 653 | |
| 654 /** | |
| 655 * Set session authentication cookie | |
| 656 */ | |
| 657 public function set_auth_cookie() | |
| 658 { | |
| 659 $this->cookie = $this->_mkcookie($this->now); | |
| 660 rcube_utils::setcookie($this->cookiename, $this->cookie, 0); | |
| 661 $_COOKIE[$this->cookiename] = $this->cookie; | |
| 662 } | |
| 663 | |
| 664 /** | |
| 665 * Create session cookie for specified time slot. | |
| 666 * | |
| 667 * @param int Time slot to use | |
| 668 * | |
| 669 * @return string | |
| 670 */ | |
| 671 protected function _mkcookie($timeslot) | |
| 672 { | |
| 673 // make sure the secret key exists | |
| 674 $this->set_secret(); | |
| 675 | |
| 676 // no need to hash this, it's just a random string | |
| 677 return $_SESSION['auth_secret'] . '-' . $timeslot; | |
| 678 } | |
| 679 | |
| 680 /** | |
| 681 * Writes debug information to the log | |
| 682 */ | |
| 683 function log($line) | |
| 684 { | |
| 685 if ($this->logging) { | |
| 686 rcube::write_log('session', $line); | |
| 687 } | |
| 688 } | |
| 689 } |
