]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/DbSession.php
start with backend type DB_Session's, for ADODB and more
[SourceForge/phpwiki.git] / lib / DbSession.php
1 <?php rcs_id('$Id: DbSession.php,v 1.4 2004-02-26 01:38:16 rurban Exp $');
2
3 /**
4  * Store sessions data in Pear DB / ADODB ....
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 class DB_Session
13 {
14     /**
15      * Constructor
16      *
17      * @param mixed $dbh
18      * Pear DB handle, or WikiDB object (from which the Pear DB handle will
19      * be extracted.
20      *
21      * @param string $table
22      * Name of SQL table containing session data.
23      */
24     function DB_Session(&$dbh, $table = 'session') {
25         // Coerce WikiDB to PearDB or ADODB.
26         // Todo: adodb/dba handlers
27         $db_type = $GLOBALS['DBParams']['dbtype'];
28         if (isa($dbh, 'WikiDB')) {
29             $backend = &$dbh->_backend;
30             $db_type = substr(get_class($dbh),7);
31             $class = "DB_Session_".$db_type;
32             if (class_exists($class)) {
33                 return new $class(&$backend->_dbh, $table);
34                 //return new DB_Session_SQL(&$dbh, $table);
35                 //return new DB_Session_ADODB(&$dbh, $table);
36             }
37         }
38         //Fixme: E_USER_WARNING ignored!
39         trigger_error(sprintf(
40 _("Your WikiDB DB backend '%s' cannot be used for DB_Session. Set USE_DB_SESSION to false."),
41                              $db_type), E_USER_WARNING);
42         return;
43      }
44 }
45
46 class DB_Session_SQL
47 extends DB_Session
48 {
49     var $_backend_type = "SQL";
50
51     function DB_Session_SQL ($dbh, $table) {
52
53         $this->_dbh = &$dbh;
54         $this->_table = $table;
55
56         ini_set('session.save_handler','user');
57         session_module_name('user'); // new style
58         session_set_save_handler(array(&$this, 'do_open'),
59                                  array(&$this, 'do_close'),
60                                  array(&$this, 'do_read'),
61                                  array(&$this, 'do_write'),
62                                  array(&$this, 'do_destroy'),
63                                  array(&$this, 'do_gc'));
64     }
65
66     function _connect() {
67         $dbh = &$this->_dbh;
68         $this->_connected = (bool)$dbh->connection;
69         if (!$this->_connected) {
70             $res = $dbh->connect($dbh->dsn);
71             if (DB::isError($res)) {
72                 error_log("PhpWiki::DB_Session::_connect: " . $res->getMessage());
73             }
74         }
75         return $dbh;
76     }
77
78     function _disconnect() {
79         if (!$this->_connected)
80             $this->_dbh->disconnect();
81     }
82
83     /**
84      * Opens a session.
85      *
86      * Actually this function is a fake for session_set_save_handle.
87      * @param  string $save_path a path to stored files
88      * @param  string $session_name a name of the concrete file
89      * @return boolean true just a variable to notify PHP that everything 
90      * is good.
91      * @access private
92      */
93     function do_open ($save_path, $session_name) {
94         //$this->log("_do_open($save_path, $session_name)");
95         return true;
96     }
97
98     /**
99      * Closes a session.
100      *
101      * This function is called just after <i>do_write</i> call.
102      *
103      * @return boolean true just a variable to notify PHP that everything 
104      * is good.
105      * @access private
106      */
107     function do_close() {
108         //$this->log("_do_close()");
109         return true;
110     }
111
112     /**
113      * Reads the session data from DB.
114      *
115      * @param  string $id an id of current session
116      * @return string
117      * @access private
118      */
119     function do_read ($id) {
120         //$this->log("_do_read($id)");
121         $dbh = &$this->_connect();
122         $table = $this->_table;
123         $qid = $dbh->quote($id);
124     
125         $res = $dbh->getOne("SELECT sess_data FROM $table WHERE sess_id=$qid");
126
127         $this->_disconnect();
128         if (DB::isError($res) || empty($res))
129             return '';
130         if (preg_match('|^[a-zA-Z0-9/+=]+$|', $res))
131             $res = base64_decode($res);
132         return $res;
133     }
134   
135     /**
136      * Saves the session data into DB.
137      *
138      * Just  a  comment:       The  "write"  handler  is  not 
139      * executed until after the output stream is closed. Thus,
140      * output from debugging statements in the "write" handler
141      * will  never be seen in the browser. If debugging output
142      * is  necessary, it is suggested that the debug output be
143      * written to a file instead.
144      *
145      * @param  string $id
146      * @param  string $sess_data
147      * @return boolean true if data saved successfully  and false
148      * otherwise.
149      * @access private
150      */
151     function do_write ($id, $sess_data) {
152         
153         $dbh = &$this->_connect();
154         $table = $this->_table;
155         $qid = $dbh->quote($id);
156         $time = time();
157
158         // postgres can't handle binary data in a TEXT field.
159         if (isa($dbh, 'DB_pgsql'))
160             $sess_data = base64_encode($sess_data);
161         $qdata = $dbh->quote($sess_data);
162         
163         $res = $dbh->query("UPDATE $table"
164                            . " SET sess_data=$qdata, sess_date=$time"
165                            . " WHERE sess_id=$qid");
166
167         if ($dbh->affectedRows() == 0)
168             $res = $dbh->query("INSERT INTO $table"
169                                . " (sess_id, sess_data, sess_date)"
170                                . " VALUES ($qid, $qdata, $time)");
171
172         $this->_disconnect();
173         return ! DB::isError($res);
174     }
175
176     /**
177      * Destroys a session.
178      *
179      * Removes a session from the table.
180      *
181      * @param  string $id
182      * @return boolean true 
183      * @access private
184      */
185     function do_destroy ($id) {
186         $dbh = &$this->_connect();
187         $table = $this->_table;
188         $qid = $dbh->quote($id);
189
190         $dbh->query("DELETE FROM $table WHERE sess_id=$qid");
191
192         $this->_disconnect();
193         return true;     
194     }
195
196     /**
197      * Cleans out all expired sessions.
198      *
199      * @param  int $maxlifetime session's time to live.
200      * @return boolean true
201      * @access private
202      */
203     function do_gc ($maxlifetime) {
204         $dbh = &$this->_connect();
205         $table = $this->_table;
206         $threshold = time() - $maxlifetime;
207
208         $dbh->query("DELETE FROM $table WHERE sess_date < $threshold");
209
210         $this->_disconnect();
211         return true;
212     }
213 }
214
215
216 // adodb-session wrapper: warning! uses different db layout
217 class DB_Session_ADODB_test
218 extends DB_Session
219 {
220     var $_backend_type = "ADODB";
221
222     function DB_Session_ADODB_test ($dbh, $table) {
223     }
224 }
225
226 // Local Variables:
227 // mode: php
228 // tab-width: 8
229 // c-basic-offset: 4
230 // c-hanging-comment-ender-p: nil
231 // indent-tabs-mode: nil
232 // End:
233 ?>