LEPTON CMS 7.2.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 &$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 $range['min'] = 0;
368 }
369
370 if (!array_key_exists('max', $range))
371 {
372 $range['max'] = 255;
373 }
374
375 if (!array_key_exists('char', $range))
376 {
377 $range['char'] = " ";
378 }
379
380 switch (strtolower($type) )
381 {
382 case 'integer':
383 case 'integer+':
384 case 'integer-':
385 case 'integer_eval':
386 case 'float':
387 if (($value < $range['min']) || ($value > $range['max']))
388 {
389 switch (strtolower($range['use']))
390 {
391 case 'default':
392 $value = $default;
393 break;
394
395 case 'min':
396 $value = $range['min'];
397 break;
398
399 case 'max':
400 $value = $range['max'];
401 break;
402
403 case 'near':
404 if ($value <= $range['min'])
405 {
406 $value = $range['min'];
407 }
408
409 if ($value >= $range['max'])
410 {
411 $value = $range['max'];
412 }
413 break;
414
415 default:
416 // nothing
417 break;
418 }
419 }
420 break;
421
422 case 'string':
423 $nc = strlen($value);
424
425 if (($nc < $range['min']) || ($nc > $range['max']))
426 {
427
428 switch(strtolower($range['use']))
429 {
430 case 'default':
431 $value = $default;
432 break;
433
434 case 'fill':
435 for ($i=$nc; $i<=$range['min'];$i++)
436 {
437 $value .= $range['char'];
438 }
439 break;
440
441 case 'cut':
442 $value = substr(
443 $value,
444 0,
445 ( isset($range['max'])
446 ? intval($range['max'])
447 : $nc
448 )
449 );
450 break;
451
452 default:
453 // nothing - keep value as it is
454 break;
455 }
456 }
457 break;
458
459 default:
460 // nothing
461 break;
462 }
463 return true;
464 }
465
466
467 static public function getRequest(string $sField = "")
468 {
469 $sReturnValue = filter_input(
470 INPUT_GET,
471 $sField,
472 FILTER_VALIDATE_REGEXP,
473 [ "options" => [
474 "regexp" => "~^[a-z0-9-_]{2,}$~i",
475 "default" => null
476 ]]
477 );
478
479 if (null !== $sReturnValue)
480 {
481 return $sReturnValue;
482 }
483 else
484 {
485 return filter_input(
486 INPUT_POST,
487 $sField,
488 FILTER_VALIDATE_REGEXP,
489 [ "options" => [
490 "regexp" => "~^[a-z0-9-_]{2,}$~i",
491 "default" => null
492 ]
493 ]
494 );
495 }
496 }
497
498 static public function getPageID()
499 {
500 if (defined("PAGE_ID"))
501 {
502 return PAGE_ID;
503 }
504
505 $sField="page_id" ;
506
507 $sReturnValue = filter_input(
508 INPUT_GET,
509 $sField,
510 FILTER_VALIDATE_REGEXP,
511 [ "options" => [
512 "regexp" => "~^[1-9-]?[0-9]*$~",
513 "default" => null
514 ]
515 ]
516 );
517
518 if (null !== $sReturnValue)
519 {
520 return $sReturnValue;
521 }
522 else
523 {
524 return filter_input(
525 INPUT_POST,
526 $sField,
527 FILTER_VALIDATE_REGEXP,
528 [ "options" => [
529 "regexp" => "~^[1-9-]?[0-9]*$~",
530 "default" => null
531 ]
532 ]
533 );
534 }
535 }
536
546 public function filterValue(
547 string|int|array|float|bool|null $return_value,
548 string $type,
549 string|int|array|float|bool|null $aDefault=null,
550 string|array $range=""
551 ): string|int|array|float|bool|null
552 {
553 switch (strtolower($type))
554 {
555 // [1] Integers
556 // [1.1]
557 case 'integer':
558 case 'number':
559 $return_value = intval($return_value);
560 if (!is_int($return_value)) {
561 $return_value = $aDefault;
562 } else {
563 if ( true === is_array($range) )
564 {
565 $this->check_range($type, $return_value, $aDefault, $range);
566 }
567 }
568 break;
569
570 // [1.2] Only positive integers (without 0)
571 case 'integer+':
572 $return_value = intval($return_value);
573 if (!is_int($return_value))
574 {
575 $return_value = $aDefault;
576 }
577
578 if ($return_value <= 0)
579 {
580 $return_value = $aDefault;
581 }
582
583 if (true === is_array($range) )
584 {
585 $this->check_range($type, $return_value, $aDefault, $range);
586 }
587 break;
588
589 // [1.3] Only negative integers (without 0)
590 case 'integer-':
591 $return_value = intval($return_value);
592 if (!is_int($return_value))
593 {
594 $return_value = $aDefault;
595 }
596
597 if ( $return_value >= 0)
598 {
599 $return_value = $aDefault;
600 }
601
602 if ( true === is_array($range) )
603 {
604 $this->check_range($type, $return_value, $aDefault, $range);
605 }
606 break;
607
608 /* [1.4] decimal
609 * Keep in mind that we only replace the "," (Comma) with "." (decimal-dot)!
610 * to save a valid value in the database.
611 *
612 * e.g. "Win 1.234.300 Euro" will become "1234300"
613 * "1.300.000,34" will become "1300000.34"
614 * "1.300.000.27" will become "1300000.27"
615 * "-23,99" will become "-23.99"
616 */
617 case 'float':
618 case 'double':
619 case 'decimal': // -12.350,78
620 // 1.4.1 remove all NONE numbers (but keep '.', ',' and '-')
621 $sPattern = "/[^0-9-,\.]/i";
622 $return_value = preg_replace (
623 $sPattern,
624 "",
625 (string)$return_value
626 );
627
628 // [1.4.2] replace existing "," with "."
629 $return_value = str_replace(",", ".", $return_value);
630
631 // [1.4.3] force to keep at last ONE dot (.)
632 $aTemp = explode(".", $return_value);
633
634 // [1.4.3.1] more than one dot found!
635 if(count($aTemp) > 2)
636 {
637 $sPrefix = array_pop($aTemp);
638 $return_value = implode("", $aTemp).".".$sPrefix;
639 }
640
641 // [1.4.4] the range
642 if ( true === is_array($range) )
643 {
644 $this->check_range($type, $return_value, $aDefault, $range);
645 }
646 break;
647
648 // [1.5] Evaluate an expression. E.g. "3 * 5" results in 15
649 case 'integer_eval':
650 $return_value = intval(eval("return ".$return_value.";"));
651
652 if (true === is_array($range))
653 {
654 $this->check_range($type, $return_value, $aDefault, $range);
655 }
656 break;
657
658 // [2] Strings
659 // [2.1]
660 case 'string':
661 // keep in mind that pdo add slashes automatically via prepare and execute
662 if (!is_string($return_value))
663 {
664 $return_value = $aDefault;
665 }
666
667 if (true === is_array($range))
668 {
669 $this->check_range($type, $return_value, $aDefault, $range);
670 }
671 break;
672
673 // 2.2 string without any html tags
674 case 'string_clean':
675 if (!is_string($return_value))
676 {
677 $return_value = $aDefault;
678 }
679 else
680 {
681 $return_value = htmlspecialchars(strip_tags($return_value));
682 }
683 break;
684
685 // [2.3] string with all html-tags converted to htmlspecialchars
686 case 'string_chars':
687
688 if (!is_string((string)$return_value))
689 {
690 $return_value = $aDefault;
691 }
692 else
693 {
694 $return_value = lib_lepton::getToolInstance("htmlpurifier")->purify($return_value);
695 $return_value = htmlspecialchars($return_value);
696 }
697 break;
698
699 // [2.4] string without tags but allowed html-tags
700 case 'string_allowed':
701
702 if (!is_string((string)$return_value))
703 {
704 $return_value = $aDefault;
705 }
706 else
707 {
708 $return_value = strip_tags($return_value, $range);
709 }
710 break;
711
712 // [2.5] string only with some chars, see LEPTON_core->string_secure
713 case 'string_secure':
714 if (false === LEPTON_handle::checkStringSecure($return_value))
715 {
716 $return_value = $aDefault;
717 }
718 break;
719
720 // [4.1] E-Mail
721 case 'email':
722 if (!is_string($return_value))
723 {
724 $return_value = $aDefault;
725 }
726 elseif (false === LEPTON_handle::checkEmailChars($return_value))
727 {
728 $return_value = $aDefault;
729 }
730 break;
731
732 // [4.2] username
733 case 'username':
734 if (!is_string($return_value))
735 {
736 $return_value = $aDefault;
737 }
738 elseif (false === LEPTON_handle::checkUsernameChars($return_value))
739 {
740 $return_value = $aDefault;
741 }
742 break;
743
744 // [4.3] password // just to check password chars, NO testing if password is valid
745 case 'password':
746 if (!is_string($return_value))
747 {
748 $return_value = $aDefault;
749 }
750 elseif (false === LEPTON_handle::checkPasswordChars($return_value))
751 {
752 $return_value = $aDefault;
753 }
754 break;
755
756 // [5] Date(-s)
757 // [5.1]
758 case 'date':
759 $format = 'Y-m-d';
760 $d = DateTime::createFromFormat($format, $return_value);
761 $result = $d && $d->format($format) == $return_value;
762 if ($result === false) {
763 $return_value = $aDefault;
764 }
765 break;
766
767 // [5.2]
768 case 'datetime':
769 $format = 'Y-m-d H:i:s';
770 $d = DateTime::createFromFormat($format, $return_value);
771 $result = $d && $d->format($format) == $return_value;
772 if ($result === false) {
773 $return_value = $aDefault;
774 }
775 break;
776
777 // [5.3]
778 case 'datetime_local':
779 $format = 'Y-m-d\TH:i:s';
780 $d = DateTime::createFromFormat($format, $return_value);
781 $result = $d && $d->format($format) == $return_value;
782 if ($result === false) {
783 $return_value = $aDefault;
784 }
785 break;
786
787 // [5.4]
788 case 'month':
789 $format = 'Y-m';
790 $d = DateTime::createFromFormat($format, $return_value);
791 $result = $d && $d->format($format) == $return_value;
792 if ($result === false) {
793 $return_value = $aDefault;
794 }
795 break;
796
797 // [5.5]
798 case 'time': // hour 00:00
799 $format = 'H:i';
800 $d = DateTime::createFromFormat($format, $return_value);
801 $result = $d && $d->format($format) == $return_value;
802 if ($result === false) {
803 $return_value = $aDefault;
804 }
805 break;
806
807 // [5.6]
808 case 'week':
809 // $format = 'Y-W[0-9]{2}';
810 $result = preg_match("/^[1-9][0-9]{3}[-][W][0-9]{2}$/", $return_value);
811 if ($result != 1) {
812 $return_value = $aDefault;
813 }
814 break;
815
816 // [6] Arrays -- Keep in mind that this one could be problematic for recursive requests!
817 case 'array':
818 if (!is_array($return_value))
819 {
820 $return_value = $aDefault;
821 }
822 break;
823
824 // [7] RegExp
825 case 'regexp':
826 if ((true === is_array($range)) && (isset($range['pattern'])))
827 {
828 $test = preg_match($range['pattern'], $return_value);
829 if ($test !== 1)
830 {
831 $return_value = $range['default'] ?? $aDefault;
832 }
833 }
834 break;
835
836 // [8] Boolean
837 case 'bool':
838 $return_value = filter_var(
839 $return_value,
840 FILTER_VALIDATE_BOOLEAN,
841 ['flags' => FILTER_NULL_ON_FAILURE]
842 ) ?? $aDefault;
843 break;
844
845 // [9]
846 default:
847 // nothing above match.
848 break;
849 }
850
851 return $return_value;
852 }
853
854 protected function testType(string $name, string $expected, string $getTypeResult): void
855 {
856 if (true === $this->error_mode)
857 {
858 $types = [
859 'string' => ['string', 'str'],
860 'integer' => ['integer', 'integer+', 'integer-', 'int', 'int+', 'int-']
861 ];
862
863 if (isset($types[$getTypeResult]) && (in_array($expected, $types[$getTypeResult])))
864 {
865
866 }
867 else
868 {
869 $strTemp = "Type does not match! '%s' is not %s. [%s].";
870 $this->writeInfoToLogfile(
871 sprintf(
872 $strTemp,
873 $name,
874 $expected,
875 $getTypeResult
876 )
877 );
878 }
879 }
880 }
881
882 protected function writeInfoToLogfile(string $sMessage=""): void
883 {
884 $sOutputStrg = "[".date("Y-m-d H:i:s")."] ".$sMessage."\n";
885 $sFullPath = dirname(__DIR__, 2).$this->logFilePath.$this->logFileName;
886 file_put_contents($sFullPath, $sOutputStrg, FILE_APPEND);
887 }
888}
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="")
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