Merge branch '2.3' into 2.6

* 2.3:
  bumped Symfony version to 2.3.28
  updated VERSION for 2.3.27
  update CONTRIBUTORS for 2.3.27
  updated CHANGELOG for 2.3.27
  isFromTrustedProxy to confirm request came from a trusted proxy.
  Safe escaping of fragments for eval()

Conflicts:
	src/Symfony/Component/HttpFoundation/Request.php
	src/Symfony/Component/HttpKernel/HttpCache/Esi.php
	src/Symfony/Component/HttpKernel/Kernel.php
This commit is contained in:
Fabien Potencier 2015-04-01 18:50:12 +02:00
commit ec2cb961cc
6 changed files with 112 additions and 72 deletions

View File

@ -7,6 +7,16 @@ in 2.3 minor versions.
To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash
To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v2.3.0...v2.3.1
* 2.3.27 (2015-04-01)
* security #14167 CVE-2015-2308 (nicolas-grekas)
* security #14166 CVE-2015-2309 (neclimdul)
* bug #14010 Replace GET parameters when changed in form (WouterJ)
* bug #13991 [Dependency Injection] Improve PhpDumper Performance for huge Containers (BattleRattle)
* bug #13997 [2.3+][Form][DoctrineBridge] Improved loading of entities and documents (guilhermeblanco)
* bug #13953 [Translation][MoFileLoader] fixed load empty translation. (aitboudad)
* bug #13912 [DependencyInjection] Highest precedence for user parameters (lyrixx)
* 2.3.26 (2015-03-17)
* bug #13927 Fixing wrong variable name from #13519 (weaverryan)

View File

