From 6a5e44a04c5b0a0f19b42eabdb6fbf7edb384ff2 Mon Sep 17 00:00:00 2001 From: Fernando Ontiveros Date: Fri, 25 Apr 2025 16:20:18 +0000 Subject: [PATCH] improvements streamCSSBigFile --- gulliver/system/class.bootstrap.php | 132 +++++++++++++--------------- workflow/public_html/sysGeneric.php | 14 +-- 2 files changed, 72 insertions(+), 74 deletions(-) diff --git a/gulliver/system/class.bootstrap.php b/gulliver/system/class.bootstrap.php index debb4fbea..d8688619b 100644 --- a/gulliver/system/class.bootstrap.php +++ b/gulliver/system/class.bootstrap.php @@ -27,8 +27,8 @@ class Bootstrap self::$startingTime = microtime(true); // Determine session lifetime - $sessionLifetime = isset($config['session.gc_maxlifetime']) - ? $config['session.gc_maxlifetime'] + $sessionLifetime = isset($config['session.gc_maxlifetime']) + ? $config['session.gc_maxlifetime'] : ini_get('session.gc_maxlifetime'); // Default to 1440 seconds (24 minutes) if lifetime is not set @@ -64,13 +64,13 @@ class Bootstrap $isSafari = preg_match("/safari/i", $userAgent) && !preg_match("/chrome/i", $userAgent); // Set cookie lifetime based on browser and configuration - if (($isIE && $config['ie_cookie_lifetime'] != 1) || + if (($isIE && $config['ie_cookie_lifetime'] != 1) || ($isSafari && $config['safari_cookie_lifetime'] != 1)) { return; // Do not set cookie lifetime if conditions are not met } ini_set('session.cookie_lifetime', $sessionLifetime); - } + } /** * @deprecated 3.2.2, We keep this function only for backwards compatibility because is used in the plugin manager @@ -302,7 +302,7 @@ class Bootstrap //if (DEBUG_TIME_LOG) { // to do: remove comment self::logTimeByPage(); - //} + //} $browserCacheFilesUid = G::browserCacheFilesGetUid(); @@ -408,19 +408,20 @@ class Bootstrap } /** - * Parsing the URI + * Parses the given URI and sets system constants based on the parsed values. * - * @author Fernando Ontiveros Lira - * @access public - * @param string $urlLink - * @param array $arrayFriendlyUri + * @param string $uri The URI to parse. + * @param array $arrayFriendlyUri An optional array for friendly URIs. * * @return string */ - public static function parseURI($uri, array $arrayFriendlyUri = null) + public static function parseURI($uri, array $arrayFriendlyUri = []) { - $aRequestUri = explode('/', $uri); - $args = self::parseNormalUri($aRequestUri, $arrayFriendlyUri); + // Split the URI into segments + $requestUriSegments = explode('/', $uri); + + // Parse the URI segments into + $args = self::parseNormalUri($requestUriSegments, $arrayFriendlyUri); if (! empty($args)) { define("SYS_LANG", $args ['SYS_LANG']); @@ -428,7 +429,7 @@ class Bootstrap define('SYS_COLLECTION', $args ['SYS_COLLECTION']); define('SYS_TARGET', $args ['SYS_TARGET']); - if (array_key_exists('API_VERSION', $args)) { + if (isset($args['API_VERSION'])) { define('API_VERSION', $args['API_VERSION']); } } @@ -853,34 +854,34 @@ class Bootstrap } /** - * Dynamically generates and streams a CSS file by aggregating smaller CSS files. - * - * This function is designed to serve CSS content dynamically based on different skins or themes. - * It reads configuration files to determine which CSS files to include, handles caching headers, - * and performs browser-specific logic to ensure compatibility. + * streaming a big JS file with small js files * * @author Fernando Ontiveros Lira * @access public - * @param string $filename The name of the file, used to determine the skin and variant. - * @return string The aggregated and minified CSS content. + * @param string $file + * @return string */ public static function streamCSSBigFile($filename) { - // Set the content type to CSS and prevent MIME type sniffing header('Content-Type: text/css'); header('X-Content-Type-Options: nosniff'); - // Parse the filename to extract skin name and variant + //First get Skin info $filenameParts = explode("-", $filename); - $skinName = !empty($filenameParts[0]) ? $filenameParts[0] : 'base'; - $skinVariant = isset($filenameParts[1]) ? strtolower($filenameParts[1]) : 'skin'; + $skinName = empty($filenameParts[0]) ? 'base' : $filenameParts[0]; + $skinVariant = "skin"; - // Normalize skin names - if (in_array($skinName, ['jscolors', 'xmlcolors'])) { - $skinName = 'classic'; + if (isset($filenameParts[1])) { + $skinVariant = strtolower($filenameParts[1]); } - // Determine the configuration file path based on the skin name + $configurationFile = ''; + if ($skinName == "jscolors") { + $skinName = "classic"; + } + if ($skinName == "xmlcolors") { + $skinName = "classic"; + } if ($skinName == "classic") { $configurationFile = Bootstrap::ExpandPath("skinEngine") . 'base' . PATH_SEP . 'config.xml'; } else { @@ -894,49 +895,50 @@ class Bootstrap $configurationFile = Bootstrap::ExpandPath("skinEngine") . $skinName . PATH_SEP . 'config.xml'; } } - // Fallback to base configuration if the specific one doesn't exist if (!file_exists($configurationFile)) { $configurationFile = Bootstrap::ExpandPath("skinEngine") . 'base' . PATH_SEP . 'config.xml'; - } - - // Set caching headers - $mtime = time(); - $gmt_mtime = gmdate("D, d M Y H:i:s", $mtime) . " GMT"; - $etag = '"' . Bootstrap::encryptOld($mtime . $filename) . '"'; - $expires = gmdate("D, d M Y H:i:s", $mtime + 30 * 24 * 60 * 60) . " GMT"; // 1 month - - header('Pragma: cache'); - header('ETag: ' . $etag); - header('Last-Modified: ' . $gmt_mtime); - header('Cache-Control: public'); - header('Expires: ' . $expires); - - // Handle conditional requests for caching - $ifModifiedSince = $_SERVER['HTTP_IF_MODIFIED_SINCE'] ?? null; - $ifNoneMatch = $_SERVER['HTTP_IF_NONE_MATCH'] ?? null; - - if (($ifModifiedSince && $ifModifiedSince === $gmt_mtime) || - ($ifNoneMatch && str_replace('"', '', stripslashes($ifNoneMatch)) === Bootstrap::encryptOld($mtime . $filename))) { - header('HTTP/1.1 304 Not Modified'); - exit(); } - // Read and parse the configuration XML file + $mtime = date('U'); + $gmt_mtime = gmdate("D, d M Y H:i:s", $mtime) . " GMT"; + header('Pragma: cache'); + header('ETag: "' . Bootstrap::encryptOld($mtime . $filename) . '"'); + header("Last-Modified: " . $gmt_mtime); + header('Cache-Control: public'); + header("Expires: " . gmdate("D, d M Y H:i:s", time() + 30 * 60 * 60 * 24) . " GMT"); //1 month + //header("Expires: " . gmdate("D, d M Y H:i:s", time () + 60*60*24 ) . " GMT"); //1 day - tempor + if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) { + if ($_SERVER['HTTP_IF_MODIFIED_SINCE'] == $gmt_mtime) { + header('HTTP/1.1 304 Not Modified'); + exit(); + } + } + + if (isset($_SERVER['HTTP_IF_NONE_MATCH'])) { + if (str_replace('"', '', stripslashes($_SERVER['HTTP_IF_NONE_MATCH'])) == Bootstrap::encryptOld($mtime . $filename)) { + header("HTTP/1.1 304 Not Modified"); + exit(); + } + } + + //Read Configuration File $xmlConfiguration = file_get_contents($configurationFile); $xmlConfigurationObj = Bootstrap::xmlParser($xmlConfiguration); $baseSkinDirectory = dirname($configurationFile); $directorySize = Bootstrap::getDirectorySize($baseSkinDirectory); $mtime = $directorySize['maxmtime']; - // Prepare the CSS output with a header comment - $outputHeader = "/* Autogenerated CSS file by gulliver framework ** \n"; + //if userAgent (BROWSER) is MSIE we need special headers to avoid MSIE behaivor. + //$userAgent = strtolower($_SERVER['HTTP_USER_AGENT']); + + $outputHeader = "/* Autogenerated CSS file by gulliver framework \n"; $outputHeader .= " Skin: $filename\n"; $mtimeNow = date('U'); $gmt_mtimeNow = gmdate("D, d M Y H:i:s", $mtimeNow) . " GMT"; $outputHeader .= " Date: $gmt_mtimeNow*/\n"; $output = ""; - // Include base CSS files based on the skin variant + //Base files switch (strtolower($skinVariant)) { case "extjs": //Base @@ -951,7 +953,7 @@ class Bootstrap break; } - // Get browser information for compatibility checks + //Get Browser Info $infoBrowser = Bootstrap::get_current_browser(); $browserName = $infoBrowser['browser_working']; if (isset($infoBrowser[$browserName . '_data'])) { @@ -960,7 +962,7 @@ class Bootstrap } } - // Parse the configuration to get the list of CSS files to include + //Read Configuration File $xmlConfiguration = file_get_contents($configurationFile); $xmlConfigurationObj = Bootstrap::xmlParser($xmlConfiguration); @@ -971,8 +973,6 @@ class Bootstrap if (isset($skinFilesArray['__ATTRIBUTES__'])) { $skinFilesArray = array($skinFilesArray); } - - // Iterate over each CSS file and include it if compatible with the current browser foreach ($skinFilesArray as $keyFile => $cssFileInfo) { $enabledBrowsers = explode(",", $cssFileInfo['__ATTRIBUTES__']['enabledBrowsers']); $disabledBrowsers = explode(",", $cssFileInfo['__ATTRIBUTES__']['disabledBrowsers']); @@ -1000,14 +1000,8 @@ class Bootstrap } } - // Minify the CSS by removing comments and unnecessary whitespace - $regex = array( - "`^([\t\s]+)`ism" => '', - "`^\/\*(.+?)\*\/`ism" => "", - "`([\n;]+)\/\*(.+?)\*\/`ism" => "$1", - "`([\n;\s]+)//(.+?)[\n\r]`ism" => "$1\n", - "`(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+`ism" => "\n" - ); + //Remove comments.. + $regex = array("`^([\t\s]+)`ism" => '', "`^\/\*(.+?)\*\/`ism" => "", "`([\n;]+)\/\*(.+?)\*\/`ism" => "$1", "`([\n;\s]+)//(.+?)[\n\r]`ism" => "$1\n", "`(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+`ism" => "\n"); $output = preg_replace(array_keys($regex), $regex, $output); $output = $outputHeader . $output; @@ -2731,7 +2725,7 @@ class Bootstrap /** * Returns an array containing the values of the current execution context. - * + * * @global object $RBAC * @param array $extraParams * @return array diff --git a/workflow/public_html/sysGeneric.php b/workflow/public_html/sysGeneric.php index b82abe0ea..6dccb81cc 100644 --- a/workflow/public_html/sysGeneric.php +++ b/workflow/public_html/sysGeneric.php @@ -181,7 +181,7 @@ $_SERVER['SERVER_ADDR'] = isset($_SERVER['SERVER_ADDR']) ? $_SERVER['SERVER_ADDR //to do: make different environments. sys -//check if it is a installation instance +//check if it is a installation instance if (!defined('PATH_C')) { // to do: review // is a intallation instance, so we need to define PATH_C and PATH_LANGUAGECONT constants temporarily define('PATH_C', (rtrim(Bootstrap::sys_get_temp_dir(), PATH_SEP) . PATH_SEP)); @@ -380,16 +380,20 @@ if (!defined('PATH_DB') || !file_exists(PATH_DB)) { app()->useStoragePath(realpath(PATH_DATA)); app()->make(Kernel::class)->bootstrap(); + restore_error_handler(); //Overwrite with the Processmaker env.ini configuration used in production environments //@todo: move env.ini configuration to .env -ini_set('display_errors', $config['display_errors']); -ini_set('error_reporting', $config['error_reporting']); +//ini_set('display_errors', $config['display_errors']); +//ini_set('error_reporting', $config['error_reporting']); +ini_set('display_errors', true); +ini_set('error_reporting', true); ini_set('short_open_tag', 'On'); ini_set('default_charset', "UTF-8"); ini_set('soap.wsdl_cache_enabled', $config['wsdl_cache']); ini_set('date.timezone', TIME_ZONE); //Set Time Zone + date_default_timezone_set(TIME_ZONE); config(['app.timezone' => TIME_ZONE]); @@ -745,7 +749,7 @@ if (!defined('EXECUTE_BY_CRON')) { // Default to 1440 seconds (24 minutes) if lifetime is not set if (is_null($sessionLifetime)) { $sessionLifetime = 1440; - } + } $cookieOptions = Bootstrap::buildCookieOptions(['expires' => time() + $sessionLifetime, 'httponly' => true]); setcookie(session_name(), session_id(), $cookieOptions); } @@ -795,7 +799,7 @@ if (!defined('EXECUTE_BY_CRON')) { $noLoginFolders[] = 'services'; $noLoginFolders[] = 'tracker'; $noLoginFolders[] = 'InstallerModule'; - + $data = new stdClass(); $data->noLoginFiles = &$noLoginFiles; $data->noLoginFolders = &$noLoginFolders;