1 <?php rcs_id('$Id: DbSession.php,v 1.3 2003-03-04 05:33:00 dairiki Exp $');
4 * Store sessions data in Pear DB.
8 * Originally by Stanislav Shramko <stanis@movingmail.com>
9 * Minor rewrite by Reini Urban <rurban@x-ray.at> for Phpwiki.
10 * Quasi-major rewrite/decruft/fix by Jeff Dairiki <dairiki@dairiki.org>.
18 * Pear DB handle, or WikiDB object (from which the Pear DB handle will
21 * @param string $table
22 * Name of SQL table containing session data.
24 function DB_Session(&$dbh, $table = 'session') {
26 // Coerce WikiDB to Pear DB.
27 if (isa($dbh, 'WikiDB')) {
28 $backend = &$dbh->_backend;
29 if (!isa($backend, 'WikiDB_backend_PearDB')) {
30 trigger_error('Your WikiDB does not seem to be using a Pear DB backend',
34 $dbh = &$backend->_dbh;
38 $this->_table = $table;
40 ini_set('session.save_handler','user');
42 session_set_save_handler(array(&$this, 'do_open'),
43 array(&$this, 'do_close'),
44 array(&$this, 'do_read'),
45 array(&$this, 'do_write'),
46 array(&$this, 'do_destroy'),
47 array(&$this, 'do_gc'));
52 $this->_connected = (bool)$dbh->connection;
53 if (!$this->_connected) {
54 $res = $dbh->connect($dbh->dsn);
55 if (DB::isError($res)) {
56 error_log("PhpWiki::DB_Session::_connect: " . $res->getMessage());
62 function _disconnect() {
63 if (!$this->_connected)
64 $this->_dbh->disconnect();
70 * Actually this function is a fake for session_set_save_handle.
71 * @param string $save_path a path to stored files
72 * @param string $session_name a name of the concrete file
73 * @return boolean true just a variable to notify PHP that everything
77 function do_open ($save_path, $session_name) {
78 //$this->log("_do_open($save_path, $session_name)");
85 * This function is called just after <i>do_write</i> call.
87 * @return boolean true just a variable to notify PHP that everything
92 //$this->log("_do_close()");
97 * Reads the session data from DB.
99 * @param string $id an id of current session
103 function do_read ($id) {
104 //$this->log("_do_read($id)");
105 $dbh = &$this->_connect();
106 $table = $this->_table;
107 $qid = $dbh->quote($id);
109 $res = $dbh->getOne("SELECT sess_data FROM $table WHERE sess_id=$qid");
111 $this->_disconnect();
112 if (DB::isError($res) || empty($res))
114 if (preg_match('|^[a-zA-Z0-9/+=]+$|', $res))
115 $res = base64_decode($res);
120 * Saves the session data into DB.
122 * Just a comment: The "write" handler is not
123 * executed until after the output stream is closed. Thus,
124 * output from debugging statements in the "write" handler
125 * will never be seen in the browser. If debugging output
126 * is necessary, it is suggested that the debug output be
127 * written to a file instead.
130 * @param string $sess_data
131 * @return boolean true if data saved successfully and false
135 function do_write ($id, $sess_data) {
137 $dbh = &$this->_connect();
138 $table = $this->_table;
139 $qid = $dbh->quote($id);
142 // postgres can't handle binary data in a TEXT field.
143 if (isa($dbh, 'DB_pgsql'))
144 $sess_data = base64_encode($sess_data);
145 $qdata = $dbh->quote($sess_data);
147 $res = $dbh->query("UPDATE $table"
148 . " SET sess_data=$qdata, sess_date=$time"
149 . " WHERE sess_id=$qid");
151 if ($dbh->affectedRows() == 0)
152 $res = $dbh->query("INSERT INTO $table"
153 . " (sess_id, sess_data, sess_date)"
154 . " VALUES ($qid, $qdata, $time)");
156 $this->_disconnect();
157 return ! DB::isError($res);
161 * Destroys a session.
163 * Removes a session from the table.
166 * @return boolean true
169 function do_destroy ($id) {
170 $dbh = &$this->_connect();
171 $table = $this->_table;
172 $qid = $dbh->quote($id);
174 $dbh->query("DELETE FROM $table WHERE sess_id=$qid");
176 $this->_disconnect();
181 * Cleans out all expired sessions.
183 * @param int $maxlifetime session's time to live.
184 * @return boolean true
187 function do_gc ($maxlifetime) {
188 $dbh = &$this->_connect();
189 $table = $this->_table;
190 $threshold = time() - $maxlifetime;
192 $dbh->query("DELETE FROM $table WHERE sess_date < $threshold");
194 $this->_disconnect();
204 // c-hanging-comment-ender-p: nil
205 // indent-tabs-mode: nil