]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/DbSession/ADODB.php
var --> public
[SourceForge/phpwiki.git] / lib / DbSession / ADODB.php
1 <?php
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 along
18  * with PhpWiki; if not, write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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     public $_backend_type = "ADODB";
31
32     function DbSession_ADODB($dbh, $table)
33     {
34
35         $this->_dbh = $dbh;
36         $this->_table = $table;
37
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'),
45             array(&$this, 'gc'));
46         return $this;
47     }
48
49     function & _connect()
50     {
51         global $request;
52         static $parsed = false;
53         $dbh = &$this->_dbh;
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']);
59             $dbh = &$this->_dbh;
60         }
61         return $dbh;
62     }
63
64     function query($sql)
65     {
66         return $this->_dbh->Execute($sql);
67     }
68
69     function quote($string)
70     {
71         return $this->_dbh->qstr($string);
72     }
73
74     function _disconnect()
75     {
76         if (0 and $this->_dbh)
77             $this->_dbh->close();
78     }
79
80     /**
81      * Opens a session.
82      *
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
87      * is good.
88      * @access private
89      */
90     function open($save_path, $session_name)
91     {
92         //$this->log("_open($save_path, $session_name)");
93         return true;
94     }
95
96     /**
97      * Closes a session.
98      *
99      * This function is called just after <i>write</i> call.
100      *
101      * @return boolean true just a variable to notify PHP that everything
102      * is good.
103      * @access private
104      */
105     function close()
106     {
107         //$this->log("_close()");
108         return true;
109     }
110
111     /**
112      * Reads the session data from DB.
113      *
114      * @param  string $id an id of current session
115      * @return string
116      * @access private
117      */
118     function read($id)
119     {
120         //$this->log("_read($id)");
121         $dbh = $this->_connect();
122         $table = $this->_table;
123         $qid = $dbh->qstr($id);
124         $res = '';
125         $row = $dbh->GetRow("SELECT sess_data FROM $table WHERE sess_id=$qid");
126         if ($row)
127             $res = $row[0];
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 = '';
137         }
138         return $res;
139     }
140
141     /**
142      * Saves the session data into DB.
143      *
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.
150      *
151      * @param  string  $id
152      * @param  string  $sess_data
153      * @return boolean true if data saved successfully  and false
154      * otherwise.
155      * @access private
156      */
157     function write($id, $sess_data)
158     {
159         if (defined("WIKI_XMLRPC") or defined("WIKI_SOAP")) return;
160
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());
166
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);
171
172         /* AffectedRows with sessions seems to be instable on certain platforms.
173          * Enable the safe and slow USE_SAFE_DBSESSION then.
174          */
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)");
181         } else {
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)");
190             }
191         }
192         $result = !$rs->EOF;
193         if ($result) $rs->free();
194         $this->_disconnect();
195         return $result;
196     }
197
198     /**
199      * Destroys a session.
200      *
201      * Removes a session from the table.
202      *
203      * @param  string  $id
204      * @return boolean true
205      * @access private
206      */
207     function destroy($id)
208     {
209         $dbh = $this->_connect();
210         $table = $this->_table;
211         $qid = $dbh->qstr($id);
212
213         $dbh->Execute("DELETE FROM $table WHERE sess_id=$qid");
214
215         $this->_disconnect();
216         return true;
217     }
218
219     /**
220      * Cleans out all expired sessions.
221      *
222      * @param  int     $maxlifetime session's time to live.
223      * @return boolean true
224      * @access private
225      */
226     function gc($maxlifetime)
227     {
228         $dbh = $this->_connect();
229         $table = $this->_table;
230         $threshold = time() - $maxlifetime;
231
232         $dbh->Execute("DELETE FROM $table WHERE sess_date < $threshold");
233
234         $this->_disconnect();
235         return true;
236     }
237
238     // WhoIsOnline support.
239     // TODO: ip-accesstime dynamic blocking API
240     function currentSessions()
241     {
242         $sessions = array();
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");
246         if ($rs->EOF) {
247             $rs->free();
248             return $sessions;
249         }
250         while (!$rs->EOF) {
251             $row = $rs->fetchRow();
252             $data = $row[0];
253             $date = $row[1];
254             $ip = $row[2];
255             if (preg_match('|^[a-zA-Z0-9/+=]+$|', $data))
256                 $data = base64_decode($data);
257             if ($date < 908437560 or $date > 1588437560)
258                 $date = 0;
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
263                 'date' => $date,
264                 'ip' => $ip);
265             $rs->MoveNext();
266         }
267         $rs->free();
268         $this->_disconnect();
269         return $sessions;
270     }
271 }
272
273 // Local Variables:
274 // mode: php
275 // tab-width: 8
276 // c-basic-offset: 4
277 // c-hanging-comment-ender-p: nil
278 // indent-tabs-mode: nil
279 // End: