* * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; use Symfony\Component\HttpFoundation\Session\SessionInterface; /** * Request represents an HTTP request. * * The methods dealing with URL accept / return a raw path (% encoded): * * getBasePath * * getBaseUrl * * getPathInfo * * getRequestUri * * getUri * * getUriForPath * * @author Fabien Potencier * * @api */ class Request { static protected $trustProxy = false; /** * @var \Symfony\Component\HttpFoundation\ParameterBag * * @api */ public $attributes; /** * @var \Symfony\Component\HttpFoundation\ParameterBag * * @api */ public $request; /** * @var \Symfony\Component\HttpFoundation\ParameterBag * * @api */ public $query; /** * @var \Symfony\Component\HttpFoundation\ServerBag * * @api */ public $server; /** * @var \Symfony\Component\HttpFoundation\FileBag * * @api */ public $files; /** * @var \Symfony\Component\HttpFoundation\ParameterBag * * @api */ public $cookies; /** * @var \Symfony\Component\HttpFoundation\HeaderBag * * @api */ public $headers; /** * @var string */ protected $content; /** * @var array */ protected $languages; /** * @var array */ protected $charsets; /** * @var array */ protected $acceptableContentTypes; /** * @var string */ protected $pathInfo; /** * @var string */ protected $requestUri; /** * @var string */ protected $baseUrl; /** * @var string */ protected $basePath; /** * @var string */ protected $method; /** * @var string */ protected $format; /** * @var \Symfony\Component\HttpFoundation\Session\SessionInterface */ protected $session; /** * @var string */ protected $locale; /** * @var string */ protected $defaultLocale = 'en'; /** * @var array */ static protected $formats; /** * Constructor. * * @param array $query The GET parameters * @param array $request The POST parameters * @param array $attributes The request attributes (parameters parsed from the PATH_INFO, ...) * @param array $cookies The COOKIE parameters * @param array $files The FILES parameters * @param array $server The SERVER parameters * @param string $content The raw body data * * @api */ public function __construct(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null) { $this->initialize($query, $request, $attributes, $cookies, $files, $server, $content); } /** * Sets the parameters for this request. * * This method also re-initializes all properties. * * @param array $query The GET parameters * @param array $request The POST parameters * @param array $attributes The request attributes (parameters parsed from the PATH_INFO, ...) * @param array $cookies The COOKIE parameters * @param array $files The FILES parameters * @param array $server The SERVER parameters * @param string $content The raw body data * * @api */ public function initialize(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null) { $this->request = new ParameterBag($request); $this->query = new ParameterBag($query); $this->attributes = new ParameterBag($attributes); $this->cookies = new ParameterBag($cookies); $this->files = new FileBag($files); $this->server = new ServerBag($server); $this->headers = new HeaderBag($this->server->getHeaders()); $this->content = $content; $this->languages = null; $this->charsets = null; $this->acceptableContentTypes = null; $this->pathInfo = null; $this->requestUri = null; $this->baseUrl = null; $this->basePath = null; $this->method = null; $this->format = null; } /** * Creates a new request with values from PHP's super globals. * * @return Request A new request * * @api */ static public function createFromGlobals() { $request = new static($_GET, $_POST, array(), $_COOKIE, $_FILES, $_SERVER); if (0 === strpos($request->server->get('CONTENT_TYPE'), 'application/x-www-form-urlencoded') && in_array(strtoupper($request->server->get('REQUEST_METHOD', 'GET')), array('PUT', 'DELETE', 'PATCH')) ) { parse_str($request->getContent(), $data); $request->request = new ParameterBag($data); } return $request; } /** * Creates a Request based on a given URI and configuration. * * @param string $uri The URI * @param string $method The HTTP method * @param array $parameters The request (GET) or query (POST) parameters * @param array $cookies The request cookies ($_COOKIE) * @param array $files The request files ($_FILES) * @param array $server The server parameters ($_SERVER) * @param string $content The raw body data * * @return Request A Request instance * * @api */ static public function create($uri, $method = 'GET', $parameters = array(), $cookies = array(), $files = array(), $server = array(), $content = null) { $defaults = array( 'SERVER_NAME' => 'localhost', 'SERVER_PORT' => 80, 'HTTP_HOST' => 'localhost', 'HTTP_USER_AGENT' => 'Symfony/2.X', 'HTTP_ACCEPT' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'HTTP_ACCEPT_LANGUAGE' => 'en-us,en;q=0.5', 'HTTP_ACCEPT_CHARSET' => 'ISO-8859-1,utf-8;q=0.7,*;q=0.7', 'REMOTE_ADDR' => '127.0.0.1', 'SCRIPT_NAME' => '', 'SCRIPT_FILENAME' => '', 'SERVER_PROTOCOL' => 'HTTP/1.1', 'REQUEST_TIME' => time(), ); $components = parse_url($uri); if (isset($components['host'])) { $defaults['SERVER_NAME'] = $components['host']; $defaults['HTTP_HOST'] = $components['host']; } if (isset($components['scheme'])) { if ('https' === $components['scheme']) { $defaults['HTTPS'] = 'on'; $defaults['SERVER_PORT'] = 443; } } if (isset($components['port'])) { $defaults['SERVER_PORT'] = $components['port']; $defaults['HTTP_HOST'] = $defaults['HTTP_HOST'].':'.$components['port']; } if (isset($components['user'])) { $defaults['PHP_AUTH_USER'] = $components['user']; } if (isset($components['pass'])) { $defaults['PHP_AUTH_PW'] = $components['pass']; } if (!isset($components['path'])) { $components['path'] = ''; } switch (strtoupper($method)) { case 'POST': case 'PUT': case 'DELETE': $defaults['CONTENT_TYPE'] = 'application/x-www-form-urlencoded'; case 'PATCH': $request = $parameters; $query = array(); break; default: $request = array(); $query = $parameters; break; } if (isset($components['query'])) { $queryString = html_entity_decode($components['query']); parse_str($queryString, $qs); if (is_array($qs)) { $query = array_replace($qs, $query); } } $queryString = http_build_query($query); $uri = $components['path'].($queryString ? '?'.$queryString : ''); $server = array_replace($defaults, $server, array( 'REQUEST_METHOD' => strtoupper($method), 'PATH_INFO' => '', 'REQUEST_URI' => $uri, 'QUERY_STRING' => $queryString, )); return new static($query, $request, array(), $cookies, $files, $server, $content); } /** * Clones a request and overrides some of its parameters. * * @param array $query The GET parameters * @param array $request The POST parameters * @param array $attributes The request attributes (parameters parsed from the PATH_INFO, ...) * @param array $cookies The COOKIE parameters * @param array $files The FILES parameters * @param array $server The SERVER parameters * * @return Request The duplicated request * * @api */ public function duplicate(array $query = null, array $request = null, array $attributes = null, array $cookies = null, array $files = null, array $server = null) { $dup = clone $this; if ($query !== null) { $dup->query = new ParameterBag($query); } if ($request !== null) { $dup->request = new ParameterBag($request); } if ($attributes !== null) { $dup->attributes = new ParameterBag($attributes); } if ($cookies !== null) { $dup->cookies = new ParameterBag($cookies); } if ($files !== null) { $dup->files = new FileBag($files); } if ($server !== null) { $dup->server = new ServerBag($server); $dup->headers = new HeaderBag($dup->server->getHeaders()); } $dup->languages = null; $dup->charsets = null; $dup->acceptableContentTypes = null; $dup->pathInfo = null; $dup->requestUri = null; $dup->baseUrl = null; $dup->basePath = null; $dup->method = null; $dup->format = null; return $dup; } /** * Clones the current request. * * Note that the session is not cloned as duplicated requests * are most of the time sub-requests of the main one. */ public function __clone() { $this->query = clone $this->query; $this->request = clone $this->request; $this->attributes = clone $this->attributes; $this->cookies = clone $this->cookies; $this->files = clone $this->files; $this->server = clone $this->server; $this->headers = clone $this->headers; } /** * Returns the request as a string. * * @return string The request */ public function __toString() { return sprintf('%s %s %s', $this->getMethod(), $this->getRequestUri(), $this->server->get('SERVER_PROTOCOL'))."\r\n". $this->headers."\r\n". $this->getContent(); } /** * Overrides the PHP global variables according to this request instance. * * It overrides $_GET, $_POST, $_REQUEST, $_SERVER, $_COOKIE. * $_FILES is never override, see rfc1867 * * @api */ public function overrideGlobals() { $_GET = $this->query->all(); $_POST = $this->request->all(); $_SERVER = $this->server->all(); $_COOKIE = $this->cookies->all(); foreach ($this->headers->all() as $key => $value) { $key = strtoupper(str_replace('-', '_', $key)); if (in_array($key, array('CONTENT_TYPE', 'CONTENT_LENGTH'))) { $_SERVER[$key] = implode(', ', $value); } else { $_SERVER['HTTP_'.$key] = implode(', ', $value); } } $request = array('g' => $_GET, 'p' => $_POST, 'c' => $_COOKIE); $request_order = ini_get('request_order') ?: ini_get('variable_order'); $request_order = preg_replace('#[^cgp]#', '', strtolower($request_order)) ?: 'gp'; $_REQUEST = array(); foreach (str_split($request_order) as $order) { $_REQUEST = array_merge($_REQUEST, $request[$order]); } } /** * Trusts $_SERVER entries coming from proxies. * * You should only call this method if your application * is hosted behind a reverse proxy that you manage. * * @api */ static public function trustProxyData() { self::$trustProxy = true; } /** * Returns true if $_SERVER entries coming from proxies are trusted, * false otherwise. * * @return boolean */ static public function isProxyTrusted() { return self::$trustProxy; } /** * Gets a "parameter" value. * * This method is mainly useful for libraries that want to provide some flexibility. * * Order of precedence: GET, PATH, POST, COOKIE * * Avoid using this method in controllers: * * * slow * * prefer to get from a "named" source * * It is better to explicity get request parameters from the appropriate * public property instead (query, request, attributes, ...). * * @param string $key the key * @param mixed $default the default value * @param Boolean $deep is parameter deep in multidimensional array * * @return mixed */ public function get($key, $default = null, $deep = false) { return $this->query->get($key, $this->attributes->get($key, $this->request->get($key, $default, $deep), $deep), $deep); } /** * Gets the Session. * * @return SessionInterface|null The session * * @api */ public function getSession() { return $this->session; } /** * Whether the request contains a Session which was started in one of the * previous requests. * * @return boolean * * @api */ public function hasPreviousSession() { // the check for $this->session avoids malicious users trying to fake a session cookie with proper name $sessionName = $this->hasSession() ? $this->session->getName() : null; return $this->cookies->has($sessionName) && $this->hasSession(); } /** * Whether the request contains a Session object. * * @return boolean * * @api */ public function hasSession() { return null !== $this->session; } /** * Sets the Session. * * @param SessionInterface $session The Session * * @api */ public function setSession(SessionInterface $session) { $this->session = $session; } /** * Returns the client IP address. * * @return string The client IP address * * @api */ public function getClientIp() { if (self::$trustProxy) { if ($this->server->has('HTTP_CLIENT_IP')) { return $this->server->get('HTTP_CLIENT_IP'); } elseif ($this->server->has('HTTP_X_FORWARDED_FOR')) { $clientIp = explode(',', $this->server->get('HTTP_X_FORWARDED_FOR')); foreach ($clientIp as $ipAddress) { $cleanIpAddress = trim($ipAddress); if (false !== filter_var($cleanIpAddress, FILTER_VALIDATE_IP)) { return $cleanIpAddress; } } return ''; } } return $this->server->get('REMOTE_ADDR'); } /** * Returns current script name. * * @return string * * @api */ public function getScriptName() { return $this->server->get('SCRIPT_NAME', $this->server->get('ORIG_SCRIPT_NAME', '')); } /** * Returns the path being requested relative to the executed script. * * The path info always starts with a /. * * Suppose this request is instantiated from /mysite on localhost: * * * http://localhost/mysite returns an empty string * * http://localhost/mysite/about returns '/about' * * htpp://localhost/mysite/enco%20ded returns '/enco%20ded' * * http://localhost/mysite/about?var=1 returns '/about' * * @return string The raw path (i.e. not urldecoded) * * @api */ public function getPathInfo() { if (null === $this->pathInfo) { $this->pathInfo = $this->preparePathInfo(); } return $this->pathInfo; } /** * Returns the root path from which this request is executed. * * Suppose that an index.php file instantiates this request object: * * * http://localhost/index.php returns an empty string * * http://localhost/index.php/page returns an empty string * * http://localhost/web/index.php returns '/web' * * http://localhost/we%20b/index.php returns '/we%20b' * * @return string The raw path (i.e. not urldecoded) * * @api */ public function getBasePath() { if (null === $this->basePath) { $this->basePath = $this->prepareBasePath(); } return $this->basePath; } /** * Returns the root url from which this request is executed. * * The base URL never ends with a /. * * This is similar to getBasePath(), except that it also includes the * script filename (e.g. index.php) if one exists. * * @return string The raw url (i.e. not urldecoded) * * @api */ public function getBaseUrl() { if (null === $this->baseUrl) { $this->baseUrl = $this->prepareBaseUrl(); } return $this->baseUrl; } /** * Gets the request's scheme. * * @return string * * @api */ public function getScheme() { return $this->isSecure() ? 'https' : 'http'; } /** * Returns the port on which the request is made. * * @return string * * @api */ public function getPort() { if (self::$trustProxy && $this->headers->has('X-Forwarded-Port')) { return $this->headers->get('X-Forwarded-Port'); } return $this->server->get('SERVER_PORT'); } /** * Returns the user. * * @return string|null */ public function getUser() { return $this->server->get('PHP_AUTH_USER'); } /** * Returns the password. * * @return string|null */ public function getPassword() { return $this->server->get('PHP_AUTH_PW'); } /** * Returns the HTTP host being requested. * * The port name will be appended to the host if it's non-standard. * * @return string * * @api */ public function getHttpHost() { $scheme = $this->getScheme(); $port = $this->getPort(); if (('http' == $scheme && $port == 80) || ('https' == $scheme && $port == 443)) { return $this->getHost(); } return $this->getHost().':'.$port; } /** * Returns the requested URI. * * @return string The raw URI (i.e. not urldecoded) * * @api */ public function getRequestUri() { if (null === $this->requestUri) { $this->requestUri = $this->prepareRequestUri(); } return $this->requestUri; } /** * Generates a normalized URI for the Request. * * @return string A normalized URI for the Request * * @see getQueryString() * * @api */ public function getUri() { $qs = $this->getQueryString(); if (null !== $qs) { $qs = '?'.$qs; } $auth = ''; if ($user = $this->getUser()) { $auth = $user; } if ($pass = $this->getPassword()) { $auth .= ":$pass"; } if ('' !== $auth) { $auth .= '@'; } return $this->getScheme().'://'.$auth.$this->getHttpHost().$this->getBaseUrl().$this->getPathInfo().$qs; } /** * Generates a normalized URI for the given path. * * @param string $path A path to use instead of the current one * * @return string The normalized URI for the path * * @api */ public function getUriForPath($path) { return $this->getScheme().'://'.$this->getHttpHost().$this->getBaseUrl().$path; } /** * Generates the normalized query string for the Request. * * It builds a normalized query string, where keys/value pairs are alphabetized * and have consistent escaping. * * @return string|null A normalized query string for the Request * * @api */ public function getQueryString() { if (!$qs = $this->server->get('QUERY_STRING')) { return null; } $parts = array(); $order = array(); foreach (explode('&', $qs) as $segment) { if (false === strpos($segment, '=')) { $parts[] = $segment; $order[] = $segment; } else { $tmp = explode('=', rawurldecode($segment), 2); $parts[] = rawurlencode($tmp[0]).'='.rawurlencode($tmp[1]); $order[] = $tmp[0]; } } array_multisort($order, SORT_ASC, $parts); return implode('&', $parts); } /** * Checks whether the request is secure or not. * * @return Boolean * * @api */ public function isSecure() { return ( (strtolower($this->server->get('HTTPS')) == 'on' || $this->server->get('HTTPS') == 1) || (self::$trustProxy && strtolower($this->headers->get('SSL_HTTPS')) == 'on' || $this->headers->get('SSL_HTTPS') == 1) || (self::$trustProxy && strtolower($this->headers->get('X_FORWARDED_PROTO')) == 'https') ); } /** * Returns the host name. * * @return string * * @api */ public function getHost() { if (self::$trustProxy && $host = $this->headers->get('X_FORWARDED_HOST')) { $elements = explode(',', $host); $host = trim($elements[count($elements) - 1]); } else { if (!$host = $this->headers->get('HOST')) { if (!$host = $this->server->get('SERVER_NAME')) { $host = $this->server->get('SERVER_ADDR', ''); } } } // Remove port number from host $host = preg_replace('/:\d+$/', '', $host); // host is lowercase as per RFC 952/2181 return trim(strtolower($host)); } /** * Sets the request method. * * @param string $method * * @api */ public function setMethod($method) { $this->method = null; $this->server->set('REQUEST_METHOD', $method); } /** * Gets the request method. * * The method is always an uppercased string. * * @return string The request method * * @api */ public function getMethod() { if (null === $this->method) { $this->method = strtoupper($this->server->get('REQUEST_METHOD', 'GET')); if ('POST' === $this->method) { $this->method = strtoupper($this->headers->get('X-HTTP-METHOD-OVERRIDE', $this->request->get('_method', 'POST'))); } } return $this->method; } /** * Gets the mime type associated with the format. * * @param string $format The format * * @return string The associated mime type (null if not found) * * @api */ public function getMimeType($format) { if (null === static::$formats) { static::initializeFormats(); } return isset(static::$formats[$format]) ? static::$formats[$format][0] : null; } /** * Gets the format associated with the mime type. * * @param string $mimeType The associated mime type * * @return string The format (null if not found) * * @api */ public function getFormat($mimeType) { if (false !== $pos = strpos($mimeType, ';')) { $mimeType = substr($mimeType, 0, $pos); } if (null === static::$formats) { static::initializeFormats(); } foreach (static::$formats as $format => $mimeTypes) { if (in_array($mimeType, (array) $mimeTypes)) { return $format; } } return null; } /** * Associates a format with mime types. * * @param string $format The format * @param string|array $mimeTypes The associated mime types (the preferred one must be the first as it will be used as the content type) * * @api */ public function setFormat($format, $mimeTypes) { if (null === static::$formats) { static::initializeFormats(); } static::$formats[$format] = is_array($mimeTypes) ? $mimeTypes : array($mimeTypes); } /** * Gets the request format. * * Here is the process to determine the format: * * * format defined by the user (with setRequestFormat()) * * _format request parameter * * $default * * @param string $default The default format * * @return string The request format * * @api */ public function getRequestFormat($default = 'html') { if (null === $this->format) { $this->format = $this->get('_format', $default); } return $this->format; } /** * Sets the request format. * * @param string $format The request format. * * @api */ public function setRequestFormat($format) { $this->format = $format; } /** * Gets the format associated with the request. * * @return string The format (null if no content type is present) * * @api */ public function getContentType() { return $this->getFormat($this->server->get('CONTENT_TYPE')); } /** * Sets the default locale. * * @param string $locale * * @api */ public function setDefaultLocale($locale) { $this->setPhpDefaultLocale($this->defaultLocale = $locale); } /** * Sets the locale. * * @param string $locale * * @api */ public function setLocale($locale) { $this->setPhpDefaultLocale($this->locale = $locale); } /** * Get the locale. * * @return string */ public function getLocale() { return null === $this->locale ? $this->defaultLocale : $this->locale; } /** * Checks if the request method is of specified type. * * @param string $method Uppercase request method (GET, POST etc). * * @return Boolean */ public function isMethod($method) { return $this->getMethod() === strtoupper($method); } /** * Checks whether the method is safe or not. * * @return Boolean * * @api */ public function isMethodSafe() { return in_array($this->getMethod(), array('GET', 'HEAD')); } /** * Returns the request body content. * * @param Boolean $asResource If true, a resource will be returned * * @return string|resource The request body content or a resource to read the body stream. */ public function getContent($asResource = false) { if (false === $this->content || (true === $asResource && null !== $this->content)) { throw new \LogicException('getContent() can only be called once when using the resource return type.'); } if (true === $asResource) { $this->content = false; return fopen('php://input', 'rb'); } if (null === $this->content) { $this->content = file_get_contents('php://input'); } return $this->content; } /** * Gets the Etags. * * @return array The entity tags */ public function getETags() { return preg_split('/\s*,\s*/', $this->headers->get('if_none_match'), null, PREG_SPLIT_NO_EMPTY); } /** * @return Boolean */ public function isNoCache() { return $this->headers->hasCacheControlDirective('no-cache') || 'no-cache' == $this->headers->get('Pragma'); } /** * Returns the preferred language. * * @param array $locales An array of ordered available locales * * @return string|null The preferred locale * * @api */ public function getPreferredLanguage(array $locales = null) { $preferredLanguages = $this->getLanguages(); if (empty($locales)) { return isset($preferredLanguages[0]) ? $preferredLanguages[0] : null; } if (!$preferredLanguages) { return $locales[0]; } $preferredLanguages = array_values(array_intersect($preferredLanguages, $locales)); return isset($preferredLanguages[0]) ? $preferredLanguages[0] : $locales[0]; } /** * Gets a list of languages acceptable by the client browser. * * @return array Languages ordered in the user browser preferences * * @api */ public function getLanguages() { if (null !== $this->languages) { return $this->languages; } $languages = $this->splitHttpAcceptHeader($this->headers->get('Accept-Language')); $this->languages = array(); foreach ($languages as $lang => $q) { if (strstr($lang, '-')) { $codes = explode('-', $lang); if ($codes[0] == 'i') { // Language not listed in ISO 639 that are not variants // of any listed language, which can be registered with the // i-prefix, such as i-cherokee if (count($codes) > 1) { $lang = $codes[1]; } } else { for ($i = 0, $max = count($codes); $i < $max; $i++) { if ($i == 0) { $lang = strtolower($codes[0]); } else { $lang .= '_'.strtoupper($codes[$i]); } } } } $this->languages[] = $lang; } return $this->languages; } /** * Gets a list of charsets acceptable by the client browser. * * @return array List of charsets in preferable order * * @api */ public function getCharsets() { if (null !== $this->charsets) { return $this->charsets; } return $this->charsets = array_keys($this->splitHttpAcceptHeader($this->headers->get('Accept-Charset'))); } /** * Gets a list of content types acceptable by the client browser * * @return array List of content types in preferable order * * @api */ public function getAcceptableContentTypes() { if (null !== $this->acceptableContentTypes) { return $this->acceptableContentTypes; } return $this->acceptableContentTypes = array_keys($this->splitHttpAcceptHeader($this->headers->get('Accept'))); } /** * Returns true if the request is a XMLHttpRequest. * * It works if your JavaScript library set an X-Requested-With HTTP header. * It is known to work with Prototype, Mootools, jQuery. * * @return Boolean true if the request is an XMLHttpRequest, false otherwise * * @api */ public function isXmlHttpRequest() { return 'XMLHttpRequest' == $this->headers->get('X-Requested-With'); } /** * Splits an Accept-* HTTP header. * * @param string $header Header to split * * @return array Array indexed by the values of the Accept-* header in preferred order */ public function splitHttpAcceptHeader($header) { if (!$header) { return array(); } $values = array(); foreach (array_filter(explode(',', $header)) as $value) { // Cut off any q-value that might come after a semi-colon if (preg_match('/;\s*(q=.*$)/', $value, $match)) { $q = (float) substr(trim($match[1]), 2); $value = trim(substr($value, 0, -strlen($match[0]))); } else { $q = 1; } if (0 < $q) { $values[trim($value)] = $q; } } arsort($values); reset($values); return $values; } /* * The following methods are derived from code of the Zend Framework (1.10dev - 2010-01-24) * * Code subject to the new BSD license (http://framework.zend.com/license/new-bsd). * * Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) */ protected function prepareRequestUri() { $requestUri = ''; if ($this->headers->has('X_REWRITE_URL') && false !== stripos(PHP_OS, 'WIN')) { // check this first so IIS will catch $requestUri = $this->headers->get('X_REWRITE_URL'); } elseif ($this->server->get('IIS_WasUrlRewritten') == '1' && $this->server->get('UNENCODED_URL') != '') { // IIS7 with URL Rewrite: make sure we get the unencoded url (double slash problem) $requestUri = $this->server->get('UNENCODED_URL'); } elseif ($this->server->has('REQUEST_URI')) { $requestUri = $this->server->get('REQUEST_URI'); // HTTP proxy reqs setup request uri with scheme and host [and port] + the url path, only use url path $schemeAndHttpHost = $this->getScheme().'://'.$this->getHttpHost(); if (strpos($requestUri, $schemeAndHttpHost) === 0) { $requestUri = substr($requestUri, strlen($schemeAndHttpHost)); } } elseif ($this->server->has('ORIG_PATH_INFO')) { // IIS 5.0, PHP as CGI $requestUri = $this->server->get('ORIG_PATH_INFO'); if ($this->server->get('QUERY_STRING')) { $requestUri .= '?'.$this->server->get('QUERY_STRING'); } } return $requestUri; } /** * Prepares the base URL. * * @return string */ protected function prepareBaseUrl() { $filename = basename($this->server->get('SCRIPT_FILENAME')); if (basename($this->server->get('SCRIPT_NAME')) === $filename) { $baseUrl = $this->server->get('SCRIPT_NAME'); } elseif (basename($this->server->get('PHP_SELF')) === $filename) { $baseUrl = $this->server->get('PHP_SELF'); } elseif (basename($this->server->get('ORIG_SCRIPT_NAME')) === $filename) { $baseUrl = $this->server->get('ORIG_SCRIPT_NAME'); // 1and1 shared hosting compatibility } else { // Backtrack up the script_filename to find the portion matching // php_self $path = $this->server->get('PHP_SELF', ''); $file = $this->server->get('SCRIPT_FILENAME', ''); $segs = explode('/', trim($file, '/')); $segs = array_reverse($segs); $index = 0; $last = count($segs); $baseUrl = ''; do { $seg = $segs[$index]; $baseUrl = '/'.$seg.$baseUrl; ++$index; } while (($last > $index) && (false !== ($pos = strpos($path, $baseUrl))) && (0 != $pos)); } // Does the baseUrl have anything in common with the request_uri? $requestUri = $this->getRequestUri(); if ($baseUrl && false !== $prefix = $this->getUrlencodedPrefix($requestUri, $baseUrl)) { // full $baseUrl matches return $prefix; } if ($baseUrl && false !== $prefix = $this->getUrlencodedPrefix($requestUri, dirname($baseUrl))) { // directory portion of $baseUrl matches return rtrim($prefix, '/'); } $truncatedRequestUri = $requestUri; if (($pos = strpos($requestUri, '?')) !== false) { $truncatedRequestUri = substr($requestUri, 0, $pos); } $basename = basename($baseUrl); if (empty($basename) || !strpos(rawurldecode($truncatedRequestUri), $basename)) { // no match whatsoever; set it blank return ''; } // If using mod_rewrite or ISAPI_Rewrite strip the script filename // out of baseUrl. $pos !== 0 makes sure it is not matching a value // from PATH_INFO or QUERY_STRING if ((strlen($requestUri) >= strlen($baseUrl)) && ((false !== ($pos = strpos($requestUri, $baseUrl))) && ($pos !== 0))) { $baseUrl = substr($requestUri, 0, $pos + strlen($baseUrl)); } return rtrim($baseUrl, '/'); } /** * Prepares the base path. * * @return string base path */ protected function prepareBasePath() { $filename = basename($this->server->get('SCRIPT_FILENAME')); $baseUrl = $this->getBaseUrl(); if (empty($baseUrl)) { return ''; } if (basename($baseUrl) === $filename) { $basePath = dirname($baseUrl); } else { $basePath = $baseUrl; } if ('\\' === DIRECTORY_SEPARATOR) { $basePath = str_replace('\\', '/', $basePath); } return rtrim($basePath, '/'); } /** * Prepares the path info. * * @return string path info */ protected function preparePathInfo() { $baseUrl = $this->getBaseUrl(); if (null === ($requestUri = $this->getRequestUri())) { return '/'; } $pathInfo = '/'; // Remove the query string from REQUEST_URI if ($pos = strpos($requestUri, '?')) { $requestUri = substr($requestUri, 0, $pos); } if ((null !== $baseUrl) && (false === ($pathInfo = substr($requestUri, strlen($baseUrl))))) { // If substr() returns false then PATH_INFO is set to an empty string return '/'; } elseif (null === $baseUrl) { return $requestUri; } return (string) $pathInfo; } /** * Initializes HTTP request formats. */ static protected function initializeFormats() { static::$formats = array( 'html' => array('text/html', 'application/xhtml+xml'), 'txt' => array('text/plain'), 'js' => array('application/javascript', 'application/x-javascript', 'text/javascript'), 'css' => array('text/css'), 'json' => array('application/json', 'application/x-json'), 'xml' => array('text/xml', 'application/xml', 'application/x-xml'), 'rdf' => array('application/rdf+xml'), 'atom' => array('application/atom+xml'), 'rss' => array('application/rss+xml'), ); } /** * Sets the default PHP locale. * * @param string $locale */ private function setPhpDefaultLocale($locale) { // if either the class Locale doesn't exist, or an exception is thrown when // setting the default locale, the intl module is not installed, and // the call can be ignored: try { if (class_exists('Locale', false)) { \Locale::setDefault($locale); } } catch (\Exception $e) { } } /* * Returns the prefix as encoded in the string when the string starts with * the given prefix, false otherwise. * * @param string $string The urlencoded string * @param string $prefix The prefix not encoded * * @return string|false The prefix as it is encoded in $string, or false */ private function getUrlencodedPrefix($string, $prefix) { if (0 !== strpos(rawurldecode($string), $prefix)) { return false; } $len = strlen($prefix); if (preg_match("#^(%[[:xdigit:]]{2}|.){{$len}}#", $string, $match)) { return $match[0]; } return false; } }