diff --git a/README.md b/README.md index e42b035..b5fd3f5 100644 --- a/README.md +++ b/README.md @@ -15,9 +15,10 @@ With Yellow you don't get a lot of extra stuff, there are [Yellow extensions on How to make a website? ---------------------- You already have everything you need, start by editing the default pages. -For more information please see [Yellow documentation](https://github.com/markseu/yellowcms-extensions/tree/master/documentation). +For more information please see [Yellow documentation](https://github.com/markseu/yellowcms-extensions/blob/master/documentation/README.md). Need help? Have a question? ---------------------------- +--------------------------- +Looking for something, then get in touch with others. Visit [Yellow on Reddit](http://www.reddit.com/r/yellowcms/), follow [Yellow on Twitter](https://twitter.com/yellowcms). \ No newline at end of file diff --git a/content/1-home/page.txt b/content/1-home/page.txt index 5660af1..a80e38f 100755 --- a/content/1-home/page.txt +++ b/content/1-home/page.txt @@ -2,7 +2,7 @@ Title: Home --- Yes, your Yellow installation works! -You can now [edit this page](@baselocation/wiki/) or use your favorite text editor. -See [Yellow documentation](https://github.com/markseu/yellowcms-extensions/tree/master/documentation) for more. +You can now [edit this page](@baselocation/edit/) or use your favorite text editor. +Information for web designers are in the [documentation](https://github.com/markseu/yellowcms-extensions/blob/master/documentation/README.md). Have fun making your website. \ No newline at end of file diff --git a/system/core/core.php b/system/core/core.php index a043ddb..9383222 100755 --- a/system/core/core.php +++ b/system/core/core.php @@ -5,7 +5,7 @@ // Yellow main class class Yellow { - const Version = "0.1.4"; + const Version = "0.1.5"; var $page; //current page data var $pages; //current page tree from file system var $toolbox; //toolbox with helpers @@ -62,6 +62,7 @@ class Yellow // Process request function processRequest() { + ob_start(); $statusCode = 0; $baseLocation = $this->config->get("baseLocation"); $location = $this->getRelativeLocation($baseLocation); @@ -76,8 +77,9 @@ class Yellow } if($statusCode == 0) $statusCode = $this->processRequestFile($baseLocation, $location, $fileName, $statusCode); if(defined("DEBUG") && DEBUG>=1) echo "Yellow::processRequest status:$statusCode location:$location
\n"; + ob_end_flush(); } - + // Process request for a file function processRequestFile($baseLocation, $location, $fileName, $statusCode, $cache = true) { @@ -85,91 +87,104 @@ class Yellow { if(is_readable($fileName)) { - $time = gmdate("D, d M Y H:i:s", filemtime($fileName))." GMT"; - if(isset($_SERVER["HTTP_IF_MODIFIED_SINCE"]) && $_SERVER["HTTP_IF_MODIFIED_SINCE"]==$time && $cache) - { - $statusCode = 304; - $this->sendStatus($statusCode); - } else { - $statusCode = 200; - header("Content-Type: text/html; charset=UTF-8"); - if($cache) - { - header("Last-Modified: ".$time); - } else { - header("Cache-Control: no-cache"); - header("Pragma: no-cache"); - header("Expires: 0"); - } - $fileHandle = @fopen($fileName, "r"); - if($fileHandle) - { - $fileData = fread($fileHandle, filesize($fileName)); - fclose($fileHandle); - } else { - die("Server problem: Can't read file '$fileName'!"); - } - } + $statusCode = 200; + $fileName = $this->readPage($baseLocation, $location, $fileName, $statusCode); } else { if($this->toolbox->isFileLocation($location) && is_dir($this->getContentDirectory("$location/"))) { $statusCode = 301; - $serverName = $this->config->get("serverName"); - $this->sendStatus($statusCode, "Location: http://$serverName$baseLocation$location/"); + $this->sendStatus($statusCode, "Location: http://".$this->config->get("serverName")."$baseLocation$location/"); } else { $statusCode = 404; + $fileName = $this->readPage($baseLocation, $location, $fileName, $statusCode); } } + } else if($statusCode >= 400) { + $fileName = $this->readPage($baseLocation, $location, $fileName, $statusCode); } - if($statusCode >= 400) + if(is_object($this->page)) { - header($this->toolbox->getHttpStatusFormated($statusCode)); - header("Content-Type: text/html; charset=UTF-8"); - $fileName = strreplaceu("(.*)", $statusCode, $this->config->get("configDir").$this->config->get("errorPageFile")); - $fileHandle = @fopen($fileName, "r"); - if($fileHandle) + $statusCode = $this->sendPage($statusCode, $cache); + } + if(defined("DEBUG") && DEBUG>=1) echo "Yellow::processRequestFile base:$baseLocation file:$fileName
\n"; + return $statusCode; + } + + // Read page + function readPage($baseLocation, $location, $fileName, $statusCode) + { + if($statusCode >= 400) $fileName = strreplaceu("(.*)", $statusCode, $this->config->get("configDir").$this->config->get("errorPageFile")); + $fileHandle = @fopen($fileName, "r"); + if($fileHandle) + { + $fileData = fread($fileHandle, filesize($fileName)); + fclose($fileHandle); + } else { + die("Server problem: Can't read file '$fileName'!"); + } + $this->pages = new Yellow_Pages($baseLocation, $this->toolbox, $this->config, $this->plugins); + $this->page = new Yellow_Page($baseLocation, $location, $fileName, $fileData, $this->pages, true); + $this->text->setLanguage($this->page->get("language")); + return $fileName; + } + + // Send page response + function sendPage($statusCode, $cache) + { + $fileNameStyle = $this->config->get("styleDir").$this->page->get("style").".css"; + if(!is_file($fileNameStyle)) die("Style '".$this->page->get("style")."' does not exist!"); + $fileNameTemplate = $this->config->get("templateDir").$this->page->get("template").".php"; + if(!is_file($fileNameTemplate)) die("Template '".$this->page->get("template")."' does not exist!"); + global $yellow; + require($fileNameTemplate); + + $pageHeaders["last-modified"] = $this->page->getModified(true); + $pageHeaders["content-type"] = "text/html; charset=UTF-8"; + foreach(headers_list() as $header) + { + $tokens = explode(':', $header, 2); + $key = strtoloweru($tokens[0]); + if(!is_null($pageHeaders[$key])) { - $fileData = fread($fileHandle, filesize($fileName)); - fclose($fileHandle); - } else { - die("Configuration problem: Can't open file '$fileName'!"); + $pageHeaders[$key] = trim($tokens[1]); + header_remove($tokens[0]); } } - if(!empty($fileData)) $this->sendPage($baseLocation, $location, $fileName, $fileData, $statusCode); - if(defined("DEBUG") && DEBUG>=1) echo "Yellow::processRequestFile base:$baseLocation file:$fileName
\n"; + if($statusCode==200 && $cache && isset($_SERVER["HTTP_IF_MODIFIED_SINCE"]) && + $_SERVER["HTTP_IF_MODIFIED_SINCE"]==$pageHeaders["last-modified"]) + { + $statusCode = 304; + $this->sendStatus($statusCode); + } else { + header("Content-Type: ".$pageHeaders["content-type"]); + if($cache) + { + header("Last-Modified:". $pageHeaders["last-modified"]); + } else { + header("Cache-Control: no-cache"); + header("Pragma: no-cache"); + header("Expires: 0"); + } + } + if(defined("DEBUG") && DEBUG>=1) echo "Yellow::sendFile template:$fileNameTemplate style:$fileNameStyle
\n"; return $statusCode; } // Send status response function sendStatus($statusCode, $text = "") { - header($this->toolbox->getHttpStatusFormated($statusCode)); + header($this->toolbox->getHttpStatusFormatted($statusCode)); if(!empty($text)) header($text); } - - // Send page response - function sendPage($baseLocation, $location, $fileName, $fileData, $statusCode) - { - $this->pages = new Yellow_Pages($baseLocation, $this->toolbox, $this->config, $this->plugins); - $this->page = new Yellow_Page($baseLocation, $location, $fileName, $fileData, $this->pages, true); - $this->text->setLanguage($this->page->get("language")); - - $fileName = $this->config->get("styleDir").$this->page->get("style").".css"; - if(!is_file($fileName)) die("Style '".$this->page->get("style")."' does not exist!"); - $fileName = $this->config->get("templateDir").$this->page->get("template").".php"; - if(!is_file($fileName)) die("Template '".$this->page->get("template")."' does not exist!"); - global $yellow; - require($fileName); - } // Execute a template snippet function snippet($name, $args = NULL) { $this->page->args = func_get_args(); - $fileName = $this->config->get("snippetDir")."$name.php"; - if(!is_file($fileName)) die("Snippet '$name' does not exist!"); + $fileNameSnippet = $this->config->get("snippetDir")."$name.php"; + if(!is_file($fileNameSnippet)) die("Snippet '$name' does not exist!"); global $yellow; - require($fileName); + require($fileNameSnippet); } // Return template snippet arguments @@ -211,7 +226,7 @@ class Yellow return $this->toolbox->findFileFromLocation($location, $this->config->get("contentDir"), $this->config->get("contentHomeDir"), "", ""); } - + // Execute a plugin command function plugin($name, $args = NULL) { @@ -237,13 +252,13 @@ class Yellow_Page var $fileName; //content file name var $parser; //content parser var $metaData; //meta data of page - var $rawData; //raw data of page (unparsed) - var $rawTextOffsetBytes; //raw text of page (unparsed) + var $rawData; //raw data of page + var $rawTextOffsetBytes; //raw text of page var $args; //arguments for template snippet var $pages; //access to file system - var $active; //page is active? - var $hidden; //page is hidden in navigation? - + var $active; //page is active? (boolean) + var $hidden; //page is hidden in navigation? (boolean) + function __construct($baseLocation, $location, $fileName, $rawData, $pages, $parseContent = false) { $this->baseLocation = $baseLocation; @@ -354,16 +369,18 @@ class Yellow_Page return substrb($this->rawData, $this->rawTextOffsetBytes); } - // Return absolut page location + // Return absolute page location function getLocation() { return $this->baseLocation.$this->location; } - // Return page modification time (Unix time UTC) - function getModified() + // Return page modification time, Unix time + function getModified($httpFormat = false) { - return filemtime($this->fileName); + $modified = is_readable($this->fileName) ? filemtime($this->fileName) : ""; + if($this->IsExisting("modified")) $modified = strtotime($this->get("modified")); + return $httpFormat ? $this->pages->toolbox->getHttpTimeFormatted($modified) : $modified; } // Return child pages relative to current page @@ -477,7 +494,7 @@ class Yellow_PageCollection extends ArrayObject return $this->paginationCount; } - // Return absolut location for a page in pagination + // Return absolute location for a page in pagination function getLocationPage($pageNumber) { if($pageNumber>=1 && $pageNumber<=$this->paginationCount) @@ -488,7 +505,7 @@ class Yellow_PageCollection extends ArrayObject return $location; } - // Return absolut location for previous page in pagination + // Return absolute location for previous page in pagination function getLocationPrevious() { $pageNumber = $this->paginationPage; @@ -496,13 +513,21 @@ class Yellow_PageCollection extends ArrayObject return $this->getLocationPage($pageNumber); } - // Return absolut location for next page in pagination + // Return absolute location for next page in pagination function getLocationNext() { $pageNumber = $this->paginationPage; $pageNumber = ($pageNumber>=1 && $pageNumber<$this->paginationCount) ? $pageNumber+1 : 0; return $this->getLocationPage($pageNumber); } + + // Return last modification time for page collection, Unix time + function getModified($httpFormat = false) + { + $modified = 0; + foreach($this->getIterator() as $page) $modified = max($modified, $page->getModified()); + return $httpFormat ? $this->toolbox->getHttpTimeFormatted($modified) : $modified; + } // Check if there is an active pagination function isPagination() @@ -789,7 +814,7 @@ class Yellow_Toolbox } // Return human readable HTTP server status - static function getHttpStatusFormated($statusCode) + static function getHttpStatusFormatted($statusCode) { switch($statusCode) { @@ -800,10 +825,17 @@ class Yellow_Toolbox case 401: $text = "$_SERVER[SERVER_PROTOCOL] $statusCode Unauthorised"; break; case 404: $text = "$_SERVER[SERVER_PROTOCOL] $statusCode Not found"; break; case 424: $text = "$_SERVER[SERVER_PROTOCOL] $statusCode Does not exist"; break; + case 500: $text = "$_SERVER[SERVER_PROTOCOL] $statusCode Server error"; break; default: die("Unknown HTTP status $statusCode!"); } return $text; } + + // Return human readable HTTP time + static function getHttpTimeFormatted($timestamp) + { + return gmdate("D, d M Y H:i:s", $timestamp)." GMT"; + } // Return files and directories static function getDirectoryEntries($path, $regex = "/.*/", $sort = false, $directories = true) @@ -1158,8 +1190,8 @@ class Yellow_Plugins require_once("core_webinterface.php"); foreach($yellow->toolbox->getDirectoryEntries($yellow->config->get("pluginDir"), "/.*\.php/", true, false) as $entry) { - $fileName = $yellow->config->get("pluginDir")."/$entry"; - require_once($fileName); + $fileNamePlugin = $yellow->config->get("pluginDir")."/$entry"; + require_once($fileNamePlugin); } foreach($this->plugins as $key=>$value) { diff --git a/system/core/core_webinterface.php b/system/core/core_webinterface.php index 8e8ee3e..74eb37d 100755 --- a/system/core/core_webinterface.php +++ b/system/core/core_webinterface.php @@ -5,18 +5,18 @@ // Web interface core plugin class Yellow_Webinterface { - const Version = "0.1.1"; + const Version = "0.1.2"; var $yellow; //access to API var $users; //web interface users var $activeLocation; //web interface location? (boolean) - var $activeUserFail; //web interface login failed (boolean) + var $activeUserFail; //web interface login failed? (boolean) var $activeUserEmail; //web interface user currently logged in // Initialise plugin function initPlugin($yellow) { $this->yellow = $yellow; - $this->yellow->config->setDefault("webinterfaceLocation", "/wiki/"); + $this->yellow->config->setDefault("webinterfaceLocation", "/edit/"); $this->yellow->config->setDefault("webinterfaceUserFile", "user.ini"); $this->users = new Yellow_WebinterfaceUsers(); $this->users->load($this->yellow->config->get("configDir").$this->yellow->config->get("webinterfaceUserFile")); @@ -38,7 +38,8 @@ class Yellow_Webinterface if($this->yellow->config->get("webinterfaceLocation") == "$location/") { $statusCode = 301; - $this->yellow->sendStatus($statusCode, "Location: http://$_SERVER[SERVER_NAME]$baseLocation$location/"); + $serverName = $this->yellow->config->get("serverName"); + $this->yellow->sendStatus($statusCode, "Location: http://$serverName$baseLocation$location/"); } } return $statusCode; @@ -104,6 +105,7 @@ class Yellow_Webinterface function processRequestAction($baseLocation, $location, $fileName) { $statusCode = 0; + $serverName = $this->yellow->config->get("serverName"); if($_POST["action"] == "edit") { if(!empty($_POST["rawdata"])) @@ -117,24 +119,24 @@ class Yellow_Webinterface die("Configuration problem: Can't write page '$fileName'!"); } $statusCode = 303; - $this->yellow->sendStatus($statusCode, "Location: http://$_SERVER[SERVER_NAME]$baseLocation$location"); + $this->yellow->sendStatus($statusCode, "Location: http://$serverName$baseLocation$location"); } } else if($_POST["action"]== "login") { $statusCode = 303; - $this->yellow->sendStatus($statusCode, "Location: http://$_SERVER[SERVER_NAME]$baseLocation$location"); + $this->yellow->sendStatus($statusCode, "Location: http://$serverName$baseLocation$location"); } else if($_POST["action"]== "logout") { $this->users->destroyCookie("login"); $this->activeUserEmail = ""; $statusCode = 302; $newLocation = $this->yellow->config->getHtml("baseLocation").$location; - $this->yellow->sendStatus($statusCode, "Location: http://$_SERVER[SERVER_NAME]$newLocation"); + $this->yellow->sendStatus($statusCode, "Location: http://$serverName$newLocation"); } else { if(!is_readable($fileName)) { if($this->yellow->toolbox->isFileLocation($location) && is_dir($this->yellow->getContentDirectory("$location/"))) { $statusCode = 301; - $this->yellow->sendStatus($statusCode, "Location: http://$_SERVER[SERVER_NAME]$baseLocation$location/"); + $this->yellow->sendStatus($statusCode, "Location: http://$serverName$baseLocation$location/"); } else { $statusCode = $this->checkUserPermissions($location, $fileName) ? 424 : 404; $this->yellow->processRequestFile($baseLocation, $location, $fileName, $statusCode, false);