<?php /** * Zend Framework * * LICENSE * * This source file is subject to the new BSD license that is bundled * with this package in the file LICENSE.txt. * It is also available through the world-wide-web at this URL: * http://framework.zend.com/license/new-bsd * If you did not receive a copy of the license and are unable to * obtain it through the world-wide-web, please send an email * to license@zend.com so we can send you a copy immediately. * * @category Zend * @package Zend_Controller * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id$ */ /** @see Zend_Controller_Request_Abstract */ require_once 'Zend/Controller/Request/Abstract.php'; /** @see Zend_Uri */ require_once 'Zend/Uri.php'; /** * Zend_Controller_Request_Http * * HTTP request object for use with Zend_Controller family. * * @uses Zend_Controller_Request_Abstract * @package Zend_Controller * @subpackage Request */ class Zend_Controller_Request_Http extends Zend_Controller_Request_Abstract { /** * Scheme for http * */ const SCHEME_HTTP = 'http'; /** * Scheme for https * */ const SCHEME_HTTPS = 'https'; /** * Allowed parameter sources * @var array */ protected $_paramSources = array('_GET', '_POST'); /** * REQUEST_URI * @var string; */ protected $_requestUri; /** * Base URL of request * @var string */ protected $_baseUrl = null; /** * Base path of request * @var string */ protected $_basePath = null; /** * PATH_INFO * @var string */ protected $_pathInfo = ''; /** * Instance parameters * @var array */ protected $_params = array(); /** * Raw request body * @var string|false */ protected $_rawBody; /** * Alias keys for request parameters * @var array */ protected $_aliases = array(); /** * Constructor * * If a $uri is passed, the object will attempt to populate itself using * that information. * * @param string|Zend_Uri $uri * @return void * @throws Zend_Controller_Request_Exception when invalid URI passed */ public function __construct($uri = null) { if (null !== $uri) { if (!$uri instanceof Zend_Uri) { $uri = Zend_Uri::factory($uri); } if ($uri->valid()) { $path = $uri->getPath(); $query = $uri->getQuery(); if (!empty($query)) { $path .= '?' . $query; } $this->setRequestUri($path); } else { require_once 'Zend/Controller/Request/Exception.php'; throw new Zend_Controller_Request_Exception('Invalid URI provided to constructor'); } } else { $this->setRequestUri(); } } /** * Access values contained in the superglobals as public members * Order of precedence: 1. GET, 2. POST, 3. COOKIE, 4. SERVER, 5. ENV * * @see http://msdn.microsoft.com/en-us/library/system.web.httprequest.item.aspx * @param string $key * @return mixed */ public function __get($key) { switch (true) { case isset($this->_params[$key]): return $this->_params[$key]; case isset($_GET[$key]): return $_GET[$key]; case isset($_POST[$key]): return $_POST[$key]; case isset($_COOKIE[$key]): return $_COOKIE[$key]; case ($key == 'REQUEST_URI'): return $this->getRequestUri(); case ($key == 'PATH_INFO'): return $this->getPathInfo(); case isset($_SERVER[$key]): return $_SERVER[$key]; case isset($_ENV[$key]): return $_ENV[$key]; default: return null; } } /** * Alias to __get * * @param string $key * @return mixed */ public function get($key) { return $this->__get($key); } /** * Set values * * In order to follow {@link __get()}, which operates on a number of * superglobals, setting values through overloading is not allowed and will * raise an exception. Use setParam() instead. * * @param string $key * @param mixed $value * @return void * @throws Zend_Controller_Request_Exception */ public function __set($key, $value) { require_once 'Zend/Controller/Request/Exception.php'; throw new Zend_Controller_Request_Exception('Setting values in superglobals not allowed; please use setParam()'); } /** * Alias to __set() * * @param string $key * @param mixed $value * @return void */ public function set($key, $value) { return $this->__set($key, $value); } /** * Check to see if a property is set * * @param string $key * @return boolean */ public function __isset($key) { switch (true) { case isset($this->_params[$key]): return true; case isset($_GET[$key]): return true; case isset($_POST[$key]): return true; case isset($_COOKIE[$key]): return true; case isset($_SERVER[$key]): return true; case isset($_ENV[$key]): return true; default: return false; } } /** * Alias to __isset() * * @param string $key * @return boolean */ public function has($key) { return $this->__isset($key); } /** * Set GET values * * @param string|array $spec * @param null|mixed $value * @return Zend_Controller_Request_Http */ public function setQuery($spec, $value = null) { if ((null === $value) && !is_array($spec)) { require_once 'Zend/Controller/Exception.php'; throw new Zend_Controller_Exception('Invalid value passed to setQuery(); must be either array of values or key/value pair'); } if ((null === $value) && is_array($spec)) { foreach ($spec as $key => $value) { $this->setQuery($key, $value); } return $this; } $_GET[(string) $spec] = $value; return $this; } /** * Retrieve a member of the $_GET superglobal * * If no $key is passed, returns the entire $_GET array. * * @todo How to retrieve from nested arrays * @param string $key * @param mixed $default Default value to use if key not found * @return mixed Returns null if key does not exist */ public function getQuery($key = null, $default = null) { if (null === $key) { return $_GET; } return (isset($_GET[$key])) ? $_GET[$key] : $default; } /** * Set POST values * * @param string|array $spec * @param null|mixed $value * @return Zend_Controller_Request_Http */ public function setPost($spec, $value = null) { if ((null === $value) && !is_array($spec)) { require_once 'Zend/Controller/Exception.php'; throw new Zend_Controller_Exception('Invalid value passed to setPost(); must be either array of values or key/value pair'); } if ((null === $value) && is_array($spec)) { foreach ($spec as $key => $value) { $this->setPost($key, $value); } return $this; } $_POST[(string) $spec] = $value; return $this; } /** * Retrieve a member of the $_POST superglobal * * If no $key is passed, returns the entire $_POST array. * * @todo How to retrieve from nested arrays * @param string $key * @param mixed $default Default value to use if key not found * @return mixed Returns null if key does not exist */ public function getPost($key = null, $default = null) { if (null === $key) { return $_POST; } return (isset($_POST[$key])) ? $_POST[$key] : $default; } /** * Retrieve a member of the $_COOKIE superglobal * * If no $key is passed, returns the entire $_COOKIE array. * * @todo How to retrieve from nested arrays * @param string $key * @param mixed $default Default value to use if key not found * @return mixed Returns null if key does not exist */ public function getCookie($key = null, $default = null) { if (null === $key) { return $_COOKIE; } return (isset($_COOKIE[$key])) ? $_COOKIE[$key] : $default; } /** * Retrieve a member of the $_SERVER superglobal * * If no $key is passed, returns the entire $_SERVER array. * * @param string $key * @param mixed $default Default value to use if key not found * @return mixed Returns null if key does not exist */ public function getServer($key = null, $default = null) { if (null === $key) { return $_SERVER; } return (isset($_SERVER[$key])) ? $_SERVER[$key] : $default; } /** * Retrieve a member of the $_ENV superglobal * * If no $key is passed, returns the entire $_ENV array. * * @param string $key * @param mixed $default Default value to use if key not found * @return mixed Returns null if key does not exist */ public function getEnv($key = null, $default = null) { if (null === $key) { return $_ENV; } return (isset($_ENV[$key])) ? $_ENV[$key] : $default; } /** * Set the REQUEST_URI on which the instance operates * * If no request URI is passed, uses the value in $_SERVER['REQUEST_URI'], * $_SERVER['HTTP_X_REWRITE_URL'], or $_SERVER['ORIG_PATH_INFO'] + $_SERVER['QUERY_STRING']. * * @param string $requestUri * @return Zend_Controller_Request_Http */ public function setRequestUri($requestUri = null) { if ($requestUri === null) { if (isset($_SERVER['HTTP_X_ORIGINAL_URL'])) { // IIS with Microsoft Rewrite Module $requestUri = $_SERVER['HTTP_X_ORIGINAL_URL']; } elseif (isset($_SERVER['HTTP_X_REWRITE_URL'])) { // IIS with ISAPI_Rewrite $requestUri = $_SERVER['HTTP_X_REWRITE_URL']; } elseif ( // IIS7 with URL Rewrite: make sure we get the unencoded url (double slash problem) isset($_SERVER['IIS_WasUrlRewritten']) && $_SERVER['IIS_WasUrlRewritten'] == '1' && isset($_SERVER['UNENCODED_URL']) && $_SERVER['UNENCODED_URL'] != '' ) { $requestUri = $_SERVER['UNENCODED_URL']; } elseif (isset($_SERVER['REQUEST_URI'])) { $requestUri = $_SERVER['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 (isset($_SERVER['ORIG_PATH_INFO'])) { // IIS 5.0, PHP as CGI $requestUri = $_SERVER['ORIG_PATH_INFO']; if (!empty($_SERVER['QUERY_STRING'])) { $requestUri .= '?' . $_SERVER['QUERY_STRING']; } } else { return $this; } } elseif (!is_string($requestUri)) { return $this; } else { // Set GET items, if available if (false !== ($pos = strpos($requestUri, '?'))) { // Get key => value pairs and set $_GET $query = substr($requestUri, $pos + 1); parse_str($query, $vars); $this->setQuery($vars); } } $this->_requestUri = $requestUri; return $this; } /** * Returns the REQUEST_URI taking into account * platform differences between Apache and IIS * * @return string */ public function getRequestUri() { if (empty($this->_requestUri)) { $this->setRequestUri(); } return $this->_requestUri; } /** * Set the base URL of the request; i.e., the segment leading to the script name * * E.g.: * - /admin * - /myapp * - /subdir/index.php * * Do not use the full URI when providing the base. The following are * examples of what not to use: * - http://example.com/admin (should be just /admin) * - http://example.com/subdir/index.php (should be just /subdir/index.php) * * If no $baseUrl is provided, attempts to determine the base URL from the * environment, using SCRIPT_FILENAME, SCRIPT_NAME, PHP_SELF, and * ORIG_SCRIPT_NAME in its determination. * * @param mixed $baseUrl * @return Zend_Controller_Request_Http */ public function setBaseUrl($baseUrl = null) { if ((null !== $baseUrl) && !is_string($baseUrl)) { return $this; } if ($baseUrl === null) { $filename = (isset($_SERVER['SCRIPT_FILENAME'])) ? basename($_SERVER['SCRIPT_FILENAME']) : ''; if (isset($_SERVER['SCRIPT_NAME']) && basename($_SERVER['SCRIPT_NAME']) === $filename) { $baseUrl = $_SERVER['SCRIPT_NAME']; } elseif (isset($_SERVER['PHP_SELF']) && basename($_SERVER['PHP_SELF']) === $filename) { $baseUrl = $_SERVER['PHP_SELF']; } elseif (isset($_SERVER['ORIG_SCRIPT_NAME']) && basename($_SERVER['ORIG_SCRIPT_NAME']) === $filename) { $baseUrl = $_SERVER['ORIG_SCRIPT_NAME']; // 1and1 shared hosting compatibility } else { // Backtrack up the script_filename to find the portion matching // php_self $path = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : ''; $file = isset($_SERVER['SCRIPT_FILENAME']) ? $_SERVER['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 (0 === strpos($requestUri, $baseUrl)) { // full $baseUrl matches $this->_baseUrl = $baseUrl; return $this; } if (0 === strpos($requestUri, dirname($baseUrl))) { // directory portion of $baseUrl matches $this->_baseUrl = rtrim(dirname($baseUrl), '/'); return $this; } $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 $this->_baseUrl = ''; return $this; } // 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)); } } $this->_baseUrl = rtrim($baseUrl, '/'); return $this; } /** * Everything in REQUEST_URI before PATH_INFO * <form action="<?=$baseUrl?>/news/submit" method="POST"/> * * @return string */ public function getBaseUrl($raw = false) { if (null === $this->_baseUrl) { $this->setBaseUrl(); } return (($raw == false) ? urldecode($this->_baseUrl) : $this->_baseUrl); } /** * Set the base path for the URL * * @param string|null $basePath * @return Zend_Controller_Request_Http */ public function setBasePath($basePath = null) { if ($basePath === null) { $filename = (isset($_SERVER['SCRIPT_FILENAME'])) ? basename($_SERVER['SCRIPT_FILENAME']) : ''; $baseUrl = $this->getBaseUrl(); if (empty($baseUrl)) { $this->_basePath = ''; return $this; } if (basename($baseUrl) === $filename) { $basePath = dirname($baseUrl); } else { $basePath = $baseUrl; } } if (substr(PHP_OS, 0, 3) === 'WIN') { $basePath = str_replace('\\', '/', $basePath); } $this->_basePath = rtrim($basePath, '/'); return $this; } /** * Everything in REQUEST_URI before PATH_INFO not including the filename * <img src="<?=$basePath?>/images/zend.png"/> * * @return string */ public function getBasePath() { if (null === $this->_basePath) { $this->setBasePath(); } return $this->_basePath; } /** * Set the PATH_INFO string * * @param string|null $pathInfo * @return Zend_Controller_Request_Http */ public function setPathInfo($pathInfo = null) { if ($pathInfo === null) { $baseUrl = $this->getBaseUrl(); // this actually calls setBaseUrl() & setRequestUri() $baseUrlRaw = $this->getBaseUrl(false); $baseUrlEncoded = urlencode($baseUrlRaw); if (null === ($requestUri = $this->getRequestUri())) { return $this; } // Remove the query string from REQUEST_URI if ($pos = strpos($requestUri, '?')) { $requestUri = substr($requestUri, 0, $pos); } if (!empty($baseUrl) || !empty($baseUrlRaw)) { if (strpos($requestUri, $baseUrl) === 0) { $pathInfo = substr($requestUri, strlen($baseUrl)); } elseif (strpos($requestUri, $baseUrlRaw) === 0) { $pathInfo = substr($requestUri, strlen($baseUrlRaw)); } elseif (strpos($requestUri, $baseUrlEncoded) === 0) { $pathInfo = substr($requestUri, strlen($baseUrlEncoded)); } else { $pathInfo = $requestUri; } } else { $pathInfo = $requestUri; } } $this->_pathInfo = (string) $pathInfo; return $this; } /** * Returns everything between the BaseUrl and QueryString. * This value is calculated instead of reading PATH_INFO * directly from $_SERVER due to cross-platform differences. * * @return string */ public function getPathInfo() { if (empty($this->_pathInfo)) { $this->setPathInfo(); } return $this->_pathInfo; } /** * Set allowed parameter sources * * Can be empty array, or contain one or more of '_GET' or '_POST'. * * @param array $paramSoures * @return Zend_Controller_Request_Http */ public function setParamSources(array $paramSources = array()) { $this->_paramSources = $paramSources; return $this; } /** * Get list of allowed parameter sources * * @return array */ public function getParamSources() { return $this->_paramSources; } /** * Set a userland parameter * * Uses $key to set a userland parameter. If $key is an alias, the actual * key will be retrieved and used to set the parameter. * * @param mixed $key * @param mixed $value * @return Zend_Controller_Request_Http */ public function setParam($key, $value) { $key = (null !== ($alias = $this->getAlias($key))) ? $alias : $key; parent::setParam($key, $value); return $this; } /** * Retrieve a parameter * * Retrieves a parameter from the instance. Priority is in the order of * userland parameters (see {@link setParam()}), $_GET, $_POST. If a * parameter matching the $key is not found, null is returned. * * If the $key is an alias, the actual key aliased will be used. * * @param mixed $key * @param mixed $default Default value to use if key not found * @return mixed */ public function getParam($key, $default = null) { $keyName = (null !== ($alias = $this->getAlias($key))) ? $alias : $key; $paramSources = $this->getParamSources(); if (isset($this->_params[$keyName])) { return $this->_params[$keyName]; } elseif (in_array('_GET', $paramSources) && (isset($_GET[$keyName]))) { return $_GET[$keyName]; } elseif (in_array('_POST', $paramSources) && (isset($_POST[$keyName]))) { return $_POST[$keyName]; } return $default; } /** * Retrieve an array of parameters * * Retrieves a merged array of parameters, with precedence of userland * params (see {@link setParam()}), $_GET, $_POST (i.e., values in the * userland params will take precedence over all others). * * @return array */ public function getParams() { $return = $this->_params; $paramSources = $this->getParamSources(); if (in_array('_GET', $paramSources) && isset($_GET) && is_array($_GET) ) { $return += $_GET; } if (in_array('_POST', $paramSources) && isset($_POST) && is_array($_POST) ) { $return += $_POST; } return $return; } /** * Set parameters * * Set one or more parameters. Parameters are set as userland parameters, * using the keys specified in the array. * * @param array $params * @return Zend_Controller_Request_Http */ public function setParams(array $params) { foreach ($params as $key => $value) { $this->setParam($key, $value); } return $this; } /** * Set a key alias * * Set an alias used for key lookups. $name specifies the alias, $target * specifies the actual key to use. * * @param string $name * @param string $target * @return Zend_Controller_Request_Http */ public function setAlias($name, $target) { $this->_aliases[$name] = $target; return $this; } /** * Retrieve an alias * * Retrieve the actual key represented by the alias $name. * * @param string $name * @return string|null Returns null when no alias exists */ public function getAlias($name) { if (isset($this->_aliases[$name])) { return $this->_aliases[$name]; } return null; } /** * Retrieve the list of all aliases * * @return array */ public function getAliases() { return $this->_aliases; } /** * Return the method by which the request was made * * @return string */ public function getMethod() { return $this->getServer('REQUEST_METHOD'); } /** * Was the request made by POST? * * @return boolean */ public function isPost() { if ('POST' == $this->getMethod()) { return true; } return false; } /** * Was the request made by GET? * * @return boolean */ public function isGet() { if ('GET' == $this->getMethod()) { return true; } return false; } /** * Was the request made by PUT? * * @return boolean */ public function isPut() { if ('PUT' == $this->getMethod()) { return true; } return false; } /** * Was the request made by DELETE? * * @return boolean */ public function isDelete() { if ('DELETE' == $this->getMethod()) { return true; } return false; } /** * Was the request made by HEAD? * * @return boolean */ public function isHead() { if ('HEAD' == $this->getMethod()) { return true; } return false; } /** * Was the request made by OPTIONS? * * @return boolean */ public function isOptions() { if ('OPTIONS' == $this->getMethod()) { return true; } return false; } /** * Is the request a Javascript XMLHttpRequest? * * Should work with Prototype/Script.aculo.us, possibly others. * * @return boolean */ public function isXmlHttpRequest() { return ($this->getHeader('X_REQUESTED_WITH') == 'XMLHttpRequest'); } /** * Is this a Flash request? * * @return boolean */ public function isFlashRequest() { $header = strtolower($this->getHeader('USER_AGENT')); return (strstr($header, ' flash')) ? true : false; } /** * Is https secure request * * @return boolean */ public function isSecure() { return ($this->getScheme() === self::SCHEME_HTTPS); } /** * Return the raw body of the request, if present * * @return string|false Raw body, or false if not present */ public function getRawBody() { if (null === $this->_rawBody) { $body = file_get_contents('php://input'); if (strlen(trim($body)) > 0) { $this->_rawBody = $body; } else { $this->_rawBody = false; } } return $this->_rawBody; } /** * Return the value of the given HTTP header. Pass the header name as the * plain, HTTP-specified header name. Ex.: Ask for 'Accept' to get the * Accept header, 'Accept-Encoding' to get the Accept-Encoding header. * * @param string $header HTTP header name * @return string|false HTTP header value, or false if not found * @throws Zend_Controller_Request_Exception */ public function getHeader($header) { if (empty($header)) { require_once 'Zend/Controller/Request/Exception.php'; throw new Zend_Controller_Request_Exception('An HTTP header name is required'); } // Try to get it from the $_SERVER array first $temp = 'HTTP_' . strtoupper(str_replace('-', '_', $header)); if (isset($_SERVER[$temp])) { return $_SERVER[$temp]; } // This seems to be the only way to get the Authorization header on // Apache if (function_exists('apache_request_headers')) { $headers = apache_request_headers(); if (isset($headers[$header])) { return $headers[$header]; } $header = strtolower($header); foreach ($headers as $key => $value) { if (strtolower($key) == $header) { return $value; } } } return false; } /** * Get the request URI scheme * * @return string */ public function getScheme() { return ($this->getServer('HTTPS') == 'on') ? self::SCHEME_HTTPS : self::SCHEME_HTTP; } /** * Get the HTTP host. * * "Host" ":" host [ ":" port ] ; Section 3.2.2 * Note the HTTP Host header is not the same as the URI host. * It includes the port while the URI host doesn't. * * @return string */ public function getHttpHost() { $host = $this->getServer('HTTP_HOST'); if (!empty($host)) { return $host; } $scheme = $this->getScheme(); $name = $this->getServer('SERVER_NAME'); $port = $this->getServer('SERVER_PORT'); if(null === $name) { return ''; } elseif (($scheme == self::SCHEME_HTTP && $port == 80) || ($scheme == self::SCHEME_HTTPS && $port == 443)) { return $name; } else { return $name . ':' . $port; } } /** * Get the client's IP addres * * @param boolean $checkProxy * @return string */ public function getClientIp($checkProxy = true) { if ($checkProxy && $this->getServer('HTTP_CLIENT_IP') != null) { $ip = $this->getServer('HTTP_CLIENT_IP'); } else if ($checkProxy && $this->getServer('HTTP_X_FORWARDED_FOR') != null) { $ip = $this->getServer('HTTP_X_FORWARDED_FOR'); } else { $ip = $this->getServer('REMOTE_ADDR'); } return $ip; } }