diff --git a/Zephir/aes-loader/hydraterbootloader/hydraterbootloader/loader.zep b/Zephir/aes-loader/hydraterbootloader/hydraterbootloader/loader.zep index 2755602..661fd0c 100644 --- a/Zephir/aes-loader/hydraterbootloader/hydraterbootloader/loader.zep +++ b/Zephir/aes-loader/hydraterbootloader/hydraterbootloader/loader.zep @@ -93,13 +93,12 @@ class Loader let cacheDir = this->getCacheDir(); let hash = hash("sha256", filePath); - let tmpPath = cacheDir . "/aesphp_" . hash . ".php"; + let tmpPath = cacheDir . "/ap_" . hash; if useInclude && file_exists(tmpPath) && !forceRefresh { let expired = this->isExpired(tmpPath, 28800); // 8 hours = 28800 seconds if !expired { - require tmpPath; - return; + return require tmpPath; } else { unlink(tmpPath); // Remove expired cache } @@ -119,6 +118,7 @@ class Loader } return require tmpPath; } else { + let plaintext = str_replace([""], ["",""], plaintext); return eval(plaintext); } } diff --git a/src/bootstrap/errors.php b/src/bootstrap/errors.php index 250b46a..97aa2a2 100644 --- a/src/bootstrap/errors.php +++ b/src/bootstrap/errors.php @@ -6,9 +6,104 @@ define('WORD_WRAP_CHRS', 80); // Letters before Line Wrap on Errors // Configuration if (! defined('BaseDir')) { + define('BaseDir', ""); // To avoid defination errors define('LOG_FILE', false); } else { - define('LOG_FILE', BaseDir . '/protected/logs/error_log.txt'); + define('LOG_FILE', BaseDir . '/protected/logs/errors.log.txt'); +} + +function fallback_dev(): bool { + if (! defined("ENVIRONMENT")) { + return false; // Force (false) which means Live on unknown state + } + return (ENVIRONMENT === 'development') ? true : false; +} + +function fallback_get_config(string $key, string $item, $default_when_not_found = false) { + if (! method_exists("\CodeHydrater\bootstrap\configure", "has")) { + return $default_when_not_found; + } + $value = $default_when_not_found; // Init defaults + if (configure::has($key, $item)) { + $value = configure::get($key, $item); + if ($value === null) { + return $default_when_not_found; + } + } + return $value; +} + +function should_be_broken(string $msg = ""): bool { + + $clear = fallback_get_config("CodeHydrater", "clear_screen_on_prod_errors"); + + if (fallback_get_config("CodeHydrater", "if_live_with_error_show_broken_page") === true) { + broken_error($msg, $clear); + return true; + } else { + broken_error($msg, false); // Don't Clear + } + + return false; +} + +function fallback_mini_view_prod(string $msg, string $file = "prod_error.php") { + if (fallback_get_config("CodeHydrater", "clear_screen_on_prod_errors") === false) { + return $msg; // Return Error Message on False and do not clear the Screen + } + echo fallback_mini_view($msg, $file); +} + +function fallback_mini_view_dev(string $msg, string $file = "dev_error.php") { + if (fallback_get_config("CodeHydrater", "clear_screen_on_dev_errors") === false) { + return $msg; // Return Error Message on False and do not clear the Screen + } + echo fallback_mini_view($msg, $file); +} + +function fallback_mini_view(string $msg, string $file = "dev_error.php"): string { + + @ob_end_clean(); // Wipe all HTML content before this.... + if (!headers_sent()) { + header('Content-Type: text/html; charset=utf-8', true, 200); + } + + views::ob_start(); + + $saved_ob_level = ob_get_level(); + + $mini = new \stdClass(); + $mini->page_output = $msg; + if (fallback_requires($file, false, $mini) === false) { + fallback_requires("views/on_error/" . $file, true, $mini); + } + + // If you really must close all of your output buffers except one, this'll do it: + while (ob_get_level() > $saved_ob_level) { + ob_end_flush(); + } + + return @ob_get_clean(); +} + +function fallback_logger(string $logMessage, string $file = LOG_FILE) { + if (method_exists("CodeHydrater\services\log", "write")) { + $logger = new \CodeHydrater\services\log("errors"); + $written = $logger->write($logMessage); + if ($written === false) { + // Open a connection to the system logger + openlog("PHP App", LOG_PID | LOG_ODELAY, LOG_LOCAL0); + + // Write a message + syslog(LOG_INFO, $logMessage); + + // Close the connection + closelog(); + } + } else { + $Message = date('[Y-m-d H:i:s]') . $logMessage; + file_put_contents($file, $Message, FILE_APPEND); + } } /** @@ -29,13 +124,23 @@ function formatMessage($message, $type = 'error') { } else { // Web HTML formatting $styles = [ - 'error' => 'color:red;', - 'warning' => 'color:orange;', - 'notice' => 'color:blue;' + 'error' => 'uk-alert-danger', + 'warning' => 'uk-alert-warning', + 'notice' => 'uk-alert-primary' ]; $style = $styles[$type] ?? $styles['error']; $message = wordwrap($message, WORD_WRAP_CHRS, "
\n"); - return "
$message
"; + + $assets = "/assets/uikit/css/uikit.gradient.min.css"; + if (file_exists(BaseDir. "/public/" . $assets)) { + $msg = ''; + $msg .= "
"; + } else { + $msg = "
getMessage() . " in " . $e->getFile() . " on line " . $e->getLine() . PHP_EOL; + $logMessage = " [EXCEPTION] " . $e->getMessage() . " in " . $e->getFile() . " on line " . $e->getLine() . PHP_EOL; $displayMessage = "UNCAUGHT EXCEPTION: " . $e->getMessage() . " in " . $e->getFile() . " on line " . $e->getLine(); - if (LOG_FILE !== false) { - file_put_contents(LOG_FILE, $logMessage, FILE_APPEND); - } + fallback_logger($logMessage); + // Are we developing...? if so, show details on error if (fallback_dev()) { - echo formatMessage($displayMessage, 'error'); + echo fallback_mini_view_dev(formatMessage($displayMessage, 'error')); } else { - // In production, show user-friendly message - echo PHP_SAPI === 'cli' - ? "An error occurred. Our team has been notified." . PHP_EOL - : "An error occurred. Our team has been notified."; + if (should_be_broken($displayMessage) === false) { + // In production, show user-friendly message + echo PHP_SAPI === 'cli' + ? "An error occurred. Our team has been notified." . PHP_EOL + : "An error occurred. Our team has been notified."; + } } }); @@ -123,31 +221,28 @@ register_shutdown_function(function() { } $error = error_get_last(); if ($error && in_array($error['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR])) { - $logMessage = date('[Y-m-d H:i:s]') . " [FATAL] {$error['message']} in {$error['file']} on line {$error['line']}" . PHP_EOL; + $logMessage = " [FATAL] {$error['message']} in {$error['file']} on line {$error['line']}" . PHP_EOL; $displayMessage = "FATAL ERROR: {$error['message']} in {$error['file']} on line {$error['line']}"; + + fallback_logger($logMessage); - if (LOG_FILE !== false) { - file_put_contents(LOG_FILE, $logMessage, FILE_APPEND); - } // If developing, show error if (fallback_dev()) { - echo formatMessage($displayMessage, 'error'); + echo fallback_mini_view_dev(formatMessage($displayMessage, 'error')); + } else { + should_be_broken($displayMessage); } } }); -function fallback_is_live(): bool { - return is_live(); // from main.php -} - /** * Displays Error page * @param type $ex error message */ -function broken_error($ex = ''): void { +function broken_error(string $ex = "", bool $clear = false): void { if (fallback_is_cli()) { echo $ex; - exit(1); + return; } $use_api = fallback_is_api(); @@ -155,24 +250,14 @@ function broken_error($ex = ''): void { $internal_error = "An unexpected error occured."; $status_code = 500; fallback_json_error($internal_error, $status_code); + return; } - if (fallback_is_live()) { - // Try really Hard to display Prod Error Page - $exists = fallback_requires('prod_error.php'); - if (! $exists) { - $exists = fallback_requires('views/on_error/prod_error.php', true); - } - if ($exists === false) { - echo "

Sorry, we had an error...

We apologize for any inconvenience this may cause.

"; - } + $error_message = "

Sorry, we had an error...

We apologize for any inconvenience this may cause.

"; + if ($clear === false) { + echo $error_message; } else { - if ($ex === "") { - echo "

Unknown Issue...

"; - } else { - echo $ex; - } - echo "

Error Page

Please go back to another page...

"; + echo fallback_mini_view_prod($error_message); } } @@ -188,7 +273,6 @@ function fallback_json_error(string $data, int $status_code): void { header('Content-Type: application/json; charset=utf-8', true, intval($status_code)); } echo json_encode($data); - exit; } function fallback_is_api(): bool { @@ -224,20 +308,14 @@ function fallback_is_cli() { } function fallback_get_uri(): ?string { - return strtok($_SERVER['REQUEST_URI']); -} - -function fallback_dev(): bool { - if (! defined("ENVIRONMENT")) { - return false; // Force Live on unknown state - } - if (ENVIRONMENT === 'development') { - return true; + $uri = strtok($_SERVER['REQUEST_URI'], "?"); + if ($uri === false) { + return ""; } - return false; + return $uri; } -function fallback_requires(string $file, bool $fw = false): bool { +function fallback_requires(string $file, bool $fw = false, $local = null): bool { $exists = method_exists("\CodeHydrater\bootstrap\requires", "secure_include"); if ($exists) { if ($fw === false) { @@ -261,19 +339,6 @@ function fallback_requires(string $file, bool $fw = false): bool { return false; // You have failed me for the last time! LOL } -/** - * Check if already on Error Page - * @return bool - */ -function is_on_error_page(): bool { - if (fallback_is_cli()) { - exit(1); - } else { - return (stripos(fallback_get_uri(), "error.html") !== false); - } -} - - // Test the error handler (uncomment to test) // trigger_error("This is a test warning", E_USER_WARNING); // throw new Exception("This is a test exception"); diff --git a/src/bootstrap/main.php b/src/bootstrap/main.php index 4b43e77..e06a4c9 100644 --- a/src/bootstrap/main.php +++ b/src/bootstrap/main.php @@ -293,6 +293,7 @@ registry::get('loader')->add_namespace("Project", CodeHydrater_PROJECT); load_all::init(CodeHydrater_PROJECT); +// Keep these blocks of code here not anywhere before it... if (! defined('ENVIRONMENT')) { if (is_live() === false) { define('ENVIRONMENT', 'development'); diff --git a/src/classes/enums/view_type.php b/src/classes/enums/view_type.php new file mode 100644 index 0000000..2119660 --- /dev/null +++ b/src/classes/enums/view_type.php @@ -0,0 +1,16 @@ + + * @copyright (c) 2025, Robert Strutts + * @license MIT + */ +namespace CodeHydrater\enums; + +enum view_type: string { + case LIQUID = ".tpl"; + case TWIG = ".twig"; + case PHP = ".php"; +} \ No newline at end of file diff --git a/src/classes/extras_booter.php b/src/classes/extras_booter.php index 14bbe81..fd89df0 100644 --- a/src/classes/extras_booter.php +++ b/src/classes/extras_booter.php @@ -12,19 +12,23 @@ namespace CodeHydrater; use HydraterBootloader\LicenseVerifier; -const PublicPEM = BaseDir."/keydata/public.pem"; -const AESKeysFile = BaseDir."/src/aeskeys.php"; -const LicenseFile = BaseDir."/keydata/license.json"; +const PublicPEM = BaseDir."/protected/keydata/public.pem"; +const AESKeysFile = BaseDir."/protected/src/aeskeys.php"; +const LicenseFile = BaseDir."/protected/keydata/license.json"; class extras_booter { - public static function tryToEnableFeature(string $featureName) { + public static function tryToEnableFeature(string $featureName, bool $include = true, $refresh = false) { if (! class_exists("HydraterBootloader\LicenseVerifier")) { return false; } $verifier = new LicenseVerifier(); - return $verifier->tryEnabledItem(LicenseFile, AESKeysFile, $featureName, PublicPEM); + try { + return $verifier->tryEnabledItem(LicenseFile, AESKeysFile, $featureName, PublicPEM, $include, $refresh); + } catch (\Exception $e) { + return false; + } } } // tryToEnableFeature("testing"); \ No newline at end of file diff --git a/src/classes/services/log.php b/src/classes/services/log.php index 78daf52..33204c9 100644 --- a/src/classes/services/log.php +++ b/src/classes/services/log.php @@ -99,7 +99,10 @@ final class log { } $dt = new \DateTime(); $now = $dt->format('g:i A \o\n l jS F Y'); - fwrite($this->handle, $now . ' - ' . print_r($message, true) . "\n"); + $written = fwrite($this->handle, $now . ' - ' . print_r($message, true) . "\n"); + if ($written === false) { + return false; + } return true; } diff --git a/src/classes/tag_matches.php b/src/classes/tag_matches.php index 6e2882d..20e3a59 100644 --- a/src/classes/tag_matches.php +++ b/src/classes/tag_matches.php @@ -3,12 +3,12 @@ declare(strict_types=1); /** - * @author Robert Strutts + * @author Robert Strutts * @copyright Copyright (c) 2022, Robert Strutts. * @license MIT */ -namespace tts; +namespace CodeHydrater; final class tag_matches { @@ -23,16 +23,16 @@ const tags_to_check = array('div', 'span', 'form', 'i*', 'a*', 'h1', 'p*'); public static function check_tags(string $page): array { $alert = ''; $output = ''; - $l_page = \bs_tts\common::string_to_lowercase($page); + $l_page = bootstrap\common::string_to_lowercase($page); unset($page); - $assets = \bs_tts\site_helper::get_asset("uikit/css/uikit.gradient.min.css"); + $assets = "/assets/uikit/css/uikit.gradient.min.css"; $ui = ''; $ui .= '
'; $ui_end = '
'; foreach (self::tags_to_check as $tag_name) { - if (\bs_tts\common::is_string_found($tag_name, '*')) { + if (bootstrap\common::is_string_found($tag_name, '*')) { $tag_name = str_replace('*', '', $tag_name); $otag = "<{$tag_name}>"; // Open Tag $open = substr_count($l_page, $otag); // Count open tags in page @@ -50,11 +50,11 @@ public static function check_tags(string $page): array { if ($total_still_open > 0) { $msg = "{$total_still_open} possibly MISSING closing {$tag_name} !!!"; $alert .= "console.log('{$msg}');\r\n"; - $output .= (\main_tts\is_live()) ? "\r\n" : "{$ui}{$msg}{$ui_end}\r\n"; + $output .= (bootstrap\is_live()) ? "\r\n" : "{$ui}{$msg}{$ui_end}\r\n"; } elseif ($total_still_open < 0) { $msg = abs($total_still_open) . " possibly MISSING opening {$tag_name} !!!"; $alert .= "console.log('{$msg}');\r\n"; - $output .= (\main_tts\is_live()) ? "\r\n" : "{$ui}{$msg}{$ui_end}\r\n"; + $output .= (bootstrap\is_live()) ? "\r\n" : "{$ui}{$msg}{$ui_end}\r\n"; } } return array('output' => $output, 'alert' => $alert); diff --git a/src/classes/view.php b/src/classes/view.php index 58dcf8f..b72437b 100644 --- a/src/classes/view.php +++ b/src/classes/view.php @@ -208,8 +208,8 @@ final class view { $page_output .= ob_get_clean(); try { - if (bootstrap\common::get_bool(bootstrap\configure::get('tts', 'check_HTML_tags')) === true) { - $tags = \tts\tag_matches::check_tags($page_output); + if (bootstrap\common::get_bool(bootstrap\configure::get('CodeHydrater', 'check_HTML_tags')) === true) { + $tags = \CodeHydrater\tag_matches::check_tags($page_output); if (! empty($tags['output'])) { $page_output .= $tags['output']; $page_output .= ''; @@ -219,7 +219,7 @@ final class view { } } } catch (exceptions\Bool_Exception $e) { - if (bootstrap\configure::get('tts', 'live') === false) { + if (bootstrap\configure::get('CodeHydrater', 'live') === false) { $page_output .= assets::alert('SET Config for tts: check_HTML_tags'); } } diff --git a/src/views/on_error/dev_error.php b/src/views/on_error/dev_error.php index 7f36528..05f7ff4 100644 --- a/src/views/on_error/dev_error.php +++ b/src/views/on_error/dev_error.php @@ -14,7 +14,7 @@ - +

Development errors:

page_output; ?>