]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/DbSession/ADODB.php
Activated Id substitution for Subversion
[SourceForge/phpwiki.git] / lib / DbSession / ADODB.php
1 <?php rcs_id('$Id$');
2 /*
3  Copyright 2005 $ThePhpWikiProgrammingTeam
4
5  This file is part of PhpWiki.
6
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.
11
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.
16
17  You should have received a copy of the GNU General Public License
18  along with PhpWiki; if not, write to the Free Software
19  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20 */ 
21
22 /** 
23  * ADODB db sessions, based on pear DB Sessions.
24  *
25  * @author: Reini Urban
26  */
27 class DbSession_ADODB
28 extends DbSession
29 {
30     var $_backend_type = "ADODB";
31
32     function DbSession_ADODB ($dbh, $table) {
33
34         $this->_dbh = $dbh;
35         $this->_table = $table;
36
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'),
44                                  array(&$this, 'gc'));
45         return $this;
46     }
47
48     function & _connect() {
49         global $request;
50         static $parsed = false;
51         $dbh = &$this->_dbh;
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']);
57             $dbh = &$this->_dbh;                             
58         }
59         return $dbh;
60     }
61     
62     function query($sql) {
63         return $this->_dbh->Execute($sql);
64     }
65
66     function quote($string) {
67         return $this->_dbh->qstr($string);
68     }
69
70     function _disconnect() {
71         if (0 and $this->_dbh)
72             $this->_dbh->close();
73     }
74
75     /**
76      * Opens a session.
77      *
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 
82      * is good.
83      * @access private
84      */
85     function open ($save_path, $session_name) {
86         //$this->log("_open($save_path, $session_name)");
87         return true;
88     }
89
90     /**
91      * Closes a session.
92      *
93      * This function is called just after <i>write</i> call.
94      *
95      * @return boolean true just a variable to notify PHP that everything 
96      * is good.
97      * @access private
98      */
99     function close() {
100         //$this->log("_close()");
101         return true;
102     }
103
104     /**
105      * Reads the session data from DB.
106      *
107      * @param  string $id an id of current session
108      * @return string
109      * @access private
110      */
111     function read ($id) {
112         //$this->log("_read($id)");
113         $dbh = $this->_connect();
114         $table = $this->_table;
115         $qid = $dbh->qstr($id);
116         $res = '';
117         $row = $dbh->GetRow("SELECT sess_data FROM $table WHERE sess_id=$qid");
118         if ($row)
119             $res = $row[0];
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 = '';
129         }
130         return $res;
131     }
132   
133     /**
134      * Saves the session data into DB.
135      *
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.
142      *
143      * @param  string $id
144      * @param  string $sess_data
145      * @return boolean true if data saved successfully  and false
146      * otherwise.
147      * @access private
148      */
149     function write ($id, $sess_data) {
150         if (defined("WIKI_XMLRPC") or defined("WIKI_SOAP")) return;     
151         
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());
157
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);
162
163         /* AffectedRows with sessions seems to be instable on certain platforms.
164          * Enable the safe and slow USE_SAFE_DBSESSION then.
165          */
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)");
172         } else {
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)");
181             }
182         }
183         $result = ! $rs->EOF;
184         if ($result) $rs->free();                        
185         $this->_disconnect();
186         return $result;
187     }
188
189     /**
190      * Destroys a session.
191      *
192      * Removes a session from the table.
193      *
194      * @param  string $id
195      * @return boolean true 
196      * @access private
197      */
198     function destroy ($id) {
199         $dbh = $this->_connect();
200         $table = $this->_table;
201         $qid = $dbh->qstr($id);
202
203         $dbh->Execute("DELETE FROM $table WHERE sess_id=$qid");
204
205         $this->_disconnect();
206         return true;     
207     }
208
209     /**
210      * Cleans out all expired sessions.
211      *
212      * @param  int $maxlifetime session's time to live.
213      * @return boolean true
214      * @access private
215      */
216     function gc ($maxlifetime) {
217         $dbh = $this->_connect();
218         $table = $this->_table;
219         $threshold = time() - $maxlifetime;
220
221         $dbh->Execute("DELETE FROM $table WHERE sess_date < $threshold");
222
223         $this->_disconnect();
224         return true;
225     }
226
227     // WhoIsOnline support. 
228     // TODO: ip-accesstime dynamic blocking API
229     function currentSessions() {
230         $sessions = array();
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");
234         if ($rs->EOF) {
235             $rs->free();
236             return $sessions;
237         }
238         while (!$rs->EOF) {
239             $row = $rs->fetchRow();
240             $data = $row[0];
241             $date = $row[1];
242             $ip   = $row[2];
243             if (preg_match('|^[a-zA-Z0-9/+=]+$|', $data))
244                 $data = base64_decode($data);
245             if ($date < 908437560 or $date > 1588437560)
246                 $date = 0;
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
251                                 'date' => $date,
252                                 'ip' => $ip);
253             $rs->MoveNext();
254         }
255         $rs->free();
256         $this->_disconnect();
257         return $sessions;
258     }
259 }
260
261 // $Log: not supported by cvs2svn $
262 // Revision 1.2  2005/11/21 20:48:48  rurban
263 // fix ref warnings reported by schorni
264 //
265 // Revision 1.1  2005/02/11 14:41:40  rurban
266 // seperate DbSession classes: less memory, a bit slower
267 //
268
269 // Local Variables:
270 // mode: php
271 // tab-width: 8
272 // c-basic-offset: 4
273 // c-hanging-comment-ender-p: nil
274 // indent-tabs-mode: nil
275 // End:
276 ?>