1: <?php
2:
3: 4: 5: 6:
7:
8: namespace Nette\Http;
9:
10: use Nette;
11: use Nette\Utils\Strings;
12:
13:
14: 15: 16: 17: 18:
19: class RequestFactory extends Nette\Object
20: {
21:
22: const CHARS = '\x09\x0A\x0D\x20-\x7E\xA0-\x{10FFFF}';
23:
24:
25: public $urlFilters = array(
26: 'path' => array('#/{2,}#' => '/'),
27: 'url' => array(),
28: );
29:
30:
31: private $binary = FALSE;
32:
33:
34: private $proxies = array();
35:
36:
37: 38: 39: 40:
41: public function setBinary($binary = TRUE)
42: {
43: $this->binary = (bool) $binary;
44: return $this;
45: }
46:
47:
48: 49: 50: 51:
52: public function setProxy($proxy)
53: {
54: $this->proxies = (array) $proxy;
55: return $this;
56: }
57:
58:
59: 60: 61: 62:
63: public function createHttpRequest()
64: {
65:
66: $url = new UrlScript;
67: $url->setScheme(!empty($_SERVER['HTTPS']) && strcasecmp($_SERVER['HTTPS'], 'off') ? 'https' : 'http');
68: $url->setUser(isset($_SERVER['PHP_AUTH_USER']) ? $_SERVER['PHP_AUTH_USER'] : '');
69: $url->setPassword(isset($_SERVER['PHP_AUTH_PW']) ? $_SERVER['PHP_AUTH_PW'] : '');
70:
71:
72: if ((isset($_SERVER[$tmp = 'HTTP_HOST']) || isset($_SERVER[$tmp = 'SERVER_NAME']))
73: && preg_match('#^([a-z0-9_.-]+|\[[a-f0-9:]+\])(:\d+)?\z#i', $_SERVER[$tmp], $pair)
74: ) {
75: $url->setHost(strtolower($pair[1]));
76: if (isset($pair[2])) {
77: $url->setPort(substr($pair[2], 1));
78: } elseif (isset($_SERVER['SERVER_PORT'])) {
79: $url->setPort($_SERVER['SERVER_PORT']);
80: }
81: }
82:
83:
84: if (isset($_SERVER['REQUEST_URI'])) {
85: $requestUrl = $_SERVER['REQUEST_URI'];
86:
87: } elseif (isset($_SERVER['ORIG_PATH_INFO'])) {
88: $requestUrl = $_SERVER['ORIG_PATH_INFO'];
89: if (isset($_SERVER['QUERY_STRING']) && $_SERVER['QUERY_STRING'] != '') {
90: $requestUrl .= '?' . $_SERVER['QUERY_STRING'];
91: }
92: } else {
93: $requestUrl = '';
94: }
95:
96: $requestUrl = Strings::replace($requestUrl, $this->urlFilters['url']);
97: $tmp = explode('?', $requestUrl, 2);
98: $url->setPath(Strings::replace($tmp[0], $this->urlFilters['path']));
99: $url->setQuery(isset($tmp[1]) ? $tmp[1] : '');
100:
101:
102: $url->canonicalize();
103: $url->setPath(Strings::fixEncoding($url->getPath()));
104:
105:
106: if (isset($_SERVER['SCRIPT_NAME'])) {
107: $script = $_SERVER['SCRIPT_NAME'];
108: } elseif (isset($_SERVER['DOCUMENT_ROOT'], $_SERVER['SCRIPT_FILENAME'])
109: && strncmp($_SERVER['DOCUMENT_ROOT'], $_SERVER['SCRIPT_FILENAME'], strlen($_SERVER['DOCUMENT_ROOT'])) === 0
110: ) {
111: $script = '/' . ltrim(strtr(substr($_SERVER['SCRIPT_FILENAME'], strlen($_SERVER['DOCUMENT_ROOT'])), '\\', '/'), '/');
112: } else {
113: $script = '/';
114: }
115:
116: $path = strtolower($url->getPath()) . '/';
117: $script = strtolower($script) . '/';
118: $max = min(strlen($path), strlen($script));
119: for ($i = 0; $i < $max; $i++) {
120: if ($path[$i] !== $script[$i]) {
121: break;
122: } elseif ($path[$i] === '/') {
123: $url->setScriptPath(substr($url->getPath(), 0, $i + 1));
124: }
125: }
126:
127:
128: $useFilter = (!in_array(ini_get('filter.default'), array('', 'unsafe_raw')) || ini_get('filter.default_flags'));
129:
130: parse_str($url->getQuery(), $query);
131: if (!$query) {
132: $query = $useFilter ? filter_input_array(INPUT_GET, FILTER_UNSAFE_RAW) : (empty($_GET) ? array() : $_GET);
133: }
134: $post = $useFilter ? filter_input_array(INPUT_POST, FILTER_UNSAFE_RAW) : (empty($_POST) ? array() : $_POST);
135: $cookies = $useFilter ? filter_input_array(INPUT_COOKIE, FILTER_UNSAFE_RAW) : (empty($_COOKIE) ? array() : $_COOKIE);
136:
137: $gpc = (bool) get_magic_quotes_gpc();
138:
139:
140: $reChars = '#^[' . self::CHARS . ']*+\z#u';
141: if ($gpc || !$this->binary) {
142: $list = array(& $query, & $post, & $cookies);
143: while (list($key, $val) = each($list)) {
144: foreach ($val as $k => $v) {
145: unset($list[$key][$k]);
146:
147: if ($gpc) {
148: $k = stripslashes($k);
149: }
150:
151: if (!$this->binary && is_string($k) && (!preg_match($reChars, $k) || preg_last_error())) {
152:
153:
154: } elseif (is_array($v)) {
155: $list[$key][$k] = $v;
156: $list[] = & $list[$key][$k];
157:
158: } else {
159: if ($gpc && !$useFilter) {
160: $v = stripSlashes($v);
161: }
162: if (!$this->binary) {
163: $v = (string) preg_replace('#[^' . self::CHARS . ']+#u', '', $v);
164: }
165: $list[$key][$k] = $v;
166: }
167: }
168: }
169: unset($list, $key, $val, $k, $v);
170: }
171:
172:
173:
174: $files = array();
175: $list = array();
176: if (!empty($_FILES)) {
177: foreach ($_FILES as $k => $v) {
178: if (!$this->binary && is_string($k) && (!preg_match($reChars, $k) || preg_last_error())) {
179: continue;
180: }
181: $v['@'] = & $files[$k];
182: $list[] = $v;
183: }
184: }
185:
186: while (list(, $v) = each($list)) {
187: if (!isset($v['name'])) {
188: continue;
189:
190: } elseif (!is_array($v['name'])) {
191: if ($gpc) {
192: $v['name'] = stripSlashes($v['name']);
193: }
194: if (!$this->binary && (!preg_match($reChars, $v['name']) || preg_last_error())) {
195: $v['name'] = '';
196: }
197: if ($v['error'] !== UPLOAD_ERR_NO_FILE) {
198: $v['@'] = new FileUpload($v);
199: }
200: continue;
201: }
202:
203: foreach ($v['name'] as $k => $foo) {
204: if (!$this->binary && is_string($k) && (!preg_match($reChars, $k) || preg_last_error())) {
205: continue;
206: }
207: $list[] = array(
208: 'name' => $v['name'][$k],
209: 'type' => $v['type'][$k],
210: 'size' => $v['size'][$k],
211: 'tmp_name' => $v['tmp_name'][$k],
212: 'error' => $v['error'][$k],
213: '@' => & $v['@'][$k],
214: );
215: }
216: }
217:
218:
219:
220: if (function_exists('apache_request_headers')) {
221: $headers = apache_request_headers();
222: } else {
223: $headers = array();
224: foreach ($_SERVER as $k => $v) {
225: if (strncmp($k, 'HTTP_', 5) == 0) {
226: $k = substr($k, 5);
227: } elseif (strncmp($k, 'CONTENT_', 8)) {
228: continue;
229: }
230: $headers[ strtr($k, '_', '-') ] = $v;
231: }
232: }
233:
234:
235: $remoteAddr = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : NULL;
236: $remoteHost = isset($_SERVER['REMOTE_HOST']) ? $_SERVER['REMOTE_HOST'] : NULL;
237:
238:
239: foreach ($this->proxies as $proxy) {
240: if (Helpers::ipMatch($remoteAddr, $proxy) && !empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
241: $proxies = $this->proxies;
242: $xForwardedForWithoutProxies = array_filter(explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']), function ($ip) use ($proxies) {
243: return !array_filter($proxies, function ($proxy) use ($ip) {
244: return Helpers::ipMatch(trim($ip), $proxy);
245: });
246: });
247: $remoteAddr = trim(end($xForwardedForWithoutProxies));
248:
249: if (!empty($_SERVER['HTTP_X_FORWARDED_HOST'])) {
250: $xForwardedForRealIpKey = key($xForwardedForWithoutProxies);
251: $xForwardedHost = explode(',', $_SERVER['HTTP_X_FORWARDED_HOST']);
252: if (isset($xForwardedHost[$xForwardedForRealIpKey])) {
253: $remoteHost = trim($xForwardedHost[$xForwardedForRealIpKey]);
254: }
255: }
256: break;
257: }
258: }
259:
260:
261: $method = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : NULL;
262: if ($method === 'POST' && isset($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'])
263: && preg_match('#^[A-Z]+\z#', $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'])
264: ) {
265: $method = $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'];
266: }
267:
268: return new Request($url, $query, $post, $files, $cookies, $headers, $method, $remoteAddr, $remoteHost);
269: }
270:
271: }
272: