3 * Copyright 2005 $ThePhpWikiProgrammingTeam
5 * This file is part of PhpWiki.
7 * PhpWiki is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * PhpWiki is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with PhpWiki; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 * ADODB db sessions, based on pear DB Sessions.
25 * @author: Reini Urban
30 var $_backend_type = "ADODB";
32 function DbSession_ADODB ($dbh, $table) {
35 $this->_table = $table;
37 ini_set('session.save_handler','user');
38 session_module_name('user'); // new style
39 session_set_save_handler(array(&$this, 'open'),
40 array(&$this, 'close'),
41 array(&$this, 'read'),
42 array(&$this, 'write'),
43 array(&$this, 'destroy'),
48 function & _connect() {
50 static $parsed = false;
52 if (!$dbh or !is_resource($dbh->_connectionID)) {
53 if (!$parsed) $parsed = parseDSN($request->_dbi->getParam('dsn'));
54 $this->_dbh =& ADONewConnection($parsed['phptype']); // Probably only MySql works just now
55 $this->_dbh->Connect($parsed['hostspec'],$parsed['username'],
56 $parsed['password'], $parsed['database']);
62 function query($sql) {
63 return $this->_dbh->Execute($sql);
66 function quote($string) {
67 return $this->_dbh->qstr($string);
70 function _disconnect() {
71 if (0 and $this->_dbh)
78 * Actually this function is a fake for session_set_save_handle.
79 * @param string $save_path a path to stored files
80 * @param string $session_name a name of the concrete file
81 * @return boolean true just a variable to notify PHP that everything
85 function open ($save_path, $session_name) {
86 //$this->log("_open($save_path, $session_name)");
93 * This function is called just after <i>write</i> call.
95 * @return boolean true just a variable to notify PHP that everything
100 //$this->log("_close()");
105 * Reads the session data from DB.
107 * @param string $id an id of current session
111 function read ($id) {
112 //$this->log("_read($id)");
113 $dbh = $this->_connect();
114 $table = $this->_table;
115 $qid = $dbh->qstr($id);
117 $row = $dbh->GetRow("SELECT sess_data FROM $table WHERE sess_id=$qid");
120 $this->_disconnect();
121 if (!empty($res) and preg_match('|^[a-zA-Z0-9/+=]+$|', $res))
122 $res = base64_decode($res);
123 if (strlen($res) > 4000) {
124 trigger_error("Overlarge session data! ".strlen($res).
125 " gt. 4000", E_USER_WARNING);
126 $res = preg_replace('/s:6:"_cache";O:12:"WikiDB_cache".+}$/',"",$res);
127 $res = preg_replace('/s:12:"_cached_html";s:.+",s:4:"hits"/','s:4:"hits"',$res);
128 if (strlen($res) > 4000) $res = '';
134 * Saves the session data into DB.
136 * Just a comment: The "write" handler is not
137 * executed until after the output stream is closed. Thus,
138 * output from debugging statements in the "write" handler
139 * will never be seen in the browser. If debugging output
140 * is necessary, it is suggested that the debug output be
141 * written to a file instead.
144 * @param string $sess_data
145 * @return boolean true if data saved successfully and false
149 function write ($id, $sess_data) {
150 if (defined("WIKI_XMLRPC") or defined("WIKI_SOAP")) return;
152 $dbh = $this->_connect();
153 $table = $this->_table;
154 $qid = $dbh->qstr($id);
155 $qip = $dbh->qstr($GLOBALS['request']->get('REMOTE_ADDR'));
156 $time = $dbh->qstr(time());
158 // postgres can't handle binary data in a TEXT field.
159 if (isa($dbh, 'ADODB_postgres64'))
160 $sess_data = base64_encode($sess_data);
161 $qdata = $dbh->qstr($sess_data);
163 /* AffectedRows with sessions seems to be instable on certain platforms.
164 * Enable the safe and slow USE_SAFE_DBSESSION then.
166 if (USE_SAFE_DBSESSION) {
167 $dbh->Execute("DELETE FROM $table"
168 . " WHERE sess_id=$qid");
169 $rs = $dbh->Execute("INSERT INTO $table"
170 . " (sess_id, sess_data, sess_date, sess_ip)"
171 . " VALUES ($qid, $qdata, $time, $qip)");
173 $rs = $dbh->Execute("UPDATE $table"
174 . " SET sess_data=$qdata, sess_date=$time, sess_ip=$qip"
175 . " WHERE sess_id=$qid");
176 $result = $dbh->Affected_Rows();
177 if ( $result === false or $result < 1 ) { // false or int > 0
178 $rs = $dbh->Execute("INSERT INTO $table"
179 . " (sess_id, sess_data, sess_date, sess_ip)"
180 . " VALUES ($qid, $qdata, $time, $qip)");
183 $result = ! $rs->EOF;
184 if ($result) $rs->free();
185 $this->_disconnect();
190 * Destroys a session.
192 * Removes a session from the table.
195 * @return boolean true
198 function destroy ($id) {
199 $dbh = $this->_connect();
200 $table = $this->_table;
201 $qid = $dbh->qstr($id);
203 $dbh->Execute("DELETE FROM $table WHERE sess_id=$qid");
205 $this->_disconnect();
210 * Cleans out all expired sessions.
212 * @param int $maxlifetime session's time to live.
213 * @return boolean true
216 function gc ($maxlifetime) {
217 $dbh = $this->_connect();
218 $table = $this->_table;
219 $threshold = time() - $maxlifetime;
221 $dbh->Execute("DELETE FROM $table WHERE sess_date < $threshold");
223 $this->_disconnect();
227 // WhoIsOnline support.
228 // TODO: ip-accesstime dynamic blocking API
229 function currentSessions() {
231 $dbh = $this->_connect();
232 $table = $this->_table;
233 $rs = $dbh->Execute("SELECT sess_data,sess_date,sess_ip FROM $table ORDER BY sess_date DESC");
239 $row = $rs->fetchRow();
243 if (preg_match('|^[a-zA-Z0-9/+=]+$|', $data))
244 $data = base64_decode($data);
245 if ($date < 908437560 or $date > 1588437560)
247 // session_data contains the <variable name> + "|" + <packed string>
248 // we need just the wiki_user object (might be array as well)
249 $user = strstr($data,"wiki_user|");
250 $sessions[] = array('wiki_user' => substr($user,10), // from "O:" onwards
256 $this->_disconnect();
265 // c-hanging-comment-ender-p: nil
266 // indent-tabs-mode: nil