| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413 | <?php/* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * 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. * * @author Fabien Potencier <fabien@symfony.com> * * @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 string     */    protected $languages;    /**     * @var string     */    protected $charsets;    /**     * @var string     */    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 string     */    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     *     * @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, and $_FILES.     *     * @api     */    public function overrideGlobals()    {        $_GET = $this->query->all();        $_POST = $this->request->all();        $_SERVER = $this->server->all();        $_COOKIE = $this->cookies->all();        // FIXME: populate $_FILES        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);            }        }        // FIXME: should read variables_order and request_order        // to know which globals to merge and in which order        $_REQUEST = array_merge($_GET, $_POST);    }    /**     * 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 type      $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'), 2);                return isset($clientIp[0]) ? trim($clientIp[0]) : '';            }        }        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'     *  * http://localhost/mysite/about?var=1  returns '/about'     *     * @return string     *     * @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    return '/web'     *     * @return string     *     * @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     *     * @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');        } else {            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     *     * @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);        return trim($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 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);    }    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 && 0 === strpos($requestUri, $baseUrl)) {            // full $baseUrl matches            return $baseUrl;        }        if ($baseUrl && 0 === strpos($requestUri, dirname($baseUrl))) {            // directory portion of $baseUrl matches            return rtrim(dirname($baseUrl), '/');        }        $truncatedRequestUri = $requestUri;        if (($pos = strpos($requestUri, '?')) !== false) {            $truncatedRequestUri = substr($requestUri, 0, $pos);        }        $basename = basename($baseUrl);        if (empty($basename) || !strpos($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(urldecode($requestUri), strlen(urldecode($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) {        }    }}
 |