session.php 4.34 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
<?php
#
# Copyright (c) 2006-2014 University of Utah and the Flux Group.
# 
# {{{EMULAB-LICENSE
# 
# This file is part of the Emulab network testbed software.
# 
# This file is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or (at
# your option) any later version.
# 
# This file 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 Affero General Public
# License for more details.
# 
# You should have received a copy of the GNU Affero General Public License
# along with this file.  If not, see <http://www.gnu.org/licenses/>.
# 
# }}}
#
# Store PHP sessions in out DB. This came off the php manual page,
# in one of the comments. There is some oddity below for $_SESSION,
# which will go away when we are running php 5.4.
#
# I am not really sure how we will be usng sessions yet, for now
# just experimenting with it.
#
class SessionSaveHandler {
    // session-lifetime 
    var $lifeTime; 
	
    public function __construct() {
	global $TBAUTHDOMAIN;

	# Enforce secure cookies, this domain only.
	session_set_cookie_params(600, "/", $TBAUTHDOMAIN, 1);
	
        session_set_save_handler(
            array($this, "open"),
            array($this, "close"),
            array($this, "read"),
            array($this, "write"),
            array($this, "destroy"),
            array($this, "gc")
        );
        register_shutdown_function('session_write_close');
    }

    function ValidSessionID($id) {
	if (preg_match("/^[-\w]+$/", $id)) {
	    return TRUE;
	}
	return FALSE;
    }

    // Note that we have a permanent connection to the database, so
    // we do not need to do open/close on it.
    public function open($savePath, $sessionName) {
       // get session-lifetime 
       $this->lifeTime = ini_get("session.gc_maxlifetime");
       return true; 
    }

    public function close() {
	$this->gc($this->lifeTime);
        return true;
    }

    public function read($id) {
	if (! $this->ValidSessionID($id)) {
	    return "";
	}

	$query_result =
	    DBQueryWarn("select session_data from web_sessions ".
			"where session_id='$id' and ".
			"      session_expires>now()");
	if (! ($query_result && mysql_num_rows($query_result))) {
	    return "";
	}
	$row  = mysql_fetch_array($query_result);
	$foo  = json_decode($row["session_data"]);

	foreach ($foo AS $key => $value) {
	    $_SESSION[$key] = $value;
	}
	return "";
    }

    public function write($id, $data) {
	if (! $this->ValidSessionID($id)) {
	    return "";
	}
        // new session-expire-time 
        $newExp = time() + $this->lifeTime;

	// Convert to JSON, but need to unserialize the data first.
	// We want the backend perl code to be able to use it.
	$safe_data = addslashes(json_encode($_SESSION));

        // is a session with this id in the database?
	$query_result =
		DBQueryFatal("select * FROM web_sessions ".
			     "where session_id = '$id'");
	
        if (mysql_num_rows($query_result)) {
		$query_result = 
		    DBQueryWarn("update web_sessions set ".
				"       session_expires=FROM_UNIXTIME($newExp), ".
				"       session_data='$safe_data' ".
				"where session_id='$id'");
		if ($query_result && DBAffectedRows()) {
		    return true;
		}
        } 
        else { 
            // New session.
	    $query_result =
	        DBQueryWarn("replace into web_sessions set ".
			     " session_id='$id', ".
			    "  session_expires=FROM_UNIXTIME($newExp), ".
			     " session_data='$safe_data'");
	    if ($query_result && DBAffectedRows()) {
		return true;
	    }
        } 
        // an unknown error occured 
        return false; 
    } 

    public function destroy($id) {
	if (! $this->ValidSessionID($id)) {
	    return false;
	}
	$query_result =
	    DBQueryWarn("delete from web_sessions ".
			"where session_id='$id'");
	
        // if session was deleted, return true, 
	if ($query_result && DBAffectedRows()) {
            return true;
	}
	return false;
    }

    public function gc($maxlifetime) {
        // delete old sessions
	DBQueryWarn("delete from web_sessions where session_expires<now()");
	
        // return affected rows 
        return DBAffectedRows();
    }
}
# Create once and we are done.
new SessionSaveHandler();
?>