dbXapp 2.0
RAD, CMS, Module und Runtime-IDE fuer dbXapp
Loading...
Searching...
No Matches
index.php
Go to the documentation of this file.
1<?php
4 *
5 * @package dbXapp
6 * @author Armin Leonard Braun
7 * @copyright 2021 dbXwebApp Org
8 * @license GPL-2.0-or-later
9 *
10 * Description: dbXwebApp (Content, Applications, Views, Forms, Tabels, Grids)
11 * Version: 2.0 (dbXapp)
12 * Requires PHP: 8.x
13 * Author: Armin L. Braun
14 * Author URI: https://www.dbxwebapp.org/ArminBraun
15 * License: GPL v2 or later
16 * License URI: http://www.gnu.org/licenses/gpl-2.0.txt
17 */
18
19$__dbx_request_started_at = microtime(true);
20
21ob_start("ob_gzhandler"); // Compression
22
23
24$https = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') || (int)($_SERVER['SERVER_PORT'] ?? 0) === 443;
25if (session_status() !== PHP_SESSION_ACTIVE) {
26 ini_set('session.use_strict_mode', '1');
27 ini_set('session.use_only_cookies', '1');
28 ini_set('session.use_trans_sid', '0');
29
30 session_set_cookie_params([
31 'lifetime' => 0, // Dauer des Cookies, 0 bedeutet bis der Browser geschlossen wird
32 'path' => '/', // Gültiger Pfad für das Cookie
33 'domain' => '', // Optional: Das Domain-Feld kann leer gelassen werden, wenn nicht spezifisch
34 'secure' => $https, // Nur bei HTTPS erzwingen, damit lokale HTTP-Setups weiter funktionieren
35 'httponly' => true, // Verhindert Zugriff über JavaScript
36 'samesite' => 'Lax' // Optional: Verhindert das Senden bei Cross-Site-Requests
37 ]);
38 //ini_set('session.use_cookies', '0');
39 //ini_set('session.use_only_cookies', '0');
40 //ini_set('session.use_trans_sid', '1');
41 session_start();
42}
43
44 // Normale Web-Requests muessen immer die Rechte des angemeldeten Benutzers pruefen.
45 // CLI-/Admin-Tools setzen dbxRunAsAdmin bei Bedarf in ihrem eigenen Einstiegspunkt.
46 define('dbxSystem', 'dbxWebApp');
47 define('dbxRunAsAdmin', 0);
48
50 $dir = __DIR__ . DIRECTORY_SEPARATOR . 'files';
51
52 if (!is_dir($dir)) {
53 @mkdir($dir, 0775, true);
54 }
55
56 return $dir . DIRECTORY_SEPARATOR . 'dbxError.log';
57}
58
59function dbx_error_type($errno) {
60 $types = array(
61 E_ERROR => 'E_ERROR',
62 E_WARNING => 'E_WARNING',
63 E_PARSE => 'E_PARSE',
64 E_NOTICE => 'E_NOTICE',
65 E_CORE_ERROR => 'E_CORE_ERROR',
66 E_CORE_WARNING => 'E_CORE_WARNING',
67 E_COMPILE_ERROR => 'E_COMPILE_ERROR',
68 E_COMPILE_WARNING => 'E_COMPILE_WARNING',
69 E_USER_ERROR => 'E_USER_ERROR',
70 E_USER_WARNING => 'E_USER_WARNING',
71 E_USER_NOTICE => 'E_USER_NOTICE',
72 E_STRICT => 'E_STRICT',
73 E_RECOVERABLE_ERROR => 'E_RECOVERABLE_ERROR',
74 E_DEPRECATED => 'E_DEPRECATED',
75 E_USER_DEPRECATED => 'E_USER_DEPRECATED',
76 );
77
78 return $types[$errno] ?? 'E_UNKNOWN';
79}
80
81function dbx_write_php_error_log($type, $message, $file = '', $line = 0) {
82 $request = $_SERVER['REQUEST_METHOD'] ?? 'CLI';
83 $uri = $_SERVER['REQUEST_URI'] ?? '';
84 $ip = $_SERVER['REMOTE_ADDR'] ?? '';
85
86 $log = sprintf(
87 "[%s] %s: %s in %s:%d | %s %s | IP=%s%s",
88 date('Y-m-d H:i:s'),
89 $type,
90 str_replace(array("\r", "\n"), ' ', (string) $message),
91 (string) $file,
92 (int) $line,
93 $request,
94 $uri,
95 $ip,
96 PHP_EOL
97 );
98
99 error_log($log, 3, dbx_error_log_file());
100}
101
102error_reporting(E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED & ~E_NOTICE);
103date_default_timezone_set('Europe/Berlin');
104set_time_limit(600); // long time for Big Data
105ini_set('max_execution_time', 600); // 600 Sekunden
106ini_set('display_errors' , 0); // Fehler nicht direkt ausgeben
107ini_set('log_errors' , 1); // Fehler protokollieren
108ini_set('error_log' , dbx_error_log_file()); // Fehler in Datei schreiben
109
110set_error_handler(function ($errno, $errstr, $errfile, $errline) {
111 if (!(error_reporting() & $errno)) {
112 return false;
113 }
114
115 dbx_write_php_error_log(dbx_error_type($errno), $errstr, $errfile, $errline);
116
117 return true;
118});
119
120set_exception_handler(function ($exception) {
122 get_class($exception),
123 $exception->getMessage(),
124 $exception->getFile(),
125 $exception->getLine()
126 );
127
128 if (!headers_sent()) {
129 http_response_code(500);
130 }
131});
132
133register_shutdown_function(function () {
134 $error = error_get_last();
135
136 if (!$error) {
137 return;
138 }
139
140 $fatalTypes = array(E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_RECOVERABLE_ERROR);
141
142 if (!in_array($error['type'], $fatalTypes, true)) {
143 return;
144 }
145
147 dbx_error_type($error['type']),
148 $error['message'] ?? '',
149 $error['file'] ?? '',
150 $error['line'] ?? 0
151 );
152});
153
154
155
156
157function dbx_get_base_dir($cut_Data=0) {
158 $path= (str_replace('\\','/',__DIR__)).'/';
159 if ($cut_Data) $path = str_ends_with($path, "/Data/") ? substr($path, 0, -5) : $path;
160 $path = rtrim($path, '/') . "/";
161 return $path;
162};
163
165
166 // Ersetze alle gemischten Backslashes und Slashes durch einheitliche Slashes
167 $path_file = str_replace(['\\', '//', '\\\\'], '/', $path_file);
168 //return $path_file;
169
170 // Entferne doppelte Slashes außer am Anfang (z. B. für Netzwerkpfade wie //server/share)
171 $path_file = preg_replace('#(?<!:)//+#', '/', $path_file);
172
173 // Falls unter Windows, konvertiere zu Backslashes
174 if (DIRECTORY_SEPARATOR === '\\') {
175 $path_file = str_replace('/', '\\', $path_file);
176 }
177
178 // Prüfe, ob es eine Datei oder ein Ordner ist
179 $separator = DIRECTORY_SEPARATOR;
180 if (!str_ends_with($path_file, $separator)) {
181 if (!str_contains(basename($path_file), '.')) {
182 $path_file .= $separator;
183 }
184 }
185
186 return $path_file;
187}
188
189function dbx_path_is_absolute(string $path): bool {
190 $path = str_replace('\\', '/', trim($path));
191 if ($path === '') {
192 return false;
193 }
194 if ($path[0] === '/') {
195 return true;
196 }
197 return (bool) preg_match('#^[A-Za-z]:/#', $path);
198}
199
200function dbx_config_path_store(string $path, bool $dirTrailingSlash = false): string {
201 $path = str_replace('\\', '/', trim($path));
202 if ($path === '') {
203 return '';
204 }
205 $base = str_replace('\\', '/', dbx_get_base_dir());
206 if (dbx_path_is_absolute($path) || str_starts_with($path, $base)) {
207 $abs = str_replace('\\', '/', dbx_os_path_file($path));
208 $baseNorm = str_replace('\\', '/', dbx_os_path_file($base));
209 if (str_starts_with($abs, $baseNorm)) {
210 $path = substr($abs, strlen($baseNorm));
211 }
212 }
213 $path = ltrim($path, '/');
214 if ($dirTrailingSlash && $path !== '') {
215 $path = rtrim($path, '/') . '/';
216 }
217 return $path;
218}
219
220function dbx_config_path_resolve(string $path): string {
221 $path = str_replace('\\', '/', trim($path));
222 if ($path === '') {
223 return '';
224 }
225 if (!dbx_path_is_absolute($path)) {
226 $path = dbx_get_base_dir() . ltrim($path, '/');
227 }
228 return dbx_os_path_file($path);
229}
230
231function dbx_config_is_module_db_entry(string $key, array $entry): bool {
232 $type = strtolower(trim((string) ($entry['type'] ?? '')));
233 if ($type === 'sqlite' || $type === 'sqlite3') {
234 return true;
235 }
236 if (preg_match('/\.(db3|sqlite|sqlite3)$/i', $key)) {
237 return true;
238 }
239 $dbName = (string) ($entry['dbname'] ?? ($entry['name'] ?? ''));
240 if (strpos($key, '|') !== false && preg_match('/\.(db3|sqlite|sqlite3)$/i', $dbName)) {
241 return true;
242 }
243 return false;
244}
245
247 if (!isset($config['db']) || !is_array($config['db'])) {
248 return $config;
249 }
250 foreach ($config['db'] as $key => $entry) {
251 if (!is_array($entry)) {
252 continue;
253 }
254 if (dbx_config_is_module_db_entry((string) $key, $entry)) {
255 unset($config['db'][$key]);
256 }
257 }
258 return $config;
259}
260
264
266 $path=dbx_get_base_dir().'files/';
267 return $path;
268}
269
270$path_file=dbx_get_base_dir().'dbx/vendor/autoload.php';
271require $path_file;
272
273$path_file=dbx_get_base_dir().'dbx/include/dbxKernel.php';
274include_once dbx_os_path_file($path_file);
275
276function dbx_media_missing_key($mid, $rel = '') {
277 if (trim((string)$rel) !== '') {
278 return ltrim(str_replace('\\', '/', (string)$rel), '/');
279 }
280 $uri = trim((string)($_SERVER['REQUEST_URI'] ?? ''));
281 if ($uri !== '') {
282 return $uri;
283 }
284 return 'index.php?dbx_modul=dbxContent&dbx_run1=media&dbx_mid=' . (int)$mid;
285}
286
287function dbx_media_serve_fail($code, $mid, $rel = '') {
288 if ((int)$code === 404) {
289 dbx()->log_missing(dbx_media_missing_key($mid, $rel));
290 }
291 http_response_code((int)$code);
292 exit;
293}
294
296 $modul = $_GET['dbx_modul'] ?? '';
297 $run1 = $_GET['dbx_run1'] ?? '';
298 $mid = isset($_GET['dbx_mid']) ? (int)$_GET['dbx_mid'] : 0;
299 $thumb = isset($_GET['dbx_thumb']) && (string)$_GET['dbx_thumb'] === '1';
300
301 if ($modul !== 'dbxContent' || $run1 !== 'media' || $mid <= 0) {
302 return;
303 }
304
305 try {
306 $db = dbx()->get_system_obj('dbxDB');
307 $row = is_object($db) ? $db->select1('dbxMedia', array('id' => $mid, 'active' => 1), '*', 0) : array();
308 if (!is_array($row) || (int)($row['id'] ?? 0) <= 0) {
309 dbx_media_serve_fail(404, $mid);
310 }
311
312 $rel_key = $thumb && !empty($row['thumb_file_path']) ? 'thumb_file_path' : 'file_path';
313 $rel = rawurldecode((string)($row[$rel_key] ?? ''));
314 $rel = str_replace('\\', '/', $rel);
315 $rel = ltrim($rel, '/');
316 if ($rel === '' || strpos($rel, '..') !== false || !preg_match('~^(media|dbxContent/media)/~i', $rel)) {
317 http_response_code(403);
318 exit;
319 }
320
321 $root = dbx_os_path_file(rtrim(dbx_get_file_dir(), '/\\') . '/');
322 $file = dbx_os_path_file($root . $rel);
323 $base = realpath($root);
324 $real = realpath($file);
325 if (!$base || !$real || strpos($real, $base) !== 0 || !is_file($real) || !is_readable($real)) {
326 if ($thumb && !empty($row['file_path'])) {
327 $fallback_rel = rawurldecode((string)$row['file_path']);
328 $fallback_rel = ltrim(str_replace('\\', '/', $fallback_rel), '/');
329 $fallback_file = dbx_os_path_file($root . $fallback_rel);
330 $fallback_real = realpath($fallback_file);
331 if ($base && $fallback_real && strpos($fallback_real, $base) === 0 && is_file($fallback_real) && is_readable($fallback_real)) {
332 $real = $fallback_real;
333 $rel = $fallback_rel;
334 $mime = trim((string)($row['mime'] ?? ''));
335 if ($mime === '') {
336 $detected = function_exists('mime_content_type') ? mime_content_type($real) : '';
337 $mime = $detected ?: 'application/octet-stream';
338 }
339 $file_name = trim((string)($row['file_name'] ?? ''));
340 if ($file_name === '') $file_name = basename($real);
341 $file_name = str_replace('"', '', basename($file_name));
342 if (function_exists('session_status') && session_status() === PHP_SESSION_ACTIVE) {
343 session_write_close();
344 }
345 header('Content-Type: ' . $mime);
346 header('Content-Length: ' . filesize($real));
347 header('Content-Disposition: inline; filename="' . $file_name . '"');
348 header('Accept-Ranges: bytes');
349 header('Cache-Control: private, max-age=3600');
350 header('X-Content-Type-Options: nosniff');
351 readfile($real);
352 exit;
353 }
354 }
355 dbx_media_serve_fail(404, $mid, $rel);
356 }
357
358 while (ob_get_level() > 0) {
359 ob_end_clean();
360 }
361
362 $mime = trim((string)($thumb && !empty($row['thumb_file_path']) ? 'image/jpeg' : ($row['mime'] ?? '')));
363 if ($mime === '') {
364 $detected = function_exists('mime_content_type') ? mime_content_type($real) : '';
365 $mime = $detected ?: 'application/octet-stream';
366 }
367
368 $file_name = trim((string)($row['file_name'] ?? ''));
369 if ($file_name === '') $file_name = basename($real);
370 $file_name = str_replace('"', '', basename($file_name));
371
372 if (function_exists('session_status') && session_status() === PHP_SESSION_ACTIVE) {
373 session_write_close();
374 }
375
376 $size = filesize($real);
377 $start = 0;
378 $end = $size > 0 ? $size - 1 : 0;
379 $range = isset($_SERVER['HTTP_RANGE']) ? trim((string)$_SERVER['HTTP_RANGE']) : '';
380 if ($range !== '' && preg_match('/bytes=(\d*)-(\d*)/i', $range, $m)) {
381 if ($m[1] !== '') $start = max(0, (int)$m[1]);
382 if ($m[2] !== '') $end = min($end, (int)$m[2]);
383 if ($m[1] === '' && $m[2] !== '') {
384 $suffix = max(0, (int)$m[2]);
385 $start = max(0, $size - $suffix);
386 }
387 if ($start <= $end && $size > 0) {
388 http_response_code(206);
389 header('Content-Range: bytes ' . $start . '-' . $end . '/' . $size);
390 } else {
391 http_response_code(416);
392 header('Content-Range: bytes */' . $size);
393 exit;
394 }
395 }
396
397 header('Content-Type: ' . $mime);
398 header('Content-Length: ' . max(0, $end - $start + 1));
399 header('Content-Disposition: inline; filename="' . $file_name . '"');
400 header('Accept-Ranges: bytes');
401 header('Cache-Control: private, max-age=3600');
402 header('X-Content-Type-Options: nosniff');
403 $out = fopen($real, 'rb');
404 if ($out) {
405 if ($start > 0) fseek($out, $start);
406 $remaining = $end - $start + 1;
407 while ($remaining > 0 && !feof($out)) {
408 $chunk = fread($out, min(8192, $remaining));
409 if ($chunk === false || $chunk === '') break;
410 echo $chunk;
411 $remaining -= strlen($chunk);
412 if (function_exists('connection_aborted') && connection_aborted()) break;
413 }
414 fclose($out);
415 }
416 exit;
417 } catch (Throwable $e) {
418 dbx_write_php_error_log(get_class($e), $e->getMessage(), $e->getFile(), $e->getLine());
419 http_response_code(500);
420 exit;
421 }
422}
423
425
426
427function run_dbXwebApp() {
428 $session_id = session_id();
429 $page_content='';
430 dbx()->debug("#### Session #### PHP-ID=($session_id)");
431
432
433
434
435 dbx()->timer('system','full-app');
436 dbx()->timer('system-load','load Kernel');
437
438
439
440 $oWebApp = dbx()->get_system_obj('dbxWebApp');
441 $oSession = dbx()->get_system_obj('dbxSession');
442 $oInterpreter = null;
443 dbx()->timer('system-load');
444
445 dbx()->timer('session-load','Session load');
446 $oSession->load_session();
447 dbx()->timer('session-load');
448
449 dbx()->timer('system-check','System check');
450 dbx()->set_system_var('dbx_activ_modul','dbx'); // dbx_set_remember use dbx_activ_modul
451
452
453 $oWebApp->check_request(); // set sysvar: base_url base_uri permalink self_url
454 $oWebApp->check_remember(); // edit color design
455 $oWebApp->check_lng(); // set sysvar: dbx_lng !Important for check_perma()
456
457 $oWebApp->check_missing();
458 $sync=dbx()->get_request_var('dbx_sync',1,'int');
459 $oWebApp->check_perma(); // Permalink-Routing: dbxContent bei Treffer, dbxHome bei Fehler
460 $oWebApp->check_config();
461 $oWebApp->check_design(); // set design
462 $oWebApp->check_modul(); // set modul
463
464 //dbx()->login(1); // auto login for test
465 $self =dbx()->get_self_url();
466 $base =dbx()->get_base_url();
467 $uid =dbx()->user();
468 $ajax =dbx()->get_system_var('dbx_ajax',0,'int');
469
470 $cache =dbx()->get_config('dbx','cache');
471 $perma =dbx()->get_system_var('dbx_permalink','undef');
472 $modul =dbx()->get_system_var('dbx_modul' ,'undef');
473 $action=dbx()->get_system_var('dbx_run1' ,'undef');
474 dbx()->debug("#DBX RUN Base-URL($base) Self=($self) Ajax=($ajax) Perma ($perma) User=($uid) SYS CACHE=($cache) ");
475
476 dbx()->timer('system-check');
477
478 dbx()->timer($modul,'Master-Modul');
479 $modul_content=$oWebApp->run();
480 dbx()->timer($modul);
481
482 dbx()->timer('page-load','Page-Load');
483 dbx()->debug("#RUN-DBXWEBAPP SYNC=$sync");
484 if ($sync) {
485
486 //dbx_debug("sync content");
487 $page_content =$oWebApp->design_load($modul_content);
488 if ($oInterpreter === null) {
489 $oInterpreter = dbx()->get_system_obj('dbxInterpreter');
490 }
491 dbx()->timer('interpreter','Interpreter');
492 $page_content=$oInterpreter->run($page_content);
493 dbx()->timer('interpreter');
494
495 //dbx_debug('######TRANSLATE#######');
496 //$page_content=$oWebApp->translate($page_content);
497
498 $page_content=$oWebApp->add_norep($page_content);
499 $page_content=$oWebApp->add_editor_files_data($page_content);
500 // - - - - - - - - - - - - - -
501 //$page_content=$oWebApp->out_filter($page_content));
502 $page_content=$oWebApp->out_filter($page_content);
503 } else {
504 dbx()->debug("no sync no output");
505 http_response_code(204); // Kein Inhalt
506 }
507 dbx()->timer('page-load');
508 dbx()->debug("call session_save($sync)");
509 $oSession->save_session();
510 $oSession->clean_session();
511 if (!empty($GLOBALS['dbx_session_destroy_pending'])) {
512 $oSession->destroy_php_session();
513 }
514 dbx()->timer('system');
515 return $page_content;
516}
517
519$syncRequest = (int) dbx()->get_request_var('dbx_sync', 1, 'int') === 1;
521 dbx()->send_runtime_headers();
522}
523echo $response; // the one and onley Point
524while (ob_get_level() > 0) ob_end_flush();
525
526dbx()->debug_timer(0); // wenn es länger als 3 sec dauert dann debug timer für Analyse
527if ($syncRequest && (int) dbx()->get_system_var('dbx_ajax', 0, 'int') !== 1) {
528 dbx()->store_performance_timer();
529}
530dbx()->debug("#END#");
531
$config['version']
Definition config.php:2
dbx_error_log_file()
Definition index.php:49
dbx_media_serve_fail($code, $mid, $rel='')
Definition index.php:287
$__dbx_request_started_at
Definition index.php:19
dbx_normalize_config_for_store(array $config)
Definition index.php:261
dbx_os_path_file($path_file)
Definition index.php:164
dbx_config_is_module_db_entry(string $key, array $entry)
Definition index.php:231
dbx_config_path_store(string $path, bool $dirTrailingSlash=false)
Definition index.php:200
dbx_error_type($errno)
Definition index.php:59
dbx_media_missing_key($mid, $rel='')
Definition index.php:276
$https
Definition index.php:24
$syncRequest
Definition index.php:519
exit
Definition index.php:532
dbx_config_path_resolve(string $path)
Definition index.php:220
run_dbXwebApp()
Definition index.php:427
dbx_write_php_error_log($type, $message, $file='', $line=0)
Definition index.php:81
dbx_path_is_absolute(string $path)
Definition index.php:189
dbx_get_file_dir()
Definition index.php:265
$path_file
Definition index.php:270
dbx_config_strip_module_db_entries(array $config)
Definition index.php:246
if( $syncRequest)
Definition index.php:520
dbx_get_base_dir($cut_Data=0)
Definition index.php:157
$response
Definition index.php:518
dbx_serve_content_media_request()
Definition index.php:295
DBX schema administration.
$_SERVER['REQUEST_URI']