@ -11,8 +11,8 @@ Symfony is the result of the work of many people who made the code better
- Jordi Boggiano (seldaek)
- Johannes S (johannes)
- Kris Wallsmith (kriswallsmith)
- Christophe Coevoet (stof)
- Nicolas Grekas (nicolas-grekas)
- Christophe Coevoet (stof)
- Jakub Zalas (jakubzalas)
- Pascal Borreli (pborreli)
- Hugo Hamon (hhamon)
@ -21,9 +21,9 @@ Symfony is the result of the work of many people who made the code better
- Ryan Weaver (weaverryan)
- Lukas Kahwe Smith (lsmith)
- Romain Neutron (romain)
- Christian Flothmann (xabbuh)
- Jeremy Mikola (jmikola)
- Jean-François Simon (jfsimon)
- Christian Flothmann (xabbuh)
- Benjamin Eberlei (beberlei)
- Igor Wiedler (igorw)
- Martin Hasoň (hason)
@ -37,16 +37,16 @@ Symfony is the result of the work of many people who made the code better
- stealth35 (stealth35)
- Alexander Mols (asm89)
- Bulat Shakirzyanov (avalanche123)
- Abdellatif Ait boudad (aitboudad)
- Francis Besset (francisbesset)
- Saša Stamenković (umpirsky)
- Henrik Bjørnskov (henrikbjorn)
- Miha Vrhovnik
- Kévin Dunglas (dunglas)
- Sarah Khalil (saro0h)
- Konstantin Kudryashov (everzet)
- Bilal Amarni (bamarni)
- Kévin Dunglas (dunglas)
- Florin Patan (florinpatan)
- Abdellatif Ait Boudad (aitboudad)
- Sarah Khalil (saro0h)
- Eric Clemmons (ericclemmons)
- Andrej Hudec (pulzarraider)
- Deni
@ -61,13 +61,14 @@ Symfony is the result of the work of many people who made the code better
- Daniel Holmes (dholmes)
- Bart van den Burg (burgov)
- Jordan Alliot (jalliot)
- Kevin Bond (kbond)
- John Wards (johnwards)
- Fran Moreno (franmomu)
- Antoine Hérault (herzult)
- Kevin Bond (kbond)
- Toni Uebernickel (havvg)
- Luis Cordova (cordoval)
- Antoine Hérault (herzult)
- Toni Uebernickel (havvg)
- Arnaud Le Blanc (arnaud-lb)
- Gábor Egyed (1ed)
- Tim Nagel (merk)
- Brice BERNARD (brikou)
- marc.weistroff
@ -78,7 +79,6 @@ Symfony is the result of the work of many people who made the code better
- Colin Frei
- Jérôme Tamarelle (gromnan)
- Adrien Brault (adrienbrault)
- Gábor Egyed (1ed)
- excelwebzone
- Jacob Dreesen (jdreesen)
- Fabien Pennequin (fabienpennequin)
@ -93,26 +93,29 @@ Symfony is the result of the work of many people who made the code better
- Daniel Gomes (danielcsgomes)
- Hidenori Goto (hidenorigoto)
- David Buchmann (dbu)
- Guilherme Blanco (guilhermeblanco)
- Jérémy DERUSSÉ (jderusse)
- Pablo Godel (pgodel)
- Eric GELOEN (gelo)
- Jérémie Augustin (jaugustin)
- Rafael Dohms (rdohms)
- Guilherme Blanco (guilhermeblanco)
- Tigran Azatyan (tigranazatyan)
- Javier Eguiluz (javier.eguiluz)
- Arnaud Kleinpeter (nanocom)
- Richard Shank (iampersistent)
- Dariusz Ruminski
- Clemens Tolboom
- Helmer Aaviksoo
- Sebastiaan Stok (sstok)
- Hiromi Hishida (77web)
- Matthieu Ouellette-Vachon (maoueh)
- Michał Pipa (michal.pipa)
- Issei Murasawa (issei_m)
- Amal Raghav (kertz)
- Jonathan Ingram (jonathaningram)
- Artur Kotyrba
- Rouven Weßling (realityking)
- Andréia Bohner (andreia)
- Dmitrii Chekaliuk (lazyhammer)
- Clément JOBEILI (dator)
- Dorian Villet (gnutix)
@ -123,14 +126,12 @@ Symfony is the result of the work of many people who made the code better
- Benjamin Dulau (dbenjamin)
- Matthias Pigulla (mpdude)
- Andreas Hucks (meandmymonkey)
- Andréia Bohner (andreia)
- Noel Guilbert (noel)
- Joel Wurtz (brouznouf)
- Charles Sarrazin (csarrazi)
- bronze1man
- sun (sun)
- Larry Garfield (crell)
- Issei Murasawa (issei_m)
- Martin Schuhfuß (usefulthink)
- Thomas Rabaix (rande)
- Matthieu Bontemps (mbontemps)
@ -163,6 +164,7 @@ Symfony is the result of the work of many people who made the code better
- Xavier Montaña Carreras (xmontana)
- Michele Orselli (orso)
- Chris Wilkinson (thewilkybarkid)
- Joshua Thijssen
- Xavier Perez
- Arjen Brouwer (arjenjb)
- Katsuhiro OGAWA
@ -181,16 +183,18 @@ Symfony is the result of the work of many people who made the code better
- Jeremy Livingston (jeremylivingston)
- Nikita Konstantinov
- Wodor Wodorski
- Matthieu Auger (matthieuauger)
- julien pauli (jpauli)
- Beau Simensen (simensen)
- Robert Kiss (kepten)
- John Kary (johnkary)
- Ruben Gonzalez (rubenrua)
- Kim Hemsø Rasmussen (kimhemsoe)
- Florian Lonqueu-Brochard (florianlb)
- Tom Van Looy (tvlooy)
- Wouter Van Hecke
- Joshua Thijssen
- Peter Kruithof (pkruithof)
- Vladimir Reznichenko (kalessil)
- Michael Holm (hollo)
- Warnar Boekkooi (boekkooi)
- Marc Weistroff (futurecat)
@ -222,7 +226,6 @@ Symfony is the result of the work of many people who made the code better
- Marco Pivetta (ocramius)
- Ricard Clau (ricardclau)
- Erin Millard
- John Kary (johnkary)
- Matthew Lewinski (lewinski)
- alquerci
- Francesco Levorato
@ -232,7 +235,6 @@ Symfony is the result of the work of many people who made the code better
- Inal DJAFAR (inalgnu)
- Christian Gärtner (dagardner)
- Felix Labrecque
- Vladimir Reznichenko (kalessil)
- Yaroslav Kiliba
- Sébastien Lavoie (lavoiesl)
- Terje Bråten
@ -283,7 +285,6 @@ Symfony is the result of the work of many people who made the code better
- Brian King
- Michel Salib (michelsalib)
- geoffrey
- Matthieu Auger (matthieuauger)
- Lorenz Schori
- Jeanmonod David (jeanmonod)
- Jan Schumann
@ -309,7 +310,6 @@ Symfony is the result of the work of many people who made the code better
- Christian Schmidt
- Marcin Sikoń (marphi)
- franek (franek)
- Dariusz Ruminski
- Adam Harvey
- Diego Saint Esteben (dii3g0)
- Alex Bakhturin
@ -336,6 +336,7 @@ Symfony is the result of the work of many people who made the code better
- mmoreram
- Markus Lanthaler (lanthaler)
- Vicent Soria Durá (vicentgodella)
- Anthony Ferrara
- Ioan Negulescu
- Jakub Škvára (jskvara)
- Daniel Beyer
@ -343,9 +344,11 @@ Symfony is the result of the work of many people who made the code better
- alexpods
- Erik Trapman (eriktrapman)
- De Cock Xavier (xdecock)
- Scott Arciszewski
- Norbert Orzechowicz (norzechowicz)
- Tobias Nyholm (tobias)
- Matthijs van den Bos (matthijs)
- Loick Piera (pyrech)
- Lenard Palko
- Nils Adermann (naderman)
- Gábor Fási
@ -371,9 +374,11 @@ Symfony is the result of the work of many people who made the code better
- Zach Badgett (zachbadgett)
- Aurélien Fredouelle
- Pavel Campr (pcampr)
- Maxime Steinhausser (ogizanagi)
- Disquedur
- Geoffrey Tran (geoff)
- Jan Behrens
- Mantas Var (mvar)
- Sebastian Krebs
- Christopher Davis (chrisguitarguy)
- Thomas Lallement (raziel057)
@ -387,6 +392,7 @@ Symfony is the result of the work of many people who made the code better
- Max Rath (drak3)
- Stéphane Escandell (sescandell)
- Sinan Eldem
- Alexandre Dupuy (satchette)
- Nahuel Cuesta (ncuesta)
- Chris Boden (cboden)
- Asmir Mustafic (goetas)
@ -484,7 +490,6 @@ Symfony is the result of the work of many people who made the code better
- Xavier Lacot (xavier)
- Olivier Maisonneuve (olineuve)
- Francis Turmel (fturmel)
- Loick Piera (pyrech)
- cgonzalez
- Ben
- Jayson Xu (superjavason)
@ -506,6 +511,7 @@ Symfony is the result of the work of many people who made the code better
- Fabian Vogler (fabian)
- Korvin Szanto
- Maksim Kotlyar (makasim)
- Ivan Kurnosov
- Neil Ferreira
- Dmitry Parnas (parnas)
- DQNEO
@ -516,6 +522,7 @@ Symfony is the result of the work of many people who made the code better
- David Romaní
- Patrick Allaert
- Gustavo Falco (gfalco)
- Matt Robinson (inanimatt)
- Aleksey Podskrebyshev
- David Marín Carreño (davefx)
- Jörn Lang (j.lang)
@ -580,6 +587,7 @@ Symfony is the result of the work of many people who made the code better
- Michael Tibben
- Sander Marechal
- Radosław Benkel
- Marcos Sánchez
- ttomor
- Mei Gwilym (meigwilym)
- Michael H. Arieli (excelwebzone)
@ -622,6 +630,7 @@ Symfony is the result of the work of many people who made the code better
- nacho
- Piotr Antosik (antek88)
- Artem Lopata
- Samuel ROZE (sroze)
- Marcos Quesada (marcos_quesada)
- Matthew Vickery (mattvick)
- Dan Finnie
@ -675,6 +684,7 @@ Symfony is the result of the work of many people who made the code better
- Yannick
- Eduardo García Sanz (coma)
- Sebastian Grodzicki (sgrodzicki)
- Michael Lee (zerustech)
- Roy Van Ginneken
- David de Boer (ddeboer)
- Gilles Doge (gido)
@ -721,6 +731,7 @@ Symfony is the result of the work of many people who made the code better
- Malaney J. Hill
- Christian Flach (cmfcmf)
- Cédric Girard (enk_)
- Lars Ambrosius Wallenborn (larsborn)
- Oriol Mangas Abellan (oriolman)
- Sebastian Göttschkes (sgoettschkes)
- Tatsuya Tsuruoka
@ -847,6 +858,7 @@ Symfony is the result of the work of many people who made the code better
- Gunnar Lium (gunnarlium)
- Tiago Garcia (tiagojsag)
- Artiom
- Jakub Simon
- Bouke Haarsma
- Martin Eckhardt
- Denis Zunke
@ -876,7 +888,6 @@ Symfony is the result of the work of many people who made the code better
- Vasily Khayrulin (sirian)
- Stefan Koopmanschap (skoop)
- Stefan Hüsges (tronsha)
- Ivan Kurnosov
- stloyd
- Chris Tickner
- Andrew Coulton
@ -905,7 +916,6 @@ Symfony is the result of the work of many people who made the code better
- Julius Beckmann
- Romain Dorgueil
- Grayson Koonce (breerly)
- Matt Robinson (inanimatt)
- Karim Cassam Chenaï (ka)
- Nicolas Bastien (nicolas_bastien)
- Andy Stanberry
@ -992,6 +1002,7 @@ Symfony is the result of the work of many people who made the code better
- grifx
- Robert Campbell
- Matt Lehner
- Hidde Wieringa
- Hein Zaw Htet™
- Ruben Kruiswijk
- Michael J
@ -1048,9 +1059,7 @@ Symfony is the result of the work of many people who made the code better
- Muriel (metalmumu)
- Michaël Perrin (michael.perrin)
- Michael Pohlers (mick_the_big)
- Mantas Var (mvar)
- Cayetano Soriano Gallego (neoshadybeat)
- Maxime Steinhausser (ogizanagi)
- Pablo Monterde Perez (plebs)
- Jimmy Leger (redpanda)
- Cyrille Jouineau (tuxosaurus)
@ -1128,6 +1137,7 @@ Symfony is the result of the work of many people who made the code better
- Brian Freytag
- Skorney
- mieszko4
- Neophy7e
- Arrilot
- Markus Staab
- Pierre-Louis LAUNAY
@ -1140,6 +1150,8 @@ Symfony is the result of the work of many people who made the code better
- Sema
- Thorsten Hallwas
- Michael Squires
- Norman Soetbeer
- Benjamin Long
- Matt Janssen
- Peter Gribanov
- kwiateusz
@ -1235,6 +1247,7 @@ Symfony is the result of the work of many people who made the code better
- Vincent (vincent1870)
- Eugene Babushkin (warl)
- Xavier Amado (xamado)
- Jesper Søndergaard Pedersen (zerrvox)
- Florent Cailhol
- szymek
- craigmarvelley

