Fixed Cookie Sessions to close before Response Body...in Kernel.

main
Robert 3 weeks ago
parent b7b18a924d
commit 9b2d9f9390
  1. 3
      src/Bootstrap.php
  2. 445
      src/Framework/Assets.php
  3. 4
      src/Framework/ErrorHandler.php
  4. 869
      src/Framework/HtmlDocument.php
  5. 3
      src/Framework/Http/Kernel.php
  6. 5
      src/Framework/Services/Sessions/CookieSessionHandler.php
  7. 10
      src/Framework/SessionManagement.php
  8. 63
      src/Framework/SiteHelper.php

@ -11,6 +11,7 @@ declare(strict_types=1);
use IOcornerstone\Psr4AutoloaderClass;
use IOcornerstone\Framework\{
Registry as Reg,
SiteHelper,
Console,
Configure,
CliDefaults,
@ -46,6 +47,8 @@ $loader->addNamespace("Psr\Http\Server", [
PSR . 'http-server-handler' . DIRECTORY_SEPARATOR . 'src'
]);
SiteHelper::setupHTTP();
function dd($var = 'nothing', endDump $end = endDump::EXIT_AND_STOP)
{
Common::dump($var, $end);

@ -1,12 +1,13 @@
<?php
declare(strict_types = 1);
declare(strict_types=1);
/**
* @author Robert Strutts
* @copyright (c) 2026, Robert Strutts
* @license MIT
*/
namespace IOcornerstone\Framework;
use IOcornerstone\Framework\{
@ -17,26 +18,34 @@ use IOcornerstone\Framework\{
class Assets
{
public static function getVer(string $filename): string {
if (self::attemptsRootDir($filename)) {
return "";
private static $files = [];
public static function getAssetFiles(): array{
return self::$files;
}
$safe_file = Security::filterUri($filename);
if (! file_exists($safe_file)) {
return "?ver=false";
public static function getVer(string $filename): string
{
if (self::attemptsRootDir($filename)) {
return "";
}
$safe_file = Security::filterUri($filename);
if (!file_exists($safe_file)) {
return "?ver=false";
}
return "?ver=" . date('Y.m.d_H.i.s', filemtime($safe_file));
}
return "?ver=" . date('Y.m.d_H.i.s', filemtime($safe_file));
}
/**
/**
* Check for / or absolute path not belonging to /var/www or PRJ:ROOT
* @param string|null $path
* @return bool
*/
private static function attemptsRootDir(?string $path): bool {
private static function attemptsRootDir(?string $path): bool
{
// up from src and back up to public
$open_base_dir_path = BaseDir. '/public/';
$open_base_dir_path = BaseDir . '/public/';
if ($path === null || $path === '') {
return false;
@ -50,219 +59,249 @@ class Assets
return false;
}
public static function getAjaxFiles(string $ajax_folder): string {
if (self::attemptsRootDir($ajax_folder)) {
return "";
}
$safe_folder = Security::filterUri($ajax_folder);
$ret = "var assets_files = [];" . PHP_EOL;
$js = glob($safe_folder . "*.{js,css}", GLOB_BRACE);
foreach($js as $file) {
$ret .= 'assets_files.push({ filename: "' . basename($file) . '", ts: "' . self::getVer($file) . '" });' . PHP_EOL;
public static function getAjaxFiles(string $ajax_folder): string
{
if (self::attemptsRootDir($ajax_folder)) {
return "";
}
$safe_folder = Security::filterUri($ajax_folder);
$ret = "var assets_files = [];" . PHP_EOL;
$js = glob($safe_folder . "*.{js,css}", GLOB_BRACE);
foreach ($js as $file) {
$ret .= 'assets_files.push({ filename: "' . basename($file) . '", ts: "' . self::getVer($file) . '" });' . PHP_EOL;
}
return $ret;
}
return $ret;
}
public static function loadallCss(array $files, string $scope='project'): string {
$ret = '';
foreach($files as $file=>$a_media) {
$ret .= self::wrapCss($file, $scope, $a_media);
public static function loadallCss(array $files, string $scope = 'project'): string
{
$ret = '';
foreach ($files as $file => $a_media) {
$ret .= self::wrapCss($file, $scope, $a_media);
}
return $ret;
}
return $ret;
}
public static function loadallJs(array $files, string $scope='project'): string {
$ret = '';
foreach($files as $file=>$a) {
$ret .= self::wrapJs($file, $scope, $a);
public static function loadallJs(array $files, string $scope = 'project'): string
{
$ret = '';
foreach ($files as $file => $a) {
$ret .= self::wrapJs($file, $scope, $a);
}
return $ret;
}
return $ret;
}
public static function image(string $file, string $scope = '', array $a = array()): string {
$more = '';
if (count($a)) {
foreach ($a as $k => $v) {
$more .= " {$k}=\"{$v}\"";
}
public static function image(string $file, string $scope = '', array $a = array()): string
{
$more = '';
if (count($a)) {
foreach ($a as $k => $v) {
$more .= " {$k}=\"{$v}\"";
}
}
$file = self::wrapAsset($file, $scope);
if ($file === false) {
return '';
}
return "<img src=\"{$file}\" {$more}/>\r\n";
}
$file = self::wrapAsset($file, $scope);
if ($file === false) {
return '';
public static function alert($msg)
{
return self::inlineJs('alert("' . $msg . '");');
}
return "<img src=\"{$file}\" {$more}/>\r\n";
}
public static function alert($msg) {
return self::inlineJs('alert("'.$msg.'");');
}
/**
* Wrapper for JS/CSS assets for the page.
* @param string $file or CDN
* @param string $scope (project/framework/cdn)
* @retval boolean|string false is not found, else Asset REF
*/
public static function wrapAsset(string $file, string $scope = 'project')
{
$scope = StringFacade::strtolower($scope);
if ($scope === 'cdn') {
$proto = $_SERVER['SERVER_PROTOCOL'];
if ($proto === null) {
$protocol = '://';
} else {
$protocol = strtolower(substr($proto, 0, strpos($proto, '/'))) . '://';
}
return (str_contains($file, '://') === true) ? $file : $protocol . $file;
}
if ($scope === 'project' || $scope === 'app') {
$path = PROJECT_ASSETS_DIR;
$ism = self::isMinified($path, $file);
return ($ism !== false) ? PROJECT_ASSETS_BASE_REF . "/" . $ism : false;
}
if ($scope === 'assets') {
$path = ASSETS_DIR . "/";
$ism = self::isMinified($path, $file);
return ($ism !== false) ? ASSETS_BASE_REF . "/" . $ism : false;
}
return $file;
}
/**
* Wrapper for JS/CSS assets for the page.
* @param string $file or CDN
* @param string $scope (project/framework/cdn)
* @retval boolean|string false is not found, else Asset REF
*/
public static function wrapAsset(string $file, string $scope = 'project') {
$scope = StringFacade::strtolower($scope);
if ($scope === 'cdn') {
$proto = $_SERVER['SERVER_PROTOCOL'];
if ($proto === null) {
$protocol = '://';
/**
* Fetch Version of file if exists
* @param string $file
* @param string $scope
* @return string|bool
*/
private static function projectPaths(string $file, string $scope = 'project'): string|bool
{
$scope = stringFacade::strtolower($scope);
if ($scope === 'cdn') {
return "";
} else if ($scope === 'project' || $scope === 'app') {
$path = PROJECT_ASSETS_DIR;
} else if ($scope === 'assets') {
$path = ASSETS_DIR . "/";
} else {
$protocol = strtolower(substr($proto, 0, strpos($proto, '/'))) . '://';
return "";
}
$check = self::isMinified($path, $file);
$version = ($check !== false) ? self::getVer($path . $check) : false;
if ($version === false) {
return false;
}
return (str_contains($file, '://') === true) ? $file : $protocol . $file;
}
if ($scope === 'project' || $scope === 'app') {
$path = PROJECT_ASSETS_DIR;
$ism = self::isMinified($path, $file);
return ($ism !== false) ? PROJECT_ASSETS_BASE_REF . "/" . $ism : false;
}
if ($scope === 'assets') {
$path = ASSETS_DIR . "/";
$ism = self::isMinified($path, $file);
return ($ism !== false) ? ASSETS_BASE_REF . "/" . $ism : false;
}
return $file;
}
/**
* Fetch Version of file if exists
* @param string $file
* @param string $scope
* @return string|bool
*/
private static function projectPaths(string $file, string $scope = 'project'): string | bool {
$scope = stringFacade::strtolower($scope);
if ($scope === 'cdn') {
return "";
} else if ($scope === 'project' || $scope === 'app') {
$path = PROJECT_ASSETS_DIR;
} else if ($scope === 'assets') {
$path = ASSETS_DIR . "/";
} else {
return "";
}
$check = self::isMinified($path, $file);
return ($check !==false) ? self::getVer($path . $check) : false;
}
/**
* Wrapper to return the CSS href=file.. stylesheet code for use in page.
* @param string $file - CSS file
* @param string $media - default of all media
* @retval string
*/
public static function wrapCss(string $file, string $scope = 'project', array $a_media = array()): string {
$more = '';
if (count($a_media)) {
foreach ($a_media as $k => $v) {
$more .= " {$k}=\"{$v}\"";
}
} else {
$more .= " media=\"all\"";
if (self::hasFile($file)) {
return false;
}
return $version;
}
$ver = self::projectPaths($file, $scope);
$wrap_file = self::wrapAsset($file, $scope);
if ($ver === false || $wrap_file === false) {
return "<!-- CSS: {$file} not Found -->";
private static function hasFile(string $file): bool
{
if (in_array($file, static::$files)) {
return true;
}
static::$files[] = $file;
return false;
}
return "<link rel=\"stylesheet\" href=\"{$wrap_file}{$ver}\" type=\"text/css\"{$more}/>\r\n";
}
/**
* Wrapper to return the JavaScript src=file... code for use with page.
* @param type $file - external JS file.
* @retval string of script src=file
*/
public static function wrapJs(string $file, string $scope = 'project', array $a = array()): string {
$more = '';
if (count($a)) {
foreach ($a as $k => $v) {
$more .= (isset($k) && $k !=0 ) ? " {$k}=\"{$v}\"" : " {$v}";
}
}
/**
* Wrapper to return the CSS href=file.. stylesheet code for use in page.
* @param string $file - CSS file
* @param string $media - default of all media
* @retval string
*/
public static function wrapCss(string $file, string $scope = 'project', array $a_media = array()): string
{
$more = '';
if (count($a_media)) {
foreach ($a_media as $k => $v) {
$more .= " {$k}=\"{$v}\"";
}
} else {
$more .= " media=\"all\"";
}
$ver = self::projectPaths($file, $scope);
$wrap_file = self::wrapAsset($file, $scope);
if ($ver === false || $wrap_file === false) {
return "<!-- Script: {$file} not Found -->";
$ver = self::projectPaths($file, $scope);
$wrap_file = self::wrapAsset($file, $scope);
if ($ver === false || $wrap_file === false) {
return "<!-- CSS: {$file} not Found -->";
}
return "<link rel=\"stylesheet\" href=\"{$wrap_file}{$ver}\" type=\"text/css\"{$more}/>\r\n";
}
return "<script src=\"{$wrap_file}{$ver}\"{$more}></script>\r\n";
//return "<script type=\"text/javascript\">js_loader(\"{$file}\");</script>";
}
/**
* Purpose: To do inline JavaScript.
* @param type $code string of code to inline into page.
* @retval type
*/
public static function inlineJs(string $code): string {
return "<script type=\"text/javascript\">\r\n//<![CDATA[\r\n {$code}\r\n //]]> \r\n </script>\r\n";
}
/**
* Wrapper to return the JavaScript src=file... code for use with page.
* @param type $file - external JS file.
* @retval string of script src=file
*/
public static function wrapJs(string $file, string $scope = 'project', array $a = array()): string
{
$more = '';
if (count($a)) {
foreach ($a as $k => $v) {
$more .= (isset($k) && $k != 0) ? " {$k}=\"{$v}\"" : " {$v}";
}
}
/**
* Purpose: To execute this JavaScript code once JQuery is Ready().
* @param string $code to do once JQuery is Ready
* @retval string wrapped in ready code...
*/
public static function jqueryLoad(string $code): string {
return "\r\n$(function() { \r\n \t {$code} \r\n }); \r\n";
}
$ver = self::projectPaths($file, $scope);
$wrap_file = self::wrapAsset($file, $scope);
if ($ver === false || $wrap_file === false) {
return "<!-- Script: {$file} not Found -->";
}
return "<script src=\"{$wrap_file}{$ver}\"{$more}></script>\r\n";
//return "<script type=\"text/javascript\">js_loader(\"{$file}\");</script>";
}
public static function isMinified(string $path, string $file) {
if (self::attemptsRootDir($path)) {
return false;
/**
* Purpose: To do inline JavaScript.
* @param type $code string of code to inline into page.
* @retval type
*/
public static function inlineJs(string $code): string
{
return "<script type=\"text/javascript\">\r\n//<![CDATA[\r\n {$code}\r\n //]]> \r\n </script>\r\n";
}
$safe_path = Security::filterUri($path);
$safe_file = Security::filterUri($file);
if (str_contains($safe_file, '.auto.js')) {
$production = (isLive());
$safe_file = str_replace('.auto.js', '', $safe_file);
if ( $production && file_exists($safe_path . $safe_file . '.min.js') ) {
return $safe_file . '.min.js';
}
return (file_exists($safe_path . $safe_file . '.js')) ? $safe_file . '.js' : false;
/**
* Purpose: To execute this JavaScript code once JQuery is Ready().
* @param string $code to do once JQuery is Ready
* @retval string wrapped in ready code...
*/
public static function jqueryLoad(string $code): string
{
return "\r\n$(function() { \r\n \t {$code} \r\n }); \r\n";
}
if (str_contains($safe_file, '.auto.css')) {
$production = (isLive());
$safe_file = str_replace('.auto.css', '', $safe_file);
if ( $production && file_exists($safe_path . $safe_file . '.min.css') ) {
return $safe_file . '.min.css';
}
return (file_exists($safe_path . $safe_file . '.css')) ? $safe_file . '.css' : false;
}
return ( file_exists($safe_path . $safe_file) ) ? $safe_file : false;
}
/**
* meta redirect when headers are already sent...
* @param string url - site to do redirect on
* @reval none
*/
public static function gotoUrl(string $url): void {
echo '<META http-equiv="refresh" content="0;URL=' . $url . '">';
exit;
}
public static function isMinified(string $path, string $file)
{
if (self::attemptsRootDir($path)) {
return false;
}
$safe_path = Security::filterUri($path);
$safe_file = Security::filterUri($file);
if (str_contains($safe_file, '.auto.js')) {
$production = (isLive());
$safe_file = str_replace('.auto.js', '', $safe_file);
if ($production && file_exists($safe_path . $safe_file . '.min.js')) {
return $safe_file . '.min.js';
}
return (file_exists($safe_path . $safe_file . '.js')) ? $safe_file . '.js' : false;
}
if (str_contains($safe_file, '.auto.css')) {
$production = (isLive());
$safe_file = str_replace('.auto.css', '', $safe_file);
if ($production && file_exists($safe_path . $safe_file . '.min.css')) {
return $safe_file . '.min.css';
}
return (file_exists($safe_path . $safe_file . '.css')) ? $safe_file . '.css' : false;
}
return (file_exists($safe_path . $safe_file)) ? $safe_file : false;
}
/**
* Rediect to url and attempt to send via header.
* @param string $url - site to do redirect for
* @retval none - exits once done
*/
public static function redirectUrl(string $url): void {
$url = str_replace(array('&amp;', "\n", "\r"), array('&', '', ''), $url);
if (!headers_sent()) {
header('Location: ' . $url);
} else {
self::goto_url($url);
/**
* meta redirect when headers are already sent...
* @param string url - site to do redirect on
* @reval none
*/
public static function gotoUrl(string $url): void
{
echo '<META http-equiv="refresh" content="0;URL=' . $url . '">';
exit;
}
exit;
}
/**
* Rediect to url and attempt to send via header.
* @param string $url - site to do redirect for
* @retval none - exits once done
*/
public static function redirectUrl(string $url): void
{
$url = str_replace(array('&amp;', "\n", "\r"), array('&', '', ''), $url);
if (!headers_sent()) {
header('Location: ' . $url);
} else {
self::goto_url($url);
}
exit;
}
}

@ -115,7 +115,9 @@ final class ErrorHandler
return true;
}
http_response_code(500);
if (! headers_sent()) {
http_response_code(500);
}
if ($this->debug) {
$this->renderDebug($e);

@ -1,12 +1,13 @@
<?php
declare(strict_types = 1);
declare(strict_types=1);
/**
* @author Robert Strutts
* @copyright (c) 2026, Robert Strutts
* @license MIT
*/
namespace IOcornerstone\Framework;
use IOcornerstone\Framework\{
@ -22,414 +23,474 @@ use IOcornerstone\Framework\{
*/
class HtmlDocument
{
private $title = '';
private $author = '';
private $description = '';
private $keywords = '';
private $robots = '';
private $head = '';
private $header = '';
private $body = '';
private $footer = '';
private $jsOnReady = '';
private $styles = '';
private $scripts = '';
private $mainStyles = '';
private $mainScripts = '';
private $activeCrumb = '';
private $breadcrumb = array();
public function __construct() {
$this->title = Configure::get('html', 'title') ?? '';
$this->author = Configure::get('html', 'author') ?? '';
$this->footer = Configure::get('html', 'footer') ?? '';
$this->keywords = Configure::get('html', 'keywords') ?? '';
$this->description = Configure::get('html', 'description') ?? '';
$this->robots = Configure::get('html', 'robots');
$css = Configure::get('html', 'css');
if (Common::getCount($css) > 0) {
foreach($css as $file=>$path) {
if (is_array($file)) continue;
if (is_array($path)) {
if (isset($path['path'])) {
$pathType = $path['path'];
unset($path['path']);
} else {
$pathType = "project";
private $title = '';
private $author = '';
private $description = '';
private $keywords = '';
private $robots = '';
private $head = '';
private $header = '';
private $body = '';
private $footer = '';
private $jsOnReady = '';
private $styles = '';
private $scripts = '';
private $mainStyles = '';
private $mainScripts = '';
private $activeCrumb = '';
private $breadcrumb = [];
public function __construct()
{
$this->title = Configure::get('html', 'title') ?? '';
$this->author = Configure::get('html', 'author') ?? '';
$this->footer = Configure::get('html', 'footer') ?? '';
$this->keywords = Configure::get('html', 'keywords') ?? '';
$this->description = Configure::get('html', 'description') ?? '';
$this->robots = Configure::get('html', 'robots');
$css = Configure::get('html', 'css');
if (Common::getCount($css) > 0) {
foreach ($css as $file => $path) {
if (is_array($file))
continue;
if (is_array($path)) {
if (isset($path['path'])) {
$pathType = $path['path'];
unset($path['path']);
} else {
$pathType = "project";
}
$this->addCss($file, $pathType, $path);
} else {
$this->addCss($file, $path);
}
}
$this->addCss($file, $pathType, $path);
} else {
$this->addCss($file, $path);
}
}
}
$js = Configure::get('html', 'javascript');
if (Common::getCount($js) >0) {
foreach($js as $file=>$path) {
if (is_array($file)) continue;
if (is_array($path)) {
if (isset($path['path'])) {
$pathType = $path['path'];
unset($path['path']);
} else {
$pathType = "project";
$js = Configure::get('html', 'javascript');
if (Common::getCount($js) > 0) {
foreach ($js as $file => $path) {
if (is_array($file))
continue;
if (is_array($path)) {
if (isset($path['path'])) {
$pathType = $path['path'];
unset($path['path']);
} else {
$pathType = "project";
}
$this->addJs($file, $pathType, $path);
} else {
$this->addJs($file, $path);
}
}
$this->addJs($file, $pathType, $path);
} else {
$this->addJs($file, $path);
}
}
}
}
public function clearCss(): void {
$this->styles = '';
}
public function clearJs(): void {
$this->scripts = '';
}
/**
* Set both Title and Header for HTML
* @param string $title
*/
public function setTitleAndHeader(string $title): void {
$this->title = $title;
$this->header = $title;
}
/**
* Set Author for HTML
* @param string $title
*/
public function setAuthor(string $author): void {
$this->author = $author;
}
/**
* Set Title for HTML
* @param string $title
*/
public function setTitle(string $title): void {
$this->title = $title;
}
/**
* Set Header for HTML
* @param string $header
*/
public function setHeader(string $header): void {
$this->header = $header;
}
public function setHead(string $head): void {
$this->head = $head;
}
/**
* Set Footer for HTML
* @param string $footer
*/
public function setFooter(string $footer): void {
public function clearCss(): void
{
$this->styles = '';
}
public function clearJs(): void
{
$this->scripts = '';
}
/**
* Set both Title and Header for HTML
* @param string $title
*/
public function setTitleAndHeader(string $title): void
{
$this->title = $title;
$this->header = $title;
}
/**
* Set Author for HTML
* @param string $title
*/
public function setAuthor(string $author): void
{
$this->author = $author;
}
/**
* Set Title for HTML
* @param string $title
*/
public function setTitle(string $title): void
{
$this->title = $title;
}
/**
* Set Header for HTML
* @param string $header
*/
public function setHeader(string $header): void
{
$this->header = $header;
}
public function setHead(string $head): void
{
$this->head = $head;
}
/**
* Set Footer for HTML
* @param string $footer
*/
public function setFooter(string $footer): void
{
// $this->add_css('footer.css', 'project');
$this->footer = $footer;
}
/**
* Set Description for HTML
* @param string $description
*/
public function setDescription(string $description): void {
$this->description = $description;
}
/**
* Set Keywords for HTML
* @param string $keywords
*/
public function setKeywords(string $keywords): void {
$this->keywords = $keywords;
}
/**
* Set Robots for HTML
* @param string $robot
*/
public function setRobots(string $robot): void {
$this->robots = $robot;
}
public function setBody(string $body): void {
$this->body = $body;
}
/**
* Set Active BreadCrumb in HTML
* @param string $active
*/
public function setActiveCrumb(string $active): void {
$this->activeCrumb = $active;
}
/**
* Set BreadCrumbs using array (HyperLink => Name of Crumb)
* @param array $crumbs Array(href => name)
*/
public function setBreadcrumbs(array $crumbs): void {
$this->breadcrumb = $crumbs;
}
public function setAssetsFromArray(array $files, string $which, string $scope = 'project'): void {
foreach($files as $file => $a) {
switch($which) {
case 'main_css':
$this->addMainCss($file, $scope, $a);
break;
case 'css':
$this->addCss($file, $scope, $a);
break;
case 'main_js':
$this->addMainJs($file, $scope, $a);
break;
case 'js':
$this->addJs($file, $scope, $a);
break;
}
}
}
private function missingFile(string $file, string $scope, string $kind) {
$failed = strtoupper($kind) . " filename of {$file} - {$scope} Asset Failed to Load!";
$this->addToJavascript("console.log(\"%c {$failed}\", \"color: red\")");
$comment = "<!-- {$failed} -->";
if ($kind === "css") {
$this->styles .= $comment;
} else if ($kind === "main_css") {
$this->mainStyles .= $comment;
} else if ($kind === "js") {
$this->scripts .= $comment;
} else if ($kind === "main_js") {
$this->mainScripts .= $comment;
$this->footer = $footer;
}
/**
* Set Description for HTML
* @param string $description
*/
public function setDescription(string $description): void
{
$this->description = $description;
}
/**
* Set Keywords for HTML
* @param string $keywords
*/
public function setKeywords(string $keywords): void
{
$this->keywords = $keywords;
}
/**
* Set Robots for HTML
* @param string $robot
*/
public function setRobots(string $robot): void
{
$this->robots = $robot;
}
public function setBody(string $body): void
{
$this->body = $body;
}
/**
* Set Active BreadCrumb in HTML
* @param string $active
*/
public function setActiveCrumb(string $active): void
{
$this->activeCrumb = $active;
}
/**
* Set BreadCrumbs using array (HyperLink => Name of Crumb)
* @param array $crumbs Array(href => name)
*/
public function setBreadcrumbs(array $crumbs): void
{
$this->breadcrumb = $crumbs;
}
public function setAssetsFromArray(array $files, string $which, string $scope = 'project'): void
{
foreach ($files as $file => $a) {
switch ($which) {
case 'main_css':
$this->addMainCss($file, $scope, $a);
break;
case 'css':
$this->addCss($file, $scope, $a);
break;
case 'main_js':
$this->addMainJs($file, $scope, $a);
break;
case 'js':
$this->addJs($file, $scope, $a);
break;
}
}
}
private function missingFile(string $file, string $scope, string $kind)
{
$failed = strtoupper($kind) . " filename of {$file} - {$scope} Asset Failed to Load!";
$this->addToJavascript("console.log(\"%c {$failed}\", \"color: red\")");
$comment = "<!-- {$failed} -->";
if ($kind === "css") {
$this->styles .= $comment;
} else if ($kind === "main_css") {
$this->mainStyles .= $comment;
} else if ($kind === "js") {
$this->scripts .= $comment;
} else if ($kind === "main_js") {
$this->mainScripts .= $comment;
}
}
/**
* Add CSS stylesheet to HTML under main CSS
* @param string $file
* @param string $scope (project, framework, cdn)
* @return bool was successful
*/
public function addCss(string $file, string $scope = 'project', array $a = array()): bool
{
$css = Assets::wrapAsset($file, $scope);
if ($css === false) {
$this->missingFile($file, $scope, "css");
return false;
}
$this->styles .= Assets::wrapCss($file, $scope, $a);
return true;
}
/**
* Add JS JavaScript to HTML under main JS
* @param string $file
* @param string $scope (project, framework, cdn)
* @return bool was successful
*/
public function addJs(string $file, string $scope = 'project', array $a = array()): bool
{
$js = Assets::wrapAsset($file, $scope);
if ($js === false) {
$this->jsLog($file . " - {$scope} Asset Failed to Load!");
return false;
}
$this->scripts .= Assets::wrapJs($file, $scope, $a);
return true;
}
/**
* Add CSS stylesheet to HTML towards top of HTML for CSS
* @param string $file
* @param string $scope (project, framework, cdn)
* @return bool was successful
*/
public function addMainCss(string $file, string $scope = 'project', array $a = array()): bool
{
$css = Assets::wrapAsset($file, $scope);
if ($css === false) {
$this->jsLog($file . " - {$scope} Asset Failed to Load!");
return false;
}
$this->mainStyles .= Assets::wrapCss($file, $scope, $a);
return true;
}
/**
* Add JavaScript to HTML towards top of HTML for JS
* @param string $file
* @param string $scope (project, framework, cdn)
* @return bool was successful
*/
public function addMainJs(string $file, string $scope = 'project', array $a = array()): bool
{
$js = Assets::wrapAsset($file, $scope);
if ($js === false) {
$this->jsLog($file . " - {$scope} Asset Failed to Load!");
return false;
}
$this->mainScripts .= Assets::wrapJs($file, $scope, $a);
return true;
}
/**
* Adds JavaScript code to called after JQuery is ready.
* @param string $code
*/
//public function add_js_onready(string $code): void {
// $this->js_onready .= \px_inline_js(\px_jquery_load($code));
//}
/**
* Log to JavaScript Console under Chrome Browser
* @param string $log
*/
public function jsLog(string $log): void
{
$this->addToJavascript("console.log('{$log}');");
}
/**
* Place JavaScript in HTML
* @param string $js
*/
public function addToJavascript(string $js): void
{
if (!empty($js)) {
$this->scripts .= Assets::inlineJs($js);
}
}
/**
* Use CSS/JS for Database SSP
public function datatables_code(): void {
$this->addCss('datatables/datatables.min.css', 'cl');
$this->addJs('datatables/datatables_no_jquery.min.js', 'cl');
}
}
/**
* Add CSS stylesheet to HTML under main CSS
* @param string $file
* @param string $scope (project, framework, cdn)
* @return bool was successful
*/
public function addCss(string $file, string $scope = 'project', array $a = array()): bool {
$css = Assets::wrapAsset($file, $scope);
if ($css === false) {
$this->missingFile($file, $scope, "css");
return false;
}
$this->styles .= Assets::wrapCss($file, $scope, $a);
return true;
}
/**
* Add JS JavaScript to HTML under main JS
* @param string $file
* @param string $scope (project, framework, cdn)
* @return bool was successful
*/
public function addJs(string $file, string $scope = 'project', array $a = array()): bool {
$js = Assets::wrapAsset($file, $scope);
if ($js === false) {
$this->js_log($file . " - {$scope} Asset Failed to Load!");
return false;
}
$this->scripts .= Assets::wrapJs($file, $scope, $a);
return true;
}
/**
* Add CSS stylesheet to HTML towards top of HTML for CSS
* @param string $file
* @param string $scope (project, framework, cdn)
* @return bool was successful
*/
public function addMainCss(string $file, string $scope = 'project', array $a = array()): bool {
$css = Assets::wrapAsset($file, $scope);
if ($css === false) {
$this->js_log($file . " - {$scope} Asset Failed to Load!");
return false;
}
$this->mainStyles .= Assets::wrapCss($file, $scope, $a);
return true;
}
/**
* Add JavaScript to HTML towards top of HTML for JS
* @param string $file
* @param string $scope (project, framework, cdn)
* @return bool was successful
*/
public function addMainJs(string $file, string $scope = 'project', array $a = array()): bool {
$js = Assets::wrapAsset($file, $scope);
if ($js === false) {
$this->js_log($file . " - {$scope} Asset Failed to Load!");
return false;
}
$this->mainScripts .= Assets::wrapJs($file, $scope, $a);
return true;
}
/**
* Adds JavaScript code to called after JQuery is ready.
* @param string $code
*/
//public function add_js_onready(string $code): void {
// $this->js_onready .= \px_inline_js(\px_jquery_load($code));
//}
/**
* Log to JavaScript Console under Chrome Browser
* @param string $log
*/
public function jsLog(string $log): void {
$this->addToJavascript("console.log('{$log}');");
}
/**
* Place JavaScript in HTML
* @param string $js
*/
public function addToJavascript(string $js): void {
if (! empty($js)) {
$this->scripts .= Assets::inlineJs($js);
}
}
/**
* Use CSS/JS for Database SSP
public function datatables_code(): void {
$this->addCss('datatables/datatables.min.css', 'cl');
$this->addJs('datatables/datatables_no_jquery.min.js', 'cl');
}
*
*/
/**
* Used by Template file to render HTML Author
* @return string HTML Author
*/
public function getAuthor(): string {
return $this->author;
}
/**
* Used by Template file to render HTML TITLE
* @return string HTML TITLE
*/
public function getTitle(): string {
return $this->title;
}
/**
* Used by Template file to render HTML Header
* @return string HTML Header
*/
public function getHeader(): string {
return $this->header;
}
public function getBody(): string {
return $this->body;
}
/**
* Used by Template file to render HTML Footer
* @return string HTML Footer
*/
public function getFooter(): string {
return $this->footer;
}
/**
* Used by Template file to render HTML Meta data for Description
* @return string HTML Meta Description
*/
public function getDescription(): string {
return $this->description;
}
/**
* Used by Template file to render HTML Meta data for Keywords
* @return string HTML Meta Keywords
*/
public function getKeywords(): string {
return $this->keywords;
}
/**
* Used by Template file to render HTML Meta data for Robots
* @return string HTML Meta Robots
*/
public function getRobots(): ?string {
return $this->robots;
}
/**
* Used by Template file to render HTML CSS
* @return string HTML CSS
*/
public function getStyles(): string {
return $this->styles;
}
/**
* Used by Template file to render HTML JavaScripts
* @return string HTML JS
*/
public function getScripts(): string {
return $this->scripts;
}
/**
* Used by Template file to render HTML main CSS @Top
* @return string HTML CSS
*/
public function getMainStyles(): string {
return $this->mainStyles;
}
/**
* Used by Template file to render HTML main JS @Top
* @return string HTML JavaScript
*/
public function getMainScripts(): string {
return $this->mainScripts;
}
/**
* Used by Template file to render HTML JS after main JS
* @return string HTML JS
*/
public function getJsOnReady(): string {
return $this->jsOnReady;
}
/**
* Used by Template file to render HTML Active BreadCrumb
* @return string HTML Active BreadCrumb
*/
public function getActiveCrumb(): string {
return $this->activeCrumb;
}
/**
* Used by Template file to render HTML BreadCrumbs
* @return string HTML BreadCrumbs
*/
public function getBreadcrumbs(): array {
return $this->breadcrumb;
}
public function getHead(): string {
return $this->head;
}
*
*/
/**
* Used by Template file to render HTML Author
* @return string HTML Author
*/
public function getAuthor(): string
{
return $this->author;
}
/**
* Used by Template file to render HTML TITLE
* @return string HTML TITLE
*/
public function getTitle(): string
{
return $this->title;
}
/**
* Used by Template file to render HTML Header
* @return string HTML Header
*/
public function getHeader(): string
{
return $this->header;
}
public function getBody(): string
{
return $this->body;
}
/**
* Used by Template file to render HTML Footer
* @return string HTML Footer
*/
public function getFooter(): string
{
return $this->footer;
}
/**
* Used by Template file to render HTML Meta data for Description
* @return string HTML Meta Description
*/
public function getDescription(): string
{
return $this->description;
}
/**
* Used by Template file to render HTML Meta data for Keywords
* @return string HTML Meta Keywords
*/
public function getKeywords(): string
{
return $this->keywords;
}
/**
* Used by Template file to render HTML Meta data for Robots
* @return string HTML Meta Robots
*/
public function getRobots(): ?string
{
return $this->robots;
}
/**
* Used by Template file to render HTML CSS
* @return string HTML CSS
*/
public function getStyles(): string
{
return $this->styles;
}
/**
* Used by Template file to render HTML JavaScripts
* @return string HTML JS
*/
public function getScripts(): string
{
return $this->scripts;
}
/**
* Used by Template file to render HTML main CSS @Top
* @return string HTML CSS
*/
public function getMainStyles(): string
{
return $this->mainStyles;
}
/**
* Used by Template file to render HTML main JS @Top
* @return string HTML JavaScript
*/
public function getMainScripts(): string
{
return $this->mainScripts;
}
/**
* Used by Template file to render HTML JS after main JS
* @return string HTML JS
*/
public function getJsOnReady(): string
{
return $this->jsOnReady;
}
/**
* Used by Template file to render HTML Active BreadCrumb
* @return string HTML Active BreadCrumb
*/
public function getActiveCrumb(): string
{
return $this->activeCrumb;
}
/**
* Used by Template file to render HTML BreadCrumbs
* @return string HTML BreadCrumbs
*/
public function getBreadcrumbs(): array
{
return $this->breadcrumb;
}
public function getHead(): string
{
return $this->head;
}
public function getBreadcrumbsAuto(): string
{
if (! count($this->breadcrumb) && empty($this->activeCrumb)) {
return "";
}
$out = "<nav><ul class=\"breadcrumb\">" . PHP_EOL;
foreach($this->breadcrumb as $link => $crumb) {
$out .= "<li><a href=\"$link\">$crumb</a></li>" . PHP_EOL;
}
if (! empty($this->activeCrumb)) {
$out .= "<li>" . $this->activeCrumb . "</li>" . PHP_EOL;
}
$out .= "</ul></nav>" . PHP_EOL;
return $out;
}
}

@ -130,6 +130,9 @@ class Kernel {
header("$name: $value", false);
}
}
if (function_exists('session_status') && session_status() == PHP_SESSION_ACTIVE) {
session_write_close();
}
echo $response->getBody();
}

@ -39,10 +39,7 @@ class CookieSessionHandler implements \SessionHandlerInterface {
if (isset($options['cookie_secure'])) {
self::$cookieSecure = $options['cookie_secure'];
} else {
/**
* @todo Fix this...use_secure
*/
$use_secure = true;
$use_secure = (USE_SECURE);
if ($use_secure === false) {
self::$cookieSecure = false;
}

@ -45,7 +45,7 @@ final class SessionManagement
'files' => new FileSes($enc, $options),
default => new CookieSes($enc, $options),
};
session_set_save_handler($handler, true);
session_set_save_handler($handler);
self::makeSessionStarted();
}
@ -55,13 +55,9 @@ final class SessionManagement
if ($name !== null) {
session_name($name);
}
/**
* @todo Fix ForceSecure....to detect mode
*/
if (! headers_sent()) {
$use_secure = 1; // (site_helper::get_use_secure()) ? 1 : 0;
$use_secure = (USE_SECURE) ? 1 : 0;
$use_secure = ($force_secure) ? 1 : $use_secure;
session_start([
'cookie_lifetime' => 0, // until browser is closed

@ -1,12 +1,13 @@
<?php
declare(strict_types = 1);
declare(strict_types=1);
/**
* @author Robert Strutts
* @copyright (c) 2026, Robert Strutts
* @license MIT
*/
namespace IOcornerstone\Framework;
use IOcornerstone\Framework\Security;
@ -19,27 +20,48 @@ use IOcornerstone\Framework\Security;
*/
final class SiteHelper
{
private static $local_site_domains = ['localhost'];
private static $Private_IPs_allowed = ['127.0.0.1', '::1'];
private static $Public_IPs_allowed = [];
public static function setLocalSiteDomains(string|array $domain_name): void {
public static function setupHTTP(): void
{
define("PROJECT_ASSETS_DIR", BaseDir . DIRECTORY_SEPARATOR . "public" . DIRECTORY_SEPARATOR . "assets" . DIRECTORY_SEPARATOR);
$server_port = $_SERVER['SERVER_PORT'] ?? 80;
$secure_port_on = $_SERVER['HTTPS'] ?? "off";
$use_secure = ($server_port == "443" || $secure_port_on == "on");
$protocol = ($use_secure) ? "https://" : "http://";
$domain_name = $_SERVER['HTTP_HOST'] ?? "";
define("HTTP_PROT", $protocol);
define("USE_SECURE", $use_secure);
define("PROJECT_BASE_REF", $protocol . $domain_name);
define("PROJECT_ASSETS_BASE_REF", PROJECT_BASE_REF . "/assets");
define("ASSETS_DIR", PROJECT_ASSETS_DIR);
define('ASSETS_BASE_REF', PROJECT_ASSETS_BASE_REF);
}
public static function setLocalSiteDomains(string|array $domain_name): void
{
if (is_array($domain_name)) {
foreach($domain_name as $domain) {
foreach ($domain_name as $domain) {
self::$local_site_domains[] = $domain;
}
} elseif (is_string($domain_name)) {
self::$local_site_domains[] = $domain_name;
}
}
public static function setAllowedPrivateIPs(string|array $IP_addresses): void {
public static function setAllowedPrivateIPs(string|array $IP_addresses): void
{
if (is_array($IP_addresses)) {
foreach($IP_addresses as $IP) {
foreach ($IP_addresses as $IP) {
$s_ip = Security::getValidIp($IP);
if ($s_ip === false) {
continue;
}
}
self::$Private_IPs_allowed[] = $IP;
}
} elseif (is_string($IP_addresses)) {
@ -50,10 +72,11 @@ final class SiteHelper
self::$Private_IPs_allowed[] = $IP_addresses;
}
}
public static function setAllowedPublicIPs(string|array $IP_addresses): void {
public static function setAllowedPublicIPs(string|array $IP_addresses): void
{
if (is_array($IP_addresses)) {
foreach($IP_addresses as $IP) {
foreach ($IP_addresses as $IP) {
$s_ip = Security::getValidPublicIp($IP);
if ($s_ip === false) {
continue;
@ -68,17 +91,20 @@ final class SiteHelper
self::$Public_IPs_allowed[] = $IP_addresses;
}
}
public static function isServerName_A_PrivateDomain(): bool {
public static function isServerName_A_PrivateDomain(): bool
{
$white_list = array_merge(self::$local_site_domains, self::$Private_IPs_allowed);
return (Security::isServerNameOnDomainList($white_list));
}
public static function remoteNotAllowedForceLive(): bool {
return (! self::is_allowed());
public static function remoteNotAllowedForceLive(): bool
{
return (!self::is_allowed());
}
public static function is_allowed(): bool {
public static function is_allowed(): bool
{
$remote_ip = Security::getClientIpAddress();
if (in_array($remote_ip, self::$Public_IPs_allowed)) {
return true;
@ -88,5 +114,4 @@ final class SiteHelper
}
return false;
}
}

Loading…
Cancel
Save