1
|
|
|
<?php |
2
|
|
|
namespace WebServCo\Framework\Libraries; |
3
|
|
|
|
4
|
|
|
final class Request extends \WebServCo\Framework\AbstractLibrary |
5
|
|
|
{ |
6
|
|
|
/** |
7
|
|
|
* Sanitized _SERVER data. |
8
|
|
|
*/ |
9
|
|
|
public $server = []; |
10
|
|
|
/** |
11
|
|
|
* Request method. |
12
|
|
|
*/ |
13
|
|
|
public $method; |
14
|
|
|
/** |
15
|
|
|
* Current script filename. Should most commonly be index.php |
16
|
|
|
*/ |
17
|
|
|
public $filename; |
18
|
|
|
/** |
19
|
|
|
* Script path. |
20
|
|
|
* For HTTP requests this will be public web server subdirectory |
21
|
|
|
* the project is located in. |
22
|
|
|
* For CLI request this will be the script path |
23
|
|
|
* (full or relative, depending on how the script was called). |
24
|
|
|
*/ |
25
|
|
|
public $path = ''; |
26
|
|
|
/** |
27
|
|
|
* Sanitized Framework customized target path. |
28
|
|
|
*/ |
29
|
|
|
public $target = ''; |
30
|
|
|
/** |
31
|
|
|
* Sanitized request query. |
32
|
|
|
*/ |
33
|
|
|
public $query = []; |
34
|
|
|
/** |
35
|
|
|
* Sanitized Framework customized CLI arguments. |
36
|
|
|
* |
37
|
|
|
* Excludes the script name and the second argument |
38
|
|
|
* which is the Framework customized target path. |
39
|
|
|
*/ |
40
|
|
|
public $args = []; |
41
|
|
|
|
42
|
|
|
public function __construct($config, $server, $post = []) |
43
|
|
|
{ |
44
|
|
|
parent::__construct($config); |
45
|
|
|
|
46
|
|
|
$this->init($server, $post); |
47
|
|
|
} |
48
|
|
|
|
49
|
|
|
private function init($server, $post = []) |
50
|
|
|
{ |
51
|
|
|
$this->server = $this->sanitize($server); |
52
|
|
|
$this->method = $this->getMethod(); |
53
|
|
|
$this->filename = $this->getFilename(); |
54
|
|
|
$this->path = $this->getPath(); |
55
|
|
|
$this->process(); |
56
|
|
|
|
57
|
|
|
switch ($this->method) { |
58
|
|
|
case \WebServCo\Framework\Http::METHOD_GET: |
59
|
|
|
case \WebServCo\Framework\Http::METHOD_HEAD: |
60
|
|
|
break; |
61
|
|
|
case \WebServCo\Framework\Http::METHOD_POST: |
62
|
|
|
$this->processPost($post); |
63
|
|
|
break; |
64
|
|
|
} |
65
|
|
|
if ($this->setting('clear_globals', true)) { |
66
|
|
|
$this->clearGlobals(); |
67
|
|
|
} |
68
|
|
|
} |
69
|
|
|
|
70
|
|
|
private function clearGlobals() |
71
|
|
|
{ |
72
|
|
|
if (!empty($_GET)) { |
73
|
|
|
foreach ($_GET as $k => $v) { |
74
|
|
|
unset($_REQUEST[$k]); |
75
|
|
|
} |
76
|
|
|
$_GET = []; |
77
|
|
|
} |
78
|
|
|
if (!empty($_POST)) { |
79
|
|
|
$_POST = []; |
80
|
|
|
} |
81
|
|
|
return true; |
82
|
|
|
} |
83
|
|
|
|
84
|
|
|
private function processPost($post = []) |
85
|
|
|
{ |
86
|
|
|
$this->data = []; |
87
|
|
|
foreach ($post as $k => $v) { |
88
|
|
|
$this->data[$this->sanitize($k)] = $v; |
89
|
|
|
} |
90
|
|
|
return true; |
91
|
|
|
} |
92
|
|
|
|
93
|
|
|
private function process() |
94
|
|
|
{ |
95
|
|
|
if (\WebServCo\Framework\Framework::isCLI()) { |
96
|
|
|
return $this->processCli(); |
|
|
|
|
97
|
|
|
} |
98
|
|
|
|
99
|
|
|
return $this->processHttp(); |
|
|
|
|
100
|
|
|
} |
101
|
|
|
|
102
|
|
|
private function processCli() |
103
|
|
|
{ |
104
|
|
|
if (isset($this->server['argv'][1])) { |
105
|
|
|
$this->target = $this->server['argv'][1]; |
106
|
|
|
} |
107
|
|
|
if (isset($this->server['argv'][2])) { |
108
|
|
|
foreach ($this->server['argv'] as $k => $v) { |
109
|
|
|
if (in_array($k, [0,1])) { |
110
|
|
|
continue; |
111
|
|
|
} |
112
|
|
|
$this->args[] = $this->sanitize($v); |
113
|
|
|
} |
114
|
|
|
} |
115
|
|
|
} |
116
|
|
|
|
117
|
|
|
private function processHttp() |
118
|
|
|
{ |
119
|
|
|
$string = null; |
120
|
|
|
switch (true) { |
121
|
|
|
case isset($this->server['REQUEST_URI']): |
122
|
|
|
$string = $this->server['REQUEST_URI']; |
123
|
|
|
break; |
124
|
|
|
case isset($this->server['PATH_INFO']): |
125
|
|
|
$string = $this->server['PATH_INFO']; |
126
|
|
|
break; |
127
|
|
|
case isset($this->server['ORIG_PATH_INFO']): |
128
|
|
|
$string = $this->server['ORIG_PATH_INFO']; |
129
|
|
|
break; |
130
|
|
|
case !empty($this->server['QUERY_STRING']): |
131
|
|
|
$string = $this->server['ORIG_PATH_INFO']; |
132
|
|
|
break; |
133
|
|
|
default: |
134
|
|
|
break; |
135
|
|
|
} |
136
|
|
|
list ($target, $queryString) = $this->parse($string); |
137
|
|
|
$this->target = $this->sanitize(urldecode($target)); |
138
|
|
|
$this->query = $this->format($this->sanitize($queryString)); |
139
|
|
|
} |
140
|
|
|
|
141
|
|
|
private function getMethod() |
142
|
|
|
{ |
143
|
|
|
return !empty($this->server['REQUEST_METHOD']) && |
144
|
|
|
in_array( |
145
|
|
|
$this->server['REQUEST_METHOD'], |
146
|
|
|
\WebServCo\Framework\Http::getMethods() |
147
|
|
|
) ? |
148
|
|
|
$this->server['REQUEST_METHOD'] : false; |
149
|
|
|
} |
150
|
|
|
|
151
|
|
|
private function getFilename() |
152
|
|
|
{ |
153
|
|
|
return !empty($this->server['SCRIPT_NAME']) ? |
154
|
|
|
basename($this->server['SCRIPT_NAME']) : false; |
155
|
|
|
} |
156
|
|
|
|
157
|
|
|
private function getPath() |
158
|
|
|
{ |
159
|
|
|
if (empty($this->server['SCRIPT_NAME'])) { |
160
|
|
|
return false; |
161
|
|
|
} |
162
|
|
|
$path = str_replace($this->getFilename(), '', $this->server['SCRIPT_NAME']); |
|
|
|
|
163
|
|
|
return rtrim($path, DIRECTORY_SEPARATOR); |
164
|
|
|
} |
165
|
|
|
|
166
|
|
|
public function sanitize($data) |
167
|
|
|
{ |
168
|
|
|
if (is_array($data)) { |
169
|
|
|
array_walk_recursive($data, [$this, 'sanitizeString']); |
170
|
|
|
return $data; |
171
|
|
|
} |
172
|
|
|
return $this->sanitizeString($data); |
173
|
|
|
} |
174
|
|
|
|
175
|
|
|
protected function sanitizeString($string) |
176
|
|
|
{ |
177
|
|
|
// Strip tags, optionally strip or encode special characters. |
178
|
|
|
$string = filter_var($string, FILTER_SANITIZE_STRING); |
179
|
|
|
$unwanted = [ |
180
|
|
|
"`", |
181
|
|
|
//"'", |
182
|
|
|
//'"', |
183
|
|
|
"\b", |
184
|
|
|
"\n", |
185
|
|
|
"\r", |
186
|
|
|
"\t", |
187
|
|
|
//"?", |
188
|
|
|
//"!", |
189
|
|
|
//"~", |
190
|
|
|
//"#", |
191
|
|
|
//"^", |
192
|
|
|
//"&", |
193
|
|
|
//"*", |
194
|
|
|
//"=", |
195
|
|
|
//"[", |
196
|
|
|
//"]", |
197
|
|
|
//":", |
198
|
|
|
//";", |
199
|
|
|
//",", |
200
|
|
|
//"|", |
201
|
|
|
"\\", |
202
|
|
|
//"{", |
203
|
|
|
//"}", |
204
|
|
|
//"(", |
205
|
|
|
//")", |
206
|
|
|
"\$" |
207
|
|
|
]; |
208
|
|
|
$string = str_replace($unwanted, '', $string); |
209
|
|
|
return $string; |
210
|
|
|
} |
211
|
|
|
|
212
|
|
|
private function parse($string) |
213
|
|
|
{ |
214
|
|
|
$pathLen = strlen($this->path); |
215
|
|
|
if (0 === strncasecmp($this->path, $string, $pathLen)) { |
216
|
|
|
$string = substr($string, $pathLen); |
217
|
|
|
} |
218
|
|
|
$filenameLen = strlen($this->filename); |
219
|
|
|
if (0 === strncasecmp($this->filename, $string, $filenameLen)) { |
220
|
|
|
$string = substr($string, $filenameLen); |
221
|
|
|
} |
222
|
|
|
list($target, $query) = $this->explode($string); |
223
|
|
|
$target = $this->removeSuffix($this->transform($target)); |
224
|
|
|
$query = $this->transform($query); |
225
|
|
|
return [$target, $query]; |
226
|
|
|
} |
227
|
|
|
|
228
|
|
|
private function explode($string) |
229
|
|
|
{ |
230
|
|
|
if (false !== strpos($string, '?')) { |
231
|
|
|
return explode('?', $string, 2); |
232
|
|
|
} elseif (false !== strpos($string, '&')) { |
233
|
|
|
return explode('&', $string, 2); |
234
|
|
|
} |
235
|
|
|
return [$string, null]; |
236
|
|
|
} |
237
|
|
|
|
238
|
|
|
private function transform($string) |
239
|
|
|
{ |
240
|
|
|
$string = str_replace(['?','&','=','//'], ['','/','/','/0/'], $string); |
241
|
|
|
return trim($string, ' /'); |
242
|
|
|
} |
243
|
|
|
|
244
|
|
|
private function removeSuffix($string) |
245
|
|
|
{ |
246
|
|
|
$suffixes = $this->setting('suffixes'); |
247
|
|
|
if (is_array($suffixes)) { |
248
|
|
|
$stringRev = strrev($string); |
249
|
|
|
foreach ($suffixes as $suffix) { |
250
|
|
|
$suffixRev = strrev($suffix); |
251
|
|
|
$suffixLen = strlen($suffix); |
252
|
|
|
if (0 === strncasecmp($suffixRev, $stringRev, $suffixLen)) { |
253
|
|
|
return strrev(substr($stringRev, $suffixLen)); |
254
|
|
|
} |
255
|
|
|
} |
256
|
|
|
} |
257
|
|
|
return $string; |
258
|
|
|
} |
259
|
|
|
|
260
|
|
|
private function format($string) |
261
|
|
|
{ |
262
|
|
|
$data = []; |
263
|
|
|
$parts = $this->split($string); |
264
|
|
|
$num = count($parts); |
265
|
|
|
for ($position = 0; $position < $num; $position +=2) { |
266
|
|
|
$data[$parts[$position]] = $position == $num -1 ? null : |
267
|
|
|
$parts[$position + 1]; |
268
|
|
|
} |
269
|
|
|
return $data; |
270
|
|
|
} |
271
|
|
|
|
272
|
|
|
public function split($string) |
273
|
|
|
{ |
274
|
|
|
$parts = explode('/', $string); |
275
|
|
|
$parts = array_map('urldecode', $parts); |
276
|
|
|
return array_diff($parts, ['']); |
277
|
|
|
} |
278
|
|
|
|
279
|
|
|
public function getSchema() |
280
|
|
|
{ |
281
|
|
|
if (\WebServCo\Framework\Framework::isCLI()) { |
282
|
|
|
return null; |
283
|
|
|
} |
284
|
|
|
|
285
|
|
|
if (isset($this->server['HTTPS']) && 'off' != $this->server['HTTPS']) { |
286
|
|
|
return 'https'; |
287
|
|
|
} elseif (isset($this->server['HTTP_X_FORWARDED_PROTO']) && |
288
|
|
|
'https' == $this->server['HTTP_X_FORWARDED_PROTO']) { |
289
|
|
|
return 'https'; |
290
|
|
|
} elseif (isset($this->server['HTTP_X_FORWARDED_SSL']) && |
291
|
|
|
'on' == $this->server['HTTP_X_FORWARDED_SSL']) { |
292
|
|
|
return 'https'; |
293
|
|
|
} |
294
|
|
|
return 'http'; |
295
|
|
|
} |
296
|
|
|
|
297
|
|
|
public function getReferer() |
298
|
|
|
{ |
299
|
|
|
return isset($this->server['HTTP_REFERER']) ? $this->server['HTTP_REFERER'] : null; |
300
|
|
|
} |
301
|
|
|
|
302
|
|
|
public function getHost() |
303
|
|
|
{ |
304
|
|
|
if (!empty($this->server['HTTP_HOST'])) { |
305
|
|
|
return $this->server['HTTP_HOST']; |
306
|
|
|
} elseif (!empty($this->server['SERVER_NAME'])) { |
307
|
|
|
return $this->server['SERVER_NAME']; |
308
|
|
|
} elseif (!empty($this->server['HOSTNAME'])) { |
309
|
|
|
return $this->server['HOSTNAME']; //CLI |
310
|
|
|
} |
311
|
|
|
return null; |
312
|
|
|
} |
313
|
|
|
|
314
|
|
|
public function guessAppUrl() |
315
|
|
|
{ |
316
|
|
|
if (\WebServCo\Framework\Framework::isCLI()) { |
317
|
|
|
return false; |
318
|
|
|
} |
319
|
|
|
return $this->getSchema() . |
320
|
|
|
'://' . |
321
|
|
|
$this->getHost() . |
322
|
|
|
$this->path . |
323
|
|
|
DIRECTORY_SEPARATOR; |
324
|
|
|
} |
325
|
|
|
} |
326
|
|
|
|
This check looks for function or method calls that always return null and whose return value is used.
The method
getObject()
can return nothing but null, so it makes no sense to use the return value.The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.