PageRenderTime 84ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/cart/bootstrap_cache.php

https://github.com/noelg/symfony-demo
PHP | 2495 lines | 2492 code | 3 blank | 0 comment | 355 complexity | 6d8998ff258197face03839a0f5e6d7f MD5 | raw file
Possible License(s): ISC, BSD-3-Clause
  1. <?php
  2. namespace { require_once __DIR__.'/autoload.php'; }
  3. namespace Symfony\Component\HttpKernel
  4. {
  5. use Symfony\Component\DependencyInjection\ContainerInterface;
  6. use Symfony\Component\HttpKernel\HttpKernelInterface;
  7. use Symfony\Component\HttpKernel\Bundle\BundleInterface;
  8. use Symfony\Component\Config\Loader\LoaderInterface;
  9. interface KernelInterface extends HttpKernelInterface, \Serializable
  10. {
  11. function registerRootDir();
  12. function registerBundles();
  13. function registerContainerConfiguration(LoaderInterface $loader);
  14. function boot();
  15. function shutdown();
  16. function getBundles();
  17. function isClassInActiveBundle($class);
  18. function getBundle($name, $first = true);
  19. function locateResource($name, $dir = null, $first = true);
  20. function getName();
  21. function getEnvironment();
  22. function isDebug();
  23. function getRootDir();
  24. function getContainer();
  25. function getStartTime();
  26. function getCacheDir();
  27. function getLogDir();
  28. }
  29. }
  30. namespace Symfony\Component\HttpKernel
  31. {
  32. use Symfony\Component\DependencyInjection\ContainerInterface;
  33. use Symfony\Component\DependencyInjection\ContainerBuilder;
  34. use Symfony\Component\DependencyInjection\Dumper\PhpDumper;
  35. use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
  36. use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
  37. use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
  38. use Symfony\Component\DependencyInjection\Loader\IniFileLoader;
  39. use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
  40. use Symfony\Component\DependencyInjection\Loader\ClosureLoader;
  41. use Symfony\Component\HttpFoundation\Request;
  42. use Symfony\Component\HttpKernel\HttpKernelInterface;
  43. use Symfony\Component\HttpKernel\Bundle\BundleInterface;
  44. use Symfony\Component\HttpKernel\Config\FileLocator;
  45. use Symfony\Component\Config\Loader\LoaderResolver;
  46. use Symfony\Component\Config\Loader\DelegatingLoader;
  47. use Symfony\Component\Config\ConfigCache;
  48. abstract class Kernel implements KernelInterface
  49. {
  50. protected $bundles;
  51. protected $bundleMap;
  52. protected $container;
  53. protected $rootDir;
  54. protected $environment;
  55. protected $debug;
  56. protected $booted;
  57. protected $name;
  58. protected $startTime;
  59. const VERSION = '2.0.0-DEV';
  60. public function __construct($environment, $debug)
  61. {
  62. $this->environment = $environment;
  63. $this->debug = (Boolean) $debug;
  64. $this->booted = false;
  65. $this->rootDir = realpath($this->registerRootDir());
  66. $this->name = preg_replace('/[^a-zA-Z0-9_]+/', '', basename($this->rootDir));
  67. if ($this->debug) {
  68. ini_set('display_errors', 1);
  69. error_reporting(-1);
  70. $this->startTime = microtime(true);
  71. } else {
  72. ini_set('display_errors', 0);
  73. }
  74. }
  75. public function __clone()
  76. {
  77. if ($this->debug) {
  78. $this->startTime = microtime(true);
  79. }
  80. $this->booted = false;
  81. $this->container = null;
  82. }
  83. public function boot()
  84. {
  85. if (true === $this->booted) {
  86. return;
  87. }
  88. $this->initializeBundles();
  89. $this->initializeContainer();
  90. foreach ($this->getBundles() as $bundle) {
  91. $bundle->setContainer($this->container);
  92. $bundle->boot();
  93. }
  94. $this->booted = true;
  95. }
  96. public function shutdown()
  97. {
  98. $this->booted = false;
  99. foreach ($this->getBundles() as $bundle) {
  100. $bundle->shutdown();
  101. $bundle->setContainer(null);
  102. }
  103. $this->container = null;
  104. }
  105. public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
  106. {
  107. if (false === $this->booted) {
  108. $this->boot();
  109. }
  110. return $this->getHttpKernel()->handle($request, $type, $catch);
  111. }
  112. protected function getHttpKernel()
  113. {
  114. return $this->container->get('http_kernel');
  115. }
  116. public function getBundles()
  117. {
  118. return $this->bundles;
  119. }
  120. public function isClassInActiveBundle($class)
  121. {
  122. foreach ($this->getBundles() as $bundle) {
  123. if (0 === strpos($class, $bundle->getNamespace())) {
  124. return true;
  125. }
  126. }
  127. return false;
  128. }
  129. public function getBundle($name, $first = true)
  130. {
  131. if (!isset($this->bundleMap[$name])) {
  132. throw new \InvalidArgumentException(sprintf('Bundle "%s" does not exist or it is not enabled. Maybe you forgot to add it in the registerBundles() function of your %s.php file?', $name, get_class($this)));
  133. }
  134. if (true === $first) {
  135. return $this->bundleMap[$name][0];
  136. } elseif (false === $first) {
  137. return $this->bundleMap[$name];
  138. }
  139. }
  140. public function locateResource($name, $dir = null, $first = true)
  141. {
  142. if ('@' !== $name[0]) {
  143. throw new \InvalidArgumentException(sprintf('A resource name must start with @ ("%s" given).', $name));
  144. }
  145. if (false !== strpos($name, '..')) {
  146. throw new \RuntimeException(sprintf('File name "%s" contains invalid characters (..).', $name));
  147. }
  148. $name = substr($name, 1);
  149. list($bundle, $path) = explode('/', $name, 2);
  150. $isResource = 0 === strpos($path, 'Resources');
  151. $files = array();
  152. if (true === $isResource && null !== $dir && file_exists($file = $dir.'/'.$bundle.'/'.substr($path, 10))) {
  153. if ($first) {
  154. return $file;
  155. }
  156. $files[] = $file;
  157. }
  158. foreach ($this->getBundle($bundle, false) as $bundle) {
  159. if (file_exists($file = $bundle->getPath().'/'.$path)) {
  160. if ($first) {
  161. return $file;
  162. }
  163. $files[] = $file;
  164. }
  165. }
  166. if ($files) {
  167. return $files;
  168. }
  169. throw new \InvalidArgumentException(sprintf('Unable to find file "@%s".', $name));
  170. }
  171. public function getName()
  172. {
  173. return $this->name;
  174. }
  175. public function getEnvironment()
  176. {
  177. return $this->environment;
  178. }
  179. public function isDebug()
  180. {
  181. return $this->debug;
  182. }
  183. public function getRootDir()
  184. {
  185. return $this->rootDir;
  186. }
  187. public function getContainer()
  188. {
  189. return $this->container;
  190. }
  191. public function getStartTime()
  192. {
  193. return $this->debug ? $this->startTime : -INF;
  194. }
  195. public function getCacheDir()
  196. {
  197. return $this->rootDir.'/cache/'.$this->environment;
  198. }
  199. public function getLogDir()
  200. {
  201. return $this->rootDir.'/logs';
  202. }
  203. protected function initializeBundles()
  204. {
  205. $this->bundles = array();
  206. $topMostBundles = array();
  207. $directChildren = array();
  208. foreach ($this->registerBundles() as $bundle) {
  209. $name = $bundle->getName();
  210. if (isset($this->bundles[$name])) {
  211. throw new \LogicException(sprintf('Trying to register two bundles with the same name "%s"', $name));
  212. }
  213. $this->bundles[$name] = $bundle;
  214. if ($parentName = $bundle->getParent()) {
  215. if (isset($directChildren[$parentName])) {
  216. throw new \LogicException(sprintf('Bundle "%s" is directly extended by two bundles "%s" and "%s".', $parentName, $name, $directChildren[$parentName]));
  217. }
  218. $directChildren[$parentName] = $name;
  219. } else {
  220. $topMostBundles[$name] = $bundle;
  221. }
  222. }
  223. if (count($diff = array_values(array_diff(array_keys($directChildren), array_keys($this->bundles))))) {
  224. throw new \LogicException(sprintf('Bundle "%s" extends bundle "%s", which is not registered.', $directChildren[$diff[0]], $diff[0]));
  225. }
  226. $this->bundleMap = array();
  227. foreach ($topMostBundles as $name => $bundle) {
  228. $bundleMap = array($bundle);
  229. $hierarchy = array($name);
  230. while (isset($directChildren[$name])) {
  231. $name = $directChildren[$name];
  232. array_unshift($bundleMap, $this->bundles[$name]);
  233. $hierarchy[] = $name;
  234. }
  235. foreach ($hierarchy as $bundle) {
  236. $this->bundleMap[$bundle] = $bundleMap;
  237. array_pop($bundleMap);
  238. }
  239. }
  240. }
  241. protected function initializeContainer()
  242. {
  243. $class = $this->name.ucfirst($this->environment).($this->debug ? 'Debug' : '').'ProjectContainer';
  244. $cache = new ConfigCache($this->getCacheDir(), $class, $this->debug);
  245. $fresh = false;
  246. if (!$cache->isFresh()) {
  247. $container = $this->buildContainer();
  248. $this->dumpContainer($cache, $container, $class);
  249. $fresh = true;
  250. }
  251. require_once $cache;
  252. $this->container = new $class();
  253. $this->container->set('kernel', $this);
  254. if ($fresh && 'cli' !== php_sapi_name()) {
  255. $this->container->get('cache_warmer')->warmUp($this->container->getParameter('kernel.cache_dir'));
  256. }
  257. }
  258. protected function getKernelParameters()
  259. {
  260. $bundles = array();
  261. foreach ($this->bundles as $name => $bundle) {
  262. $bundles[$name] = get_class($bundle);
  263. }
  264. return array_merge(
  265. array(
  266. 'kernel.root_dir' => $this->rootDir,
  267. 'kernel.environment' => $this->environment,
  268. 'kernel.debug' => $this->debug,
  269. 'kernel.name' => $this->name,
  270. 'kernel.cache_dir' => $this->getCacheDir(),
  271. 'kernel.logs_dir' => $this->getLogDir(),
  272. 'kernel.bundles' => $bundles,
  273. 'kernel.charset' => 'UTF-8',
  274. ),
  275. $this->getEnvParameters()
  276. );
  277. }
  278. protected function getEnvParameters()
  279. {
  280. $parameters = array();
  281. foreach ($_SERVER as $key => $value) {
  282. if ('SYMFONY__' === substr($key, 0, 9)) {
  283. $parameters[strtolower(str_replace('__', '.', substr($key, 9)))] = $value;
  284. }
  285. }
  286. return $parameters;
  287. }
  288. protected function buildContainer()
  289. {
  290. $parameterBag = new ParameterBag($this->getKernelParameters());
  291. $container = new ContainerBuilder($parameterBag);
  292. foreach ($this->bundles as $bundle) {
  293. $bundle->build($container);
  294. if ($this->debug) {
  295. $container->addObjectResource($bundle);
  296. }
  297. }
  298. $container->addObjectResource($this);
  299. if (null !== $cont = $this->registerContainerConfiguration($this->getContainerLoader($container))) {
  300. $container->merge($cont);
  301. }
  302. $container->compile();
  303. return $container;
  304. }
  305. protected function dumpContainer(ConfigCache $cache, ContainerBuilder $container, $class)
  306. {
  307. foreach (array('cache', 'logs') as $name) {
  308. $dir = $container->getParameter(sprintf('kernel.%s_dir', $name));
  309. if (!is_dir($dir)) {
  310. if (false === @mkdir($dir, 0777, true)) {
  311. die(sprintf("Unable to create the %s directory (%s)\n", $name, dirname($dir)));
  312. }
  313. } elseif (!is_writable($dir)) {
  314. die(sprintf("Unable to write in the %s directory (%s)\n", $name, $dir));
  315. }
  316. }
  317. $dumper = new PhpDumper($container);
  318. $content = $dumper->dump(array('class' => $class));
  319. if (!$this->debug) {
  320. $content = self::stripComments($content);
  321. }
  322. $cache->write($content, $container->getResources());
  323. }
  324. protected function getContainerLoader(ContainerInterface $container)
  325. {
  326. $resolver = new LoaderResolver(array(
  327. new XmlFileLoader($container, new FileLocator($this)),
  328. new YamlFileLoader($container, new FileLocator($this)),
  329. new IniFileLoader($container, new FileLocator($this)),
  330. new PhpFileLoader($container, new FileLocator($this)),
  331. new ClosureLoader($container, new FileLocator($this)),
  332. ));
  333. return new DelegatingLoader($resolver);
  334. }
  335. static public function stripComments($source)
  336. {
  337. if (!function_exists('token_get_all')) {
  338. return $source;
  339. }
  340. $output = '';
  341. foreach (token_get_all($source) as $token) {
  342. if (is_string($token)) {
  343. $output .= $token;
  344. } elseif (!in_array($token[0], array(T_COMMENT, T_DOC_COMMENT))) {
  345. $output .= $token[1];
  346. }
  347. }
  348. $output = preg_replace(array('/\s+$/Sm', '/\n+/S'), "\n", $output);
  349. return $output;
  350. }
  351. public function serialize()
  352. {
  353. return serialize(array($this->environment, $this->debug));
  354. }
  355. public function unserialize($data)
  356. {
  357. list($environment, $debug) = unserialize($data);
  358. $this->__construct($environment, $debug);
  359. }
  360. }
  361. }
  362. namespace Symfony\Component\HttpKernel
  363. {
  364. use Symfony\Component\HttpFoundation\Request;
  365. interface HttpKernelInterface
  366. {
  367. const MASTER_REQUEST = 1;
  368. const SUB_REQUEST = 2;
  369. function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true);
  370. }
  371. }
  372. namespace Symfony\Component\HttpKernel\HttpCache
  373. {
  374. use Symfony\Component\HttpKernel\HttpKernelInterface;
  375. use Symfony\Component\HttpFoundation\Request;
  376. use Symfony\Component\HttpFoundation\Response;
  377. class HttpCache implements HttpKernelInterface
  378. {
  379. protected $kernel;
  380. protected $traces;
  381. protected $store;
  382. protected $request;
  383. protected $esi;
  384. protected $esiTtls;
  385. public function __construct(HttpKernelInterface $kernel, StoreInterface $store, Esi $esi = null, array $options = array())
  386. {
  387. $this->store = $store;
  388. $this->kernel = $kernel;
  389. register_shutdown_function(array($this->store, 'cleanup'));
  390. $this->options = array_merge(array(
  391. 'debug' => false,
  392. 'default_ttl' => 0,
  393. 'private_headers' => array('Authorization', 'Cookie'),
  394. 'allow_reload' => false,
  395. 'allow_revalidate' => false,
  396. 'stale_while_revalidate' => 2,
  397. 'stale_if_error' => 60,
  398. ), $options);
  399. $this->esi = $esi;
  400. }
  401. public function getTraces()
  402. {
  403. return $this->traces;
  404. }
  405. public function getLog()
  406. {
  407. $log = array();
  408. foreach ($this->traces as $request => $traces) {
  409. $log[] = sprintf('%s: %s', $request, implode(', ', $traces));
  410. }
  411. return implode('; ', $log);
  412. }
  413. public function getRequest()
  414. {
  415. return $this->request;
  416. }
  417. public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
  418. {
  419. if (HttpKernelInterface::MASTER_REQUEST === $type) {
  420. $this->traces = array();
  421. $this->request = $request;
  422. $this->esiTtls = array();
  423. }
  424. $path = $request->getPathInfo();
  425. if ($qs = $request->getQueryString()) {
  426. $path .= '?'.$qs;
  427. }
  428. $this->traces[$request->getMethod().' '.$path] = array();
  429. if (!$request->isMethodSafe($request)) {
  430. $response = $this->invalidate($request, $catch);
  431. } elseif ($request->headers->has('expect')) {
  432. $response = $this->pass($request, $catch);
  433. } else {
  434. $response = $this->lookup($request, $catch);
  435. }
  436. $response->isNotModified($request);
  437. $this->restoreResponseBody($request, $response);
  438. if (HttpKernelInterface::MASTER_REQUEST === $type && $this->options['debug']) {
  439. $response->headers->set('X-Symfony-Cache', $this->getLog());
  440. }
  441. if (null !== $this->esi) {
  442. $this->addEsiTtl($response);
  443. if ($request === $this->request) {
  444. $this->updateResponseCacheControl($response);
  445. }
  446. }
  447. return $response;
  448. }
  449. protected function addEsiTtl(Response $response)
  450. {
  451. $this->esiTtls[] = $response->isValidateable() ? -1 : $response->getTtl();
  452. }
  453. protected function updateResponseCacheControl(Response $response)
  454. {
  455. $ttl = min($this->esiTtls);
  456. if (-1 === $ttl) {
  457. $response->headers->set('Cache-Control', 'no-cache, must-revalidate');
  458. } else {
  459. $response->setSharedMaxAge($ttl);
  460. $response->setMaxAge(0);
  461. }
  462. }
  463. protected function pass(Request $request, $catch = false)
  464. {
  465. $this->record($request, 'pass');
  466. return $this->forward($request, $catch);
  467. }
  468. protected function invalidate(Request $request, $catch = false)
  469. {
  470. $response = $this->pass($request, $catch);
  471. if ($response->isSuccessful() || $response->isRedirect()) {
  472. try {
  473. $this->store->invalidate($request, $catch);
  474. $this->record($request, 'invalidate');
  475. } catch (\Exception $e) {
  476. $this->record($request, 'invalidate-failed');
  477. if ($this->options['debug']) {
  478. throw $e;
  479. }
  480. }
  481. }
  482. return $response;
  483. }
  484. protected function lookup(Request $request, $catch = false)
  485. {
  486. if ($this->options['allow_reload'] && $request->isNoCache()) {
  487. $this->record($request, 'reload');
  488. return $this->fetch($request);
  489. }
  490. try {
  491. $entry = $this->store->lookup($request);
  492. } catch (\Exception $e) {
  493. $this->record($request, 'lookup-failed');
  494. if ($this->options['debug']) {
  495. throw $e;
  496. }
  497. return $this->pass($request, $catch);
  498. }
  499. if (null === $entry) {
  500. $this->record($request, 'miss');
  501. return $this->fetch($request, $catch);
  502. }
  503. if (!$this->isFreshEnough($request, $entry)) {
  504. $this->record($request, 'stale');
  505. return $this->validate($request, $entry);
  506. }
  507. $this->record($request, 'fresh');
  508. $entry->headers->set('Age', $entry->getAge());
  509. return $entry;
  510. }
  511. protected function validate(Request $request, Response $entry)
  512. {
  513. $subRequest = clone $request;
  514. $subRequest->setMethod('get');
  515. $subRequest->headers->set('if_modified_since', $entry->headers->get('Last-Modified'));
  516. $cachedEtags = array($entry->getEtag());
  517. $requestEtags = $request->getEtags();
  518. $etags = array_unique(array_merge($cachedEtags, $requestEtags));
  519. $subRequest->headers->set('if_none_match', $etags ? implode(', ', $etags) : '');
  520. $response = $this->forward($subRequest, false, $entry);
  521. if (304 == $response->getStatusCode()) {
  522. $this->record($request, 'valid');
  523. $etag = $response->getEtag();
  524. if ($etag && in_array($etag, $requestEtags) && !in_array($etag, $cachedEtags)) {
  525. return $response;
  526. }
  527. $entry = clone $entry;
  528. $entry->headers->remove('Date');
  529. foreach (array('Date', 'Expires', 'Cache-Control', 'ETag', 'Last-Modified') as $name) {
  530. if ($response->headers->has($name)) {
  531. $entry->headers->set($name, $response->headers->get($name));
  532. }
  533. }
  534. $response = $entry;
  535. } else {
  536. $this->record($request, 'invalid');
  537. }
  538. if ($response->isCacheable()) {
  539. $this->store($request, $response);
  540. }
  541. return $response;
  542. }
  543. protected function fetch(Request $request, $catch = false)
  544. {
  545. $subRequest = clone $request;
  546. $subRequest->setMethod('get');
  547. $subRequest->headers->remove('if_modified_since');
  548. $subRequest->headers->remove('if_none_match');
  549. $response = $this->forward($subRequest, $catch);
  550. if ($this->isPrivateRequest($request) && !$response->headers->hasCacheControlDirective('public')) {
  551. $response->setPrivate(true);
  552. } elseif ($this->options['default_ttl'] > 0 && null === $response->getTtl() && !$response->headers->getCacheControlDirective('must-revalidate')) {
  553. $response->setTtl($this->options['default_ttl']);
  554. }
  555. if ($response->isCacheable()) {
  556. $this->store($request, $response);
  557. }
  558. return $response;
  559. }
  560. protected function forward(Request $request, $catch = false, Response $entry = null)
  561. {
  562. if ($this->esi) {
  563. $this->esi->addSurrogateEsiCapability($request);
  564. }
  565. $response = $this->kernel->handle($request, HttpKernelInterface::MASTER_REQUEST, $catch);
  566. if (null !== $entry && in_array($response->getStatusCode(), array(500, 502, 503, 504))) {
  567. if (null === $age = $entry->headers->getCacheControlDirective('stale-if-error')) {
  568. $age = $this->options['stale_if_error'];
  569. }
  570. if (abs($entry->getTtl()) < $age) {
  571. $this->record($request, 'stale-if-error');
  572. return $entry;
  573. }
  574. }
  575. $this->processResponseBody($request, $response);
  576. return $response;
  577. }
  578. protected function isFreshEnough(Request $request, Response $entry)
  579. {
  580. if (!$entry->isFresh()) {
  581. return $this->lock($request, $entry);
  582. }
  583. if ($this->options['allow_revalidate'] && null !== $maxAge = $request->headers->getCacheControlDirective('max-age')) {
  584. return $maxAge > 0 && $maxAge >= $entry->getAge();
  585. }
  586. return true;
  587. }
  588. protected function lock(Request $request, Response $entry)
  589. {
  590. $lock = $this->store->lock($request, $entry);
  591. if (true !== $lock) {
  592. if (null === $age = $entry->headers->getCacheControlDirective('stale-while-revalidate')) {
  593. $age = $this->options['stale_while_revalidate'];
  594. }
  595. if (abs($entry->getTtl()) < $age) {
  596. $this->record($request, 'stale-while-revalidate');
  597. return true;
  598. } else {
  599. $wait = 0;
  600. while (file_exists($lock) && $wait < 5000000) {
  601. usleep($wait += 50000);
  602. }
  603. if ($wait < 2000000) {
  604. $new = $this->lookup($request);
  605. $entry->headers = $new->headers;
  606. $entry->setContent($new->getContent());
  607. $entry->setStatusCode($new->getStatusCode());
  608. $entry->setProtocolVersion($new->getProtocolVersion());
  609. $entry->setCookies($new->getCookies());
  610. return true;
  611. } else {
  612. $entry->setStatusCode(503);
  613. $entry->setContent('503 Service Unavailable');
  614. $entry->headers->set('Retry-After', 10);
  615. return true;
  616. }
  617. }
  618. }
  619. return false;
  620. }
  621. protected function store(Request $request, Response $response)
  622. {
  623. try {
  624. $this->store->write($request, $response);
  625. $this->record($request, 'store');
  626. $response->headers->set('Age', $response->getAge());
  627. } catch (\Exception $e) {
  628. $this->record($request, 'store-failed');
  629. if ($this->options['debug']) {
  630. throw $e;
  631. }
  632. }
  633. $this->store->unlock($request);
  634. }
  635. protected function restoreResponseBody(Request $request, Response $response)
  636. {
  637. if ('head' === strtolower($request->getMethod())) {
  638. $response->setContent('');
  639. $response->headers->remove('X-Body-Eval');
  640. $response->headers->remove('X-Body-File');
  641. return;
  642. }
  643. if ($response->headers->has('X-Body-Eval')) {
  644. ob_start();
  645. if ($response->headers->has('X-Body-File')) {
  646. include $response->headers->get('X-Body-File');
  647. } else {
  648. eval('; ?>'.$response->getContent().'<?php ;');
  649. }
  650. $response->setContent(ob_get_clean());
  651. $response->headers->remove('X-Body-Eval');
  652. } elseif ($response->headers->has('X-Body-File')) {
  653. $response->setContent(file_get_contents($response->headers->get('X-Body-File')));
  654. } else {
  655. return;
  656. }
  657. $response->headers->remove('X-Body-File');
  658. if (!$response->headers->has('Transfer-Encoding')) {
  659. $response->headers->set('Content-Length', strlen($response->getContent()));
  660. }
  661. }
  662. protected function processResponseBody(Request $request, Response $response)
  663. {
  664. if (null !== $this->esi && $this->esi->needsEsiParsing($response)) {
  665. $this->esi->process($request, $response);
  666. }
  667. }
  668. protected function isPrivateRequest(Request $request)
  669. {
  670. foreach ($this->options['private_headers'] as $key) {
  671. $key = strtolower(str_replace('HTTP_', '', $key));
  672. if ('cookie' === $key) {
  673. if (count($request->cookies->all())) {
  674. return true;
  675. }
  676. } elseif ($request->headers->has($key)) {
  677. return true;
  678. }
  679. }
  680. return false;
  681. }
  682. protected function record(Request $request, $event)
  683. {
  684. $path = $request->getPathInfo();
  685. if ($qs = $request->getQueryString()) {
  686. $path .= '?'.$qs;
  687. }
  688. $this->traces[$request->getMethod().' '.$path][] = $event;
  689. }
  690. }
  691. }
  692. namespace Symfony\Component\HttpKernel\HttpCache
  693. {
  694. use Symfony\Component\HttpFoundation\Request;
  695. use Symfony\Component\HttpFoundation\Response;
  696. use Symfony\Component\HttpFoundation\HeaderBag;
  697. interface StoreInterface
  698. {
  699. function lookup(Request $request);
  700. function write(Request $request, Response $response);
  701. function invalidate(Request $request);
  702. function lock(Request $request);
  703. function unlock(Request $request);
  704. function purge($url);
  705. function cleanup();
  706. }
  707. }
  708. namespace Symfony\Component\HttpKernel\HttpCache
  709. {
  710. use Symfony\Component\HttpFoundation\Request;
  711. use Symfony\Component\HttpFoundation\Response;
  712. use Symfony\Component\HttpFoundation\HeaderBag;
  713. class Store implements StoreInterface
  714. {
  715. protected $root;
  716. protected $keyCache;
  717. protected $locks;
  718. public function __construct($root)
  719. {
  720. $this->root = $root;
  721. if (!is_dir($this->root)) {
  722. mkdir($this->root, 0777, true);
  723. }
  724. $this->keyCache = new \SplObjectStorage();
  725. $this->locks = array();
  726. }
  727. public function cleanup()
  728. {
  729. foreach ($this->locks as $lock) {
  730. @unlink($lock);
  731. }
  732. $error = error_get_last();
  733. if (1 === $error['type'] && false === headers_sent()) {
  734. header('HTTP/1.0 503 Service Unavailable');
  735. header('Retry-After: 10');
  736. echo '503 Service Unavailable';
  737. }
  738. }
  739. public function lock(Request $request)
  740. {
  741. if (false !== $lock = @fopen($path = $this->getPath($this->getCacheKey($request).'.lck'), 'x')) {
  742. fclose($lock);
  743. $this->locks[] = $path;
  744. return true;
  745. } else {
  746. return $path;
  747. }
  748. }
  749. public function unlock(Request $request)
  750. {
  751. return @unlink($this->getPath($this->getCacheKey($request).'.lck'));
  752. }
  753. public function lookup(Request $request)
  754. {
  755. $key = $this->getCacheKey($request);
  756. if (!$entries = $this->getMetadata($key)) {
  757. return null;
  758. }
  759. $match = null;
  760. foreach ($entries as $entry) {
  761. if ($this->requestsMatch(isset($entry[1]['vary']) ? $entry[1]['vary'][0] : '', $request->headers->all(), $entry[0])) {
  762. $match = $entry;
  763. break;
  764. }
  765. }
  766. if (null === $match) {
  767. return null;
  768. }
  769. list($req, $headers) = $match;
  770. if (file_exists($body = $this->getPath($headers['x-content-digest'][0]))) {
  771. return $this->restoreResponse($headers, $body);
  772. } else {
  773. return null;
  774. }
  775. }
  776. public function write(Request $request, Response $response)
  777. {
  778. $key = $this->getCacheKey($request);
  779. $storedEnv = $this->persistRequest($request);
  780. if (!$response->headers->has('X-Content-Digest')) {
  781. $digest = 'en'.sha1($response->getContent());
  782. if (false === $this->save($digest, $response->getContent())) {
  783. throw new \RuntimeException('Unable to store the entity.');
  784. }
  785. $response->headers->set('X-Content-Digest', $digest);
  786. if (!$response->headers->has('Transfer-Encoding')) {
  787. $response->headers->set('Content-Length', strlen($response->getContent()));
  788. }
  789. }
  790. $entries = array();
  791. $vary = $response->headers->get('vary');
  792. foreach ($this->getMetadata($key) as $entry) {
  793. if (!isset($entry[1]['vary'])) {
  794. $entry[1]['vary'] = array('');
  795. }
  796. if ($vary != $entry[1]['vary'][0] || !$this->requestsMatch($vary, $entry[0], $storedEnv)) {
  797. $entries[] = $entry;
  798. }
  799. }
  800. $headers = $this->persistResponse($response);
  801. unset($headers['age']);
  802. array_unshift($entries, array($storedEnv, $headers));
  803. if (false === $this->save($key, serialize($entries))) {
  804. throw new \RuntimeException('Unable to store the metadata.');
  805. }
  806. return $key;
  807. }
  808. public function invalidate(Request $request)
  809. {
  810. $modified = false;
  811. $key = $this->getCacheKey($request);
  812. $entries = array();
  813. foreach ($this->getMetadata($key) as $entry) {
  814. $response = $this->restoreResponse($entry[1]);
  815. if ($response->isFresh()) {
  816. $response->expire();
  817. $modified = true;
  818. $entries[] = array($entry[0], $this->persistResponse($response));
  819. } else {
  820. $entries[] = $entry;
  821. }
  822. }
  823. if ($modified) {
  824. if (false === $this->save($key, serialize($entries))) {
  825. throw new \RuntimeException('Unable to store the metadata.');
  826. }
  827. }
  828. foreach (array('Location', 'Content-Location') as $header) {
  829. if ($uri = $request->headers->get($header)) {
  830. $subRequest = Request::create($uri, 'get', array(), array(), array(), $request->server->all());
  831. $this->invalidate($subRequest);
  832. }
  833. }
  834. }
  835. protected function requestsMatch($vary, $env1, $env2)
  836. {
  837. if (empty($vary)) {
  838. return true;
  839. }
  840. foreach (preg_split('/[\s,]+/', $vary) as $header) {
  841. $key = strtr(strtolower($header), '_', '-');
  842. $v1 = isset($env1[$key]) ? $env1[$key] : null;
  843. $v2 = isset($env2[$key]) ? $env2[$key] : null;
  844. if ($v1 !== $v2) {
  845. return false;
  846. }
  847. }
  848. return true;
  849. }
  850. protected function getMetadata($key)
  851. {
  852. if (false === $entries = $this->load($key)) {
  853. return array();
  854. }
  855. return unserialize($entries);
  856. }
  857. public function purge($url)
  858. {
  859. if (file_exists($path = $this->getPath($this->getCacheKey(Request::create($url))))) {
  860. unlink($path);
  861. return true;
  862. }
  863. return false;
  864. }
  865. protected function load($key)
  866. {
  867. $path = $this->getPath($key);
  868. return file_exists($path) ? file_get_contents($path) : false;
  869. }
  870. protected function save($key, $data)
  871. {
  872. $path = $this->getPath($key);
  873. if (!is_dir(dirname($path)) && false === @mkdir(dirname($path), 0777, true)) {
  874. return false;
  875. }
  876. $tmpFile = tempnam(dirname($path), basename($path));
  877. if (false === $fp = @fopen($tmpFile, 'wb')) {
  878. return false;
  879. }
  880. @fwrite($fp, $data);
  881. @fclose($fp);
  882. if ($data != file_get_contents($tmpFile)) {
  883. return false;
  884. }
  885. if (false === @rename($tmpFile, $path)) {
  886. return false;
  887. }
  888. chmod($path, 0644);
  889. }
  890. public function getPath($key)
  891. {
  892. return $this->root.DIRECTORY_SEPARATOR.substr($key, 0, 2).DIRECTORY_SEPARATOR.substr($key, 2, 2).DIRECTORY_SEPARATOR.substr($key, 4, 2).DIRECTORY_SEPARATOR.substr($key, 6);
  893. }
  894. protected function getCacheKey(Request $request)
  895. {
  896. if (isset($this->keyCache[$request])) {
  897. return $this->keyCache[$request];
  898. }
  899. return $this->keyCache[$request] = 'md'.sha1($request->getUri());
  900. }
  901. protected function persistRequest(Request $request)
  902. {
  903. return $request->headers->all();
  904. }
  905. protected function persistResponse(Response $response)
  906. {
  907. $headers = $response->headers->all();
  908. $headers['X-Status'] = array($response->getStatusCode());
  909. return $headers;
  910. }
  911. protected function restoreResponse($headers, $body = null)
  912. {
  913. $status = $headers['X-Status'][0];
  914. unset($headers['X-Status']);
  915. if (null !== $body) {
  916. $headers['X-Body-File'] = array($body);
  917. }
  918. return new Response($body, $status, $headers);
  919. }
  920. }
  921. }
  922. namespace Symfony\Component\HttpKernel\HttpCache
  923. {
  924. use Symfony\Component\HttpFoundation\Request;
  925. use Symfony\Component\HttpFoundation\Response;
  926. use Symfony\Component\HttpKernel\HttpKernelInterface;
  927. class Esi
  928. {
  929. protected $contentTypes;
  930. public function __construct(array $contentTypes = array('text/html', 'text/xml', 'application/xml'))
  931. {
  932. $this->contentTypes = $contentTypes;
  933. }
  934. public function hasSurrogateEsiCapability(Request $request)
  935. {
  936. if (null === $value = $request->headers->get('Surrogate-Capability')) {
  937. return false;
  938. }
  939. return (Boolean) preg_match('#ESI/1.0#', $value);
  940. }
  941. public function addSurrogateEsiCapability(Request $request)
  942. {
  943. $current = $request->headers->get('Surrogate-Capability');
  944. $new = 'symfony2="ESI/1.0"';
  945. $request->headers->set('Surrogate-Capability', $current ? $current.', '.$new : $new);
  946. }
  947. public function addSurrogateControl(Response $response)
  948. {
  949. if (false !== strpos($response->getContent(), '<esi:include')) {
  950. $response->headers->set('Surrogate-Control', 'content="ESI/1.0"');
  951. }
  952. }
  953. public function needsEsiParsing(Response $response)
  954. {
  955. if (!$control = $response->headers->get('Surrogate-Control')) {
  956. return false;
  957. }
  958. return (Boolean) preg_match('#content="[^"]*ESI/1.0[^"]*"#', $control);
  959. }
  960. public function renderIncludeTag($uri, $alt = null, $ignoreErrors = true, $comment = '')
  961. {
  962. $html = sprintf('<esi:include src="%s"%s%s />',
  963. $uri,
  964. $ignoreErrors ? ' onerror="continue"' : '',
  965. $alt ? sprintf(' alt="%s"', $alt) : ''
  966. );
  967. if (!empty($comment)) {
  968. return sprintf("<esi:comment text=\"%s\" />\n%s", $comment, $html);
  969. }
  970. return $html;
  971. }
  972. public function process(Request $request, Response $response)
  973. {
  974. $this->request = $request;
  975. $type = $response->headers->get('Content-Type');
  976. if (empty($type)) {
  977. $type = 'text/html';
  978. }
  979. $parts = explode(';', $type);
  980. if (!in_array($parts[0], $this->contentTypes)) {
  981. return $response;
  982. }
  983. $content = $response->getContent();
  984. $content = preg_replace_callback('#<esi\:include\s+(.*?)\s*/>#', array($this, 'handleEsiIncludeTag'), $content);
  985. $content = preg_replace('#<esi\:comment[^>]*/>#', '', $content);
  986. $content = preg_replace('#<esi\:remove>.*?</esi\:remove>#', '', $content);
  987. $response->setContent($content);
  988. $response->headers->set('X-Body-Eval', 'ESI');
  989. if ($response->headers->has('Surrogate-Control')) {
  990. $value = $response->headers->get('Surrogate-Control');
  991. if ('content="ESI/1.0"' == $value) {
  992. $response->headers->remove('Surrogate-Control');
  993. } elseif (preg_match('#,\s*content="ESI/1.0"#', $value)) {
  994. $response->headers->set('Surrogate-Control', preg_replace('#,\s*content="ESI/1.0"#', '', $value));
  995. } elseif (preg_match('#content="ESI/1.0",\s*#', $value)) {
  996. $response->headers->set('Surrogate-Control', preg_replace('#content="ESI/1.0",\s*#', '', $value));
  997. }
  998. }
  999. }
  1000. public function handle(HttpCache $cache, $uri, $alt, $ignoreErrors)
  1001. {
  1002. $subRequest = Request::create($uri, 'get', array(), $cache->getRequest()->cookies->all(), array(), $cache->getRequest()->server->all());
  1003. try {
  1004. $response = $cache->handle($subRequest, HttpKernelInterface::SUB_REQUEST, true);
  1005. if (!$response->isSuccessful()) {
  1006. throw new \RuntimeException(sprintf('Error when rendering "%s" (Status code is %s).', $subRequest->getUri(), $response->getStatusCode()));
  1007. }
  1008. return $response->getContent();
  1009. } catch (\Exception $e) {
  1010. if ($alt) {
  1011. return $this->handle($cache, $alt, '', $ignoreErrors);
  1012. }
  1013. if (!$ignoreErrors) {
  1014. throw $e;
  1015. }
  1016. }
  1017. }
  1018. protected function handleEsiIncludeTag($attributes)
  1019. {
  1020. $options = array();
  1021. preg_match_all('/(src|onerror|alt)="([^"]*?)"/', $attributes[1], $matches, PREG_SET_ORDER);
  1022. foreach ($matches as $set) {
  1023. $options[$set[1]] = $set[2];
  1024. }
  1025. if (!isset($options['src'])) {
  1026. throw new \RuntimeException('Unable to process an ESI tag without a "src" attribute.');
  1027. }
  1028. return sprintf('<?php echo $this->esi->handle($this, \'%s\', \'%s\', %s) ?>'."\n",
  1029. $options['src'],
  1030. isset($options['alt']) ? $options['alt'] : null,
  1031. isset($options['onerror']) && 'continue' == $options['onerror'] ? 'true' : 'false'
  1032. );
  1033. }
  1034. }
  1035. }
  1036. namespace Symfony\Component\HttpFoundation
  1037. {
  1038. class ParameterBag
  1039. {
  1040. protected $parameters;
  1041. public function __construct(array $parameters = array())
  1042. {
  1043. $this->parameters = $parameters;
  1044. }
  1045. public function all()
  1046. {
  1047. return $this->parameters;
  1048. }
  1049. public function keys()
  1050. {
  1051. return array_keys($this->parameters);
  1052. }
  1053. public function replace(array $parameters = array())
  1054. {
  1055. $this->parameters = $parameters;
  1056. }
  1057. public function add(array $parameters = array())
  1058. {
  1059. $this->parameters = array_replace($this->parameters, $parameters);
  1060. }
  1061. public function get($key, $default = null)
  1062. {
  1063. return array_key_exists($key, $this->parameters) ? $this->parameters[$key] : $default;
  1064. }
  1065. public function set($key, $value)
  1066. {
  1067. $this->parameters[$key] = $value;
  1068. }
  1069. public function has($key)
  1070. {
  1071. return array_key_exists($key, $this->parameters);
  1072. }
  1073. public function remove($key)
  1074. {
  1075. unset($this->parameters[$key]);
  1076. }
  1077. public function getAlpha($key, $default = '')
  1078. {
  1079. return preg_replace('/[^[:alpha:]]/', '', $this->get($key, $default));
  1080. }
  1081. public function getAlnum($key, $default = '')
  1082. {
  1083. return preg_replace('/[^[:alnum:]]/', '', $this->get($key, $default));
  1084. }
  1085. public function getDigits($key, $default = '')
  1086. {
  1087. return preg_replace('/[^[:digit:]]/', '', $this->get($key, $default));
  1088. }
  1089. public function getInt($key, $default = 0)
  1090. {
  1091. return (int) $this->get($key, $default);
  1092. }
  1093. }
  1094. }
  1095. namespace Symfony\Component\HttpFoundation
  1096. {
  1097. use Symfony\Component\HttpFoundation\File\UploadedFile;
  1098. class FileBag extends ParameterBag
  1099. {
  1100. private $fileKeys = array('error', 'name', 'size', 'tmp_name', 'type');
  1101. public function __construct(array $parameters = array())
  1102. {
  1103. $this->replace($parameters);
  1104. }
  1105. public function replace(array $files = array())
  1106. {
  1107. $this->parameters = array();
  1108. $this->add($files);
  1109. }
  1110. public function set($key, $value)
  1111. {
  1112. if (is_array($value) || $value instanceof UploadedFile) {
  1113. parent::set($key, $this->convertFileInformation($value));
  1114. }
  1115. }
  1116. public function add(array $files = array())
  1117. {
  1118. foreach ($files as $key => $file) {
  1119. $this->set($key, $file);
  1120. }
  1121. }
  1122. protected function convertFileInformation($file)
  1123. {
  1124. if ($file instanceof UploadedFile) {
  1125. return $file;
  1126. }
  1127. $file = $this->fixPhpFilesArray($file);
  1128. if (is_array($file)) {
  1129. $keys = array_keys($file);
  1130. sort($keys);
  1131. if ($keys == $this->fileKeys) {
  1132. $file['error'] = (int) $file['error'];
  1133. }
  1134. if ($keys != $this->fileKeys) {
  1135. $file = array_map(array($this, 'convertFileInformation'), $file);
  1136. } else
  1137. if ($file['error'] === UPLOAD_ERR_NO_FILE) {
  1138. $file = null;
  1139. } else {
  1140. $file = new UploadedFile($file['tmp_name'], $file['name'],
  1141. $file['type'], $file['size'], $file['error']);
  1142. }
  1143. }
  1144. return $file;
  1145. }
  1146. protected function fixPhpFilesArray($data)
  1147. {
  1148. if (! is_array($data)) {
  1149. return $data;
  1150. }
  1151. $keys = array_keys($data);
  1152. sort($keys);
  1153. if ($this->fileKeys != $keys || ! isset($data['name']) ||
  1154. ! is_array($data['name'])) {
  1155. return $data;
  1156. }
  1157. $files = $data;
  1158. foreach ($this->fileKeys as $k) {
  1159. unset($files[$k]);
  1160. }
  1161. foreach (array_keys($data['name']) as $key) {
  1162. $files[$key] = $this->fixPhpFilesArray(array(
  1163. 'error' => $data['error'][$key],
  1164. 'name' => $data['name'][$key], 'type' => $data['type'][$key],
  1165. 'tmp_name' => $data['tmp_name'][$key],
  1166. 'size' => $data['size'][$key]
  1167. ));
  1168. }
  1169. return $files;
  1170. }
  1171. }
  1172. }
  1173. namespace Symfony\Component\HttpFoundation
  1174. {
  1175. class ServerBag extends ParameterBag
  1176. {
  1177. public function getHeaders()
  1178. {
  1179. $headers = array();
  1180. foreach ($this->parameters as $key => $value) {
  1181. if ('HTTP_' === substr($key, 0, 5)) {
  1182. $headers[substr($key, 5)] = $value;
  1183. }
  1184. }
  1185. return $headers;
  1186. }
  1187. }
  1188. }
  1189. namespace Symfony\Component\HttpFoundation
  1190. {
  1191. class HeaderBag
  1192. {
  1193. protected $headers;
  1194. protected $cookies;
  1195. protected $cacheControl;
  1196. public function __construct(array $headers = array())
  1197. {
  1198. $this->cacheControl = array();
  1199. $this->cookies = array();
  1200. $this->headers = array();
  1201. foreach ($headers as $key => $values) {
  1202. $this->set($key, $values);
  1203. }
  1204. }
  1205. public function all()
  1206. {
  1207. return $this->headers;
  1208. }
  1209. public function keys()
  1210. {
  1211. return array_keys($this->headers);
  1212. }
  1213. public function replace(array $headers = array())
  1214. {
  1215. $this->headers = array();
  1216. $this->add($headers);
  1217. }
  1218. public function add(array $headers)
  1219. {
  1220. foreach ($headers as $key => $values) {
  1221. $this->set($key, $values);
  1222. }
  1223. }
  1224. public function get($key, $default = null, $first = true)
  1225. {
  1226. $key = strtr(strtolower($key), '_', '-');
  1227. if (!array_key_exists($key, $this->headers)) {
  1228. if (null === $default) {
  1229. return $first ? null : array();
  1230. } else {
  1231. return $first ? $default : array($default);
  1232. }
  1233. }
  1234. if ($first) {
  1235. return count($this->headers[$key]) ? $this->headers[$key][0] : $default;
  1236. } else {
  1237. return $this->headers[$key];
  1238. }
  1239. }
  1240. public function set($key, $values, $replace = true)
  1241. {
  1242. $key = strtr(strtolower($key), '_', '-');
  1243. if (!is_array($values)) {
  1244. $values = array($values);
  1245. }
  1246. if (true === $replace || !isset($this->headers[$key])) {
  1247. $this->headers[$key] = $values;
  1248. } else {
  1249. $this->headers[$key] = array_merge($this->headers[$key], $values);
  1250. }
  1251. if ('cache-control' === $key) {
  1252. $this->cacheControl = $this->parseCacheControl($values[0]);
  1253. }
  1254. }
  1255. public function has($key)
  1256. {
  1257. return array_key_exists(strtr(strtolower($key), '_', '-'), $this->headers);
  1258. }
  1259. public function contains($key, $value)
  1260. {
  1261. return in_array($value, $this->get($key, null, false));
  1262. }
  1263. public function remove($key)
  1264. {
  1265. $key = strtr(strtolower($key), '_', '-');
  1266. unset($this->headers[$key]);
  1267. if ('cache-control' === $key) {
  1268. $this->cacheControl = array();
  1269. }
  1270. }
  1271. public function setCookie(Cookie $cookie)
  1272. {
  1273. $this->cookies[$cookie->getName()] = $cookie;
  1274. }
  1275. public function removeCookie($name)
  1276. {
  1277. unset($this->cookies[$name]);
  1278. }
  1279. public function hasCookie($name)
  1280. {
  1281. return isset($this->cookies[$name]);
  1282. }
  1283. public function getCookie($name)
  1284. {
  1285. if (!$this->hasCookie($name)) {
  1286. throw new \InvalidArgumentException(sprintf('There is no cookie with name "%s".', $name));
  1287. }
  1288. return $this->cookies[$name];
  1289. }
  1290. public function getCookies()
  1291. {
  1292. return $this->cookies;
  1293. }
  1294. public function getDate($key, \DateTime $default = null)
  1295. {
  1296. if (null === $value = $this->get($key)) {
  1297. return $default;
  1298. }
  1299. if (false === $date = \DateTime::createFromFormat(DATE_RFC2822, $value)) {
  1300. throw new \RuntimeException(sprintf('The %s HTTP header is not parseable (%s).', $key, $value));
  1301. }
  1302. return $date;
  1303. }
  1304. public function addCacheControlDirective($key, $value = true)
  1305. {
  1306. $this->cacheControl[$key] = $value;
  1307. $this->set('Cache-Control', $this->getCacheControlHeader());
  1308. }
  1309. public function hasCacheControlDirective($key)
  1310. {
  1311. return array_key_exists($key, $this->cacheControl);
  1312. }
  1313. public function getCacheControlDirective($key)
  1314. {
  1315. return array_key_exists($key, $this->cacheControl) ? $this->cacheControl[$key] : null;
  1316. }
  1317. public function removeCacheControlDirective($key)
  1318. {
  1319. unset($this->cacheControl[$key]);
  1320. $this->set('Cache-Control', $this->getCacheControlHeader());
  1321. }
  1322. protected function getCacheControlHeader()
  1323. {
  1324. $parts = array();
  1325. ksort($this->cacheControl);
  1326. foreach ($this->cacheControl as $key => $value) {
  1327. if (true === $value) {
  1328. $parts[] = $key;
  1329. } else {
  1330. if (preg_match('#[^a-zA-Z0-9._-]#', $value)) {
  1331. $value = '"'.$value.'"';
  1332. }
  1333. $parts[] = "$key=$value";
  1334. }
  1335. }
  1336. return implode(', ', $parts);
  1337. }
  1338. protected function parseCacheControl($header)
  1339. {
  1340. $cacheControl = array();
  1341. preg_match_all('#([a-zA-Z][a-zA-Z_-]*)\s*(?:=(?:"([^"]*)"|([^ \t",;]*)))?#', $header, $matches, PREG_SET_ORDER);
  1342. foreach ($matches as $match) {
  1343. $cacheControl[strtolower($match[1])] = isset($match[2]) && $match[2] ? $match[2] : (isset($match[3]) ? $match[3] : true);
  1344. }
  1345. return $cacheControl;
  1346. }
  1347. }
  1348. }
  1349. namespace Symfony\Component\HttpFoundation
  1350. {
  1351. use Symfony\Component\HttpFoundation\SessionStorage\NativeSessionStorage;
  1352. use Symfony\Component\HttpFoundation\File\UploadedFile;
  1353. class Request
  1354. {
  1355. public $attributes;
  1356. public $request;
  1357. public $query;
  1358. public $server;
  1359. public $files;
  1360. public $cookies;
  1361. public $headers;
  1362. protected $content;
  1363. protected $languages;
  1364. protected $charsets;
  1365. protected $acceptableContentTypes;
  1366. protected $pathInfo;
  1367. protected $requestUri;
  1368. protected $baseUrl;
  1369. protected $basePath;
  1370. protected $method;
  1371. protected $format;
  1372. protected $session;
  1373. static protected $formats;
  1374. public function __construct(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null)
  1375. {
  1376. $this->initialize($query, $request, $attributes, $cookies, $files, $server, $content);
  1377. }
  1378. public function initialize(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null)
  1379. {
  1380. $this->request = new ParameterBag($request);
  1381. $this->query = new ParameterBag($query);
  1382. $this->attributes = new ParameterBag($attributes);
  1383. $this->cookies = new ParameterBag($cookies);
  1384. $this->files = new FileBag($files);
  1385. $this->server = new ServerBag($server);
  1386. $this->headers = new HeaderBag($this->server->getHeaders());
  1387. $this->content = $content;
  1388. $this->languages = null;
  1389. $this->charsets = null;
  1390. $this->acceptableContentTypes = null;
  1391. $this->pathInfo = null;
  1392. $this->requestUri = null;
  1393. $this->baseUrl = null;
  1394. $this->basePath = null;
  1395. $this->method = null;
  1396. $this->format = null;
  1397. }
  1398. static public function createfromGlobals()
  1399. {
  1400. return new static($_GET, $_POST, array(), $_COOKIE, $_FILES, $_SERVER);
  1401. }
  1402. static public function create($uri, $method = 'GET', $parameters = array(), $cookies = array(), $files = array(), $server = array(), $content = null)
  1403. {
  1404. $defaults = array(
  1405. 'SERVER_NAME' => 'localhost',
  1406. 'SERVER_PORT' => 80,
  1407. 'HTTP_HOST' => 'localhost',
  1408. 'HTTP_USER_AGENT' => 'Symfony/2.X',
  1409. 'HTTP_ACCEPT' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
  1410. 'HTTP_ACCEPT_LANGUAGE' => 'en-us,en;q=0.5',
  1411. 'HTTP_ACCEPT_CHARSET' => 'ISO-8859-1,utf-8;q=0.7,*;q=0.7',
  1412. 'REMOTE_ADDR' => '127.0.0.1',
  1413. 'SCRIPT_NAME' => '',
  1414. 'SCRIPT_FILENAME' => '',
  1415. );
  1416. $components = parse_url($uri);
  1417. if (isset($components['host'])) {
  1418. $defaults['SERVER_NAME'] = $components['host'];
  1419. $defaults['HTTP_HOST'] = $components['host'];
  1420. }
  1421. if (isset($components['scheme'])) {
  1422. if ('https' === $components['scheme']) {
  1423. $defaults['HTTPS'] = 'on';
  1424. $defaults['SERVER_PORT'] = 443;
  1425. }
  1426. }
  1427. if (isset($components['port'])) {
  1428. $defaults['SERVER_PORT'] = $components['port'];
  1429. $defaults['HTTP_HOST'] = $defaults['HTTP_HOST'].':'.$components['port'];
  1430. }
  1431. if (in_array(strtoupper($method), array('POST', 'PUT', 'DELETE'))) {
  1432. $request = $parameters;
  1433. $query = array();
  1434. $defaults['CONTENT_TYPE'] = 'application/x-www-form-urlencoded';
  1435. } else {
  1436. $request = array();
  1437. $query = $parameters;
  1438. if (false !== $pos = strpos($uri, '?')) {
  1439. $qs = substr($uri, $pos + 1);
  1440. parse_str($qs, $params);
  1441. $query = array_merge($params, $query);
  1442. }
  1443. }
  1444. $queryString = isset($components['query']) ? html_entity_decode($components['query']) : '';
  1445. parse_str($queryString, $qs);
  1446. if (is_array($qs)) {
  1447. $query = array_replace($qs, $query);
  1448. }
  1449. $uri = $components['path'] . ($queryString ? '?'.$queryString : '');
  1450. $server = array_replace($defaults, $server, array(
  1451. 'REQUEST_METHOD' => strtoupper($method),
  1452. 'PATH_INFO' => '',
  1453. 'REQUEST_URI' => $uri,
  1454. 'QUERY_STRING' => $queryString,
  1455. ));
  1456. return new static($query, $request, array(), $cookies, $files, $server, $content);
  1457. }
  1458. public function duplicate(array $query = null, array $request = null, array $attributes = null, array $cookies = null, array $files = null, array $server = null)
  1459. {
  1460. $dup = clone $this;
  1461. if ($query !== null) {
  1462. $dup->query = new ParameterBag($query);
  1463. }
  1464. if ($request !== null) {
  1465. $dup->request = new ParameterBag($request);
  1466. }
  1467. if ($attributes !== null) {
  1468. $dup->attributes = new ParameterBag($attributes);
  1469. }
  1470. if ($cookies !== null) {
  1471. $dup->cookies = new ParameterBag($cookies);
  1472. }
  1473. if ($files !== null) {
  1474. $dup->files = new FileBag($files);
  1475. }
  1476. if ($server !== null) {
  1477. $dup->server = new ServerBag($server);
  1478. $dup->headers = new HeaderBag($dup->server->getHeaders());
  1479. }
  1480. $this->languages = null;
  1481. $this->charsets = null;
  1482. $this->acceptableContentTypes = null;
  1483. $this->pathInfo = null;
  1484. $this->requestUri = null;
  1485. $this->baseUrl = null;
  1486. $this->basePath = null;
  1487. $this->method = null;
  1488. $this->format = null;
  1489. return $dup;
  1490. }
  1491. public function __clone()
  1492. {
  1493. $this->query = clone $this->query;
  1494. $this->request = clone $this->request;
  1495. $this->attributes = clone $this->attributes;
  1496. $this->cookies = clone $this->cookies;
  1497. $this->files = clone $this->files;
  1498. $this->server = clone $this->server;
  1499. $this->headers = clone $this->headers;
  1500. }
  1501. public function overrideGlobals()
  1502. {
  1503. $_GET = $this->query->all();
  1504. $_POST = $this->request->all();
  1505. $_SERVER = $this->server->all();
  1506. $_COOKIE = $this->cookies->all();
  1507. foreach ($this->headers->all() as $key => $value) {
  1508. $_SERVER['HTTP_'.strtoupper(str_replace('-', '_', $key))] = implode(', ', $value);
  1509. }
  1510. $_REQUEST = array_merge($_GET, $_POST);
  1511. }
  1512. public function get($key, $default = null)
  1513. {
  1514. return $this->query->get($key, $this->attributes->get($key, $this->request->get($key, $default)));
  1515. }
  1516. public function getSession()
  1517. {
  1518. return $this->session;
  1519. }
  1520. public function hasSession()
  1521. {
  1522. return $this->cookies->has(session_name());
  1523. }
  1524. public function setSession(Session $session)
  1525. {
  1526. $this->session = $session;
  1527. }
  1528. public function getClientIp($proxy = false)
  1529. {
  1530. if ($proxy) {
  1531. if ($this->server->has('HTTP_CLIENT_IP')) {
  1532. return $this->server->get('HTTP_CLIENT_IP');
  1533. } elseif ($this->server->has('HTTP_X_FORWARDED_FOR')) {
  1534. return $this->server->get('HTTP_X_FORWARDED_FOR');
  1535. }
  1536. }
  1537. return $this->server->get('REMOTE_ADDR');
  1538. }
  1539. public function getScriptName()
  1540. {
  1541. return $this->server->get('SCRIPT_NAME', $this->server->get('ORIG_SCRIPT_NAME', ''));
  1542. }
  1543. public function getPathInfo()
  1544. {
  1545. if (null === $this->pathInfo) {
  1546. $this->pathInfo = $this->preparePathInfo();
  1547. }
  1548. return $this->pathInfo;
  1549. }
  1550. public function getBasePath()
  1551. {
  1552. if (null === $this->basePath) {
  1553. $this->basePath = $this->prepareBasePath();
  1554. }
  1555. return $this->basePath;
  1556. }
  1557. public function getBaseUrl()
  1558. {
  1559. if (null === $this->baseUrl) {
  1560. $this->baseUrl = $this->prepareBaseUrl();
  1561. }
  1562. return $this->baseUrl;
  1563. }
  1564. public function getScheme()
  1565. {
  1566. return ($this->server->get('HTTPS') == 'on') ? 'https' : 'http';
  1567. }
  1568. public function getPort()
  1569. {
  1570. return $this->server->get('SERVER_PORT');
  1571. }
  1572. public function getHttpHost()
  1573. {
  1574. $host = $this->headers->get('HOST');
  1575. if (!empty($host)) {
  1576. return $host;
  1577. }
  1578. $scheme = $this->getScheme();
  1579. $name = $this->server->get('SERVER_NAME');
  1580. $port = $this->getPort();
  1581. if (('http' == $scheme && $port == 80) || ('https' == $scheme && $port == 443)) {
  1582. return $name;
  1583. } else {
  1584. return $name.':'.$port;
  1585. }
  1586. }
  1587. public function getRequestUri()
  1588. {
  1589. if (null === $this->requestUri) {
  1590. $this->requestUri = $this->prepareRequestUri();
  1591. }
  1592. return $this->requestUri;
  1593. }
  1594. public function getUri()
  1595. {
  1596. $qs = $this->getQueryString();
  1597. if (null !== $qs) {
  1598. $qs = '?'.$qs;
  1599. }
  1600. return $this->getScheme().'://'.$this->getHttpHost().$this->getBaseUrl().$this->getPathInfo().$qs;
  1601. }
  1602. public function getUriForPath($path)
  1603. {
  1604. return $this->getScheme().'://'.$this->getHttpHost().$this->getBaseUrl().$path;
  1605. }
  1606. public function getQueryString()
  1607. {
  1608. if (!$qs = $this->server->get('QUERY_STRING')) {
  1609. return null;
  1610. }
  1611. $parts = array();
  1612. $order = array();
  1613. foreach (explode('&', $qs) as $segment) {
  1614. if (false === strpos($segment, '=')) {
  1615. $parts[] = $segment;
  1616. $order[] = $segment;
  1617. } else {
  1618. $tmp = explode('=', urldecode($segment), 2);
  1619. $parts[] = urlencode($tmp[0]).'='.urlencode($tmp[1]);
  1620. $order[] = $tmp[0];
  1621. }
  1622. }
  1623. array_multisort($order, SORT_ASC, $parts);
  1624. return implode('&', $parts);
  1625. }
  1626. public function isSecure()
  1627. {
  1628. return (
  1629. (strtolower($this->server->get('HTTPS')) == 'on' || $this->server->get('HTTPS') == 1)
  1630. ||
  1631. (strtolower($this->headers->get('SSL_HTTPS')) == 'on' || $this->headers->get('SSL_HTTPS') == 1)
  1632. ||
  1633. (strtolower($this->headers->get('X_FORWARDED_PROTO')) == 'https')
  1634. );
  1635. }
  1636. public function getHost()
  1637. {
  1638. if ($host = $this->headers->get('X_FORWARDED_HOST')) {
  1639. $elements = explode(',', $host);
  1640. $host = trim($elements[count($elements) - 1]);
  1641. } else {
  1642. if (!$host = $this->headers->get('HOST')) {
  1643. if (!$host = $this->server->get('SERVER_NAME')) {
  1644. $host = $this->server->get('SERVER_ADDR', '');
  1645. }
  1646. }
  1647. }
  1648. $elements = explode(':', $host);
  1649. return trim($elements[0]);
  1650. }
  1651. public function setMethod($method)
  1652. {
  1653. $this->method = null;
  1654. $this->server->set('REQUEST_METHOD', $method);
  1655. }
  1656. public function getMethod()
  1657. {
  1658. if (null === $this->method) {
  1659. $this->method = strtoupper($this->server->get('REQUEST_METHOD', 'GET'));
  1660. if ('POST' === $this->method) {
  1661. $this->method = strtoupper($this->request->get('_method', 'POST'));
  1662. }
  1663. }
  1664. return $this->method;
  1665. }
  1666. public function getMimeType($format)
  1667. {
  1668. if (null === static::$formats) {
  1669. static::initializeFormats();
  1670. }
  1671. return isset(static::$formats[$format]) ? static::$formats[$format][0] : null;
  1672. }
  1673. public function getFormat($mimeType)
  1674. {
  1675. if (null === static::$formats) {
  1676. static::initializeFormats();
  1677. }
  1678. foreach (static::$formats as $format => $mimeTypes) {
  1679. if (in_array($mimeType, (array) $mimeTypes)) {
  1680. return $format;
  1681. }
  1682. }
  1683. return null;
  1684. }
  1685. public function setFormat($format, $mimeTypes)
  1686. {
  1687. if (null === static::$formats) {
  1688. static::initializeFormats();
  1689. }
  1690. static::$formats[$format] = is_array($mimeTypes) ? $mimeTypes : array($mimeTypes);
  1691. }
  1692. public function getRequestFormat()
  1693. {
  1694. if (null === $this->format) {
  1695. $this->format = $this->get('_format', 'html');
  1696. }
  1697. return $this->format;
  1698. }
  1699. public function setRequestFormat($format)
  1700. {
  1701. $this->format = $format;
  1702. }
  1703. public function isMethodSafe()
  1704. {
  1705. return in_array($this->getMethod(), array('GET', 'HEAD'));
  1706. }
  1707. public function getContent($asResource = false)
  1708. {
  1709. if (false === $this->content || (true === $asResource && null !== $this->content)) {
  1710. throw new \LogicException('getContent() can only be called once when using the resource return type.');
  1711. }
  1712. if (true === $asResource) {
  1713. $this->content = false;
  1714. return fopen('php://input', 'rb');
  1715. }
  1716. if (null === $this->content) {
  1717. $this->content = file_get_contents('php://input');
  1718. }
  1719. return $this->content;
  1720. }
  1721. public function getETags()
  1722. {
  1723. return preg_split('/\s*,\s*/', $this->headers->get('if_none_match'), null, PREG_SPLIT_NO_EMPTY);
  1724. }
  1725. public function isNoCache()
  1726. {
  1727. return $this->headers->hasCacheControlDirective('no-cache') || 'no-cache' == $this->headers->get('Pragma');
  1728. }
  1729. public function getPreferredLanguage(array $locales = null)
  1730. {
  1731. $preferredLanguages = $this->getLanguages();
  1732. if (null === $locales) {
  1733. return isset($preferredLanguages[0]) ? $preferredLanguages[0] : null;
  1734. }
  1735. if (!$preferredLanguages) {
  1736. return $locales[0];
  1737. }
  1738. $preferredLanguages = array_values(array_intersect($preferredLanguages, $locales));
  1739. return isset($preferredLanguages[0]) ? $preferredLanguages[0] : $locales[0];
  1740. }
  1741. public function getLanguages()
  1742. {
  1743. if (null !== $this->languages) {
  1744. return $this->languages;
  1745. }
  1746. $languages = $this->splitHttpAcceptHeader($this->headers->get('Accept-Language'));
  1747. foreach ($languages as $lang) {
  1748. if (strstr($lang, '-')) {
  1749. $codes = explode('-', $lang);
  1750. if ($codes[0] == 'i') {
  1751. if (count($codes) > 1) {
  1752. $lang = $codes[1];
  1753. }
  1754. } else {
  1755. for ($i = 0, $max = count($codes); $i < $max; $i++) {
  1756. if ($i == 0) {
  1757. $lang = strtolower($codes[0]);
  1758. } else {
  1759. $lang .= '_'.strtoupper($codes[$i]);
  1760. }
  1761. }
  1762. }
  1763. }
  1764. $this->languages[] = $lang;
  1765. }
  1766. return $this->languages;
  1767. }
  1768. public function getCharsets()
  1769. {
  1770. if (null !== $this->charsets) {
  1771. return $this->charsets;
  1772. }
  1773. return $this->charsets = $this->splitHttpAcceptHeader($this->headers->get('Accept-Charset'));
  1774. }
  1775. public function getAcceptableContentTypes()
  1776. {
  1777. if (null !== $this->acceptableContentTypes) {
  1778. return $this->acceptableContentTypes;
  1779. }
  1780. return $this->acceptableContentTypes = $this->splitHttpAcceptHeader($this->headers->get('Accept'));
  1781. }
  1782. public function isXmlHttpRequest()
  1783. {
  1784. return 'XMLHttpRequest' == $this->headers->get('X-Requested-With');
  1785. }
  1786. public function splitHttpAcceptHeader($header)
  1787. {
  1788. if (!$header) {
  1789. return array();
  1790. }
  1791. $values = array();
  1792. foreach (array_filter(explode(',', $header)) as $value) {
  1793. if ($pos = strpos($value, ';')) {
  1794. $q = (float) trim(substr($value, strpos($value, '=') + 1));
  1795. $value = trim(substr($value, 0, $pos));
  1796. } else {
  1797. $q = 1;
  1798. }
  1799. if (0 < $q) {
  1800. $values[trim($value)] = $q;
  1801. }
  1802. }
  1803. arsort($values);
  1804. return array_keys($values);
  1805. }
  1806. protected function prepareRequestUri()
  1807. {
  1808. $requestUri = '';
  1809. if ($this->headers->has('X_REWRITE_URL')) {
  1810. $requestUri = $this->headers->get('X_REWRITE_URL');
  1811. } elseif ($this->server->get('IIS_WasUrlRewritten') == '1' && $this->server->get('UNENCODED_URL') != '') {
  1812. $requestUri = $this->server->get('UNENCODED_URL');
  1813. } elseif ($this->server->has('REQUEST_URI')) {
  1814. $requestUri = $this->server->get('REQUEST_URI');
  1815. $schemeAndHttpHost = $this->getScheme().'://'.$this->getHttpHost();
  1816. if (strpos($requestUri, $schemeAndHttpHost) === 0) {
  1817. $requestUri = substr($requestUri, strlen($schemeAndHttpHost));
  1818. }
  1819. } elseif ($this->server->has('ORIG_PATH_INFO')) {
  1820. $requestUri = $this->server->get('ORIG_PATH_INFO');
  1821. if ($this->server->get('QUERY_STRING')) {
  1822. $requestUri .= '?'.$this->server->get('QUERY_STRING');
  1823. }
  1824. }
  1825. return $requestUri;
  1826. }
  1827. protected function prepareBaseUrl()
  1828. {
  1829. $filename = basename($this->server->get('SCRIPT_FILENAME'));
  1830. if (basename($this->server->get('SCRIPT_NAME')) === $filename) {
  1831. $baseUrl = $this->server->get('SCRIPT_NAME');
  1832. } elseif (basename($this->server->get('PHP_SELF')) === $filename) {
  1833. $baseUrl = $this->server->get('PHP_SELF');
  1834. } elseif (basename($this->server->get('ORIG_SCRIPT_NAME')) === $filename) {
  1835. $baseUrl = $this->server->get('ORIG_SCRIPT_NAME'); } else {
  1836. $path = $this->server->get('PHP_SELF', '');
  1837. $file = $this->server->get('SCRIPT_FILENAME', '');
  1838. $segs = explode('/', trim($file, '/'));
  1839. $segs = array_reverse($segs);
  1840. $index = 0;
  1841. $last = count($segs);
  1842. $baseUrl = '';
  1843. do {
  1844. $seg = $segs[$index];
  1845. $baseUrl = '/'.$seg.$baseUrl;
  1846. ++$index;
  1847. } while (($last > $index) && (false !== ($pos = strpos($path, $baseUrl))) && (0 != $pos));
  1848. }
  1849. $requestUri = $this->getRequestUri();
  1850. if ($baseUrl && 0 === strpos($requestUri, $baseUrl)) {
  1851. return $baseUrl;
  1852. }
  1853. if ($baseUrl && 0 === strpos($requestUri, dirname($baseUrl))) {
  1854. return rtrim(dirname($baseUrl), '/');
  1855. }
  1856. $truncatedRequestUri = $requestUri;
  1857. if (($pos = strpos($requestUri, '?')) !== false) {
  1858. $truncatedRequestUri = substr($requestUri, 0, $pos);
  1859. }
  1860. $basename = basename($baseUrl);
  1861. if (empty($basename) || !strpos($truncatedRequestUri, $basename)) {
  1862. return '';
  1863. }
  1864. if ((strlen($requestUri) >= strlen($baseUrl)) && ((false !== ($pos = strpos($requestUri, $baseUrl))) && ($pos !== 0))) {
  1865. $baseUrl = substr($requestUri, 0, $pos + strlen($baseUrl));
  1866. }
  1867. return rtrim($baseUrl, '/');
  1868. }
  1869. protected function prepareBasePath()
  1870. {
  1871. $filename = basename($this->server->get('SCRIPT_FILENAME'));
  1872. $baseUrl = $this->getBaseUrl();
  1873. if (empty($baseUrl)) {
  1874. return '';
  1875. }
  1876. if (basename($baseUrl) === $filename) {
  1877. $basePath = dirname($baseUrl);
  1878. } else {
  1879. $basePath = $baseUrl;
  1880. }
  1881. if ('\\' === DIRECTORY_SEPARATOR) {
  1882. $basePath = str_replace('\\', '/', $basePath);
  1883. }
  1884. return rtrim($basePath, '/');
  1885. }
  1886. protected function preparePathInfo()
  1887. {
  1888. $baseUrl = $this->getBaseUrl();
  1889. if (null === ($requestUri = $this->getRequestUri())) {
  1890. return '';
  1891. }
  1892. $pathInfo = '';
  1893. if ($pos = strpos($requestUri, '?')) {
  1894. $requestUri = substr($requestUri, 0, $pos);
  1895. }
  1896. if ((null !== $baseUrl) && (false === ($pathInfo = substr($requestUri, strlen($baseUrl))))) {
  1897. return '';
  1898. } elseif (null === $baseUrl) {
  1899. return $requestUri;
  1900. }
  1901. return (string) $pathInfo;
  1902. }
  1903. static protected function initializeFormats()
  1904. {
  1905. static::$formats = array(
  1906. 'txt' => array('text/plain'),
  1907. 'js' => array('application/javascript', 'application/x-javascript', 'text/javascript'),
  1908. 'css' => array('text/css'),
  1909. 'json' => array('application/json', 'application/x-json'),
  1910. 'xml' => array('text/xml', 'application/xml', 'application/x-xml'),
  1911. 'rdf' => array('application/rdf+xml'),
  1912. 'atom' => array('application/atom+xml'),
  1913. );
  1914. }
  1915. }
  1916. }
  1917. namespace Symfony\Component\HttpFoundation
  1918. {
  1919. class ApacheRequest extends Request
  1920. {
  1921. protected function prepareRequestUri()
  1922. {
  1923. return $this->server->get('REQUEST_URI');
  1924. }
  1925. protected function prepareBaseUrl()
  1926. {
  1927. return $this->server->get('SCRIPT_NAME');
  1928. }
  1929. protected function preparePathInfo()
  1930. {
  1931. return $this->server->get('PATH_INFO');
  1932. }
  1933. }
  1934. }
  1935. namespace Symfony\Component\HttpFoundation
  1936. {
  1937. class ResponseHeaderBag extends HeaderBag
  1938. {
  1939. protected $computedCacheControl = array();
  1940. public function __construct(array $headers = array())
  1941. {
  1942. parent::__construct($headers);
  1943. if (!isset($this->headers['cache-control'])) {
  1944. $this->set('cache-control', '');
  1945. }
  1946. }
  1947. public function replace(array $headers = array())
  1948. {
  1949. parent::replace($headers);
  1950. if (!isset($this->headers['cache-control'])) {
  1951. $this->set('cache-control', '');
  1952. }
  1953. }
  1954. public function set($key, $values, $replace = true)
  1955. {
  1956. parent::set($key, $values, $replace);
  1957. if ('cache-control' === strtr(strtolower($key), '_', '-')) {
  1958. $computed = $this->computeCacheControlValue();
  1959. $this->headers['cache-control'] = array($computed);
  1960. $this->computedCacheControl = $this->parseCacheControl($computed);
  1961. }
  1962. }
  1963. public function remove($key)
  1964. {
  1965. parent::remove($key);
  1966. if ('cache-control' === strtr(strtolower($key), '_', '-')) {
  1967. $this->computedCacheControl = array();
  1968. }
  1969. }
  1970. public function hasCacheControlDirective($key)
  1971. {
  1972. return array_key_exists($key, $this->computedCacheControl);
  1973. }
  1974. public function getCacheControlDirective($key)
  1975. {
  1976. return array_key_exists($key, $this->computedCacheControl) ? $this->computedCacheControl[$key] : null;
  1977. }
  1978. public function clearCookie($name, $path = null, $domain = null)
  1979. {
  1980. $this->setCookie(new Cookie($name, null, 1, $path, $domain));
  1981. }
  1982. protected function computeCacheControlValue()
  1983. {
  1984. if (!$this->cacheControl && !$this->has('ETag') && !$this->has('Last-Modified') && !$this->has('Expires')) {
  1985. return 'no-cache';
  1986. }
  1987. if (!$this->cacheControl) {
  1988. return 'private, must-revalidate';
  1989. }
  1990. $header = $this->getCacheControlHeader();
  1991. if (isset($this->cacheControl['public']) || isset($this->cacheControl['private'])) {
  1992. return $header;
  1993. }
  1994. if (!isset($this->cacheControl['s-maxage'])) {
  1995. return $header.', private';
  1996. }
  1997. return $header;
  1998. }
  1999. }}
  2000. namespace Symfony\Component\HttpFoundation
  2001. {
  2002. class Response
  2003. {
  2004. public $headers;
  2005. protected $content;
  2006. protected $version;
  2007. protected $statusCode;
  2008. protected $statusText;
  2009. protected $charset;
  2010. static public $statusTexts = array(
  2011. 100 => 'Continue',
  2012. 101 => 'Switching Protocols',
  2013. 200 => 'OK',
  2014. 201 => 'Created',
  2015. 202 => 'Accepted',
  2016. 203 => 'Non-Authoritative Information',
  2017. 204 => 'No Content',
  2018. 205 => 'Reset Content',
  2019. 206 => 'Partial Content',
  2020. 300 => 'Multiple Choices',
  2021. 301 => 'Moved Permanently',
  2022. 302 => 'Found',
  2023. 303 => 'See Other',
  2024. 304 => 'Not Modified',
  2025. 305 => 'Use Proxy',
  2026. 307 => 'Temporary Redirect',
  2027. 400 => 'Bad Request',
  2028. 401 => 'Unauthorized',
  2029. 402 => 'Payment Required',
  2030. 403 => 'Forbidden',
  2031. 404 => 'Not Found',
  2032. 405 => 'Method Not Allowed',
  2033. 406 => 'Not Acceptable',
  2034. 407 => 'Proxy Authentication Required',
  2035. 408 => 'Request Timeout',
  2036. 409 => 'Conflict',
  2037. 410 => 'Gone',
  2038. 411 => 'Length Required',
  2039. 412 => 'Precondition Failed',
  2040. 413 => 'Request Entity Too Large',
  2041. 414 => 'Request-URI Too Long',
  2042. 415 => 'Unsupported Media Type',
  2043. 416 => 'Requested Range Not Satisfiable',
  2044. 417 => 'Expectation Failed',
  2045. 418 => 'I\'m a teapot',
  2046. 500 => 'Internal Server Error',
  2047. 501 => 'Not Implemented',
  2048. 502 => 'Bad Gateway',
  2049. 503 => 'Service Unavailable',
  2050. 504 => 'Gateway Timeout',
  2051. 505 => 'HTTP Version Not Supported',
  2052. );
  2053. public function __construct($content = '', $status = 200, $headers = array())
  2054. {
  2055. $this->setContent($content);
  2056. $this->setStatusCode($status);
  2057. $this->setProtocolVersion('1.0');
  2058. $this->headers = new ResponseHeaderBag($headers);
  2059. }
  2060. public function __toString()
  2061. {
  2062. $content = '';
  2063. if (!$this->headers->has('Content-Type')) {
  2064. $this->headers->set('Content-Type', 'text/html; charset='.(null === $this->charset ? 'UTF-8' : $this->charset));
  2065. }
  2066. $content .= sprintf('HTTP/%s %s %s', $this->version, $this->statusCode, $this->statusText)."\n";
  2067. foreach ($this->headers->all() as $name => $values) {
  2068. foreach ($values as $value) {
  2069. $content .= "$name: $value\n";
  2070. }
  2071. }
  2072. $content .= "\n".$this->getContent();
  2073. return $content;
  2074. }
  2075. public function __clone()
  2076. {
  2077. $this->headers = clone $this->headers;
  2078. }
  2079. public function sendHeaders()
  2080. {
  2081. if (!$this->headers->has('Content-Type')) {
  2082. $this->headers->set('Content-Type', 'text/html; charset='.(null === $this->charset ? 'UTF-8' : $this->charset));
  2083. }
  2084. header(sprintf('HTTP/%s %s %s', $this->version, $this->statusCode, $this->statusText));
  2085. foreach ($this->headers->all() as $name => $values) {
  2086. foreach ($values as $value) {
  2087. header($name.': '.$value);
  2088. }
  2089. }
  2090. foreach ($this->headers->getCookies() as $cookie) {
  2091. setcookie($cookie->getName(), $cookie->getValue(), $cookie->getExpire(), $cookie->getPath(), $cookie->getDomain(), $cookie->isSecure(), $cookie->isHttpOnly());
  2092. }
  2093. }
  2094. public function sendContent()
  2095. {
  2096. echo $this->content;
  2097. }
  2098. public function send()
  2099. {
  2100. $this->sendHeaders();
  2101. $this->sendContent();
  2102. }
  2103. public function setContent($content)
  2104. {
  2105. $this->content = $content;
  2106. }
  2107. public function getContent()
  2108. {
  2109. return $this->content;
  2110. }
  2111. public function setProtocolVersion($version)
  2112. {
  2113. $this->version = $version;
  2114. }
  2115. public function getProtocolVersion()
  2116. {
  2117. return $this->version;
  2118. }
  2119. public function setStatusCode($code, $text = null)
  2120. {
  2121. $this->statusCode = (int) $code;
  2122. if ($this->statusCode < 100 || $this->statusCode > 599) {
  2123. throw new \InvalidArgumentException(sprintf('The HTTP status code "%s" is not valid.', $code));
  2124. }
  2125. $this->statusText = false === $text ? '' : (null === $text ? self::$statusTexts[$this->statusCode] : $text);
  2126. }
  2127. public function getStatusCode()
  2128. {
  2129. return $this->statusCode;
  2130. }
  2131. public function setCharset($charset)
  2132. {
  2133. $this->charset = $charset;
  2134. }
  2135. public function getCharset()
  2136. {
  2137. return $this->charset;
  2138. }
  2139. public function isCacheable()
  2140. {
  2141. if (!in_array($this->statusCode, array(200, 203, 300, 301, 302, 404, 410))) {
  2142. return false;
  2143. }
  2144. if ($this->headers->hasCacheControlDirective('no-store') || $this->headers->getCacheControlDirective('private')) {
  2145. return false;
  2146. }
  2147. return $this->isValidateable() || $this->isFresh();
  2148. }
  2149. public function isFresh()
  2150. {
  2151. return $this->getTtl() > 0;
  2152. }
  2153. public function isValidateable()
  2154. {
  2155. return $this->headers->has('Last-Modified') || $this->headers->has('ETag');
  2156. }
  2157. public function setPrivate()
  2158. {
  2159. $this->headers->removeCacheControlDirective('public');
  2160. $this->headers->addCacheControlDirective('private');
  2161. }
  2162. public function setPublic()
  2163. {
  2164. $this->headers->addCacheControlDirective('public');
  2165. $this->headers->removeCacheControlDirective('private');
  2166. }
  2167. public function mustRevalidate()
  2168. {
  2169. return $this->headers->hasCacheControlDirective('must-revalidate') || $this->headers->has('must-proxy-revalidate');
  2170. }
  2171. public function getDate()
  2172. {
  2173. if (null === $date = $this->headers->getDate('Date')) {
  2174. $date = new \DateTime(null, new \DateTimeZone('UTC'));
  2175. $this->headers->set('Date', $date->format('D, d M Y H:i:s').' GMT');
  2176. }
  2177. return $date;
  2178. }
  2179. public function getAge()
  2180. {
  2181. if ($age = $this->headers->get('Age')) {
  2182. return $age;
  2183. }
  2184. return max(time() - $this->getDate()->format('U'), 0);
  2185. }
  2186. public function expire()
  2187. {
  2188. if ($this->isFresh()) {
  2189. $this->headers->set('Age', $this->getMaxAge());
  2190. }
  2191. }
  2192. public function getExpires()
  2193. {
  2194. return $this->headers->getDate('Expires');
  2195. }
  2196. public function setExpires(\DateTime $date = null)
  2197. {
  2198. if (null === $date) {
  2199. $this->headers->remove('Expires');
  2200. } else {
  2201. $date = clone $date;
  2202. $date->setTimezone(new \DateTimeZone('UTC'));
  2203. $this->headers->set('Expires', $date->format('D, d M Y H:i:s').' GMT');
  2204. }
  2205. }
  2206. public function getMaxAge()
  2207. {
  2208. if ($age = $this->headers->getCacheControlDirective('s-maxage')) {
  2209. return $age;
  2210. }
  2211. if ($age = $this->headers->getCacheControlDirective('max-age')) {
  2212. return $age;
  2213. }
  2214. if (null !== $this->getExpires()) {
  2215. return $this->getExpires()->format('U') - $this->getDate()->format('U');
  2216. }
  2217. return null;
  2218. }
  2219. public function setMaxAge($value)
  2220. {
  2221. $this->headers->addCacheControlDirective('max-age', $value);
  2222. }
  2223. public function setSharedMaxAge($value)
  2224. {
  2225. $this->headers->addCacheControlDirective('s-maxage', $value);
  2226. }
  2227. public function getTtl()
  2228. {
  2229. if ($maxAge = $this->getMaxAge()) {
  2230. return $maxAge - $this->getAge();
  2231. }
  2232. return null;
  2233. }
  2234. public function setTtl($seconds)
  2235. {
  2236. $this->setSharedMaxAge($this->getAge() + $seconds);
  2237. }
  2238. public function setClientTtl($seconds)
  2239. {
  2240. $this->setMaxAge($this->getAge() + $seconds);
  2241. }
  2242. public function getLastModified()
  2243. {
  2244. return $this->headers->getDate('LastModified');
  2245. }
  2246. public function setLastModified(\DateTime $date = null)
  2247. {
  2248. if (null === $date) {
  2249. $this->headers->remove('Last-Modified');
  2250. } else {
  2251. $date = clone $date;
  2252. $date->setTimezone(new \DateTimeZone('UTC'));
  2253. $this->headers->set('Last-Modified', $date->format('D, d M Y H:i:s').' GMT');
  2254. }
  2255. }
  2256. public function getEtag()
  2257. {
  2258. return $this->headers->get('ETag');
  2259. }
  2260. public function setEtag($etag = null, $weak = false)
  2261. {
  2262. if (null === $etag) {
  2263. $this->headers->remove('Etag');
  2264. } else {
  2265. if (0 !== strpos($etag, '"')) {
  2266. $etag = '"'.$etag.'"';
  2267. }
  2268. $this->headers->set('ETag', (true === $weak ? 'W/' : '').$etag);
  2269. }
  2270. }
  2271. public function setCache(array $options)
  2272. {
  2273. if ($diff = array_diff(array_keys($options), array('etag', 'last_modified', 'max_age', 's_maxage', 'private', 'public'))) {
  2274. throw new \InvalidArgumentException(sprintf('Response does not support the following options: "%s".', implode('", "', array_keys($diff))));
  2275. }
  2276. if (isset($options['etag'])) {
  2277. $this->setEtag($options['etag']);
  2278. }
  2279. if (isset($options['last_modified'])) {
  2280. $this->setLastModified($options['last_modified']);
  2281. }
  2282. if (isset($options['max_age'])) {
  2283. $this->setMaxAge($options['max_age']);
  2284. }
  2285. if (isset($options['s_maxage'])) {
  2286. $this->setSharedMaxAge($options['s_maxage']);
  2287. }
  2288. if (isset($options['public'])) {
  2289. if ($options['public']) {
  2290. $this->setPublic();
  2291. } else {
  2292. $this->setPrivate();
  2293. }
  2294. }
  2295. if (isset($options['private'])) {
  2296. if ($options['private']) {
  2297. $this->setPrivate();
  2298. } else {
  2299. $this->setPublic();
  2300. }
  2301. }
  2302. }
  2303. public function setNotModified()
  2304. {
  2305. $this->setStatusCode(304);
  2306. $this->setContent(null);
  2307. foreach (array('Allow', 'Content-Encoding', 'Content-Language', 'Content-Length', 'Content-MD5', 'Content-Type', 'Last-Modified') as $header) {
  2308. $this->headers->remove($header);
  2309. }
  2310. }
  2311. public function hasVary()
  2312. {
  2313. return (Boolean) $this->headers->get('Vary');
  2314. }
  2315. public function getVary()
  2316. {
  2317. if (!$vary = $this->headers->get('Vary')) {
  2318. return array();
  2319. }
  2320. return is_array($vary) ? $vary : preg_split('/[\s,]+/', $vary);
  2321. }
  2322. public function setVary($headers, $replace = true)
  2323. {
  2324. $this->headers->set('Vary', $headers, $replace);
  2325. }
  2326. public function isNotModified(Request $request)
  2327. {
  2328. $lastModified = $request->headers->get('If-Modified-Since');
  2329. $notModified = false;
  2330. if ($etags = $request->getEtags()) {
  2331. $notModified = (in_array($this->getEtag(), $etags) || in_array('*', $etags)) && (!$lastModified || $this->headers->get('Last-Modified') == $lastModified);
  2332. } elseif ($lastModified) {
  2333. $notModified = $lastModified == $this->headers->get('Last-Modified');
  2334. }
  2335. if ($notModified) {
  2336. $this->setNotModified();
  2337. }
  2338. return $notModified;
  2339. }
  2340. public function isInvalid()
  2341. {
  2342. return $this->statusCode < 100 || $this->statusCode >= 600;
  2343. }
  2344. public function isInformational()
  2345. {
  2346. return $this->statusCode >= 100 && $this->statusCode < 200;
  2347. }
  2348. public function isSuccessful()
  2349. {
  2350. return $this->statusCode >= 200 && $this->statusCode < 300;
  2351. }
  2352. public function isRedirection()
  2353. {
  2354. return $this->statusCode >= 300 && $this->statusCode < 400;
  2355. }
  2356. public function isClientError()
  2357. {
  2358. return $this->statusCode >= 400 && $this->statusCode < 500;
  2359. }
  2360. public function isServerError()
  2361. {
  2362. return $this->statusCode >= 500 && $this->statusCode < 600;
  2363. }
  2364. public function isOk()
  2365. {
  2366. return 200 === $this->statusCode;
  2367. }
  2368. public function isForbidden()
  2369. {
  2370. return 403 === $this->statusCode;
  2371. }
  2372. public function isNotFound()
  2373. {
  2374. return 404 === $this->statusCode;
  2375. }
  2376. public function isRedirect()
  2377. {
  2378. return in_array($this->statusCode, array(301, 302, 303, 307));
  2379. }
  2380. public function isEmpty()
  2381. {
  2382. return in_array($this->statusCode, array(201, 204, 304));
  2383. }
  2384. public function isRedirected($location)
  2385. {
  2386. return $this->isRedirect() && $location == $this->headers->get('Location');
  2387. }
  2388. }
  2389. }
  2390. namespace Symfony\Component\ClassLoader
  2391. {
  2392. class UniversalClassLoader
  2393. {
  2394. protected $namespaces = array();
  2395. protected $prefixes = array();
  2396. protected $namespaceFallback = array();
  2397. protected $prefixFallback = array();
  2398. public function getNamespaces()
  2399. {
  2400. return $this->namespaces;
  2401. }
  2402. public function getPrefixes()
  2403. {
  2404. return $this->prefixes;
  2405. }
  2406. public function getNamespaceFallback()
  2407. {
  2408. return $this->namespaceFallback;
  2409. }
  2410. public function getPrefixFallback()
  2411. {
  2412. return $this->prefixFallback;
  2413. }
  2414. public function registerNamespaceFallback($dirs)
  2415. {
  2416. $this->namespaceFallback = (array) $dirs;
  2417. }
  2418. public function registerPrefixFallback($dirs)
  2419. {
  2420. $this->prefixFallback = (array) $dirs;
  2421. }
  2422. public function registerNamespaces(array $namespaces)
  2423. {
  2424. foreach ($namespaces as $namespace => $locations) {
  2425. $this->namespaces[$namespace] = (array) $locations;
  2426. }
  2427. }
  2428. public function registerNamespace($namespace, $paths)
  2429. {
  2430. $this->namespaces[$namespace] = (array) $paths;
  2431. }
  2432. public function registerPrefixes(array $classes)
  2433. {
  2434. foreach ($classes as $prefix => $locations) {
  2435. $this->prefixes[$prefix] = (array) $locations;
  2436. }
  2437. }
  2438. public function registerPrefix($prefix, $paths)
  2439. {
  2440. $this->prefixes[$prefix] = (array) $paths;
  2441. }
  2442. public function register($prepend = false)
  2443. {
  2444. spl_autoload_register(array($this, 'loadClass'), true, $prepend);
  2445. }
  2446. public function loadClass($class)
  2447. {
  2448. $class = ltrim($class, '\\');
  2449. if (false !== ($pos = strrpos($class, '\\'))) {
  2450. $namespace = substr($class, 0, $pos);
  2451. foreach ($this->namespaces as $ns => $dirs) {
  2452. foreach ($dirs as $dir) {
  2453. if (0 === strpos($namespace, $ns)) {
  2454. $className = substr($class, $pos + 1);
  2455. $file = $dir.DIRECTORY_SEPARATOR.str_replace('\\', DIRECTORY_SEPARATOR, $namespace).DIRECTORY_SEPARATOR.str_replace('_', DIRECTORY_SEPARATOR, $className).'.php';
  2456. if (file_exists($file)) {
  2457. require $file;
  2458. return;
  2459. }
  2460. }
  2461. }
  2462. }
  2463. foreach ($this->namespaceFallback as $dir) {
  2464. $file = $dir.DIRECTORY_SEPARATOR.str_replace('\\', DIRECTORY_SEPARATOR, $class).'.php';
  2465. if (file_exists($file)) {
  2466. require $file;
  2467. return;
  2468. }
  2469. }
  2470. } else {
  2471. foreach ($this->prefixes as $prefix => $dirs) {
  2472. foreach ($dirs as $dir) {
  2473. if (0 === strpos($class, $prefix)) {
  2474. $file = $dir.DIRECTORY_SEPARATOR.str_replace('_', DIRECTORY_SEPARATOR, $class).'.php';
  2475. if (file_exists($file)) {
  2476. require $file;
  2477. return;
  2478. }
  2479. }
  2480. }
  2481. }
  2482. foreach ($this->prefixFallback as $dir) {
  2483. $file = $dir.DIRECTORY_SEPARATOR.str_replace('_', DIRECTORY_SEPARATOR, $class).'.php';
  2484. if (file_exists($file)) {
  2485. require $file;
  2486. return;
  2487. }
  2488. }
  2489. }
  2490. }
  2491. }
  2492. }