LEPTON CMS 7.3.0
feel free to keep it strictly simple...
Loading...
Searching...
No Matches
lepton_request.php
Go to the documentation of this file.
1<?php
2
3declare(strict_types=1);
4
26{
28
29 const USE_POST = "post";
30 const USE_GET = "get";
31 const USE_REQUEST = "request";
32 const USE_SESSION = "session";
33 const USE_SERVER = "server";
34
41 ];
42
43 public static $instance;
44
53 protected string $strict_looking_inside = "post";
54
63 public bool $error_mode = false;
64
71 public string $logFileName = "LEPTON_request.log";
72
79 public string $logFilePath = "/temp/secure/";
80
89 public array $errors = [];
90
91 public function setStrictLookInside(string $sNewValue = ''): bool
92 {
93 if ($sNewValue === '')
94 {
95 return false;
96 }
97
98 $sNewValueLower = strtolower($sNewValue);
99
100 if (in_array($sNewValueLower, self::ALLOWED_INSIDE))
101 {
102 $this->strict_looking_inside = $sNewValueLower;
103 return true;
104 } else {
105 return false;
106 }
107 }
108
130 public function testPostValues(array &$aValueList ): array
131 {
132 $this->strict_looking_inside = "post";
133
134 $aReturnList = [];
135 foreach($aValueList as $term => $options)
136 {
137 $aReturnList[ $term ] = $this->get_request(
138 $term,
139 $options['default'],
140 $options['type'],
141 (isset($options['range']) ? $options['range'] : "" )
142 );
143 }
144
145 return $aReturnList;
146 }
147
170 public function testGetValues(array &$aValueList): array
171 {
172 $this->strict_looking_inside = "get";
173
174 $aReturnList = [];
175 foreach($aValueList as $term => $options)
176 {
177 $aReturnList[ $term ] = $this->get_request(
178 $term,
179 $options['default'],
180 $options['type'],
181 (isset($options['range']) ? $options['range'] : "" )
182 );
183 }
184
185 return $aReturnList;
186 }
187
195 public function testValues(array &$aValueList): array
196 {
197 $aReturnList = [];
198 foreach($aValueList as $term => $options)
199 {
200 $aReturnList[ $term ] = $this->get_request(
201 $term,
202 $options['default'],
203 $options['type'],
204 (isset($options['range']) ? $options['range'] : "" )
205 );
206 }
207
208 return $aReturnList;
209 }
210
211
270 public function get_request(string $aName="", string|int|array|float|bool|null $aDefault=null, string $type="", string|array $range="")
271 {
272
273 if ($aName == "")
274 {
275 return null;
276 }
277
278 if (false === $this->strict_looking_inside)
279 {
280
281 if (strtoupper($_SERVER['REQUEST_METHOD']) == "POST")
282 {
283 $return_value = (true === array_key_exists ($aName , $_POST) ) ? $_POST[$aName] : $aDefault;
284 }
285 else
286 {
287 $return_value = (true === array_key_exists ($aName , $_GET) ) ? $_GET[$aName] : $aDefault;
288 }
289 }
290 else
291 {
292 switch ($this->strict_looking_inside)
293 {
294 case self::USE_POST:
295 $return_value = $_POST[$aName] ?? $aDefault;
296 break;
297
298 case self::USE_GET:
299 $return_value = $_GET[$aName] ?? $aDefault;
300 break;
301
303 $return_value = $_REQUEST[$aName] ?? $aDefault;
304 break;
305
307 $return_value = $_SESSION[$aName] ?? $aDefault;
308 break;
309
310 case self::USE_SERVER:
311 $return_value = $_SERVER[$aName] ?? $aDefault;
312 break;
313
314 default:
315 $return_value = null;
316 break;
317 }
318 }
319
320 if (!empty($type))
321 {
322 // $this->testType($aName, $type, gettype($return_value));
323
324 if (is_array($return_value) && ($type != "array"))
325 {
326 foreach ($return_value as $key => &$tempValue)
327 {
328 $tempValue = $this->filterValue($tempValue, $type, $aDefault, $range);
329 }
330 }
331 else
332 {
333 $return_value = $this->filterValue($return_value, $type, $aDefault, $range);
334 }
335 }
336 return $return_value;
337 }
338
339 static public function add_slash(string &$sText="" ): void
340 {
341 if (substr($sText, 0,1) != "/")
342 {
343 $sText = "/".$sText;
344 }
345
346 if (substr($sText, -1) != "/")
347 {
348 $sText .= "/";
349 }
350 }
351
352 private function check_range(string $type, int|string|array|float &$value, int|string|array|float|null &$default, string|array|float|int &$range)
353 {
354
355 if (is_null($value))
356 {
357 return true;
358 }
359
360 if (!array_key_exists('use', $range))
361 {
362 $range['use'] = 'default';
363 }
364
365 if (!array_key_exists('min', $range))
366 {
367 switch (strtolower($type))
368 {
369 case 'date':
370 $range['min'] = '2000-01-01';
371 break;
372
373 case 'datetime':
374 case 'timestamp':
375 $range['min'] = '2000-01-01 00:00:00';
376 break;
377
378 case 'time':
379 $range['min'] = "00:00";
380 break;
381
382 default:
383 $range['min'] = 0;
384 break;
385 }
386 }
387
388 if (!array_key_exists('max', $range))
389 {
390 switch (strtolower($type))
391 {
392 case 'date':
393 $range['max'] = '2048-01-01';
394 break;
395
396 case 'datetime':
397 case 'timestamp':
398 $range['max'] = '2048-12-31 23:59:59';
399 break;
400
401 case 'time':
402 $range['max'] = "23:59";
403 break;
404
405 default:
406 $range['max'] = 255;
407 break;
408 }
409 }
410
411 if (!array_key_exists('char', $range))
412 {
413 $range['char'] = " ";
414 }
415
416 switch (strtolower($type) )
417 {
418 case 'integer':
419 case 'integer+':
420 case 'integer-':
421 case 'integer_eval':
422 case 'float':
423 case 'number':
424 if (($value < $range['min']) || ($value > $range['max']))
425 {
426 switch (strtolower($range['use']))
427 {
428 case 'default':
429 $value = $default;
430 break;
431
432 case 'min':
433 $value = $range['min'];
434 break;
435
436 case 'max':
437 $value = $range['max'];
438 break;
439
440 case 'near':
441 if ($value <= $range['min'])
442 {
443 $value = $range['min'];
444 }
445
446 if ($value >= $range['max'])
447 {
448 $value = $range['max'];
449 }
450 break;
451
452 default:
453 // nothing
454 break;
455 }
456 }
457 break;
458
459 case 'string':
460 $nc = strlen($value);
461
462 if (($nc < $range['min']) || ($nc > $range['max']))
463 {
464
465 switch(strtolower($range['use']))
466 {
467 case 'default':
468 $value = $default;
469 break;
470
471 case 'fill':
472 for ($i=$nc; $i<=$range['min'];$i++)
473 {
474 $value .= $range['char'];
475 }
476 break;
477
478 case 'cut':
479 $value = substr(
480 $value,
481 0,
482 ( isset($range['max'])
483 ? intval($range['max'])
484 : $nc
485 )
486 );
487 break;
488
489 default:
490 // nothing - keep value as it is
491 break;
492 }
493 }
494 break;
495
496 case 'date':
497 case 'datetime':
498 case 'timestamp':
499 $iValue = strtotime($value);
500 $iMin = strtotime($range['min']);
501 $iMax = strtotime($range['max']);
502 if (($iValue < $iMin) || ($iValue > $iMax))
503 {
504 switch(strtolower($range['use']))
505 {
506 case 'default':
507 $value = $default;
508 break;
509
510 case 'min':
511 $value = $range['min'];
512 break;
513
514 case 'max':
515 $value = $range['max'];
516 break;
517
518 case 'near':
519 $value = ($iValue < $iMin)
520 ? $range['min']
521 : $range['max']
522 ;
523
524 default:
525 // nothing - keep value as it is
526 break;
527 }
528 }
529 break;
530
531 case 'time':
532 $aValue = explode(":", $value);
533 $iValue = mktime(intval($aValue[0]),intval($aValue[1]), 0, 1, 1, 1970);
534
535 $aMin = explode(":", $range['min']);
536 $iMin = mktime(intval($aMin[0]),intval($aMin[1]), 0, 1, 1, 1970);
537
538 $aMax = explode(":", $range['max']);
539 $iMax = mktime(intval($aMax[0]),intval($aMax[1]), 0, 1, 1, 1970);
540
541 if (($iValue < $iMin) || ($iValue > $iMax))
542 {
543 switch(strtolower($range['use']))
544 {
545 case 'default':
546 $value = $default;
547 break;
548
549 case 'min':
550 $value = $range['min'];
551 break;
552
553 case 'max':
554 $value = $range['max'];
555 break;
556
557 case 'near':
558 $value = ($iValue < $iMin)
559 ? $range['min']
560 : $range['max']
561 ;
562
563 default:
564 // nothing - keep value as it is
565 break;
566 }
567 }
568
569 break;
570
571 default:
572 // nothing
573 break;
574 }
575 return true;
576 }
577
578
579 static public function getRequest(string $sField = "")
580 {
581 $sReturnValue = filter_input(
582 INPUT_GET,
583 $sField,
584 FILTER_VALIDATE_REGEXP,
585 [ "options" => [
586 "regexp" => "~^[a-z0-9-_]{2,}$~i",
587 "default" => null
588 ]]
589 );
590
591 if (null !== $sReturnValue)
592 {
593 return $sReturnValue;
594 }
595 else
596 {
597 return filter_input(
598 INPUT_POST,
599 $sField,
600 FILTER_VALIDATE_REGEXP,
601 [ "options" => [
602 "regexp" => "~^[a-z0-9-_]{2,}$~i",
603 "default" => null
604 ]
605 ]
606 );
607 }
608 }
609
610 static public function getPageID()
611 {
612 if (defined("PAGE_ID"))
613 {
614 return PAGE_ID;
615 }
616
617 $sField="page_id" ;
618
619 $sReturnValue = filter_input(
620 INPUT_GET,
621 $sField,
622 FILTER_VALIDATE_REGEXP,
623 [ "options" => [
624 "regexp" => "~^[1-9-]?[0-9]*$~",
625 "default" => null
626 ]
627 ]
628 );
629
630 if (null !== $sReturnValue)
631 {
632 return $sReturnValue;
633 }
634 else
635 {
636 return filter_input(
637 INPUT_POST,
638 $sField,
639 FILTER_VALIDATE_REGEXP,
640 [ "options" => [
641 "regexp" => "~^[1-9-]?[0-9]*$~",
642 "default" => null
643 ]
644 ]
645 );
646 }
647 }
648
658 public function filterValue(
659 string|int|array|float|bool|null $return_value,
660 string $type,
661 string|int|array|float|bool|null $aDefault=null,
662 string|array $range=""
663 ): string|int|array|float|bool|null
664 {
665 switch (strtolower($type))
666 {
667 // [1] Integers
668 // [1.1]
669 case 'number':
670 case 'integer':
671 $return_value = intval($return_value);
672 if (!is_int($return_value)) {
673 $return_value = $aDefault;
674 } else {
675 if (true === is_array($range))
676 {
677 $this->check_range($type, $return_value, $aDefault, $range);
678 }
679 }
680 break;
681
682 // [1.2] Only positive integers (without 0)
683 case 'integer+':
684 $return_value = intval($return_value);
685 if (!is_int($return_value))
686 {
687 $return_value = $aDefault;
688 }
689
690 if ($return_value <= 0)
691 {
692 $return_value = $aDefault;
693 }
694
695 if (true === is_array($range) )
696 {
697 $this->check_range($type, $return_value, $aDefault, $range);
698 }
699 break;
700
701 // [1.3] Only negative integers (without 0)
702 case 'integer-':
703 $return_value = intval($return_value);
704 if (!is_int($return_value))
705 {
706 $return_value = $aDefault;
707 }
708
709 if ( $return_value >= 0)
710 {
711 $return_value = $aDefault;
712 }
713
714 if ( true === is_array($range) )
715 {
716 $this->check_range($type, $return_value, $aDefault, $range);
717 }
718 break;
719
720 /* [1.4] decimal
721 * Keep in mind that we only replace the "," (Comma) with "." (decimal-dot)!
722 * to save a valid value in the database.
723 *
724 * e.g. "Win 1.234.300 Euro" will become "1234300"
725 * "1.300.000,34" will become "1300000.34"
726 * "1.300.000.27" will become "1300000.27"
727 * "-23,99" will become "-23.99"
728 */
729 case 'float':
730 case 'double':
731 case 'decimal': // -12.350,78
732 // 1.4.1 remove all NONE numbers (but keep '.', ',' and '-')
733 $sPattern = "/[^0-9-,\.]/i";
734 $return_value = preg_replace (
735 $sPattern,
736 "",
737 (string)$return_value
738 );
739
740 // [1.4.2] replace existing "," with "."
741 $return_value = str_replace(",", ".", $return_value);
742
743 // [1.4.3] force to keep at last ONE dot (.)
744 $aTemp = explode(".", $return_value);
745
746 // [1.4.3.1] more than one dot found!
747 if(count($aTemp) > 2)
748 {
749 $sPrefix = array_pop($aTemp);
750 $return_value = implode("", $aTemp).".".$sPrefix;
751 }
752
753 // [1.4.4] the range
754 if ( true === is_array($range) )
755 {
756 $this->check_range($type, $return_value, $aDefault, $range);
757 }
758 break;
759
760 // [1.5] Evaluate an expression. E.g. "3 * 5" results in 15
761 case 'integer_eval':
762 $return_value = intval(eval("return ".$return_value.";"));
763
764 if (true === is_array($range))
765 {
766 $this->check_range($type, $return_value, $aDefault, $range);
767 }
768 break;
769
770 // [2] Strings
771 // [2.1]
772 case 'string':
773 // keep in mind that pdo add slashes automatically via prepare and execute
774 if (!is_string($return_value))
775 {
776 $return_value = $aDefault;
777 }
778
779 if (true === is_array($range))
780 {
781 $this->check_range($type, $return_value, $aDefault, $range);
782 }
783 break;
784
785 // 2.2 string without any html tags
786 case 'string_clean':
787 if (!is_string($return_value))
788 {
789 $return_value = $aDefault;
790 }
791 else
792 {
793 $return_value = htmlspecialchars(strip_tags($return_value));
794 }
795 break;
796
797 // [2.3] string with all html-tags converted to htmlspecialchars
798 case 'string_chars':
799
800 if (!is_string($return_value))
801 {
802 $return_value = $aDefault;
803 }
804 else
805 {
806 $return_value = lib_lepton::getToolInstance("htmlpurifier")->purify($return_value);
807 $return_value = htmlspecialchars($return_value);
808 }
809 break;
810
811 // [2.4] string without tags but allowed html-tags
812 case 'string_allowed':
813
814 if (!is_string($return_value))
815 {
816 $return_value = $aDefault;
817 }
818 else
819 {
820 $return_value = strip_tags($return_value, $range);
821 }
822 break;
823
824 // [2.5] string only with some chars, see LEPTON_core->string_secure
825 case 'string_secure':
826 if (false === LEPTON_handle::checkStringSecure($return_value))
827 {
828 $return_value = $aDefault;
829 }
830 break;
831
832 // [4.1] E-Mail
833 case 'email':
834 if (!is_string($return_value))
835 {
836 $return_value = $aDefault;
837 }
838 elseif (false === LEPTON_handle::checkEmailChars($return_value))
839 {
840 $return_value = $aDefault;
841 }
842 break;
843
844 // [4.2] username
845 case 'username':
846 if (!is_string($return_value))
847 {
848 $return_value = $aDefault;
849 }
850 elseif (false === LEPTON_handle::checkUsernameChars($return_value))
851 {
852 $return_value = $aDefault;
853 }
854 break;
855
856 // [4.3] password // just to check password chars, NO testing if password is valid
857 case 'password':
858 if (!is_string($return_value))
859 {
860 $return_value = $aDefault;
861 }
862 elseif (false === LEPTON_handle::checkPasswordChars($return_value))
863 {
864 $return_value = $aDefault;
865 }
866 break;
867
868 // [5] Date(-s)
869 // [5.1]
870 case 'date':
871 if (!is_string($return_value))
872 {
873 $return_value = $aDefault;
874 } else {
875 $format = 'Y-m-d';
876 $d = DateTime::createFromFormat($format, $return_value);
877 $result = $d && $d->format($format) == $return_value;
878 if ($result === false) {
879 $return_value = $aDefault;
880 } else {
881 if (true === is_array($range) )
882 {
883 $this->check_range($type, $return_value, $aDefault, $range);
884 }
885 }
886 }
887 break;
888
889 // [5.2]
890 case 'datetime':
891 case 'timestamp':
892 if (!is_string($return_value))
893 {
894 $return_value = $aDefault;
895 } else {
896 $format = 'Y-m-d H:i:s';
897 $d = DateTime::createFromFormat($format, $return_value);
898 $result = $d && $d->format($format) == $return_value;
899 if ($result === false) {
900 $return_value = $aDefault;
901 } else {
902 if (true === is_array($range) )
903 {
904 $this->check_range($type, $return_value, $aDefault, $range);
905 }
906 }
907 }
908 break;
909
910 // [5.3]
911 case 'datetime_local':
912 if (!is_string($return_value))
913 {
914 $return_value = $aDefault;
915 } else {
916 $format = 'Y-m-d\TH:i:s';
917 $d = DateTime::createFromFormat($format, $return_value);
918 $result = $d && $d->format($format) == $return_value;
919 if ($result === false) {
920 $return_value = $aDefault;
921 }
922 }
923 break;
924
925 // [5.4]
926 case 'month':
927 if (!is_string($return_value))
928 {
929 $return_value = $aDefault;
930 } else {
931 $format = 'Y-m';
932 $d = DateTime::createFromFormat($format, $return_value);
933 $result = $d && $d->format($format) == $return_value;
934 if ($result === false) {
935 $return_value = $aDefault;
936 }
937 }
938 break;
939
940 // [5.5]
941 case 'time': // hour 00:00
942 if (!is_string($return_value))
943 {
944 $return_value = $aDefault;
945 } else {
946 $format = 'H:i';
947 $d = DateTime::createFromFormat($format, $return_value);
948 $result = $d && $d->format($format) == $return_value;
949 if ($result === false) {
950 $return_value = $aDefault;
951 } else {
952 if (true === is_array($range) )
953 {
954 $this->check_range($type, $return_value, $aDefault, $range);
955 }
956 }
957 }
958 break;
959
960 // [5.6]
961 case 'week':
962 if (!is_string($return_value))
963 {
964 $return_value = $aDefault;
965 } else {
966 // $format = 'Y-W[0-9]{2}';
967 $result = preg_match("/^[1-9][0-9]{3}[-][W][0-9]{2}$/", $return_value);
968 if ($result != 1) {
969 $return_value = $aDefault;
970 }
971 }
972 break;
973
974 // [6] Arrays -- Keep in mind that this one could be problematic for recursive requests!
975 case 'array':
976 if (!is_array($return_value))
977 {
978 $return_value = $aDefault;
979 }
980 break;
981
982 // [7] RegExp
983 case 'regexp':
984 if ((true === is_array($range)) && (isset($range['pattern'])))
985 {
986 $test = preg_match($range['pattern'], $return_value);
987 if ($test !== 1)
988 {
989 $return_value = $range['default'] ?? $aDefault;
990 }
991 }
992 break;
993
994 // [8] Boolean
995 case 'bool':
996 $return_value = filter_var(
997 $return_value,
998 FILTER_VALIDATE_BOOLEAN,
999 ['flags' => FILTER_NULL_ON_FAILURE]
1000 ) ?? $aDefault;
1001 break;
1002
1003 // [9]
1004 default:
1005 // nothing above match.
1006 break;
1007 }
1008
1009 return $return_value;
1010 }
1011
1028 static public function getStringToArray(string $input, string $delimiter=";", string $subdelimiter = ":"): array
1029 {
1030 $aTemp = explode($delimiter, $input);
1031 $aReturn = [];
1032 foreach ($aTemp as $term)
1033 {
1034 if (!empty($term))
1035 {
1036 $aTerm = explode($subdelimiter, $term);
1037 $aReturn[trim($aTerm[0])] = trim($aTerm[1] ?? "");
1038 }
1039 }
1040 return $aReturn;
1041 }
1042
1043 protected function testType(string $name, string $expected, string $getTypeResult): void
1044 {
1045 if (true === $this->error_mode)
1046 {
1047 $types = [
1048 'string' => ['string', 'str'],
1049 'integer' => ['integer', 'integer+', 'integer-', 'int', 'int+', 'int-']
1050 ];
1051
1052 if (isset($types[$getTypeResult]) && (in_array($expected, $types[$getTypeResult])))
1053 {
1054
1055 }
1056 else
1057 {
1058 $strTemp = "Type does not match! '%s' is not %s. [%s].";
1059 $this->writeInfoToLogfile(
1060 sprintf(
1061 $strTemp,
1062 $name,
1063 $expected,
1064 $getTypeResult
1065 )
1066 );
1067 }
1068 }
1069 }
1070
1071 protected function writeInfoToLogfile(string $sMessage=""): void
1072 {
1073 $sOutputStrg = "[".date("Y-m-d H:i:s")."] ".$sMessage."\n";
1074 $sFullPath = dirname(__DIR__, 2).$this->logFilePath.$this->logFileName;
1075 file_put_contents($sFullPath, $sOutputStrg, FILE_APPEND);
1076 }
1077
1078}
static checkPasswordChars(string $sPassword)
static checkEmailChars(string $sEmail)
static checkUsernameChars(string $sName)
static checkStringSecure(string $sString)
static add_slash(string &$sText="")
string $strict_looking_inside
static getRequest(string $sField="")
filterValue(string|int|array|float|bool|null $return_value, string $type, string|int|array|float|bool|null $aDefault=null, string|array $range="")
static getStringToArray(string $input, string $delimiter=";", string $subdelimiter=":")
writeInfoToLogfile(string $sMessage="")
testType(string $name, string $expected, string $getTypeResult)
get_request(string $aName="", string|int|array|float|bool|null $aDefault=null, string $type="", string|array $range="")
setStrictLookInside(string $sNewValue='')
testGetValues(array &$aValueList)
testValues(array &$aValueList)
testPostValues(array &$aValueList)
trait LEPTON_singleton