1: | <?php |
2: | /* |
3: | You may not change or alter any portion of this comment or credits |
4: | of supporting developers from this source code or any supporting source code |
5: | which is considered copyrighted (c) material of the original comment or credit authors. |
6: | |
7: | This program is distributed in the hope that it will be useful, |
8: | but WITHOUT ANY WARRANTY; without even the implied warranty of |
9: | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
10: | */ |
11: | |
12: | namespace Xmf; |
13: | |
14: | /** |
15: | * Request Class |
16: | * |
17: | * This class serves to provide a common interface to access |
18: | * request variables. This includes $_POST, $_GET, and naturally $_REQUEST. Variables |
19: | * can be passed through an input filter to avoid injection or returned raw. |
20: | * |
21: | * @category Xmf\Request |
22: | * @package Xmf |
23: | * @author Richard Griffith <richard@geekwright.com> |
24: | * @author trabis <lusopoemas@gmail.com> |
25: | * @author Joomla! |
26: | * @copyright 2011-2023 XOOPS Project (https://xoops.org) |
27: | * @license GNU GPL 2.0 or later (https://www.gnu.org/licenses/gpl-2.0.html) |
28: | * @link https://xoops.org |
29: | */ |
30: | class Request |
31: | { |
32: | /** |
33: | * Available masks for cleaning variables |
34: | */ |
35: | const MASK_NO_TRIM = 1; |
36: | const MASK_ALLOW_RAW = 2; |
37: | const MASK_ALLOW_HTML = 4; |
38: | |
39: | /** |
40: | * Gets the request method |
41: | * |
42: | * @return string |
43: | */ |
44: | public static function getMethod() |
45: | { |
46: | $method = strtoupper($_SERVER['REQUEST_METHOD']); |
47: | |
48: | return $method; |
49: | } |
50: | |
51: | /** |
52: | * Fetches and returns a given variable. |
53: | * |
54: | * The default behaviour is fetching variables depending on the |
55: | * current request method: GET and HEAD will result in returning |
56: | * an entry from $_GET, POST and PUT will result in returning an |
57: | * entry from $_POST. |
58: | * |
59: | * You can force the source by setting the $hash parameter: |
60: | * |
61: | * - post $_POST |
62: | * - get $_GET |
63: | * - files $_FILES |
64: | * - cookie $_COOKIE |
65: | * - env $_ENV |
66: | * - server $_SERVER |
67: | * - method via current $_SERVER['REQUEST_METHOD'] |
68: | * - default $_REQUEST |
69: | * |
70: | * @param string $name Variable name |
71: | * @param mixed $default Default value if the variable does not exist |
72: | * @param string $hash Source of variable value (POST, GET, FILES, COOKIE, METHOD) |
73: | * @param string $type Return type for the variable (INT, FLOAT, BOOLEAN, WORD, |
74: | * ALPHANUM, CMD, BASE64, STRING, ARRAY, PATH, NONE) For more |
75: | * information see FilterInput::clean(). |
76: | * @param int $mask Filter mask for the variable |
77: | * |
78: | * @return mixed Requested variable |
79: | */ |
80: | public static function getVar($name, $default = null, $hash = 'default', $type = 'none', $mask = 0) |
81: | { |
82: | // Ensure hash and type are uppercase |
83: | $hash = strtoupper($hash); |
84: | if ('METHOD' === $hash) { |
85: | $hash = static::getMethod(); |
86: | } |
87: | $type = strtoupper($type); |
88: | |
89: | // Get the input hash |
90: | switch ($hash) { |
91: | case 'GET': |
92: | $input = &$_GET; |
93: | break; |
94: | case 'POST': |
95: | $input = &$_POST; |
96: | break; |
97: | case 'FILES': |
98: | $input = &$_FILES; |
99: | break; |
100: | case 'COOKIE': |
101: | $input = &$_COOKIE; |
102: | break; |
103: | case 'ENV': |
104: | $input = &$_ENV; |
105: | break; |
106: | case 'SERVER': |
107: | $input = &$_SERVER; |
108: | break; |
109: | default: |
110: | $input = &$_REQUEST; |
111: | break; |
112: | } |
113: | |
114: | if (isset($input[$name]) && null !== $input[$name]) { |
115: | // Get the variable from the input hash and clean it |
116: | $var = static::cleanVar($input[$name], $mask, $type); |
117: | |
118: | // Handle magic quotes compatibility |
119: | if (function_exists('get_magic_quotes_gpc') |
120: | && @get_magic_quotes_gpc() && ($var != $default) |
121: | && ('FILES' !== $hash) |
122: | ) { |
123: | $var = static::stripSlashesRecursive($var); |
124: | } |
125: | } elseif (null !== $default) { |
126: | // Clean the default value |
127: | $var = static::cleanVar($default, $mask, $type); |
128: | } else { |
129: | $var = $default; |
130: | |
131: | } |
132: | |
133: | return $var; |
134: | } |
135: | |
136: | /** |
137: | * Fetches and returns a given filtered variable. The integer |
138: | * filter will allow only digits to be returned. This is currently |
139: | * only a proxy function for getVar(). |
140: | * |
141: | * See getVar() for more in-depth documentation on the parameters. |
142: | * |
143: | * @param string $name Variable name |
144: | * @param int $default Default value if the variable does not exist |
145: | * @param string $hash Where the var should come from (POST, GET, FILES, COOKIE, METHOD) |
146: | * |
147: | * @return int Requested variable |
148: | */ |
149: | public static function getInt($name, $default = 0, $hash = 'default') |
150: | { |
151: | return static::getVar($name, $default, $hash, 'int'); |
152: | } |
153: | |
154: | /** |
155: | * Fetches and returns a given filtered variable. The float |
156: | * filter only allows digits and periods. This is currently |
157: | * only a proxy function for getVar(). |
158: | * |
159: | * See getVar() for more in-depth documentation on the parameters. |
160: | * |
161: | * @param string $name Variable name |
162: | * @param float $default Default value if the variable does not exist |
163: | * @param string $hash Where the var should come from (POST, GET, FILES, COOKIE, METHOD) |
164: | * |
165: | * @return float Requested variable |
166: | */ |
167: | public static function getFloat($name, $default = 0.0, $hash = 'default') |
168: | { |
169: | return static::getVar($name, $default, $hash, 'float'); |
170: | } |
171: | |
172: | /** |
173: | * Fetches and returns a given filtered variable. The bool |
174: | * filter will only return true/false bool values. This is |
175: | * currently only a proxy function for getVar(). |
176: | * |
177: | * See getVar() for more in-depth documentation on the parameters. |
178: | * |
179: | * @param string $name Variable name |
180: | * @param bool $default Default value if the variable does not exist |
181: | * @param string $hash Where the var should come from (POST, GET, FILES, COOKIE, METHOD) |
182: | * |
183: | * @return bool Requested variable |
184: | */ |
185: | public static function getBool($name, $default = false, $hash = 'default') |
186: | { |
187: | return static::getVar($name, $default, $hash, 'bool'); |
188: | } |
189: | |
190: | /** |
191: | * Fetches and returns a given filtered variable. The word |
192: | * filter only allows the characters [A-Za-z_]. This is currently |
193: | * only a proxy function for getVar(). |
194: | * |
195: | * See getVar() for more in-depth documentation on the parameters. |
196: | * |
197: | * @param string $name Variable name |
198: | * @param string $default Default value if the variable does not exist |
199: | * @param string $hash Where the var should come from (POST, GET, FILES, COOKIE, METHOD) |
200: | * |
201: | * @return string Requested variable |
202: | */ |
203: | public static function getWord($name, $default = '', $hash = 'default') |
204: | { |
205: | return static::getVar($name, $default, $hash, 'word'); |
206: | } |
207: | |
208: | /** |
209: | * Fetches and returns a given filtered variable. The cmd filter only allows the characters |
210: | * [A-Za-z0-9.-_] and returns in lower case. This is currently a proxy function for getVar(). |
211: | * |
212: | * See getVar() for more in-depth documentation on the parameters. |
213: | * |
214: | * @param string $name Variable name |
215: | * @param string $default Default value if the variable does not exist |
216: | * @param string $hash Where the var should come from (POST, GET, FILES, COOKIE, METHOD) |
217: | * |
218: | * @return string Requested variable |
219: | */ |
220: | public static function getCmd($name, $default = '', $hash = 'default') |
221: | { |
222: | return static::getVar($name, $default, $hash, 'cmd'); |
223: | } |
224: | |
225: | /** |
226: | * Fetches and returns a given filtered variable. The string |
227: | * filter deletes 'bad' HTML code, if not overridden by the mask. |
228: | * This is currently only a proxy function for getVar(). |
229: | * |
230: | * See getVar() for more in-depth documentation on the parameters. |
231: | * |
232: | * @param string $name Variable name |
233: | * @param string $default Default value if the variable does not exist |
234: | * @param string $hash Where the var should come from (POST, GET, FILES, COOKIE, METHOD) |
235: | * @param int $mask Filter mask for the variable |
236: | * |
237: | * @return string Requested variable |
238: | */ |
239: | public static function getString($name, $default = '', $hash = 'default', $mask = 0) |
240: | { |
241: | // Cast to string, in case static::MASK_ALLOW_RAW was specified for mask |
242: | return (string) static::getVar($name, $default, $hash, 'string', $mask); |
243: | } |
244: | |
245: | /** |
246: | * Fetches and returns an array |
247: | * |
248: | * @param string $name Variable name |
249: | * @param mixed $default Default value if the variable does not exist |
250: | * @param string $hash Where the var should come from (POST, GET, FILES, COOKIE, METHOD) |
251: | * |
252: | * @return array |
253: | */ |
254: | public static function getArray($name, $default = array(), $hash = 'default') |
255: | { |
256: | return static::getVar($name, $default, $hash, 'array'); |
257: | } |
258: | |
259: | /** |
260: | * Fetches and returns raw text |
261: | * |
262: | * @param string $name Variable name |
263: | * @param string $default Default value if the variable does not exist |
264: | * @param string $hash Where the var should come from (POST, GET, FILES, COOKIE, METHOD) |
265: | * |
266: | * @return string Requested variable |
267: | */ |
268: | public static function getText($name, $default = '', $hash = 'default') |
269: | { |
270: | return (string) static::getVar($name, $default, $hash, 'string', static::MASK_ALLOW_RAW); |
271: | } |
272: | |
273: | /** |
274: | * Fetches and returns a web url |
275: | * |
276: | * @param string $name Variable name |
277: | * @param string $default Default value if the variable does not exist |
278: | * @param string $hash Where the var should come from (POST, GET, FILES, COOKIE, METHOD) |
279: | * |
280: | * @return string Requested variable |
281: | */ |
282: | public static function getUrl($name, $default = '', $hash = 'default') |
283: | { |
284: | return (string) static::getVar($name, $default, $hash, 'weburl'); |
285: | } |
286: | |
287: | /** |
288: | * Fetches and returns a file (or web) path |
289: | * |
290: | * @param string $name Variable name |
291: | * @param string $default Default value if the variable does not exist |
292: | * @param string $hash Where the var should come from (POST, GET, FILES, COOKIE, METHOD) |
293: | * |
294: | * @return string Requested variable |
295: | */ |
296: | public static function getPath($name, $default = '', $hash = 'default') |
297: | { |
298: | return (string) static::getVar($name, $default, $hash, 'path'); |
299: | } |
300: | |
301: | /** |
302: | * Fetches and returns an email address |
303: | * |
304: | * @param string $name Variable name |
305: | * @param string $default Default value if the variable does not exist |
306: | * @param string $hash Where the var should come from (POST, GET, FILES, COOKIE, METHOD) |
307: | * |
308: | * @return string email address or default if invalid |
309: | */ |
310: | public static function getEmail($name, $default = '', $hash = 'default') |
311: | { |
312: | $ret = (string) static::getVar($name, $default, $hash, 'email'); |
313: | return empty($ret) ? $default : $ret; |
314: | } |
315: | |
316: | /** |
317: | * Fetches and returns an IP address |
318: | * |
319: | * @param string $name Variable name |
320: | * @param string $default Default value if the variable does not exist |
321: | * @param string $hash Where the var should come from (POST, GET, FILES, COOKIE, METHOD) |
322: | * |
323: | * @return string IP address or default if invalid |
324: | */ |
325: | public static function getIP($name, $default = '', $hash = 'default') |
326: | { |
327: | $ret = (string) static::getVar($name, $default, $hash, 'ip'); |
328: | return empty($ret) ? $default : $ret; |
329: | } |
330: | |
331: | /** |
332: | * get request header |
333: | * |
334: | * @param string $headerName name of header to retrieve, case-insensitive |
335: | * @param string|null $default default to return if named header is not found |
336: | * |
337: | * @return string header value or default if header was not found |
338: | */ |
339: | public static function getHeader($headerName, $default = '') |
340: | { |
341: | /** @var string[] $headers */ |
342: | static $headers = null; |
343: | |
344: | if (null === $headers) { |
345: | $headers = array(); |
346: | if (function_exists('apache_request_headers')) { |
347: | $rawHeaders = apache_request_headers(); |
348: | foreach ($rawHeaders as $name => $value) { |
349: | $headers[strtolower($name)] = $value; |
350: | } |
351: | } else { |
352: | // From joyview - https://php.net/manual/en/function.getallheaders.php |
353: | foreach ($_SERVER as $name => $value) { |
354: | if ('HTTP_' === substr($name, 0, 5)) { |
355: | $translatedName = (string)str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($name, 5)))); |
356: | $headers[$translatedName] = $value; |
357: | } |
358: | } |
359: | } |
360: | } |
361: | |
362: | $name = strtolower($headerName); |
363: | if (isset($headers[$name])) { |
364: | return static::cleanVar($headers[$name]); |
365: | } |
366: | return $default; |
367: | } |
368: | |
369: | /** |
370: | * See if a variable exists in one of the request hashes |
371: | * |
372: | * @param string $name variable to look for |
373: | * @param string $hash hash to check |
374: | * |
375: | * @return bool True if hash has an element 'name', otherwise false |
376: | */ |
377: | public static function hasVar($name, $hash = 'default') |
378: | { |
379: | $hash = strtoupper($hash); |
380: | if ('METHOD' === $hash) { |
381: | $hash = strtoupper($_SERVER['REQUEST_METHOD']); |
382: | } |
383: | |
384: | // Get the requested hash and determine existing value |
385: | $original = static::get($hash, static::MASK_ALLOW_RAW); |
386: | if (isset($original[$name])) { |
387: | return true; |
388: | } |
389: | return false; |
390: | } |
391: | |
392: | /** |
393: | * Set a variable in one of the request variables |
394: | * |
395: | * @param string $name Name |
396: | * @param string $value Value |
397: | * @param string $hash Hash |
398: | * @param bool $overwrite Boolean |
399: | * |
400: | * @return string Previous value |
401: | */ |
402: | public static function setVar($name, $value = null, $hash = 'method', $overwrite = true) |
403: | { |
404: | $hash = strtoupper($hash); |
405: | if ('METHOD' === $hash) { |
406: | $hash = strtoupper($_SERVER['REQUEST_METHOD']); |
407: | } |
408: | |
409: | // Get the requested hash and determine existing value |
410: | $original = static::get($hash, static::MASK_ALLOW_RAW); |
411: | if (isset($original[$name])) { |
412: | $previous = $original[$name]; |
413: | // don't overwrite value unless asked |
414: | if (!$overwrite) { |
415: | return $previous; |
416: | } |
417: | } else { |
418: | $previous = null; |
419: | } |
420: | |
421: | // set the value |
422: | switch ($hash) { |
423: | case 'GET': |
424: | $_GET[$name] = $value; |
425: | $_REQUEST[$name] = $value; |
426: | break; |
427: | case 'POST': |
428: | $_POST[$name] = $value; |
429: | $_REQUEST[$name] = $value; |
430: | break; |
431: | case 'REQUEST': |
432: | $_REQUEST[$name] = $value; |
433: | break; |
434: | case 'COOKIE': |
435: | $_COOKIE[$name] = $value; |
436: | $_REQUEST[$name] = $value; |
437: | break; |
438: | case 'FILES': |
439: | $_FILES[$name] = $value; |
440: | break; |
441: | case 'ENV': |
442: | $_ENV['name'] = $value; |
443: | break; |
444: | case 'SERVER': |
445: | $_SERVER['name'] = $value; |
446: | break; |
447: | } |
448: | |
449: | return $previous; |
450: | } |
451: | |
452: | /** |
453: | * Fetches and returns a request array. |
454: | * |
455: | * The default behaviour is fetching variables depending on the |
456: | * current request method: GET and HEAD will result in returning |
457: | * $_GET, POST and PUT will result in returning $_POST. |
458: | * |
459: | * You can force the source by setting the $hash parameter: |
460: | * |
461: | * - post $_POST |
462: | * - get $_GET |
463: | * - files $_FILES |
464: | * - cookie $_COOKIE |
465: | * - env $_ENV |
466: | * - server $_SERVER |
467: | * - method via current $_SERVER['REQUEST_METHOD'] |
468: | * - default $_REQUEST |
469: | * |
470: | * @param string $hash to get (POST, GET, FILES, METHOD) |
471: | * @param int $mask Filter mask for the variable |
472: | * |
473: | * @return mixed Request hash |
474: | */ |
475: | public static function get($hash = 'default', $mask = 0) |
476: | { |
477: | $hash = strtoupper($hash); |
478: | |
479: | if ('METHOD' === $hash) { |
480: | $hash = strtoupper($_SERVER['REQUEST_METHOD']); |
481: | } |
482: | |
483: | switch ($hash) { |
484: | case 'GET': |
485: | $input = $_GET; |
486: | break; |
487: | case 'POST': |
488: | $input = $_POST; |
489: | break; |
490: | case 'FILES': |
491: | $input = $_FILES; |
492: | break; |
493: | case 'COOKIE': |
494: | $input = $_COOKIE; |
495: | break; |
496: | case 'ENV': |
497: | $input = &$_ENV; |
498: | break; |
499: | case 'SERVER': |
500: | $input = &$_SERVER; |
501: | break; |
502: | default: |
503: | $input = $_REQUEST; |
504: | break; |
505: | } |
506: | |
507: | // Handle magic quotes compatibility |
508: | if (function_exists('get_magic_quotes_gpc') && @get_magic_quotes_gpc() && ('FILES' !== $hash)) { |
509: | $input = static::stripSlashesRecursive($input); |
510: | } |
511: | |
512: | $result = static::cleanVars($input, $mask); |
513: | |
514: | return $result; |
515: | } |
516: | |
517: | /** |
518: | * Sets a request variable |
519: | * |
520: | * @param array $array An associative array of key-value pairs |
521: | * @param string $hash The request variable to set (POST, GET, FILES, METHOD) |
522: | * @param bool $overwrite If true and an existing key is found, the value is overwritten, |
523: | * otherwise it is ignored |
524: | * |
525: | * @return void |
526: | */ |
527: | public static function set($array, $hash = 'method', $overwrite = true) |
528: | { |
529: | foreach ($array as $key => $value) { |
530: | static::setVar($key, $value, $hash, $overwrite); |
531: | } |
532: | } |
533: | |
534: | /** |
535: | * Clean up an input variable. |
536: | * |
537: | * @param mixed $var The input variable. |
538: | * @param int $mask Filter bit mask. |
539: | * - 1=no trim: If this flag is cleared and the input is a string, |
540: | * the string will have leading and trailing whitespace trimmed. |
541: | * - 2=allow_raw: If set, no more filtering is performed, higher bits are ignored. |
542: | * - 4=allow_html: HTML is allowed, but passed through a safe HTML filter first. |
543: | * If set, no more filtering is performed. |
544: | * - If no bits other than the 1 bit is set, a strict filter is applied. |
545: | * @param string $type The variable type. See {@link FilterInput::clean()}. |
546: | * |
547: | * @return string |
548: | */ |
549: | protected static function cleanVar($var, $mask = 0, $type = null) |
550: | { |
551: | // Static input filters for specific settings |
552: | static $noHtmlFilter = null; |
553: | static $safeHtmlFilter = null; |
554: | |
555: | // convert $var in array if $type is ARRAY |
556: | if ('array' === strtolower((string)$type) && !is_array($var)) { |
557: | $var = array($var); |
558: | } |
559: | |
560: | // If the no trim flag is not set, trim the variable |
561: | if (!($mask & static::MASK_NO_TRIM) && is_string($var)) { |
562: | $var = trim($var); |
563: | } |
564: | |
565: | // Now we handle input filtering |
566: | // If the 'allow raw' flag is set, do not modify the variable |
567: | if (!($mask & static::MASK_ALLOW_RAW)) { |
568: | if ($mask & static::MASK_ALLOW_HTML) { |
569: | // If the allow html flag is set, apply a safe html filter to the variable |
570: | if (null === $safeHtmlFilter) { |
571: | $safeHtmlFilter = FilterInput::getInstance(array(), array(), 1, 1); |
572: | } |
573: | $var = $safeHtmlFilter->cleanVar($var, $type); |
574: | } else { |
575: | // Since no allow flags were set, we will apply the most strict filter to the variable |
576: | if (null === $noHtmlFilter) { |
577: | $noHtmlFilter = FilterInput::getInstance(); |
578: | } |
579: | $var = $noHtmlFilter::clean($var, $type); |
580: | } |
581: | } |
582: | |
583: | return $var; |
584: | } |
585: | |
586: | /** |
587: | * Clean up an array of variables. |
588: | * |
589: | * @param mixed $var The input variable. |
590: | * @param int $mask Filter bit mask. See {@link Request::cleanVar()} |
591: | * @param string $type The variable type. See {@link FilterInput::clean()}. |
592: | * |
593: | * @return string |
594: | */ |
595: | protected static function cleanVars($var, $mask = 0, $type = null) |
596: | { |
597: | if (is_array($var)) { |
598: | foreach ($var as $key => &$value) { |
599: | $value = static::cleanVars($value, $mask, $type); |
600: | } |
601: | } else { |
602: | $var = static::cleanVar($var, $mask, $type); |
603: | } |
604: | |
605: | return $var; |
606: | } |
607: | |
608: | /** |
609: | * Strips slashes recursively on an array |
610: | * |
611: | * @param string|array $value string of Array of (nested arrays of) strings |
612: | * |
613: | * @return array The input array with stripslashes applied to it |
614: | */ |
615: | protected static function stripSlashesRecursive($value) |
616: | { |
617: | $value = is_array($value) |
618: | ? array_map(array(get_called_class(), 'stripSlashesRecursive'), $value) |
619: | : stripslashes($value); |
620: | |
621: | return $value; |
622: | } |
623: | } |
624: |