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: