mikuli.cz

:)
git clone https://git.sr.ht/~ashymad/mikuli.cz
Log | Files | Refs

commit b8d7052a277aeb0d1a9f8b07090baa2c02c256b5
parent 9f60667bb10ae5e9329024b6127f3bd2c148b6ee
Author: markseu <mark2011@mayberg.se>
Date:   Fri, 29 Nov 2013 13:16:14 +0100

Better status handling

Diffstat:
Msystem/core/core.php | 476++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
Msystem/core/core_commandline.php | 33++++++++++++++++++---------------
2 files changed, 281 insertions(+), 228 deletions(-)

diff --git a/system/core/core.php b/system/core/core.php @@ -5,20 +5,20 @@ // Yellow main class class Yellow { - const Version = "0.1.21"; + const Version = "0.1.22"; var $page; //current page data var $pages; //current page tree from file system - var $toolbox; //toolbox with helpers var $config; //configuration var $text; //text strings + var $toolbox; //toolbox with helpers var $plugins; //plugins function __construct() { $this->pages = new Yellow_Pages($this); + $this->config = new Yellow_Config($this); + $this->text = new Yellow_Text($this); $this->toolbox = new Yellow_Toolbox(); - $this->config = new Yellow_Config(); - $this->text = new Yellow_Text(); $this->plugins = new Yellow_Plugins(); $this->config->setDefault("sitename", "Yellow"); $this->config->setDefault("author", "Yellow"); @@ -48,7 +48,7 @@ class Yellow $this->config->setDefault("errorPageFile", "error(.*).txt"); $this->config->setDefault("textStringFile", "text_(.*).ini"); $this->config->load($this->config->get("configDir").$this->config->get("configFile")); - $this->text->load($this->config->get("configDir").$this->config->get("textStringFile"), $this->toolbox); + $this->text->load($this->config->get("configDir").$this->config->get("textStringFile")); } // Handle request @@ -101,14 +101,6 @@ class Yellow { $statusCode = 200; $fileName = $this->readPage($serverBase, $location, $fileName, $cacheable, $statusCode); - if($this->page->isExisting("redirect") && $handler=="core") - { - $statusCode = 301; - $locationHeader = $this->toolbox->getHttpLocationHeader($serverName, $serverBase, $this->page->get("redirect")); - $this->page->statusCode = 0; - $this->header($locationHeader); - $this->sendStatus($statusCode, $locationHeader); - } } else { $statusCode = 303; $locationArgs = $this->toolbox->getLocationArgsCleanUrl(); @@ -186,16 +178,26 @@ class Yellow } $statusCode = $this->page->statusCode; + if($statusCode==200 && $this->getRequestHandler()=="core" && $this->page->isExisting("redirect")) + { + $statusCode = 301; + $location = $this->page->get("redirect"); + if(preg_match("/^[^\/]+$/", $location)) $location = $this->toolbox->getDirectoryLocation($this->page->getLocation()).$location; + $this->page->clean($statusCode, $this->toolbox->getHttpLocationHeader($this->config->get("serverName"), "", $location)); + $this->page->setHeader("Last-Modified", $this->page->getModified(true)); + $this->page->setHeader("Cache-Control", "no-cache, must-revalidate"); + } if($statusCode==200 && $this->page->isCacheable() && $this->toolbox->isFileNotModified($this->page->getHeader("Last-Modified"))) { - ob_clean(); $statusCode = 304; + $this->page->clean($statusCode); } + if($this->page->isExisting("pageClean")) ob_clean(); if(PHP_SAPI != "cli") { @header($this->toolbox->getHttpStatusFormatted($statusCode)); - if($statusCode != 304) foreach($this->page->headerData as $key=>$value) @header("$key: $value"); + foreach($this->page->headerData as $key=>$value) @header("$key: $value"); } if(defined("DEBUG") && DEBUG>=1) { @@ -206,12 +208,12 @@ class Yellow } // Send status response - function sendStatus($statusCode, $text = "") + function sendStatus($statusCode, $responseHeader = "") { if(PHP_SAPI != "cli") { @header($this->toolbox->getHttpStatusFormatted($statusCode)); - if(!empty($text)) @header($text); + if(!empty($responseHeader)) @header($responseHeader); } } @@ -327,9 +329,9 @@ class Yellow } // Set a response header - function header($text) + function header($responseHeader) { - $tokens = explode(':', $text, 2); + $tokens = explode(':', $responseHeader, 2); $this->page->setHeader(trim($tokens[0]), trim($tokens[1])); } } @@ -487,10 +489,22 @@ class Yellow_Page // Respond with error page function error($statusCode, $pageError = "") { - if(!$this->isExisting("pageError")) + if(!$this->isExisting("pageError") && $statusCode>0) + { + $this->statusCode = $statusCode; + $this->set("pageError", empty($pageError) ? "Template/snippet error!" : $pageError); + } + } + + // Respond without page content + function clean($statusCode, $responseHeader = "") + { + if(!$this->isExisting("pageClean") && $statusCode>0) { $this->statusCode = $statusCode; - $this->set("pageError", empty($pageError) ? "Template/snippet error" : $pageError); + $this->headerData = array(); + if(!empty($responseHeader)) $this->yellow->header($responseHeader); + $this->set("pageClean", (string)$statusCode); } } @@ -544,6 +558,13 @@ class Yellow_Page return $this->yellow->pages->serverBase.$this->location; } + // Return full page URL, with server name + function getUrl() + { + return $this->yellow->toolbox->getHttpUrl($this->yellow->config->get("serverName"), + $this->yellow->pages->serverBase, $this->location); + } + // Return page modification time, Unix time function getModified($httpFormat = false) { @@ -799,8 +820,8 @@ class Yellow_Pages function __construct($yellow) { - $this->pages = array(); $this->yellow = $yellow; + $this->pages = array(); } // Return empty page collection @@ -948,6 +969,213 @@ class Yellow_Pages } } +// Yellow configuration +class Yellow_Config +{ + var $yellow; //access to API + var $modified; //configuration modification time + var $config; //configuration + var $configDefaults; //configuration defaults + + function __construct($yellow) + { + $this->yellow = $yellow; + $this->modified = 0; + $this->config = array(); + $this->configDefaults = array(); + } + + // Load configuration from file + function load($fileName) + { + $fileData = @file($fileName); + if($fileData) + { + if(defined("DEBUG") && DEBUG>=2) echo "Yellow_Config::load file:$fileName<br/>\n"; + $this->modified = filemtime($fileName); + foreach($fileData as $line) + { + if(preg_match("/^\//", $line)) continue; + preg_match("/^\s*(.*?)\s*=\s*(.*?)\s*$/", $line, $matches); + if(!empty($matches[1]) && !strempty($matches[2])) + { + $this->set($matches[1], $matches[2]); + if(defined("DEBUG") && DEBUG>=3) echo "Yellow_Config::load key:$matches[1] $matches[2]<br/>\n"; + } + } + } + } + + // Set default configuration + function setDefault($key, $value) + { + $this->configDefaults[$key] = $value; + } + + // Set configuration + function set($key, $value) + { + $this->config[$key] = $value; + } + + // Return configuration + function get($key) + { + return $this->isExisting($key) ? $this->config[$key] : $this->configDefaults[$key]; + } + + // Return configuration, HTML encoded + function getHtml($key) + { + return htmlspecialchars($this->get($key)); + } + + // Return configuration strings + function getData($filterEnd = "") + { + $config = array(); + if(empty($filterEnd)) + { + $config = $this->config; + } else { + foreach($this->config as $key=>$value) + { + if(substru($key, -strlenu($filterEnd)) == $filterEnd) $config[$key] = $value; + } + } + return $config; + } + + // Return configuration modification time, Unix time + function getModified($httpFormat = false) + { + return $httpFormat ? $this->yellow->toolbox->getHttpTimeFormatted($this->modified) : $this->modified; + } + + // Check if configuration exists + function isExisting($key) + { + return !is_null($this->config[$key]); + } +} + +// Yellow text strings +class Yellow_Text +{ + var $yellow; //access to API + var $modified; //text modification time + var $text; //text strings + var $language; //current language + + function __construct($yellow) + { + $this->yellow = $yellow; + $this->modified = 0; + $this->text = array(); + } + + // Load text strings from file + function load($fileName) + { + $path = dirname($fileName); + $regex = "/".basename($fileName)."/"; + foreach($this->yellow->toolbox->getDirectoryEntries($path, $regex, true, false) as $entry) + { + $fileData = @file("$path/$entry"); + if($fileData) + { + if(defined("DEBUG") && DEBUG>=2) echo "Yellow_Text::load file:$path/$entry<br/>\n"; + $this->modified = max($this->modified, filemtime("$path/$entry")); + $language = ""; + foreach($fileData as $line) + { + preg_match("/^\s*(.*?)\s*=\s*(.*?)\s*$/", $line, $matches); + if($matches[1]=="language" && !empty($matches[2])) { $language = $matches[2]; break; } + } + foreach($fileData as $line) + { + if(preg_match("/^\//", $line)) continue; + preg_match("/^\s*(.*?)\s*=\s*(.*?)\s*$/", $line, $matches); + if(!empty($language) && !empty($matches[1]) && !strempty($matches[2])) + { + $this->setLanguageText($language, $matches[1], $matches[2]); + if(defined("DEBUG") && DEBUG>=3) echo "Yellow_Text::load key:$matches[1] $matches[2]<br/>\n"; + } + } + } + } + } + + // Set current language + function setLanguage($language) + { + $this->language = $language; + } + + // Set text string for specific language + function setLanguageText($language, $key, $value) + { + if(is_null($this->text[$language])) $this->text[$language] = array(); + $this->text[$language][$key] = $value; + } + + // Return text string for specific language + function getLanguageText($language, $key) + { + return ($this->isLanguageText($language, $key)) ? $this->text[$language][$key] : "[$key]"; + } + + // Return text string + function get($key) + { + return $this->isExisting($key) ? $this->text[$this->language][$key] : "[$key]"; + } + + // Return text string, HTML encoded + function getHtml($key) + { + return htmlspecialchars($this->get($key)); + } + + // Return text strings for specific language + function getData($language, $filterStart = "") + { + $text = array(); + if(!is_null($this->text[$language])) + { + if(empty($filterStart)) + { + $text = $this->text[$language]; + } else { + foreach($this->text[$language] as $key=>$value) + { + if(substru($key, 0, strlenu("language")) == "language") $text[$key] = $value; + if(substru($key, 0, strlenu($filterStart)) == $filterStart) $text[$key] = $value; + } + } + } + return $text; + } + + // Return text modification time, Unix time + function getModified($httpFormat = false) + { + return $httpFormat ? $this->yellow->toolbox->getHttpTimeFormatted($this->modified) : $this->modified; + } + + // Check if text string for specific language exists + function isLanguageText($language, $key) + { + return !is_null($this->text[$language]) && !is_null($this->text[$language][$key]); + } + + // Check if text string exists + function isExisting($key) + { + return !is_null($this->text[$this->language]) && !is_null($this->text[$this->language][$key]); + } +} + // Yellow toolbox with helpers class Yellow_Toolbox { @@ -1182,6 +1410,7 @@ class Yellow_Toolbox case 304: $text = "$_SERVER[SERVER_PROTOCOL] $statusCode Not modified"; break; case 401: $text = "$_SERVER[SERVER_PROTOCOL] $statusCode Unauthorised"; break; case 404: $text = "$_SERVER[SERVER_PROTOCOL] $statusCode Not found"; break; + case 409: $text = "$_SERVER[SERVER_PROTOCOL] $statusCode Conflict"; break; case 424: $text = "$_SERVER[SERVER_PROTOCOL] $statusCode Does not exist"; break; case 500: $text = "$_SERVER[SERVER_PROTOCOL] $statusCode Server error"; break; default: $text = "$_SERVER[SERVER_PROTOCOL] $statusCode Unknown status"; @@ -1195,16 +1424,22 @@ class Yellow_Toolbox return gmdate("D, d M Y H:i:s", $timestamp)." GMT"; } - // Return HTTP location header - function getHttpLocationHeader($serverName, $serverBase, $location) + // Return HTTP URL + function getHttpUrl($serverName, $serverBase, $location) { if(preg_match("/^(http|https):\/\//", $location)) { - $locationHeader = "Location: $location"; + $url = $location; } else { - $locationHeader = "Location: http://$serverName$serverBase$location"; + $url = "http://$serverName$serverBase$location"; } - return $locationHeader; + return $url; + } + + // Return HTTP location header + function getHttpLocationHeader($serverName, $serverBase, $location) + { + return "Location: ".self::getHttpUrl($serverName, $serverBase, $location); } // Return directory location @@ -1308,7 +1543,7 @@ class Yellow_Toolbox if(preg_match("/^(blockquote|br|div|h\d|hr|li|ol|p|pre|ul)/i", $elementName)) $string .= ' '; if(preg_match("/^\/(code|pre)/i", $elementName)) $string = preg_replace("/^(\d+\n){2,}$/", "", $string); $string = preg_replace("/\s+/s", " ", $string); - if(substru($string, 0 , 1)==" " && (empty($output) || substru($output, -1)==' ')) $string = substru($string, 1); + if(substru($string, 0, 1)==" " && (empty($output) || substru($output, -1)==' ')) $string = substru($string, 1); $length = strlenu($string); $output .= substru($string, 0, $length < $lengthMax ? $length : $lengthMax-1); $lengthMax -= $length; @@ -1433,191 +1668,6 @@ class Yellow_Toolbox } } -// Yellow configuration -class Yellow_Config -{ - var $config; //configuration - var $configDefaults; //configuration defaults - - function __construct() - { - $this->config = array(); - $this->configDefaults = array(); - } - - // Load configuration from file - function load($fileName) - { - $fileData = @file($fileName); - if($fileData) - { - if(defined("DEBUG") && DEBUG>=2) echo "Yellow_Config::load file:$fileName<br/>\n"; - foreach($fileData as $line) - { - if(preg_match("/^\//", $line)) continue; - preg_match("/^\s*(.*?)\s*=\s*(.*?)\s*$/", $line, $matches); - if(!empty($matches[1]) && !strempty($matches[2])) - { - $this->set($matches[1], $matches[2]); - if(defined("DEBUG") && DEBUG>=3) echo "Yellow_Config::load key:$matches[1] $matches[2]<br/>\n"; - } - } - } - } - - // Set default configuration - function setDefault($key, $value) - { - $this->configDefaults[$key] = $value; - } - - // Set configuration - function set($key, $value) - { - $this->config[$key] = $value; - } - - // Return configuration - function get($key) - { - return $this->isExisting($key) ? $this->config[$key] : $this->configDefaults[$key]; - } - - // Return configuration, HTML encoded - function getHtml($key) - { - return htmlspecialchars($this->get($key)); - } - - // Return configuration strings - function getData($filterEnd = "") - { - $config = array(); - if(empty($filterEnd)) - { - $config = $this->config; - } else { - foreach($this->config as $key=>$value) - { - if(substru($key, -strlenu($filterEnd)) == $filterEnd) $config[$key] = $value; - } - } - return $config; - } - - // Check if configuration exists - function isExisting($key) - { - return !is_null($this->config[$key]); - } -} - -// Yellow text strings -class Yellow_Text -{ - var $text; //text strings - var $language; //current language - - function __construct() - { - $this->text = array(); - } - - // Load text strings from file - function load($fileName, $toolbox) - { - $path = dirname($fileName); - $regex = "/".basename($fileName)."/"; - foreach($toolbox->getDirectoryEntries($path, $regex, true, false) as $entry) - { - $fileData = @file("$path/$entry"); - if($fileData) - { - if(defined("DEBUG") && DEBUG>=2) echo "Yellow_Text::load file:$path/$entry<br/>\n"; - $language = ""; - foreach($fileData as $line) - { - preg_match("/^\s*(.*?)\s*=\s*(.*?)\s*$/", $line, $matches); - if($matches[1]=="language" && !empty($matches[2])) { $language = $matches[2]; break; } - } - foreach($fileData as $line) - { - if(preg_match("/^\//", $line)) continue; - preg_match("/^\s*(.*?)\s*=\s*(.*?)\s*$/", $line, $matches); - if(!empty($language) && !empty($matches[1]) && !strempty($matches[2])) - { - $this->setLanguageText($language, $matches[1], $matches[2]); - if(defined("DEBUG") && DEBUG>=3) echo "Yellow_Text::load key:$matches[1] $matches[2]<br/>\n"; - } - } - } - } - } - - // Set current language - function setLanguage($language) - { - $this->language = $language; - } - - // Set text string for specific language - function setLanguageText($language, $key, $value) - { - if(is_null($this->text[$language])) $this->text[$language] = array(); - $this->text[$language][$key] = $value; - } - - // Return text string for specific language - function getLanguageText($language, $key) - { - return ($this->isLanguageText($language, $key)) ? $this->text[$language][$key] : "[$key]"; - } - - // Return text string - function get($key) - { - return $this->isExisting($key) ? $this->text[$this->language][$key] : "[$key]"; - } - - // Return text string, HTML encoded - function getHtml($key) - { - return htmlspecialchars($this->get($key)); - } - - // Return text strings for specific language - function getData($language, $filterStart = "") - { - $text = array(); - if(!is_null($this->text[$language])) - { - if(empty($filterStart)) - { - $text = $this->text[$language]; - } else { - foreach($this->text[$language] as $key=>$value) - { - if(substru($key, 0, strlenu("language")) == "language") $text[$key] = $value; - if(substru($key, 0, strlenu($filterStart)) == $filterStart) $text[$key] = $value; - } - } - } - return $text; - } - - // Check if text string for specific language exists - function isLanguageText($language, $key) - { - return !is_null($this->text[$language]) && !is_null($this->text[$language][$key]); - } - - // Check if text string exists - function isExisting($key) - { - return !is_null($this->text[$this->language]) && !is_null($this->text[$this->language][$key]); - } -} - // Yellow plugins class Yellow_Plugins { diff --git a/system/core/core_commandline.php b/system/core/core_commandline.php @@ -5,7 +5,7 @@ // Command line core plugin class Yellow_Commandline { - const Version = "0.1.4"; + const Version = "0.1.5"; var $yellow; //access to API // Initialise plugin @@ -149,7 +149,7 @@ class Yellow_Commandline { $fileName = $this->getStaticFileName($location, $path); $fileData = ob_get_contents(); - if($statusCode == 301) $fileData = $this->getStaticRedirect($this->yellow->page->getHeader("Location")); + if($statusCode>=301 && $statusCode<=303) $fileData = $this->getStaticRedirect($this->yellow->page->getHeader("Location")); $fileOk = $this->makeStaticFile($fileName, $fileData, $modified); } else { if(!$this->yellow->toolbox->isFileLocation($location)) @@ -164,8 +164,8 @@ class Yellow_Commandline $fileOk = $this->makeStaticFile($fileName, $fileData, $modified); } } else { - $statusCode = 500; - $this->yellow->page->error($statusCode, "Invalid file name for type '$contentType'!"); + $statusCode = 409; + $this->yellow->page->error($statusCode, "Type '$contentType' does not match file name!"); } } if(!$fileOk) @@ -217,20 +217,23 @@ class Yellow_Commandline // Return static location corresponding to content type function getStaticLocation($location, $contentType) { - $extension = ($pos = strrposu($location, '.')) ? substru($location, $pos) : ""; - if($contentType == "text/html") + if(!empty($contentType)) { - if($this->yellow->toolbox->isFileLocation($location)) + $extension = ($pos = strrposu($location, '.')) ? substru($location, $pos) : ""; + if($contentType == "text/html") { - if(!empty($extension) && $extension!=".html") $location .= ".html"; - } - } else { - if($this->yellow->toolbox->isFileLocation($location)) - { - if(empty($extension)) $location .= ".unknown"; + if($this->yellow->toolbox->isFileLocation($location)) + { + if(!empty($extension) && $extension!=".html") $location .= ".html"; + } } else { - if(preg_match("/^(\w+)\/(\w+)/", $contentType, $matches)) $extension = ".$matches[2]"; - $location .= "index$extension"; + if($this->yellow->toolbox->isFileLocation($location)) + { + if(empty($extension)) $location .= ".unknown"; + } else { + if(preg_match("/^(\w+)\/(\w+)/", $contentType, $matches)) $extension = ".$matches[2]"; + $location .= "index$extension"; + } } } return $location;