Overview

Namespaces

  • Evenement
  • None
  • PHP
  • Psr
    • Http
      • Message
  • Ratchet
    • Http
    • RFC6455
      • Handshake
      • Messaging
    • Server
    • Session
      • Serialize
      • Storage
        • Proxy
    • Wamp
    • WebSocket
  • React
    • EventLoop
      • Tick
      • Timer
    • Socket
    • Stream
  • Symfony
    • Component
      • HttpFoundation
        • Session
          • Attribute
          • Flash
          • Storage
            • Handler
            • Proxy
      • Routing
        • Annotation
        • Exception
        • Generator
          • Dumper
        • Loader
          • DependencyInjection
        • Matcher
          • Dumper
        • Tests
          • Annotation
          • Fixtures
            • AnnotatedClasses
            • OtherAnnotatedClasses
          • Generator
            • Dumper
          • Loader
          • Matcher
            • Dumper

Classes

  • SessionProvider
  • Overview
  • Namespace
  • Class
  • Tree
  1: <?php
  2: namespace Ratchet\Session;
  3: use Ratchet\ConnectionInterface;
  4: use Ratchet\Http\HttpServerInterface;
  5: use Psr\Http\Message\RequestInterface;
  6: use Ratchet\Session\Storage\VirtualSessionStorage;
  7: use Ratchet\Session\Serialize\HandlerInterface;
  8: use Symfony\Component\HttpFoundation\Session\Session;
  9: use Symfony\Component\HttpFoundation\Session\Storage\Handler\NullSessionHandler;
 10: 
 11: /**
 12:  * This component will allow access to session data from your website for each user connected
 13:  * Symfony HttpFoundation is required for this component to work
 14:  * Your website must also use Symfony HttpFoundation Sessions to read your sites session data
 15:  * If your are not using at least PHP 5.4 you must include a SessionHandlerInterface stub (is included in Symfony HttpFoundation, loaded w/ composer)
 16:  */
 17: class SessionProvider implements HttpServerInterface {
 18:     /**
 19:      * @var \Ratchet\MessageComponentInterface
 20:      */
 21:     protected $_app;
 22: 
 23:     /**
 24:      * Selected handler storage assigned by the developer
 25:      * @var \SessionHandlerInterface
 26:      */
 27:     protected $_handler;
 28: 
 29:     /**
 30:      * Null storage handler if no previous session was found
 31:      * @var \SessionHandlerInterface
 32:      */
 33:     protected $_null;
 34: 
 35:     /**
 36:      * @var \Ratchet\Session\Serialize\HandlerInterface
 37:      */
 38:     protected $_serializer;
 39: 
 40:     /**
 41:      * @param \Ratchet\Http\HttpServerInterface           $app
 42:      * @param \SessionHandlerInterface                    $handler
 43:      * @param array                                       $options
 44:      * @param \Ratchet\Session\Serialize\HandlerInterface $serializer
 45:      * @throws \RuntimeException
 46:      */
 47:     public function __construct(HttpServerInterface $app, \SessionHandlerInterface $handler, array $options = array(), HandlerInterface $serializer = null) {
 48:         $this->_app     = $app;
 49:         $this->_handler = $handler;
 50:         $this->_null    = new NullSessionHandler;
 51: 
 52:         ini_set('session.auto_start', 0);
 53:         ini_set('session.cache_limiter', '');
 54:         ini_set('session.use_cookies', 0);
 55: 
 56:         $this->setOptions($options);
 57: 
 58:         if (null === $serializer) {
 59:             $serialClass = __NAMESPACE__ . "\\Serialize\\{$this->toClassCase(ini_get('session.serialize_handler'))}Handler"; // awesome/terrible hack, eh?
 60:             if (!class_exists($serialClass)) {
 61:                 throw new \RuntimeException('Unable to parse session serialize handler');
 62:             }
 63: 
 64:             $serializer = new $serialClass;
 65:         }
 66: 
 67:         $this->_serializer = $serializer;
 68:     }
 69: 
 70:     /**
 71:      * {@inheritdoc}
 72:      */
 73:     public function onOpen(ConnectionInterface $conn, RequestInterface $request = null) {
 74:         $sessionName = ini_get('session.name');
 75: 
 76:         $id = array_reduce($request->getHeader('Cookie'), function($accumulator, $cookie) use ($sessionName) {
 77:             if ($accumulator) {
 78:                 return $accumulator;
 79:             }
 80: 
 81:             $crumbs = $this->parseCookie($cookie);
 82: 
 83:             return isset($crumbs['cookies'][$sessionName]) ? $crumbs['cookies'][$sessionName] : false;
 84:         }, false);
 85: 
 86:         if (null === $request || false === $id) {
 87:             $saveHandler = $this->_null;
 88:             $id = '';
 89:         } else {
 90:             $saveHandler = $this->_handler;
 91:         }
 92: 
 93:         $conn->Session = new Session(new VirtualSessionStorage($saveHandler, $id, $this->_serializer));
 94: 
 95:         if (ini_get('session.auto_start')) {
 96:             $conn->Session->start();
 97:         }
 98: 
 99:         return $this->_app->onOpen($conn, $request);
100:     }
101: 
102:     /**
103:      * {@inheritdoc}
104:      */
105:     function onMessage(ConnectionInterface $from, $msg) {
106:         return $this->_app->onMessage($from, $msg);
107:     }
108: 
109:     /**
110:      * {@inheritdoc}
111:      */
112:     function onClose(ConnectionInterface $conn) {
113:         // "close" session for Connection
114: 
115:         return $this->_app->onClose($conn);
116:     }
117: 
118:     /**
119:      * {@inheritdoc}
120:      */
121:     function onError(ConnectionInterface $conn, \Exception $e) {
122:         return $this->_app->onError($conn, $e);
123:     }
124: 
125:     /**
126:      * Set all the php session. ini options
127:      * © Symfony
128:      * @param array $options
129:      * @return array
130:      */
131:     protected function setOptions(array $options) {
132:         $all = array(
133:             'auto_start', 'cache_limiter', 'cookie_domain', 'cookie_httponly',
134:             'cookie_lifetime', 'cookie_path', 'cookie_secure',
135:             'entropy_file', 'entropy_length', 'gc_divisor',
136:             'gc_maxlifetime', 'gc_probability', 'hash_bits_per_character',
137:             'hash_function', 'name', 'referer_check',
138:             'serialize_handler', 'use_cookies',
139:             'use_only_cookies', 'use_trans_sid', 'upload_progress.enabled',
140:             'upload_progress.cleanup', 'upload_progress.prefix', 'upload_progress.name',
141:             'upload_progress.freq', 'upload_progress.min-freq', 'url_rewriter.tags'
142:         );
143: 
144:         foreach ($all as $key) {
145:             if (!array_key_exists($key, $options)) {
146:                 $options[$key] = ini_get("session.{$key}");
147:             } else {
148:                 ini_set("session.{$key}", $options[$key]);
149:             }
150:         }
151: 
152:         return $options;
153:     }
154: 
155:     /**
156:      * @param string $langDef Input to convert
157:      * @return string
158:      */
159:     protected function toClassCase($langDef) {
160:         return str_replace(' ', '', ucwords(str_replace('_', ' ', $langDef)));
161:     }
162: 
163:     /**
164:      * Taken from Guzzle3
165:      */
166:     private static $cookieParts = array(
167:         'domain'      => 'Domain',
168:         'path'        => 'Path',
169:         'max_age'     => 'Max-Age',
170:         'expires'     => 'Expires',
171:         'version'     => 'Version',
172:         'secure'      => 'Secure',
173:         'port'        => 'Port',
174:         'discard'     => 'Discard',
175:         'comment'     => 'Comment',
176:         'comment_url' => 'Comment-Url',
177:         'http_only'   => 'HttpOnly'
178:     );
179: 
180:     /**
181:      * Taken from Guzzle3
182:      */
183:     private function parseCookie($cookie, $host = null, $path = null, $decode = false) {
184:         // Explode the cookie string using a series of semicolons
185:         $pieces = array_filter(array_map('trim', explode(';', $cookie)));
186: 
187:         // The name of the cookie (first kvp) must include an equal sign.
188:         if (empty($pieces) || !strpos($pieces[0], '=')) {
189:             return false;
190:         }
191: 
192:         // Create the default return array
193:         $data = array_merge(array_fill_keys(array_keys(self::$cookieParts), null), array(
194:             'cookies'   => array(),
195:             'data'      => array(),
196:             'path'      => $path ?: '/',
197:             'http_only' => false,
198:             'discard'   => false,
199:             'domain'    => $host
200:         ));
201:         $foundNonCookies = 0;
202: 
203:         // Add the cookie pieces into the parsed data array
204:         foreach ($pieces as $part) {
205: 
206:             $cookieParts = explode('=', $part, 2);
207:             $key = trim($cookieParts[0]);
208: 
209:             if (count($cookieParts) == 1) {
210:                 // Can be a single value (e.g. secure, httpOnly)
211:                 $value = true;
212:             } else {
213:                 // Be sure to strip wrapping quotes
214:                 $value = trim($cookieParts[1], " \n\r\t\0\x0B\"");
215:                 if ($decode) {
216:                     $value = urldecode($value);
217:                 }
218:             }
219: 
220:             // Only check for non-cookies when cookies have been found
221:             if (!empty($data['cookies'])) {
222:                 foreach (self::$cookieParts as $mapValue => $search) {
223:                     if (!strcasecmp($search, $key)) {
224:                         $data[$mapValue] = $mapValue == 'port' ? array_map('trim', explode(',', $value)) : $value;
225:                         $foundNonCookies++;
226:                         continue 2;
227:                     }
228:                 }
229:             }
230: 
231:             // If cookies have not yet been retrieved, or this value was not found in the pieces array, treat it as a
232:             // cookie. IF non-cookies have been parsed, then this isn't a cookie, it's cookie data. Cookies then data.
233:             $data[$foundNonCookies ? 'data' : 'cookies'][$key] = $value;
234:         }
235: 
236:         // Calculate the expires date
237:         if (!$data['expires'] && $data['max_age']) {
238:             $data['expires'] = time() + (int) $data['max_age'];
239:         }
240: 
241:         return $data;
242:     }
243: }
244: 
Ratchet API documentation generated by ApiGen 2.8.0