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 NONCHARS = '#[^\x09\x0A\x0D\x20-\x7E\xA0-\x{10FFFF}]#u';
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'), TRUE) || 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: if ($gpc || !$this->binary) {
141: $list = array(& $query, & $post, & $cookies);
142: while (list($key, $val) = each($list)) {
143: foreach ($val as $k => $v) {
144: unset($list[$key][$k]);
145:
146: if ($gpc) {
147: $k = stripslashes($k);
148: }
149:
150: if (!$this->binary && is_string($k) && (preg_match(self::NONCHARS, $k) || preg_last_error())) {
151:
152:
153: } elseif (is_array($v)) {
154: $list[$key][$k] = $v;
155: $list[] = & $list[$key][$k];
156:
157: } else {
158: if ($gpc && !$useFilter) {
159: $v = stripSlashes($v);
160: }
161: if (!$this->binary && (preg_match(self::NONCHARS, $v) || preg_last_error())) {
162: $v = '';
163: }
164: $list[$key][$k] = $v;
165: }
166: }
167: }
168: unset($list, $key, $val, $k, $v);
169: }
170:
171:
172:
173: $files = array();
174: $list = array();
175: if (!empty($_FILES)) {
176: foreach ($_FILES as $k => $v) {
177: if (!$this->binary && is_string($k) && (preg_match(self::NONCHARS, $k) || preg_last_error())) {
178: continue;
179: }
180: $v['@'] = & $files[$k];
181: $list[] = $v;
182: }
183: }
184:
185: while (list(, $v) = each($list)) {
186: if (!isset($v['name'])) {
187: continue;
188:
189: } elseif (!is_array($v['name'])) {
190: if ($gpc) {
191: $v['name'] = stripSlashes($v['name']);
192: }
193: if (!$this->binary && (preg_match(self::NONCHARS, $v['name']) || preg_last_error())) {
194: $v['name'] = '';
195: }
196: if ($v['error'] !== UPLOAD_ERR_NO_FILE) {
197: $v['@'] = new FileUpload($v);
198: }
199: continue;
200: }
201:
202: foreach ($v['name'] as $k => $foo) {
203: if (!$this->binary && is_string($k) && (preg_match(self::NONCHARS, $k) || preg_last_error())) {
204: continue;
205: }
206: $list[] = array(
207: 'name' => $v['name'][$k],
208: 'type' => $v['type'][$k],
209: 'size' => $v['size'][$k],
210: 'tmp_name' => $v['tmp_name'][$k],
211: 'error' => $v['error'][$k],
212: '@' => & $v['@'][$k],
213: );
214: }
215: }
216:
217:
218:
219: if (function_exists('apache_request_headers')) {
220: $headers = apache_request_headers();
221: } else {
222: $headers = array();
223: foreach ($_SERVER as $k => $v) {
224: if (strncmp($k, 'HTTP_', 5) == 0) {
225: $k = substr($k, 5);
226: } elseif (strncmp($k, 'CONTENT_', 8)) {
227: continue;
228: }
229: $headers[ strtr($k, '_', '-') ] = $v;
230: }
231: }
232:
233:
234: $remoteAddr = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : NULL;
235: $remoteHost = isset($_SERVER['REMOTE_HOST']) ? $_SERVER['REMOTE_HOST'] : NULL;
236:
237:
238: foreach ($this->proxies as $proxy) {
239: if (Helpers::ipMatch($remoteAddr, $proxy)) {
240: if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
241: $remoteAddr = trim(current(explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'])));
242: }
243: if (isset($_SERVER['HTTP_X_FORWARDED_HOST'])) {
244: $remoteHost = trim(current(explode(',', $_SERVER['HTTP_X_FORWARDED_HOST'])));
245: }
246: break;
247: }
248: }
249:
250:
251: $method = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : NULL;
252: if ($method === 'POST' && isset($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'])
253: && preg_match('#^[A-Z]+\z#', $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'])
254: ) {
255: $method = $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'];
256: }
257:
258: return new Request($url, $query, $post, $files, $cookies, $headers, $method, $remoteAddr, $remoteHost);
259: }
260:
261: }
262: