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