LEPTON CMS 7.3.0
feel free to keep it strictly simple...
Loading...
Searching...
No Matches
lepton_core.php
Go to the documentation of this file.
1<?php
2
3declare(strict_types=1);
4
21class LEPTON_core extends LEPTON_securecms
22{
24
25 public static $instance;
26
27 public string $string_secure = 'a-zA-Z0-9\-_\.';
28
29 public string $password_chars = 'a-zA-Z0-9\_\-\!\$\ย\ง\#\*\+';
30
31 public string $email_chars = 'a-zA-Z0-9@\_\-\.';
32
33 public string $username_chars = 'a-zA-Z0-9@ \_\-,\.';
34
35 public string $hex_chars = 'a-fA-F0-9\-';
36
37 public static array $HEADERS = [
38 'frontend' => [
39 'css' => [],
40 'js' => []
41 ],
42 'backend' => [
43 'css' => [],
44 'js' => []
45 ]
46 ];
47
48 public static array $FOOTERS = [
49 'frontend' => [
50 'css' => [],
51 'js' => []
52 ],
53 'backend' => [
54 'css' => [],
55 'js' => []
56 ]
57 ];
58
59 public static bool $bUserGotAdminRights = false;
60
64 public function __construct()
65 {
66
67 }
68
77 public function page_is_visible( $page ): bool
78 {
79 // First check if visibility is 'none', 'deleted'
80
81 $show_it = false;
82 switch ($page['visibility'])
83 {
84 case 'hidden':
85 case 'public':
86 $show_it = true;
87 break;
88
89 case 'private':
90 case 'registered':
91 if ($this->is_authenticated() === true)
92 {
93 $show_it = ($this->is_group_match($this->getValue('groups_id', 'string', 'session',','), $page['viewing_groups']) );
94 }
95 break;
96
97 case 'none':
98 case 'deleted':
99 default:
100 $show_it = false;
101 break;
102 }
103
104 return ($show_it);
105 }
106
114 public function section_is_active(int $section_id): bool
115 {
116 $now = time();
117 $sql = "
118 SELECT COUNT(*)
119 FROM `" . TABLE_PREFIX . "sections`
120 WHERE (" . $now . " BETWEEN `publ_start` AND `publ_end`)
121 OR (" . $now . " > `publ_start` AND `publ_end`=0)
122 AND `section_id`=" . $section_id;
123
124 return (LEPTON_database::getInstance()->get_one($sql) > 0);
125 }
126
134 public function page_is_active(array $page ): bool
135 {
136 $now = time();
137 $sql = "
138 SELECT COUNT(*)
139 FROM `".TABLE_PREFIX."sections`
140 WHERE `page_id` = ".$page['page_id']."
141 AND (".$now." BETWEEN `publ_start` AND `publ_end` OR (".$now." > `publ_start` AND `publ_end`= 0))
142 ";
143
144 return (LEPTON_database::getInstance()->get_one($sql) > 0 );
145 }
146
153 public function show_page(array|null $page ): bool
154 {
155 if (!is_array($page))
156 {
157 $page = [];
158 LEPTON_database::getInstance()->execute_query(
159 "SELECT `page_id`, `visibility` FROM `" . TABLE_PREFIX . "pages` WHERE `page_id`=" . (int) $page,
160 true,
161 $page,
162 false
163 );
164
165 if (empty($page))
166 {
167 return false;
168 }
169 }
170 return ($this->page_is_visible($page) && $this->page_is_active($page));
171 }
172
173 // Check if the user is already authenticated or not
174 public function is_authenticated(): bool
175 {
176 return ( (isset( $_SESSION[ 'USER_ID' ] ) ) // gesetzt
177 && ($_SESSION[ 'USER_ID' ] != "") // nicht leer
178 && (is_numeric( $_SESSION[ 'USER_ID' ] ) ) // eine Zahl
179 );
180 }
181
189 public function buildPageLink(string $link): string
190 {
191 // Check for :// in the link (used in URL's) as well as mailto:
192 if (strstr($link, '://') == '' && !str_starts_with($link, 'mailto:'))
193 {
194 return LEPTON_URL . PAGES_DIRECTORY . $link . PAGE_EXTENSION;
195 }
196 else
197 {
198 return $link;
199 }
200 }
201
202 // @ADD_method 20230907: for use instead of old marked deprecated methods
229 public static function getValue(
230 string $lookForName,
231 string $type = "string_clean",
232 string $requestFrom = "post",
233 string $dividerString = "X",
234 string|int|array|null $default = null,
235 string|int|array|null $range = null
236 ): string|int|array|null
237 {
238 // $_SESSION keys are always upper case
239 if ($requestFrom == 'session')
240 {
241 $lookForName = strtoupper($lookForName);
242 }
243
244 LEPTON_request::getInstance()->setStrictLookInside($requestFrom);
245 $aField = [ $lookForName => [
246 'type' => $type,
247 'default' => $default,
248 'range' => $range
249 ]
250 ];
251 $sTested = LEPTON_request::getInstance()->testValues($aField);
252
253 // L*VII.3 if result is NULL or EMPTY and the default value is set, use the default
254 if ((is_null($sTested[$lookForName]) || empty($sTested[$lookForName])) && (!empty($default)))
255 {
256 $sTested[$lookForName] = $default;
257 }
258 // make sure that comma seperated strings are exploded
259 if ($dividerString != 'X')
260 {
261 if (!is_array($sTested[$lookForName]))
262 {
263 $sTested[$lookForName] = explode($dividerString, $sTested[$lookForName] ?? "");
264 } else {
265 foreach ($sTested[$lookForName] as &$item)
266 {
267 $item = explode($dividerString, $item ?? "");
268 }
269 }
270 }
271 return $sTested[$lookForName];
272 }
273
282 public function is_group_match(int|string|array $groups_list1 = '', int|string|array $groups_list2 = ''): bool
283 {
284 if ($groups_list1 == '')
285 {
286 return false;
287 }
288 if ($groups_list2 == '')
289 {
290 return false;
291 }
292 if (!is_array($groups_list1))
293 {
294 $groups_list1 = explode( ',', $groups_list1 );
295 }
296 if (!is_array($groups_list2))
297 {
298 $groups_list2 = explode( ',', $groups_list2 );
299 }
300
301 return (sizeof(array_intersect($groups_list1, $groups_list2)) != 0);
302 }
303
312 public static function addItems(string $for = 'frontend', string $path = LEPTON_PATH, bool $footer = false): void
313 {
314 $trail = explode('/', $path);
315 $subdir = array_pop($trail);
316
317 $mod_headers = [];
318 $mod_footers = [];
319
320 if ($footer)
321 {
322 $add_to = &self::$FOOTERS;
323 $to_load = 'footers.inc.php';
324 }
325 else
326 {
327 $add_to = &self::$HEADERS;
328 $to_load = 'headers.inc.php';
329 }
330
331 require $path.'/'.$to_load;
332
333 if (true === $footer)
334 {
335 $aRefArray = &$mod_footers;
336 }
337 else
338 {
339 $aRefArray = &$mod_headers;
340 }
341
342 if (count($aRefArray))
343 {
344 foreach (['css', 'js'] as $key)
345 {
346 if (!isset($aRefArray[$for][$key]))
347 {
348 continue;
349 }
350 foreach ($aRefArray[$for][$key] as &$item)
351 {
352 // let's see if the path is relative (i.e., does not contain the current subdir)
353 if ((isset($item['file']))
354 && (!preg_match("#/$subdir/#", $item['file']))
355 && (file_exists($path.'/'.$item['file']))
356 )
357 {
358 // treat path as relative, add modules subfolder
359 $item['file'] = str_ireplace(LEPTON_PATH, '', $path).'/'.$item['file'];
360 }
361
362 $is_ok = true;
363 if ($key === "css") {
364 foreach ($add_to[$for][$key] as $temp_ref)
365 {
366 if ($temp_ref['file'] == $item['file'])
367 {
368 $is_ok = false;
369 }
370 }
371 } elseif ($key === "js")
372 {
373 foreach ($add_to[$for][$key] as $temp_ref)
374 {
375 if ($item === $temp_ref)
376 {
377 $is_ok = false;
378 }
379 }
380
381 }
382
383 if (true === $is_ok)
384 {
385 $add_to[$for][$key][] = $item;
386 }
387 }
388 }
389 }
390
391 if ($footer && file_exists($path.$for.'_body.js'))
392 {
393 $add_to[$for]['js'][] = '/modules/'.$subdir.'_body.js';
394 }
395
396 }
397
403 public function getProtectedFunctions(string &$html, object &$oReference): void
404 {
405 $this->addLepToken($html, $oReference);
406 }
407
412 protected function addLepToken(string &$html, object &$oReference): void
413 {
417 if (!LEPTOKEN_LIFETIME)
418 {
419 return;
420 }
421
422 $token = $oReference->createLepToken();
423
424 $token1 = "$1?leptoken=".$token."$3"; // no parameters so far
425 $token2 = "leptoken=".$token; // for replacing placeholder in JS functions
426 $token3 = "$1&leptoken=".$token."$3"; // with existing parameters, produces html-valid code
427 $token4 = "$1?leptoken=".$token."$2"; // for special cases
428 $hiddentoken = "$1\n<span><input type='hidden' name='leptoken' value='".$token."' /></span>\n"; // for GET forms, add a hidden field too
429
430 // finds absolute Links with Parameter:
431 $qs = '~((href|action|window\.location)\s?=\s?[\'"]' . LEPTON_URL . '[\w\-\./]+\.php\?[\w\-\.=&%;/]+)([#[\w]*]?[\'"])~';
432 $html = preg_replace( $qs, $token3, $html, -1 );
433
434 // finds absolute Links without Parameter:
435 $qs = '~((href|action|ajaxfilemanagerurl|window\.location)\s?=\s?[\'"]' . LEPTON_URL . '[\w\-\./]+\.php)([#[\w]*]?[\'"])~';
436 $html = preg_replace( $qs, $token1, $html, -1 );
437
438 // finds relative Links with Parameter:
439 $qs = '~((href|action|window\.location)\s?=\s?[\'"][\w/]+\.php\?[\w\-\.=%&;/]+)([#[\w]*]?[\'"])~';
440 $html = preg_replace( $qs, $token3, $html, -1 );
441
442 // finds relative Links without Parameter:
443 $qs = '~((href|action|window\.location)\s?=\s?[\'"][\w/]+\.php)([#[\w]*]?[\'"])~';
444 $html = preg_replace( $qs, $token1, $html, -1 );
445
446 // finds Start page without Parameter:
447 $qs = '~(href\s?=\s?[\'"]' . LEPTON_URL . ')([\'"])~';
448 $html = preg_replace( $qs, $token4, $html, -1 );
449
450 // finds Testmail in Options:
451 $qs = '~(send_testmail\‍(\'' . ADMIN_URL . '/settings/ajax_testmail\.php)(\'\‍))~';
452 $html = preg_replace( $qs, $token4, $html, -1 );
453
454 // finds forms with method=get and adds a hidden field
455 $qs = '~(<form\s+action=[\'"][\w:\.\?/]+leptoken=\w{32}[\'"]\s+method=[\'"]get[\'"]\s*>)~';
456 $html = preg_replace( $qs, $hiddentoken, $html, -1 );
457
458 // set leptoken in JS functions
459 $qs = '~leptokh=#-!leptoken-!#~';
460 $html = preg_replace( $qs, $token2, $html, -1 );
461 }
462
463
471 static public function make_dir(string $dir_name, string|null $dir_mode = NULL): bool
472 {
473 if ($dir_mode == NULL)
474 {
475 $dir_mode = (int) octdec( STRING_DIR_MODE );
476 }
477
478 if (!is_dir($dir_name))
479 {
480 $umask = umask(); // get current mask
481 $result = mkdir($dir_name, $dir_mode, true);
482 if($result == false)
483 {
484 echo(LEPTON_tools::display('Cannot create directory!', 'pre','ui red message'));
485 return false;
486 }
487 umask($umask);
488 return true;
489 }
490 return false;
491 }
492
501 static public function change_mode(string $name ): bool
502 {
503 if (OPERATING_SYSTEM != 'windows')
504 {
505 $mode = (is_dir($name)) ? (int)octdec(STRING_DIR_MODE) : (int)octdec(STRING_FILE_MODE);
506 if (file_exists($name))
507 {
508 $umask = umask(); // get current
509 chmod($name, $mode);
510 umask($umask);
511 return true;
512 }
513 else
514 {
515 return false;
516 }
517 }
518 else
519 {
520 return true;
521 }
522 }
523
524
532 static public function create_access_file(string $filename, int $page_id): bool
533 {
534 global $admin, $MESSAGE;
535 $pages_path = LEPTON_PATH . PAGES_DIRECTORY;
536 $rel_pages_dir = str_replace($pages_path, '', dirname($filename));
537 $rel_filename = str_replace($pages_path, '', $filename);
538 // root_check prevent system directories and important files from being overwritten if PAGES_DIR = '/'
539 $denied = false;
540 if (PAGES_DIRECTORY == '')
541 {
542 $forbidden = [
543 'account',
544 'admins',
545 'framework',
546 'include',
547 'install',
548 'languages',
549 'media',
550 'modules',
551 'page',
552 'search',
553 'temp',
554 'templates',
555 'index.php',
556 '/config/config.php'
557 ];
558 $search = explode('/', $rel_filename);
559 // we need only the first level
560 $denied = in_array($search[1], $forbidden);
561 }
562 if ((true === is_writable($pages_path)) && (false === $denied))
563 {
564 // First make sure parent folder exists
565 $parent_folders = explode('/', $rel_pages_dir);
566 $parents = '';
567 foreach ($parent_folders as $parent_folder)
568 {
569 if ($parent_folder != '/' && $parent_folder != '')
570 {
571 $parents .= '/' . $parent_folder;
572 if (!file_exists($pages_path . $parents))
573 {
574 LEPTON_core::make_dir( $pages_path . $parents );
575 LEPTON_core::change_mode( $pages_path . $parents );
576 }
577 }
578 }
579 $step_back = str_repeat('../', substr_count($rel_pages_dir, '/') + (PAGES_DIRECTORY == "" ? 0 : 1));
580 $content = '<?php' . "\n";
581 $content .= "/**\n *\tThis file is autogenerated by LEPTON - Version: ".LEPTON_VERSION."\n";
582 $content .= " *\tDo not modify this file!\n */\n";
583 $content .= "\t" . '$page_id = ' . $page_id . ';' . "\n";
584 $content .= "\t" . 'require_once(\'' . $step_back . 'index.php\');' . "\n";
585
590 $fp = fopen($filename, 'w');
591 if ($fp)
592 {
593 fwrite($fp, $content, strlen($content));
594 fclose($fp);
599 LEPTON_core::change_mode($filename);
605 $temp_index_path = dirname($filename)."/index.php";
606 if (!file_exists($temp_index_path))
607 {
608 $origin = ADMIN_PATH."/pages/master_index.php";
609 if (file_exists($origin))
610 {
611 copy($origin, $temp_index_path);
612 }
613 }
614 }
615 else
616 {
617 $admin->print_error($MESSAGE['PAGES_CANNOT_CREATE_ACCESS_FILE']."<br />Problems while trying to open the file!");
618 return false;
619 }
620 return true;
621 }
622 else
623 {
624 $admin->print_error($MESSAGE['PAGES_CANNOT_CREATE_ACCESS_FILE']);
625 return false;
626 }
627 }
628
637 static public function level_count(int $iPageId ): int
638 {
640 // Get page parent
641 $iParent = $database->get_one('SELECT `parent` FROM `'.TABLE_PREFIX.'pages` WHERE `page_id` = '.$iPageId);
642 if ($iParent > 0)
643 {
644 // Get the level of the parent
645 $iLevel = $database->get_one('SELECT `level` FROM `'.TABLE_PREFIX.'pages` WHERE `page_id` = '.$iParent);
646 return $iLevel + 1;
647 }
648 else
649 {
650 return 0;
651 }
652 }
653
654
670 static public function get_subs(int $parent, array &$subs): void
671 {
673
674 // Get id's
675 $all = [];
676 $database->execute_query(
677 "SELECT page_id FROM ".TABLE_PREFIX."pages WHERE parent = ".$parent." ORDER BY position",
678 true,
679 $all,
680 true
681 );
682
683 foreach ($all as &$fetch)
684 {
685 $subs[] = $fetch['page_id'];
686
687 // Get subs of this sub - recursive call!
688 self::get_subs($fetch['page_id'], $subs);
689 }
690 }
691
692
701 static public function delete_page(int $page_id): void
702 {
704 $admin = self::getGlobal('admin');
705 $MESSAGE = self::getGlobal('MESSAGE');
706 $section_id = self::getGlobal('section_id');
707
708 LEPTON_handle::register("rm_full_dir");
709
710 // Find out more about the page
711 $page_info = [];
712 $database->execute_query(
713 'SELECT link, parent FROM '.TABLE_PREFIX.'pages WHERE page_id = '.$page_id,
714 true,
715 $page_info,
716 false
717 );
718
719 if (empty($page_info))
720 {
721 $admin->print_error($MESSAGE['PAGES_NOT_FOUND']);
722 }
723
724 // Get the sections that belong to the page
725 $all_sections = [];
726 $database->execute_query(
727 'SELECT section_id, module FROM '.TABLE_PREFIX.'sections WHERE page_id = '.$page_id,
728 true,
729 $all_sections
730 );
731
732 foreach($all_sections as &$section)
733 {
734 // Set section id
735 $section_id = $section['section_id'];
736
737 // Include the modules delete file if it exists
738 if (file_exists(LEPTON_PATH.'/modules/'.$section['module'].'/delete.php'))
739 {
740 include LEPTON_PATH.'/modules/'.$section['module'].'/delete.php';
741 }
742 }
743
744 // Update the pages table
745 $database->simple_query("DELETE FROM ".TABLE_PREFIX."pages WHERE page_id = ".$page_id);
746
747 // Update the sections table
748 $database->simple_query("DELETE FROM ".TABLE_PREFIX."sections WHERE page_id = ".$page_id);
749
750 // Include the ordering class or clean-up ordering
751 $order = LEPTON_order::getInstance(TABLE_PREFIX.'pages', 'position', 'page_id', 'parent');
752 $order->clean($page_info['parent']);
753
754 // Unlink the page access file and directory
755 $directory = LEPTON_PATH . PAGES_DIRECTORY . $page_info['link'];
756 $filename = $directory . PAGE_EXTENSION;
757 $directory .= '/';
758 if (file_exists($filename))
759 {
760 if (!is_writable(LEPTON_PATH . PAGES_DIRECTORY . '/'))
761 {
762 $admin->print_error($MESSAGE['PAGES_CANNOT_DELETE_ACCESS_FILE']);
763 }
764 else
765 {
766 unlink($filename);
767 if (file_exists($directory) && (rtrim($directory, '/') != LEPTON_PATH . PAGES_DIRECTORY) && ($page_info['link'][0] != '.'))
768 {
769 rm_full_dir($directory);
770 }
771 }
772 }
773 }
774
779 static public function getGlobal(string $name): null|int|string|array|object
780 {
781 $returnValue = null;
782 if (isset($GLOBALS[$name]))
783 {
784 $returnValue = &$GLOBALS[$name];
785 }
786 return $returnValue;
787 }
788
794 static function registerBasicFunctions(): void
795 {
796 $functionListToRegister = [
797 "get_page_headers",
798 "get_page_footers",
799 "page_content",
800 "easymultilang_menu"
801 ];
802
803 LEPTON_handle::register($functionListToRegister);
804 }
805
810 static function loadCodeSnippets(): void
811 {
812 $snippets = [];
813 LEPTON_database::getInstance()->execute_query(
814 "SELECT `directory` FROM `".TABLE_PREFIX."addons` WHERE `function` = 'snippet'",
815 true,
816 $snippets,
817 true
818 );
819
820 foreach ($snippets as $snippet)
821 {
822 $tempPath = LEPTON_PATH."/modules/".$snippet['directory']."/include.php";
823 if (file_exists($tempPath))
824 {
825 require $tempPath;
826 }
827 }
828 }
829
836 static public function check_entry(string $value): bool
837 {
838 // get all keepouts
839 $all_entries = [];
840 LEPTON_database::getInstance()->execute_query(
841 "SELECT * FROM ".TABLE_PREFIX."keepout ORDER BY id DESC",
842 true,
843 $all_entries,
844 true
845 );
846
847 if (!empty($all_entries))
848 {
849 foreach ($all_entries as $check)
850 {
851 if (str_contains($check['email'], '*'))
852 {
853 $check_email = str_replace('*','',$check['email']);
854 if (str_contains($value, $check_email))
855 {
856 return true;
857 }
858 }
859
860 if ($value == $check['ip'] || $value == $check['email'])
861 {
862 return true;
863 }
864 }
865 return false;
866 }
867 return false;
868 }
869
875 static public function userHasAdminRights(): bool
876 {
877 if (self::$bUserGotAdminRights == false)
878 {
879 // Current user has admin rights?
880 $aUser = explode(",", ($_SESSION['GROUPS_ID'] ?? ""));
881 self::$bUserGotAdminRights = (in_array(1, $aUser));
882 }
883
884 return self::$bUserGotAdminRights;
885 }
886
892 static public function imageTypesAllowed(): array
893 {
894 $aWhiteList = explode(',', UPLOAD_WHITELIST);
895 $aImageTypes = lib_r_filemanager::allowed_image_types;
896
897 return array_merge(array_intersect($aWhiteList, $aImageTypes), []);
898 }
899
900}
static getInstance(array &$settings=[])
static getInstance(string $table, string $order_field='position', string $id_field='id', string $common_field='')
static display(mixed $something_to_display="", string $tag="pre", string|null $css_class=null, bool|null $useVarDump=null)
$database
Definition constants.php:52
rm_full_dir(string $directory)
trait LEPTON_singleton