View File

@ -825,7 +825,7 @@ class Request
{
$ip = $this->server->get('REMOTE_ADDR');
if (!self::$trustedProxies) {
if (!$this->isFromTrustedProxy()) {
return array($ip);
}
@ -991,7 +991,7 @@ class Request
*/
public function getPort()
{
if (self::$trustedProxies) {
if ($this->isFromTrustedProxy()) {
if (self::$trustedHeaders[self::HEADER_CLIENT_PORT] && $port = $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_PORT])) {
return $port;
}
@ -1172,7 +1172,7 @@ class Request
*/
public function isSecure()
{
if (self::$trustedProxies && self::$trustedHeaders[self::HEADER_CLIENT_PROTO] && $proto = $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_PROTO])) {
if ($this->isFromTrustedProxy() && self::$trustedHeaders[self::HEADER_CLIENT_PROTO] && $proto = $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_PROTO])) {
return in_array(strtolower(current(explode(',', $proto))), array('https', 'on', 'ssl', '1'));
}
@ -1200,7 +1200,7 @@ class Request
*/
public function getHost()
{
if (self::$trustedProxies && self::$trustedHeaders[self::HEADER_CLIENT_HOST] && $host = $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_HOST])) {
if ($this->isFromTrustedProxy() && self::$trustedHeaders[self::HEADER_CLIENT_HOST] && $host = $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_HOST])) {
$elements = explode(',', $host);
$host = $elements[count($elements) - 1];
@ -1917,4 +1917,9 @@ class Request
return new static($query, $request, $attributes, $cookies, $files, $server, $content);
}
private function isFromTrustedProxy()
{
return self::$trustedProxies && IpUtils::checkIp($this->server->get('REMOTE_ADDR'), self::$trustedProxies);
}
}

