]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/DbSession/PDO.php
fix more refs
[SourceForge/phpwiki.git] / lib / DbSession / PDO.php
1 <?php rcs_id('$Id: PDO.php,v 1.2 2006-02-22 20:56:24 rurban Exp $');
2
3 /** 
4  * Db sessions for PDO, based on pear DB Sessions.
5  *
6  * @author: Reini Urban
7  */
8 class DbSession_PDO
9 extends DbSession
10 {
11     var $_backend_type = "PDO";
12
13     function DbSession_PDO ($dbh, $table) {
14
15         $this->_dbh = $dbh;
16         $this->_table = $table;
17
18         ini_set('session.save_handler','user');
19         session_module_name('user'); // new style
20         session_set_save_handler(array(&$this, 'open'),
21                                  array(&$this, 'close'),
22                                  array(&$this, 'read'),
23                                  array(&$this, 'write'),
24                                  array(&$this, 'destroy'),
25                                  array(&$this, 'gc'));
26         return $this;
27     }
28
29     function & _connect() {
30         $dbh =& $this->_dbh;
31         if (!$dbh or !is_object($dbh)) {
32             global $DBParams;
33             $db = new WikiDB_backend_PDO($DBParams);
34             $this->_dbh =& $db->_dbh;
35             $this->_backend =& $db;
36         }
37         return $dbh->_dbh;
38     }
39     
40     function query($sql) {
41         return $this->_backend->query($sql);
42     }
43
44     function quote($string) {
45         return $this->_backend->quote($sql);
46     }
47
48     function _disconnect() {
49         if (0 and $this->_dbh)
50             unset($this->_dbh);
51     }
52
53     /**
54      * Opens a session.
55      *
56      * Actually this function is a fake for session_set_save_handle.
57      * @param  string $save_path a path to stored files
58      * @param  string $session_name a name of the concrete file
59      * @return boolean true just a variable to notify PHP that everything 
60      * is good.
61      * @access private
62      */
63     function open ($save_path, $session_name) {
64         //$this->log("_open($save_path, $session_name)");
65         return true;
66     }
67
68     /**
69      * Closes a session.
70      *
71      * This function is called just after <i>write</i> call.
72      *
73      * @return boolean true just a variable to notify PHP that everything 
74      * is good.
75      * @access private
76      */
77     function close() {
78         //$this->log("_close()");
79         return true;
80     }
81
82     /**
83      * Reads the session data from DB.
84      *
85      * @param  string $id an id of current session
86      * @return string
87      * @access private
88      */
89     function read ($id) {
90         //$this->log("_read($id)");
91         $dbh = $this->_connect();
92         $table = $this->_table;
93         $sth = $dbh->prepare("SELECT sess_data FROM $table WHERE sess_id=?");
94         $sth->bindParam(1, $id, PDO_PARAM_STR, 32);
95         if ($sth->execute()) $res = $sth->fetchSingle();
96         else $res = '';
97         $this->_disconnect();
98         if (!empty($res) and isa($dbh, 'ADODB_postgres64'))
99             $res = base64_decode($res);
100         if (strlen($res) > 4000) {
101             trigger_error("Overlarge session data! ".strlen($res).
102                         " gt. 4000", E_USER_WARNING);
103             $res = preg_replace('/s:6:"_cache";O:12:"WikiDB_cache".+}$/',"",$res);
104             $res = preg_replace('/s:12:"_cached_html";s:.+",s:4:"hits"/','s:4:"hits"',$res);
105             if (strlen($res) > 4000) $res = '';
106         }
107         return $res;
108     }
109   
110     /**
111      * Saves the session data into DB.
112      *
113      * Just  a  comment:       The  "write"  handler  is  not 
114      * executed until after the output stream is closed. Thus,
115      * output from debugging statements in the "write" handler
116      * will  never be seen in the browser. If debugging output
117      * is  necessary, it is suggested that the debug output be
118      * written to a file instead.
119      *
120      * @param  string $id
121      * @param  string $sess_data
122      * @return boolean true if data saved successfully  and false
123      * otherwise.
124      * @access private
125      */
126     function write ($id, $sess_data) {
127         
128         $dbh = $this->_connect();
129         $table = $this->_table;
130         $time = time();
131
132         // postgres can't handle binary data in a TEXT field.
133         if (isa($dbh, 'ADODB_postgres64'))
134             $sess_data = base64_encode($sess_data);
135
136         /* AffectedRows with sessions seems to be instable on certain platforms.
137          * Enable the safe and slow USE_SAFE_DBSESSION then.
138          */
139         if (USE_SAFE_DBSESSION) {
140             $this->_backend->beginTransaction();
141             $rs = $this->query("DELETE FROM $table"
142                                . " WHERE sess_id=$qid");
143             $sth = $dbh->prepare("INSERT INTO $table"
144                                 . " (sess_id, sess_data, sess_date, sess_ip)"
145                                  . " VALUES (?, ?, ?, ?)");
146             $sth->bindParam(1, $id, PDO_PARAM_STR, 32);
147             $sth->bindParam(2, $sess_data, PDO_PARAM_LOB);
148             $sth->bindParam(3, $time, PDO_PARAM_INT);
149             $sth->bindParam(4, $GLOBALS['request']->get('REMOTE_ADDR'), PDO_PARAM_STR, 15);
150             if ($result = $sth->execute()) {
151                 $this->_backend->commit();
152             } else {
153                 $this->_backend->rollBack();
154             }
155         } else {
156             $sth = $dbh->prepare("UPDATE $table"
157                                 . " SET sess_data=?, sess_date=?, sess_ip=?"
158                                 . " WHERE sess_id=?");
159             $sth->bindParam(1, $sess_data, PDO_PARAM_LOB);
160             $sth->bindParam(2, $time, PDO_PARAM_INT);
161             $sth->bindParam(3, $GLOBALS['request']->get('REMOTE_ADDR'), PDO_PARAM_STR, 15);
162             $sth->bindParam(4, $id, PDO_PARAM_STR, 32);
163             $result = $sth->execute(); // implicit affected rows
164             if ( $result === false or $result < 1 ) { // false or int > 0
165                 $sth = $dbh->prepare("INSERT INTO $table"
166                                      . " (sess_id, sess_data, sess_date, sess_ip)"
167                                      . " VALUES (?, ?, ?, ?)");
168                 $sth->bindParam(1, $id, PDO_PARAM_STR, 32);
169                 $sth->bindParam(2, $sess_data, PDO_PARAM_LOB);
170                 $sth->bindParam(3, $time, PDO_PARAM_INT);
171                 $sth->bindParam(4, $GLOBALS['request']->get('REMOTE_ADDR'), PDO_PARAM_STR, 15);
172                 $result = $sth->execute();
173             }
174         }
175         $this->_disconnect();
176         return $result;
177     }
178
179     /**
180      * Destroys a session.
181      *
182      * Removes a session from the table.
183      *
184      * @param  string $id
185      * @return boolean true 
186      * @access private
187      */
188     function destroy ($id) {
189         $table = $this->_table;
190         $dbh = $this->_connect();
191         $sth = $dbh->prepare("DELETE FROM $table WHERE sess_id=?");
192         $sth->bindParam(1, $id, PDO_PARAM_STR, 32);
193         $sth->execute();
194         $this->_disconnect();
195         return true;     
196     }
197
198     /**
199      * Cleans out all expired sessions.
200      *
201      * @param  int $maxlifetime session's time to live.
202      * @return boolean true
203      * @access private
204      */
205     function gc ($maxlifetime) {
206         $table = $this->_table;
207         $threshold = time() - $maxlifetime;
208         $dbh = $this->_connect();
209         $sth = $dbh->prepare("DELETE FROM $table WHERE sess_date < ?");
210         $sth->bindParam(1, $threshold, PDO_PARAM_INT);
211         $sth->execute();
212         $this->_disconnect();
213         return true;
214     }
215
216     // WhoIsOnline support. 
217     // TODO: ip-accesstime dynamic blocking API
218     function currentSessions() {
219         $sessions = array();
220         $table = $this->_table;
221         $dbh = $this->_connect();
222         $sth = $dbh->prepare("SELECT sess_data,sess_date,sess_ip FROM $table ORDER BY sess_date DESC");
223         if (!$sth->execute()) {
224             return $sessions;
225         }
226         while ($row = $sth->fetch(PDO_FETCH_NUM)) {
227             $data = $row[0];
228             $date = $row[1];
229             $ip   = $row[2];
230             if (preg_match('|^[a-zA-Z0-9/+=]+$|', $data))
231                 $data = base64_decode($data);
232             if ($date < 908437560 or $date > 1588437560)
233                 $date = 0;
234             // session_data contains the <variable name> + "|" + <packed string>
235             // we need just the wiki_user object (might be array as well)
236             $user = strstr($data, "wiki_user|");
237             $sessions[] = array('wiki_user' => substr($user,10), // from "O:" onwards
238                                 'date' => $date,
239                                 'ip' => $ip);
240         }
241         $this->_disconnect();
242         return $sessions;
243     }
244 }
245
246 // $Log: not supported by cvs2svn $
247 // Revision 1.1  2005/02/11 14:41:40  rurban
248 // seperate DbSession classes: less memory, a bit slower
249 //
250
251 // Local Variables:
252 // mode: php
253 // tab-width: 8
254 // c-basic-offset: 4
255 // c-hanging-comment-ender-p: nil
256 // indent-tabs-mode: nil
257 // End:
258 ?>