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)
36 $this->_table = $table;
38 ini_set('session.save_handler', 'user');
39 session_module_name('user'); // new style
40 session_set_save_handler(array(&$this, 'open'),
41 array(&$this, 'close'),
42 array(&$this, 'read'),
43 array(&$this, 'write'),
44 array(&$this, 'destroy'),
52 static $parsed = false;
54 if (!$dbh or !is_resource($dbh->_connectionID)) {
55 if (!$parsed) $parsed = parseDSN($request->_dbi->getParam('dsn'));
56 $this->_dbh =& ADONewConnection($parsed['phptype']); // Probably only MySql works just now
57 $this->_dbh->Connect($parsed['hostspec'], $parsed['username'],
58 $parsed['password'], $parsed['database']);
66 return $this->_dbh->Execute($sql);
69 function quote($string)
71 return $this->_dbh->qstr($string);
74 function _disconnect()
76 if (0 and $this->_dbh)
83 * Actually this function is a fake for session_set_save_handle.
84 * @param string $save_path a path to stored files
85 * @param string $session_name a name of the concrete file
86 * @return boolean true just a variable to notify PHP that everything
90 function open($save_path, $session_name)
92 //$this->log("_open($save_path, $session_name)");
99 * This function is called just after <i>write</i> call.
101 * @return boolean true just a variable to notify PHP that everything
107 //$this->log("_close()");
112 * Reads the session data from DB.
114 * @param string $id an id of current session
120 //$this->log("_read($id)");
121 $dbh = $this->_connect();
122 $table = $this->_table;
123 $qid = $dbh->qstr($id);
125 $row = $dbh->GetRow("SELECT sess_data FROM $table WHERE sess_id=$qid");
128 $this->_disconnect();
129 if (!empty($res) and preg_match('|^[a-zA-Z0-9/+=]+$|', $res))
130 $res = base64_decode($res);
131 if (strlen($res) > 4000) {
132 trigger_error("Overlarge session data! " . strlen($res) .
133 " gt. 4000", E_USER_WARNING);
134 $res = preg_replace('/s:6:"_cache";O:12:"WikiDB_cache".+}$/', "", $res);
135 $res = preg_replace('/s:12:"_cached_html";s:.+",s:4:"hits"/', 's:4:"hits"', $res);
136 if (strlen($res) > 4000) $res = '';
142 * Saves the session data into DB.
144 * Just a comment: The "write" handler is not
145 * executed until after the output stream is closed. Thus,
146 * output from debugging statements in the "write" handler
147 * will never be seen in the browser. If debugging output
148 * is necessary, it is suggested that the debug output be
149 * written to a file instead.
152 * @param string $sess_data
153 * @return boolean true if data saved successfully and false
157 function write($id, $sess_data)
159 if (defined("WIKI_XMLRPC") or defined("WIKI_SOAP")) return;
161 $dbh = $this->_connect();
162 $table = $this->_table;
163 $qid = $dbh->qstr($id);
164 $qip = $dbh->qstr($GLOBALS['request']->get('REMOTE_ADDR'));
165 $time = $dbh->qstr(time());
167 // postgres can't handle binary data in a TEXT field.
168 if (isa($dbh, 'ADODB_postgres64'))
169 $sess_data = base64_encode($sess_data);
170 $qdata = $dbh->qstr($sess_data);
172 /* AffectedRows with sessions seems to be instable on certain platforms.
173 * Enable the safe and slow USE_SAFE_DBSESSION then.
175 if (USE_SAFE_DBSESSION) {
176 $dbh->Execute("DELETE FROM $table"
177 . " WHERE sess_id=$qid");
178 $rs = $dbh->Execute("INSERT INTO $table"
179 . " (sess_id, sess_data, sess_date, sess_ip)"
180 . " VALUES ($qid, $qdata, $time, $qip)");
182 $rs = $dbh->Execute("UPDATE $table"
183 . " SET sess_data=$qdata, sess_date=$time, sess_ip=$qip"
184 . " WHERE sess_id=$qid");
185 $result = $dbh->Affected_Rows();
186 if ($result === false or $result < 1) { // false or int > 0
187 $rs = $dbh->Execute("INSERT INTO $table"
188 . " (sess_id, sess_data, sess_date, sess_ip)"
189 . " VALUES ($qid, $qdata, $time, $qip)");
193 if ($result) $rs->free();
194 $this->_disconnect();
199 * Destroys a session.
201 * Removes a session from the table.
204 * @return boolean true
207 function destroy($id)
209 $dbh = $this->_connect();
210 $table = $this->_table;
211 $qid = $dbh->qstr($id);
213 $dbh->Execute("DELETE FROM $table WHERE sess_id=$qid");
215 $this->_disconnect();
220 * Cleans out all expired sessions.
222 * @param int $maxlifetime session's time to live.
223 * @return boolean true
226 function gc($maxlifetime)
228 $dbh = $this->_connect();
229 $table = $this->_table;
230 $threshold = time() - $maxlifetime;
232 $dbh->Execute("DELETE FROM $table WHERE sess_date < $threshold");
234 $this->_disconnect();
238 // WhoIsOnline support.
239 // TODO: ip-accesstime dynamic blocking API
240 function currentSessions()
243 $dbh = $this->_connect();
244 $table = $this->_table;
245 $rs = $dbh->Execute("SELECT sess_data,sess_date,sess_ip FROM $table ORDER BY sess_date DESC");
251 $row = $rs->fetchRow();
255 if (preg_match('|^[a-zA-Z0-9/+=]+$|', $data))
256 $data = base64_decode($data);
257 if ($date < 908437560 or $date > 1588437560)
259 // session_data contains the <variable name> + "|" + <packed string>
260 // we need just the wiki_user object (might be array as well)
261 $user = strstr($data, "wiki_user|");
262 $sessions[] = array('wiki_user' => substr($user, 10), // from "O:" onwards
268 $this->_disconnect();
277 // c-hanging-comment-ender-p: nil
278 // indent-tabs-mode: nil