View File

@ -723,35 +723,37 @@ class RequestTest extends \PHPUnit_Framework_TestCase
'HTTP_X_FORWARDED_PROTO' => 'https',
'HTTP_X_FORWARDED_PORT' => '8443',
));
$port = $request->getPort();
$this->assertEquals(8443, $port, 'With PROTO and PORT set PORT takes precedence.');
$this->assertEquals(80, $request->getPort(), 'With PROTO and PORT on untrusted connection server value takes precedence.');
$request->server->set('REMOTE_ADDR', '1.1.1.1');
$this->assertEquals(8443, $request->getPort(), 'With PROTO and PORT set PORT takes precedence.');
$request = Request::create('http://example.com', 'GET', array(), array(), array(), array(
'HTTP_X_FORWARDED_PROTO' => 'https',
));
$port = $request->getPort();
$this->assertEquals(443, $port, 'With only PROTO set getPort() defaults to 443.');
$this->assertEquals(80, $request->getPort(), 'With only PROTO set getPort() ignores trusted headers on untrusted connection.');
$request->server->set('REMOTE_ADDR', '1.1.1.1');
$this->assertEquals(443, $request->getPort(), 'With only PROTO set getPort() defaults to 443.');
$request = Request::create('http://example.com', 'GET', array(), array(), array(), array(
'HTTP_X_FORWARDED_PROTO' => 'http',
));
$port = $request->getPort();
$this->assertEquals(80, $port, 'If X_FORWARDED_PROTO is set to HTTP return 80.');
$this->assertEquals(80, $request->getPort(), 'If X_FORWARDED_PROTO is set to HTTP getPort() ignores trusted headers on untrusted connection.');
$request->server->set('REMOTE_ADDR', '1.1.1.1');
$this->assertEquals(80, $request->getPort(), 'If X_FORWARDED_PROTO is set to HTTP getPort() returns port of the original request.');
$request = Request::create('http://example.com', 'GET', array(), array(), array(), array(
'HTTP_X_FORWARDED_PROTO' => 'On',
));
$port = $request->getPort();
$this->assertEquals(443, $port, 'With only PROTO set and value is On, getPort() defaults to 443.');
$this->assertEquals(80, $request->getPort(), 'With only PROTO set and value is On, getPort() ignores trusted headers on untrusted connection.');
$request->server->set('REMOTE_ADDR', '1.1.1.1');
$this->assertEquals(443, $request->getPort(), 'With only PROTO set and value is On, getPort() defaults to 443.');
$request = Request::create('http://example.com', 'GET', array(), array(), array(), array(
'HTTP_X_FORWARDED_PROTO' => '1',
));
$port = $request->getPort();
$this->assertEquals(443, $port, 'With only PROTO set and value is 1, getPort() defaults to 443.');
$this->assertEquals(80, $request->getPort(), 'With only PROTO set and value is 1, getPort() ignores trusted headers on untrusted connection.');
$request->server->set('REMOTE_ADDR', '1.1.1.1');
$this->assertEquals(443, $request->getPort(), 'With only PROTO set and value is 1, getPort() defaults to 443.');
$request = Request::create('http://example.com', 'GET', array(), array(), array(), array(
'HTTP_X_FORWARDED_PROTO' => 'something-else',
@ -1021,6 +1023,8 @@ class RequestTest extends \PHPUnit_Framework_TestCase
$request->headers->set('X_FORWARDED_PROTO', 'https');
Request::setTrustedProxies(array('1.1.1.1'));
$this->assertFalse($request->isSecure());
$request->server->set('REMOTE_ADDR', '1.1.1.1');
$this->assertTrue($request->isSecure());
Request::setTrustedProxies(array());
@ -1480,7 +1484,15 @@ class RequestTest extends \PHPUnit_Framework_TestCase
$this->assertEquals(443, $request->getPort());
$this->assertTrue($request->isSecure());
// trusted proxy via setTrustedProxies()
Request::setTrustedProxies(array('3.3.3.4', '2.2.2.2'));
$this->assertEquals('3.3.3.3', $request->getClientIp());
$this->assertEquals('example.com', $request->getHost());
$this->assertEquals(80, $request->getPort());
$this->assertFalse($request->isSecure());
// check various X_FORWARDED_PROTO header values
Request::setTrustedProxies(array('3.3.3.3', '2.2.2.2'));
$request->headers->set('X_FORWARDED_PROTO', 'ssl');
$this->assertTrue($request->isSecure());

View File

@ -29,6 +29,10 @@ use Symfony\Component\HttpKernel\HttpKernelInterface;
class Esi implements SurrogateInterface
{
private $contentTypes;
private $phpEscapeMap = array(
array('<?', '<%', '<s', '<S'),
array('<?php echo "<?"; ?>', '<?php echo "<%"; ?>', '<?php echo "<s"; ?>', '<?php echo "<S"; ?>'),
);
/**
* Constructor.
@ -203,10 +207,34 @@ class Esi implements SurrogateInterface
// we don't use a proper XML parser here as we can have ESI tags in a plain text response
$content = $response->getContent();
$content = str_replace(array('<?', '<%'), array('<?php echo "<?"; ?>', '<?php echo "<%"; ?>'), $content);
$content = preg_replace_callback('#<esi\:include\s+(.*?)\s*(?:/|</esi\:include)>#', array($this, 'handleEsiIncludeTag'), $content);
$content = preg_replace('#<esi\:comment[^>]*(?:/|</esi\:comment)>#', '', $content);
$content = preg_replace('#<esi\:remove>.*?</esi\:remove>#', '', $content);
$content = preg_replace('#<esi\:comment[^>]*(?:/|</esi\:comment)>#', '', $content);
$chunks = preg_split('#<esi\:include\s+(.*?)\s*(?:/|</esi\:include)>#', $content, -1, PREG_SPLIT_DELIM_CAPTURE);
$chunks[0] = str_replace($this->phpEscapeMap[0], $this->phpEscapeMap[1], $chunks[0]);
$i = 1;
while (isset($chunks[$i])) {
$options = array();
preg_match_all('/(src|onerror|alt)="([^"]*?)"/', $chunks[$i], $matches, PREG_SET_ORDER);
foreach ($matches as $set) {
$options[$set[1]] = $set[2];
}
if (!isset($options['src'])) {
throw new \RuntimeException('Unable to process an ESI tag without a "src" attribute.');
}
$chunks[$i] = sprintf('<?php echo $this->surrogate->handle($this, %s, %s, %s) ?>'."\n",
var_export($options['src'], true),
var_export(isset($options['alt']) ? $options['alt'] : '', true),
isset($options['onerror']) && 'continue' == $options['onerror'] ? 'true' : 'false'
);
++$i;
$chunks[$i] = str_replace($this->phpEscapeMap[0], $this->phpEscapeMap[1], $chunks[$i]);
++$i;
}
$content = implode('', $chunks);
$response->setContent($content);
$response->headers->set('X-Body-Eval', 'ESI');
@ -259,32 +287,4 @@ class Esi implements SurrogateInterface
}
}
}
/**
* Handles an ESI include tag (called internally).
*
* @param array $attributes An array containing the attributes.
*
* @return string The response content for the include.
*
* @throws \RuntimeException
*/
private function handleEsiIncludeTag($attributes)
{
$options = array();
preg_match_all('/(src|onerror|alt)="([^"]*?)"/', $attributes[1], $matches, PREG_SET_ORDER);
foreach ($matches as $set) {
$options[$set[1]] = $set[2];
}
if (!isset($options['src'])) {
throw new \RuntimeException('Unable to process an ESI tag without a "src" attribute.');
}
return sprintf('<?php echo $this->surrogate->handle($this, %s, %s, %s) ?>'."\n",
var_export($options['src'], true),
var_export(isset($options['alt']) ? $options['alt'] : '', true),
isset($options['onerror']) && 'continue' == $options['onerror'] ? 'true' : 'false'
);
}
}

View File

@ -124,10 +124,10 @@ class EsiTest extends \PHPUnit_Framework_TestCase
$esi = new Esi();
$request = Request::create('/');
$response = new Response('foo <?php die("foo"); ?><%= "lala" %>');
$response = new Response('<?php <? <% <script language=php>');
$esi->process($request, $response);
$this->assertEquals('foo <?php echo "<?"; ?>php die("foo"); ?><?php echo "<%"; ?>= "lala" %>', $response->getContent());
$this->assertEquals('<?php echo "<?"; ?>php <?php echo "<?"; ?> <?php echo "<%"; ?> <?php echo "<s"; ?>cript language=php>', $response->getContent());
}
/**