PageRenderTime 61ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/vendor/symfony/src/Symfony/Component/HttpKernel/bootstrap_cache.php

https://github.com/casoetan/ServerGroveLiveChat
PHP | 2484 lines | 2484 code | 0 blank | 0 comment | 227 complexity | 1930940b3e76a2316b0e82b015a8c584 MD5 | raw file
Possible License(s): LGPL-2.1, LGPL-3.0, ISC, BSD-3-Clause
  1. <?php
  2. namespace Symfony\Component\HttpKernel
  3. {
  4. use Symfony\Component\DependencyInjection\ContainerInterface;
  5. use Symfony\Component\DependencyInjection\Loader\LoaderInterface;
  6. use Symfony\Component\HttpKernel\HttpKernelInterface;
  7. use Symfony\Component\HttpKernel\Bundle\BundleInterface;
  8. interface KernelInterface extends HttpKernelInterface, \Serializable
  9. {
  10. function registerRootDir();
  11. function registerBundles();
  12. function registerContainerConfiguration(LoaderInterface $loader);
  13. function boot();
  14. function shutdown();
  15. function getBundles();
  16. function isClassInActiveBundle($class);
  17. function getBundle($name, $first = true);
  18. function locateResource($name, $dir = null, $first = true);
  19. function getName();
  20. function getEnvironment();
  21. function isDebug();
  22. function getRootDir();
  23. function getContainer();
  24. function getStartTime();
  25. function getCacheDir();
  26. function getLogDir();
  27. }
  28. }
  29. namespace Symfony\Component\HttpKernel
  30. {
  31. use Symfony\Component\DependencyInjection\ContainerInterface;
  32. use Symfony\Component\DependencyInjection\ContainerBuilder;
  33. use Symfony\Component\DependencyInjection\Dumper\PhpDumper;
  34. use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
  35. use Symfony\Component\DependencyInjection\Loader\DelegatingLoader;
  36. use Symfony\Component\DependencyInjection\Loader\LoaderResolver;
  37. use Symfony\Component\DependencyInjection\Loader\LoaderInterface;
  38. use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
  39. use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
  40. use Symfony\Component\DependencyInjection\Loader\IniFileLoader;
  41. use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
  42. use Symfony\Component\DependencyInjection\Loader\ClosureLoader;
  43. use Symfony\Component\HttpFoundation\Request;
  44. use Symfony\Component\HttpKernel\HttpKernelInterface;
  45. use Symfony\Component\HttpKernel\Bundle\BundleInterface;
  46. abstract class Kernel implements KernelInterface
  47. {
  48. protected $bundles;
  49. protected $bundleMap;
  50. protected $container;
  51. protected $rootDir;
  52. protected $environment;
  53. protected $debug;
  54. protected $booted;
  55. protected $name;
  56. protected $startTime;
  57. const VERSION = '2.0.0-DEV';
  58. public function __construct($environment, $debug)
  59. {
  60. $this->environment = $environment;
  61. $this->debug = (Boolean) $debug;
  62. $this->booted = false;
  63. $this->rootDir = realpath($this->registerRootDir());
  64. $this->name = preg_replace('/[^a-zA-Z0-9_]+/', '', basename($this->rootDir));
  65. if ($this->debug) {
  66. ini_set('display_errors', 1);
  67. error_reporting(-1);
  68. $this->startTime = microtime(true);
  69. } else {
  70. ini_set('display_errors', 0);
  71. }
  72. }
  73. public function __clone()
  74. {
  75. if ($this->debug) {
  76. $this->startTime = microtime(true);
  77. }
  78. $this->booted = false;
  79. $this->container = null;
  80. }
  81. public function boot()
  82. {
  83. if (true === $this->booted) {
  84. return;
  85. }
  86. $this->initializeBundles();
  87. $this->initializeContainer();
  88. foreach ($this->bundles as $bundle) {
  89. $bundle->setContainer($this->container);
  90. $bundle->boot();
  91. }
  92. $this->booted = true;
  93. }
  94. public function shutdown()
  95. {
  96. $this->booted = false;
  97. foreach ($this->bundles as $bundle) {
  98. $bundle->shutdown();
  99. $bundle->setContainer(null);
  100. }
  101. $this->container = null;
  102. }
  103. public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
  104. {
  105. if (false === $this->booted) {
  106. $this->boot();
  107. }
  108. return $this->container->get('http_kernel')->handle($request, $type, $catch);
  109. }
  110. public function getBundles()
  111. {
  112. return $this->bundles;
  113. }
  114. public function isClassInActiveBundle($class)
  115. {
  116. foreach ($this->bundles as $bundle) {
  117. $bundleClass = get_class($bundle);
  118. if (0 === strpos($class, substr($bundleClass, 0, strrpos($bundleClass, '\\')))) {
  119. return true;
  120. }
  121. }
  122. return false;
  123. }
  124. public function getBundle($name, $first = true)
  125. {
  126. if (!isset($this->bundleMap[$name])) {
  127. throw new \InvalidArgumentException(sprintf('Bundle "%s" does not exist or it is not enabled.', $name));
  128. }
  129. if (true === $first) {
  130. return $this->bundleMap[$name][0];
  131. } elseif (false === $first) {
  132. return $this->bundleMap[$name];
  133. }
  134. }
  135. public function locateResource($name, $dir = null, $first = true)
  136. {
  137. if ('@' !== $name[0]) {
  138. throw new \InvalidArgumentException(sprintf('A resource name must start with @ ("%s" given).', $name));
  139. }
  140. if (false !== strpos($name, '..')) {
  141. throw new \RuntimeException(sprintf('File name "%s" contains invalid characters (..).', $name));
  142. }
  143. $name = substr($name, 1);
  144. list($bundle, $path) = explode('/', $name, 2);
  145. $isResource = 0 === strpos($path, 'Resources');
  146. $files = array();
  147. if (true === $isResource && null !== $dir && file_exists($file = $dir.'/'.$bundle.'/'.substr($path, 10))) {
  148. if ($first) {
  149. return $file;
  150. }
  151. $files[] = $file;
  152. }
  153. foreach ($this->getBundle($bundle, false) as $bundle) {
  154. if (file_exists($file = $bundle->getNormalizedPath().'/'.$path)) {
  155. if ($first) {
  156. return $file;
  157. }
  158. $files[] = $file;
  159. }
  160. }
  161. if ($files) {
  162. return $files;
  163. }
  164. throw new \InvalidArgumentException(sprintf('Unable to find file "@%s".', $name));
  165. }
  166. public function getName()
  167. {
  168. return $this->name;
  169. }
  170. public function getEnvironment()
  171. {
  172. return $this->environment;
  173. }
  174. public function isDebug()
  175. {
  176. return $this->debug;
  177. }
  178. public function getRootDir()
  179. {
  180. return $this->rootDir;
  181. }
  182. public function getContainer()
  183. {
  184. return $this->container;
  185. }
  186. public function getStartTime()
  187. {
  188. return $this->debug ? $this->startTime : -INF;
  189. }
  190. public function getCacheDir()
  191. {
  192. return $this->rootDir.'/cache/'.$this->environment;
  193. }
  194. public function getLogDir()
  195. {
  196. return $this->rootDir.'/logs';
  197. }
  198. protected function initializeBundles()
  199. {
  200. $this->bundles = array();
  201. $topMostBundles = array();
  202. $directChildren = array();
  203. foreach ($this->registerBundles() as $bundle) {
  204. $name = $bundle->getName();
  205. if (isset($this->bundles[$name])) {
  206. throw new \LogicException(sprintf('Trying to register two bundles with the same name "%s"', $name));
  207. }
  208. $this->bundles[$name] = $bundle;
  209. if ($parentName = $bundle->getParent()) {
  210. if (isset($directChildren[$parentName])) {
  211. throw new \LogicException(sprintf('Bundle "%s" is directly extended by two bundles "%s" and "%s".', $parentName, $name, $directChildren[$parentName]));
  212. }
  213. $directChildren[$parentName] = $name;
  214. } else {
  215. $topMostBundles[$name] = $bundle;
  216. }
  217. }
  218. if (count($diff = array_diff(array_keys($directChildren), array_keys($this->bundles)))) {
  219. throw new \LogicException(sprintf('Bundle "%s" extends bundle "%s", which is not registered.', $directChildren[$diff[0]], $diff[0]));
  220. }
  221. $this->bundleMap = array();
  222. foreach ($topMostBundles as $name => $bundle) {
  223. $bundleMap = array($bundle);
  224. $hierarchy = array($name);
  225. while (isset($directChildren[$name])) {
  226. $name = $directChildren[$name];
  227. array_unshift($bundleMap, $this->bundles[$name]);
  228. $hierarchy[] = $name;
  229. }
  230. foreach ($hierarchy as $bundle) {
  231. $this->bundleMap[$bundle] = $bundleMap;
  232. array_pop($bundleMap);
  233. }
  234. }
  235. }
  236. protected function initializeContainer()
  237. {
  238. $class = $this->name.ucfirst($this->environment).($this->debug ? 'Debug' : '').'ProjectContainer';
  239. $location = $this->getCacheDir().'/'.$class;
  240. $reload = $this->debug ? $this->needsReload($class, $location) : false;
  241. $fresh = false;
  242. if ($reload || !file_exists($location.'.php')) {
  243. $container = $this->buildContainer();
  244. $this->dumpContainer($container, $class, $location.'.php');
  245. $fresh = true;
  246. }
  247. require_once $location.'.php';
  248. $this->container = new $class();
  249. $this->container->set('kernel', $this);
  250. if ($fresh && 'cli' !== php_sapi_name()) {
  251. $this->container->get('cache_warmer')->warmUp($this->container->getParameter('kernel.cache_dir'));
  252. }
  253. }
  254. protected function getKernelParameters()
  255. {
  256. $bundles = array();
  257. foreach ($this->bundles as $name => $bundle) {
  258. $bundles[$name] = get_class($bundle);
  259. }
  260. return array_merge(
  261. array(
  262. 'kernel.root_dir' => $this->rootDir,
  263. 'kernel.environment' => $this->environment,
  264. 'kernel.debug' => $this->debug,
  265. 'kernel.name' => $this->name,
  266. 'kernel.cache_dir' => $this->getCacheDir(),
  267. 'kernel.logs_dir' => $this->getLogDir(),
  268. 'kernel.bundles' => $bundles,
  269. 'kernel.charset' => 'UTF-8',
  270. ),
  271. $this->getEnvParameters()
  272. );
  273. }
  274. protected function getEnvParameters()
  275. {
  276. $parameters = array();
  277. foreach ($_SERVER as $key => $value) {
  278. if ('SYMFONY__' === substr($key, 0, 9)) {
  279. $parameters[strtolower(str_replace('__', '.', substr($key, 9)))] = $value;
  280. }
  281. }
  282. return $parameters;
  283. }
  284. protected function needsReload($class, $location)
  285. {
  286. if (!file_exists($location.'.meta') || !file_exists($location.'.php')) {
  287. return true;
  288. }
  289. $meta = unserialize(file_get_contents($location.'.meta'));
  290. $time = filemtime($location.'.php');
  291. foreach ($meta as $resource) {
  292. if (!$resource->isUptodate($time)) {
  293. return true;
  294. }
  295. }
  296. return false;
  297. }
  298. protected function buildContainer()
  299. {
  300. $parameterBag = new ParameterBag($this->getKernelParameters());
  301. $container = new ContainerBuilder($parameterBag);
  302. foreach ($this->bundles as $bundle) {
  303. $bundle->registerExtensions($container);
  304. if ($this->debug) {
  305. $container->addObjectResource($bundle);
  306. }
  307. }
  308. if (null !== $cont = $this->registerContainerConfiguration($this->getContainerLoader($container))) {
  309. $container->merge($cont);
  310. }
  311. $container->compile();
  312. return $container;
  313. }
  314. protected function dumpContainer(ContainerBuilder $container, $class, $file)
  315. {
  316. foreach (array('cache', 'logs') as $name) {
  317. $dir = $container->getParameter(sprintf('kernel.%s_dir', $name));
  318. if (!is_dir($dir)) {
  319. if (false === @mkdir($dir, 0777, true)) {
  320. die(sprintf('Unable to create the %s directory (%s)', $name, dirname($dir)));
  321. }
  322. } elseif (!is_writable($dir)) {
  323. die(sprintf('Unable to write in the %s directory (%s)', $name, $dir));
  324. }
  325. }
  326. $dumper = new PhpDumper($container);
  327. $content = $dumper->dump(array('class' => $class));
  328. if (!$this->debug) {
  329. $content = self::stripComments($content);
  330. }
  331. $this->writeCacheFile($file, $content);
  332. if ($this->debug) {
  333. $container->addObjectResource($this);
  334. $this->writeCacheFile($this->getCacheDir().'/'.$class.'.meta', serialize($container->getResources()));
  335. }
  336. }
  337. protected function getContainerLoader(ContainerInterface $container)
  338. {
  339. $resolver = new LoaderResolver(array(
  340. new XmlFileLoader($container),
  341. new YamlFileLoader($container),
  342. new IniFileLoader($container),
  343. new PhpFileLoader($container),
  344. new ClosureLoader($container),
  345. ));
  346. return new DelegatingLoader($resolver);
  347. }
  348. static public function stripComments($source)
  349. {
  350. if (!function_exists('token_get_all')) {
  351. return $source;
  352. }
  353. $output = '';
  354. foreach (token_get_all($source) as $token) {
  355. if (is_string($token)) {
  356. $output .= $token;
  357. } elseif (!in_array($token[0], array(T_COMMENT, T_DOC_COMMENT))) {
  358. $output .= $token[1];
  359. }
  360. }
  361. $output = preg_replace(array('/\s+$/Sm', '/\n+/S'), "\n", $output);
  362. return $output;
  363. }
  364. protected function writeCacheFile($file, $content)
  365. {
  366. $tmpFile = tempnam(dirname($file), basename($file));
  367. if (false !== @file_put_contents($tmpFile, $content) && @rename($tmpFile, $file)) {
  368. chmod($file, 0644);
  369. return;
  370. }
  371. throw new \RuntimeException(sprintf('Failed to write cache file "%s".', $file));
  372. }
  373. public function serialize()
  374. {
  375. return serialize(array($this->environment, $this->debug));
  376. }
  377. public function unserialize($data)
  378. {
  379. list($environment, $debug) = unserialize($data);
  380. $this->__construct($environment, $debug);
  381. }
  382. }
  383. }
  384. namespace Symfony\Component\HttpKernel
  385. {
  386. use Symfony\Component\HttpFoundation\Request;
  387. interface HttpKernelInterface
  388. {
  389. const MASTER_REQUEST = 1;
  390. const SUB_REQUEST = 2;
  391. function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true);
  392. }
  393. }
  394. namespace Symfony\Component\HttpKernel\HttpCache
  395. {
  396. use Symfony\Component\HttpKernel\HttpKernelInterface;
  397. use Symfony\Component\HttpFoundation\Request;
  398. use Symfony\Component\HttpFoundation\Response;
  399. class HttpCache implements HttpKernelInterface
  400. {
  401. protected $kernel;
  402. protected $traces;
  403. protected $store;
  404. protected $request;
  405. protected $esi;
  406. public function __construct(HttpKernelInterface $kernel, StoreInterface $store, Esi $esi = null, array $options = array())
  407. {
  408. $this->store = $store;
  409. $this->kernel = $kernel;
  410. register_shutdown_function(array($this->store, 'cleanup'));
  411. $this->options = array_merge(array(
  412. 'debug' => false,
  413. 'default_ttl' => 0,
  414. 'private_headers' => array('Authorization', 'Cookie'),
  415. 'allow_reload' => false,
  416. 'allow_revalidate' => false,
  417. 'stale_while_revalidate' => 2,
  418. 'stale_if_error' => 60,
  419. ), $options);
  420. $this->esi = $esi;
  421. }
  422. public function getTraces()
  423. {
  424. return $this->traces;
  425. }
  426. public function getLog()
  427. {
  428. $log = array();
  429. foreach ($this->traces as $request => $traces) {
  430. $log[] = sprintf('%s: %s', $request, implode(', ', $traces));
  431. }
  432. return implode('; ', $log);
  433. }
  434. public function getRequest()
  435. {
  436. return $this->request;
  437. }
  438. public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
  439. {
  440. if (HttpKernelInterface::MASTER_REQUEST === $type) {
  441. $this->traces = array();
  442. $this->request = $request;
  443. }
  444. $path = $request->getPathInfo();
  445. if ($qs = $request->getQueryString()) {
  446. $path .= '?'.$qs;
  447. }
  448. $this->traces[$request->getMethod().' '.$path] = array();
  449. if (!$request->isMethodSafe($request)) {
  450. $response = $this->invalidate($request, $catch);
  451. } elseif ($request->headers->has('expect')) {
  452. $response = $this->pass($request, $catch);
  453. } else {
  454. $response = $this->lookup($request, $catch);
  455. }
  456. $response->isNotModified($request);
  457. $this->restoreResponseBody($request, $response);
  458. if (HttpKernelInterface::MASTER_REQUEST === $type && $this->options['debug']) {
  459. $response->headers->set('X-Symfony-Cache', $this->getLog());
  460. }
  461. return $response;
  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 (200 != $response->getStatusCode()) {
  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. parent::__construct();
  1104. $this->replace($parameters);
  1105. }
  1106. public function replace(array $files = array())
  1107. {
  1108. $this->parameters = array();
  1109. $this->add($files);
  1110. }
  1111. public function set($key, $value)
  1112. {
  1113. if (is_array($value) || $value instanceof UploadedFile) {
  1114. parent::set($key, $this->convertFileInformation($value));
  1115. }
  1116. }
  1117. public function add(array $files = array())
  1118. {
  1119. foreach ($files as $key => $file) {
  1120. $this->set($key, $file);
  1121. }
  1122. }
  1123. protected function convertFileInformation($file)
  1124. {
  1125. if ($file instanceof UploadedFile) {
  1126. return $file;
  1127. }
  1128. $file = $this->fixPhpFilesArray($file);
  1129. if (is_array($file)) {
  1130. $keys = array_keys($file);
  1131. sort($keys);
  1132. if ($keys == $this->fileKeys) {
  1133. $file['error'] = (int) $file['error'];
  1134. }
  1135. if ($keys != $this->fileKeys) {
  1136. $file = array_map(array($this, 'convertFileInformation'), $file);
  1137. } else
  1138. if ($file['error'] === UPLOAD_ERR_NO_FILE) {
  1139. $file = null;
  1140. } else {
  1141. $file = new UploadedFile($file['tmp_name'], $file['name'],
  1142. $file['type'], $file['size'], $file['error']);
  1143. }
  1144. }
  1145. return $file;
  1146. }
  1147. protected function fixPhpFilesArray($data)
  1148. {
  1149. if (! is_array($data)) {
  1150. return $data;
  1151. }
  1152. $keys = array_keys($data);
  1153. sort($keys);
  1154. if ($this->fileKeys != $keys || ! isset($data['name']) ||
  1155. ! is_array($data['name'])) {
  1156. return $data;
  1157. }
  1158. $files = $data;
  1159. foreach ($this->fileKeys as $k) {
  1160. unset($files[$k]);
  1161. }
  1162. foreach (array_keys($data['name']) as $key) {
  1163. $files[$key] = $this->fixPhpFilesArray(array(
  1164. 'error' => $data['error'][$key],
  1165. 'name' => $data['name'][$key], 'type' => $data['type'][$key],
  1166. 'tmp_name' => $data['tmp_name'][$key],
  1167. 'size' => $data['size'][$key]
  1168. ));
  1169. }
  1170. return $files;
  1171. }
  1172. }
  1173. }
  1174. namespace Symfony\Component\HttpFoundation
  1175. {
  1176. class ServerBag extends ParameterBag
  1177. {
  1178. public function getHeaders()
  1179. {
  1180. $headers = array();
  1181. foreach ($this->parameters as $key => $value) {
  1182. if ('HTTP_' === substr($key, 0, 5)) {
  1183. $headers[substr($key, 5)] = $value;
  1184. }
  1185. }
  1186. return $headers;
  1187. }
  1188. }
  1189. }
  1190. namespace Symfony\Component\HttpFoundation
  1191. {
  1192. class HeaderBag
  1193. {
  1194. protected $headers;
  1195. protected $cookies;
  1196. protected $cacheControl;
  1197. public function __construct(array $headers = array())
  1198. {
  1199. $this->cacheControl = array();
  1200. $this->cookies = array();
  1201. $this->headers = array();
  1202. foreach ($headers as $key => $values) {
  1203. $this->set($key, $values);
  1204. }
  1205. }
  1206. public function all()
  1207. {
  1208. return $this->headers;
  1209. }
  1210. public function keys()
  1211. {
  1212. return array_keys($this->headers);
  1213. }
  1214. public function replace(array $headers = array())
  1215. {
  1216. $this->headers = array();
  1217. $this->add($headers);
  1218. }
  1219. public function add(array $headers)
  1220. {
  1221. foreach ($headers as $key => $values) {
  1222. $this->set($key, $values);
  1223. }
  1224. }
  1225. public function get($key, $default = null, $first = true)
  1226. {
  1227. $key = strtr(strtolower($key), '_', '-');
  1228. if (!array_key_exists($key, $this->headers)) {
  1229. if (null === $default) {
  1230. return $first ? null : array();
  1231. } else {
  1232. return $first ? $default : array($default);
  1233. }
  1234. }
  1235. if ($first) {
  1236. return count($this->headers[$key]) ? $this->headers[$key][0] : $default;
  1237. } else {
  1238. return $this->headers[$key];
  1239. }
  1240. }
  1241. public function set($key, $values, $replace = true)
  1242. {
  1243. $key = strtr(strtolower($key), '_', '-');
  1244. if (!is_array($values)) {
  1245. $values = array($values);
  1246. }
  1247. if (true === $replace || !isset($this->headers[$key])) {
  1248. $this->headers[$key] = $values;
  1249. } else {
  1250. $this->headers[$key] = array_merge($this->headers[$key], $values);
  1251. }
  1252. if ('cache-control' === $key) {
  1253. $this->cacheControl = $this->parseCacheControl($values[0]);
  1254. }
  1255. }
  1256. public function has($key)
  1257. {
  1258. return array_key_exists(strtr(strtolower($key), '_', '-'), $this->headers);
  1259. }
  1260. public function contains($key, $value)
  1261. {
  1262. return in_array($value, $this->get($key, null, false));
  1263. }
  1264. public function remove($key)
  1265. {
  1266. $key = strtr(strtolower($key), '_', '-');
  1267. unset($this->headers[$key]);
  1268. if ('cache-control' === $key) {
  1269. $this->cacheControl = array();
  1270. }
  1271. }
  1272. public function setCookie(Cookie $cookie)
  1273. {
  1274. $this->cookies[$cookie->getName()] = $cookie;
  1275. }
  1276. public function removeCookie($name)
  1277. {
  1278. unset($this->cookies[$name]);
  1279. }
  1280. public function hasCookie($name)
  1281. {
  1282. return isset($this->cookies[$name]);
  1283. }
  1284. public function getCookie($name)
  1285. {
  1286. if (!$this->hasCookie($name)) {
  1287. throw new \InvalidArgumentException(sprintf('There is no cookie with name "%s".', $name));
  1288. }
  1289. return $this->cookies[$name];
  1290. }
  1291. public function getCookies()
  1292. {
  1293. return $this->cookies;
  1294. }
  1295. public function getDate($key, \DateTime $default = null)
  1296. {
  1297. if (null === $value = $this->get($key)) {
  1298. return $default;
  1299. }
  1300. if (false === $date = \DateTime::createFromFormat(DATE_RFC2822, $value)) {
  1301. throw new \RuntimeException(sprintf('The %s HTTP header is not parseable (%s).', $key, $value));
  1302. }
  1303. return $date;
  1304. }
  1305. public function addCacheControlDirective($key, $value = true)
  1306. {
  1307. $this->cacheControl[$key] = $value;
  1308. $this->set('Cache-Control', $this->getCacheControlHeader());
  1309. }
  1310. public function hasCacheControlDirective($key)
  1311. {
  1312. return array_key_exists($key, $this->cacheControl);
  1313. }
  1314. public function getCacheControlDirective($key)
  1315. {
  1316. return array_key_exists($key, $this->cacheControl) ? $this->cacheControl[$key] : null;
  1317. }
  1318. public function removeCacheControlDirective($key)
  1319. {
  1320. unset($this->cacheControl[$key]);
  1321. $this->set('Cache-Control', $this->getCacheControlHeader());
  1322. }
  1323. protected function getCacheControlHeader()
  1324. {
  1325. $parts = array();
  1326. ksort($this->cacheControl);
  1327. foreach ($this->cacheControl as $key => $value) {
  1328. if (true === $value) {
  1329. $parts[] = $key;
  1330. } else {
  1331. if (preg_match('#[^a-zA-Z0-9._-]#', $value)) {
  1332. $value = '"'.$value.'"';
  1333. }
  1334. $parts[] = "$key=$value";
  1335. }
  1336. }
  1337. return implode(', ', $parts);
  1338. }
  1339. protected function parseCacheControl($header)
  1340. {
  1341. $cacheControl = array();
  1342. preg_match_all('#([a-zA-Z][a-zA-Z_-]*)\s*(?:=(?:"([^"]*)"|([^ \t",;]*)))?#', $header, $matches, PREG_SET_ORDER);
  1343. foreach ($matches as $match) {
  1344. $cacheControl[strtolower($match[1])] = isset($match[2]) && $match[2] ? $match[2] : (isset($match[3]) ? $match[3] : true);
  1345. }
  1346. return $cacheControl;
  1347. }
  1348. }
  1349. }
  1350. namespace Symfony\Component\HttpFoundation
  1351. {
  1352. use Symfony\Component\HttpFoundation\SessionStorage\NativeSessionStorage;
  1353. use Symfony\Component\HttpFoundation\File\UploadedFile;
  1354. class Request
  1355. {
  1356. public $attributes;
  1357. public $request;
  1358. public $query;
  1359. public $server;
  1360. public $files;
  1361. public $cookies;
  1362. public $headers;
  1363. protected $content;
  1364. protected $languages;
  1365. protected $charsets;
  1366. protected $acceptableContentTypes;
  1367. protected $pathInfo;
  1368. protected $requestUri;
  1369. protected $baseUrl;
  1370. protected $basePath;
  1371. protected $method;
  1372. protected $format;
  1373. protected $session;
  1374. static protected $formats;
  1375. public function __construct(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null)
  1376. {
  1377. $this->initialize($query, $request, $attributes, $cookies, $files, $server, $content);
  1378. }
  1379. public function initialize(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null)
  1380. {
  1381. $this->request = new ParameterBag($request);
  1382. $this->query = new ParameterBag($query);
  1383. $this->attributes = new ParameterBag($attributes);
  1384. $this->cookies = new ParameterBag($cookies);
  1385. $this->files = new FileBag($files);
  1386. $this->server = new ServerBag($server);
  1387. $this->headers = new HeaderBag($this->server->getHeaders());
  1388. $this->content = $content;
  1389. $this->languages = null;
  1390. $this->charsets = null;
  1391. $this->acceptableContentTypes = null;
  1392. $this->pathInfo = null;
  1393. $this->requestUri = null;
  1394. $this->baseUrl = null;
  1395. $this->basePath = null;
  1396. $this->method = null;
  1397. $this->format = null;
  1398. }
  1399. static public function createfromGlobals()
  1400. {
  1401. return new static($_GET, $_POST, array(), $_COOKIE, $_FILES, $_SERVER);
  1402. }
  1403. static public function create($uri, $method = 'GET', $parameters = array(), $cookies = array(), $files = array(), $server = array(), $content = null)
  1404. {
  1405. $defaults = array(
  1406. 'SERVER_NAME' => 'localhost',
  1407. 'SERVER_PORT' => 80,
  1408. 'HTTP_HOST' => 'localhost',
  1409. 'HTTP_USER_AGENT' => 'Symfony/2.X',
  1410. 'HTTP_ACCEPT' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
  1411. 'HTTP_ACCEPT_LANGUAGE' => 'en-us,en;q=0.5',
  1412. 'HTTP_ACCEPT_CHARSET' => 'ISO-8859-1,utf-8;q=0.7,*;q=0.7',
  1413. 'REMOTE_ADDR' => '127.0.0.1',
  1414. 'SCRIPT_NAME' => '',
  1415. 'SCRIPT_FILENAME' => '',
  1416. );
  1417. $components = parse_url($uri);
  1418. if (isset($components['host'])) {
  1419. $defaults['SERVER_NAME'] = $components['host'];
  1420. $defaults['HTTP_HOST'] = $components['host'];
  1421. }
  1422. if (isset($components['scheme'])) {
  1423. if ('https' === $components['scheme']) {
  1424. $defaults['HTTPS'] = 'on';
  1425. $defaults['SERVER_PORT'] = 443;
  1426. }
  1427. }
  1428. if (isset($components['port'])) {
  1429. $defaults['SERVER_PORT'] = $components['port'];
  1430. $defaults['HTTP_HOST'] = $defaults['HTTP_HOST'].':'.$components['port'];
  1431. }
  1432. if (in_array(strtoupper($method), array('POST', 'PUT', 'DELETE'))) {
  1433. $request = $parameters;
  1434. $query = array();
  1435. $defaults['CONTENT_TYPE'] = 'application/x-www-form-urlencoded';
  1436. } else {
  1437. $request = array();
  1438. $query = $parameters;
  1439. if (false !== $pos = strpos($uri, '?')) {
  1440. $qs = substr($uri, $pos + 1);
  1441. parse_str($qs, $params);
  1442. $query = array_merge($params, $query);
  1443. }
  1444. }
  1445. $queryString = isset($components['query']) ? html_entity_decode($components['query']) : '';
  1446. parse_str($queryString, $qs);
  1447. if (is_array($qs)) {
  1448. $query = array_replace($qs, $query);
  1449. }
  1450. $uri = $components['path'] . ($queryString ? '?'.$queryString : '');
  1451. $server = array_replace($defaults, $server, array(
  1452. 'REQUEST_METHOD' => strtoupper($method),
  1453. 'PATH_INFO' => '',
  1454. 'REQUEST_URI' => $uri,
  1455. 'QUERY_STRING' => $queryString,
  1456. ));
  1457. return new static($query, $request, array(), $cookies, $files, $server, $content);
  1458. }
  1459. public function duplicate(array $query = null, array $request = null, array $attributes = null, array $cookies = null, array $files = null, array $server = null)
  1460. {
  1461. $dup = clone $this;
  1462. $dup->initialize(
  1463. null !== $query ? $query : $this->query->all(),
  1464. null !== $request ? $request : $this->request->all(),
  1465. null !== $attributes ? $attributes : $this->attributes->all(),
  1466. null !== $cookies ? $cookies : $this->cookies->all(),
  1467. null !== $files ? $files : $this->files->all(),
  1468. null !== $server ? $server : $this->server->all()
  1469. );
  1470. return $dup;
  1471. }
  1472. public function __clone()
  1473. {
  1474. $this->query = clone $this->query;
  1475. $this->request = clone $this->request;
  1476. $this->attributes = clone $this->attributes;
  1477. $this->cookies = clone $this->cookies;
  1478. $this->files = clone $this->files;
  1479. $this->server = clone $this->server;
  1480. $this->headers = clone $this->headers;
  1481. }
  1482. public function overrideGlobals()
  1483. {
  1484. $_GET = $this->query->all();
  1485. $_POST = $this->request->all();
  1486. $_SERVER = $this->server->all();
  1487. $_COOKIE = $this->cookies->all();
  1488. foreach ($this->headers->all() as $key => $value) {
  1489. $_SERVER['HTTP_'.strtoupper(str_replace('-', '_', $key))] = implode(', ', $value);
  1490. }
  1491. $_REQUEST = array_merge($_GET, $_POST);
  1492. }
  1493. public function get($key, $default = null)
  1494. {
  1495. return $this->query->get($key, $this->attributes->get($key, $this->request->get($key, $default)));
  1496. }
  1497. public function getSession()
  1498. {
  1499. return $this->session;
  1500. }
  1501. public function hasSession()
  1502. {
  1503. return $this->cookies->has(session_name());
  1504. }
  1505. public function setSession(Session $session)
  1506. {
  1507. $this->session = $session;
  1508. }
  1509. public function getClientIp($proxy = false)
  1510. {
  1511. if ($proxy) {
  1512. if ($this->server->has('HTTP_CLIENT_IP')) {
  1513. return $this->server->get('HTTP_CLIENT_IP');
  1514. } elseif ($this->server->has('HTTP_X_FORWARDED_FOR')) {
  1515. return $this->server->get('HTTP_X_FORWARDED_FOR');
  1516. }
  1517. }
  1518. return $this->server->get('REMOTE_ADDR');
  1519. }
  1520. public function getScriptName()
  1521. {
  1522. return $this->server->get('SCRIPT_NAME', $this->server->get('ORIG_SCRIPT_NAME', ''));
  1523. }
  1524. public function getPathInfo()
  1525. {
  1526. if (null === $this->pathInfo) {
  1527. $this->pathInfo = $this->preparePathInfo();
  1528. }
  1529. return $this->pathInfo;
  1530. }
  1531. public function getBasePath()
  1532. {
  1533. if (null === $this->basePath) {
  1534. $this->basePath = $this->prepareBasePath();
  1535. }
  1536. return $this->basePath;
  1537. }
  1538. public function getBaseUrl()
  1539. {
  1540. if (null === $this->baseUrl) {
  1541. $this->baseUrl = $this->prepareBaseUrl();
  1542. }
  1543. return $this->baseUrl;
  1544. }
  1545. public function getScheme()
  1546. {
  1547. return ($this->server->get('HTTPS') == 'on') ? 'https' : 'http';
  1548. }
  1549. public function getPort()
  1550. {
  1551. return $this->server->get('SERVER_PORT');
  1552. }
  1553. public function getHttpHost()
  1554. {
  1555. $host = $this->headers->get('HOST');
  1556. if (!empty($host)) {
  1557. return $host;
  1558. }
  1559. $scheme = $this->getScheme();
  1560. $name = $this->server->get('SERVER_NAME');
  1561. $port = $this->getPort();
  1562. if (('http' == $scheme && $port == 80) || ('https' == $scheme && $port == 443)) {
  1563. return $name;
  1564. } else {
  1565. return $name.':'.$port;
  1566. }
  1567. }
  1568. public function getRequestUri()
  1569. {
  1570. if (null === $this->requestUri) {
  1571. $this->requestUri = $this->prepareRequestUri();
  1572. }
  1573. return $this->requestUri;
  1574. }
  1575. public function getUri()
  1576. {
  1577. $qs = $this->getQueryString();
  1578. if (null !== $qs) {
  1579. $qs = '?'.$qs;
  1580. }
  1581. return $this->getScheme().'://'.$this->getHttpHost().$this->getBaseUrl().$this->getPathInfo().$qs;
  1582. }
  1583. public function getUriForPath($path)
  1584. {
  1585. return $this->getScheme().'://'.$this->getHttpHost().$this->getBaseUrl().$path;
  1586. }
  1587. public function getQueryString()
  1588. {
  1589. if (!$qs = $this->server->get('QUERY_STRING')) {
  1590. return null;
  1591. }
  1592. $parts = array();
  1593. $order = array();
  1594. foreach (explode('&', $qs) as $segment) {
  1595. if (false === strpos($segment, '=')) {
  1596. $parts[] = $segment;
  1597. $order[] = $segment;
  1598. } else {
  1599. $tmp = explode('=', urldecode($segment), 2);
  1600. $parts[] = urlencode($tmp[0]).'='.urlencode($tmp[1]);
  1601. $order[] = $tmp[0];
  1602. }
  1603. }
  1604. array_multisort($order, SORT_ASC, $parts);
  1605. return implode('&', $parts);
  1606. }
  1607. public function isSecure()
  1608. {
  1609. return (
  1610. (strtolower($this->server->get('HTTPS')) == 'on' || $this->server->get('HTTPS') == 1)
  1611. ||
  1612. (strtolower($this->headers->get('SSL_HTTPS')) == 'on' || $this->headers->get('SSL_HTTPS') == 1)
  1613. ||
  1614. (strtolower($this->headers->get('X_FORWARDED_PROTO')) == 'https')
  1615. );
  1616. }
  1617. public function getHost()
  1618. {
  1619. if ($host = $this->headers->get('X_FORWARDED_HOST')) {
  1620. $elements = explode(',', $host);
  1621. $host = trim($elements[count($elements) - 1]);
  1622. } else {
  1623. if (!$host = $this->headers->get('HOST')) {
  1624. if (!$host = $this->server->get('SERVER_NAME')) {
  1625. $host = $this->server->get('SERVER_ADDR', '');
  1626. }
  1627. }
  1628. }
  1629. $elements = explode(':', $host);
  1630. return trim($elements[0]);
  1631. }
  1632. public function setMethod($method)
  1633. {
  1634. $this->method = null;
  1635. $this->server->set('REQUEST_METHOD', $method);
  1636. }
  1637. public function getMethod()
  1638. {
  1639. if (null === $this->method) {
  1640. $this->method = strtoupper($this->server->get('REQUEST_METHOD', 'GET'));
  1641. if ('POST' === $this->method) {
  1642. $this->method = strtoupper($this->request->get('_method', 'POST'));
  1643. }
  1644. }
  1645. return $this->method;
  1646. }
  1647. public function getMimeType($format)
  1648. {
  1649. if (null === static::$formats) {
  1650. static::initializeFormats();
  1651. }
  1652. return isset(static::$formats[$format]) ? static::$formats[$format][0] : null;
  1653. }
  1654. public function getFormat($mimeType)
  1655. {
  1656. if (null === static::$formats) {
  1657. static::initializeFormats();
  1658. }
  1659. foreach (static::$formats as $format => $mimeTypes) {
  1660. if (in_array($mimeType, (array) $mimeTypes)) {
  1661. return $format;
  1662. }
  1663. }
  1664. return null;
  1665. }
  1666. public function setFormat($format, $mimeTypes)
  1667. {
  1668. if (null === static::$formats) {
  1669. static::initializeFormats();
  1670. }
  1671. static::$formats[$format] = is_array($mimeTypes) ? $mimeTypes : array($mimeTypes);
  1672. }
  1673. public function getRequestFormat()
  1674. {
  1675. if (null === $this->format) {
  1676. $this->format = $this->get('_format', 'html');
  1677. }
  1678. return $this->format;
  1679. }
  1680. public function setRequestFormat($format)
  1681. {
  1682. $this->format = $format;
  1683. }
  1684. public function isMethodSafe()
  1685. {
  1686. return in_array($this->getMethod(), array('GET', 'HEAD'));
  1687. }
  1688. public function getContent($asResource = false)
  1689. {
  1690. if (false === $this->content || (true === $asResource && null !== $this->content)) {
  1691. throw new \LogicException('getContent() can only be called once when using the resource return type.');
  1692. }
  1693. if (true === $asResource) {
  1694. $this->content = false;
  1695. return fopen('php://input', 'rb');
  1696. }
  1697. if (null === $this->content) {
  1698. $this->content = file_get_contents('php://input');
  1699. }
  1700. return $this->content;
  1701. }
  1702. public function getETags()
  1703. {
  1704. return preg_split('/\s*,\s*/', $this->headers->get('if_none_match'), null, PREG_SPLIT_NO_EMPTY);
  1705. }
  1706. public function isNoCache()
  1707. {
  1708. return $this->headers->hasCacheControlDirective('no-cache') || 'no-cache' == $this->headers->get('Pragma');
  1709. }
  1710. public function getPreferredLanguage(array $locales = null)
  1711. {
  1712. $preferredLanguages = $this->getLanguages();
  1713. if (null === $locales) {
  1714. return isset($preferredLanguages[0]) ? $preferredLanguages[0] : null;
  1715. }
  1716. if (!$preferredLanguages) {
  1717. return $locales[0];
  1718. }
  1719. $preferredLanguages = array_values(array_intersect($preferredLanguages, $locales));
  1720. return isset($preferredLanguages[0]) ? $preferredLanguages[0] : $locales[0];
  1721. }
  1722. public function getLanguages()
  1723. {
  1724. if (null !== $this->languages) {
  1725. return $this->languages;
  1726. }
  1727. $languages = $this->splitHttpAcceptHeader($this->headers->get('Accept-Language'));
  1728. foreach ($languages as $lang) {
  1729. if (strstr($lang, '-')) {
  1730. $codes = explode('-', $lang);
  1731. if ($codes[0] == 'i') {
  1732. if (count($codes) > 1) {
  1733. $lang = $codes[1];
  1734. }
  1735. } else {
  1736. for ($i = 0, $max = count($codes); $i < $max; $i++) {
  1737. if ($i == 0) {
  1738. $lang = strtolower($codes[0]);
  1739. } else {
  1740. $lang .= '_'.strtoupper($codes[$i]);
  1741. }
  1742. }
  1743. }
  1744. }
  1745. $this->languages[] = $lang;
  1746. }
  1747. return $this->languages;
  1748. }
  1749. public function getCharsets()
  1750. {
  1751. if (null !== $this->charsets) {
  1752. return $this->charsets;
  1753. }
  1754. return $this->charsets = $this->splitHttpAcceptHeader($this->headers->get('Accept-Charset'));
  1755. }
  1756. public function getAcceptableContentTypes()
  1757. {
  1758. if (null !== $this->acceptableContentTypes) {
  1759. return $this->acceptableContentTypes;
  1760. }
  1761. return $this->acceptableContentTypes = $this->splitHttpAcceptHeader($this->headers->get('Accept'));
  1762. }
  1763. public function isXmlHttpRequest()
  1764. {
  1765. return 'XMLHttpRequest' == $this->headers->get('X-Requested-With');
  1766. }
  1767. public function splitHttpAcceptHeader($header)
  1768. {
  1769. if (!$header) {
  1770. return array();
  1771. }
  1772. $values = array();
  1773. foreach (array_filter(explode(',', $header)) as $value) {
  1774. if ($pos = strpos($value, ';')) {
  1775. $q = (float) trim(substr($value, strpos($value, '=') + 1));
  1776. $value = trim(substr($value, 0, $pos));
  1777. } else {
  1778. $q = 1;
  1779. }
  1780. if (0 < $q) {
  1781. $values[trim($value)] = $q;
  1782. }
  1783. }
  1784. arsort($values);
  1785. return array_keys($values);
  1786. }
  1787. protected function prepareRequestUri()
  1788. {
  1789. $requestUri = '';
  1790. if ($this->headers->has('X_REWRITE_URL')) {
  1791. $requestUri = $this->headers->get('X_REWRITE_URL');
  1792. } elseif ($this->server->get('IIS_WasUrlRewritten') == '1' && $this->server->get('UNENCODED_URL') != '') {
  1793. $requestUri = $this->server->get('UNENCODED_URL');
  1794. } elseif ($this->server->has('REQUEST_URI')) {
  1795. $requestUri = $this->server->get('REQUEST_URI');
  1796. $schemeAndHttpHost = $this->getScheme().'://'.$this->getHttpHost();
  1797. if (strpos($requestUri, $schemeAndHttpHost) === 0) {
  1798. $requestUri = substr($requestUri, strlen($schemeAndHttpHost));
  1799. }
  1800. } elseif ($this->server->has('ORIG_PATH_INFO')) {
  1801. $requestUri = $this->server->get('ORIG_PATH_INFO');
  1802. if ($this->server->get('QUERY_STRING')) {
  1803. $requestUri .= '?'.$this->server->get('QUERY_STRING');
  1804. }
  1805. }
  1806. return $requestUri;
  1807. }
  1808. protected function prepareBaseUrl()
  1809. {
  1810. $filename = basename($this->server->get('SCRIPT_FILENAME'));
  1811. if (basename($this->server->get('SCRIPT_NAME')) === $filename) {
  1812. $baseUrl = $this->server->get('SCRIPT_NAME');
  1813. } elseif (basename($this->server->get('PHP_SELF')) === $filename) {
  1814. $baseUrl = $this->server->get('PHP_SELF');
  1815. } elseif (basename($this->server->get('ORIG_SCRIPT_NAME')) === $filename) {
  1816. $baseUrl = $this->server->get('ORIG_SCRIPT_NAME'); } else {
  1817. $path = $this->server->get('PHP_SELF', '');
  1818. $file = $this->server->get('SCRIPT_FILENAME', '');
  1819. $segs = explode('/', trim($file, '/'));
  1820. $segs = array_reverse($segs);
  1821. $index = 0;
  1822. $last = count($segs);
  1823. $baseUrl = '';
  1824. do {
  1825. $seg = $segs[$index];
  1826. $baseUrl = '/'.$seg.$baseUrl;
  1827. ++$index;
  1828. } while (($last > $index) && (false !== ($pos = strpos($path, $baseUrl))) && (0 != $pos));
  1829. }
  1830. $requestUri = $this->getRequestUri();
  1831. if ($baseUrl && 0 === strpos($requestUri, $baseUrl)) {
  1832. return $baseUrl;
  1833. }
  1834. if ($baseUrl && 0 === strpos($requestUri, dirname($baseUrl))) {
  1835. return rtrim(dirname($baseUrl), '/');
  1836. }
  1837. $truncatedRequestUri = $requestUri;
  1838. if (($pos = strpos($requestUri, '?')) !== false) {
  1839. $truncatedRequestUri = substr($requestUri, 0, $pos);
  1840. }
  1841. $basename = basename($baseUrl);
  1842. if (empty($basename) || !strpos($truncatedRequestUri, $basename)) {
  1843. return '';
  1844. }
  1845. if ((strlen($requestUri) >= strlen($baseUrl)) && ((false !== ($pos = strpos($requestUri, $baseUrl))) && ($pos !== 0))) {
  1846. $baseUrl = substr($requestUri, 0, $pos + strlen($baseUrl));
  1847. }
  1848. return rtrim($baseUrl, '/');
  1849. }
  1850. protected function prepareBasePath()
  1851. {
  1852. $filename = basename($this->server->get('SCRIPT_FILENAME'));
  1853. $baseUrl = $this->getBaseUrl();
  1854. if (empty($baseUrl)) {
  1855. return '';
  1856. }
  1857. if (basename($baseUrl) === $filename) {
  1858. $basePath = dirname($baseUrl);
  1859. } else {
  1860. $basePath = $baseUrl;
  1861. }
  1862. if ('\\' === DIRECTORY_SEPARATOR) {
  1863. $basePath = str_replace('\\', '/', $basePath);
  1864. }
  1865. return rtrim($basePath, '/');
  1866. }
  1867. protected function preparePathInfo()
  1868. {
  1869. $baseUrl = $this->getBaseUrl();
  1870. if (null === ($requestUri = $this->getRequestUri())) {
  1871. return '';
  1872. }
  1873. $pathInfo = '';
  1874. if ($pos = strpos($requestUri, '?')) {
  1875. $requestUri = substr($requestUri, 0, $pos);
  1876. }
  1877. if ((null !== $baseUrl) && (false === ($pathInfo = substr($requestUri, strlen($baseUrl))))) {
  1878. return '';
  1879. } elseif (null === $baseUrl) {
  1880. return $requestUri;
  1881. }
  1882. return (string) $pathInfo;
  1883. }
  1884. static protected function initializeFormats()
  1885. {
  1886. static::$formats = array(
  1887. 'txt' => array('text/plain'),
  1888. 'js' => array('application/javascript', 'application/x-javascript', 'text/javascript'),
  1889. 'css' => array('text/css'),
  1890. 'json' => array('application/json', 'application/x-json'),
  1891. 'xml' => array('text/xml', 'application/xml', 'application/x-xml'),
  1892. 'rdf' => array('application/rdf+xml'),
  1893. 'atom' => array('application/atom+xml'),
  1894. );
  1895. }
  1896. }
  1897. }
  1898. namespace Symfony\Component\HttpFoundation
  1899. {
  1900. class ApacheRequest extends Request
  1901. {
  1902. protected function prepareRequestUri()
  1903. {
  1904. return $this->server->get('REQUEST_URI');
  1905. }
  1906. protected function prepareBaseUrl()
  1907. {
  1908. return $this->server->get('SCRIPT_NAME');
  1909. }
  1910. protected function preparePathInfo()
  1911. {
  1912. return $this->server->get('PATH_INFO');
  1913. }
  1914. }
  1915. }
  1916. namespace Symfony\Component\HttpFoundation
  1917. {
  1918. class ResponseHeaderBag extends HeaderBag
  1919. {
  1920. protected $computedCacheControl = array();
  1921. public function __construct(array $parameters = array())
  1922. {
  1923. parent::__construct();
  1924. $this->replace($parameters);
  1925. }
  1926. public function replace(array $headers = array())
  1927. {
  1928. parent::replace($headers);
  1929. if (!isset($this->headers['cache-control'])) {
  1930. $this->set('cache-control', '');
  1931. }
  1932. }
  1933. public function set($key, $values, $replace = true)
  1934. {
  1935. parent::set($key, $values, $replace);
  1936. if ('cache-control' === strtr(strtolower($key), '_', '-')) {
  1937. $computed = $this->computeCacheControlValue();
  1938. $this->headers['cache-control'] = array($computed);
  1939. $this->computedCacheControl = $this->parseCacheControl($computed);
  1940. }
  1941. }
  1942. public function remove($key)
  1943. {
  1944. parent::remove($key);
  1945. if ('cache-control' === strtr(strtolower($key), '_', '-')) {
  1946. $this->computedCacheControl = array();
  1947. }
  1948. }
  1949. public function hasCacheControlDirective($key)
  1950. {
  1951. return array_key_exists($key, $this->computedCacheControl);
  1952. }
  1953. public function getCacheControlDirective($key)
  1954. {
  1955. return array_key_exists($key, $this->computedCacheControl) ? $this->computedCacheControl[$key] : null;
  1956. }
  1957. public function clearCookie($name, $path = null, $domain = null)
  1958. {
  1959. $this->setCookie(new Cookie($name, null, time() - 86400, $path, $domain));
  1960. }
  1961. protected function computeCacheControlValue()
  1962. {
  1963. if (!$this->cacheControl && !$this->has('ETag') && !$this->has('Last-Modified') && !$this->has('Expires')) {
  1964. return 'no-cache';
  1965. }
  1966. if (!$this->cacheControl) {
  1967. return 'private, max-age=0, must-revalidate';
  1968. }
  1969. $header = $this->getCacheControlHeader();
  1970. if (isset($this->cacheControl['public']) || isset($this->cacheControl['private'])) {
  1971. return $header;
  1972. }
  1973. if (!isset($this->cacheControl['s-maxage'])) {
  1974. return $header.', private';
  1975. }
  1976. return $header;
  1977. }
  1978. }
  1979. }
  1980. namespace Symfony\Component\HttpFoundation
  1981. {
  1982. class Response
  1983. {
  1984. public $headers;
  1985. protected $content;
  1986. protected $version;
  1987. protected $statusCode;
  1988. protected $statusText;
  1989. protected $charset = 'UTF-8';
  1990. static public $statusTexts = array(
  1991. 100 => 'Continue',
  1992. 101 => 'Switching Protocols',
  1993. 200 => 'OK',
  1994. 201 => 'Created',
  1995. 202 => 'Accepted',
  1996. 203 => 'Non-Authoritative Information',
  1997. 204 => 'No Content',
  1998. 205 => 'Reset Content',
  1999. 206 => 'Partial Content',
  2000. 300 => 'Multiple Choices',
  2001. 301 => 'Moved Permanently',
  2002. 302 => 'Found',
  2003. 303 => 'See Other',
  2004. 304 => 'Not Modified',
  2005. 305 => 'Use Proxy',
  2006. 307 => 'Temporary Redirect',
  2007. 400 => 'Bad Request',
  2008. 401 => 'Unauthorized',
  2009. 402 => 'Payment Required',
  2010. 403 => 'Forbidden',
  2011. 404 => 'Not Found',
  2012. 405 => 'Method Not Allowed',
  2013. 406 => 'Not Acceptable',
  2014. 407 => 'Proxy Authentication Required',
  2015. 408 => 'Request Timeout',
  2016. 409 => 'Conflict',
  2017. 410 => 'Gone',
  2018. 411 => 'Length Required',
  2019. 412 => 'Precondition Failed',
  2020. 413 => 'Request Entity Too Large',
  2021. 414 => 'Request-URI Too Long',
  2022. 415 => 'Unsupported Media Type',
  2023. 416 => 'Requested Range Not Satisfiable',
  2024. 417 => 'Expectation Failed',
  2025. 418 => 'I\'m a teapot',
  2026. 500 => 'Internal Server Error',
  2027. 501 => 'Not Implemented',
  2028. 502 => 'Bad Gateway',
  2029. 503 => 'Service Unavailable',
  2030. 504 => 'Gateway Timeout',
  2031. 505 => 'HTTP Version Not Supported',
  2032. );
  2033. public function __construct($content = '', $status = 200, $headers = array())
  2034. {
  2035. $this->setContent($content);
  2036. $this->setStatusCode($status);
  2037. $this->setProtocolVersion('1.0');
  2038. $this->headers = new ResponseHeaderBag($headers);
  2039. }
  2040. public function __toString()
  2041. {
  2042. $content = '';
  2043. if (!$this->headers->has('Content-Type')) {
  2044. $this->headers->set('Content-Type', 'text/html; charset='.$this->charset);
  2045. }
  2046. $content .= sprintf('HTTP/%s %s %s', $this->version, $this->statusCode, $this->statusText)."\n";
  2047. foreach ($this->headers->all() as $name => $values) {
  2048. foreach ($values as $value) {
  2049. $content .= "$name: $value\n";
  2050. }
  2051. }
  2052. $content .= "\n".$this->getContent();
  2053. return $content;
  2054. }
  2055. public function __clone()
  2056. {
  2057. $this->headers = clone $this->headers;
  2058. }
  2059. public function sendHeaders()
  2060. {
  2061. if (!$this->headers->has('Content-Type')) {
  2062. $this->headers->set('Content-Type', 'text/html; charset='.$this->charset);
  2063. }
  2064. header(sprintf('HTTP/%s %s %s', $this->version, $this->statusCode, $this->statusText));
  2065. foreach ($this->headers->all() as $name => $values) {
  2066. foreach ($values as $value) {
  2067. header($name.': '.$value);
  2068. }
  2069. }
  2070. foreach ($this->headers->getCookies() as $cookie) {
  2071. setcookie($cookie->getName(), $cookie->getValue(), $cookie->getExpire(), $cookie->getPath(), $cookie->getDomain(), $cookie->isSecure(), $cookie->isHttpOnly());
  2072. }
  2073. }
  2074. public function sendContent()
  2075. {
  2076. echo $this->content;
  2077. }
  2078. public function send()
  2079. {
  2080. $this->sendHeaders();
  2081. $this->sendContent();
  2082. }
  2083. public function setContent($content)
  2084. {
  2085. $this->content = $content;
  2086. }
  2087. public function getContent()
  2088. {
  2089. return $this->content;
  2090. }
  2091. public function setProtocolVersion($version)
  2092. {
  2093. $this->version = $version;
  2094. }
  2095. public function getProtocolVersion()
  2096. {
  2097. return $this->version;
  2098. }
  2099. public function setStatusCode($code, $text = null)
  2100. {
  2101. $this->statusCode = (int) $code;
  2102. if ($this->statusCode < 100 || $this->statusCode > 599) {
  2103. throw new \InvalidArgumentException(sprintf('The HTTP status code "%s" is not valid.', $code));
  2104. }
  2105. $this->statusText = false === $text ? '' : (null === $text ? self::$statusTexts[$this->statusCode] : $text);
  2106. }
  2107. public function getStatusCode()
  2108. {
  2109. return $this->statusCode;
  2110. }
  2111. public function setCharset($charset)
  2112. {
  2113. $this->charset = $charset;
  2114. }
  2115. public function getCharset()
  2116. {
  2117. return $this->charset;
  2118. }
  2119. public function isCacheable()
  2120. {
  2121. if (!in_array($this->statusCode, array(200, 203, 300, 301, 302, 404, 410))) {
  2122. return false;
  2123. }
  2124. if ($this->headers->hasCacheControlDirective('no-store') || $this->headers->getCacheControlDirective('private')) {
  2125. return false;
  2126. }
  2127. return $this->isValidateable() || $this->isFresh();
  2128. }
  2129. public function isFresh()
  2130. {
  2131. return $this->getTtl() > 0;
  2132. }
  2133. public function isValidateable()
  2134. {
  2135. return $this->headers->has('Last-Modified') || $this->headers->has('ETag');
  2136. }
  2137. public function setPrivate()
  2138. {
  2139. $this->headers->removeCacheControlDirective('public');
  2140. $this->headers->addCacheControlDirective('private');
  2141. }
  2142. public function setPublic()
  2143. {
  2144. $this->headers->addCacheControlDirective('public');
  2145. $this->headers->removeCacheControlDirective('private');
  2146. }
  2147. public function mustRevalidate()
  2148. {
  2149. return $this->headers->hasCacheControlDirective('must-revalidate') || $this->headers->has('must-proxy-revalidate');
  2150. }
  2151. public function getDate()
  2152. {
  2153. if (null === $date = $this->headers->getDate('Date')) {
  2154. $date = new \DateTime(null, new \DateTimeZone('UTC'));
  2155. $this->headers->set('Date', $date->format('D, d M Y H:i:s').' GMT');
  2156. }
  2157. return $date;
  2158. }
  2159. public function getAge()
  2160. {
  2161. if ($age = $this->headers->get('Age')) {
  2162. return $age;
  2163. }
  2164. return max(time() - $this->getDate()->format('U'), 0);
  2165. }
  2166. public function expire()
  2167. {
  2168. if ($this->isFresh()) {
  2169. $this->headers->set('Age', $this->getMaxAge());
  2170. }
  2171. }
  2172. public function getExpires()
  2173. {
  2174. return $this->headers->getDate('Expires');
  2175. }
  2176. public function setExpires(\DateTime $date = null)
  2177. {
  2178. if (null === $date) {
  2179. $this->headers->remove('Expires');
  2180. } else {
  2181. $date = clone $date;
  2182. $date->setTimezone(new \DateTimeZone('UTC'));
  2183. $this->headers->set('Expires', $date->format('D, d M Y H:i:s').' GMT');
  2184. }
  2185. }
  2186. public function getMaxAge()
  2187. {
  2188. if ($age = $this->headers->getCacheControlDirective('s-maxage')) {
  2189. return $age;
  2190. }
  2191. if ($age = $this->headers->getCacheControlDirective('max-age')) {
  2192. return $age;
  2193. }
  2194. if (null !== $this->getExpires()) {
  2195. return $this->getExpires()->format('U') - $this->getDate()->format('U');
  2196. }
  2197. return null;
  2198. }
  2199. public function setMaxAge($value)
  2200. {
  2201. $this->headers->addCacheControlDirective('max-age', $value);
  2202. }
  2203. public function setSharedMaxAge($value)
  2204. {
  2205. $this->headers->addCacheControlDirective('s-maxage', $value);
  2206. }
  2207. public function getTtl()
  2208. {
  2209. if ($maxAge = $this->getMaxAge()) {
  2210. return $maxAge - $this->getAge();
  2211. }
  2212. return null;
  2213. }
  2214. public function setTtl($seconds)
  2215. {
  2216. $this->setSharedMaxAge($this->getAge() + $seconds);
  2217. }
  2218. public function setClientTtl($seconds)
  2219. {
  2220. $this->setMaxAge($this->getAge() + $seconds);
  2221. }
  2222. public function getLastModified()
  2223. {
  2224. return $this->headers->getDate('LastModified');
  2225. }
  2226. public function setLastModified(\DateTime $date = null)
  2227. {
  2228. if (null === $date) {
  2229. $this->headers->remove('Last-Modified');
  2230. } else {
  2231. $date = clone $date;
  2232. $date->setTimezone(new \DateTimeZone('UTC'));
  2233. $this->headers->set('Last-Modified', $date->format('D, d M Y H:i:s').' GMT');
  2234. }
  2235. }
  2236. public function getEtag()
  2237. {
  2238. return $this->headers->get('ETag');
  2239. }
  2240. public function setEtag($etag = null, $weak = false)
  2241. {
  2242. if (null === $etag) {
  2243. $this->headers->remove('Etag');
  2244. } else {
  2245. if (0 !== strpos($etag, '"')) {
  2246. $etag = '"'.$etag.'"';
  2247. }
  2248. $this->headers->set('ETag', (true === $weak ? 'W/' : '').$etag);
  2249. }
  2250. }
  2251. public function setCache(array $options)
  2252. {
  2253. if ($diff = array_diff(array_keys($options), array('etag', 'last_modified', 'max_age', 's_maxage', 'private', 'public'))) {
  2254. throw new \InvalidArgumentException(sprintf('Response does not support the following options: "%s".', implode('", "', array_keys($diff))));
  2255. }
  2256. if (isset($options['etag'])) {
  2257. $this->setEtag($options['etag']);
  2258. }
  2259. if (isset($options['last_modified'])) {
  2260. $this->setLastModified($options['last_modified']);
  2261. }
  2262. if (isset($options['max_age'])) {
  2263. $this->setMaxAge($options['max_age']);
  2264. }
  2265. if (isset($options['s_maxage'])) {
  2266. $this->setSharedMaxAge($options['s_maxage']);
  2267. }
  2268. if (isset($options['public'])) {
  2269. if ($options['public']) {
  2270. $this->setPublic();
  2271. } else {
  2272. $this->setPrivate();
  2273. }
  2274. }
  2275. if (isset($options['private'])) {
  2276. if ($options['private']) {
  2277. $this->setPrivate();
  2278. } else {
  2279. $this->setPublic();
  2280. }
  2281. }
  2282. }
  2283. public function setNotModified()
  2284. {
  2285. $this->setStatusCode(304);
  2286. $this->setContent(null);
  2287. foreach (array('Allow', 'Content-Encoding', 'Content-Language', 'Content-Length', 'Content-MD5', 'Content-Type', 'Last-Modified') as $header) {
  2288. $this->headers->remove($header);
  2289. }
  2290. }
  2291. public function setRedirect($url, $status = 302)
  2292. {
  2293. if (empty($url)) {
  2294. throw new \InvalidArgumentException('Cannot redirect to an empty URL.');
  2295. }
  2296. $this->setStatusCode($status);
  2297. if (!$this->isRedirect()) {
  2298. throw new \InvalidArgumentException(sprintf('The HTTP status code is not a redirect ("%s" given).', $status));
  2299. }
  2300. $this->headers->set('Location', $url);
  2301. $this->setContent(sprintf('<html><head><meta http-equiv="refresh" content="1;url=%s"/></head></html>', htmlspecialchars($url, ENT_QUOTES)));
  2302. }
  2303. public function hasVary()
  2304. {
  2305. return (Boolean) $this->headers->get('Vary');
  2306. }
  2307. public function getVary()
  2308. {
  2309. if (!$vary = $this->headers->get('Vary')) {
  2310. return array();
  2311. }
  2312. return is_array($vary) ? $vary : preg_split('/[\s,]+/', $vary);
  2313. }
  2314. public function setVary($headers, $replace = true)
  2315. {
  2316. $this->headers->set('Vary', $headers, $replace);
  2317. }
  2318. public function isNotModified(Request $request)
  2319. {
  2320. $lastModified = $request->headers->get('If-Modified-Since');
  2321. $notModified = false;
  2322. if ($etags = $request->getEtags()) {
  2323. $notModified = (in_array($this->getEtag(), $etags) || in_array('*', $etags)) && (!$lastModified || $this->headers->get('Last-Modified') == $lastModified);
  2324. } elseif ($lastModified) {
  2325. $notModified = $lastModified == $this->headers->get('Last-Modified');
  2326. }
  2327. if ($notModified) {
  2328. $this->setNotModified();
  2329. }
  2330. return $notModified;
  2331. }
  2332. public function isInvalid()
  2333. {
  2334. return $this->statusCode < 100 || $this->statusCode >= 600;
  2335. }
  2336. public function isInformational()
  2337. {
  2338. return $this->statusCode >= 100 && $this->statusCode < 200;
  2339. }
  2340. public function isSuccessful()
  2341. {
  2342. return $this->statusCode >= 200 && $this->statusCode < 300;
  2343. }
  2344. public function isRedirection()
  2345. {
  2346. return $this->statusCode >= 300 && $this->statusCode < 400;
  2347. }
  2348. public function isClientError()
  2349. {
  2350. return $this->statusCode >= 400 && $this->statusCode < 500;
  2351. }
  2352. public function isServerError()
  2353. {
  2354. return $this->statusCode >= 500 && $this->statusCode < 600;
  2355. }
  2356. public function isOk()
  2357. {
  2358. return 200 === $this->statusCode;
  2359. }
  2360. public function isForbidden()
  2361. {
  2362. return 403 === $this->statusCode;
  2363. }
  2364. public function isNotFound()
  2365. {
  2366. return 404 === $this->statusCode;
  2367. }
  2368. public function isRedirect()
  2369. {
  2370. return in_array($this->statusCode, array(301, 302, 303, 307));
  2371. }
  2372. public function isEmpty()
  2373. {
  2374. return in_array($this->statusCode, array(201, 204, 304));
  2375. }
  2376. public function isRedirected($location)
  2377. {
  2378. return $this->isRedirect() && $location == $this->headers->get('Location');
  2379. }
  2380. }
  2381. }
  2382. namespace Symfony\Component\ClassLoader
  2383. {
  2384. class UniversalClassLoader
  2385. {
  2386. protected $namespaces = array();
  2387. protected $prefixes = array();
  2388. protected $namespaceFallback = array();
  2389. protected $prefixFallback = array();
  2390. public function getNamespaces()
  2391. {
  2392. return $this->namespaces;
  2393. }
  2394. public function getPrefixes()
  2395. {
  2396. return $this->prefixes;
  2397. }
  2398. public function getNamespaceFallback()
  2399. {
  2400. return $this->namespaceFallback;
  2401. }
  2402. public function getPrefixFallback()
  2403. {
  2404. return $this->prefixFallback;
  2405. }
  2406. public function registerNamespaceFallback($dirs)
  2407. {
  2408. $this->namespaceFallback = (array) $dirs;
  2409. }
  2410. public function registerPrefixFallback($dirs)
  2411. {
  2412. $this->prefixFallback = (array) $dirs;
  2413. }
  2414. public function registerNamespaces(array $namespaces)
  2415. {
  2416. foreach ($namespaces as $namespace => $locations) {
  2417. $this->namespaces[$namespace] = (array) $locations;
  2418. }
  2419. }
  2420. public function registerNamespace($namespace, $paths)
  2421. {
  2422. $this->namespaces[$namespace] = (array) $paths;
  2423. }
  2424. public function registerPrefixes(array $classes)
  2425. {
  2426. foreach ($classes as $prefix => $locations) {
  2427. $this->prefixes[$prefix] = (array) $locations;
  2428. }
  2429. }
  2430. public function registerPrefix($prefix, $paths)
  2431. {
  2432. $this->prefixes[$prefix] = (array) $paths;
  2433. }
  2434. public function register($prepend = false)
  2435. {
  2436. spl_autoload_register(array($this, 'loadClass'), true, $prepend);
  2437. }
  2438. public function loadClass($class)
  2439. {
  2440. $class = ltrim($class, '\\');
  2441. if (false !== ($pos = strrpos($class, '\\'))) {
  2442. $namespace = substr($class, 0, $pos);
  2443. foreach ($this->namespaces as $ns => $dirs) {
  2444. foreach ($dirs as $dir) {
  2445. if (0 === strpos($namespace, $ns)) {
  2446. $className = substr($class, $pos + 1);
  2447. $file = $dir.DIRECTORY_SEPARATOR.str_replace('\\', DIRECTORY_SEPARATOR, $namespace).DIRECTORY_SEPARATOR.str_replace('_', DIRECTORY_SEPARATOR, $className).'.php';
  2448. if (file_exists($file)) {
  2449. require $file;
  2450. return;
  2451. }
  2452. }
  2453. }
  2454. }
  2455. foreach ($this->namespaceFallback as $dir) {
  2456. $file = $dir.DIRECTORY_SEPARATOR.str_replace('\\', DIRECTORY_SEPARATOR, $class).'.php';
  2457. if (file_exists($file)) {
  2458. require $file;
  2459. return;
  2460. }
  2461. }
  2462. } else {
  2463. foreach ($this->prefixes as $prefix => $dirs) {
  2464. foreach ($dirs as $dir) {
  2465. if (0 === strpos($class, $prefix)) {
  2466. $file = $dir.DIRECTORY_SEPARATOR.str_replace('_', DIRECTORY_SEPARATOR, $class).'.php';
  2467. if (file_exists($file)) {
  2468. require $file;
  2469. return;
  2470. }
  2471. }
  2472. }
  2473. }
  2474. foreach ($this->prefixFallback as $dir) {
  2475. $file = $dir.DIRECTORY_SEPARATOR.str_replace('_', DIRECTORY_SEPARATOR, $class).'.php';
  2476. if (file_exists($file)) {
  2477. require $file;
  2478. return;
  2479. }
  2480. }
  2481. }
  2482. }
  2483. }
  2484. }