| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221 |
- <?php
- /*
- Copyright (c) 2009-2017 F3::Factory/Bong Cosca, All rights reserved.
- This file is part of the Fat-Free Framework (http://fatfreeframework.com).
- This is free software: you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation, either version 3 of the License, or later.
- Fat-Free Framework is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
- You should have received a copy of the GNU General Public License along
- with Fat-Free Framework. If not, see <http://www.gnu.org/licenses/>.
- */
- namespace DB\SQL;
- //! SQL-managed session handler
- class Session extends Mapper {
- protected
- //! Session ID
- $sid,
- //! Anti-CSRF token
- $_csrf,
- //! User agent
- $_agent,
- //! IP,
- $_ip,
- //! Suspect callback
- $onsuspect;
- /**
- * Open session
- * @return TRUE
- * @param $path string
- * @param $name string
- **/
- function open($path,$name) {
- return TRUE;
- }
- /**
- * Close session
- * @return TRUE
- **/
- function close() {
- $this->reset();
- $this->sid=NULL;
- return TRUE;
- }
- /**
- * Return session data in serialized format
- * @return string
- * @param $id string
- **/
- function read($id) {
- $this->load(['session_id=?',$this->sid=$id]);
- if ($this->dry())
- return '';
- if ($this->get('ip')!=$this->_ip || $this->get('agent')!=$this->_agent) {
- $fw=\Base::instance();
- if (!isset($this->onsuspect) ||
- $fw->call($this->onsuspect,[$this,$id])===FALSE) {
- //NB: `session_destroy` can't be called at that stage (`session_start` not completed)
- $this->destroy($id);
- $this->close();
- unset($fw->{'COOKIE.'.session_name()});
- $fw->error(403);
- }
- }
- return $this->get('data');
- }
- /**
- * Write session data
- * @return TRUE
- * @param $id string
- * @param $data string
- **/
- function write($id,$data) {
- $this->set('session_id',$id);
- $this->set('data',$data);
- $this->set('ip',$this->_ip);
- $this->set('agent',$this->_agent);
- $this->set('stamp',time());
- $this->save();
- return TRUE;
- }
- /**
- * Destroy session
- * @return TRUE
- * @param $id string
- **/
- function destroy($id) {
- $this->erase(['session_id=?',$id]);
- return TRUE;
- }
- /**
- * Garbage collector
- * @return TRUE
- * @param $max int
- **/
- function cleanup($max) {
- $this->erase(['stamp+?<?',$max,time()]);
- return TRUE;
- }
- /**
- * Return session id (if session has started)
- * @return string|NULL
- **/
- function sid() {
- return $this->sid;
- }
- /**
- * Return anti-CSRF token
- * @return string
- **/
- function csrf() {
- return $this->_csrf;
- }
- /**
- * Return IP address
- * @return string
- **/
- function ip() {
- return $this->_ip;
- }
- /**
- * Return Unix timestamp
- * @return string|FALSE
- **/
- function stamp() {
- if (!$this->sid)
- session_start();
- return $this->dry()?FALSE:$this->get('stamp');
- }
- /**
- * Return HTTP user agent
- * @return string
- **/
- function agent() {
- return $this->_agent;
- }
- /**
- * Instantiate class
- * @param $db \DB\SQL
- * @param $table string
- * @param $force bool
- * @param $onsuspect callback
- * @param $key string
- **/
- function __construct(\DB\SQL $db,$table='sessions',$force=TRUE,$onsuspect=NULL,$key=NULL) {
- if ($force) {
- $eol="\n";
- $tab="\t";
- $sqlsrv=preg_match('/mssql|sqlsrv|sybase/',$db->driver());
- $db->exec(
- ($sqlsrv?
- ('IF NOT EXISTS (SELECT * FROM sysobjects WHERE '.
- 'name='.$db->quote($table).' AND xtype=\'U\') '.
- 'CREATE TABLE dbo.'):
- ('CREATE TABLE IF NOT EXISTS '.
- ((($name=$db->name())&&$db->driver()!='pgsql')?
- ($db->quotekey($name,FALSE).'.'):''))).
- $db->quotekey($table,FALSE).' ('.$eol.
- ($sqlsrv?$tab.$db->quotekey('id').' INT IDENTITY,'.$eol:'').
- $tab.$db->quotekey('session_id').' VARCHAR(255),'.$eol.
- $tab.$db->quotekey('data').' TEXT,'.$eol.
- $tab.$db->quotekey('ip').' VARCHAR(45),'.$eol.
- $tab.$db->quotekey('agent').' VARCHAR(300),'.$eol.
- $tab.$db->quotekey('stamp').' INTEGER,'.$eol.
- $tab.'PRIMARY KEY ('.$db->quotekey($sqlsrv?'id':'session_id').')'.$eol.
- ($sqlsrv?',CONSTRAINT [UK_session_id] UNIQUE(session_id)':'').
- ');'
- );
- }
- parent::__construct($db,$table);
- $this->onsuspect=$onsuspect;
- session_set_save_handler(
- [$this,'open'],
- [$this,'close'],
- [$this,'read'],
- [$this,'write'],
- [$this,'destroy'],
- [$this,'cleanup']
- );
- register_shutdown_function('session_commit');
- $fw=\Base::instance();
- $headers=$fw->HEADERS;
- $this->_csrf=$fw->hash($fw->SEED.
- extension_loaded('openssl')?
- implode(unpack('L',openssl_random_pseudo_bytes(4))):
- mt_rand()
- );
- if ($key)
- $fw->$key=$this->_csrf;
- $this->_agent=isset($headers['User-Agent'])?$headers['User-Agent']:'';
- if (strlen($this->_agent) > 300) {
- $this->_agent = substr($this->_agent, 0, 300);
- }
- $this->_ip=$fw->IP;
- }
- }
|