Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
 
3
/**
4
 * sfCacheSessionStorage manages session storage via a signed cookie and cache backend.
5
 *
6
 * This class stores the session data in via sfCache instance and with an id issued in a
7
 * signed cookie. Useful when you don't want to store the session.
8
 *
9
 * @package    symfony
10
 * @subpackage storage
11
 * @author     Dustin Whittle <dustin.whittle@symfony-project.com>
12
 */
13
class sfCacheSessionStorage extends sfStorage
14
{
15
  protected
16
    $id          = null,
17
    $context     = null,
18
    $dispatcher  = null,
19
    $request     = null,
20
    $response    = null,
21
    $cache       = null,
22
    $data        = array(),
23
    $dataChanged = false;
24
 
25
  /**
26
   * Initialize this Storage.
27
   *
28
   * @param array $options  An associative array of initialization parameters.
29
   *                        session_name [required] name of session to use
30
   *                        session_cookie_path [required] cookie path
31
   *                        session_cookie_domain [required] cookie domain
32
   *                        session_cookie_lifetime [required] liftime of cookie
33
   *                        session_cookie_secure [required] send only if secure connection
34
   *                        session_cookie_http_only [required] accessible only via http protocol
35
   *
36
   * @return bool true, when initialization completes successfully.
37
   *
38
   * @throws <b>sfInitializationException</b> If an error occurs while initializing this Storage.
39
   */
40
  public function initialize($options = array())
41
  {
42
    // initialize parent
43
    parent::initialize(array_merge(array('session_name' => 'sfproject',
44
                                         'session_cookie_lifetime' => '+30 days',
45
                                         'session_cookie_path' => '/',
46
                                         'session_cookie_domain' => null,
47
                                         'session_cookie_secure' => false,
48
                                         'session_cookie_http_only' => true,
49
                                         'session_cookie_secret' => 'sf$ecret'), $options));
50
 
51
    // create cache instance
52
    if (isset($this->options['cache']) && $this->options['cache']['class'])
53
    {
54
      $this->cache = new $this->options['cache']['class'](is_array($this->options['cache']['param']) ? $this->options['cache']['param'] : array());
55
    }
56
    else
57
    {
58
      throw new InvalidArgumentException('sfCacheSessionStorage requires cache option.');
59
    }
60
 
61
    $this->context     = sfContext::getInstance();
62
 
63
    $this->dispatcher  = $this->context->getEventDispatcher();
64
    $this->request     = $this->context->getRequest();
65
    $this->response    = $this->context->getResponse();
66
 
67
    $cookie = $this->request->getCookie($this->options['session_name']);
68
 
69
    if(strpos($cookie, ':') !== false)
70
    {
71
      // split cookie data id:signature(id+secret)
72
      list($id, $signature) = explode(':', $cookie, 2);
73
 
74
      if($signature == sha1($id.':'.$this->options['session_cookie_secret']))
75
      {
76
        // cookie is valid
77
        $this->id = $id;
78
      }
79
      else
80
      {
81
        // cookie signature broken
82
        $this->id = null;
83
      }
84
    }
85
    else
86
    {
87
      // cookie format wrong
88
      $this->id = null;
89
    }
90
 
91
    if(empty($this->id))
92
    {
93
       $ip = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : 'localhost';
94
       $ua = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : 'ua';
95
 
96
       // generate new id based on random # / ip / user agent / secret
97
       $this->id = md5(rand(0, 999999).$ip.$ua.$this->options['session_cookie_secret']);
98
 
99
       if(sfConfig::get('sf_logging_enabled'))
100
       {
101
         $this->dispatcher->notify(new sfEvent($this, 'application.log', array('New session created')));
102
       }
103
 
104
       // only send cookie when id is issued
105
       $this->response->setCookie($this->options['session_name'],
106
                                  $this->id.':'.sha1($this->id.':'.$this->options['session_cookie_secret']),
107
                                  $this->options['session_cookie_lifetime'],
108
                                  $this->options['session_cookie_path'],
109
                                  $this->options['session_cookie_domain'],
110
                                  $this->options['session_cookie_secure'],
111
                                  $this->options['session_cookie_http_only']);
112
 
113
       $this->data = array();
114
    }
115
    else
116
    {
117
      // load data from cache
118
      $this->data = $this->cache->get($this->id, array());
119
 
120
      if(sfConfig::get('sf_logging_enabled'))
121
      {
122
        $this->dispatcher->notify(new sfEvent($this, 'application.log', array('Restored previous session')));
123
      }
124
    }
125
    session_id($this->id);
126
    $this->response->addCacheControlHttpHeader('private');
127
 
128
    return true;
129
  }
130
 
131
  /**
132
   * Write data to this storage.
133
   *
134
   * The preferred format for a key is directory style so naming conflicts can be avoided.
135
   *
136
   * @param string $key  A unique key identifying your data.
137
   * @param mixed  $data Data associated with your key.
138
   *
139
   * @return void
140
   */
141
  public function write($key, $data)
142
  {
143
    $this->dataChanged = true;
144
 
145
    $this->data[$key] =& $data;
146
  }
147
 
148
  /**
149
   * Read data from this storage.
150
   *
151
   * The preferred format for a key is directory style so naming conflicts can be avoided.
152
   *
153
   * @param string $key A unique key identifying your data.
154
   *
155
   * @return mixed Data associated with the key.
156
   */
157
  public function read($key)
158
  {
159
    $retval = null;
160
 
161
    if (isset($this->data[$key]))
162
    {
163
      $retval =& $this->data[$key];
164
    }
165
 
166
    return $retval;
167
  }
168
 
169
  /**
170
   * Remove data from this storage.
171
   *
172
   * The preferred format for a key is directory style so naming conflicts can be avoided.
173
   *
174
   * @param string $key A unique key identifying your data.
175
   *
176
   * @return mixed Data associated with the key.
177
   */
178
  public function remove($key)
179
  {
180
    $retval = null;
181
 
182
    if (isset($this->data[$key]))
183
    {
184
      $this->dataChanged = true;
185
 
186
      $retval =& $this->data[$key];
187
      unset($this->data[$key]);
188
    }
189
 
190
    return $retval;
191
  }
192
 
193
  /**
194
   * Regenerates id that represents this storage.
195
   *
196
   * @param boolean $destroy Destroy session when regenerating?
197
   *
198
   * @return boolean True if session regenerated, false if error
199
   *
200
   * @throws <b>sfStorageException</b> If an error occurs while regenerating this storage
201
   */
202
  public function regenerate($destroy = false)
203
  {
204
    if($destroy)
205
    {
206
      $this->data = array();
207
      $this->cache->remove($this->id);
208
    }
209
 
210
    // generate session id
211
    $this->id = md5(rand(0, 999999).$_SERVER['REMOTE_ADDR'].$_SERVER['HTTP_USER_AGENT'].$this->options['session_cookie_secret']);
212
 
213
    // save data to cache
214
    $this->cache->set($this->id, $this->data);
215
 
216
    // update session id in signed cookie
217
    $this->response->setCookie($this->options['session_name'],
218
                               $this->id.':'.sha1($this->id.':'.$this->options['session_cookie_secret']),
219
                               $this->options['session_cookie_lifetime'],
220
                               $this->options['session_cookie_path'],
221
                               $this->options['session_cookie_domain'],
222
                               $this->options['session_cookie_secure'],
223
                               $this->options['session_cookie_http_only']);
224
    session_id($this->id);
225
    return true;
226
  }
227
 
228
  /**
229
   * Expires the session storage instance.
230
   */
231
  public function expire()
232
  {
233
    // destroy data and regenerate id
234
    $this->regenerate(true);
235
 
236
    if(sfConfig::get('sf_logging_enabled'))
237
    {
238
      $this->dispatcher->notify(new sfEvent($this, 'application.log', array('new session created due to expiraton')));
239
    }
240
  }
241
 
242
  /**
243
   * Executes the shutdown procedure.
244
   *
245
   * @throws <b>sfStorageException</b> If an error occurs while shutting down this storage
246
   */
247
  public function shutdown()
248
  {
249
    // only update cache if session has changed
250
    if($this->dataChanged === true)
251
    {
252
      $this->cache->set($this->id, $this->data);
253
      if(sfConfig::get('sf_logging_enabled'))
254
      {
255
        $this->dispatcher->notify(new sfEvent($this, 'application.log', array('Storing session to cache')));
256
        // $this->dispatcher->notify(new sfEvent($this, 'application.log', array(var_export($this->data, true))));
257
      }
258
    }
259
  }
260
}