29 private const RESOURCE_MIME_TYPES = array(
31 'css' =>
'text/css; charset=UTF-8',
32 'js' =>
'application/javascript; charset=UTF-8',
33 'mjs' =>
'application/javascript; charset=UTF-8',
34 'cjs' =>
'application/javascript; charset=UTF-8',
35 'map' =>
'application/json; charset=UTF-8',
36 'json' =>
'application/json; charset=UTF-8',
37 'webmanifest' =>
'application/manifest+json; charset=UTF-8',
38 'wasm' =>
'application/wasm',
41 'avif' =>
'image/avif',
44 'ico' =>
'image/x-icon',
45 'jfif' =>
'image/jpeg',
46 'jpg' =>
'image/jpeg',
47 'jpeg' =>
'image/jpeg',
49 'svg' =>
'image/svg+xml',
50 'svgz' =>
'image/svg+xml',
51 'tif' =>
'image/tiff',
52 'tiff' =>
'image/tiff',
53 'webp' =>
'image/webp',
56 'eot' =>
'application/vnd.ms-fontobject',
59 'woff' =>
'font/woff',
60 'woff2' =>
'font/woff2',
63 'csv' =>
'text/csv; charset=UTF-8',
64 'pdf' =>
'application/pdf',
65 'txt' =>
'text/plain; charset=UTF-8',
66 'xml' =>
'application/xml; charset=UTF-8',
67 '7z' =>
'application/x-7z-compressed',
68 'gz' =>
'application/gzip',
69 'rar' =>
'application/vnd.rar',
70 'tar' =>
'application/x-tar',
71 'zip' =>
'application/zip',
72 'exe' =>
'application/octet-stream',
76 'flac' =>
'audio/flac',
78 'mp3' =>
'audio/mpeg',
81 'opus' =>
'audio/opus',
83 'avi' =>
'video/x-msvideo',
85 'mov' =>
'video/quicktime',
87 'mpeg' =>
'video/mpeg',
88 'mpg' =>
'video/mpeg',
90 'webm' =>
'video/webm',
94 private const DYNAMIC_FILE_ROUTES = array(
107 private const REPORT_ACTION_POLICIES = array(
108 'row_delete' => array(
'action' =>
'dbxReport.row_delete',
'bind' => array(
'rid')),
109 'delete_tab' => array(
'action' =>
'dbxReport.delete_tab',
'bind' => array()),
110 'multi_delete' => array(
'action' =>
'dbxReport.multi_delete',
'bind' => array()),
111 'multi_activate' => array(
'action' =>
'dbxReport.multi_activate',
'bind' => array()),
112 'multi_deactivate' => array(
'action' =>
'dbxReport.multi_deactivate',
'bind' => array()),
113 'rows_delete' => array(
'action' =>
'dbxReport.multi_delete',
'bind' => array()),
114 'rows_activate' => array(
'action' =>
'dbxReport.multi_activate',
'bind' => array()),
115 'rows_deactivate' => array(
'action' =>
'dbxReport.multi_deactivate',
'bind' => array()),
125 private const AUTOMATIC_RID_ACTIONS = array(
126 'delete' =>
'dbxAction.delete',
127 'save' =>
'dbxAction.save',
136 private $actionRouteCache = array();
156 ?
'https://' :
'http://';
158 $host = preg_replace(
'/:\d+$/',
'', (
string) $host);
160 if ($host ===
'heserver') {
162 } elseif ($host ===
'localhost' || $host ===
'127.0.0.1') {
166 $port = (int) (
$_SERVER[
'SERVER_PORT'] ?? 0);
167 $xport = ($port && $port != 80 && $port != 443) ?
":$port" :
'';
168 $request_origin = $protocol . $host . $xport;
170 if ($base_url && $port != 4221) {
172 $cached_scheme = strtolower((
string) (
$cached[
'scheme'] ??
''));
173 $cached_host = strtolower((
string) (
$cached[
'host'] ??
''));
174 $cached_port = (int) (
$cached[
'port'] ?? ($cached_scheme ===
'https' ? 443 : 80));
175 $cached_path =
'/' . trim(str_replace(
'\\',
'/', (
string) (
$cached[
'path'] ??
'')),
'/');
176 $request_path =
'/' . trim(str_replace(
'\\',
'/', $uri),
'/');
177 $request_port = $port ?: ($protocol ===
'https://' ? 443 : 80);
180 $cached_scheme !== rtrim($protocol,
':/') ||
181 $cached_host !== strtolower($host) ||
182 $cached_port !== $request_port ||
183 $cached_path !== $request_path
191 $base_url = $request_origin . rtrim($uri,
'/');
197 if (file_exists($base_href_file)) {
198 $base_url = trim(preg_replace(
'/[\x00-\x1F\x7F]/',
'', file_get_contents($base_href_file)));
203 $base_url = str_replace(
'\\',
'/', rtrim($base_url,
'\\'));
204 if (!in_array(substr($base_url, -1), [
'/',
'?'])) {
208 dbx()->set_remember_var(
'base_url', $base_url,
'dbx');
224 if ($modul ==
'dbx') {
231 $config[
'accessible_lng'] =
'de,en,es';
232 $config[
'default_color'] =
'blau';
233 $config[
'default_design_user'] =
'lda';
234 $config[
'default_design_admin'] =
'_admin';
239 $config[
'secure']=
'secure-key';
262 if (isset($url_components[
'path'])) {
263 $uri = $url_components[
'path'];
267 if (isset($url_components[
'query'])) {
268 parse_str($url_components[
'query'], $query_params);
269 foreach ($query_params as $key =>
$value) {
290 $url = trim(str_replace(
'&',
'&', (
string)
$url));
293 $hashPos = strpos(
$url,
'#');
294 if ($hashPos !==
false) {
295 $fragment = substr(
$url, $hashPos);
302 if (substr(
$url, 0, 1) ===
'?') {
303 $query = substr(
$url, 1);
305 parse_str($query, $params);
310 'fragment' => $fragment,
315 foreach (array(
'?',
'&') as $delimiter) {
316 $pos = strpos(
$url, $delimiter);
317 if ($pos !==
false && ($delimPos ===
false || $pos < $delimPos)) {
322 if ($delimPos !==
false) {
323 $path = substr(
$url, 0, $delimPos);
324 $query = substr(
$url, $delimPos + 1);
326 parse_str($query, $params);
333 'permalink' => str_replace(
'\\',
'/', $path),
335 'fragment' => $fragment,
356 $permalink = str_replace(
'\\',
'/', trim((
string) $permalink));
357 $permalink = trim($permalink,
'/');
360 if ($permalink ===
'') {
361 if (empty($params)) {
362 return '?' . $fragment;
364 return '?' . http_build_query($params,
'',
'&', PHP_QUERY_RFC3986) . $fragment;
367 if (empty($params)) {
368 return $permalink . $fragment;
371 return $permalink .
'?' . http_build_query($params,
'',
'&', PHP_QUERY_RFC3986) . $fragment;
394 foreach ($params as $key =>
$value) {
395 $route[
'params'][(string) $key] = (
string)
$value;
397 return $this->
build_route_url($route[
'permalink'], $route[
'params'], $route[
'fragment']);
410 private function effective_action_params(array $params): array {
411 $currentModul = trim((string)
dbx()->get_system_var(
'dbx_modul',
'',
'parameter'));
412 $modul = trim((
string)($params[
'dbx_modul'] ??
''));
415 $modul = $currentModul;
417 $params[
'dbx_modul'] = $modul;
421 if ($modul === $currentModul || $currentModul ===
'') {
422 foreach (array(
'dbx_run1',
'dbx_run2',
'dbx_run3') as $key) {
423 if (!array_key_exists($key, $params) || (
string)$params[$key] ===
'') {
424 $value =
dbx()->get_system_var($key,
'',
'parameter');
425 if ((
string)
$value !==
'') {
441 private function normalize_action_scope_value(
$value) {
447 return $value ?
'1' :
'0';
453 foreach (
$value as $key => $item) {
454 $normalized[(string)$key] = $this->normalize_action_scope_value($item);
471 private function resolve_action_bindings(array $bindings, array $params): array {
474 foreach ($bindings as $key =>
$value) {
476 $name = trim((
string)
$value);
484 $name = trim((
string)$key);
509 $params = $this->effective_action_params((array)($route[
'params'] ?? array()));
510 return $this->action_scope_from_params($params, (
string)$action, (array)$bindings);
521 private function action_scope_from_params(array $params,
string $action, array $bindings): string {
522 $params = $this->effective_action_params($params);
524 foreach (array(
'dbx_modul',
'dbx_run1',
'dbx_run2',
'dbx_run3') as $key) {
525 $route[$key] = $this->normalize_action_scope_value($params[$key] ??
'');
530 'action' => trim($action),
532 'bind' => $this->normalize_action_scope_value(
533 $this->resolve_action_bindings($bindings, $params)
537 $json = json_encode($payload, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
538 if (!is_string(
$json)) {
539 $json = serialize($payload);
542 return 'route-v1:' . hash(
'sha256',
$json);
555 private function action_route_matches(array $match, array $params): bool {
557 $actual = $params[(string)$key] ??
'';
562 if ((
string)$candidate ===
'*') {
563 $matched = (string)$actual !==
'';
564 } elseif ((
string)$actual === (
string)$candidate) {
599 private function configured_action_policy(array $params): array {
600 $modul = trim((string)($params[
'dbx_modul'] ??
''));
605 if (!array_key_exists($modul, $this->actionRouteCache)) {
606 $routes =
dbx()->get_config($modul,
'action_routes', array());
607 $this->actionRouteCache[$modul] = is_array($routes) ? $routes : array();
610 $routes = $this->actionRouteCache[$modul];
611 if (!is_array($routes)) {
622 if (!is_array($match) || !$match || !$this->action_route_matches($match, $params)) {
626 $policyName = trim((
string)(
$definition[
'action'] ?? $name));
627 if ($policyName ===
'') {
628 $policyName =
'action';
632 'source' =>
'module',
633 'action' => $modul .
'.' . $policyName,
650 private function report_action_policy(array $params): array {
651 foreach (array(
'dbx_do',
'dbx_run3',
'dbx_run2') as $parameter) {
652 $code = strtolower(trim((
string)($params[$parameter] ??
'')));
653 if ($code ===
'' || !isset(self::REPORT_ACTION_POLICIES[$code])) {
659 'source' =>
'dbxReport',
662 'match' => array($parameter => $code),
680 private function automatic_rid_action_policy(array $params): array {
681 if (trim((string)($params[
'rid'] ??
'')) ===
'') {
685 foreach (array(
'dbx_do',
'dbx_run3',
'dbx_run2',
'dbx_run1') as $parameter) {
686 $code = strtolower(trim((
string)($params[$parameter] ??
'')));
691 $parts = preg_split(
'/[^a-z0-9]+/', $code, -1, PREG_SPLIT_NO_EMPTY);
692 foreach (self::AUTOMATIC_RID_ACTIONS as $keyword => $action) {
693 if (!in_array($keyword, is_array($parts) ? $parts : array(),
true)) {
698 'source' =>
'automatic',
700 'bind' => array(
'rid'),
723 private function automatic_grid_action_policy(array $params): array {
724 $actions = array(
'save',
'insert',
'delete',
'sort',
'sync');
725 $contextBindings = array(
'rid',
'id',
'cid',
'iid',
'modul',
'dd',
'fd',
'xmodul');
727 foreach (array(
'dbx_run3',
'dbx_run2',
'dbx_run1') as $parameter) {
728 $code = strtolower(trim((
string)($params[$parameter] ??
'')));
733 $parts = preg_split(
'/[^a-z0-9]+/', $code, -1, PREG_SPLIT_NO_EMPTY);
734 $parts = is_array($parts) ? $parts : array();
735 $gridLike = in_array(
'grid', $parts,
true)
736 || (isset($parts[0]) && in_array($parts[0], array(
'data',
'fields'),
true));
742 if (!in_array($action, $parts,
true)) {
747 foreach ($contextBindings as
$binding) {
748 if (array_key_exists(
$binding, $params)
749 && trim((
string)$params[
$binding]) !==
'') {
755 'source' =>
'dbxReport',
756 'action' =>
'dbxReport.grid_' . $action,
758 'match' => array($parameter => $code),
777 private function resolve_action_policy(array $params): array {
778 $params = $this->effective_action_params($params);
779 $policy = $this->configured_action_policy($params);
781 $policy = $this->report_action_policy($params);
784 $policy = $this->automatic_grid_action_policy($params);
787 $policy = $this->automatic_rid_action_policy($params);
793 $policy[
'bindings'] = $this->resolve_action_bindings((array)$policy[
'bind'], $params);
794 $policy[
'scope'] = $this->action_scope_from_params(
796 (
string)$policy[
'action'],
797 (array)$policy[
'bindings']
799 $policy[
'params'] = $params;
814 return $this->resolve_action_policy((array)($route[
'params'] ?? array()));
822 private function current_action_request_params(): array {
823 $params = is_array(
$_GET ?? null) ?
$_GET : array();
824 if (is_array(
$_POST ??
null)) {
825 $params = array_replace($params,
$_POST);
828 foreach (array(
'dbx_modul',
'dbx_run1',
'dbx_run2',
'dbx_run3') as $key) {
829 $value =
dbx()->get_system_var($key,
'',
'parameter');
830 if ((
string)
$value !==
'') {
835 return $this->effective_action_params($params);
844 return $this->resolve_action_policy($this->current_action_request_params());
866 if (isset(
$_GET[
'dbx_token'])) {
869 if (isset(
$_POST[
'dbx_token'])) {
873 return dbx()->check_action_token((
string)($policy[
'scope'] ??
''),
$token);
884 if ($route[
'permalink'] ===
'') {
885 return empty($route[
'params'])
890 if (empty($route[
'params'])) {
891 return $route[
'permalink'] .
'?';
894 return $this->
build_route_url($route[
'permalink'], $route[
'params']) .
'&';
904 $requestUri =
$_SERVER[
'REQUEST_URI'] ??
'';
905 if ($requestUri ===
'') {
909 if ($baseUri ===
'') {
913 $path =
parse_url($requestUri, PHP_URL_PATH) ??
'';
914 $path = str_replace(
'\\',
'/', $path);
915 $baseUri = str_replace(
'\\',
'/', $baseUri);
917 if ($baseUri !==
'/' && $baseUri !==
'' && strpos($path, $baseUri) === 0) {
918 $path = substr($path, strlen($baseUri));
921 $route = ltrim($path,
'/');
922 $query =
parse_url($requestUri, PHP_URL_QUERY);
924 if ($query !==
null && $query !==
'') {
928 if (strpos($route,
'?') ===
false && strpos($route,
'&') ===
false) {
929 return $route .
'?' . $query;
931 return $route .
'&' . $query;
946 explode(
',', (
string) $unwanted),
956 unset($params[$key]);
973 if ($permalink !==
'') {
974 $route[
'permalink'] = str_replace(
'\\',
'/', trim((
string) $permalink,
'/'));
977 return $this->
build_route_url($route[
'permalink'], $params, $route[
'fragment']);
986 return array(
'dbx_edit',
'dbx_design',
'dbx_color',
'dbx_lng');
998 return $this->
build_route_url($route[
'permalink'], $route[
'params'], $route[
'fragment']);
1009 $path = str_replace(
'\\',
'/', (
string) $path);
1015 if (preg_match(
'/^(.*)[?&]([a-zA-Z_][a-zA-Z0-9_]*)=([^\/&?#]+)$/', $path, $match)) {
1017 $params[$match[2]] = rawurldecode($match[3]);
1022 if (preg_match(
'/^(.*?)([a-zA-Z_][a-zA-Z0-9_]*)=([^\/&?#]+)$/', $path, $match)) {
1023 if (preg_match(
'/^dbx_/', $match[2]) || strpos($match[2],
'_') !==
false) {
1025 $params[$match[2]] = rawurldecode($match[3]);
1031 return rtrim($path,
'-&?/');
1043 if (!is_array($params)) {
1047 foreach ($params as $key =>
$value) {
1048 if ($key ===
'' ||
$value ===
null) {
1069 if (!empty(
$_SERVER[
'SCRIPT_NAME'])) {
1073 elseif (!empty(
$_SERVER[
'PHP_SELF'])) {
1077 elseif (!empty(
$_SERVER[
'REQUEST_URI'])) {
1087 if ($uri==
'\\') $uri=
'/';
1088 $uri = str_replace(
'\\',
'/', $uri);
1102 return $route[
'permalink'];
1116 if (!empty($route[
'params'])) {
1117 $_GET = array_merge(
$_GET, $route[
'params']);
1146 $raw = file_get_contents(
'php://input');
1147 $data = json_decode($raw,
true);
1150 if (is_array($data)) {
1156 $pvx=array(); $gvx=array();
1160 if (isset(
$_POST[
'dbx_get'])) {
1161 $get =
$_POST[
'dbx_get'];
1162 $get = ltrim($get,
'?');
1163 parse_str($get, $gvx);
1165 unset(
$_POST[
'dbx_get']);
1168 if (isset(
$_POST[
'dbx_post'])) {
1169 $post=
$_POST[
'dbx_post'];
1170 $post= ltrim($post,
'?');
1171 parse_str($post, $pvx);
1173 unset(
$_POST[
'dbx_post']);
1200 if (!empty($route[
'params'])) {
1201 $_GET = array_merge($route[
'params'],
$_GET);
1208 $self_url =$this->
get_self_url($permalink,
'dbx_ajax,dbx_window,dbx_target,dbx_go');
1209 $go =
dbx()->get_request_var(
'dbx_go' ,0,
'parameter');
1210 $ajax =
dbx()->get_request_var(
'dbx_ajax' ,0,
'int');
1211 $window =
dbx()->get_request_var(
'dbx_window',0,
'int');
1214 dbx()->debug(
"#SYS Self-url=($self_url) base-Url=($base_url) base_uri=($base_uri) Perma=($permalink)");
1221 dbx()->set_system_var(
'dbx_permalink',$permalink);
1222 dbx()->set_system_var(
'dbx_self_url' ,$self_url);
1223 dbx()->set_system_var(
'dbx_base_url' ,$base_url);
1224 dbx()->set_system_var(
'dbx_base_uri' ,$base_uri);
1225 dbx()->set_system_var(
'dbx_window' ,$window);
1226 dbx()->set_system_var(
'dbx_ajax' ,
$ajax);
1227 dbx()->set_system_var(
'dbx_go' ,$go);
1247 $permalink = strtolower(trim(
1248 str_replace(
'\\',
'/', (
string)
dbx()->get_system_var(
'dbx_permalink',
'')),
1251 if ($permalink !==
'home') {
1265 foreach ($routeKeys as $key) {
1266 if (trim((
string)
dbx()->get_request_var($key,
'',
'*')) !==
'') {
1281 if (
$target ===
'' || headers_sent()) {
1285 header(
'Location: ' .
$target,
true, 301);
1305 'dbx_modul',
'dbx_run1',
'dbx_run2',
'dbx_run3',
'dbx_action',
1306 'dbx_do',
'action',
'dbx_ajax',
'dbx_window',
'cid',
'dbx_cid',
1308 if (trim((
string)
dbx()->get_request_var($key,
'',
'*')) !==
'') {
1313 $permalink = strtolower(trim(
1314 str_replace(
'\\',
'/', (
string)
dbx()->get_system_var(
'dbx_permalink',
'')),
1317 if ($permalink ===
'' || $permalink ===
'home') {
1321 $lng = strtolower(trim((
string)
dbx()->get_system_var(
'dbx_lng',
'de')));
1322 if (!preg_match(
'/^[a-z]{2,3}$/',
$lng)) {
1326 $redirects =
dbx()->get_config(
'dbxContent',
'permalink_redirects', array());
1327 $redirects = is_array($redirects) && is_array($redirects[
$lng] ??
null)
1330 if (!array_key_exists($permalink, $redirects)) {
1334 $target = strtolower(trim((
string)$redirects[$permalink]));
1339 if (!preg_match(
'/^[a-z0-9]+(?:-[a-z0-9]+)*$/',
$target)) {
1353 if (
$target ===
'' || headers_sent()) {
1357 header(
'Location: ' .
$target,
true, 301);
1369 $ext = strtolower(ltrim(trim((
string)$ext),
'.'));
1370 return isset(self::RESOURCE_MIME_TYPES[$ext]) ? 1 : 0;
1374 private function get_resource_extension($permalink): string {
1375 $path = str_replace(
'\\',
'/', rawurldecode((string)$permalink));
1376 return strtolower((
string)pathinfo($path, PATHINFO_EXTENSION));
1380 private function is_dynamic_file_route($permalink): bool {
1381 $route = strtolower(trim(str_replace(
'\\',
'/', rawurldecode((string)$permalink)),
'/'));
1382 return in_array($route, self::DYNAMIC_FILE_ROUTES,
true);
1391 private function has_internal_resource_referer(): bool {
1392 $referer = trim((string)(
$_SERVER[
'HTTP_REFERER'] ??
''));
1393 if ($referer ===
'') {
1397 $refererHost = (string)(
parse_url($referer, PHP_URL_HOST) ??
'');
1398 $requestAuthority = trim((
string)(
$_SERVER[
'HTTP_HOST'] ??
$_SERVER[
'SERVER_NAME'] ??
''));
1399 $requestHost = (string)(
parse_url(
'http://' . $requestAuthority, PHP_URL_HOST) ??
'');
1401 $normalize =
static function (
string $host): string {
1402 $host = rtrim(strtolower(trim($host)),
'.');
1403 return str_starts_with($host,
'www.') ? substr($host, 4) : $host;
1408 return $refererHost !==
'' && $requestHost !==
'' && hash_equals($requestHost, $refererHost);
1420 private function get_resource_file($permalink) {
1421 $path = str_replace(
'\\',
'/', rawurldecode((
string) $permalink));
1422 $path = ltrim($path,
'/');
1424 if ($path ===
'' || strpos($path,
"\0") !==
false) {
1428 $parts = explode(
'/', $path);
1429 foreach ($parts as $part) {
1430 if ($part ===
'..') {
1437 if (preg_match(
'/^apple-touch-icon(?:-precomposed)?(?:-\d+x\d+)?\.png$/i', $path)) {
1438 $path =
'favicon.png';
1439 $parts = array($path);
1447 $file = realpath(
$base . DIRECTORY_SEPARATOR . implode(DIRECTORY_SEPARATOR, $parts));
1452 $baseCheck = rtrim(str_replace(
'\\',
'/', strtolower(
$base)),
'/') .
'/';
1453 $fileCheck = str_replace(
'\\',
'/', strtolower(
$file));
1455 if (strpos($fileCheck, $baseCheck) !== 0) {
1468 private function get_resource_mime($ext) {
1469 $ext = strtolower(ltrim(trim((
string)$ext),
'.'));
1470 return self::RESOURCE_MIME_TYPES[$ext] ??
'application/octet-stream';
1480 private function send_resource_file(
$file, $ext) {
1481 if (headers_sent()) {
1485 header(
'Content-Type: ' . $this->get_resource_mime($ext));
1486 header(
'X-Content-Type-Options: nosniff');
1487 header(
'Cache-Control: public, max-age=3600');
1488 header(
'Content-Length: ' . (
string)filesize(
$file));
1490 if (strtoupper((
string)(
$_SERVER[
'REQUEST_METHOD'] ??
'GET')) !==
'HEAD') {
1511 $install = (int)(
$config[
'install'] ?? 1);
1513 $timezone = trim((
string)(
$config[
'timezone'] ??
'Europe/Berlin'));
1514 if ($timezone !==
'' && in_array($timezone, timezone_identifiers_list(),
true)) {
1515 date_default_timezone_set($timezone);
1518 dbx()->set_system_var(
'dbx_install', $install);
1519 dbx()->set_system_var(
'dbx_construct', (
int)(
$config[
'construct'] ?? 0));
1521 dbx()->set_system_var(
'dbx_install', 1);
1539 $permalink=
dbx()->get_system_var(
'dbx_permalink',
'',
'*');
1541 if (trim((
string)$permalink) ===
'' || $this->is_dynamic_file_route($permalink)) {
1545 $ext = $this->get_resource_extension($permalink);
1546 if (!$this->get_is_resorce($ext)) {
1550 $resourceFile = $this->get_resource_file($permalink);
1551 if ($resourceFile) {
1552 dbx()->debug(
"## resource exists, not missing ($permalink) file=($resourceFile)");
1553 $this->send_resource_file($resourceFile, $ext);
1557 http_response_code(404);
1558 header(
'X-Content-Type-Options: nosniff');
1559 header(
'Cache-Control: no-store');
1561 dbx()->debug(
"## check missing ($permalink)");
1563 if ($this->has_internal_resource_referer()) {
1564 $ok =
dbx()->log_missing($permalink);
1566 dbx()->debug(
"## missing resource not logged: no internal referer ($permalink)");
1568 dbx()->debug(
"#MISSING# ($permalink) Ext=($ext) ok=($ok)");
1582 $design=
dbx()->get_remember_var(
'dbx_design',
'user' ,
'dbx');
1583 $edit =
dbx()->get_remember_var(
'dbx_edit' ,0 ,
'dbx');
1584 $lng =
dbx()->get_remember_var(
'dbx_lng' ,
'de' ,
'dbx');
1585 $defaultColor =
dbx()->normalize_skin(
1586 (
string)
dbx()->get_config(
'dbx',
'default_color',
'blau'),
1589 $color =
dbx()->get_remember_var(
'dbx_color', $defaultColor,
'dbx');
1593 $edit =
dbx()->get_request_var(
'dbx_edit' ,$edit);
1595 $color =
dbx()->normalize_skin(
1596 (
string)
dbx()->get_request_var(
'dbx_color', $color),
1602 if (strtolower(trim((
string)
$design)) ===
'fleurop') {
1607 dbx()->set_remember_var(
'dbx_design',
$design,
'dbx');
1608 dbx()->set_remember_var(
'dbx_edit' ,$edit ,
'dbx');
1609 dbx()->set_remember_var(
'dbx_lng' ,
$lng ,
'dbx');
1610 dbx()->set_remember_var(
'dbx_color' ,$color ,
'dbx');
1612 dbx()->set_system_var(
'dbx_design',
$design);
1613 dbx()->set_system_var(
'dbx_edit' , $edit);
1614 dbx()->set_system_var(
'dbx_lng' ,
$lng);
1615 dbx()->set_system_var(
'dbx_color' , $color);
1616 dbx()->set_system_var(
'dbx_last_editor_tpl_paths', array());
1634 private function get_content_root(): int {
1635 $requestRoot =
dbx()->get_request_var(
'root',
'',
'int');
1637 if ($requestRoot !==
'') {
1638 return (
int) $requestRoot;
1641 $configRoot =
dbx()->get_config(
'dbxContent',
'root');
1642 if ($configRoot ===
'undef' || $configRoot ===
'') {
1646 return (
int) $configRoot;
1656 private function set_content_route(
int $cid,
string $source =
''): void {
1662 $root = $this->get_content_root();
1664 dbx()->set_system_var(
'dbx_modul',
'dbxContent');
1665 dbx()->set_system_var(
'dbx_cid', $cid);
1666 dbx()->set_system_var(
'cid', $cid);
1667 dbx()->set_system_var(
'dbx_content_route_cid', $cid);
1669 $cacheableContentRoute = str_starts_with(
$source,
'permalink-');
1670 dbx()->set_system_var(
'dbx_content_permalink_request', $cacheableContentRoute ? 1 : 0);
1672 if (
$mode ===
'cms') {
1673 dbx()->set_system_var(
'dbx_run1',
'cms');
1674 dbx()->set_system_var(
'dbx_run2',
'show');
1675 dbx()->set_system_var(
'root',
$root);
1677 dbx()->set_system_var(
'dbx_run1',
'show');
1680 dbx()->debug(
"#PERMALINK set dbxContent mode=($mode) root=($root) cid=($cid) source=($source)");
1688 private function get_home_content_cid(): int {
1691 return \dbx\dbxContent\dbxContentHome::resolveCid();
1718 $permalink=
dbx()->get_system_var(
'dbx_permalink');
1719 dbx()->set_system_var(
'dbx_content_permalink_request', 0);
1720 dbx()->set_system_var(
'dbx_content_route_cid', 0);
1721 dbx()->debug(
"check perma ($permalink)");
1723 if ($permalink ==
'undef') $permalink=
'';
1724 if ($permalink ==
'/') $permalink=
'';
1727 $lng=
dbx()->get_system_var(
'dbx_lng',
'de');
1729 $modul =
dbx()->get_request_var(
'dbx_modul');
1730 $action =
dbx()->get_request_var(
'dbx_run1');
1731 $hasExplicitRoute = ($modul !==
'' && $action !==
'');
1733 if ($hasExplicitRoute) {
1734 dbx()->set_system_var(
'dbx_modul', $modul);
1735 dbx()->set_system_var(
'dbx_run1', $action);
1736 dbx()->set_system_var(
'dbx_run2',
dbx()->get_request_var(
'dbx_run2',
'',
'parameter'));
1737 dbx()->set_system_var(
'root',
dbx()->get_request_var(
'root',
'',
'int'));
1740 $requestCid = (int)
dbx()->get_request_var(
'cid', 0,
'int');
1741 if (!$requestCid) $requestCid = (int)
dbx()->get_request_var(
'dbx_cid', 0,
'int');
1743 if ($hasExplicitRoute) {
1744 dbx()->set_system_var(
'dbx_cid', $requestCid);
1745 dbx()->set_system_var(
'cid', $requestCid);
1749 if ($requestCid > 0 && (!$modul || !$action || $modul ===
'dbxHome')) {
1750 $this->set_content_route($requestCid,
'request-cid');
1754 if (!$permalink && !$modul)
$home=1;
1755 if ( $modul==
'dbxHome')
$home=1;
1756 if ($permalink ===
'home' && !$modul)
$home=1;
1760 $homeCid = $this->get_home_content_cid();
1762 $homeSource =
'dbxHome-config';
1763 if ($permalink ===
'home') {
1764 $homeSource =
'permalink-home';
1765 } elseif (!$modul) {
1766 $homeSource =
'permalink-root';
1768 $this->set_content_route($homeCid, $homeSource);
1771 dbx()->set_system_var(
'dbx_modul' ,
'dbxContent');
1772 dbx()->set_system_var(
'dbx_run1',
'show');
1773 dbx()->set_system_var(
'dbx_run2',
'');
1774 dbx()->set_system_var(
'dbx_cid', 0);
1775 dbx()->set_system_var(
'cid', 0);
1776 dbx()->set_system_var(
'dbx_design',
'user');
1780 if ($permalink ==
'admin') {
1781 dbx()->set_system_var(
'dbx_modul',
'dbxAdmin');
1782 dbx()->set_system_var(
'dbx_run1',
'run');
1783 dbx()->set_system_var(
'dbx_design',
'admin');
1787 if ($permalink ===
'sitemap.xml' || $permalink ===
'sitemap') {
1788 dbx()->set_system_var(
'dbx_modul',
'dbxContent');
1789 dbx()->set_system_var(
'dbx_run1',
'sitemap');
1793 if ($permalink ===
'robots.txt') {
1794 dbx()->set_system_var(
'dbx_modul',
'dbxContent');
1795 dbx()->set_system_var(
'dbx_run1',
'robots');
1802 $check_perma=
dbx()->get_config(
'dbx',
'permalink');
1803 if ($permalink >
' ' && $check_perma) {
1805 dbx()->debug(
"##Permalink## ($permalink) Lng=($lng) check content#");
1806 $permalink=trim((
string)$permalink,
'/');
1814 $accessibleLngs = function_exists(
'dbx_accessible_lngs')
1817 foreach ($accessibleLngs as $candidateLng) {
1818 $candidateLng = strtolower(trim((
string)$candidateLng));
1819 if ($candidateLng ===
'' || $candidateLng ===
$lng) {
1826 if (!is_array($candidate) || (
int)($candidate[
'activ'] ?? 0) !== 1) {
1830 $lng = $candidateLng;
1832 dbx()->set_remember_var(
'dbx_lng',
$lng,
'dbx');
1833 dbx()->set_system_var(
'dbx_lng',
$lng);
1834 dbx()->debug(
"##Permalink## Sprache aus sauberer URL erkannt: ($lng)");
1841 $this->set_content_route($cid,
'permalink-content');
1849 $homeCid = $this->get_home_content_cid();
1851 http_response_code(404);
1852 dbx()->set_system_var(
'dbx_content_not_found', 1);
1853 $this->set_content_route($homeCid,
'permalink-home-fallback');
1854 dbx()->debug(
"#PERMALINK not found -> HTTP 404 with /home content permalink=($permalink) cid=($homeCid)");
1858 http_response_code(404);
1859 dbx()->set_system_var(
'dbx_content_not_found', 1);
1860 dbx()->set_system_var(
'dbx_modul',
'dbxContent');
1861 dbx()->set_system_var(
'dbx_run1',
'show');
1862 dbx()->set_system_var(
'dbx_run2',
'');
1863 dbx()->set_system_var(
'dbx_cid', 0);
1864 dbx()->set_system_var(
'cid', 0);
1865 dbx()->debug(
"#PERMALINK not found and no /home content configured permalink=($permalink)");
1876 $modul=
dbx()->get_system_var(
'dbx_modul');
1878 dbx()->set_system_var(
'dbx_modul',$modul);
1894 $user_default = (string)(
$config[
'default_design_user'] ??
'dbxapp');
1895 $admin_default= (string)(
$config[
'default_design_admin'] ??
'dbxapp');
1896 $construct = (int)(
$config[
'construct'] ?? 0);
1897 $install = (int)(
$config[
'install'] ?? 1);
1898 $intro = (int) (
$config[
'intro'] ?? 0);
1901 $design =
dbx()->get_remember_var(
'dbx_design',$user_default,
'dbx');
1902 if (strtolower(trim((
string)
$design)) ===
'fleurop') {
1904 dbx()->set_remember_var(
'dbx_design',
$design,
'dbx');
1907 $page =
dbx()->get_system_var(
'dbx_page' ,
'default');
1908 $modul =
dbx()->get_system_var(
'dbx_modul');
1909 $admin_modul =
dbx()->has_text($modul,
'_admin');
1920 $ajax = (int)
dbx()->get_system_var(
'dbx_ajax', 0,
'int');
1922 $introShown = (int)
dbx()->get_session_var(
'intro_shown', 0,
'ui',
'dbx');
1923 $requestModul = trim((
string)
dbx()->get_request_var(
'dbx_modul',
'',
'parameter'));
1924 if (!$introShown && $requestModul ===
'') {
1928 dbx()->set_session_var(
'intro_shown', 1,
'ui',
'dbx');
1939 if ($install || !
$ok) {
1940 dbx()->set_system_var(
'dbx_install', 1);
1941 $modul =
'dbxSetup';
1947 dbx()->set_system_var(
'dbx_run1',
'install');
1953 dbx()->set_system_var(
'dbx_modul' ,$modul);
1954 dbx()->set_system_var(
'dbx_design' ,
$design);
1955 dbx()->set_system_var(
'dbx_page' ,
$page);
1956 $ajax=
dbx()->get_system_var(
'dbx_ajax',0);
1969 $lng_default =
$config[
'default_lng'];
1970 $lng_accessible=
$config[
'accessible_lng'];
1972 if (
$lng != $lng_default) {
1974 if (!is_array($lng_accessible)) $lng_accessible = explode(
",", $lng_accessible);
1975 foreach ($lng_accessible as $no => $val) {
1980 dbx()->set_remember_var(
'dbx_lng',
$lng,
'dbx');
1981 dbx()->set_system_var(
'dbx_lng',
$lng);
1992 if (!
$lng)
$lng=
dbx()->get_system_var(
'dbx_lng',
'de');
1993 $dir_file=
dbx()->get_base_dir().
'dbx/translate.php';
1994 if (file_exists($dir_file)) {
2011 if (isset(
$_SESSION[
'dbx'][
'add_css'])) {
2013 if (is_array($xcss)) {
2014 foreach ($xcss as $no =>
$css) { $css_content.=
$css.
"\n"; }
2029 if (isset(
$_SESSION[
'dbx'][
'add_js'])) {
2031 if (is_array($xjs)) {
2032 foreach ($xjs as $no => $js) { $js_content.=$js.
"\n"; }
2048 include
dbx()->get_base_dir().
'dbx/out_filter.php';
2060 $oTPL =
dbx()->get_system_obj(
'dbxTPL');
2061 if (is_object($oTPL) && method_exists($oTPL,
'cleanup_optional_placeholders')) {
2067 if (is_array($xnorep)) {
2068 for($i=0; $i < 2; $i++) {
2069 foreach ($xnorep as $id => $norep) {
2083 if (isset(
$_SESSION[
'dbx'][
'record'][$fld])) {
2093 $ajax =
dbx()->get_system_var(
'dbx_ajax');
2094 $window=
dbx()->get_system_var(
'dbx_window');
2096 $design=
dbx()->get_system_var(
'dbx_activ_design',
dbx()->get_system_var(
'dbx_design'));
2097 $page =
dbx()->get_system_var(
'dbx_activ_page' ,
dbx()->get_system_var(
'dbx_page'));
2098 $lng =
dbx()->get_system_var(
'dbx_activ_lng' ,
dbx()->get_system_var(
'dbx_lng'));
2103 if ($window)
$page=
'_window';
2104 $oTPL=
dbx()->get_system_obj(
'dbxTPL');
2107 if (defined(
'dbxRunAsAdmin') && (
int) constant(
'dbxRunAsAdmin') === 1) {
2108 $admin_bypass_alert=$oTPL->get_tpl(
'dbx|alert-warning', array(
2109 'msg' =>
'Admin Bypass ist aktiv'
2111 $modul_content=$admin_bypass_alert.
'<br>'.$modul_content;
2122 $edit = (int)
dbx()->get_system_var(
'dbx_edit', 0,
'int');
2124 if (($edit < 4 || $edit > 8) && $edit !== 9) {
2128 $all_files =
dbx()->get_editor_files();
2131 foreach ($all_files as
$file) {
2136 if ($edit == 4 &&
$file[
'kind'] !==
'fd') {
2140 if ($edit == 5 &&
$file[
'kind'] !==
'dd') {
2144 if ($edit == 6 &&
$file[
'kind'] !==
'class') {
2148 if ($edit == 7 &&
$file[
'kind'] !==
'sysclass') {
2152 if ($edit == 8 &&
$file[
'kind'] !==
'config') {
2162 'files' => array_values(
$files),
2165 $json = json_encode($payload, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
2171 $data =
'<script type="application/json" class="dbx-editor-files-data">' .
2172 htmlspecialchars(
$json, ENT_NOQUOTES,
'UTF-8') .
2175 if (strpos(
$content,
'</body>') !==
false) {
2176 return str_replace(
'</body>', $data .
"\n</body>",
$content);
2182 private function render_editor_files_menu($edit,
$files) {
2187 $title =
'Editor Dateien';
2188 if ($edit == 4) $title =
'FD Dateien';
2189 if ($edit == 5) $title =
'DD Dateien';
2190 if ($edit == 6) $title =
'Modul PHP Dateien';
2191 if ($edit == 7) $title =
'myX SysClass Dateien';
2192 if ($edit == 8) $title =
'Config Dateien';
2193 if ($edit == 9) $title =
'Alle Editor Dateien';
2195 $html =
'<div id="dbxEditorFilesMenu" class="dbx-editor-files-menu" ';
2196 $html .=
'style="display:none;">';
2197 $html .=
'<button type="button" class="dbx-editor-files-count" title="' . htmlspecialchars($title, ENT_QUOTES,
'UTF-8') .
'" ';
2198 $html .=
'onclick="this.parentElement.classList.toggle(\'is-open\')" ';
2199 $html .=
'style="display:inline-flex;align-items:center;gap:6px;min-height:30px;padding:4px 8px;border:1px solid rgba(0,0,0,.18);border-radius:4px;background:#212529;color:#fff;box-shadow:0 4px 12px rgba(0,0,0,.18);">';
2200 $html .=
'<i class="bi bi-pencil-square"></i><span>' . count(
$files) .
'</span></button>';
2201 $html .=
'<div class="dbx-editor-files-list" style="max-height:min(520px,calc(100vh - 96px));overflow:auto;padding:8px;border:1px solid rgba(0,0,0,.16);border-radius:4px;background:#fff;color:#212529;box-shadow:0 10px 28px rgba(0,0,0,.2);">';
2202 $html .=
'<div class="dbx-editor-files-title" style="padding:4px 6px;font-weight:600;color:#495057;">' . htmlspecialchars($title, ENT_QUOTES,
'UTF-8') .
'</div>';
2205 if (!isset(
$file[
'file'])) {
2209 $path =
$file[
'file'];
2210 $kind = isset(
$file[
'kind']) ? (string)
$file[
'kind'] :
'';
2211 $url = $this->editor_file_url($kind, $path);
2212 $label = $this->short_editor_file_label($path);
2214 $html .=
'<a href="' . htmlspecialchars(
$url, ENT_QUOTES,
'UTF-8') .
'" ';
2215 $html .=
'data-url="' . htmlspecialchars(
$url, ENT_QUOTES,
'UTF-8') .
'" data-title="' . htmlspecialchars($title, ENT_QUOTES,
'UTF-8') .
'" ';
2216 $html .=
'style="display:grid;grid-template-columns:22px minmax(0,1fr);align-items:center;gap:6px;padding:5px 6px;border-radius:4px;color:#212529;text-decoration:none;" class="dbx-win">';
2217 $html .=
'<i class="bi bi-filetype-php"></i>';
2218 $html .=
'<span style="overflow:hidden;text-overflow:ellipsis;white-space:nowrap;">' . htmlspecialchars($label, ENT_QUOTES,
'UTF-8') .
'</span>';
2228 private function short_editor_file_label($path) {
2229 $path = str_replace(
'\\',
'/', $path);
2230 $prefix =
'dbx/modules/';
2232 if (strpos($path, $prefix) === 0) {
2233 return substr($path, strlen($prefix));
2239 private function editor_file_url($kind, $path) {
2240 $kind = strtolower(trim((
string)$kind));
2241 $path = str_replace(
'\\',
'/', (
string)$path);
2243 if ($kind ===
'dd' && preg_match(
'#^dbx/modules/([^/]+)/dd/([^/]+)\.dd\.php$#', $path, $m)) {
2244 return '?dbx_modul=dbxAdmin&dbx_run1=edit_dd&modul=' . rawurlencode($m[1]) .
'&dd=' . rawurlencode($m[2]);
2247 if ($kind ===
'fd' && preg_match(
'#^dbx/modules/([^/]+)/fd/([^/]+)\.fd\.php$#', $path, $m)) {
2248 return '?dbx_modul=dbxAdmin&dbx_run1=edit_fd&modul=' . rawurlencode($m[1]) .
'&fd=' . rawurlencode($m[2]);
2251 return '?dbx_modul=dbxEditor&dbx_run1=edit&file=' . rawurlencode($path);
2264 private function reject_action_request(array $policy): string {
2265 http_response_code(403);
2267 $action = (string)($policy[
'action'] ??
'action');
2268 $params = (array)($policy[
'params'] ?? array());
2269 $modul = (string)($params[
'dbx_modul'] ??
dbx()->get_system_var(
'dbx_modul',
'',
'parameter'));
2274 'Action-Token abgewiesen',
2276 'ungueltiger oder fehlender dbx_token',
2279 'bindings' => (array)($policy[
'bindings'] ?? array()),
2280 'source' => (
string)($policy[
'source'] ??
''),
2283 }
catch (Throwable $e) {
2284 dbx()->debug(
'Action-Token-Ablehnung konnte nicht protokolliert werden: ' . $e->getMessage());
2287 $message =
'Die Aktion wurde aus Sicherheitsgründen nicht ausgeführt. Bitte laden Sie die Ausgangsseite neu und verwenden Sie den dort angebotenen Aktionslink.';
2288 $api = (int)
dbx()->get_system_var(
'dbx_api', 0,
'int') === 1;
2291 if (!headers_sent()) {
2292 header(
'Content-Type: application/json; charset=UTF-8');
2294 return (
string)json_encode(array(
2297 'error' =>
'invalid_action_token',
2298 'message' => $message,
2299 ), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
2302 $tpl =
dbx()->get_system_obj(
'dbxTPL');
2303 return $tpl->get_tpl(
'dbx|alert-warning', array(
'msg' => $message));
2310 $uid =
dbx()->user();
2311 $self =
dbx()->get_self_url();
2312 $design =
dbx()->get_system_var(
'dbx_design');
2313 $page =
dbx()->get_system_var(
'dbx_page');
2314 $lng =
dbx()->get_system_var(
'dbx_lng');
2315 $edit =
dbx()->get_system_var(
'dbx_edit');
2316 $color =
dbx()->get_system_var(
'dbx_color');
2317 $modul =
dbx()->get_system_var(
'dbx_modul');
2318 $action =
dbx()->get_system_var(
'dbx_run1');
2319 $api =
dbx()->get_system_var(
'dbx_api');
2320 $cid =
dbx()->get_system_var(
'dbx_cid',0);
2321 $run2 =
dbx()->get_system_var(
'dbx_run2',
'');
2322 $root =
dbx()->get_system_var(
'root',
'');
2323 $install=
dbx()->get_system_var(
'dbx_install',0);
2335 $access=
dbx()->can_modul($modul);
2337 $perma=
dbx()->get_system_var(
'dbx_permalink');
2338 if ( $perma && !$uid)
dbx()->set_remember_var(
'dbx_redir_after_login',$perma,
'dbx');
2339 if (!$perma && !$uid)
dbx()->set_remember_var(
'dbx_redir_after_login',
"?dbx_modul=$modul&dbx_run1=$action",
'dbx');
2341 $content=
'[modul=dbxLogin]dbx_run1=login[/modul]';
2345 dbx()->set_system_var(
'dbx_master_modul' , $modul);
2346 dbx()->set_system_var(
'dbx_master_action',$action);
2347 dbx()->set_system_var(
'dbx_activ_modul' , $modul);
2348 dbx()->set_system_var(
'dbx_activ_action' ,$action);
2352 $content = $this->reject_action_request($actionPolicy);
2354 $dbxModul=
dbx()->get_modul_obj($modul);
2355 $mid=
dbx()->get_system_var(
'dbx_activ_modul_id',0,
'*');
2357 dbx()->set_system_var(
'dbx_activ_modul_id',$mid);
2358 dbx()->set_modul_var(
'dbx_modul_id',$mid);
2359 dbx()->set_modul_var(
'dbx_modul' ,$modul);
2360 dbx()->set_modul_var(
'dbx_run1' ,$action);
2361 if ($run2 !==
'')
dbx()->set_modul_var(
'dbx_run2', $run2);
2362 dbx()->set_modul_var(
'dbx_cid' ,$cid);
2363 if ($cid)
dbx()->set_modul_var(
'cid', $cid);
2370 if (
$api)
dbx()->set_system_var(
'dbx_page',
'api');
2375 $mid=
dbx()->get_system_var(
'dbx_activ_modul_id');
2376 $go =
dbx()->get_system_var(
'dbx_go',0,
'parameter');
2378 $js =
'$(document).ready(function() { ';
2379 $js.=
"dbxGoTo('$go');";
2382 $content.=
"<br><script>$js</script><div id=dbx_end></div>";