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