Development

/branches/1.0/lib/storage/sfMySQLSessionStorage.class.php

You must first sign up to be able to contribute.

root/branches/1.0/lib/storage/sfMySQLSessionStorage.class.php

Revision 8664, 8.2 kB (checked in by FabianLange, 6 years ago)

made sfMySQLSessionStorage more robust by using SQL date functions and no longer injecting php timestamps. MySQL Now() works on both DateTime? and TimeStamp? columns ok and using the native date + INTERVAL $lifetime SECONDS possible time troubles are reduced. (fixes #3394)

  • Property svn:mime-type set to text/x-php
  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Rev Date
Line 
1 <?php
2
3 /*
4  * This file is part of the symfony package.
5  * (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
6  * (c) 2004-2006 Sean Kerr <sean@code-box.org>
7  *
8  * For the full copyright and license information, please view the LICENSE
9  * file that was distributed with this source code.
10  */
11
12 /**
13  * Provides support for session storage using a MySQL brand database.
14  *
15  * <b>Required parameters:</b>
16  *
17  * # <b>db_table</b> - [none] - The database table in which session data will be
18  *                              stored.
19  *
20  * <b>Optional parameters:</b>
21  *
22  * # <b>db_id_col</b>    - [sess_id]   - The database column in which the
23  *                                       session id will be stored.
24  * # <b>db_data_col</b>  - [sess_data] - The database column in which the
25  *                                       session data will be stored.
26  * # <b>db_time_col</b>  - [sess_time] - The database column in which the
27  *                                       session timestamp will be stored.
28  * # <b>session_name</b> - [symfony]   - The name of the session.
29  *
30  * @package    symfony
31  * @subpackage storage
32  * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
33  * @author     Sean Kerr <sean@code-box.org>
34  * @version    SVN: $Id$
35  */
36 class sfMySQLSessionStorage extends sfSessionStorage
37 {
38   protected
39     $resource = null;
40
41   /**
42    * Initializes this Storage instance.
43    *
44    * @param sfContext A sfContext instance
45    * @param array   An associative array of initialization parameters
46    *
47    * @return boolean true, if initialization completes successfully, otherwise false
48    *
49    * @throws <b>sfInitializationException</b> If an error occurs while initializing this Storage
50    */
51   public function initialize($context, $parameters = null)
52   {
53     // disable auto_start
54     $parameters['auto_start'] = false;
55
56     // initialize the parent
57     parent::initialize($context, $parameters);
58
59     if (!$this->getParameterHolder()->has('db_table'))
60     {
61         // missing required 'db_table' parameter
62         $error = 'Factory configuration file is missing required "db_table" parameter for the Storage category';
63
64         throw new sfInitializationException($error);
65     }
66
67     // use this object as the session handler
68     session_set_save_handler(array($this, 'sessionOpen'),
69                              array($this, 'sessionClose'),
70                              array($this, 'sessionRead'),
71                              array($this, 'sessionWrite'),
72                              array($this, 'sessionDestroy'),
73                              array($this, 'sessionGC'));
74
75     // start our session
76     session_start();
77   }
78
79   /**
80    * Closes a session.
81    *
82    * @return boolean true, if the session was closed, otherwise false
83    */
84   public function sessionClose()
85   {
86     // do nothing
87     return true;
88   }
89
90   /**
91    * Destroys a session.
92    *
93    * @param string A session ID
94    *
95    * @return boolean true, if the session was destroyed, otherwise an exception is thrown
96    *
97    * @throws <b>sfDatabaseException</b> If the session cannot be destroyed.
98    */
99   public function sessionDestroy($id)
100   {
101     // get table/column
102     $db_table  = $this->getParameterHolder()->get('db_table');
103     $db_id_col = $this->getParameterHolder()->get('db_id_col', 'sess_id');
104
105     // cleanup the session id, just in case
106     $id = mysql_real_escape_string($id, $this->resource);
107
108     // delete the record associated with this id
109     $sql = 'DELETE FROM '.$db_table.' WHERE '.$db_id_col.' = \''.$id.'\'';
110
111     if (@mysql_query($sql, $this->resource))
112     {
113       return true;
114     }
115
116     // failed to destroy session
117     $error = 'MySQLSessionStorage cannot destroy session id "%s"';
118     $error = sprintf($error, $id);
119
120     throw new sfDatabaseException($error);
121   }
122
123   /**
124    * Cleans up old sessions.
125    *
126    * @param int The lifetime of a session in seconds
127    *
128    * @return boolean true, if old sessions have been cleaned, otherwise an exception is thrown
129    *
130    * @throws <b>sfDatabaseException</b> If any old sessions cannot be cleaned
131    */
132   public function sessionGC($lifetime)
133   {
134     // get table/column
135     $db_table    = $this->getParameterHolder()->get('db_table');
136     $db_time_col = $this->getParameterHolder()->get('db_time_col', 'sess_time');
137
138     // delete the record associated with this id
139     $sql = 'DELETE FROM '.$db_table.' '.
140            'WHERE '.$db_time_col.' + INTERVAL '.$lifetime.' SECOND < NOW()';
141
142     if (@mysql_query($sql, $this->resource))
143     {
144       return true;
145     }
146
147     // failed to cleanup old sessions
148     $error = 'MySQLSessionStorage cannot delete old sessions';
149
150     throw new sfDatabaseException($error);
151   }
152
153   /**
154    * Opens a session.
155    *
156    * @param string
157    * @param string
158    *
159    * @return boolean true, if the session was opened, otherwise an exception is thrown
160    *
161    * @throws <b>sfDatabaseException</b> If a connection with the database does not exist or cannot be created
162    */
163   public function sessionOpen($path, $name)
164   {
165     // what database are we using?
166     $database = $this->getParameterHolder()->get('database', 'default');
167
168     // get the database resource
169     $this->resource = $this->getContext()
170                            ->getDatabaseManager()
171                            ->getDatabase($database)
172                            ->getResource();
173
174     return true;
175   }
176
177   /**
178    * Reads a session.
179    *
180    * @param string A session ID
181    *
182    * @return boolean true, if the session was read, otherwise an exception is thrown
183    *
184    * @throws <b>sfDatabaseException</b> If the session cannot be read
185    */
186   public function sessionRead($id)
187   {
188     // get table/column
189     $db_table    = $this->getParameterHolder()->get('db_table');
190     $db_data_col = $this->getParameterHolder()->get('db_data_col', 'sess_data');
191     $db_id_col   = $this->getParameterHolder()->get('db_id_col', 'sess_id');
192     $db_time_col = $this->getParameterHolder()->get('db_time_col', 'sess_time');
193
194     // cleanup the session id, just in case
195     $id = mysql_real_escape_string($id, $this->resource);
196
197     // delete the record associated with this id
198     $sql = 'SELECT '.$db_data_col.' ' .
199            'FROM '.$db_table.' ' .
200            'WHERE '.$db_id_col.' = \''.$id.'\'';
201
202     $result = @mysql_query($sql, $this->resource);
203
204     if ($result != false && @mysql_num_rows($result) == 1)
205     {
206       // found the session
207       $data = mysql_fetch_row($result);
208
209       return $data[0];
210     }
211     else
212     {
213       // session does not exist, create it
214       $sql = 'INSERT INTO '.$db_table.' ('.$db_id_col.', ' .
215              $db_data_col.', '.$db_time_col.') VALUES (' .
216              '\''.$id.'\', \'\', NOW())';
217
218       if (@mysql_query($sql, $this->resource))
219       {
220         return '';
221       }
222
223       // can't create record
224       $error = 'MySQLSessionStorage cannot create new record for id "%s"';
225       $error = sprintf($error, $id);
226
227       throw new sfDatabaseException($error);
228     }
229   }
230
231   /**
232    * Writes session data.
233    *
234    * @param string A session ID
235    * @param string A serialized chunk of session data
236    *
237    * @return boolean true, if the session was written, otherwise an exception is thrown
238    *
239    * @throws <b>sfDatabaseException</b> If the session data cannot be written
240    */
241   public function sessionWrite($id, &$data)
242   {
243     // get table/column
244     $db_table    = $this->getParameterHolder()->get('db_table');
245     $db_data_col = $this->getParameterHolder()->get('db_data_col', 'sess_data');
246     $db_id_col   = $this->getParameterHolder()->get('db_id_col', 'sess_id');
247     $db_time_col = $this->getParameterHolder()->get('db_time_col', 'sess_time');
248
249     // cleanup the session id and data, just in case
250     $id   = mysql_real_escape_string($id, $this->resource);
251     $data = mysql_real_escape_string($data, $this->resource);
252
253     // delete the record associated with this id
254     $sql = 'UPDATE '.$db_table.' ' .
255            'SET '.$db_data_col.' = \''.$data.'\', ' .
256            $db_time_col.' = NOW() ' .
257            'WHERE '.$db_id_col.' = \''.$id.'\'';
258
259     if (@mysql_query($sql, $this->resource))
260     {
261       return true;
262     }
263
264     // failed to write session data
265     $error = 'MySQLSessionStorage cannot write session data for id "%s"';
266     $error = sprintf($error, $id);
267
268     throw new sfDatabaseException($error);
269   }
270
271   /**
272    * Executes the shutdown procedure.
273    *
274    */
275   public function shutdown()
276   {
277   }
278 }
279
Note: See TracBrowser for help on using the browser.