mikuli.cz

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

commit a17580f2d18e4915577c962cc2ab3cd0e43f8cbc
parent 1a2d98192913998ae3ec42d4e1ce7b3f91d06616
Author: markseu <mark2011@mayberg.se>
Date:   Mon, 29 Jul 2013 20:49:57 +0200

Better location handling (UTF-8 is good for you)

Diffstat:
Msystem/config/config.ini | 3+++
Msystem/core/core.php | 189+++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------
Msystem/core/core_commandline.php | 181+++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------
Msystem/core/core_markdown.php | 4++--
Msystem/core/core_webinterface.js | 4++--
Msystem/core/core_webinterface.php | 49++++++++++++++++++++++++++-----------------------
Msystem/snippets/header.php | 6+++---
7 files changed, 281 insertions(+), 155 deletions(-)

diff --git a/system/config/config.ini b/system/config/config.ini @@ -8,6 +8,9 @@ template = default style = default parser = markdown +// serverName = your.domain.name +// serverBase = /yellow + styleLocation = /media/styles/ imageLocation = /media/images/ pluginLocation = /media/plugins/ diff --git a/system/core/core.php b/system/core/core.php @@ -5,7 +5,7 @@ // Yellow main class class Yellow { - const Version = "0.1.8"; + const Version = "0.1.9"; var $page; //current page data var $pages; //current page tree from file system var $toolbox; //toolbox with helpers @@ -28,7 +28,7 @@ class Yellow $this->config->setDefault("parser", "markdown"); $this->config->setDefault("yellowVersion", Yellow::Version); $this->config->setDefault("serverName", $this->toolbox->getServerName()); - $this->config->setDefault("baseLocation", $this->toolbox->getServerBase()); + $this->config->setDefault("serverBase", $this->toolbox->getServerBase()); $this->config->setDefault("styleLocation", "/media/styles/"); $this->config->setDefault("imageLocation", "/media/images/"); $this->config->setDefault("pluginLocation", "media/plugins/"); @@ -55,10 +55,11 @@ class Yellow // Handle request function request() { - ob_start(); $this->toolbox->timerStart($time); - $baseLocation = $this->config->get("baseLocation"); - $location = $this->getRelativeLocation($baseLocation); + ob_start(); + $serverName = $this->config->get("serverName"); + $serverBase = $this->config->get("serverBase"); + $location = $this->getRelativeLocation($serverBase); $fileName = $this->getContentFileName($location); $statusCode = 0; $this->page = new Yellow_Page($this, $location); @@ -66,64 +67,71 @@ class Yellow { if(method_exists($value["obj"], "onRequest")) { - $statusCode = $value["obj"]->onRequest($baseLocation, $location, $fileName); + $statusCode = $value["obj"]->onRequest($serverName, $serverBase, $location, $fileName); if($statusCode) break; } } - if($statusCode == 0) $statusCode = $this->processRequest($baseLocation, $location, $fileName, true, $statusCode); - if($this->page->isExisting("pageError")) + if($statusCode == 0) $statusCode = $this->processRequest($serverName, $serverBase, $location, $fileName, true, $statusCode); + if($this->isRequestError()) { ob_clean(); $statusCode = $this->processRequestError(); } - $this->toolbox->timerStop($time); ob_end_flush(); + $this->toolbox->timerStop($time); if(defined("DEBUG") && DEBUG>=1) echo "Yellow::request status:$statusCode location:$location<br>\n"; if(defined("DEBUG") && DEBUG>=1) echo "Yellow::request time:$time ms<br>\n"; return $statusCode; } // Process request - function processRequest($baseLocation, $location, $fileName, $cacheable, $statusCode) + function processRequest($serverName, $serverBase, $location, $fileName, $cacheable, $statusCode) { if($statusCode == 0) { if(is_readable($fileName)) { $statusCode = 200; - $fileName = $this->readPage($baseLocation, $location, $fileName, $cacheable, $statusCode); + $fileName = $this->readPage($serverBase, $location, $fileName, $cacheable, $statusCode); + if($this->page->isExisting("redirect") && $cacheable) + { + $statusCode = 301; + $locationHeader = $this->toolbox->getHttpLocationHeader($serverName, $serverBase, $this->page->get("redirect")); + $this->page->statusCode = 0; + $this->header($locationHeader); + $this->sendStatus($statusCode, $locationHeader); + } } 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, $this->toolbox->getHttpLocationHeader($serverName, $serverBase, "$location/")); } else { $statusCode = 404; - $fileName = $this->readPage($baseLocation, $location, $fileName, $cacheable, $statusCode); + $fileName = $this->readPage($serverBase, $location, $fileName, $cacheable, $statusCode); } } } else if($statusCode >= 400) { - $fileName = $this->readPage($baseLocation, $location, $fileName, $cacheable, $statusCode); + $fileName = $this->readPage($serverBase, $location, $fileName, $cacheable, $statusCode); } if($this->page->statusCode != 0) $statusCode = $this->sendPage(); - if(defined("DEBUG") && DEBUG>=1) echo "Yellow::processRequest base:$baseLocation file:$fileName<br>\n"; + if(defined("DEBUG") && DEBUG>=1) echo "Yellow::processRequest base:$serverBase file:$fileName<br>\n"; return $statusCode; } // Process request with error function processRequestError() { - $baseLocation = $this->pages->baseLocation; - $fileName = $this->readPage($baseLocation, $this->page->location, $this->page->fileName, $this->page->cacheable, + $serverBase = $this->pages->serverBase; + $fileName = $this->readPage($serverBase, $this->page->location, $this->page->fileName, $this->page->cacheable, $this->page->statusCode, $this->page->get("pageError")); $statusCode = $this->sendPage(); - if(defined("DEBUG") && DEBUG>=1) echo "Yellow::processRequestError base:$baseLocation file:$fileName<br>\n"; + if(defined("DEBUG") && DEBUG>=1) echo "Yellow::processRequestError base:$serverBase file:$fileName<br>\n"; return $statusCode; } // Read page from file - function readPage($baseLocation, $location, $fileName, $cacheable, $statusCode, $pageError = "") + function readPage($serverBase, $location, $fileName, $cacheable, $statusCode, $pageError = "") { if($statusCode >= 400) { @@ -137,7 +145,7 @@ class Yellow $fileData = fread($fileHandle, filesize($fileName)); fclose($fileHandle); } - $this->pages->baseLocation = $baseLocation; + $this->pages->serverBase = $serverBase; $this->page = new Yellow_Page($this, $location); $this->page->parseData($fileName, $fileData, $cacheable, $statusCode, $pageError); $this->page->parseContent(); @@ -183,8 +191,22 @@ class Yellow // Send status response function sendStatus($statusCode, $text = "") { - @header($this->toolbox->getHttpStatusFormatted($statusCode)); - if(!empty($text)) @header($text); + if(PHP_SAPI != "cli") + { + @header($this->toolbox->getHttpStatusFormatted($statusCode)); + if(!empty($text)) @header($text); + } + } + + // Check for request error + function isRequestError() + { + $serverBase = $this->config->get("serverBase"); + if(!empty($serverBase) && !$this->toolbox->isValidLocation($serverBase)) + { + $this->page->error(500, "Server base '$serverBase' not supported!"); + } + return $this->page->isExisting("pageError"); } // Execute a template @@ -231,14 +253,14 @@ class Yellow return $header; } - // Return content location for current HTTP request, without base location - function getRelativeLocation($baseLocation) + // Return content location for current HTTP request, without server base + function getRelativeLocation($serverBase) { $location = $this->toolbox->getRequestLocation(); $location = $this->toolbox->normaliseLocation($location); - return substru($location, strlenu($baseLocation)); + return substru($location, strlenu($serverBase)); } - + // Return content file name from location function getContentFileName($location) { @@ -253,7 +275,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) { @@ -313,8 +335,9 @@ class Yellow_Page { $this->fileName = $fileName; $this->rawData = $rawData; - $this->active = $this->yellow->toolbox->isActiveLocation($this->yellow->pages->baseLocation, $this->location); - $this->visible = $this->yellow->toolbox->isVisibleLocation($this->yellow->pages->baseLocation, $this->location, + $this->active = $this->yellow->toolbox->isActiveLocation($this->yellow->pages->serverBase, $this->location, + $this->yellow->page->location); + $this->visible = $this->yellow->toolbox->isVisibleLocation($this->yellow->pages->serverBase, $this->location, $fileName, $this->yellow->config->get("contentDir")); $this->cacheable = $cacheable; $this->statusCode = $statusCode; @@ -331,7 +354,7 @@ class Yellow_Page $this->set("template", $this->yellow->config->get("template")); $this->set("style", $this->yellow->config->get("style")); $this->set("parser", $this->yellow->config->get("parser")); - $location = $this->yellow->config->get("baseLocation").rtrim($this->yellow->config->get("webinterfaceLocation"), '/').$this->location; + $location = $this->yellow->config->get("serverBase").rtrim($this->yellow->config->get("webinterfaceLocation"), '/').$this->location; $this->set("pageEdit", $location); if(preg_match("/^(\-\-\-[\r\n]+)(.+?)([\r\n]+\-\-\-[\r\n]+)/s", $this->rawData, $parsed)) @@ -442,7 +465,7 @@ class Yellow_Page // Return absolute page location function getLocation() { - return $this->yellow->pages->baseLocation.$this->location; + return $this->yellow->pages->serverBase.$this->location; } // Return page modification time, Unix time @@ -599,7 +622,7 @@ class Yellow_PageCollection extends ArrayObject if($pageNumber>=1 && $pageNumber<=$this->paginationCount) { $locationArgs = $this->yellow->toolbox->getRequestLocationArgs($pageNumber>1 ? "page:$pageNumber" : "page:"); - $location = $this->yellow->pages->baseLocation.$this->location.$locationArgs; + $location = $this->yellow->pages->serverBase.$this->location.$locationArgs; } return $location; } @@ -640,7 +663,7 @@ class Yellow_Pages { var $yellow; //access to API var $pages; //scanned pages - var $baseLocation; //requested base location + var $serverBase; //requested server base var $snippetArgs; //requested snippet arguments function __construct($yellow) @@ -664,7 +687,7 @@ class Yellow_Pages // Find a specific page function find($location, $absoluteLocation = false) { - if($absoluteLocation) $location = substru($location, strlenu($this->baseLocation)); + if($absoluteLocation) $location = substru($location, strlenu($this->serverBase)); $parentLocation = $this->getParentLocation($location); $this->scanChildren($parentLocation); foreach($this->pages[$parentLocation] as $page) if($page->location == $location) return $page; @@ -718,8 +741,8 @@ class Yellow_Pages { array_push($fileNames, $path.$entry."/".$this->yellow->config->get("contentDefaultFile")); } - $fileRegex = "/.*\\".$this->yellow->config->get("contentExtension")."/"; - foreach($this->yellow->toolbox->getDirectoryEntries($path, $fileRegex, true, false) as $entry) + $regex = "/.*\\".$this->yellow->config->get("contentExtension")."/"; + foreach($this->yellow->toolbox->getDirectoryEntries($path, $regex, true, false) as $entry) { if($entry != $this->yellow->config->get("contentDefaultFile")) array_push($fileNames, $path.$entry); } @@ -840,22 +863,31 @@ class Yellow_Toolbox return $location; } + // Check if file has been unmodified since last HTTP request + static function isFileNotModified($lastModified) + { + return isset($_SERVER["HTTP_IF_MODIFIED_SINCE"]) && $_SERVER["HTTP_IF_MODIFIED_SINCE"]==$lastModified; + } + // Check if location is specifying file or directory static function isFileLocation($location) { return substru($location, -1, 1) != "/"; } - // Check if file has been unmodified since last HTTP request - static function isFileNotModified($lastModified) + // Check if location is valid + static function isValidLocation($location) { - return isset($_SERVER["HTTP_IF_MODIFIED_SINCE"]) && $_SERVER["HTTP_IF_MODIFIED_SINCE"]==$lastModified; + $string = "/"; + $tokens = explode('/', $location); + for($i=1; $i<count($tokens)-1; ++$i) $string .= self::normaliseName($tokens[$i]).'/'; + $string .= self::normaliseName($tokens[$i]); + return $location == $string; } // Check if location is within current HTTP request - static function isActiveLocation($baseLocation, $location) + static function isActiveLocation($serverBase, $location, $currentLocation) { - $currentLocation = substru(self::getRequestLocation(), strlenu($baseLocation)); if($location != "/") { $active = substru($currentLocation, 0, strlenu($location))==$location; @@ -866,14 +898,14 @@ class Yellow_Toolbox } // Check if location is visible in navigation - static function isVisibleLocation($baseLocation, $location, $fileName, $pathBase) + static function isVisibleLocation($serverBase, $location, $fileName, $pathBase) { $visible = true; if(substru($fileName, 0, strlenu($pathBase)) == $pathBase) $fileName = substru($fileName, strlenu($pathBase)); $tokens = explode('/', $fileName); for($i=0; $i<count($tokens)-1; ++$i) { - if(!preg_match("/^[\d\-\.]+(.*)$/", $tokens[$i])) + if(!preg_match("/^[\d\-\_\.]+(.*)$/", $tokens[$i])) { $visible = false; break; @@ -881,7 +913,7 @@ class Yellow_Toolbox } return $visible; } - + // Find file path from location static function findFileFromLocation($location, $pathBase, $pathHome, $fileDefault, $fileExtension) { @@ -891,24 +923,34 @@ class Yellow_Toolbox { for($i=1; $i<count($tokens)-1; ++$i) { - if(preg_match("/^[\d\-\.]+/", $tokens[$i])) $duplicate = true; - $entries = self::getDirectoryEntries($path, "/^[\d\-\.]+".$tokens[$i]."$/"); - $path .= empty($entries) ? "$tokens[$i]/" : "$entries[0]/"; + $tokenFound = $tokens[$i]; + if(self::normaliseName($tokens[$i]) != $tokens[$i]) $invalid = true; + $regex = "/^[\d\-\_\.]*".strreplaceu('-', '.', $tokens[$i])."$/"; + foreach(self::getDirectoryEntries($path, $regex) as $entry) + { + if(self::normaliseName($entry) == $tokens[$i]) { $tokenFound = $entry; break; } + } + $path .= "$tokenFound/"; } - if($path == $pathBase.$pathHome) $duplicate = true; + if($path == $pathBase.$pathHome) $invalid = true; } else { $i = 1; $path .= $pathHome; } if($tokens[$i] != "") { - if(preg_match("/^[\d\-\.]+/", $tokens[$i])) $duplicate = true; - $entries = self::getDirectoryEntries($path, "/^[\d\-\.]+".$tokens[$i].$fileExtension."$/", false, false); - $path .= empty($entries) ? $tokens[$i].$fileExtension : $entries[0]; + $tokenFound = $tokens[$i]; + if(self::normaliseName($tokens[$i]) != $tokens[$i]) $invalid = true; + $regex = "/^[\d\-\_\.]*".strreplaceu('-', '.', $tokens[$i]).$fileExtension."$/"; + foreach(self::getDirectoryEntries($path, $regex, false, false) as $entry) + { + if(self::normaliseName($entry, true) == $tokens[$i]) { $tokenFound = $entry; break; } + } + $path .= $tokenFound; } else { $path .= $fileDefault; } - return $duplicate ? "" : $path; + return $invalid ? "" : $path; } // Find location from file path @@ -918,19 +960,20 @@ class Yellow_Toolbox if(substru($fileName, 0, strlenu($pathBase)) == $pathBase) $fileName = substru($fileName, strlenu($pathBase)); if(substru($fileName, 0, strlenu($pathHome)) == $pathHome) $fileName = substru($fileName, strlenu($pathHome)); $tokens = explode('/', $fileName); - for($i=0; $i<count($tokens)-1; ++$i) - { - if(preg_match("/^[\d\-\.]+(.*)$/", $tokens[$i], $matches)) $tokens[$i] = $matches[1]; - $location .= "$tokens[$i]/"; - } - if($tokens[$i] != $fileDefault) - { - if(preg_match("/^[\d\-\.]+(.*)$/", $tokens[$i], $matches)) $tokens[$i] = $matches[1]; - $location .= substru($tokens[$i], 0, -strlenu($fileExtension)); - } + for($i=0; $i<count($tokens)-1; ++$i) $location .= self::normaliseName($tokens[$i]).'/'; + if($tokens[$i] != $fileDefault) $location .= self::normaliseName($tokens[$i], true); return $location; } + // Normalise directory/file name and convert unwanted characters + static function normaliseName($text, $removeExtension = false) + { + if(preg_match("/^[\d\-\_\.]+(.*)$/", $text, $matches)) $text = $matches[1]; + if($removeExtension) $text = ($pos = strrposu($text, '.')) ? substru($text, 0, $pos) : $text; + $text = preg_replace("/[^\pL\d\-\_]/u", "-", $text); + return $text; + } + // Return human readable HTTP server status static function getHttpStatusFormatted($statusCode) { @@ -957,6 +1000,18 @@ class Yellow_Toolbox return gmdate("D, d M Y H:i:s", $timestamp)." GMT"; } + // Return HTTP location header + function getHttpLocationHeader($serverName, $serverBase, $location) + { + if(preg_match("/^(http|https):\/\//", $location)) + { + $locationHeader = "Location: $location"; + } else { + $locationHeader = "Location: http://$serverName$serverBase$location"; + } + return $locationHeader; + } + // Return files and directories static function getDirectoryEntries($path, $regex = "/.*/", $sort = false, $directories = true) { @@ -999,7 +1054,7 @@ class Yellow_Toolbox return $entries; } - // Create new file + // Create file function makeFile($fileName, $fileData, $mkdir = false) { $ok = false; @@ -1263,8 +1318,8 @@ class Yellow_Text function load($fileName, $toolbox) { $path = dirname($fileName); - $regex = basename($fileName); - foreach($toolbox->getDirectoryEntries($path, "/$regex/", true, false) as $entry) + $regex = "/".basename($fileName)."/"; + foreach($toolbox->getDirectoryEntries($path, $regex, true, false) as $entry) { $fileData = @file("$path/$entry"); if($fileData) @@ -1407,12 +1462,14 @@ class Yellow_Plugins mb_internal_encoding("UTF-8"); function strlenu() { return call_user_func_array("mb_strlen", func_get_args()); } function strposu() { return call_user_func_array("mb_strpos", func_get_args()); } +function strrposu() { return call_user_func_array("mb_strrpos", func_get_args()); } function strreplaceu() { return call_user_func_array("str_replace", func_get_args()); } function strtoloweru() { return call_user_func_array("mb_strtolower", func_get_args()); } function strtoupperu() { return call_user_func_array("mb_strtoupper", func_get_args()); } function substru() { return call_user_func_array("mb_substr", func_get_args()); } function strlenb() { return call_user_func_array("strlen", func_get_args()); } function strposb() { return call_user_func_array("strpos", func_get_args()); } +function strrposb() { return call_user_func_array("strrpos", func_get_args()); } function substrb() { return call_user_func_array("substr", func_get_args()); } // Error reporting for PHP 5 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.1"; + const Version = "0.1.2"; var $yellow; //access to API // Initialise plugin @@ -43,99 +43,162 @@ class Yellow_Commandline echo "Yellow ".Yellow::Version."\n"; foreach($this->yellow->plugins->plugins as $key=>$value) echo "$value[class] $value[version]\n"; return 0; - } + } - // Build static website + // Build website function build($args) - { - $statusCodeMax = $errorCount = 0; + { + $statusCode = 0; list($name, $command, $path, $location) = $args; if(!empty($path) && $path!="/") { - $this->yellow->toolbox->timerStart($time); - if(empty($location)) + if($this->yellow->config->isExisting("serverName") && $this->yellow->config->isExisting("serverBase")) { - $pages = $this->yellow->pages->index(true); - $fileNames = $this->yellow->toolbox->getDirectoryEntriesrecursive($this->yellow->config->get("mediaDir"), "/.*/", false, false); + $this->yellow->toolbox->timerStart($time); + $serverName = $this->yellow->config->get("serverName"); + $serverBase = $this->yellow->config->get("serverBase"); + list($statusCode, $contentCount, $mediaCount, $errorCount) = $this->buildStatic($serverName, $serverBase, $location, $path); + $this->yellow->toolbox->timerStop($time); + if(defined("DEBUG") && DEBUG>=1) echo "Yellow_Commandline::build time:$time ms\n"; } else { - $pages = new Yellow_PageCollection($this->yellow, $location); - $pages->append(new Yellow_Page($this->yellow, $location)); - $fileNames = array(); + list($statusCode, $contentCount, $mediaCount, $errorCount) = array(500, 0, 0, 1); + $fileName = $this->yellow->config->get("configDir").$this->yellow->config->get("configFile"); + echo "ERROR bulding website: Please configure serverName and serverBase in file '$fileName'!\n"; } - foreach($pages as $page) + echo "Yellow build: $contentCount content, $mediaCount media"; + echo ", $errorCount error".($errorCount!=1 ? 's' : ''); + echo ", status $statusCode\n"; + } else { + echo "Yellow build: Invalid arguments\n"; + } + return $statusCode; + } + + // Build static files + function buildStatic($serverName, $serverBase, $location, $path) + { + $statusCodeMax = $errorCount = 0; + if(empty($location)) + { + $pages = $this->yellow->pages->index(true); + $fileNames = $this->yellow->toolbox->getDirectoryEntriesrecursive($this->yellow->config->get("mediaDir"), "/.*/", false, false); + } else { + $pages = new Yellow_PageCollection($this->yellow, $location); + $pages->append(new Yellow_Page($this->yellow, $location)); + $fileNames = array(); + } + foreach($pages as $page) + { + $statusCode = $this->buildStaticFile($serverName, $serverBase, $page->location, $path); + $statusCodeMax = max($statusCodeMax, $statusCode); + if($statusCode >= 400) { - $statusCode = $this->buildContentFile($path, $page->location); - $statusCodeMax = max($statusCodeMax, $statusCode); - if($statusCode >= 400) - { - ++$errorCount; - echo "ERROR building location '".$page->location."', ".$this->yellow->page->getStatusCode(true)."\n"; - } - if(defined("DEBUG") && DEBUG>=1) echo "Yellow_Commandline::build status:$statusCode location:".$page->location."\n"; + ++$errorCount; + echo "ERROR building location '".$page->location."', ".$this->yellow->page->getStatusCode(true)."\n"; } - foreach($fileNames as $fileName) + if(defined("DEBUG") && DEBUG>=1) echo "Yellow_Commandline::buildStatic status:$statusCode location:".$page->location."\n"; + } + foreach($fileNames as $fileName) + { + $statusCode = $this->copyStaticFile($fileName, "$path/$fileName") ? 200 : 500; + $statusCodeMax = max($statusCodeMax, $statusCode); + if($statusCode >= 400) { - $statusCode = $this->buildMediaFile($fileName, "$path/$fileName"); - $statusCodeMax = max($statusCodeMax, $statusCode); - if($statusCode >= 400) - { - ++$errorCount; - echo "ERROR building file '$path/$fileName', ".$this->yellow->toolbox->getHttpStatusFormatted($statusCode)."\n"; - } - if(defined("DEBUG") && DEBUG>=1) echo "Yellow_Commandline::build status:$statusCode file:$fileName\n"; + ++$errorCount; + echo "ERROR building file '$path/$fileName', ".$this->yellow->toolbox->getHttpStatusFormatted($statusCode)."\n"; } - $this->yellow->toolbox->timerStop($time); - if(defined("DEBUG") && DEBUG>=1) echo "Yellow_Commandline::build time:$time ms\n"; - echo "Yellow build: ".count($pages)." content, ".count($fileNames)." media"; - echo ", $errorCount error".($errorCount!=1 ? 's' : ''); - echo ", status $statusCodeMax\n"; - } else { - echo "Yellow build: Invalid arguments\n"; + if(defined("DEBUG") && DEBUG>=1) echo "Yellow_Commandline::buildStatic status:$statusCode file:$fileName\n"; } - return $statusCodeMax; + return array($statusCodeMax, count($pages), count($fileNames), $errorCount); } - // Build content file - function buildContentFile($path, $location) + // Build static file + function buildStaticFile($serverName, $serverBase, $location, $path) { ob_start(); - $_SERVER["REQUEST_URI"] = $this->yellow->config->get("baseLocation").$location; - $_SERVER["SCRIPT_NAME"] = $this->yellow->config->get("baseLocation")."yellow.php"; - $_SERVER["SERVER_NAME"] = $this->yellow->config->get("serverName"); $_SERVER["SERVER_PROTOCOL"] = "HTTP/1.1"; - $fileName = $path.$location; - if(!$this->yellow->toolbox->isFileLocation($location)) $fileName .= $this->yellow->config->get("commandBuildDefaultFile"); + $_SERVER["SERVER_NAME"] = $serverName; + $_SERVER["REQUEST_URI"] = $serverBase.$location; + $_SERVER["SCRIPT_NAME"] = $serverBase."yellow.php"; $statusCode = $this->yellow->request(); if($statusCode != 404) { + $ok = true; $modified = strtotime($this->yellow->page->getHeader("Last-Modified")); - if(!$this->yellow->toolbox->makeFile($fileName, ob_get_contents(), true) || - !$this->yellow->toolbox->modifyFile($fileName, $modified)) + if(preg_match("/^(\w+)\/(\w+)/", $this->yellow->page->getHeader("Content-Type"), $matches)) { - $statusCode = 500; - $this->yellow->page->error($statusCode, "Can't write file '$fileName'!"); + $contentType = "$matches[1]/$matches[2]"; + $locationExtension = $this->getStaticLocation($location, ".$matches[2]"); + } + if(empty($contentType) || $contentType=="text/html") + { + $fileName = $this->getStaticFileName($location, $path); + $fileData = ob_get_contents(); + if($statusCode == 301) $fileData = $this->getStaticRedirect($this->yellow->page->getHeader("Location")); + $ok = $this->makeStaticFile($fileName, $fileData, $modified); + } else { + $fileName = $this->getStaticFileName($location, $path); + $fileData = $this->getStaticRedirect("http://$serverName$serverBase$locationExtension"); + $ok = $this->makeStaticFile($fileName, $fileData, $modified); + if($ok) + { + $fileName = $this->getStaticFileName($locationExtension, $path); + $fileData = ob_get_contents(); + $ok = $this->makeStaticFile($fileName, $fileData, $modified); + } } - list($contentType) = explode(';', $this->yellow->page->getHeader("Content-Type")); - if($contentType != "text/html") + if(!$ok) { $statusCode = 500; - $this->yellow->page->error($statusCode, "Unsupported type '$contentType'!"); + $this->yellow->page->error($statusCode, "Can't write file '$fileName'!"); } } ob_end_clean(); return $statusCode; } - // Build media file - function buildMediaFile($fileNameSource, $fileNameDest) + // Create static file + function makeStaticFile($fileName, $fileData, $modified) + { + return $this->yellow->toolbox->makeFile($fileName, $fileData, true) && + $this->yellow->toolbox->modifyFile($fileName, $modified); + } + + // Copy static file + function copyStaticFile($fileNameSource, $fileNameDest) + { + return $this->yellow->toolbox->copyFile($fileNameSource, $fileNameDest, true) && + $this->yellow->toolbox->modifyFile($fileNameDest, filemtime($fileNameSource)); + } + + // Return static file name from location + function getStaticFileName($location, $path) { - $statusCode = 200; - if(!$this->yellow->toolbox->copyFile($fileNameSource, $fileNameDest, true) || - !$this->yellow->toolbox->modifyFile($fileNameDest, filemtime($fileNameSource))) + $fileName = $path.$location; + if(!$this->yellow->toolbox->isFileLocation($location)) { - $statusCode = 500; + $fileName .= $this->yellow->config->get("commandBuildDefaultFile"); } - return $statusCode; + return $fileName; + } + + // Return static location with file extension + function getStaticLocation($location, $extension) + { + if(!$this->yellow->toolbox->isFileLocation($location)) $location .= "index"; + return $location.$extension; + } + + // Return static redirect data + function getStaticRedirect($url) + { + $data = "<!DOCTYPE html><html>\n"; + $data .= "<head>\n"; + $data .= "<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\" />\n"; + $data .= "<meta http-equiv=\"refresh\" content=\"0;url=$url\" />\n"; + $data .= "</head>\n"; + $data .= "</html>\n"; + return $data; } } diff --git a/system/core/core_markdown.php b/system/core/core_markdown.php @@ -5,7 +5,7 @@ // Markdown parser core plugin class Yellow_Markdown { - const Version = "0.1.4"; + const Version = "0.1.5"; var $markdown; //markdown parser var $html; //generated HTML @@ -45,7 +45,7 @@ class Yellow_MarkdownExtraParser extends MarkdownExtra_Parser function _doImages_inline_callback($matches) { $path = $matches[3]=="" ? $matches[4] : $matches[3]; - $src = $this->yellow->config->get("baseLocation").$this->yellow->config->get("imageLocation").$path; + $src = $this->yellow->config->get("serverBase").$this->yellow->config->get("imageLocation").$path; list($width, $height) = $this->yellow->toolbox->detectImageDimensions($this->yellow->config->get("imageDir").$path); $alt = $matches[2]; $title = $matches[7]; diff --git a/system/core/core_webinterface.js b/system/core/core_webinterface.js @@ -4,7 +4,7 @@ // Yellow main API var yellow = { - version: "0.1.1", + version: "0.1.2", onClick: function(e) { yellow.webinterface.hidePanesOnClick(yellow.toolbox.getEventElement(e)); }, onKeydown: function(e) { yellow.webinterface.hidePanesOnKeydown(yellow.toolbox.getEventKeycode(e)); }, onResize: function() { yellow.webinterface.resizePanes(); }, @@ -61,7 +61,7 @@ yellow.webinterface = elementBar.setAttribute("id", id); if(!simple) { - var location = yellow.config.baseLocation+yellow.config.pluginLocation; + var location = yellow.config.serverBase+yellow.config.pluginLocation; elementBar.innerHTML = "<div class=\"yellow-barleft\">"+ "<a href=\"http://datenstrom.se/yellow/\" target=\"_blank\"><img src=\""+location+"core_webinterface.png\" width=\"16\" height=\"16\"> Yellow</a>"+ diff --git a/system/core/core_webinterface.php b/system/core/core_webinterface.php @@ -5,7 +5,7 @@ // Web interface core plugin class Yellow_Webinterface { - const Version = "0.1.5"; + const Version = "0.1.6"; var $yellow; //access to API var $users; //web interface users var $activeLocation; //web interface location? (boolean) @@ -24,23 +24,23 @@ class Yellow_Webinterface } // Handle web interface location - function onRequest($baseLocation, $location, $fileName) + function onRequest($serverName, $serverBase, $location, $fileName) { $statusCode = 0; if($this->checkWebinterfaceLocation($location)) { - $baseLocation .= rtrim($this->yellow->config->get("webinterfaceLocation"), '/'); - $location = $this->yellow->getRelativeLocation($baseLocation); + $serverBase .= rtrim($this->yellow->config->get("webinterfaceLocation"), '/'); + $location = $this->yellow->getRelativeLocation($serverBase); $fileName = $this->yellow->getContentFileName($location); - if($this->checkUser()) $statusCode = $this->processRequestAction($baseLocation, $location, $fileName); - if($statusCode == 0) $statusCode = $this->yellow->processRequest($baseLocation, $location, $fileName, + if($this->checkUser()) $statusCode = $this->processRequestAction($serverName, $serverBase, $location, $fileName); + if($statusCode == 0) $statusCode = $this->yellow->processRequest($serverName, $serverBase, $location, $fileName, false, $this->activeUserFail ? 401 : 0); } else { if($this->yellow->config->get("webinterfaceLocation") == "$location/") { $statusCode = 301; - $serverName = $this->yellow->config->get("serverName"); - $this->yellow->sendStatus($statusCode, "Location: http://$serverName$baseLocation$location/"); + $locationHeader = $this->yellow->toolbox->getHttpLocationHeader($serverName, $serverBase, "$location/"); + $this->yellow->sendStatus($statusCode, $locationHeader); } } return $statusCode; @@ -51,10 +51,10 @@ class Yellow_Webinterface { if($this->isWebinterfaceLocation() && $this->isUser()) { - $baseLocation = $this->yellow->config->get("baseLocation"); + $serverBase = $this->yellow->config->get("serverBase"); $webinterfaceLocation = trim($this->yellow->config->get("webinterfaceLocation"), '/'); - $text = preg_replace("#<a(.*?)href=\"$baseLocation/(?!$webinterfaceLocation)(.*?)\"(.*?)>#", - "<a$1href=\"$baseLocation/$webinterfaceLocation/$2\"$3>", $text); + $text = preg_replace("#<a(.*?)href=\"$serverBase/(?!$webinterfaceLocation)(.*?)\"(.*?)>#", + "<a$1href=\"$serverBase/$webinterfaceLocation/$2\"$3>", $text); switch($statusCode) { case 200: $this->rawDataOriginal = $this->yellow->page->rawData; break; @@ -77,7 +77,7 @@ class Yellow_Webinterface $header = ""; if($this->isWebinterfaceLocation()) { - $location = $this->yellow->config->getHtml("baseLocation").$this->yellow->config->getHtml("pluginLocation"); + $location = $this->yellow->config->getHtml("serverBase").$this->yellow->config->getHtml("pluginLocation"); $language = $this->isUser() ? $this->users->getLanguage($this->activeUserEmail) : $this->yellow->page->get("language"); $header .= "<link rel=\"styleSheet\" type=\"text/css\" media=\"all\" href=\"{$location}core_webinterface.css\" />\n"; $header .= "<script type=\"text/javascript\" src=\"{$location}core_webinterface.js\"></script>\n"; @@ -98,44 +98,46 @@ class Yellow_Webinterface } // Process request for an action - function processRequestAction($baseLocation, $location, $fileName) + function processRequestAction($serverName, $serverBase, $location, $fileName) { $statusCode = 0; - $serverName = $this->yellow->config->get("serverName"); if($_POST["action"] == "edit") { - if(!empty($_POST["rawdata"])) + if(!empty($_POST["rawdata"]) && $this->checkUserPermissions($location, $fileName)) { $this->rawDataOriginal = $_POST["rawdata"]; if($this->yellow->toolbox->makeFile($fileName, $_POST["rawdata"])) { $statusCode = 303; - $this->yellow->sendStatus($statusCode, "Location: http://$serverName$baseLocation$location"); + $locationHeader = $this->yellow->toolbox->getHttpLocationHeader($serverName, $serverBase, $location); + $this->yellow->sendStatus($statusCode, $locationHeader); } else { $statusCode = 500; - $this->yellow->processRequest($baseLocation, $location, $fileName, false, $statusCode); + $this->yellow->processRequest($serverName, $serverBase, $location, $fileName, false, $statusCode); $this->yellow->page->error($statusCode, "Can't write file '$fileName'!"); } } } else if($_POST["action"]== "login") { $statusCode = 303; - $this->yellow->sendStatus($statusCode, "Location: http://$serverName$baseLocation$location"); + $locationHeader = $this->yellow->toolbox->getHttpLocationHeader($serverName, $serverBase, $location); + $this->yellow->sendStatus($statusCode, $locationHeader); } 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://$serverName$newLocation"); + $locationHeader = $this->yellow->toolbox->getHttpLocationHeader($serverName, $this->yellow->config->get("serverBase"), $location); + $this->yellow->sendStatus($statusCode, $locationHeader); } 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://$serverName$baseLocation$location/"); + $locationHeader = $this->yellow->toolbox->getHttpLocationHeader($serverName, $serverBase, "$location/"); + $this->yellow->sendStatus($statusCode, $locationHeader); } else { $statusCode = $this->checkUserPermissions($location, $fileName) ? 424 : 404; - $this->yellow->processRequest($baseLocation, $location, $fileName, false, $statusCode); + $this->yellow->processRequest($serverName, $serverBase, $location, $fileName, false, $statusCode); } } } @@ -215,7 +217,8 @@ class Yellow_Webinterface $data = array("userEmail" => $email, "userName" => $this->users->getName($email), "userLanguage" => $this->users->getLanguage($email), - "baseLocation" => $this->yellow->config->get("baseLocation")); + "serverName" => $this->yellow->config->get("serverName"), + "serverBase" => $this->yellow->config->get("serverBase")); return array_merge($data, $this->yellow->config->getData("Location")); } } diff --git a/system/snippets/header.php b/system/snippets/header.php @@ -6,11 +6,11 @@ <meta name="author" content="<?php echo $yellow->page->getHtml("author") ?>" /> <meta name="viewport" content="width=device-width, initial-scale=1"> <title><?php echo $yellow->config->getHtml("sitename")." - ".$yellow->page->getHtml("title") ?></title> -<link rel="shortcut icon" href="<?php echo $yellow->config->get("baseLocation").$yellow->config->get("imageLocation")."default_icon.png" ?>" /> -<link rel="stylesheet" type="text/css" media="all" href="<?php echo $yellow->config->get("baseLocation").$yellow->config->get("styleLocation").$yellow->page->get("style").".css" ?>" /> +<link rel="shortcut icon" href="<?php echo $yellow->config->get("serverBase").$yellow->config->get("imageLocation")."default_icon.png" ?>" /> +<link rel="stylesheet" type="text/css" media="all" href="<?php echo $yellow->config->get("serverBase").$yellow->config->get("styleLocation").$yellow->page->get("style").".css" ?>" /> <?php echo $yellow->getHeaderExtra() ?> </head> <body> <div class="page"> -<div class="header"><h1><a href="<?php echo $yellow->config->get("baseLocation")."/" ?>"><?php echo $yellow->config->getHtml("sitename") ?></a></h1></div> +<div class="header"><h1><a href="<?php echo $yellow->config->get("serverBase")."/" ?>"><?php echo $yellow->config->getHtml("sitename") ?></a></h1></div> <div class="header-banner"></div>