Skip to content

Commit 2e7543e

Browse files
authored
NTO-707 replace (un)serialize() in sfRoute caching (master) (#14)
* imported changes from #11 * imported more changes from #11 * bumped version * added support for classes which extend from `sfRoute`
1 parent 60d0904 commit 2e7543e

File tree

6 files changed

+96
-18
lines changed

6 files changed

+96
-18
lines changed

lib/autoload/sfCoreAutoload.class.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*/
1010

1111
// The current symfony version.
12-
define('SYMFONY_VERSION', '1.6.1.1');
12+
define('SYMFONY_VERSION', '1.6.1.2-dev');
1313

1414
/**
1515
* sfCoreAutoload class.

lib/config/sfRoutingConfigHandler.class.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,14 @@ public function execute($configFiles)
3838
$routes = $route instanceof sfRouteCollection ? $route : [$name => $route];
3939
foreach (sfPatternRouting::flattenRoutes($routes) as $name => $route) {
4040
$route->setDefaultOptions($options);
41-
$data[] = sprintf('$this->routes[\'%s\'] = %s;', $name, var_export(serialize($route), true));
41+
$data[] = sprintf('$this->routes[\'%s\'] = %s;', $name, var_export(json_encode($route), true));
4242
}
4343
}
4444

4545
return sprintf(
4646
"<?php\n".
47-
"// auto-generated by sfRoutingConfigHandler\n".
48-
"// date: %s\n%s\n",
47+
"// auto-generated by sfRoutingConfigHandler\n".
48+
"// date: %s\n%s\n",
4949
date('Y/m/d H:i:s'),
5050
implode("\n", $data)
5151
);

lib/routing/sfPatternRouting.class.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,14 @@ public function getRoute($name)
146146
$route = $this->routes[$name];
147147

148148
if (is_string($route)) {
149-
$this->routes[$name] = $route = unserialize($route);
150-
$route->setDefaultParameters($this->defaultParameters);
149+
$decoded = json_decode($route, true);
150+
$route = is_array($decoded) ? sfRoute::jsonUnserialize($decoded) : unserialize($route);
151+
152+
if (is_object($route) && method_exists($route, 'setDefaultParameters')) {
153+
$route->setDefaultParameters($this->defaultParameters);
154+
}
155+
156+
$this->routes[$name] = $route;
151157
}
152158

153159
return $route;

lib/routing/sfRoute.class.php

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
*
1414
* @author Fabien Potencier <[email protected]>
1515
*/
16-
class sfRoute implements Serializable
16+
class sfRoute implements Serializable, JsonSerializable
1717
{
1818
protected $isBound = false;
1919
protected $context;
@@ -446,6 +446,41 @@ public function unserialize($serialized)
446446
$this->__unserialize($array);
447447
}
448448

449+
public function jsonSerialize(): array
450+
{
451+
return [
452+
'class' => get_class($this),
453+
'tokens' => $this->tokens,
454+
'defaultOptions' => $this->defaultOptions,
455+
'options' => $this->options,
456+
'pattern' => $this->pattern,
457+
'staticPrefix' => $this->staticPrefix,
458+
'regex' => $this->regex,
459+
'variables' => $this->variables,
460+
'defaults' => $this->defaults,
461+
'requirements' => $this->requirements,
462+
'suffix' => $this->suffix,
463+
'customToken' => $this->customToken,
464+
];
465+
}
466+
467+
public static function jsonUnserialize(array $raw): self
468+
{
469+
$class = $raw['class'] ?? 'sfRoute';
470+
$rebuilt = new $class(
471+
$raw['pattern'],
472+
$raw['defaults'],
473+
$raw['requirements'],
474+
$raw['options']
475+
);
476+
477+
$rebuilt->compile();
478+
479+
$rebuilt->setDefaultOptions($raw['defaultOptions']);
480+
481+
return $rebuilt;
482+
}
483+
449484
/**
450485
* Generates a URL for the given parameters by using the route tokens.
451486
*

lib/storage/sfCacheSessionStorage.class.php

Lines changed: 48 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -132,16 +132,21 @@ public function initialize($options = [])
132132
if (null === $raw) {
133133
$this->data = [];
134134
} else {
135-
$data = @unserialize($raw);
136-
137-
// We test 'b:0' special case, because such a string would result
138-
// in $data being === false, while raw is serialized
139-
// see http://stackoverflow.com/questions/1369936/check-to-see-if-a-string-is-serialized
140-
if ('b:0;' === $raw || false !== $data) {
141-
$this->data = $data;
135+
$data = json_decode($raw, true);
136+
if (is_array($data)) {
137+
$this->data = $this->upgradeNestedRouteObjects($data);
142138
} else {
143-
// Probably an old cached value (BC)
144-
$this->data = $raw;
139+
$data = @unserialize($raw);
140+
141+
// We test 'b:0' special case, because such a string would result
142+
// in $data being === false, while raw is serialized
143+
// see http://stackoverflow.com/questions/1369936/check-to-see-if-a-string-is-serialized
144+
if ('b:0;' === $raw || false !== $data) {
145+
$this->data = $data;
146+
} else {
147+
// Probably an old cached value (BC)
148+
$this->data = $raw;
149+
}
145150
}
146151
}
147152

@@ -155,6 +160,38 @@ public function initialize($options = [])
155160
return true;
156161
}
157162

163+
/**
164+
* Recursive method to search through a json_decode()'d cache payload for
165+
* any values which _would have been_ sfRoute objects before serialisation.
166+
* If any are found, then also rebuilds the sfRoute object from the cached
167+
* values and injects it back into the array.
168+
*
169+
* @param array $raw A dictionary of key => value pairs
170+
*/
171+
protected function upgradeNestedRouteObjects(array $raw): array
172+
{
173+
foreach ($raw as $key => $value) {
174+
if (is_array($value)) {
175+
if (
176+
'route' == $key
177+
&& isset(
178+
$value['pattern'],
179+
$value['defaults'],
180+
$value['requirements'],
181+
$value['options']
182+
)
183+
) {
184+
$raw[$key] = sfRoute::jsonUnserialize($value);
185+
continue;
186+
}
187+
188+
$raw[$key] = $this->upgradeNestedRouteObjects($value);
189+
}
190+
}
191+
192+
return $raw;
193+
}
194+
158195
/**
159196
* Write data to this storage.
160197
*
@@ -235,7 +272,7 @@ public function regenerate($destroy = false)
235272
$this->id = md5(mt_rand(0, 999999).$_SERVER['REMOTE_ADDR'].$ua.$this->options['session_cookie_secret']);
236273

237274
// save data to cache
238-
$this->cache->set($this->id, serialize($this->data));
275+
$this->cache->set($this->id, json_encode($this->data));
239276

240277
// update session id in signed cookie
241278
$this->response->setCookie(
@@ -274,7 +311,7 @@ public function shutdown()
274311
{
275312
// only update cache if session has changed
276313
if (true === $this->dataChanged) {
277-
$this->cache->set($this->id, serialize($this->data));
314+
$this->cache->set($this->id, json_encode($this->data));
278315
if (sfConfig::get('sf_logging_enabled')) {
279316
$this->dispatcher->notify(new sfEvent($this, 'application.log', ['Storing session to cache']));
280317
}

lib/util/sfBrowserBase.class.php

100755100644
File mode changed.

0 commit comments

Comments
 (0)