Request.php 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. <?php
  2. namespace OAuth2;
  3. use LogicException;
  4. /**
  5. * OAuth2\Request
  6. * This class is taken from the Symfony2 Framework and is part of the Symfony package.
  7. * See Symfony\Component\HttpFoundation\Request (https://github.com/symfony/symfony)
  8. */
  9. class Request implements RequestInterface
  10. {
  11. public $attributes;
  12. public $request;
  13. public $query;
  14. public $server;
  15. public $files;
  16. public $cookies;
  17. public $headers;
  18. public $content;
  19. /**
  20. * Constructor.
  21. *
  22. * @param array $query - The GET parameters
  23. * @param array $request - The POST parameters
  24. * @param array $attributes - The request attributes (parameters parsed from the PATH_INFO, ...)
  25. * @param array $cookies - The COOKIE parameters
  26. * @param array $files - The FILES parameters
  27. * @param array $server - The SERVER parameters
  28. * @param string $content - The raw body data
  29. * @param array $headers - The headers
  30. *
  31. * @api
  32. */
  33. public function __construct(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null, array $headers = null)
  34. {
  35. $this->initialize($query, $request, $attributes, $cookies, $files, $server, $content, $headers);
  36. }
  37. /**
  38. * Sets the parameters for this request.
  39. *
  40. * This method also re-initializes all properties.
  41. *
  42. * @param array $query - The GET parameters
  43. * @param array $request - The POST parameters
  44. * @param array $attributes - The request attributes (parameters parsed from the PATH_INFO, ...)
  45. * @param array $cookies - The COOKIE parameters
  46. * @param array $files - The FILES parameters
  47. * @param array $server - The SERVER parameters
  48. * @param string $content - The raw body data
  49. * @param array $headers - The headers
  50. *
  51. * @api
  52. */
  53. public function initialize(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null, array $headers = null)
  54. {
  55. $this->request = $request;
  56. $this->query = $query;
  57. $this->attributes = $attributes;
  58. $this->cookies = $cookies;
  59. $this->files = $files;
  60. $this->server = $server;
  61. $this->content = $content;
  62. $this->headers = is_null($headers) ? $this->getHeadersFromServer($this->server) : $headers;
  63. }
  64. /**
  65. * @param string $name
  66. * @param mixed $default
  67. * @return mixed
  68. */
  69. public function query($name, $default = null)
  70. {
  71. return isset($this->query[$name]) ? $this->query[$name] : $default;
  72. }
  73. /**
  74. * @param string $name
  75. * @param mixed $default
  76. * @return mixed
  77. */
  78. public function request($name, $default = null)
  79. {
  80. return isset($this->request[$name]) ? $this->request[$name] : $default;
  81. }
  82. /**
  83. * @param string $name
  84. * @param mixed $default
  85. * @return mixed
  86. */
  87. public function server($name, $default = null)
  88. {
  89. return isset($this->server[$name]) ? $this->server[$name] : $default;
  90. }
  91. /**
  92. * @param string $name
  93. * @param mixed $default
  94. * @return mixed
  95. */
  96. public function headers($name, $default = null)
  97. {
  98. $headers = array_change_key_case($this->headers);
  99. $name = strtolower($name);
  100. return isset($headers[$name]) ? $headers[$name] : $default;
  101. }
  102. /**
  103. * @return array
  104. */
  105. public function getAllQueryParameters()
  106. {
  107. return $this->query;
  108. }
  109. /**
  110. * Returns the request body content.
  111. *
  112. * @param boolean $asResource - If true, a resource will be returned
  113. * @return string|resource - The request body content or a resource to read the body stream.
  114. *
  115. * @throws LogicException
  116. */
  117. public function getContent($asResource = false)
  118. {
  119. if (false === $this->content || (true === $asResource && null !== $this->content)) {
  120. throw new LogicException('getContent() can only be called once when using the resource return type.');
  121. }
  122. if (true === $asResource) {
  123. $this->content = false;
  124. return fopen('php://input', 'rb');
  125. }
  126. if (null === $this->content) {
  127. $this->content = file_get_contents('php://input');
  128. }
  129. return $this->content;
  130. }
  131. /**
  132. * @param array $server
  133. * @return array
  134. */
  135. private function getHeadersFromServer($server)
  136. {
  137. $headers = array();
  138. foreach ($server as $key => $value) {
  139. if (0 === strpos($key, 'HTTP_')) {
  140. $headers[substr($key, 5)] = $value;
  141. }
  142. // CONTENT_* are not prefixed with HTTP_
  143. elseif (in_array($key, array('CONTENT_LENGTH', 'CONTENT_MD5', 'CONTENT_TYPE'))) {
  144. $headers[$key] = $value;
  145. }
  146. }
  147. if (isset($server['PHP_AUTH_USER'])) {
  148. $headers['PHP_AUTH_USER'] = $server['PHP_AUTH_USER'];
  149. $headers['PHP_AUTH_PW'] = isset($server['PHP_AUTH_PW']) ? $server['PHP_AUTH_PW'] : '';
  150. } else {
  151. /*
  152. * php-cgi under Apache does not pass HTTP Basic user/pass to PHP by default
  153. * For this workaround to work, add this line to your .htaccess file:
  154. * RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
  155. *
  156. * A sample .htaccess file:
  157. * RewriteEngine On
  158. * RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
  159. * RewriteCond %{REQUEST_FILENAME} !-f
  160. * RewriteRule ^(.*)$ app.php [QSA,L]
  161. */
  162. $authorizationHeader = null;
  163. if (isset($server['HTTP_AUTHORIZATION'])) {
  164. $authorizationHeader = $server['HTTP_AUTHORIZATION'];
  165. } elseif (isset($server['REDIRECT_HTTP_AUTHORIZATION'])) {
  166. $authorizationHeader = $server['REDIRECT_HTTP_AUTHORIZATION'];
  167. } elseif (function_exists('apache_request_headers')) {
  168. $requestHeaders = (array) apache_request_headers();
  169. // Server-side fix for bug in old Android versions (a nice side-effect of this fix means we don't care about capitalization for Authorization)
  170. $requestHeaders = array_combine(array_map('ucwords', array_keys($requestHeaders)), array_values($requestHeaders));
  171. if (isset($requestHeaders['Authorization'])) {
  172. $authorizationHeader = trim($requestHeaders['Authorization']);
  173. }
  174. }
  175. if (null !== $authorizationHeader) {
  176. $headers['AUTHORIZATION'] = $authorizationHeader;
  177. // Decode AUTHORIZATION header into PHP_AUTH_USER and PHP_AUTH_PW when authorization header is basic
  178. if (0 === stripos($authorizationHeader, 'basic')) {
  179. $exploded = explode(':', base64_decode(substr($authorizationHeader, 6)));
  180. if (count($exploded) == 2) {
  181. list($headers['PHP_AUTH_USER'], $headers['PHP_AUTH_PW']) = $exploded;
  182. }
  183. }
  184. }
  185. }
  186. // PHP_AUTH_USER/PHP_AUTH_PW
  187. if (isset($headers['PHP_AUTH_USER'])) {
  188. $headers['AUTHORIZATION'] = 'Basic '.base64_encode($headers['PHP_AUTH_USER'].':'.$headers['PHP_AUTH_PW']);
  189. }
  190. return $headers;
  191. }
  192. /**
  193. * Creates a new request with values from PHP's super globals.
  194. *
  195. * @return Request - A new request
  196. *
  197. * @api
  198. */
  199. public static function createFromGlobals()
  200. {
  201. $class = get_called_class();
  202. /** @var Request $request */
  203. $request = new $class($_GET, $_POST, array(), $_COOKIE, $_FILES, $_SERVER);
  204. $contentType = $request->server('CONTENT_TYPE', '');
  205. $requestMethod = $request->server('REQUEST_METHOD', 'GET');
  206. if (0 === strpos($contentType, 'application/x-www-form-urlencoded')
  207. && in_array(strtoupper($requestMethod), array('PUT', 'DELETE'))
  208. ) {
  209. parse_str($request->getContent(), $data);
  210. $request->request = $data;
  211. } elseif (0 === strpos($contentType, 'application/json')
  212. && in_array(strtoupper($requestMethod), array('POST', 'PUT', 'DELETE'))
  213. ) {
  214. $data = json_decode($request->getContent(), true);
  215. $request->request = $data;
  216. }
  217. return $request;
  218. }
  219. }