]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/DbSession/ADODB.php
seperate DbSession classes: less memory, a bit slower
[SourceForge/phpwiki.git] / lib / DbSession / ADODB.php
1 <?php rcs_id('$Id: ADODB.php,v 1.1 2005-02-11 14:41:40 rurban Exp $');
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         
151         $dbh = &$this->_connect();
152         $table = $this->_table;
153         $qid = $dbh->qstr($id);
154         $qip = $dbh->qstr($GLOBALS['request']->get('REMOTE_ADDR'));
155         $time = $dbh->qstr(time());
156
157         // postgres can't handle binary data in a TEXT field.
158         if (isa($dbh, 'ADODB_postgres64'))
159             $sess_data = base64_encode($sess_data);
160         $qdata = $dbh->qstr($sess_data);
161
162         /* AffectedRows with sessions seems to be instable on certain platforms.
163          * Enable the safe and slow USE_SAFE_DBSESSION then.
164          */
165         if (USE_SAFE_DBSESSION) {
166             $dbh->Execute("DELETE FROM $table"
167                           . " WHERE sess_id=$qid");
168             $rs = $dbh->Execute("INSERT INTO $table"
169                                 . " (sess_id, sess_data, sess_date, sess_ip)"
170                                 . " VALUES ($qid, $qdata, $time, $qip)");
171         } else {
172             $rs = $dbh->Execute("UPDATE $table"
173                                 . " SET sess_data=$qdata, sess_date=$time, sess_ip=$qip"
174                                 . " WHERE sess_id=$qid");
175             $result = $dbh->Affected_Rows();
176             if ( $result === false or $result < 1 ) { // false or int > 0
177                 $rs = $dbh->Execute("INSERT INTO $table"
178                                     . " (sess_id, sess_data, sess_date, sess_ip)"
179                                     . " VALUES ($qid, $qdata, $time, $qip)");
180             }
181         }
182         $result = ! $rs->EOF;
183         if ($result) $rs->free();                        
184         $this->_disconnect();
185         return $result;
186     }
187
188     /**
189      * Destroys a session.
190      *
191      * Removes a session from the table.
192      *
193      * @param  string $id
194      * @return boolean true 
195      * @access private
196      */
197     function destroy ($id) {
198         $dbh = &$this->_connect();
199         $table = $this->_table;
200         $qid = $dbh->qstr($id);
201
202         $dbh->Execute("DELETE FROM $table WHERE sess_id=$qid");
203
204         $this->_disconnect();
205         return true;     
206     }
207
208     /**
209      * Cleans out all expired sessions.
210      *
211      * @param  int $maxlifetime session's time to live.
212      * @return boolean true
213      * @access private
214      */
215     function gc ($maxlifetime) {
216         $dbh = &$this->_connect();
217         $table = $this->_table;
218         $threshold = time() - $maxlifetime;
219
220         $dbh->Execute("DELETE FROM $table WHERE sess_date < $threshold");
221
222         $this->_disconnect();
223         return true;
224     }
225
226     // WhoIsOnline support. 
227     // TODO: ip-accesstime dynamic blocking API
228     function currentSessions() {
229         $sessions = array();
230         $dbh = &$this->_connect();
231         $table = $this->_table;
232         $rs = $dbh->Execute("SELECT sess_data,sess_date,sess_ip FROM $table ORDER BY sess_date DESC");
233         if ($rs->EOF) {
234             $rs->free();
235             return $sessions;
236         }
237         while (!$rs->EOF) {
238             $row = $rs->fetchRow();
239             $data = $row[0];
240             $date = $row[1];
241             $ip   = $row[2];
242             if (preg_match('|^[a-zA-Z0-9/+=]+$|', $data))
243                 $data = base64_decode($data);
244             if ($date < 908437560 or $date > 1588437560)
245                 $date = 0;
246             // session_data contains the <variable name> + "|" + <packed string>
247             // we need just the wiki_user object (might be array as well)
248             $user = strstr($data,"wiki_user|");
249             $sessions[] = array('wiki_user' => substr($user,10), // from "O:" onwards
250                                 'date' => $date,
251                                 'ip' => $ip);
252             $rs->MoveNext();
253         }
254         $rs->free();
255         $this->_disconnect();
256         return $sessions;
257     }
258 }
259
260 // $Log: not supported by cvs2svn $
261
262 // Local Variables:
263 // mode: php
264 // tab-width: 8
265 // c-basic-offset: 4
266 // c-hanging-comment-ender-p: nil
267 // indent-tabs-mode: nil
268 // End:
269 ?>