1: <?php
2:
3: 4: 5: 6:
7:
8: namespace Nette\Http;
9:
10: use Nette,
11: 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: $requestUrl = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '/';
85: $requestUrl = Strings::replace($requestUrl, $this->urlFilters['url']);
86: $tmp = explode('?', $requestUrl, 2);
87: $path = Url::unescape($tmp[0], '%/?#');
88: $path = Strings::fixEncoding(Strings::replace($path, $this->urlFilters['path']));
89: $url->setPath($path);
90: $url->setQuery(isset($tmp[1]) ? $tmp[1] : '');
91:
92:
93: $lpath = strtolower($path);
94: $script = isset($_SERVER['SCRIPT_NAME']) ? strtolower($_SERVER['SCRIPT_NAME']) : '';
95: if ($lpath !== $script) {
96: $max = min(strlen($lpath), strlen($script));
97: for ($i = 0; $i < $max && $lpath[$i] === $script[$i]; $i++);
98: $path = $i ? substr($path, 0, strrpos($path, '/', $i - strlen($path) - 1) + 1) : '/';
99: }
100: $url->setScriptPath($path);
101:
102:
103: $useFilter = (!in_array(ini_get('filter.default'), array('', 'unsafe_raw')) || ini_get('filter.default_flags'));
104:
105: $query = $url->getQueryParameters();
106: $post = $useFilter ? filter_input_array(INPUT_POST, FILTER_UNSAFE_RAW) : (empty($_POST) ? array() : $_POST);
107: $cookies = $useFilter ? filter_input_array(INPUT_COOKIE, FILTER_UNSAFE_RAW) : (empty($_COOKIE) ? array() : $_COOKIE);
108:
109: if (get_magic_quotes_gpc()) {
110: $post = Helpers::stripslashes($post, $useFilter);
111: $cookies = Helpers::stripslashes($cookies, $useFilter);
112: }
113:
114:
115: $reChars = '#^[' . self::CHARS . ']*+\z#u';
116: if (!$this->binary) {
117: $list = array(& $query, & $post, & $cookies);
118: while (list($key, $val) = each($list)) {
119: foreach ($val as $k => $v) {
120: if (is_string($k) && (!preg_match($reChars, $k) || preg_last_error())) {
121: unset($list[$key][$k]);
122:
123: } elseif (is_array($v)) {
124: $list[$key][$k] = $v;
125: $list[] = & $list[$key][$k];
126:
127: } else {
128: $list[$key][$k] = (string) preg_replace('#[^' . self::CHARS . ']+#u', '', $v);
129: }
130: }
131: }
132: unset($list, $key, $val, $k, $v);
133: }
134: $url->setQuery($query);
135:
136:
137:
138: $files = array();
139: $list = array();
140: if (!empty($_FILES)) {
141: foreach ($_FILES as $k => $v) {
142: if (!$this->binary && is_string($k) && (!preg_match($reChars, $k) || preg_last_error())) {
143: continue;
144: }
145: $v['@'] = & $files[$k];
146: $list[] = $v;
147: }
148: }
149:
150: while (list(, $v) = each($list)) {
151: if (!isset($v['name'])) {
152: continue;
153:
154: } elseif (!is_array($v['name'])) {
155: if (get_magic_quotes_gpc()) {
156: $v['name'] = stripSlashes($v['name']);
157: }
158: if (!$this->binary && (!preg_match($reChars, $v['name']) || preg_last_error())) {
159: $v['name'] = '';
160: }
161: if ($v['error'] !== UPLOAD_ERR_NO_FILE) {
162: $v['@'] = new FileUpload($v);
163: }
164: continue;
165: }
166:
167: foreach ($v['name'] as $k => $foo) {
168: if (!$this->binary && is_string($k) && (!preg_match($reChars, $k) || preg_last_error())) {
169: continue;
170: }
171: $list[] = array(
172: 'name' => $v['name'][$k],
173: 'type' => $v['type'][$k],
174: 'size' => $v['size'][$k],
175: 'tmp_name' => $v['tmp_name'][$k],
176: 'error' => $v['error'][$k],
177: '@' => & $v['@'][$k],
178: );
179: }
180: }
181:
182:
183:
184: if (function_exists('apache_request_headers')) {
185: $headers = apache_request_headers();
186: } else {
187: $headers = array();
188: foreach ($_SERVER as $k => $v) {
189: if (strncmp($k, 'HTTP_', 5) == 0) {
190: $k = substr($k, 5);
191: } elseif (strncmp($k, 'CONTENT_', 8)) {
192: continue;
193: }
194: $headers[ strtr($k, '_', '-') ] = $v;
195: }
196: }
197:
198:
199: $remoteAddr = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : NULL;
200: $remoteHost = isset($_SERVER['REMOTE_HOST']) ? $_SERVER['REMOTE_HOST'] : NULL;
201:
202:
203: foreach ($this->proxies as $proxy) {
204: if (Helpers::ipMatch($remoteAddr, $proxy)) {
205: if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
206: $remoteAddr = trim(current(explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'])));
207: }
208: if (isset($_SERVER['HTTP_X_FORWARDED_HOST'])) {
209: $remoteHost = trim(current(explode(',', $_SERVER['HTTP_X_FORWARDED_HOST'])));
210: }
211: break;
212: }
213: }
214:
215:
216: $method = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : NULL;
217: if ($method === 'POST' && isset($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'])
218: && preg_match('#^[A-Z]+\z#', $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'])
219: ) {
220: $method = $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'];
221: }
222:
223:
224: $rawBodyCallback = function() {
225: static $rawBody;
226:
227: if (PHP_VERSION_ID >= 50600) {
228: return file_get_contents('php://input');
229:
230: } elseif ($rawBody === NULL) {
231: $rawBody = (string) file_get_contents('php://input');
232: }
233:
234: return $rawBody;
235: };
236:
237: return new Request($url, NULL, $post, $files, $cookies, $headers, $method, $remoteAddr, $remoteHost, $rawBodyCallback);
238: }
239:
240: }
241: