Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 85d4068

Browse filesBrowse files
committed
merged branch drak/sessionhandler (PR #3493)
Commits ------- eb9bf05 [HttpFoundation] Remove hard coded assumptions and replace with API calls. 9a5fc65 [HttpFoundation] Add more tests. 68074a2 Changelog and upgrading changes. 7f33b33 Refactor SessionStorage to NativeSessionStorage. b12ece0 [HttpFoundation][FrameworkBundle] Separate out mock session storage and stop polluting global namespace. d687801 [HttpKernel] Mock must invoke constructor. 7b36d0c [DoctrineBridge][HttpFoundation] Refactored tests. 39526df [HttpFoundation] Refactor away options property. 21221f7 [FrameworkBundle] Make use of session API. cb873b2 [HttpFoundation] Add tests and some CS/docblocks. a6a9280 [DoctrineBridge] Refactor session storage to handler. a1c678e [FrameworkBundle] Add session.handler service and handler_id configuration property. 1308312 [HttpFoundation] Add and relocate tests. 88b1170 [HttpFoundation] Refactor tests. 2257a3d [HttpFoundation] Move session handler classes. 0a064d8 [HttpFoundation] Refactor session handlers. 2326707 [HttpFoundation] Split session handler callbacks to separate object. bb30a44 [HttpFoundation] Prepare to split out session handler callback from session storage. Discussion ---------- [2.1] Support PHP 5.4 \SessionHandler Bug fix: no Feature addition: yes Backwards compatibility break: no Symfony2 tests pass: yes Fixes the following tickets: - Todo: - This patch allows us to add services, like an encryption layer into any session handler without having to alter or inherit any code across any session handler, internal or custom. The `\SessionHandler` class exposes internal PHP's native internal session save handlers like files, memcache, and sqlite by wrapping the internal callbacks through the class giving user-space the chance to intercept, override and filter them by inheriting from `\SessionHandler`. I've written a pretty nice use-case at http://docs.php.net/sessionhandler which really shows the power of it. I never considered how to make proper use of the `\SessionHandler` in Symfony2 until I wrote the code example you see in that documentation and also because of the `AbstractSessionStorage` base class got in the way. It's really trivial to enable support for this in Symfony2 but requires to separate out the actual handlers because inheritance is not suitable. Obviously, the feature will only work with internal PHP-extension provided handlers under PHP 5.4 and will already work in PHP 5.3 with any custom handler (since they all implement `\SessionHandlerInterface`). Symfony2 will also be the first framework to support these amazing features :-D The necessary changes are really small but beautiful: The basic idea is this: https://github.com/drak/symfony/commit/1d55d1ff148125762641a337acde7163d7936e90 removed inheritance and separates out the actual session handler callbacks - the part PHP processes internally. This is supported by an internal proxy mechanism: https://github.com/drak/symfony/commit/10a36c901e9ee77255954539b2dc3e8920189002 In terms of BC, not much changes net from 2.0: - We can restore the deprecated service ID: `session.storage.native` - We add a new service ID `session.handler` (and configuration alias `handler_id`) for the actual session handlers. This defaults to the renamed `session.handler.native_file` session handler (same behaviour just new name and as it's a default there is no BC break). --------------------------------------------------------------------------- by fabpot at 2012-03-03T12:15:10Z Looks good to me. Can you update the CHANGELOG and UPGRADE file accordingly and start to update the documentation at symfony/symfony-docs? Thanks for your work, the session handling in Symfony2 is starting to become amazing! --------------------------------------------------------------------------- by drak at 2012-03-04T11:09:31Z @fabpot I will start working on documentation this week and get the CHANGELOG/UPGRADING committed shortly. I'll ping when done. --------------------------------------------------------------------------- by drak at 2012-03-14T16:48:37Z @fabpot - This PR is ready now.
2 parents 26441af + eb9bf05 commit 85d4068
Copy full SHA for 85d4068

File tree

Expand file treeCollapse file tree

61 files changed

+1405
-576
lines changed
Filter options

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Dismiss banner
Expand file treeCollapse file tree

61 files changed

+1405
-576
lines changed

‎CHANGELOG-2.1.md

Copy file name to clipboardExpand all lines: CHANGELOG-2.1.md
+52-31Lines changed: 52 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,10 @@ To get the diff between two versions, go to https://github.com/symfony/symfony/c
2727
### DoctrineBundle
2828

2929
* This bundle has been moved to the Doctrine organization
30-
* added optional `group_by` property to `EntityType` that supports either a `PropertyPath` or a `\Closure` that is evaluated on the entity choices
31-
* The `em` option for the `UniqueEntity` constraint is now optional (and should probably not be used anymore).
30+
* added optional `group_by` property to `EntityType` that supports either a
31+
`PropertyPath` or a `\Closure` that is evaluated on the entity choices
32+
* The `em` option for the `UniqueEntity` constraint is now optional (and should
33+
probably not be used anymore).
3234

3335
### FrameworkBundle
3436

@@ -39,13 +41,17 @@ To get the diff between two versions, go to https://github.com/symfony/symfony/c
3941
* added Controller::getUser()
4042
* [BC BREAK] assets_base_urls and base_urls merging strategy has changed
4143
* changed the default profiler storage to use the filesystem instead of SQLite
42-
* added support for placeholders in route defaults and requirements (replaced by the value set in the service container)
44+
* added support for placeholders in route defaults and requirements (replaced
45+
by the value set in the service container)
4346
* added Filesystem component as a dependency
4447
* added support for hinclude (use ``standalone: 'js'`` in render tag)
4548
* session options: lifetime, path, domain, secure, httponly were deprecated.
46-
Prefixed versions should now be used instead: cookie_lifetime, cookie_path, cookie_domain, cookie_secure, cookie_httponly
47-
* [BC BREAK] following session options: 'lifetime', 'path', 'domain', 'secure', 'httponly'
48-
are now prefixed with cookie_ when dumped to the container
49+
Prefixed versions should now be used instead: cookie_lifetime, cookie_path,
50+
cookie_domain, cookie_secure, cookie_httponly
51+
* [BC BREAK] following session options: 'lifetime', 'path', 'domain', 'secure',
52+
'httponly' are now prefixed with cookie_ when dumped to the container
53+
* Added `handler_id` configuration under `session` key to represent `session.handler`
54+
service, defaults to `session.handler.native_file`.
4955

5056
### MonologBundle
5157

@@ -257,32 +263,47 @@ To get the diff between two versions, go to https://github.com/symfony/symfony/c
257263
* made mimetype to extension conversion configurable
258264
* [BC BREAK] Moved all session related classes and interfaces into own namespace, as
259265
`Symfony\Component\HttpFoudation\Session` and renamed classes accordingly.
260-
* Added `FlashBag`. Flashes expire when retrieved by `get()` or `all()`.
261-
This makes the implementation ESI compatible.
262-
* Added `AutoExpireFlashBag` (default) to replicate Symfony 2.0.x auto expire behaviour of messages auto expiring
263-
after one page page load. Messages must be retrived by `get()` or `all()`.
264-
* [BC BREAK] Removed the `close()` method from the Session class
266+
Session handlers are located in the subnamespace `Symfony\Component\HttpFoudation\Session\Handler`.
267+
* SessionHandlers must implement `\SessionHandlerInterface` or extend from the
268+
`Symfony\Component\HttpFoundation\Storage\Handler\NativeSessionHandler` base class.
269+
* Added internal storage driver proxy mechanism for forward compatibility with
270+
PHP 5.4 `\SessionHandler` class.
271+
* Added session handlers for PHP native Memcache, Memcached and SQLite session
272+
save handlers.
273+
* Added session handlers for custom Memcache, Memcached and Null session save handlers.
274+
* [BC BREAK] Removed `NativeSessionStorage` and replaced with `NativeFileSessionHandler`.
275+
* [BC BREAK] `SessionStorageInterface` methods removed: `write()`, `read()` and
276+
`remove()`. Added `getBag()`, `registerBag()`. The `NativeSessionStorage` class
277+
is a mediator for the session storage internals including the session handlers
278+
which do the real work of participating in the internal PHP session workflow.
279+
* [BC BREAK] Introduced mock implementations of `SessionStorage` to enable unit
280+
and functional testing without starting real PHP sessions. Removed
281+
`ArraySessionStorage`, and replaced with `MockArraySessionStorage` for unit
282+
tests; removed `FilesystemSessionStorage`, and replaced with`MockFileSessionStorage`
283+
for functional tests. These do not interact with global session ini
284+
configuration values, session functions or `$_SESSION` supreglobal. This means
285+
they can be configured directly allowing multiple instances to work without
286+
conflicting in the same PHP process.
287+
* [BC BREAK] Removed the `close()` method from the `Session` class, as this is
288+
now redundant.
265289
* Deprecated the following methods from the Session class: `setFlash()`, `setFlashes()`
266-
`getFlash()`, `hasFlash()`, and `removeFlash()`. Use `getFlashBag()` instead which returns a `FlashBagInterface`.
267-
* `Session->clear()` now only clears session attributes as before it cleared flash messages and
268-
attributes. `Session->getFlashBag()->all()` clears flashes now.
269-
* Added `Symfony\Component\HttpFoundation\Session\Storage\AbstractSessionStorage` base class for
270-
session storage drivers.
271-
* Added `SessionHandlerInterface` interface which storage drivers should implement after inheriting from
272-
`Symfony\Component\HttpFoundation\Session\Storage\AbstractSessionStorage` when writing custom
273-
session save handlers using PHP 5.3. This interface is a stub for the PHP 5.4 interface.
274-
* [BC BREAK] `SessionStorageInterface` methods removed: `write()`, `read()` and `remove()`. Added
275-
`getBag()`, `registerBag()`.
276-
* Moved attribute storage to `Symfony\Component\HttpFoundation\Attribute\AttributeBagInterface`.
277-
* Added `Symfony\Component\HttpFoundation\Attribute\AttributeBag` to replicate attributes storage
278-
behaviour from 2.0.x (default).
279-
* Added `Symfony\Component\HttpFoundation\Attribute\NamespacedAttributeBag` for namespace session attributes.
280-
* Session now implements `Symfony\Component\HttpFoundation\Session\SessionInterface` making
281-
implementation customizable and portable.
282-
* [BC BREAK] Removed `NativeSessionStorage` and replaced with `NativeFileSessionStorage`.
283-
* Added session storage drivers for PHP native Memcache, Memcached and SQLite session save handlers.
284-
* Added session storage drivers for custom Memcache, Memcached and Null session save handlers.
285-
* Removed `FilesystemSessionStorage`, use `MockFileSessionStorage` for functional testing instead.
290+
`getFlash()`, `hasFlash()`, and `removeFlash()`. Use `getFlashBag()` instead
291+
which returns a `FlashBagInterface`.
292+
* `Session->clear()` now only clears session attributes as before it cleared
293+
flash messages and attributes. `Session->getFlashBag()->all()` clears flashes now.
294+
* Session data is now managed by `SessionBagInterface` which to better encapsulate
295+
session data.
296+
* Refactored session attribute and flash messages system to their own
297+
`SessionBagInterface` implementations.
298+
* Added `FlashBag`. Flashes expire when retrieved by `get()` or `all()`. This
299+
implementation is ESI compatible.
300+
* Added `AutoExpireFlashBag` (default) to replicate Symfony 2.0.x auto expire
301+
behaviour of messages auto expiring.
302+
after one page page load. Messages must be retrieved by `get()` or `all()`.
303+
* Added `Symfony\Component\HttpFoundation\Attribute\AttributeBag` to replicate
304+
attributes storage behaviour from 2.0.x (default).
305+
* Added `Symfony\Component\HttpFoundation\Attribute\NamespacedAttributeBag` for
306+
namespace session attributes.
286307

287308
### HttpKernel
288309

‎UPGRADE-2.1.md

Copy file name to clipboardExpand all lines: UPGRADE-2.1.md
+21-6Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -334,13 +334,11 @@ UPGRADE FROM 2.0 to 2.1
334334
{% endfor %}
335335
```
336336
337-
* Session storage drivers should inherit from
338-
`Symfony\Component\HttpFoundation\Session\Storage\AbstractSessionStorage`
339-
and should no longer implement `read()`, `write()`, and `remove()`, which
340-
were removed from `SessionStorageInterface`.
337+
* Session handler drivers should implement `\SessionHandlerInterface` or extend from
338+
`Symfony\Component\HttpFoudation\Session\Storage\Handler\NativeHandlerInterface` base class and renamed
339+
to `Handler\FooSessionHandler`. E.g. `PdoSessionStorage` becomes `Handler\PdoSessionHandler`.
341340
342-
Any session storage driver that wants to use custom save handlers should
343-
implement `SessionHandlerInterface`.
341+
* Refactor code using `$session->*flash*()` methods to use `$session->getFlashBag()->*()`.
344342
345343
### FrameworkBundle
346344
@@ -371,3 +369,20 @@ UPGRADE FROM 2.0 to 2.1
371369
cookie_httponly: true
372370
```
373371
372+
Added `handler_id`, defaults to `session.handler.native_file`.
373+
374+
```
375+
framework:
376+
session:
377+
storage_id: session.storage.native
378+
handler_id: session.handler.native_file
379+
```
380+
381+
To use mock session storage use the following. `handler_id` is irrelevant in this context.
382+
383+
```
384+
framework:
385+
session:
386+
storage_id: session.storage.mock_file
387+
```
388+

‎src/Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionStorage.php renamed to ‎src/Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandler.php

Copy file name to clipboardExpand all lines: src/Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandler.php
+20-46Lines changed: 20 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
11
<?php
22

3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
312
namespace Symfony\Bridge\Doctrine\HttpFoundation;
413

514
use Doctrine\DBAL\Platforms\MySqlPlatform;
6-
use Symfony\Component\HttpFoundation\Session\Storage\AbstractSessionStorage;
715
use Doctrine\DBAL\Driver\Connection;
816

917
/**
@@ -12,7 +20,7 @@
1220
* @author Fabien Potencier <fabien@symfony.com>
1321
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
1422
*/
15-
class DbalSessionStorage extends AbstractSessionStorage implements \SessionHandlerInterface
23+
class DbalSessionHandler implements \SessionHandlerInterface
1624
{
1725
/**
1826
* @var Connection
@@ -25,36 +33,27 @@ class DbalSessionStorage extends AbstractSessionStorage implements \SessionHandl
2533
private $tableName;
2634

2735
/**
36+
* Constructor.
2837
*
29-
* @param Connection $con An instance of Connection.
30-
* @param string $tableName Table name.
31-
* @param array $options Session configuration options
38+
* @param Connection $con An instance of Connection.
39+
* @param string $tableName Table name.
3240
*/
33-
public function __construct(Connection $con, $tableName = 'sessions', array $options = array())
41+
public function __construct(Connection $con, $tableName = 'sessions')
3442
{
3543
$this->con = $con;
3644
$this->tableName = $tableName;
37-
38-
parent::__construct($options);
3945
}
4046

4147
/**
42-
* Opens a session.
43-
*
44-
* @param string $path (ignored)
45-
* @param string $name (ignored)
46-
*
47-
* @return Boolean true, if the session was opened, otherwise an exception is thrown
48+
* {@inheritdoc}
4849
*/
4950
public function open($path = null, $name = null)
5051
{
5152
return true;
5253
}
5354

5455
/**
55-
* Closes a session.
56-
*
57-
* @return Boolean true, if the session was closed, otherwise false
56+
* {@inheritdoc}
5857
*/
5958
public function close()
6059
{
@@ -63,13 +62,7 @@ public function close()
6362
}
6463

6564
/**
66-
* Destroys a session.
67-
*
68-
* @param string $id A session ID
69-
*
70-
* @return Boolean true, if the session was destroyed, otherwise an exception is thrown
71-
*
72-
* @throws \RuntimeException If the session cannot be destroyed
65+
* {@inheritdoc}
7366
*/
7467
public function destroy($id)
7568
{
@@ -85,13 +78,7 @@ public function destroy($id)
8578
}
8679

8780
/**
88-
* Cleans up old sessions.
89-
*
90-
* @param int $lifetime The lifetime of a session
91-
*
92-
* @return Boolean true, if old sessions have been cleaned, otherwise an exception is thrown
93-
*
94-
* @throws \RuntimeException If any old sessions cannot be cleaned
81+
* {@inheritdoc}
9582
*/
9683
public function gc($lifetime)
9784
{
@@ -107,13 +94,7 @@ public function gc($lifetime)
10794
}
10895

10996
/**
110-
* Reads a session.
111-
*
112-
* @param string $id A session ID
113-
*
114-
* @return string The session data if the session was read or created, otherwise an exception is thrown
115-
*
116-
* @throws \RuntimeException If the session cannot be read
97+
* {@inheritdoc}
11798
*/
11899
public function read($id)
119100
{
@@ -136,14 +117,7 @@ public function read($id)
136117
}
137118

138119
/**
139-
* Writes session data.
140-
*
141-
* @param string $id A session ID
142-
* @param string $data A serialized chunk of session data
143-
*
144-
* @return Boolean true, if the session was written, otherwise an exception is thrown
145-
*
146-
* @throws \RuntimeException If the session data cannot be written
120+
* {@inheritdoc}
147121
*/
148122
public function write($id, $data)
149123
{

‎src/Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionStorageSchema.php renamed to ‎src/Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandlerSchema.php

Copy file name to clipboardExpand all lines: src/Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandlerSchema.php
+10-1Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
<?php
22

3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
312
namespace Symfony\Bridge\Doctrine\HttpFoundation;
413

514
use Doctrine\DBAL\Schema\Schema;
@@ -9,7 +18,7 @@
918
*
1019
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
1120
*/
12-
final class DbalSessionStorageSchema extends Schema
21+
final class DbalSessionHandlerSchema extends Schema
1322
{
1423
private $tableName;
1524

‎src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php
+2-1Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,8 @@ private function addSessionSection(ArrayNodeDefinition $rootNode)
167167
->canBeUnset()
168168
->children()
169169
->booleanNode('auto_start')->defaultFalse()->end()
170-
->scalarNode('storage_id')->defaultValue('session.storage.native_file')->end()
170+
->scalarNode('storage_id')->defaultValue('session.storage.native')->end()
171+
->scalarNode('handler_id')->defaultValue('session.handler.native_file')->end()
171172
->scalarNode('name')->end()
172173
->scalarNode('cookie_lifetime')->end()
173174
->scalarNode('cookie_path')->end()

‎src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
+7-1Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,10 +310,16 @@ private function registerSessionConfiguration(array $config, ContainerBuilder $c
310310
}
311311
$container->setParameter('session.storage.options', $options);
312312

313+
// session handler (the internal callback registered with PHP session management)
314+
$container->setAlias('session.handler', $config['handler_id']);
315+
313316
$this->addClassesToCompile(array(
314317
'Symfony\\Bundle\\FrameworkBundle\\EventListener\\SessionListener',
315318
'Symfony\\Component\\HttpFoundation\\Session\\Storage\\SessionStorageInterface',
316-
'Symfony\\Component\\HttpFoundation\\Session\\Storage\\AbstractSessionStorage',
319+
'Symfony\\Component\\HttpFoundation\\Session\\Storage\\NativeSessionStorage',
320+
'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\NativeSessionHandler',
321+
'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Proxy\AbstractProxy',
322+
'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Proxy\SessionHandlerProxy',
317323
$container->getDefinition('session')->getClass(),
318324
));
319325

‎src/Symfony/Bundle/FrameworkBundle/EventListener/SessionListener.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/EventListener/SessionListener.php
+7Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,14 @@
2828
*/
2929
class SessionListener implements EventSubscriberInterface
3030
{
31+
/**
32+
* @var ContainerInterface
33+
*/
3134
private $container;
35+
36+
/**
37+
* @var boolean
38+
*/
3239
private $autoStart;
3340

3441
public function __construct(ContainerInterface $container, $autoStart = false)

‎src/Symfony/Bundle/FrameworkBundle/EventListener/TestSessionListener.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/EventListener/TestSessionListener.php
+7-6Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,16 @@ public function onKernelRequest(GetResponseEvent $event)
4343
}
4444

4545
// bootstrap the session
46-
if ($this->container->has('session')) {
47-
$this->container->get('session');
46+
if (!$this->container->has('session')) {
47+
return;
4848
}
4949

50+
$session = $this->container->get('session');
5051
$cookies = $event->getRequest()->cookies;
51-
if ($cookies->has(session_name())) {
52-
session_id($cookies->get(session_name()));
52+
if ($cookies->has($session->getName())) {
53+
$session->setId($cookies->get($session->getName()));
5354
} else {
54-
session_id('');
55+
$session->setId('');
5556
}
5657
}
5758

@@ -72,7 +73,7 @@ public function onKernelResponse(FilterResponseEvent $event)
7273

7374
$params = session_get_cookie_params();
7475

75-
$event->getResponse()->headers->setCookie(new Cookie(session_name(), session_id(), 0 === $params['lifetime'] ? 0 : time() + $params['lifetime'], $params['path'], $params['domain'], $params['secure'], $params['httponly']));
76+
$event->getResponse()->headers->setCookie(new Cookie($session->getName(), $session->getId(), 0 === $params['lifetime'] ? 0 : time() + $params['lifetime'], $params['path'], $params['domain'], $params['secure'], $params['httponly']));
7677
}
7778
}
7879

‎src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474

7575
<xsd:complexType name="session">
7676
<xsd:attribute name="storage-id" type="xsd:string" />
77+
<xsd:attribute name="handler-id" type="xsd:string" />
7778
<xsd:attribute name="name" type="xsd:string" />
7879
<xsd:attribute name="cookie-lifetime" type="xsd:integer" />
7980
<xsd:attribute name="cookie-path" type="xsd:string" />

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.