composer package updates
[openemr.git] / vendor / zendframework / zend-diactoros / src / functions / marshal_uri_from_sapi.php
blobb906a290d9c09d076da2df583e733b4a90159143
1 <?php
2 /**
3 * @see https://github.com/zendframework/zend-diactoros for the canonical source repository
4 * @copyright Copyright (c) 2018 Zend Technologies USA Inc. (https://www.zend.com)
5 * @license https://github.com/zendframework/zend-diactoros/blob/master/LICENSE.md New BSD License
6 */
8 namespace Zend\Diactoros;
10 use function array_change_key_case;
11 use function array_key_exists;
12 use function explode;
13 use function implode;
14 use function is_array;
15 use function ltrim;
16 use function preg_match;
17 use function preg_replace;
18 use function strlen;
19 use function strpos;
20 use function strtolower;
21 use function substr;
23 /**
24 * Marshal a Uri instance based on the values presnt in the $_SERVER array and headers.
26 * @param array $server SAPI parameters
27 * @param array $headers HTTP request headers
28 * @return Uri
30 function marshalUriFromSapi(array $server, array $headers)
32 /**
33 * Retrieve a header value from an array of headers using a case-insensitive lookup.
35 * @param string $name
36 * @param array $headers Key/value header pairs
37 * @param mixed $default Default value to return if header not found
38 * @return mixed
40 $getHeaderFromArray = function ($name, array $headers, $default = null) {
41 $header = strtolower($name);
42 $headers = array_change_key_case($headers, CASE_LOWER);
43 if (array_key_exists($header, $headers)) {
44 $value = is_array($headers[$header]) ? implode(', ', $headers[$header]) : $headers[$header];
45 return $value;
48 return $default;
51 /**
52 * Marshal the host and port from HTTP headers and/or the PHP environment.
54 * @param array $headers
55 * @param array $server
56 * @return array Array of two items, host and port, in that order (can be
57 * passed to a list() operation).
59 $marshalHostAndPort = function (array $headers, array $server) use ($getHeaderFromArray) {
60 /**
61 * @param string|array $host
62 * @return array Array of two items, host and port, in that order (can be
63 * passed to a list() operation).
65 $marshalHostAndPortFromHeader = function ($host) {
66 if (is_array($host)) {
67 $host = implode(', ', $host);
70 $port = null;
72 // works for regname, IPv4 & IPv6
73 if (preg_match('|\:(\d+)$|', $host, $matches)) {
74 $host = substr($host, 0, -1 * (strlen($matches[1]) + 1));
75 $port = (int) $matches[1];
78 return [$host, $port];
81 /**
82 * @param array $server
83 * @param string $host
84 * @param null|int $port
85 * @return array Array of two items, host and port, in that order (can be
86 * passed to a list() operation).
88 $marshalIpv6HostAndPort = function (array $server, $host, $port) {
89 $host = '[' . $server['SERVER_ADDR'] . ']';
90 $port = $port ?: 80;
91 if ($port . ']' === substr($host, strrpos($host, ':') + 1)) {
92 // The last digit of the IPv6-Address has been taken as port
93 // Unset the port so the default port can be used
94 $port = null;
96 return [$host, $port];
99 static $defaults = ['', null];
101 if ($getHeaderFromArray('host', $headers, false)) {
102 return $marshalHostAndPortFromHeader($getHeaderFromArray('host', $headers));
105 if (! isset($server['SERVER_NAME'])) {
106 return $defaults;
109 $host = $server['SERVER_NAME'];
110 $port = isset($server['SERVER_PORT']) ? (int) $server['SERVER_PORT'] : null;
112 if (! isset($server['SERVER_ADDR'])
113 || ! preg_match('/^\[[0-9a-fA-F\:]+\]$/', $host)
115 return [$host, $port];
118 // Misinterpreted IPv6-Address
119 // Reported for Safari on Windows
120 return $marshalIpv6HostAndPort($server, $host, $port);
124 * Detect the path for the request
126 * Looks at a variety of criteria in order to attempt to autodetect the base
127 * request path, including rewrite URIs, proxy URIs, etc.
129 * From ZF2's Zend\Http\PhpEnvironment\Request class
130 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
131 * @license http://framework.zend.com/license/new-bsd New BSD License
133 * @param array $server SAPI environment array (typically `$_SERVER`)
134 * @return string Discovered path
136 $marshalRequestPath = function (array $server) {
137 // IIS7 with URL Rewrite: make sure we get the unencoded url
138 // (double slash problem).
139 $iisUrlRewritten = array_key_exists('IIS_WasUrlRewritten', $server) ? $server['IIS_WasUrlRewritten'] : null;
140 $unencodedUrl = array_key_exists('UNENCODED_URL', $server) ? $server['UNENCODED_URL'] : '';
141 if ('1' === $iisUrlRewritten && ! empty($unencodedUrl)) {
142 return $unencodedUrl;
145 $requestUri = array_key_exists('REQUEST_URI', $server) ? $server['REQUEST_URI'] : null;
147 // Check this first so IIS will catch.
148 $httpXRewriteUrl = array_key_exists('HTTP_X_REWRITE_URL', $server) ? $server['HTTP_X_REWRITE_URL'] : null;
149 if ($httpXRewriteUrl !== null) {
150 $requestUri = $httpXRewriteUrl;
153 // Check for IIS 7.0 or later with ISAPI_Rewrite
154 $httpXOriginalUrl = array_key_exists('HTTP_X_ORIGINAL_URL', $server) ? $server['HTTP_X_ORIGINAL_URL'] : null;
155 if ($httpXOriginalUrl !== null) {
156 $requestUri = $httpXOriginalUrl;
159 if ($requestUri !== null) {
160 return preg_replace('#^[^/:]+://[^/]+#', '', $requestUri);
163 $origPathInfo = array_key_exists('ORIG_PATH_INFO', $server) ? $server['ORIG_PATH_INFO'] : null;
164 if (empty($origPathInfo)) {
165 return '/';
168 return $origPathInfo;
171 $uri = new Uri('');
173 // URI scheme
174 $scheme = 'http';
175 $https = array_key_exists('HTTPS', $server) ? $server['HTTPS'] : false;
176 if (($https && 'off' !== $https)
177 || $getHeaderFromArray('x-forwarded-proto', $headers, false) === 'https'
179 $scheme = 'https';
181 $uri = $uri->withScheme($scheme);
183 // Set the host
184 list($host, $port) = $marshalHostAndPort($headers, $server);
185 if (! empty($host)) {
186 $uri = $uri->withHost($host);
187 if (! empty($port)) {
188 $uri = $uri->withPort($port);
192 // URI path
193 $path = $marshalRequestPath($server);
195 // Strip query string
196 $path = explode('?', $path, 2)[0];
198 // URI query
199 $query = '';
200 if (isset($server['QUERY_STRING'])) {
201 $query = ltrim($server['QUERY_STRING'], '?');
204 // URI fragment
205 $fragment = '';
206 if (strpos($path, '#') !== false) {
207 list($path, $fragment) = explode('#', $path, 2);
210 return $uri
211 ->withPath($path)
212 ->withFragment($fragment)
213 ->withQuery($query);