commit fabd68c66a4dbc1a971bdfd03be63ac2ba31e51b
parent 80db30ad71f2fe47697b61cacf10dcacf4cb1aed
Author: markseu <mark2011@mayberg.se>
Date: Fri, 17 Feb 2017 14:52:55 +0100
System update (better software update)
Diffstat:
15 files changed, 952 insertions(+), 685 deletions(-)
diff --git a/system/config/config.ini b/system/config/config.ini
@@ -4,17 +4,20 @@ Sitename: Yellow
Author: Yellow
Email: webmaster
Language: en
+Timezone: UTC
Theme: flatsite
-# ServerScheme: http
-# ServerName: your.domain.name
-# ServerBase:
-# ServerTime: UTC
-
+StaticUrl:
+StaticDefaultFile: index.html
+StaticErrorFile: 404.html
+StaticDir: cache/
+MediaLocation: /media/
ImageLocation: /media/images/
PluginLocation: /media/plugins/
ThemeLocation: /media/themes/
AssetLocation: /media/themes/assets/
+MediaDir: media/
+ImageDir: media/images/
SystemDir: system/
ConfigDir: system/config/
PluginDir: system/plugins/
@@ -23,15 +26,10 @@ AssetDir: system/themes/assets/
SnippetDir: system/themes/snippets/
TemplateDir: system/themes/templates/
TrashDir: system/trash/
-MediaDir: media/
-ImageDir: media/images/
-StaticDir: cache/
-StaticDefaultFile: index.html
-StaticErrorFile: 404.html
-ContentPagination: page
ContentDir: content/
ContentRootDir: default/
ContentHomeDir: home/
+ContentPagination: page
ContentDefaultFile: page.txt
ContentExtension: .txt
ConfigExtension: .ini
@@ -50,11 +48,12 @@ Parser: markdown
ParserSafeMode: 0
MultiLanguageMode: 0
InstallationMode: 1
+StartupUpdateNotification: none
UpdatePluginsUrl: https://github.com/datenstrom/yellow-plugins
UpdateThemesUrl: https://github.com/datenstrom/yellow-themes
UpdateInformationFile: update.ini
UpdateVersionFile: version.ini
-UpdateNotification: none
+UpdateResourceFile: resource.ini
WebinterfaceLocation: /edit/
WebinterfaceNewFile: page-new-(.*).txt
WebinterfaceMetaFilePrefix: published
diff --git a/system/plugins/commandline.php b/system/plugins/commandline.php
@@ -5,7 +5,7 @@
// Command line plugin
class YellowCommandline
{
- const VERSION = "0.6.17";
+ const VERSION = "0.6.18";
var $yellow; //access to API
var $files; //number of files
var $errors; //number of errors
@@ -65,8 +65,7 @@ class YellowCommandline
$statusCode = 500;
$this->files = 0; $this->errors = 1;
$fileName = $this->yellow->config->get("configDir").$this->yellow->config->get("configFile");
- echo "ERROR building files: Please configure ServerScheme, ServerName, ServerBase, ServerTime in file '$fileName'!\n";
- echo "ERROR building files: Open your website in a web browser, if you want to see your server settings!\n";
+ echo "ERROR building files: Please configure StaticUrl in file '$fileName'!\n";
}
echo "Yellow $command: $this->files file".($this->files!=1 ? 's' : '');
echo ", $this->errors error".($this->errors!=1 ? 's' : '');
@@ -132,7 +131,9 @@ class YellowCommandline
if(!is_readable($this->yellow->page->fileName))
{
ob_start();
- $statusCode = $this->requestStaticFile($location);
+ $staticUrl = $this->yellow->config->get("staticUrl");
+ list($scheme, $address, $base) = $this->yellow->lookup->getUrlInformation($staticUrl);
+ $statusCode = $this->requestStaticFile($scheme, $address, $base, $location);
if($statusCode<400 || $error)
{
$fileData = ob_get_contents();
@@ -165,9 +166,9 @@ class YellowCommandline
$this->yellow->page->set("pageError", "Can't write file '$fileName'!");
}
}
- if($statusCode==200 && $analyse) $this->analyseStaticFile($fileData);
- if($statusCode==404 && $error) $statusCode = 200;
+ if($statusCode==200 && $analyse) $this->analyseStaticFile($scheme, $address, $base, $fileData);
if($statusCode==404 && $probe) $statusCode = 100;
+ if($statusCode==404 && $error) $statusCode = 200;
if($statusCode>=200) ++$this->files;
if($statusCode>=400)
{
@@ -179,35 +180,39 @@ class YellowCommandline
}
// Request static file
- function requestStaticFile($location)
+ function requestStaticFile($scheme, $address, $base, $location)
{
+ list($serverName, $serverPort) = explode(':', $address);
+ if(is_null($serverPort)) $serverPort = $scheme=="https" ? 443 : 80;
+ $_SERVER["HTTPS"] = $scheme=="https" ? "on" : "off";
$_SERVER["SERVER_PROTOCOL"] = "HTTP/1.1";
- $_SERVER["SERVER_NAME"] = $this->yellow->config->get("serverName");
- $_SERVER["REQUEST_URI"] = $this->yellow->config->get("serverBase").$location;
- $_SERVER["SCRIPT_NAME"] = $this->yellow->config->get("serverBase")."/yellow.php";
+ $_SERVER["SERVER_NAME"] = $serverName;
+ $_SERVER["SERVER_PORT"] = $serverPort;
+ $_SERVER["REQUEST_URI"] = $base.$location;
+ $_SERVER["SCRIPT_NAME"] = $base."/yellow.php";
$_SERVER["REMOTE_ADDR"] = "127.0.0.1";
$_REQUEST = array();
return $this->yellow->request();
}
// Analyse static file, detect locations with arguments
- function analyseStaticFile($rawData)
+ function analyseStaticFile($scheme, $address, $base, $rawData)
{
- $serverName = $this->yellow->config->get("serverName");
- $serverBase = $this->yellow->config->get("serverBase");
$pagination = $this->yellow->config->get("contentPagination");
preg_match_all("/<(.*?)href=\"([^\"]+)\"(.*?)>/i", $rawData, $matches);
foreach($matches[2] as $match)
{
- if(preg_match("/^(.*?)#(.*)$/", $match, $tokens)) $match = $tokens[1];
- if(preg_match("/^\w+:\/+(.*?)(\/.*)$/", $match, $tokens))
+ $location = rawurldecode($match);
+ if(preg_match("/^(.*?)#(.*)$/", $location, $tokens)) $location = $tokens[1];
+ if(preg_match("/^(\w+):\/\/([^\/]+)(.*)$/", $location, $tokens))
{
- if($tokens[1]!=$serverName) continue;
- $match = $tokens[2];
+ if($tokens[1]!=$scheme) continue;
+ if($tokens[2]!=$address) continue;
+ $location = $tokens[3];
}
- if(!$this->yellow->toolbox->isLocationArgs($match)) continue;
- if(substru($match, 0, strlenu($serverBase))!=$serverBase) continue;
- $location = rawurldecode(substru($match, strlenu($serverBase)));
+ if(substru($location, 0, strlenu($base))!=$base) continue;
+ $location = substru($location, strlenu($base));
+ if(!$this->yellow->toolbox->isLocationArgs($location)) continue;
if(!$this->yellow->toolbox->isLocationArgsPagination($location, $pagination))
{
$location = rtrim($location, '/').'/';
@@ -308,9 +313,8 @@ class YellowCommandline
// Show software version and updates
function versionCommand($args)
{
- $statusCode = 0;
- $serverSoftware = $this->yellow->toolbox->getServerSoftware();
- echo "Yellow ".YellowCore::VERSION.", PHP ".PHP_VERSION.", $serverSoftware\n";
+ $serverVersion = $this->yellow->toolbox->getServerVersion();
+ echo "Yellow ".YellowCore::VERSION.", PHP ".PHP_VERSION.", $serverVersion\n";
list($command) = $args;
list($statusCode, $dataCurrent) = $this->getSoftwareVersion();
list($statusCode, $dataLatest) = $this->getSoftwareVersion(true);
@@ -321,22 +325,17 @@ class YellowCommandline
echo "$key $value\n";
} else {
echo "$key $dataLatest[$key] - Update available\n";
- ++$updates;
}
}
if($statusCode!=200) echo "ERROR checking updates: ".$this->yellow->page->get("pageError")."\n";
- if($updates) echo "Yellow $command: $updates update".($updates==1 ? "":"s")." available\n";
return $statusCode;
}
// Check static configuration
function checkStaticConfig()
{
- $serverScheme = $this->yellow->config->get("serverScheme");
- $serverName = $this->yellow->config->get("serverName");
- $serverBase = $this->yellow->config->get("serverBase");
- return !empty($serverScheme) && !empty($serverName) &&
- $this->yellow->lookup->isValidLocation($serverBase) && $serverBase!="/";
+ $staticUrl = $this->yellow->config->get("staticUrl");
+ return !empty($staticUrl);
}
// Check static directory
@@ -380,10 +379,9 @@ class YellowCommandline
function getContentLocations()
{
$locations = array();
- $serverScheme = $this->yellow->config->get("serverScheme");
- $serverName = $this->yellow->config->get("serverName");
- $serverBase = $this->yellow->config->get("serverBase");
- $this->yellow->page->setRequestInformation($serverScheme, $serverName, $serverBase, "", "");
+ $staticUrl = $this->yellow->config->get("staticUrl");
+ list($scheme, $address, $base) = $this->yellow->lookup->getUrlInformation($staticUrl);
+ $this->yellow->page->setRequestInformation($scheme, $address, $base, "", "");
foreach($this->yellow->pages->index(true, true) as $page)
{
if($page->get("status")!="ignore" && $page->get("status")!="draft")
diff --git a/system/plugins/core.php b/system/plugins/core.php
@@ -5,7 +5,7 @@
// Yellow core
class YellowCore
{
- const VERSION = "0.6.7";
+ const VERSION = "0.6.8";
var $page; //current page
var $pages; //pages from file system
var $files; //files from file system
@@ -31,15 +31,20 @@ class YellowCore
$this->config->setDefault("author", "Yellow");
$this->config->setDefault("email", "webmaster");
$this->config->setDefault("language", "en");
+ $this->config->setDefault("timezone", "UTC");
$this->config->setDefault("theme", "default");
- $this->config->setDefault("serverScheme", $this->toolbox->getServerScheme());
- $this->config->setDefault("serverName", $this->toolbox->getServerName());
- $this->config->setDefault("serverBase", $this->toolbox->getServerBase());
- $this->config->setDefault("serverTime", $this->toolbox->getServerTime());
+ $this->config->setDefault("serverUrl", "");
+ $this->config->setDefault("staticUrl", "");
+ $this->config->setDefault("staticDefaultFile", "index.html");
+ $this->config->setDefault("staticErrorFile", "404.html");
+ $this->config->setDefault("staticDir", "cache/");
+ $this->config->setDefault("mediaLocation", "/media/");
$this->config->setDefault("imageLocation", "/media/images/");
$this->config->setDefault("pluginLocation", "/media/plugins/");
$this->config->setDefault("themeLocation", "/media/themes/");
$this->config->setDefault("assetLocation", "/media/themes/assets/");
+ $this->config->setDefault("mediaDir", "media/");
+ $this->config->setDefault("imageDir", "media/images/");
$this->config->setDefault("systemDir", "system/");
$this->config->setDefault("configDir", "system/config/");
$this->config->setDefault("pluginDir", "system/plugins/");
@@ -48,15 +53,10 @@ class YellowCore
$this->config->setDefault("snippetDir", "system/themes/snippets/");
$this->config->setDefault("templateDir", "system/themes/templates/");
$this->config->setDefault("trashDir", "system/trash/");
- $this->config->setDefault("mediaDir", "media/");
- $this->config->setDefault("imageDir", "media/images/");
- $this->config->setDefault("staticDir", "cache/");
- $this->config->setDefault("staticDefaultFile", "index.html");
- $this->config->setDefault("staticErrorFile", "404.html");
- $this->config->setDefault("contentPagination", "page");
$this->config->setDefault("contentDir", "content/");
$this->config->setDefault("contentRootDir", "default/");
$this->config->setDefault("contentHomeDir", "home/");
+ $this->config->setDefault("contentPagination", "page");
$this->config->setDefault("contentDefaultFile", "page.txt");
$this->config->setDefault("contentExtension", ".txt");
$this->config->setDefault("configExtension", ".ini");
@@ -76,6 +76,12 @@ class YellowCore
$this->config->setDefault("parserSafeMode", "0");
$this->config->setDefault("multiLanguageMode", "0");
$this->config->setDefault("installationMode", "0");
+ $this->config->setDefault("startupUpdateNotification", "none");
+ }
+
+ function __destruct()
+ {
+ $this->shutdown();
}
// Handle initialisation
@@ -83,19 +89,35 @@ class YellowCore
{
if(defined("DEBUG") && DEBUG>=2)
{
- $serverSoftware = $this->toolbox->getServerSoftware();
- echo "Yellow ".YellowCore::VERSION.", PHP ".PHP_VERSION.", $serverSoftware<br>\n";
+ $serverVersion = $this->toolbox->getServerVersion();
+ echo "Yellow ".YellowCore::VERSION.", PHP ".PHP_VERSION.", $serverVersion<br/>\n";
}
- $this->pages->requestHandler = "none";
$this->config->load($this->config->get("configDir").$this->config->get("configFile"));
$this->text->load($this->config->get("pluginDir").$this->config->get("textFile"));
$this->lookup->load();
- $this->plugins->load();
$this->themes->load();
+ $this->plugins->load();
+ $this->startup();
+ }
+
+ // Handle startup
+ function startup()
+ {
+ $tokens = explode(',', $this->config->get("startupUpdateNotification"));
foreach($this->plugins->plugins as $key=>$value)
{
- if(method_exists($value["obj"], "onUpdate")) $value["obj"]->onUpdate("");
+ if(method_exists($value["obj"], "onStartup")) $value["obj"]->onStartup(in_array($value["plugin"], $tokens));
+ }
+ foreach($this->themes->themes as $key=>$value)
+ {
+ if(method_exists($value["obj"], "onStartup")) $value["obj"]->onStartup(in_array($value["theme"], $tokens));
}
+ if($this->config->get("startupUpdateNotification")!="none")
+ {
+ $fileNameConfig = $this->config->get("configDir").$this->config->get("configFile");
+ $this->config->update($fileNameConfig, array("startupUpdateNotification" => "none"));
+ }
+ if(defined("DEBUG") && DEBUG>=2) echo "YellowCore::startup<br/>\n";
}
// Handle request
@@ -105,21 +127,21 @@ class YellowCore
$statusCode = 0;
$this->toolbox->timerStart($time);
$this->toolbox->normaliseRequest();
- list($serverScheme, $serverName, $base, $location, $fileName) = $this->getRequestInformation();
- $this->page->setRequestInformation($serverScheme, $serverName, $base, $location, $fileName);
+ list($scheme, $address, $base, $location, $fileName) = $this->getRequestInformation();
+ $this->page->setRequestInformation($scheme, $address, $base, $location, $fileName);
foreach($this->plugins->plugins as $key=>$value)
{
if(method_exists($value["obj"], "onRequest"))
{
- $this->pages->requestHandler = $key;
- $statusCode = $value["obj"]->onRequest($serverScheme, $serverName, $base, $location, $fileName);
+ $this->lookup->requestHandler = $key;
+ $statusCode = $value["obj"]->onRequest($scheme, $address, $base, $location, $fileName);
if($statusCode!=0) break;
}
}
if($statusCode==0)
{
- $this->pages->requestHandler = "core";
- $statusCode = $this->processRequest($serverScheme, $serverName, $base, $location, $fileName, true);
+ $this->lookup->requestHandler = "core";
+ $statusCode = $this->processRequest($scheme, $address, $base, $location, $fileName, true);
}
if($this->page->isExisting("pageError")) $statusCode = $this->processRequestError();
$this->toolbox->timerStop($time);
@@ -127,14 +149,13 @@ class YellowCore
if(defined("DEBUG") && DEBUG>=1)
{
$handler = $this->getRequestHandler();
- echo "YellowCore::request status:$statusCode location:$location handler:$handler<br/>\n";
- echo "YellowCore::request time:$time ms<br/>\n";
+ echo "YellowCore::request status:$statusCode handler:$handler time:$time ms<br/>\n";
}
return $statusCode;
}
// Process request
- function processRequest($serverScheme, $serverName, $base, $location, $fileName, $cacheable)
+ function processRequest($scheme, $address, $base, $location, $fileName, $cacheable)
{
$statusCode = 0;
if(is_readable($fileName))
@@ -143,7 +164,7 @@ class YellowCore
{
$statusCode = 303;
$location = $location.$this->getRequestLocationArgsClean();
- $location = $this->lookup->normaliseUrl($serverScheme, $serverName, $base, $location);
+ $location = $this->lookup->normaliseUrl($scheme, $address, $base, $location);
$this->sendStatus($statusCode, $location);
}
} else {
@@ -151,16 +172,16 @@ class YellowCore
{
$statusCode = 301;
$location = $this->lookup->isFileLocation($location) ? "$location/" : "/".$this->getRequestLanguage()."/";
- $location = $this->lookup->normaliseUrl($serverScheme, $serverName, $base, $location);
+ $location = $this->lookup->normaliseUrl($scheme, $address, $base, $location);
$this->sendStatus($statusCode, $location);
}
}
if($statusCode==0)
{
- $fileName = $this->lookup->findFileStatic($location, $fileName, $cacheable);
+ $fileName = $this->lookup->findFileStatic($location, $fileName, $cacheable && !$this->isCommandLine());
if($this->lookup->isContentFile($fileName) || !is_readable($fileName))
{
- $fileName = $this->readPage($serverScheme, $serverName, $base, $location, $fileName, $cacheable,
+ $fileName = $this->readPage($scheme, $address, $base, $location, $fileName, $cacheable,
max(is_readable($fileName) ? 200 : 404, $this->page->statusCode), $this->page->get("pageError"));
$statusCode = $this->sendPage();
} else {
@@ -175,7 +196,7 @@ class YellowCore
function processRequestError()
{
ob_clean();
- $fileName = $this->readPage($this->page->serverScheme, $this->page->serverName, $this->page->base,
+ $fileName = $this->readPage($this->page->scheme, $this->page->address, $this->page->base,
$this->page->location, $this->page->fileName, $this->page->cacheable, $this->page->statusCode,
$this->page->get("pageError"));
$statusCode = $this->sendPage();
@@ -184,7 +205,7 @@ class YellowCore
}
// Read page
- function readPage($serverScheme, $serverName, $base, $location, $fileName, $cacheable, $statusCode, $pageError)
+ function readPage($scheme, $address, $base, $location, $fileName, $cacheable, $statusCode, $pageError)
{
if($statusCode>=400)
{
@@ -193,7 +214,7 @@ class YellowCore
$cacheable = false;
}
$this->page = new YellowPage($this);
- $this->page->setRequestInformation($serverScheme, $serverName, $base, $location, $fileName);
+ $this->page->setRequestInformation($scheme, $address, $base, $location, $fileName);
$this->page->parseData($this->toolbox->readFile($fileName), $cacheable, $statusCode, $pageError);
$this->text->setLanguage($this->page->get("language"));
$this->page->parseContent();
@@ -265,52 +286,71 @@ class YellowCore
{
if(method_exists($value["obj"], "onCommand"))
{
+ $this->lookup->commandHandler = $key;
$statusCode = $value["obj"]->onCommand(func_get_args());
if($statusCode!=0) break;
}
}
if($statusCode==0)
{
+ $this->lookup->commandHandler = "core";
$statusCode = 400;
list($command) = func_get_args();
echo "Yellow $command: Command not found\n";
}
$this->toolbox->timerStop($time);
- if(defined("DEBUG") && DEBUG>=1) echo "YellowCore::command time:$time ms<br/>\n";
+ if(defined("DEBUG") && DEBUG>=1)
+ {
+ $handler = $this->getCommandHandler();
+ echo "YellowCore::command status:$statusCode handler:$handler time:$time ms<br/>\n";
+ }
return $statusCode;
}
+ // Handle shutdown
+ function shutdown()
+ {
+ foreach($this->plugins->plugins as $key=>$value)
+ {
+ if(method_exists($value["obj"], "onShutdown")) $value["obj"]->onShutdown();
+ }
+ foreach($this->themes->themes as $key=>$value)
+ {
+ if(method_exists($value["obj"], "onShutdown")) $value["obj"]->onShutdown();
+ }
+ if(defined("DEBUG") && DEBUG>=2) echo "YellowCore::shutdown<br/>\n";
+ }
+
// Parse snippet
function snippet($name, $args = null)
{
- $this->pages->snippetArgs = func_get_args();
+ $this->lookup->snippetArgs = func_get_args();
$this->page->parseSnippet($name);
}
+ // Return snippet arguments
+ function getSnippetArgs()
+ {
+ return $this->lookup->snippetArgs;
+ }
+
// Return request information
- function getRequestInformation($serverScheme = "", $serverName = "", $base = "")
+ function getRequestInformation($scheme = "", $address = "", $base = "")
{
- $serverScheme = empty($serverScheme) ? $this->config->get("serverScheme") : $serverScheme;
- $serverName = empty($serverName) ? $this->config->get("serverName") : $serverName;
- $base = empty($base) ? $this->config->get("serverBase") : $base;
- $location = $this->toolbox->getLocation();
- $location = substru($location, strlenu($base));
- if(preg_match("/\.(css|ico|js|jpg|png|svg|txt|woff)$/", $location))
+ if(empty($scheme) && empty($address) && empty($base))
{
- $pluginLocationLength = strlenu($this->config->get("pluginLocation"));
- $themeLocationLength = strlenu($this->config->get("themeLocation"));
- if(substru($location, 0, $pluginLocationLength)==$this->config->get("pluginLocation")) {
- $fileName = $this->config->get("pluginDir").substru($location, $pluginLocationLength);
- } else if(substru($location, 0, $themeLocationLength)==$this->config->get("themeLocation")) {
- $fileName = $this->config->get("themeDir").substru($location, $themeLocationLength);
- } else if($location=="/".$this->config->get("robotsFile")) {
- $fileName = $this->config->get("configDir").$this->config->get("robotsFile");
- } else if($location=="/".$this->config->get("faviconFile")) {
- $fileName = $this->config->get("assetDir").$this->config->get("siteicon").".png";
- }
+ $url = $this->config->get("serverUrl");
+ if(empty($url) || $this->isCommandLine()) $url = $this->toolbox->getServerUrl();
+ list($scheme, $address, $base) = $this->lookup->getUrlInformation($url);
+ $this->config->set("serverScheme", $scheme);
+ $this->config->set("serverAddress", $address);
+ $this->config->set("serverBase", $base);
}
+ $location = substru($this->toolbox->getLocation(), strlenu($base));
+ if(empty($fileName)) $fileName = $this->lookup->findFileFromSystem($location);
+ if(empty($fileName)) $fileName = $this->lookup->findFileFromMedia($location);
if(empty($fileName)) $fileName = $this->lookup->findFileFromLocation($location);
- return array($serverScheme, $serverName, $base, $location, $fileName);
+ return array($scheme, $address, $base, $location, $fileName);
}
// Return request location
@@ -328,13 +368,19 @@ class YellowCore
// Return request handler
function getRequestHandler()
{
- return $this->pages->requestHandler;
+ return $this->lookup->requestHandler;
+ }
+
+ // Return command handler
+ function getCommandHandler()
+ {
+ return $this->lookup->commandHandler;
}
- // Return snippet arguments
- function getSnippetArgs()
+ // Check if running at command line
+ function isCommandLine()
{
- return $this->pages->snippetArgs;
+ return !empty($this->lookup->commandHandler);
}
}
@@ -342,8 +388,8 @@ class YellowCore
class YellowPage
{
var $yellow; //access to API
- var $serverScheme; //server scheme
- var $serverName; //server name
+ var $scheme; //server scheme
+ var $address; //server address
var $base; //base location
var $location; //page location
var $fileName; //content file name
@@ -374,10 +420,10 @@ class YellowPage
}
// Set request information
- function setRequestInformation($serverScheme, $serverName, $base, $location, $fileName)
+ function setRequestInformation($scheme, $address, $base, $location, $fileName)
{
- $this->serverScheme = $serverScheme;
- $this->serverName = $serverName;
+ $this->scheme = $scheme;
+ $this->address = $address;
$this->base = $base;
$this->location = $location;
$this->fileName = $fileName;
@@ -420,7 +466,7 @@ class YellowPage
$this->set("language", $this->yellow->lookup->findLanguageFromFile($this->fileName,
$this->yellow->config->get("language")));
$this->set("theme", $this->yellow->lookup->findNameFromFile($this->fileName,
- $this->yellow->config->get("themeDir"), $this->yellow->config->get("theme"), ".css"));
+ $this->yellow->config->get("assetDir"), $this->yellow->config->get("theme"), ".css"));
$this->set("template", $this->yellow->lookup->findNameFromFile($this->fileName,
$this->yellow->config->get("templateDir"), $this->yellow->config->get("template"), ".html"));
$this->set("modified", date("Y-m-d H:i:s", $this->yellow->toolbox->getFileModified($this->fileName)));
@@ -433,11 +479,11 @@ class YellowPage
if($this->get("status")=="hidden") $this->available = false;
$this->set("pageRead", $this->yellow->lookup->normaliseUrl(
$this->yellow->config->get("serverScheme"),
- $this->yellow->config->get("serverName"),
+ $this->yellow->config->get("serverAddress"),
$this->yellow->config->get("serverBase"), $this->location));
$this->set("pageEdit", $this->yellow->lookup->normaliseUrl(
- $this->yellow->config->get("webinterfaceServerScheme"),
- $this->yellow->config->get("webinterfaceServerName"),
+ $this->yellow->config->get("serverScheme"),
+ $this->yellow->config->get("serverAddress"),
$this->yellow->config->get("serverBase"),
rtrim($this->yellow->config->get("webinterfaceLocation"), '/').$this->location));
$this->set("pageFile", $this->yellow->lookup->normaliseFile($this->fileName));
@@ -538,21 +584,12 @@ class YellowPage
$output = "<span class=\"".htmlspecialchars($name)."\">\n";
if($text=="version")
{
- $serverSoftware = $this->yellow->toolbox->getServerSoftware();
- $output .= "Yellow ".YellowCore::VERSION.", PHP ".PHP_VERSION.", $serverSoftware<br />\n";
- foreach($this->yellow->plugins->getData() as $key=>$value)
+ $serverVersion = $this->yellow->toolbox->getServerVersion();
+ $output .= "Yellow ".YellowCore::VERSION.", PHP ".PHP_VERSION.", $serverVersion<br />\n";
+ foreach(array_merge($this->yellow->plugins->getData(), $this->yellow->themes->getData()) as $key=>$value)
{
$output .= htmlspecialchars("$key $value")."<br />\n";
}
- foreach($this->yellow->themes->getData() as $key=>$value)
- {
- $output .= htmlspecialchars("$key $value")."<br />\n";
- }
- } else {
- foreach($this->yellow->config->getData($text) as $key=>$value)
- {
- $output .= htmlspecialchars(ucfirst($key).": ".$value)."<br />\n";
- }
}
$output .= "</span>\n";
if($this->parserSafeMode) $this->error(500, "Yellow '$text' is not available in safe mode!");
@@ -597,12 +634,15 @@ class YellowPage
{
$this->error(500, "Parser '".$this->get("parser")."' does not exist!");
}
- if($this->yellow->lookup->isNestedLocation($this->location, true)) $this->error(500, "Home folder may not contain subfolders!");
+ if($this->yellow->lookup->isNestedLocation($this->location, $this->fileName, true))
+ {
+ $this->error(500, "Folder '".dirname($this->fileName)."' may not contain subfolders!");
+ }
if($this->yellow->toolbox->isRequestSelf()) $this->error(500, "Rewrite module not enabled on this server!");
if($this->yellow->getRequestHandler()=="core" && $this->isExisting("redirect") && $this->statusCode==200)
{
- $location = $this->yellow->lookup->normaliseLocation($this->get("redirect"), $this->base, $this->location);
- $location = $this->yellow->lookup->normaliseUrl($this->serverScheme, $this->serverName, "", $location);
+ $location = $this->yellow->lookup->normaliseLocation($this->get("redirect"), $this->location);
+ $location = $this->yellow->lookup->normaliseUrl($this->scheme, $this->address, "", $location);
$this->clean(301, $location);
}
if($this->yellow->getRequestHandler()=="core" && !$this->isAvailable() && $this->statusCode==200)
@@ -759,10 +799,10 @@ class YellowPage
return $absoluteLocation ? $this->base.$this->location : $this->location;
}
- // Return page URL with server scheme and server name
+ // Return page URL
function getUrl()
{
- return $this->yellow->lookup->normaliseUrl($this->serverScheme, $this->serverName, $this->base, $this->location);
+ return $this->yellow->lookup->normaliseUrl($this->scheme, $this->address, $this->base, $this->location);
}
// Return page extra HTML data
@@ -779,10 +819,10 @@ class YellowPage
}
if($name=="header")
{
- if(is_file($this->yellow->config->get("themeDir").$this->get("theme").".css"))
+ if(is_file($this->yellow->config->get("assetDir").$this->get("theme").".css"))
{
$location = $this->yellow->config->get("serverBase").
- $this->yellow->config->get("themeLocation").$this->get("theme").".css";
+ $this->yellow->config->get("assetLocation").$this->get("theme").".css";
$output .= "<link rel=\"stylesheet\" type=\"text/css\" media=\"all\" href=\"".htmlspecialchars($location)."\" />\n";
}
if(is_file($this->yellow->config->get("assetDir").$this->get("theme").".js"))
@@ -1252,8 +1292,6 @@ class YellowPages
{
var $yellow; //access to API
var $pages; //scanned pages
- var $requestHandler; //request handler name
- var $snippetArgs; //requested snippet arguments
function __construct($yellow)
{
@@ -1268,8 +1306,8 @@ class YellowPages
{
if(defined("DEBUG") && DEBUG>=2) echo "YellowPages::scanLocation location:$location<br/>\n";
$this->pages[$location] = array();
- $serverScheme = $this->yellow->page->serverScheme;
- $serverName = $this->yellow->page->serverName;
+ $scheme = $this->yellow->page->scheme;
+ $address = $this->yellow->page->address;
$base = $this->yellow->page->base;
if(empty($location))
{
@@ -1278,7 +1316,7 @@ class YellowPages
{
list($rootLocation, $fileName) = explode(' ', $rootLocation, 2);
$page = new YellowPage($this->yellow);
- $page->setRequestInformation($serverScheme, $serverName, $base, $rootLocation, $fileName);
+ $page->setRequestInformation($scheme, $address, $base, $rootLocation, $fileName);
$page->parseData("", false, 0);
array_push($this->pages[$location], $page);
}
@@ -1287,7 +1325,7 @@ class YellowPages
foreach($fileNames as $fileName)
{
$page = new YellowPage($this->yellow);
- $page->setRequestInformation($serverScheme, $serverName, $base,
+ $page->setRequestInformation($scheme, $address, $base,
$this->yellow->lookup->findLocationFromFile($fileName), $fileName);
$page->parseData($this->yellow->toolbox->readFile($fileName, 4096), false, 0);
if(strlenb($page->rawData)<4096) $page->statusCode = 200;
@@ -1475,8 +1513,8 @@ class YellowFiles
{
if(defined("DEBUG") && DEBUG>=2) echo "YellowFiles::scanLocation location:$location<br/>\n";
$this->files[$location] = array();
- $serverScheme = $this->yellow->page->serverScheme;
- $serverName = $this->yellow->page->serverName;
+ $scheme = $this->yellow->page->scheme;
+ $address = $this->yellow->page->address;
$base = $this->yellow->config->get("serverBase");
if(empty($location))
{
@@ -1496,7 +1534,7 @@ class YellowFiles
foreach($fileNames as $fileName)
{
$file = new YellowPage($this->yellow);
- $file->setRequestInformation($serverScheme, $serverName, $base, "/".$fileName, $fileName);
+ $file->setRequestInformation($scheme, $address, $base, "/".$fileName, $fileName);
$file->parseData(null, false, 0);
array_push($this->files[$location], $file);
}
@@ -1507,7 +1545,7 @@ class YellowFiles
// Return page with media file information, null if not found
function find($location, $absoluteLocation = false)
{
- if($absoluteLocation) $location = substru($location, strlenu($this->yellow->page->base));
+ if($absoluteLocation) $location = substru($location, strlenu($this->yellow->config->get("serverBase")));
foreach($this->scanLocation($this->getParentLocation($location)) as $file)
{
if($file->location==$location)
@@ -1566,13 +1604,13 @@ class YellowFiles
// Return home location
function getHomeLocation($location)
{
- return "/".$this->yellow->config->get("mediaDir");
+ return $this->yellow->config->get("mediaLocation");
}
// Return parent location
function getParentLocation($location)
{
- $token = rtrim("/".$this->yellow->config->get("mediaDir"), '/');
+ $token = rtrim($this->yellow->config->get("mediaLocation"), '/');
if(preg_match("#^($token.*\/).+?$#", $location, $matches))
{
if($matches[1]!="$token/" || $this->yellow->lookup->isFileLocation($location)) $parentLocation = $matches[1];
@@ -1584,7 +1622,7 @@ class YellowFiles
// Return top-level location
function getParentTopLocation($location)
{
- $token = rtrim("/".$this->yellow->config->get("mediaDir"), '/');
+ $token = rtrim($this->yellow->config->get("mediaLocation"), '/');
if(preg_match("#^($token.+?\/)#", $location, $matches)) $parentTopLocation = $matches[1];
if(empty($parentTopLocation)) $parentTopLocation = "$token/";
return $parentTopLocation;
@@ -1606,16 +1644,17 @@ class YellowPlugins
}
// Load plugins
- function load()
+ function load($path = "")
{
- if(empty($this->yellow->pages->requestHandler)) //TODO: remove later, guard for old version
+ if(count($this->yellow->config->config)==0) //TODO: remove later, backwards compability for old Yellow version
{
$this->yellow->load();
return;
}
- $path = $this->yellow->config->get("pluginDir");
+ $path = empty($path) ? $this->yellow->config->get("pluginDir") : $path;
foreach($this->yellow->toolbox->getDirectoryEntries($path, "/^.*\.php$/", true, false) as $entry)
{
+ if(defined("DEBUG") && DEBUG>=3) echo "YellowPlugins::load file:$entry<br/>\n";
$this->modified = max($this->modified, filemtime($entry));
global $yellow;
require_once($entry);
@@ -1628,7 +1667,6 @@ class YellowPlugins
foreach($this->plugins as $key=>$value)
{
$this->plugins[$key]["obj"] = new $value["plugin"];
- if(defined("DEBUG") && DEBUG>=3) echo "YellowPlugins::load $value[plugin]:$value[version]<br/>\n";
if(method_exists($this->plugins[$key]["obj"], "onLoad")) $this->plugins[$key]["obj"]->onLoad($yellow);
}
}
@@ -1657,7 +1695,11 @@ class YellowPlugins
{
$data = array();
$data["YellowCore"] = YellowCore::VERSION;
- foreach($this->plugins as $key=>$value) $data[$value["plugin"]] = $value["version"];
+ foreach($this->plugins as $key=>$value)
+ {
+ if(empty($value["plugin"]) || empty($value["version"])) continue;
+ $data[$value["plugin"]] = $value["version"];
+ }
uksort($data, strnatcasecmp);
return $data;
}
@@ -1690,29 +1732,45 @@ class YellowThemes
}
// Load themes
- function load()
+ function load($path = "")
{
- $path = $this->yellow->config->get("themeDir");
+ $path = empty($path) ? $this->yellow->config->get("assetDir") : $path;
+ foreach($this->yellow->toolbox->getDirectoryEntries($path, "/^.*\.php$/", true, false) as $entry)
+ {
+ if(defined("DEBUG") && DEBUG>=3) echo "YellowThemes::load file:$entry<br/>\n";
+ $this->modified = max($this->modified, filemtime($entry));
+ global $yellow;
+ require_once($entry);
+ }
foreach($this->yellow->toolbox->getDirectoryEntries($path, "/^.*\.css$/", true, false) as $entry)
{
- $name = $this->yellow->lookup->normaliseName(basename($entry), true, true);
- $theme = $version = "";
+ if(defined("DEBUG") && DEBUG>=3) echo "YellowThemes::load file:$entry<br/>\n";
$this->modified = max($this->modified, filemtime($entry));
- $fileData = $this->yellow->toolbox->readFile($entry, 4096);
- foreach($this->yellow->toolbox->getTextLines($fileData) as $line)
- {
- preg_match("/^\/\*\s*(.*?)\s*:\s*(.*?)\s*\*\/$/", $line, $matches);
- if(lcfirst($matches[1])=="theme" && !strempty($matches[2])) $theme = $matches[2];
- if(lcfirst($matches[1])=="version" && !strempty($matches[2])) $version = $matches[2];
- if(!empty($line) && $line[0]!='/') break;
- }
- if(!empty($theme) && !empty($version))
- {
- $this->themes[$name] = array();
- $this->themes[$name]["theme"] = $theme;
- $this->themes[$name]["version"] = $version;
- if(defined("DEBUG") && DEBUG>=3) echo "YellowThemes::load $theme:$version<br/>\n";
- }
+ $name = $this->yellow->lookup->normaliseName(basename($entry), true, true);
+ $this->register($name, "", "");
+ }
+ $callback = function($a, $b)
+ {
+ return $a["priority"] - $b["priority"];
+ };
+ uasort($this->themes, $callback);
+ foreach($this->themes as $key=>$value)
+ {
+ $this->themes[$key]["obj"] = empty($value["theme"]) ? new stdClass : new $value["theme"];
+ if(method_exists($this->themes[$key]["obj"], "onLoad")) $this->themes[$key]["obj"]->onLoad($yellow);
+ }
+ }
+
+ // Register theme
+ function register($name, $theme, $version, $priority = 0)
+ {
+ if(!$this->isExisting($name))
+ {
+ if($priority==0) $priority = count($this->themes) + 10;
+ $this->themes[$name] = array();
+ $this->themes[$name]["theme"] = $theme;
+ $this->themes[$name]["version"] = $version;
+ $this->themes[$name]["priority"] = $priority;
}
}
@@ -1720,7 +1778,11 @@ class YellowThemes
function getData()
{
$data = array();
- foreach($this->themes as $key=>$value) $data[$value["theme"]] = $value["version"];
+ foreach($this->themes as $key=>$value)
+ {
+ if(empty($value["theme"]) || empty($value["version"])) continue;
+ $data[$value["theme"]] = $value["version"];
+ }
uksort($data, strnatcasecmp);
return $data;
}
@@ -2021,6 +2083,9 @@ class YellowText
class YellowLookup
{
var $yellow; //access to API
+ var $requestHandler; //request handler name
+ var $commandHandler; //command handler name
+ var $snippetArgs; //snippet arguments
function __construct($yellow)
{
@@ -2033,7 +2098,7 @@ class YellowLookup
list($pathRoot, $pathHome) = $this->detectFileSystem();
$this->yellow->config->set("contentRootDir", $pathRoot);
$this->yellow->config->set("contentHomeDir", $pathHome);
- date_default_timezone_set($this->yellow->config->get("serverTime"));
+ date_default_timezone_set($this->yellow->config->get("timezone"));
}
// Detect file system
@@ -2302,6 +2367,53 @@ class YellowLookup
return dirname($fileName)."/".$fileNamePrefix.$fileNameText;
}
+ // Return file path for media location
+ function findFileFromMedia($location)
+ {
+ if($this->isFileLocation($location))
+ {
+ $mediaLocationLength = strlenu($this->yellow->config->get("mediaLocation"));
+ if(substru($location, 0, $mediaLocationLength)==$this->yellow->config->get("mediaLocation"))
+ {
+ $fileName = $this->yellow->config->get("mediaDir").substru($location, 7);
+ }
+ }
+ return $fileName;
+ }
+
+ // Return file path for system location
+ function findFileFromSystem($location)
+ {
+ if(preg_match("/\.(css|ico|js|jpg|png|svg|txt|woff)$/", $location))
+ {
+ $pluginLocationLength = strlenu($this->yellow->config->get("pluginLocation"));
+ $themeLocationLength = strlenu($this->yellow->config->get("themeLocation"));
+ if(substru($location, 0, $pluginLocationLength)==$this->yellow->config->get("pluginLocation")) {
+ $fileName = $this->yellow->config->get("pluginDir").substru($location, $pluginLocationLength);
+ } else if(substru($location, 0, $themeLocationLength)==$this->yellow->config->get("themeLocation")) {
+ $fileName = $this->yellow->config->get("themeDir").substru($location, $themeLocationLength);
+ } else if($location=="/".$this->yellow->config->get("robotsFile")) {
+ $fileName = $this->yellow->config->get("configDir").$this->yellow->config->get("robotsFile");
+ } else if($location=="/".$this->yellow->config->get("faviconFile")) {
+ $fileName = $this->yellow->config->get("assetDir").$this->yellow->config->get("siteicon").".png";
+ }
+ }
+ return $fileName;
+ }
+
+ // Return file path for static file, if possible
+ function findFileStatic($location, $fileName, $cacheable)
+ {
+ if($cacheable)
+ {
+ $location .= $this->yellow->toolbox->getLocationArgs();
+ $fileNameStatic = rtrim($this->yellow->config->get("staticDir"), '/').$location;
+ if(!$this->isFileLocation($location)) $fileNameStatic .= $this->yellow->config->get("staticDefaultFile");
+ if(is_readable($fileNameStatic)) $fileName = $fileNameStatic;
+ }
+ return $fileName;
+ }
+
// Return file path for new page
function findFilePageNew($fileName, $prefix = "")
{
@@ -2328,19 +2440,6 @@ class YellowLookup
return $path;
}
- // Return file path for static file, if possible
- function findFileStatic($location, $fileName, $cacheable)
- {
- if($cacheable && PHP_SAPI!="cli")
- {
- $location .= $this->yellow->toolbox->getLocationArgs();
- $fileNameStatic = rtrim($this->yellow->config->get("staticDir"), '/').$location;
- if(!$this->isFileLocation($location)) $fileNameStatic .= $this->yellow->config->get("staticDefaultFile");
- if(is_readable($fileNameStatic)) $fileName = $fileNameStatic;
- }
- return $fileName;
- }
-
// Normalise file/directory/other name
function normaliseName($text, $removePrefix = true, $removeExtension = false, $filterStrict = false)
{
@@ -2362,23 +2461,36 @@ class YellowLookup
return $fileName;
}
+ // Normalise array, make keys with same upper/lower case
+ function normaliseUpperLower($input)
+ {
+ $array = array();
+ foreach($input as $key=>$value)
+ {
+ if(empty($key) || strempty($value)) continue;
+ $keySearch = strtoloweru($key);
+ foreach($array as $keyNew=>$valueNew) if(strtoloweru($keyNew)==$keySearch) { $key = $keyNew; break; }
+ $array[$key] += $value;
+ }
+ return $array;
+ }
+
// Normalise location, make absolute location
- function normaliseLocation($location, $pageBase, $pageLocation, $staticLocation = "", $filterStrict = true)
+ function normaliseLocation($location, $pageLocation, $filterStrict = true)
{
if(!preg_match("/^\w+:/", trim(html_entity_decode($location, ENT_QUOTES, "UTF-8"))))
{
- if(empty($staticLocation) || !preg_match("#^$staticLocation#", $location))
+ $pageBase = $this->yellow->page->base;
+ $mediaBase = $this->yellow->config->get("serverBase").$this->yellow->config->get("mediaLocation");
+ if(preg_match("/^\#/", $location))
{
- if(preg_match("/^\#/", $location))
- {
- $location = $pageBase.$pageLocation.$location;
- } else if(!preg_match("/^\//", $location)) {
- $location = $this->getDirectoryLocation($pageBase.$pageLocation).$location;
- } else if(!preg_match("#^$pageBase#", $location)) {
- $location = $pageBase.$location;
- }
- $location = strreplaceu(':', $this->yellow->toolbox->getLocationArgsSeparator(), $location);
+ $location = $pageBase.$pageLocation.$location;
+ } else if(!preg_match("/^\//", $location)) {
+ $location = $this->getDirectoryLocation($pageBase.$pageLocation).$location;
+ } else if(!preg_match("#^($pageBase|$mediaBase)#", $location)) {
+ $location = $pageBase.$location;
}
+ $location = strreplaceu(':', $this->yellow->toolbox->getLocationArgsSeparator(), $location);
} else {
if($filterStrict && !preg_match("/^(http|https|ftp|mailto):/", $location)) $location = "error-xss-filter";
}
@@ -2386,17 +2498,30 @@ class YellowLookup
}
// Normalise URL, make absolute URL
- function normaliseUrl($serverScheme, $serverName, $base, $location)
+ function normaliseUrl($scheme, $address, $base, $location, $filterStrict = true)
{
if(!preg_match("/^\w+:/", $location))
{
- $url = "$serverScheme://$serverName$base$location";
+ $url = "$scheme://$address$base$location";
} else {
+ if($filterStrict && !preg_match("/^(http|https|ftp|mailto):/", $location)) $location = "error-xss-filter";
$url = $location;
}
return $url;
}
+ // Return URL information
+ function getUrlInformation($url)
+ {
+ if(preg_match("#^(\w+)://([^/]+)(.*)$#", rtrim($url, '/'), $matches))
+ {
+ $scheme = $matches[1];
+ $address = $matches[2];
+ $base = $matches[3];
+ }
+ return array($scheme, $address, $base);
+ }
+
// Return directory location
function getDirectoryLocation($location)
{
@@ -2429,12 +2554,12 @@ class YellowLookup
}
// Check if location contains nested directories
- function isNestedLocation($location, $checkHomeLocation = false)
+ function isNestedLocation($location, $fileName, $checkHomeLocation = false)
{
$nested = false;
if(!$checkHomeLocation || $location==$this->yellow->pages->getHomeLocation($location))
{
- $path = $this->yellow->lookup->findFileFromLocation($location, true);
+ $path = dirname($fileName);
if(count($this->yellow->toolbox->getDirectoryEntries($path, "/.*/", true, true, false))) $nested = true;
}
return $nested;
@@ -2476,15 +2601,6 @@ class YellowLookup
return $active;
}
- // Check if location is valid
- function isValidLocation($location)
- {
- $string = "";
- $tokens = explode('/', $location);
- for($i=1; $i<count($tokens); ++$i) $string .= '/'.$this->normaliseName($tokens[$i]);
- return $location==$string;
- }
-
// Check if file is valid
function isValidFile($fileName)
{
@@ -2521,50 +2637,50 @@ class YellowLookup
// Yellow toolbox with helpers
class YellowToolbox
{
- // Return server software
- function getServerSoftware()
+ // Return server version from current HTTP request
+ function getServerVersion()
{
- $serverSoftware = strtoupperu(PHP_SAPI);
- if(preg_match("/^(\S+)/", $_SERVER["SERVER_SOFTWARE"], $matches)) $serverSoftware = $matches[1];
- return $serverSoftware." ".PHP_OS;
+ $serverVersion = strtoupperu(PHP_SAPI)." ".PHP_OS;
+ if(preg_match("/^(\S+)/", $_SERVER["SERVER_SOFTWARE"], $matches)) $serverVersion = $matches[1]." ".PHP_OS;
+ return $serverVersion;
}
// Return server URL from current HTTP request
function getServerUrl()
{
- $serverScheme = $this->getServerScheme();
- $serverName = $this->getServerName();
- $serverBase = $this->getServerBase();
- return "$serverScheme://$serverName$serverBase/";
+ $scheme = $this->getScheme();
+ $address = $this->getAddress();
+ $base = $this->getBase();
+ return "$scheme://$address$base/";
}
- // Return server scheme from current HTTP request
- function getServerScheme()
+ // Return scheme from current HTTP request
+ function getScheme()
{
- $serverScheme = "";
+ $scheme = "";
if(preg_match("/^HTTP\//", $_SERVER["SERVER_PROTOCOL"]))
{
$secure = isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"]!="off";
- $serverScheme = $secure ? "https" : "http";
+ $scheme = $secure ? "https" : "http";
}
- return $serverScheme;
+ return $scheme;
}
- // Return server name from current HTTP request
- function getServerName()
+ // Return address from current HTTP request
+ function getAddress()
{
- $serverName = $_SERVER["SERVER_NAME"];
- $serverPort = $_SERVER["SERVER_PORT"];
- if($serverPort!=80 && $serverPort!=443) $serverName .= ":$serverPort";
- return $serverName;
+ $address = $_SERVER["SERVER_NAME"];
+ $port = $_SERVER["SERVER_PORT"];
+ if($port!=80 && $port!=443) $address .= ":$port";
+ return $address;
}
- // Return server base from current HTTP request
- function getServerBase()
+ // Return base from current HTTP request
+ function getBase()
{
- $serverBase = "";
- if(preg_match("/^(.*)\//", $_SERVER["SCRIPT_NAME"], $matches)) $serverBase = rtrim($matches[1], '/');
- return $serverBase;
+ $base = "";
+ if(preg_match("/^(.*)\//", $_SERVER["SCRIPT_NAME"], $matches)) $base = rtrim($matches[1], '/');
+ return $base;
}
// Return location from current HTTP request
@@ -2747,30 +2863,16 @@ class YellowToolbox
}
return $text;
}
-
- // Normalise array elements with different upper and lower case
- function normaliseUpperLower($input)
- {
- $array = array();
- foreach($input as $key=>$value)
- {
- if(empty($key) || strempty($value)) continue;
- $keySearch = strtoloweru($key);
- foreach($array as $keyNew=>$valueNew) if(strtoloweru($keyNew)==$keySearch) { $key = $keyNew; break; }
- $array[$key] += $value;
- }
- return $array;
- }
- // Return server time zone
- function getServerTime()
+ // Return timezone
+ function getTimezone()
{
- $serverTime = @date_default_timezone_get();
- if(PHP_OS=="Darwin" && $serverTime=="UTC")
+ $timezone = @date_default_timezone_get();
+ if(PHP_OS=="Darwin" && $timezone=="UTC")
{
- if(preg_match("#zoneinfo/(.*)#", @readlink("/etc/localtime"), $matches)) $serverTime = $matches[1];
+ if(preg_match("#zoneinfo/(.*)#", @readlink("/etc/localtime"), $matches)) $timezone = $matches[1];
}
- return $serverTime;
+ return $timezone;
}
// Return human readable HTTP server status
diff --git a/system/plugins/image.php b/system/plugins/image.php
@@ -1,11 +1,11 @@
<?php
-// Copyright (c) 2013-2016 Datenstrom, http://datenstrom.se
+// Copyright (c) 2013-2017 Datenstrom, http://datenstrom.se
// This file may be used and distributed under the terms of the public license.
// Image plugin
class YellowImage
{
- const VERSION = "0.6.7";
+ const VERSION = "0.6.8";
var $yellow; //access to API
var $graphicsLibrary; //graphics library support? (boolean)
@@ -39,7 +39,8 @@ class YellowImage
if(empty($height)) $height = $width;
list($src, $width, $height) = $this->getImageInfo($this->yellow->config->get("imageDir").$name, $width, $height);
} else {
- $src = $this->yellow->lookup->normaliseLocation($name, $page->base, $page->location);
+ if(empty($alt)) $alt = $this->yellow->config->get("imageAlt");
+ $src = $this->yellow->lookup->normaliseUrl("", "", "", $name);
$width = $height = 0;
}
$output = "<img src=\"".htmlspecialchars($src)."\"";
diff --git a/system/plugins/markdown.php b/system/plugins/markdown.php
@@ -1,11 +1,11 @@
<?php
-// Copyright (c) 2013-2016 Datenstrom, http://datenstrom.se
+// Copyright (c) 2013-2017 Datenstrom, http://datenstrom.se
// This file may be used and distributed under the terms of the public license.
// Markdown plugin
class YellowMarkdown
{
- const VERSION = "0.6.4";
+ const VERSION = "0.6.5";
var $yellow; //access to API
// Handle initialisation
@@ -37,8 +37,7 @@ class YellowMarkdownParser extends MarkdownExtraParser
$this->no_markup = $page->parserSafeMode;
$this->url_filter_func = function($url) use ($yellow, $page)
{
- return $yellow->lookup->normaliseLocation($url, $page->base, $page->location,
- $yellow->config->get("serverBase").$yellow->config->get("imageLocation"),
+ return $yellow->lookup->normaliseLocation($url, $page->location,
$page->parserSafeMode && $page->statusCode==200);
};
parent::__construct();
diff --git a/system/plugins/update.php b/system/plugins/update.php
@@ -5,8 +5,9 @@
// Update plugin
class YellowUpdate
{
- const VERSION = "0.6.13";
+ const VERSION = "0.6.14";
var $yellow; //access to API
+ var $updates; //number of updates
// Handle initialisation
function onLoad($yellow)
@@ -16,24 +17,67 @@ class YellowUpdate
$this->yellow->config->setDefault("updateThemesUrl", "https://github.com/datenstrom/yellow-themes");
$this->yellow->config->setDefault("updateInformationFile", "update.ini");
$this->yellow->config->setDefault("updateVersionFile", "version.ini");
- $this->yellow->config->setDefault("updateNotification", "none");
+ $this->yellow->config->setDefault("updateResourceFile", "resource.ini");
}
- // Handle update
- function onUpdate($name)
+ // Handle startup
+ function onStartup($update)
{
- if(empty($name)) $this->processUpdateNotification();
+ if($this->yellow->config->isExisting("updateNotification")) //TODO: remove later, cleans old config
+ {
+ $update = true;
+ $fileNameConfig = $this->yellow->config->get("configDir").$this->yellow->config->get("configFile");
+ $fileData = $this->yellow->toolbox->readFile($fileNameConfig);
+ foreach($this->yellow->toolbox->getTextLines($fileData) as $line)
+ {
+ preg_match("/^\s*(.*?)\s*:\s*(.*?)\s*$/", $line, $matches);
+ if(!empty($matches[1]) && is_null($this->yellow->config->configDefaults[$matches[1]]) &&
+ $line[0]!='#' && substru($line, 0, 5)!="Login")
+ {
+ $fileDataNew .= "# $line";
+ } else {
+ $fileDataNew .= $line;
+ }
+ }
+ $this->yellow->toolbox->createFile($fileNameConfig, $fileDataNew);
+ }
+ if($update) //TODO: remove later, converts old Yellow version
+ {
+ $fileNameScript = "yellow.php";
+ if(filesize($fileNameScript)==591)
+ {
+ $fileData = $this->yellow->toolbox->readFile($fileNameScript);
+ $fileData = preg_replace("#yellow->plugins->load\(\)#", "yellow->load()", $fileData);
+ $this->yellow->toolbox->createFile($fileNameScript, $fileData);
+ }
+ }
+ if($update) //TODO: remove later, imports old file format
+ {
+ $path = $this->yellow->config->get("themeDir");
+ foreach($this->yellow->toolbox->getDirectoryEntries($path, "/^.*\.css$/", true, false) as $entry)
+ {
+ $fileNameAsset = $this->yellow->config->get("assetDir").basename($entry);
+ if(!is_file($fileNameAsset))
+ {
+ $fileData = $this->yellow->toolbox->readFile($entry);
+ $fileData = preg_replace("#url\(assets/(.*?)\)#", "url($1)", $fileData);
+ $this->yellow->toolbox->createFile($fileNameAsset, $fileData);
+ }
+ $this->yellow->toolbox->deleteFile($entry, $this->yellow->config->get("trashDir"));
+ $_GET["clean-url"] = "software-has-been-updated";
+ }
+ }
}
// Handle request
- function onRequest($serverScheme, $serverName, $base, $location, $fileName)
+ function onRequest($scheme, $address, $base, $location, $fileName)
{
$statusCode = 0;
- if($this->isInstallationMode())
+ if($this->yellow->config->get("installationMode"))
{
- $statusCode = $this->processRequestInstallationMode($serverScheme, $serverName, $base, $location, $fileName);
+ $statusCode = $this->processRequestInstallationMode($scheme, $address, $base, $location, $fileName);
} else {
- $statusCode = $this->processRequestInstallationPending($serverScheme, $serverName, $base, $location, $fileName);
+ $statusCode = $this->processRequestInstallationPending($scheme, $address, $base, $location, $fileName);
}
return $statusCode;
}
@@ -54,7 +98,7 @@ class YellowUpdate
// Handle command help
function onCommandHelp()
{
- return "update [FEATURE]";
+ return "update [OPTION FEATURE]";
}
// Clean downloads
@@ -78,30 +122,82 @@ class YellowUpdate
// Update website
function updateCommand($args)
{
- list($command, $feature, $option) = $args;
- list($statusCode, $data) = $this->getSoftwareUpdates($feature);
- if(!empty($data))
+ list($command, $option, $feature) = $args;
+ if(empty($option) || $option=="normal" || $option=="force")
{
- foreach($data as $key=>$value)
+ $force = $option=="force";
+ list($statusCode, $data) = $this->detectSoftware($force, $feature);
+ if($statusCode!=200 || !empty($data))
{
- list($version) = explode(',', $value);
- echo "$key $version\n";
+ $this->updates = 0;
+ if($statusCode==200) $statusCode = $this->downloadSoftware($data);
+ if($statusCode==200) $statusCode = $this->updateSoftware($force);
+ if($statusCode>=400) echo "ERROR updating files: ".$this->yellow->page->get("pageError")."\n";
+ echo "Yellow $command: Website ".($statusCode!=200 ? "not " : "")."updated";
+ echo ", $this->updates update".($this->updates!=1 ? 's' : '')." installed\n";
+ } else {
+ echo "Your website is up to date\n";
}
- if($statusCode==200) $statusCode = $this->downloadSoftware($data);
- if($statusCode==200) $statusCode = $this->updateSoftware($option);
- if($statusCode!=200) echo "ERROR updating files: ".$this->yellow->page->get("pageError")."\n";
- echo "Yellow $command: Website ".($statusCode!=200 ? "not " : "")."updated\n";
} else {
- if($statusCode!=200) echo "ERROR updating files: ".$this->yellow->page->get("pageError")."\n";
- echo "Yellow $command: No updates available\n";
+ $statusCode = 400;
+ echo "Yellow $command: Invalid arguments\n";
}
return $statusCode;
}
+ // Detect software
+ function detectSoftware($force, $feature)
+ {
+ $data = array();
+ list($statusCodeCurrent, $dataCurrent) = $this->getSoftwareVersion();
+ list($statusCodeLatest, $dataLatest) = $this->getSoftwareVersion(true, true);
+ list($statusCodeModified, $dataModified) = $this->getSoftwareModified();
+ $statusCode = max($statusCodeCurrent, $statusCodeLatest, $statusCodeModified);
+ if(empty($feature))
+ {
+ foreach($dataCurrent as $key=>$value)
+ {
+ list($version) = explode(',', $dataLatest[$key]);
+ if(strnatcasecmp($dataCurrent[$key], $version)<0) $data[$key] = $dataLatest[$key];
+ if(!is_null($dataModified[$key]) && !empty($version) && $force) $data[$key] = $dataLatest[$key];
+ }
+ } else {
+ foreach($dataCurrent as $key=>$value)
+ {
+ list($version) = explode(',', $dataLatest[$key]);
+ if(strtoloweru($key)==strtoloweru($feature) && !empty($version))
+ {
+ $data[$key] = $dataLatest[$key];
+ $dataModified = array_intersect_key($dataModified, $data);
+ break;
+ }
+ }
+ if(empty($data))
+ {
+ $statusCode = 500;
+ $this->yellow->page->error($statusCode, "Can't find feature '$feature'!");
+ }
+ }
+ if($statusCode==200)
+ {
+ foreach(array_merge($dataModified, $data) as $key=>$value)
+ {
+ list($version) = explode(',', $value);
+ if(is_null($dataModified[$key]) || $force)
+ {
+ echo "$key $version\n";
+ } else {
+ echo "$key $version has been modified - Force update\n";
+ }
+ }
+ }
+ return array($statusCode, $data);
+ }
+
// Download software
function downloadSoftware($data)
{
- $statusCode = 0;
+ $statusCode = 200;
$path = $this->yellow->config->get("pluginDir");
$fileExtension = $this->yellow->config->get("downloadExtension");
foreach($data as $key=>$value)
@@ -132,31 +228,40 @@ class YellowUpdate
}
// Update software
- function updateSoftware($option = "")
+ function updateSoftware($force = false)
{
- $statusCode = 0;
+ $statusCode = 200;
$path = $this->yellow->config->get("pluginDir");
foreach($this->yellow->toolbox->getDirectoryEntries($path, "/^.*\.zip$/", true, false) as $entry)
{
- $statusCode = max($statusCode, $this->updateSoftwareArchive($entry, $option));
+ $statusCode = max($statusCode, $this->updateSoftwareArchive($entry, $force));
+ if(!$this->yellow->toolbox->deleteFile($entry))
+ {
+ $statusCode = 500;
+ $this->yellow->page->error($statusCode, "Can't delete file '$entry'!");
+ }
}
$path = $this->yellow->config->get("themeDir");
foreach($this->yellow->toolbox->getDirectoryEntries($path, "/^.*\.zip$/", true, false) as $entry)
{
- $statusCode = max($statusCode, $this->updateSoftwareArchive($entry, $option));
+ $statusCode = max($statusCode, $this->updateSoftwareArchive($entry, $force));
+ if(!$this->yellow->toolbox->deleteFile($entry))
+ {
+ $statusCode = 500;
+ $this->yellow->page->error($statusCode, "Can't delete file '$entry'!");
+ }
}
return $statusCode;
}
// Update software from archive
- function updateSoftwareArchive($path, $option = "")
+ function updateSoftwareArchive($path, $force = false)
{
- $statusCode = 0;
+ $statusCode = 200;
$zip = new ZipArchive();
if($zip->open($path)===true)
{
if(defined("DEBUG") && DEBUG>=2) echo "YellowUpdate::updateSoftwareArchive file:$path<br/>\n";
- if(strtoloweru($option)=="force") $force = true;
if(preg_match("#^(.*\/).*?$#", $zip->getNameIndex(0), $matches)) $pathBase = $matches[1];
$fileData = $zip->getFromName($pathBase.$this->yellow->config->get("updateInformationFile"));
foreach($this->yellow->toolbox->getTextLines($fileData) as $line)
@@ -193,11 +298,10 @@ class YellowUpdate
$zip->close();
if($statusCode==200) $statusCode = $this->updateSoftwareNew($software);
if($statusCode==200) $statusCode = $this->updateSoftwareNotification($software);
- }
- if(!$this->yellow->toolbox->deleteFile($path))
- {
+ ++$this->updates;
+ } else {
$statusCode = 500;
- $this->yellow->page->error($statusCode, "Can't delete file '$path'!");
+ $this->yellow->page->error(500, "Can't open file '$path'!");
}
return $statusCode;
}
@@ -309,12 +413,12 @@ class YellowUpdate
function updateSoftwareNotification($software)
{
$statusCode = 200;
- $updateNotification = $this->yellow->config->get("updateNotification");
- if($updateNotification=="none") $updateNotification = "";
- if(!empty($updateNotification)) $updateNotification .= ",";
- $updateNotification .= $software;
+ $startupUpdateNotification = $this->yellow->config->get("startupUpdateNotification");
+ if($startupUpdateNotification=="none") $startupUpdateNotification = "";
+ if(!empty($startupUpdateNotification)) $startupUpdateNotification .= ",";
+ $startupUpdateNotification .= $software;
$fileNameConfig = $this->yellow->config->get("configDir").$this->yellow->config->get("configFile");
- if(!$this->yellow->config->update($fileNameConfig, array("updateNotification" => $updateNotification)))
+ if(!$this->yellow->config->update($fileNameConfig, array("startupUpdateNotification" => $startupUpdateNotification)))
{
$statusCode = 500;
$this->yellow->page->error(500, "Can't write file '$fileNameConfig'!");
@@ -322,17 +426,21 @@ class YellowUpdate
return $statusCode;
}
- // Update software features
- function updateSoftwareFeatures($feature)
+ // Update installation features
+ function updateInstallationFeatures($feature)
{
$statusCode = 200;
$path = $this->yellow->config->get("pluginDir");
$regex = "/^.*\\".$this->yellow->config->get("installationExtension")."$/";
foreach($this->yellow->toolbox->getDirectoryEntries($path, $regex, true, false) as $entry)
{
- if(stristr(basename($entry), $feature))
+ if(preg_match("/^(.*?)-(.*?)\./", basename($entry), $matches))
{
- $statusCode = max($statusCode, $this->updateSoftwareArchive($entry));
+ if(strtoloweru($matches[2])==strtoloweru($feature))
+ {
+ $statusCode = max($statusCode, $this->updateSoftwareArchive($entry));
+ break;
+ }
}
}
if($statusCode==200)
@@ -345,21 +453,6 @@ class YellowUpdate
return $statusCode;
}
- // Process update notification for recently installed software
- function processUpdateNotification()
- {
- if($this->yellow->config->get("updateNotification")!="none")
- {
- $tokens = explode(',', $this->yellow->config->get("updateNotification"));
- foreach($this->yellow->plugins->plugins as $key=>$value)
- {
- if(in_array($value["plugin"], $tokens) && method_exists($value["obj"], "onUpdate")) $value["obj"]->onUpdate($key);
- }
- $fileNameConfig = $this->yellow->config->get("configDir").$this->yellow->config->get("configFile");
- $this->yellow->config->update($fileNameConfig, array("updateNotification" => "none"));
- }
- }
-
// Process command to install pending software
function processCommandInstallationPending($args)
{
@@ -367,26 +460,23 @@ class YellowUpdate
if($this->isSoftwarePending())
{
$statusCode = $this->updateSoftware();
- if($statusCode!=0)
- {
- if($statusCode!=200) echo "ERROR updating files: ".$this->yellow->page->get("pageError")."\n";
- echo "Yellow has ".($statusCode!=200 ? "not " : "")."been updated: Please run command again\n";
- }
+ if($statusCode!=200) echo "ERROR updating files: ".$this->yellow->page->get("pageError")."\n";
+ echo "Yellow has ".($statusCode!=200 ? "not " : "")."been updated: Please run command again\n";
}
return $statusCode;
}
// Process request to install pending software
- function processRequestInstallationPending($serverScheme, $serverName, $base, $location, $fileName)
+ function processRequestInstallationPending($scheme, $address, $base, $location, $fileName)
{
$statusCode = 0;
- if($this->yellow->lookup->isContentFile($fileName) && $this->isSoftwarePending())
+ if($this->yellow->lookup->isContentFile($fileName) && !$this->yellow->isCommandLine() && $this->isSoftwarePending())
{
$statusCode = $this->updateSoftware();
if($statusCode==200)
{
$statusCode = 303;
- $location = $this->yellow->lookup->normaliseUrl($serverScheme, $serverName, $base, $location);
+ $location = $this->yellow->lookup->normaliseUrl($scheme, $address, $base, $location);
$this->yellow->sendStatus($statusCode, $location);
}
}
@@ -394,14 +484,14 @@ class YellowUpdate
}
// Process request to install website
- function processRequestInstallationMode($serverScheme, $serverName, $base, $location, $fileName)
+ function processRequestInstallationMode($scheme, $address, $base, $location, $fileName)
{
$statusCode = 0;
- if($this->yellow->lookup->isContentFile($fileName) && $this->isInstallationMode())
+ if($this->yellow->lookup->isContentFile($fileName) && !$this->yellow->isCommandLine())
{
$this->yellow->pages->pages["root/"] = array();
$this->yellow->page = new YellowPage($this->yellow);
- $this->yellow->page->setRequestInformation($serverScheme, $serverName, $base, $location, $fileName);
+ $this->yellow->page->setRequestInformation($scheme, $address, $base, $location, $fileName);
$this->yellow->page->parseData($this->getRawDataInstallation(), false, 404);
$this->yellow->page->parserSafeMode = false;
$this->yellow->page->parseContent();
@@ -435,7 +525,7 @@ class YellowUpdate
{
if(!empty($feature))
{
- $status = $this->updateSoftwareFeatures($feature)==200 ? "ok" : "error";
+ $status = $this->updateInstallationFeatures($feature)==200 ? "ok" : "error";
if($status=="error") $this->yellow->page->error(500, "Can't install feature '$feature'!");
}
}
@@ -449,7 +539,7 @@ class YellowUpdate
if($status=="done")
{
$statusCode = 303;
- $location = $this->yellow->lookup->normaliseUrl($serverScheme, $serverName, $base, $location);
+ $location = $this->yellow->lookup->normaliseUrl($scheme, $address, $base, $location);
$this->yellow->sendStatus($statusCode, $location);
} else {
$statusCode = $this->yellow->sendPage();
@@ -482,10 +572,10 @@ class YellowUpdate
}
$rawData .= "</p>\n";
}
- if(count($this->getSoftwareFeatures())>1)
+ if(count($this->getInstallationFeatures())>1)
{
$rawData .= "<p>".$this->yellow->text->get("webinterfaceInstallationFeature")."<p>";
- foreach($this->getSoftwareFeatures() as $feature)
+ foreach($this->getInstallationFeatures() as $feature)
{
$checked = $feature=="website" ? " checked=\"checked\"" : "";
$rawData .= "<label for=\"$feature\"><input type=\"radio\" name=\"feature\" id=\"$feature\" value=\"$feature\"$checked> ".ucfirst($feature)."</label><br />";
@@ -515,16 +605,14 @@ class YellowUpdate
if(!$this->yellow->config->isExisting($key)) continue;
$data[$key] = trim($value);
}
- $data["# serverScheme"] = $this->yellow->toolbox->getServerScheme();
- $data["# serverName"] = $this->yellow->toolbox->getServerName();
- $data["# serverBase"] = $this->yellow->toolbox->getServerBase();
- $data["# serverTime"] = $this->yellow->toolbox->getServerTime();
+ $data["timezone"] = $this->yellow->toolbox->getTimezone();
+ $data["staticUrl"] = $this->yellow->toolbox->getServerUrl();
$data["installationMode"] = "0";
return $data;
}
- // Return software features
- function getSoftwareFeatures()
+ // Return installation features
+ function getInstallationFeatures()
{
$data = array("website");
$path = $this->yellow->config->get("pluginDir");
@@ -539,25 +627,6 @@ class YellowUpdate
return $data;
}
- // Return software updates
- function getSoftwareUpdates($feature)
- {
- $data = array();
- list($statusCode, $dataCurrent) = $this->getSoftwareVersion();
- list($statusCode, $dataLatest) = $this->getSoftwareVersion(true, true);
- foreach($dataCurrent as $key=>$value)
- {
- list($version) = explode(',', $dataLatest[$key]);
- if(empty($feature))
- {
- if(strnatcasecmp($dataCurrent[$key], $version)<0) $data[$key] = $dataLatest[$key];
- } else {
- if(stristr($key, $feature) && $version) $data[$key] = $dataLatest[$key];
- }
- }
- return array($statusCode, $data);
- }
-
// Return software version
function getSoftwareVersion($latest = false, $rawFormat = false)
{
@@ -587,6 +656,46 @@ class YellowUpdate
}
return array($statusCode, $data);
}
+
+ // Return software modification
+ function getSoftwareModified()
+ {
+ $data = array();
+ $dataCurrent = array_merge($this->yellow->plugins->getData(), $this->yellow->themes->getData());
+ $urlPlugins = $this->yellow->config->get("updatePluginsUrl")."/raw/master/".$this->yellow->config->get("updateResourceFile");
+ $urlThemes = $this->yellow->config->get("updateThemesUrl")."/raw/master/".$this->yellow->config->get("updateResourceFile");
+ list($statusCodePlugins, $fileDataPlugins) = $this->getSoftwareFile($urlPlugins);
+ list($statusCodeThemes, $fileDataThemes) = $this->getSoftwareFile($urlThemes);
+ $statusCode = max($statusCodePlugins, $statusCodeThemes);
+ if($statusCode==200)
+ {
+ foreach($this->yellow->toolbox->getTextLines($fileDataPlugins."\n".$fileDataThemes) as $line)
+ {
+ preg_match("/^\s*(.*?)\s*:\s*(.*?)\s*$/", $line, $matches);
+ if(!empty($matches[1]) && !empty($matches[2]))
+ {
+ list($softwareNew) = explode('/', $matches[1]);
+ list($fileName, $flags) = explode(',', $matches[2], 2);
+ if($software!=$softwareNew)
+ {
+ $software = $softwareNew;
+ list($fileName, $flags) = explode(',', $matches[2], 2);
+ $lastPublished = $this->yellow->toolbox->getFileModified($fileName);
+ }
+ if($this->yellow->lookup->isValidFile($fileName) && !is_null($dataCurrent[$software]))
+ {
+ $lastModified = $this->yellow->toolbox->getFileModified($fileName);
+ if(preg_match("/update/i", $flags) && preg_match("/careful/i", $flags) && $lastModified!=$lastPublished)
+ {
+ $data[$software] = $dataCurrent[$software];
+ if(defined("DEBUG") && DEBUG>=2) echo "YellowUpdate::getSoftwareModified detected file:$fileName<br/>\n";
+ }
+ }
+ }
+ }
+ }
+ return array($statusCode, $data);
+ }
// Return software file
function getSoftwareFile($url)
@@ -641,12 +750,6 @@ class YellowUpdate
$data = array_merge($this->yellow->plugins->getData(), $this->yellow->themes->getData());
return !is_null($data[$software]);
}
-
- // Check if installation mode
- function isInstallationMode()
- {
- return $this->yellow->config->get("installationMode") && PHP_SAPI!="cli";
- }
}
$yellow->plugins->register("update", "YellowUpdate", YellowUpdate::VERSION, 1);
diff --git a/system/plugins/webinterface.css b/system/plugins/webinterface.css
@@ -1,4 +1,4 @@
-/* Yellow web interface 0.6.19 */
+/* Yellow web interface 0.6.20 */
.yellow-bar { position:relative; overflow:hidden; height:2em; margin-bottom:10px; }
.yellow-bar-left { display:block; float:left; }
diff --git a/system/plugins/webinterface.js b/system/plugins/webinterface.js
@@ -4,8 +4,8 @@
// Yellow API
var yellow =
{
- version: "0.6.19",
- action: function(action) { yellow.webinterface.action(action, "none"); },
+ version: "0.6.20",
+ action: function(action, status, args) { yellow.webinterface.action(action, status, args); },
onLoad: function() { yellow.webinterface.loadInterface(); },
onClick: function(e) { yellow.webinterface.hidePanesOnClick(yellow.toolbox.getEventElement(e)); },
onKeydown: function(e) { yellow.webinterface.hidePanesOnKeydown(yellow.toolbox.getEventKeycode(e)); },
@@ -22,9 +22,10 @@ yellow.webinterface =
intervalId: 0, //timer interval ID
// Handle action
- action: function(action, status)
+ action: function(action, status, args)
{
- if(yellow.config.debug) console.log("yellow.webinterface.action action:"+action+" status:"+status);
+ status = status ? status : "none";
+ args = args ? args : "none";
switch(action)
{
case "login": this.showPane("yellow-pane-login", action, status); break;
@@ -37,7 +38,7 @@ yellow.webinterface =
case "reconfirm": this.showPane("yellow-pane-settings", action, status); break;
case "change": this.showPane("yellow-pane-settings", action, status); break;
case "version": this.showPane("yellow-pane-version", action, status); break;
- case "update": this.sendPane("yellow-pane-version", action); break;
+ case "update": this.sendPane("yellow-pane-update", action, status, args); break;
case "create": this.showPane("yellow-pane-edit", action, status, true); break;
case "edit": this.showPane("yellow-pane-edit", action, status, true); break;
case "delete": this.showPane("yellow-pane-edit", action, status, true); break;
@@ -430,7 +431,7 @@ yellow.webinterface =
},
// Send pane
- sendPane: function(paneId, paneAction)
+ sendPane: function(paneId, paneAction, paneStatus, paneArgs)
{
if(yellow.config.debug) console.log("yellow.webinterface.sendPane id:"+paneId);
if(paneId=="yellow-pane-edit")
@@ -438,16 +439,27 @@ yellow.webinterface =
paneAction = this.getPaneAction(paneId, paneAction);
if(paneAction)
{
- var params = {};
- params.action = paneAction;
- params.rawdatasource = yellow.page.rawDataSource;
- params.rawdataedit = document.getElementById("yellow-pane-edit-page").value;
- yellow.toolbox.submitForm(params, true);
+ var args = {};
+ args.action = paneAction;
+ args.rawdatasource = yellow.page.rawDataSource;
+ args.rawdataedit = document.getElementById("yellow-pane-edit-page").value;
+ yellow.toolbox.submitForm(args, true);
} else {
this.hidePane(paneId);
}
} else {
- yellow.toolbox.submitForm({"action":paneAction});
+ var args = {"action":paneAction};
+ if(paneArgs)
+ {
+ var tokens = paneArgs.split('/');
+ for(var i=0; i<tokens.length; i++)
+ {
+ var pair = tokens[i].split(/[:=]/);
+ if(!pair[0] || !pair[1]) continue;
+ args[pair[0]] = pair[1];
+ }
+ }
+ yellow.toolbox.submitForm(args);
}
},
@@ -777,14 +789,14 @@ yellow.toolbox =
},
// Submit form with post method
- submitForm: function(params, encodeNewline)
+ submitForm: function(args, encodeNewline)
{
var elementForm = document.createElement("form");
elementForm.setAttribute("method", "post");
- for(var key in params)
+ for(var key in args)
{
- if(!params.hasOwnProperty(key)) continue;
- var value = encodeNewline ? this.encodeNewline(params[key]) : params[key];
+ if(!args.hasOwnProperty(key)) continue;
+ var value = encodeNewline ? this.encodeNewline(args[key]) : args[key];
var elementInput = document.createElement("input");
elementInput.setAttribute("type", "hidden");
elementInput.setAttribute("name", key);
diff --git a/system/plugins/webinterface.php b/system/plugins/webinterface.php
@@ -5,7 +5,7 @@
// Web interface plugin
class YellowWebinterface
{
- const VERSION = "0.6.19";
+ const VERSION = "0.6.20";
var $yellow; //access to API
var $response; //web interface response
var $users; //web interface users
@@ -18,8 +18,6 @@ class YellowWebinterface
$this->response = new YellowResponse($yellow);
$this->users = new YellowUsers($yellow);
$this->merge = new YellowMerge($yellow);
- $this->yellow->config->setDefault("webinterfaceServerScheme", $this->yellow->config->get("serverScheme"));
- $this->yellow->config->setDefault("webinterfaceServerName", $this->yellow->config->get("serverName"));
$this->yellow->config->setDefault("webinterfaceLocation", "/edit/");
$this->yellow->config->setDefault("webinterfaceNewFile", "page-new-(.*).txt");
$this->yellow->config->setDefault("webinterfaceMetaFilePrefix", "published");
@@ -32,24 +30,24 @@ class YellowWebinterface
$this->users->load($this->yellow->config->get("configDir").$this->yellow->config->get("webinterfaceUserFile"));
}
- // Handle update
- function onUpdate($name)
+ // Handle startup
+ function onStartup($update)
{
- if($name=="webinterface") $this->cleanCommand(array("clean", "all"));
+ if($update) $this->cleanCommand(array("clean", "all"));
}
// Handle request
- function onRequest($serverScheme, $serverName, $base, $location, $fileName)
+ function onRequest($scheme, $address, $base, $location, $fileName)
{
$statusCode = 0;
if($this->checkRequest($location))
{
- $serverScheme = $this->yellow->config->get("webinterfaceServerScheme");
- $serverName = $this->yellow->config->get("webinterfaceServerName");
+ $scheme = $this->yellow->config->get("serverScheme");
+ $address = $this->yellow->config->get("serverAddress");
$base = rtrim($this->yellow->config->get("serverBase").$this->yellow->config->get("webinterfaceLocation"), '/');
- list($serverScheme, $serverName, $base, $location, $fileName) = $this->yellow->getRequestInformation($serverScheme, $serverName, $base);
- $this->yellow->page->setRequestInformation($serverScheme, $serverName, $base, $location, $fileName);
- $statusCode = $this->processRequest($serverScheme, $serverName, $base, $location, $fileName);
+ list($scheme, $address, $base, $location, $fileName) = $this->yellow->getRequestInformation($scheme, $address, $base);
+ $this->yellow->page->setRequestInformation($scheme, $address, $base, $location, $fileName);
+ $statusCode = $this->processRequest($scheme, $address, $base, $location, $fileName);
}
return $statusCode;
}
@@ -91,9 +89,9 @@ class YellowWebinterface
$output = null;
if($name=="header" && $this->response->isActive())
{
- $location = $this->yellow->config->get("serverBase").$this->yellow->config->get("pluginLocation")."webinterface";
- $output = "<link rel=\"stylesheet\" type=\"text/css\" media=\"all\" href=\"".htmlspecialchars($location).".css\" />\n";
- $output .= "<script type=\"text/javascript\" src=\"".htmlspecialchars($location).".js\"></script>\n";
+ $pluginLocation = $this->yellow->config->get("serverBase").$this->yellow->config->get("pluginLocation");
+ $output = "<link rel=\"stylesheet\" type=\"text/css\" media=\"all\" href=\"{$pluginLocation}webinterface.css\" />\n";
+ $output .= "<script type=\"text/javascript\" src=\"{$pluginLocation}webinterface.js\"></script>\n";
$output .= "<script type=\"text/javascript\">\n";
$output .= "// <![CDATA[\n";
$output .= "yellow.page = ".json_encode($this->response->getPageData()).";\n";
@@ -176,40 +174,40 @@ class YellowWebinterface
}
// Process request
- function processRequest($serverScheme, $serverName, $base, $location, $fileName)
+ function processRequest($scheme, $address, $base, $location, $fileName)
{
$statusCode = 0;
- if($this->checkUser($serverScheme, $serverName, $base, $location, $fileName))
+ if($this->checkUser($scheme, $address, $base, $location, $fileName))
{
switch($_REQUEST["action"])
{
- case "": $statusCode = $this->processRequestShow($serverScheme, $serverName, $base, $location, $fileName); break;
- case "login": $statusCode = $this->processRequestLogin($serverScheme, $serverName, $base, $location, $fileName); break;
- case "logout": $statusCode = $this->processRequestLogout($serverScheme, $serverName, $base, $location, $fileName); break;
- case "signup": $statusCode = $this->processRequestSignup($serverScheme, $serverName, $base, $location, $fileName); break;
- case "confirm": $statusCode = $this->processRequestConfirm($serverScheme, $serverName, $base, $location, $fileName); break;
- case "approve": $statusCode = $this->processRequestApprove($serverScheme, $serverName, $base, $location, $fileName); break;
- case "recover": $statusCode = $this->processRequestRecover($serverScheme, $serverName, $base, $location, $fileName); break;
- case "settings": $statusCode = $this->processRequestSettings($serverScheme, $serverName, $base, $location, $fileName); break;
- case "reconfirm": $statusCode = $this->processRequestReconfirm($serverScheme, $serverName, $base, $location, $fileName); break;
- case "change": $statusCode = $this->processRequestChange($serverScheme, $serverName, $base, $location, $fileName); break;
- case "version": $statusCode = $this->processRequestVersion($serverScheme, $serverName, $base, $location, $fileName); break;
- case "update": $statusCode = $this->processRequestUpdate($serverScheme, $serverName, $base, $location, $fileName); break;
- case "create": $statusCode = $this->processRequestCreate($serverScheme, $serverName, $base, $location, $fileName); break;
- case "edit": $statusCode = $this->processRequestEdit($serverScheme, $serverName, $base, $location, $fileName); break;
- case "delete": $statusCode = $this->processRequestDelete($serverScheme, $serverName, $base, $location, $fileName); break;
+ case "": $statusCode = $this->processRequestShow($scheme, $address, $base, $location, $fileName); break;
+ case "login": $statusCode = $this->processRequestLogin($scheme, $address, $base, $location, $fileName); break;
+ case "logout": $statusCode = $this->processRequestLogout($scheme, $address, $base, $location, $fileName); break;
+ case "signup": $statusCode = $this->processRequestSignup($scheme, $address, $base, $location, $fileName); break;
+ case "confirm": $statusCode = $this->processRequestConfirm($scheme, $address, $base, $location, $fileName); break;
+ case "approve": $statusCode = $this->processRequestApprove($scheme, $address, $base, $location, $fileName); break;
+ case "recover": $statusCode = $this->processRequestRecover($scheme, $address, $base, $location, $fileName); break;
+ case "settings": $statusCode = $this->processRequestSettings($scheme, $address, $base, $location, $fileName); break;
+ case "reconfirm": $statusCode = $this->processRequestReconfirm($scheme, $address, $base, $location, $fileName); break;
+ case "change": $statusCode = $this->processRequestChange($scheme, $address, $base, $location, $fileName); break;
+ case "version": $statusCode = $this->processRequestVersion($scheme, $address, $base, $location, $fileName); break;
+ case "update": $statusCode = $this->processRequestUpdate($scheme, $address, $base, $location, $fileName); break;
+ case "create": $statusCode = $this->processRequestCreate($scheme, $address, $base, $location, $fileName); break;
+ case "edit": $statusCode = $this->processRequestEdit($scheme, $address, $base, $location, $fileName); break;
+ case "delete": $statusCode = $this->processRequestDelete($scheme, $address, $base, $location, $fileName); break;
}
} else {
- $this->yellow->pages->requestHandler = "core";
+ $this->yellow->lookup->requestHandler = "core";
switch($_REQUEST["action"])
{
- case "": $statusCode = $this->processRequestShow($serverScheme, $serverName, $base, $location, $fileName); break;
- case "signup": $statusCode = $this->processRequestSignup($serverScheme, $serverName, $base, $location, $fileName); break;
- case "confirm": $statusCode = $this->processRequestConfirm($serverScheme, $serverName, $base, $location, $fileName); break;
- case "approve": $statusCode = $this->processRequestApprove($serverScheme, $serverName, $base, $location, $fileName); break;
- case "recover": $statusCode = $this->processRequestRecover($serverScheme, $serverName, $base, $location, $fileName); break;
- case "reconfirm": $statusCode = $this->processRequestReconfirm($serverScheme, $serverName, $base, $location, $fileName); break;
- case "change": $statusCode = $this->processRequestChange($serverScheme, $serverName, $base, $location, $fileName); break;
+ case "": $statusCode = $this->processRequestShow($scheme, $address, $base, $location, $fileName); break;
+ case "signup": $statusCode = $this->processRequestSignup($scheme, $address, $base, $location, $fileName); break;
+ case "confirm": $statusCode = $this->processRequestConfirm($scheme, $address, $base, $location, $fileName); break;
+ case "approve": $statusCode = $this->processRequestApprove($scheme, $address, $base, $location, $fileName); break;
+ case "recover": $statusCode = $this->processRequestRecover($scheme, $address, $base, $location, $fileName); break;
+ case "reconfirm": $statusCode = $this->processRequestReconfirm($scheme, $address, $base, $location, $fileName); break;
+ case "change": $statusCode = $this->processRequestChange($scheme, $address, $base, $location, $fileName); break;
}
if($this->response->action=="fail") $this->yellow->page->error(500, "Login failed, [please log in](javascript:yellow.action('login');)!");
}
@@ -217,22 +215,22 @@ class YellowWebinterface
}
// Process request to show file
- function processRequestShow($serverScheme, $serverName, $base, $location, $fileName)
+ function processRequestShow($scheme, $address, $base, $location, $fileName)
{
$statusCode = 0;
if(is_readable($fileName))
{
- $statusCode = $this->yellow->processRequest($serverScheme, $serverName, $base, $location, $fileName, false);
+ $statusCode = $this->yellow->processRequest($scheme, $address, $base, $location, $fileName, false);
} else {
if($this->yellow->lookup->isRedirectLocation($location))
{
$statusCode = 301;
$location = $this->yellow->lookup->isFileLocation($location) ? "$location/" : "/".$this->yellow->getRequestLanguage()."/";
- $location = $this->yellow->lookup->normaliseUrl($serverScheme, $serverName, $base, $location);
+ $location = $this->yellow->lookup->normaliseUrl($scheme, $address, $base, $location);
$this->yellow->sendStatus($statusCode, $location);
} else {
$statusCode = $this->response->isUserRestrictions() ? 404 : 424;
- $this->yellow->processRequest($serverScheme, $serverName, $base, $location, $fileName, false);
+ $this->yellow->processRequest($scheme, $address, $base, $location, $fileName, false);
$this->yellow->page->error($statusCode);
}
}
@@ -240,39 +238,39 @@ class YellowWebinterface
}
// Process request for user login
- function processRequestLogin($serverScheme, $serverName, $base, $location, $fileName)
+ function processRequestLogin($scheme, $address, $base, $location, $fileName)
{
$statusCode = 0;
$home = $this->users->getHome($this->response->userEmail);
if(substru($location, 0, strlenu($home))==$home)
{
$statusCode = 303;
- $location = $this->yellow->lookup->normaliseUrl($serverScheme, $serverName, $base, $location);
+ $location = $this->yellow->lookup->normaliseUrl($scheme, $address, $base, $location);
$this->yellow->sendStatus($statusCode, $location);
} else {
$statusCode = 302;
- $location = $this->yellow->lookup->normaliseUrl($serverScheme, $serverName, $base, $home);
+ $location = $this->yellow->lookup->normaliseUrl($scheme, $address, $base, $home);
$this->yellow->sendStatus($statusCode, $location);
}
return $statusCode;
}
// Process request for user logout
- function processRequestLogout($serverScheme, $serverName, $base, $location, $fileName)
+ function processRequestLogout($scheme, $address, $base, $location, $fileName)
{
$statusCode = 302;
$this->response->userEmail = "";
- $this->response->destroyCookie($serverScheme, $serverName, $base);
+ $this->response->destroyCookie($scheme, $address, $base);
$location = $this->yellow->lookup->normaliseUrl(
$this->yellow->config->get("serverScheme"),
- $this->yellow->config->get("serverName"),
+ $this->yellow->config->get("serverAddress"),
$this->yellow->config->get("serverBase"), $location);
$this->yellow->sendStatus($statusCode, $location);
return $statusCode;
}
// Process request for user signup
- function processRequestSignup($serverScheme, $serverName, $base, $location, $fileName)
+ function processRequestSignup($scheme, $address, $base, $location, $fileName)
{
$this->response->action = "signup";
$this->response->status = "ok";
@@ -291,15 +289,15 @@ class YellowWebinterface
}
if($this->response->status=="ok")
{
- $this->response->status = $this->response->sendMail($serverScheme, $serverName, $base, $email, "confirm") ? "next" : "error";
+ $this->response->status = $this->response->sendMail($scheme, $address, $base, $email, "confirm") ? "next" : "error";
if($this->response->status=="error") $this->yellow->page->error(500, "Can't send email on this server!");
}
- $statusCode = $this->yellow->processRequest($serverScheme, $serverName, $base, $location, $fileName, false);
+ $statusCode = $this->yellow->processRequest($scheme, $address, $base, $location, $fileName, false);
return $statusCode;
}
// Process request to confirm user signup
- function processRequestConfirm($serverScheme, $serverName, $base, $location, $fileName)
+ function processRequestConfirm($scheme, $address, $base, $location, $fileName)
{
$this->response->action = "confirm";
$this->response->status = "ok";
@@ -313,15 +311,15 @@ class YellowWebinterface
}
if($this->response->status=="ok")
{
- $this->response->status = $this->response->sendMail($serverScheme, $serverName, $base, $email, "approve") ? "done" : "error";
+ $this->response->status = $this->response->sendMail($scheme, $address, $base, $email, "approve") ? "done" : "error";
if($this->response->status=="error") $this->yellow->page->error(500, "Can't send email on this server!");
}
- $statusCode = $this->yellow->processRequest($serverScheme, $serverName, $base, $location, $fileName, false);
+ $statusCode = $this->yellow->processRequest($scheme, $address, $base, $location, $fileName, false);
return $statusCode;
}
// Process request to approve user signup
- function processRequestApprove($serverScheme, $serverName, $base, $location, $fileName)
+ function processRequestApprove($scheme, $address, $base, $location, $fileName)
{
$this->response->action = "approve";
$this->response->status = "ok";
@@ -335,15 +333,15 @@ class YellowWebinterface
}
if($this->response->status=="ok")
{
- $this->response->status = $this->response->sendMail($serverScheme, $serverName, $base, $email, "welcome") ? "done" : "error";
+ $this->response->status = $this->response->sendMail($scheme, $address, $base, $email, "welcome") ? "done" : "error";
if($this->response->status=="error") $this->yellow->page->error(500, "Can't send email on this server!");
}
- $statusCode = $this->yellow->processRequest($serverScheme, $serverName, $base, $location, $fileName, false);
+ $statusCode = $this->yellow->processRequest($scheme, $address, $base, $location, $fileName, false);
return $statusCode;
}
// Process request to recover password
- function processRequestRecover($serverScheme, $serverName, $base, $location, $fileName)
+ function processRequestRecover($scheme, $address, $base, $location, $fileName)
{
$this->response->action = "recover";
$this->response->status = "ok";
@@ -356,7 +354,7 @@ class YellowWebinterface
if($this->response->status=="ok" && !$this->users->isExisting($email)) $this->response->status = "next";
if($this->response->status=="ok")
{
- $this->response->status = $this->response->sendMail($serverScheme, $serverName, $base, $email, "recover") ? "next" : "error";
+ $this->response->status = $this->response->sendMail($scheme, $address, $base, $email, "recover") ? "next" : "error";
if($this->response->status=="error") $this->yellow->page->error(500, "Can't send email on this server!");
}
} else {
@@ -374,18 +372,18 @@ class YellowWebinterface
if($this->response->status=="ok")
{
$this->response->userEmail = "";
- $this->response->destroyCookie($serverScheme, $serverName, $base);
- $this->response->status = $this->response->sendMail($serverScheme, $serverName, $base, $email, "information") ? "done" : "error";
+ $this->response->destroyCookie($scheme, $address, $base);
+ $this->response->status = $this->response->sendMail($scheme, $address, $base, $email, "information") ? "done" : "error";
if($this->response->status=="error") $this->yellow->page->error(500, "Can't send email on this server!");
}
}
}
- $statusCode = $this->yellow->processRequest($serverScheme, $serverName, $base, $location, $fileName, false);
+ $statusCode = $this->yellow->processRequest($scheme, $address, $base, $location, $fileName, false);
return $statusCode;
}
// Process request to change settings
- function processRequestSettings($serverScheme, $serverName, $base, $location, $fileName)
+ function processRequestSettings($scheme, $address, $base, $location, $fileName)
{
$this->response->action = "settings";
$this->response->status = "ok";
@@ -416,7 +414,7 @@ class YellowWebinterface
if($this->response->status=="ok")
{
$action = $email!=$emailSource ? "reconfirm" : "change";
- $this->response->status = $this->response->sendMail($serverScheme, $serverName, $base, $email, $action) ? "next" : "error";
+ $this->response->status = $this->response->sendMail($scheme, $address, $base, $email, $action) ? "next" : "error";
if($this->response->status=="error") $this->yellow->page->error(500, "Can't send email on this server!");
}
} else {
@@ -430,16 +428,16 @@ class YellowWebinterface
if($this->response->status=="done")
{
$statusCode = 303;
- $location = $this->yellow->lookup->normaliseUrl($serverScheme, $serverName, $base, $location);
+ $location = $this->yellow->lookup->normaliseUrl($scheme, $address, $base, $location);
$this->yellow->sendStatus($statusCode, $location);
} else {
- $statusCode = $this->yellow->processRequest($serverScheme, $serverName, $base, $location, $fileName, false);
+ $statusCode = $this->yellow->processRequest($scheme, $address, $base, $location, $fileName, false);
}
return $statusCode;
}
// Process request to reconfirm email
- function processRequestReconfirm($serverScheme, $serverName, $base, $location, $fileName)
+ function processRequestReconfirm($scheme, $address, $base, $location, $fileName)
{
$this->response->action = "reconfirm";
$this->response->status = "ok";
@@ -458,15 +456,15 @@ class YellowWebinterface
}
if($this->response->status=="ok")
{
- $this->response->status = $this->response->sendMail($serverScheme, $serverName, $base, $emailSource, "change") ? "done" : "error";
+ $this->response->status = $this->response->sendMail($scheme, $address, $base, $emailSource, "change") ? "done" : "error";
if($this->response->status=="error") $this->yellow->page->error(500, "Can't send email on this server!");
}
- $statusCode = $this->yellow->processRequest($serverScheme, $serverName, $base, $location, $fileName, false);
+ $statusCode = $this->yellow->processRequest($scheme, $address, $base, $location, $fileName, false);
return $statusCode;
}
// Process request to change settings
- function processRequestChange($serverScheme, $serverName, $base, $location, $fileName)
+ function processRequestChange($scheme, $address, $base, $location, $fileName)
{
$this->response->action = "change";
$this->response->status = "ok";
@@ -495,51 +493,75 @@ class YellowWebinterface
if($this->response->status=="ok")
{
$this->response->userEmail = "";
- $this->response->destroyCookie($serverScheme, $serverName, $base);
- $this->response->status = $this->response->sendMail($serverScheme, $serverName, $base, $email, "information") ? "done" : "error";
+ $this->response->destroyCookie($scheme, $address, $base);
+ $this->response->status = $this->response->sendMail($scheme, $address, $base, $email, "information") ? "done" : "error";
if($this->response->status=="error") $this->yellow->page->error(500, "Can't send email on this server!");
}
- $statusCode = $this->yellow->processRequest($serverScheme, $serverName, $base, $location, $fileName, false);
+ $statusCode = $this->yellow->processRequest($scheme, $address, $base, $location, $fileName, false);
return $statusCode;
}
// Process request to show software version
- function processRequestVersion($serverScheme, $serverName, $base, $location, $fileName)
+ function processRequestVersion($scheme, $address, $base, $location, $fileName)
{
$this->response->action = "version";
$this->response->status = "ok";
if($this->yellow->plugins->isExisting("update"))
{
- list($statusCode, $dataCurrent) = $this->yellow->plugins->get("update")->getSoftwareVersion();
- list($statusCode, $dataLatest) = $this->yellow->plugins->get("update")->getSoftwareVersion(true);
- foreach($dataCurrent as $key=>$value)
+ list($statusCodeCurrent, $dataCurrent) = $this->yellow->plugins->get("update")->getSoftwareVersion();
+ list($statusCodeLatest, $dataLatest) = $this->yellow->plugins->get("update")->getSoftwareVersion(true);
+ list($statusCodeModified, $dataModified) = $this->yellow->plugins->get("update")->getSoftwareModified();
+ $statusCode = max($statusCodeCurrent, $statusCodeLatest, $statusCodeModified);
+ if($this->response->isUserWebmaster())
{
- if(strnatcasecmp($dataCurrent[$key], $dataLatest[$key])<0)
+ foreach($dataCurrent as $key=>$value)
{
- if(!empty($this->response->rawDataOutput)) $this->response->rawDataOutput .= "<br />\n";
- $this->response->rawDataOutput .= "$key $dataLatest[$key]";
- ++$updates;
- ++$count; if($count>=4) { $this->response->rawDataOutput .= "…"; break; }
+ if(strnatcasecmp($dataCurrent[$key], $dataLatest[$key])<0)
+ {
+ ++$updates;
+ if(!empty($this->response->rawDataOutput)) $this->response->rawDataOutput .= "<br />\n";
+ $this->response->rawDataOutput .= htmlspecialchars("$key $dataLatest[$key]");
+ }
+ }
+ if($updates==0)
+ {
+ foreach($dataCurrent as $key=>$value)
+ {
+ if(!is_null($dataModified[$key]) && !is_null($dataLatest[$key]))
+ {
+ $rawData = $this->yellow->text->getTextHtml("webinterfaceVersionUpdateModified", $this->response->language)." - <a href=\"#\" onclick=\"yellow.action('update','update','".$this->yellow->toolbox->normaliseArgs("option:force/feature:$key")."'); return false;\">".$this->yellow->text->getTextHtml("webinterfaceVersionUpdateForce", $this->response->language)."</a>";
+ $rawData = preg_replace("/@software/i", htmlspecialchars("$key $dataLatest[$key]"), $rawData);
+ if(!empty($this->response->rawDataOutput)) $this->response->rawDataOutput .= "<br />\n";
+ $this->response->rawDataOutput .= $rawData;
+ }
+ }
+ }
+ } else {
+ foreach($dataCurrent as $key=>$value)
+ {
+ if(strnatcasecmp($dataCurrent[$key], $dataLatest[$key])<0) ++$updates;
}
}
$this->response->status = $updates ? "updates" : "done";
if($statusCode!=200) $this->response->status = "error";
}
- $statusCode = $this->yellow->processRequest($serverScheme, $serverName, $base, $location, $fileName, false);
+ $statusCode = $this->yellow->processRequest($scheme, $address, $base, $location, $fileName, false);
return $statusCode;
}
// Process request to update website
- function processRequestUpdate($serverScheme, $serverName, $base, $location, $fileName)
+ function processRequestUpdate($scheme, $address, $base, $location, $fileName)
{
$statusCode = 0;
if($this->yellow->plugins->isExisting("update") && $this->response->isUserWebmaster())
{
- $statusCode = $this->yellow->command("update");
+ $option = trim($_REQUEST["option"]);
+ $feature = trim($_REQUEST["feature"]);
+ $statusCode = $this->yellow->command("update", $option, $feature);
if($statusCode==200)
{
$statusCode = 303;
- $location = $this->yellow->lookup->normaliseUrl($serverScheme, $serverName, $base, $location);
+ $location = $this->yellow->lookup->normaliseUrl($scheme, $address, $base, $location);
$this->yellow->sendStatus($statusCode, $location);
}
}
@@ -547,29 +569,29 @@ class YellowWebinterface
}
// Process request to create page
- function processRequestCreate($serverScheme, $serverName, $base, $location, $fileName)
+ function processRequestCreate($scheme, $address, $base, $location, $fileName)
{
$statusCode = 0;
if(!$this->response->isUserRestrictions() && !empty($_POST["rawdataedit"]))
{
$this->response->rawDataSource = $this->response->rawDataEdit = rawurldecode($_POST["rawdatasource"]);
$rawData = $this->response->normaliseText(rawurldecode($_POST["rawdataedit"]));
- $page = $this->response->getPageNew($serverScheme, $serverName, $base, $location, $fileName, $rawData);
+ $page = $this->response->getPageNew($scheme, $address, $base, $location, $fileName, $rawData);
if(!$page->isError())
{
if($this->yellow->toolbox->createFile($page->fileName, $page->rawData, true))
{
$statusCode = 303;
- $location = $this->yellow->lookup->normaliseUrl($serverScheme, $serverName, $base, $page->location);
+ $location = $this->yellow->lookup->normaliseUrl($scheme, $address, $base, $page->location);
$this->yellow->sendStatus($statusCode, $location);
} else {
$statusCode = 500;
- $this->yellow->processRequest($serverScheme, $serverName, $base, $location, $fileName, false);
+ $this->yellow->processRequest($scheme, $address, $base, $location, $fileName, false);
$this->yellow->page->error($statusCode, "Can't write file '$page->fileName'!");
}
} else {
$statusCode = 500;
- $this->yellow->processRequest($serverScheme, $serverName, $base, $location, $fileName, false);
+ $this->yellow->processRequest($scheme, $address, $base, $location, $fileName, false);
$this->yellow->page->error($statusCode, $page->get("pageError"));
}
}
@@ -577,14 +599,14 @@ class YellowWebinterface
}
// Process request to edit page
- function processRequestEdit($serverScheme, $serverName, $base, $location, $fileName)
+ function processRequestEdit($scheme, $address, $base, $location, $fileName)
{
$statusCode = 0;
if(!$this->response->isUserRestrictions() && !empty($_POST["rawdataedit"]))
{
$this->response->rawDataSource = rawurldecode($_POST["rawdatasource"]);
$this->response->rawDataEdit = $this->response->normaliseText(rawurldecode($_POST["rawdataedit"]));
- $page = $this->response->getPageUpdate($serverScheme, $serverName, $base, $location, $fileName,
+ $page = $this->response->getPageUpdate($scheme, $address, $base, $location, $fileName,
$this->response->rawDataSource, $this->response->rawDataEdit, $this->yellow->toolbox->readFile($fileName));
if(!$page->isError())
{
@@ -592,16 +614,16 @@ class YellowWebinterface
$this->yellow->toolbox->createFile($page->fileName, $page->rawData))
{
$statusCode = 303;
- $location = $this->yellow->lookup->normaliseUrl($serverScheme, $serverName, $base, $page->location);
+ $location = $this->yellow->lookup->normaliseUrl($scheme, $address, $base, $page->location);
$this->yellow->sendStatus($statusCode, $location);
} else {
$statusCode = 500;
- $this->yellow->processRequest($serverScheme, $serverName, $base, $location, $fileName, false);
+ $this->yellow->processRequest($scheme, $address, $base, $location, $fileName, false);
$this->yellow->page->error($statusCode, "Can't write file '$page->fileName'!");
}
} else {
$statusCode = 500;
- $this->yellow->processRequest($serverScheme, $serverName, $base, $location, $fileName, false);
+ $this->yellow->processRequest($scheme, $address, $base, $location, $fileName, false);
$this->yellow->page->error($statusCode, $page->get("pageError"));
}
}
@@ -609,7 +631,7 @@ class YellowWebinterface
}
// Process request to delete page
- function processRequestDelete($serverScheme, $serverName, $base, $location, $fileName)
+ function processRequestDelete($scheme, $address, $base, $location, $fileName)
{
$statusCode = 0;
if(!$this->response->isUserRestrictions() && is_file($fileName))
@@ -620,22 +642,22 @@ class YellowWebinterface
if($this->yellow->toolbox->deleteFile($fileName, $this->yellow->config->get("trashDir")))
{
$statusCode = 303;
- $location = $this->yellow->lookup->normaliseUrl($serverScheme, $serverName, $base, $location);
+ $location = $this->yellow->lookup->normaliseUrl($scheme, $address, $base, $location);
$this->yellow->sendStatus($statusCode, $location);
} else {
$statusCode = 500;
- $this->yellow->processRequest($serverScheme, $serverName, $base, $location, $fileName, false);
+ $this->yellow->processRequest($scheme, $address, $base, $location, $fileName, false);
$this->yellow->page->error($statusCode, "Can't delete file '$fileName'!");
}
} else {
if($this->yellow->toolbox->deleteDirectory(dirname($fileName), $this->yellow->config->get("trashDir")))
{
$statusCode = 303;
- $location = $this->yellow->lookup->normaliseUrl($serverScheme, $serverName, $base, $location);
+ $location = $this->yellow->lookup->normaliseUrl($scheme, $address, $base, $location);
$this->yellow->sendStatus($statusCode, $location);
} else {
$statusCode = 500;
- $this->yellow->processRequest($serverScheme, $serverName, $base, $location, $fileName, false);
+ $this->yellow->processRequest($scheme, $address, $base, $location, $fileName, false);
$this->yellow->page->error($statusCode, "Can't delete file '$fileName'!");
}
}
@@ -646,17 +668,13 @@ class YellowWebinterface
// Check web interface request
function checkRequest($location)
{
- if($this->yellow->toolbox->getServerScheme()==$this->yellow->config->get("webinterfaceServerScheme") &&
- $this->yellow->toolbox->getServerName()==$this->yellow->config->get("webinterfaceServerName"))
- {
- $locationLength = strlenu($this->yellow->config->get("webinterfaceLocation"));
- $this->response->active = substru($location, 0, $locationLength)==$this->yellow->config->get("webinterfaceLocation");
- }
+ $locationLength = strlenu($this->yellow->config->get("webinterfaceLocation"));
+ $this->response->active = substru($location, 0, $locationLength)==$this->yellow->config->get("webinterfaceLocation");
return $this->response->isActive();
}
// Check web interface user
- function checkUser($serverScheme, $serverName, $base, $location, $fileName)
+ function checkUser($scheme, $address, $base, $location, $fileName)
{
if($_POST["action"]=="login")
{
@@ -664,7 +682,7 @@ class YellowWebinterface
$password = $_POST["password"];
if($this->users->checkUser($email, $password))
{
- $this->response->createCookie($serverScheme, $serverName, $base, $email);
+ $this->response->createCookie($scheme, $address, $base, $email);
$this->response->userEmail = $email;
$this->response->userRestrictions = $this->getUserRestrictions($email, $location, $fileName);
$this->response->language = $this->response->getLanguage($email);
@@ -749,10 +767,10 @@ class YellowResponse
}
// Return new page
- function getPageNew($serverScheme, $serverName, $base, $location, $fileName, $rawData)
+ function getPageNew($scheme, $address, $base, $location, $fileName, $rawData)
{
$page = new YellowPage($this->yellow);
- $page->setRequestInformation($serverScheme, $serverName, $base, $location, $fileName);
+ $page->setRequestInformation($scheme, $address, $base, $location, $fileName);
$page->parseData($rawData, false, 0);
if($this->yellow->lookup->isFileLocation($location) || is_file($fileName))
{
@@ -793,16 +811,16 @@ class YellowResponse
}
// Return modified page
- function getPageUpdate($serverScheme, $serverName, $base, $location, $fileName, $rawDataSource, $rawDataEdit, $rawDataFile)
+ function getPageUpdate($scheme, $address, $base, $location, $fileName, $rawDataSource, $rawDataEdit, $rawDataFile)
{
$page = new YellowPage($this->yellow);
- $page->setRequestInformation($serverScheme, $serverName, $base, $location, $fileName);
+ $page->setRequestInformation($scheme, $address, $base, $location, $fileName);
$page->parseData($this->webinterface->merge->merge($rawDataSource, $rawDataEdit, $rawDataFile), false, 0);
if(empty($page->rawData)) $page->error(500, "Page has been modified by someone else!");
if($this->yellow->lookup->isFileLocation($location) && !$page->isError())
{
$pageSource = new YellowPage($this->yellow);
- $pageSource->setRequestInformation($serverScheme, $serverName, $base, $location, $fileName);
+ $pageSource->setRequestInformation($scheme, $address, $base, $location, $fileName);
$pageSource->parseData($rawDataSource, false, 0);
$prefix = $this->yellow->config->get("webinterfaceMetaFilePrefix");
if($pageSource->get($prefix)!=$page->get($prefix) || $pageSource->get("title")!=$page->get("title"))
@@ -840,7 +858,10 @@ class YellowResponse
$data["rawDataEdit"] = $this->rawDataEdit;
$data["rawDataNew"] = $this->getRawDataNew();
$data["rawDataOutput"] = strval($this->rawDataOutput);
- $data["pageFile"] = $this->yellow->page->get("pageFile");
+ $data["scheme"] = $this->yellow->page->scheme;
+ $data["address"] = $this->yellow->page->address;
+ $data["base"] = $this->yellow->page->base;
+ $data["location"] = $this->yellow->page->location;
$data["parserSafeMode"] = $this->yellow->page->parserSafeMode;
}
if($this->action!="none") $data = array_merge($data, $this->getRequestData());
@@ -864,15 +885,14 @@ class YellowResponse
$data["userRestrictions"] = intval($this->isUserRestrictions());
$data["userWebmaster"] = intval($this->isUserWebmaster());
$data["pluginUpdate"] = intval($this->yellow->plugins->isExisting("update"));
- $data["serverScheme"] = $this->yellow->config->get("serverScheme");
- $data["serverName"] = $this->yellow->config->get("serverName");
- $data["serverBase"] = $this->yellow->config->get("serverBase");
- $data["serverTime"] = $this->yellow->config->get("serverTime");
$data["serverLanguages"] = array();
foreach($this->yellow->text->getLanguages() as $language)
{
$data["serverLanguages"][$language] = $this->yellow->text->getTextHtml("languageDescription", $language);
}
+ $data["serverScheme"] = $this->yellow->config->get("serverScheme");
+ $data["serverAddress"] = $this->yellow->config->get("serverAddress");
+ $data["serverBase"] = $this->yellow->config->get("serverBase");
$data["serverVersion"] = "Yellow ".YellowCore::VERSION;
} else {
$data["loginEmail"] = $this->yellow->config->get("loginEmail");
@@ -898,9 +918,9 @@ class YellowResponse
// Return text strings
function getTextData()
{
- $textLanguage = array_merge($this->yellow->text->getData("language", $this->language));
- $textWebinterface = array_merge($this->yellow->text->getData("webinterface", $this->language));
- $textYellow = array_merge($this->yellow->text->getData("yellow", $this->language));
+ $textLanguage = $this->yellow->text->getData("language", $this->language);
+ $textWebinterface = $this->yellow->text->getData("webinterface", $this->language);
+ $textYellow = $this->yellow->text->getData("yellow", $this->language);
return array_merge($textLanguage, $textWebinterface, $textYellow);
}
@@ -968,28 +988,28 @@ class YellowResponse
}
// Create browser cookie
- function createCookie($serverScheme, $serverName, $base, $email)
+ function createCookie($scheme, $address, $base, $email)
{
$session = $this->webinterface->users->createSession($email);
- setcookie("login", "$email,$session", time()+60*60*24*365, "$base/", "", $serverScheme=="https");
+ setcookie("login", "$email,$session", time()+60*60*24*365, "$base/", "", $scheme=="https");
}
// Destroy browser cookie
- function destroyCookie($serverScheme, $serverName, $base)
+ function destroyCookie($scheme, $address, $base)
{
- setcookie("login", "", time()-60*60, "$base/", "", $serverScheme=="https");
+ setcookie("login", "", time()-60*60, "$base/", "", $scheme=="https");
}
// Send mail to user
- function sendMail($serverScheme, $serverName, $base, $email, $action)
+ function sendMail($scheme, $address, $base, $email, $action)
{
if($action=="welcome" || $action=="information")
{
- $url = "$serverScheme://$serverName$base/";
+ $url = "$scheme://$address$base/";
} else {
$expire = time()+60*60*24;
$id = $this->webinterface->users->createRequestId($email, $action, $expire);
- $url = "$serverScheme://$serverName$base"."/action:$action/email:$email/expire:$expire/id:$id/";
+ $url = "$scheme://$address$base"."/action:$action/email:$email/expire:$expire/id:$id/";
}
if($action=="approve")
{
@@ -1012,7 +1032,7 @@ class YellowResponse
$mailTo = mb_encode_mimeheader("$name")." <$email>";
$mailSubject = mb_encode_mimeheader($this->yellow->text->getText("{$prefix}Subject", $language));
$mailHeaders = mb_encode_mimeheader("From: $sitename")." <noreply>\r\n";
- $mailHeaders .= mb_encode_mimeheader("X-Request-Url: $serverScheme://$serverName$base")."\r\n";
+ $mailHeaders .= mb_encode_mimeheader("X-Request-Url: $scheme://$address$base")."\r\n";
$mailHeaders .= mb_encode_mimeheader("X-Remote-Addr: $_SERVER[REMOTE_ADDR]")."\r\n";
$mailHeaders .= "Mime-Version: 1.0\r\n";
$mailHeaders .= "Content-Type: text/plain; charset=utf-8\r\n";
@@ -1274,7 +1294,10 @@ class YellowUsers
$data = array();
foreach($this->users as $key=>$value)
{
- $data[$key] = "$value[email] password $value[name] $value[language] $value[status]";
+ $name = $value["name"]; if(preg_match("/\s/", $name)) $name = "\"$name\"";
+ $language = $value["language"]; if(preg_match("/\s/", $language)) $language = "\"$language\"";
+ $status = $value["status"]; if(preg_match("/\s/", $status)) $status = "\"$status\"";
+ $data[$key] = "$value[email] - $name $language $status";
if($value["home"]!="/") $data[$key] .= " restrictions";
}
usort($data, strnatcasecmp);
diff --git a/system/themes/assets/flatsite.css b/system/themes/assets/flatsite.css
@@ -0,0 +1,188 @@
+/* Flatsite theme, https://github.com/datenstrom/yellow-themes/tree/master/flatsite */
+/* Copyright (c) 2013-2017 Datenstrom, http://datenstrom.se */
+/* This file may be used and distributed under the terms of the public license. */
+
+html, body, div, form, pre, span, tr, th, td, img { margin:0; padding:0; border:0; vertical-align:baseline; }
+@font-face {
+ font-family:'Open Sans';
+ font-style:normal;
+ font-weight:300;
+ src:url(opensans-light.woff) format('woff');
+}
+@font-face {
+ font-family:'Open Sans';
+ font-style:normal;
+ font-weight:400;
+ src:url(opensans-regular.woff) format('woff');
+}
+@font-face {
+ font-family:'Open Sans';
+ font-style:normal;
+ font-weight:700;
+ src:url(opensans-bold.woff) format('woff');
+}
+body {
+ margin:1em;
+ background-color:#fff; color:#717171;
+ font-family:'Open Sans',Helvetica,sans-serif;
+ font-size:1em;
+ font-weight:300;
+ line-height:1.5;
+}
+h1, h2, h3, h4, h5, h6 { color:#07d; font-weight:normal; }
+h1 { font-size:2.0em; }
+hr { height:1px; background:#ddd; border:0; }
+strong { font-weight:bold; }
+code { font-size:1.1em; }
+a { color:#07d; text-decoration:none; }
+a:hover { color:#07d; text-decoration:underline; }
+.content h1:first-child, .content>*:first-child { margin-top:0; }
+.content h1 a:hover { text-decoration:none; }
+.content img { max-width:100%; height:auto; }
+.content form { margin:1em 0; }
+.content table { border-spacing:0; border-collapse:collapse; }
+.content th { text-align:left; padding:0.3em; border-bottom:1px solid #ddd; }
+.content td { text-align:left; padding:0.3em; border-top:1px solid #ddd; }
+.content blockquote { margin-left:0; padding-left:1em; border-left:.5em solid #0a0; }
+.content blockquote blockquote { margin-left:-1.5em; border-left:.5em solid #fb0; }
+.content blockquote blockquote blockquote { border-color:#d00; }
+.content code, pre { font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace; font-size:90%; }
+.content code { padding:0.15em 0.4em; margin:0; background-color:#f7f7f7; border-radius:3px; }
+.content pre>code { padding:0; margin:0; white-space:pre; background:transparent; border:0; font-size:inherit; }
+.content pre { padding:1em; overflow:auto; line-height:1.45; background-color:#f7f7f7; border-radius:3px; }
+.content .flexible { position:relative; padding-top:0; padding-bottom:56.25%; }
+.content .flexible iframe { position:absolute; top:0; left:0; width:100%; height:100%; }
+.content .stretchable ul { margin:0 -0.5em; padding:0; list-style:none; text-align:center; }
+.content .stretchable li { margin:0; padding:1em 0; display:inline-block; text-align:center; vertical-align:top; }
+.content .stretchable a { color:#717171; text-decoration:none; }
+.content .toc { margin:0; padding:0; list-style:none; }
+.content .links { margin:1em 0; }
+.content .pagination { margin:1em 0; }
+.content .left { float:left; margin:0 1em 0 0; }
+.content .center { display:block; margin:0 auto; }
+.content .right { float:right; margin:0 0 0 1em; }
+.content .rounded { border-radius:4px; }
+
+/* Header */
+
+.header .sitename { display:block; float:left; }
+.header .sitename h1 { margin:0; }
+.header .sitename h1 a { color:#111; text-decoration:none; }
+.header .sitename h2 { margin-top:0; color:#717171; font-size:1.0em; font-weight:300; }
+
+/* Navigation */
+
+.navigation { display:block; float:right; }
+.navigation { margin-top:0.9em; margin-bottom:0.9em; line-height:2; }
+.navigation a { padding:0 0.3em; }
+.navigation ul { margin:0 -0.3em; padding:0; list-style:none; }
+.navigation li { display:inline; }
+.navigation-tree { display:block; float:right; }
+.navigation-tree { margin-top:0.9em; margin-bottom:0.9em; line-height:2; }
+.navigation-tree a { padding:0 0.3em; }
+.navigation-tree ul { margin:0 -0.3em; padding:0; list-style:none; }
+.navigation-tree li { display:inline; }
+.navigation-tree ul li { display:inline-block; position:relative; cursor:pointer; margin:0; }
+.navigation-tree ul li ul { padding:0.3em; position:absolute; width:13em; background:#fff; z-index:100; display:none; }
+.navigation-tree ul li ul { border:1px solid #bbb; border-radius:4px; box-shadow:2px 4px 10px rgba(0, 0, 0, 0.2); }
+.navigation-tree ul li ul li { display:block; }
+.navigation-tree>ul>li:hover>ul { display:block; }
+.navigation-banner { clear:both; }
+.navigation-search { padding-bottom:1em; }
+.navigation-search .search-form { position:relative; }
+.navigation-search .search-text { font-family:inherit; font-size:inherit; font-weight:inherit; }
+.navigation-search .search-text { padding:0.5em; border:1px solid #bbb; border-radius:4px; width:100%; box-sizing:border-box; }
+.navigation-search .search-text { background-color:#fff; background-image:linear-gradient(to bottom, #fff, #fff); }
+.navigation-search .search-button { position:absolute; top:0; right:0; }
+.navigation-search .search-button { font-family:inherit; font-size:inherit; font-weight:inherit; }
+.navigation-search .search-button { margin:5px; padding:0.3em; border:none; background-color:transparent; }
+
+/* Footer */
+
+.footer { margin-top:2em; }
+.footer .siteinfo a { color:#07d; }
+.footer .siteinfo a:hover { color:#07d; text-decoration:underline; }
+.footer .siteinfo a.socialmedia {
+ display:inline-block;
+ box-sizing:border-box;
+ border-radius:13px;
+ width:26px;
+ height:26px;
+ margin:-20px 0;
+ padding:1px 0;
+ text-align:center;
+ background-color:#07d;
+ color:#fff;
+}
+.footer .siteinfo a.socialmedia:hover { background-color:#039; color:#fff; }
+.footer .siteinfo-left { float:left; }
+.footer .siteinfo-right { float:right; }
+.footer .siteinfo-banner { clear:both; }
+
+/* Sidebar */
+
+.with-sidebar .main { margin-right:17em; }
+.with-sidebar .sidebar { float:right; width:16em; margin-top:3.9em; padding:2px; overflow:hidden; font-size:0.9em; }
+.with-sidebar .sidebar .search-form input { width:100%; box-sizing:border-box; }
+.with-sidebar .content:after { content:""; display:table; clear:both; }
+
+/* Forms and buttons */
+
+.form-control {
+ margin:0; padding:2px 4px;
+ display:inline-block; min-width:7em;
+ background-color:#fff; color:#555;
+ background-image:linear-gradient(to bottom, #fff, #fff);
+ border:1px solid #bbb;
+ border-radius:4px;
+ font-size:0.9em; font-family:inherit; font-weight:normal; line-height:normal;
+}
+.btn {
+ margin:0; padding:4px 22px;
+ display:inline-block; min-width:7em;
+ background-color:#eaeaea; color:#333333;
+ background-image:linear-gradient(to bottom, #f8f8f8, #e1e1e1);
+ border:1px solid #bbb;
+ border-color:#c1c1c1 #c1c1c1 #aaaaaa;
+ border-radius:4px;
+ outline-offset:-2px;
+ font-size:0.9em; font-family:inherit; font-weight:normal; line-height:1;
+ text-align:center; text-decoration:none;
+}
+.btn:hover, .btn:focus, .btn:active {
+ color:#333333;
+ background-image:none;
+ text-decoration:none;
+}
+.btn:active { box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.1); }
+
+/* Misc */
+
+.highlight .kw1, .highlight .kw2, .highlight .kw3, .highlight .kw4 { color:#b0b; }
+.highlight .st0, .highlight .st_h, .highlight .nu0 { color:#b0b; }
+.highlight .re0, .highlight .re1, .highlight .re2, .highlight .re3, .css .nu0 { color:inherit; }
+.highlight .co1, .highlight .coMULTI, .highlight .sc0, .highlight .sc-1 { color:inherit; }
+
+/* Responsive and print */
+
+.page { margin:0 auto; max-width:1000px; }
+
+@media screen and (min-width:62em) {
+ body { width:60em; margin:1em auto; }
+ .page{ margin:0; max-width:none; }
+}
+@media screen and (max-width:32em) {
+ body { margin:0.5em; font-size:0.9em; }
+ .header .sitename h1, .content h1, .content h2 { font-size:1.3em; }
+ .header .sitename h1, .header .sitename h2, .footer, .page { margin:0; padding:0; }
+ .header .sitename, .navigation, .navigation-tree { float:none; }
+ .navigation { margin-top:0.5em; margin-bottom:0.5em; }
+ .navigation-search { padding-bottom:1em; }
+ .footer .siteinfo-right { display:none; }
+ .footer .siteinfo a.socialmedia { width:24px; height:24px; padding:1px 0; }
+ .with-sidebar .main { margin-right:0; }
+ .with-sidebar .sidebar { display:none; }
+}
+@media print {
+ .page { border:none !important; }
+}
+\ No newline at end of file
diff --git a/system/themes/assets/flatsite.php b/system/themes/assets/flatsite.php
@@ -0,0 +1,12 @@
+<?php
+// Flatsite theme, https://github.com/datenstrom/yellow-themes/tree/master/flatsite
+// Copyright (c) 2013-2017 Datenstrom, http://datenstrom.se
+// This file may be used and distributed under the terms of the public license.
+
+class YellowThemeFlatsite
+{
+ const VERSION = "0.6.12";
+}
+
+$yellow->themes->register("flatsite", "YellowThemeFlatsite", YellowThemeFlatsite::VERSION);
+?>
+\ No newline at end of file
diff --git a/system/themes/assets/opensans-bold.woff b/system/themes/assets/opensans-bold.woff
Binary files differ.
diff --git a/system/themes/assets/opensans-light.woff b/system/themes/assets/opensans-light.woff
Binary files differ.
diff --git a/system/themes/assets/opensans-regular.woff b/system/themes/assets/opensans-regular.woff
Binary files differ.
diff --git a/system/themes/flatsite.css b/system/themes/flatsite.css
@@ -1,171 +0,0 @@
-/* Theme: Flatsite theme */
-/* Version: 0.6.11 */
-/* Designer: Mark Mayberg */
-
-@import url(https://fonts.googleapis.com/css?family=Open+Sans:300,400,700);
-html, body, div, form, pre, span, tr, th, td, img { margin:0; padding:0; border:0; vertical-align:baseline; }
-body {
- margin:1em;
- background-color:#fff; color:#717171;
- font-family:'Open Sans',Helvetica,sans-serif;
- font-size:1em;
- font-weight:300;
- line-height:1.5;
-}
-h1, h2, h3, h4, h5, h6 { color:#07d; font-weight:normal; }
-h1 { font-size:2.0em; }
-hr { height:1px; background:#ddd; border:0; }
-strong { font-weight:bold; }
-code { font-size:1.1em; }
-a { color:#07d; text-decoration:none; }
-a:hover { color:#07d; text-decoration:underline; }
-.content h1:first-child, .content>*:first-child { margin-top:0; }
-.content h1 a:hover { text-decoration:none; }
-.content img { max-width:100%; height:auto; }
-.content form { margin:1em 0; }
-.content table { border-spacing:0; border-collapse:collapse; }
-.content th { text-align:left; padding:0.3em; border-bottom:1px solid #ddd; }
-.content td { text-align:left; padding:0.3em; border-top:1px solid #ddd; }
-.content blockquote { margin-left:0; padding-left:1em; border-left:.5em solid #0a0; }
-.content blockquote blockquote { margin-left:-1.5em; border-left:.5em solid #fb0; }
-.content blockquote blockquote blockquote { border-color:#d00; }
-.content code, pre { font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace; font-size:90%; }
-.content code { padding:0.15em 0.4em; margin:0; background-color:#f7f7f7; border-radius:3px; }
-.content pre>code { padding:0; margin:0; white-space:pre; background:transparent; border:0; font-size:inherit; }
-.content pre { padding:1em; overflow:auto; line-height:1.45; background-color:#f7f7f7; border-radius:3px; }
-.content .flexible { position:relative; padding-top:0; padding-bottom:56.25%; }
-.content .flexible iframe { position:absolute; top:0; left:0; width:100%; height:100%; }
-.content .stretchable ul { margin:0 -0.5em; padding:0; list-style:none; text-align:center; }
-.content .stretchable li { margin:0; padding:1em 0; display:inline-block; text-align:center; vertical-align:top; }
-.content .stretchable a { color:#717171; text-decoration:none; }
-.content .toc { margin:0; padding:0; list-style:none; }
-.content .links { margin:1em 0; }
-.content .pagination { margin:1em 0; }
-.content .left { float:left; margin:0 1em 0 0; }
-.content .center { display:block; margin:0 auto; }
-.content .right { float:right; margin:0 0 0 1em; }
-.content .rounded { border-radius:4px; }
-
-/* Header */
-
-.header .sitename { display:block; float:left; }
-.header .sitename h1 { margin:0; }
-.header .sitename h1 a { color:#111; text-decoration:none; }
-.header .sitename h2 { margin-top:0; color:#717171; font-size:1.0em; font-weight:300; }
-
-/* Navigation */
-
-.navigation { display:block; float:right; }
-.navigation { margin-top:0.9em; margin-bottom:0.9em; line-height:2; }
-.navigation a { padding:0 0.3em; }
-.navigation ul { margin:0 -0.3em; padding:0; list-style:none; }
-.navigation li { display:inline; }
-.navigation-tree { display:block; float:right; }
-.navigation-tree { margin-top:0.9em; margin-bottom:0.9em; line-height:2; }
-.navigation-tree a { padding:0 0.3em; }
-.navigation-tree ul { margin:0 -0.3em; padding:0; list-style:none; }
-.navigation-tree li { display:inline; }
-.navigation-tree ul li { display:inline-block; position:relative; cursor:pointer; margin:0; }
-.navigation-tree ul li ul { padding:0.3em; position:absolute; width:13em; background:#fff; z-index:100; display:none; }
-.navigation-tree ul li ul { border:1px solid #bbb; border-radius:4px; box-shadow:2px 4px 10px rgba(0, 0, 0, 0.2); }
-.navigation-tree ul li ul li { display:block; }
-.navigation-tree>ul>li:hover>ul { display:block; }
-.navigation-banner { clear:both; }
-.navigation-search { padding-bottom:1em; }
-.navigation-search .search-form { position:relative; }
-.navigation-search .search-text { font-family:inherit; font-size:inherit; font-weight:inherit; }
-.navigation-search .search-text { padding:0.5em; border:1px solid #bbb; border-radius:4px; width:100%; box-sizing:border-box; }
-.navigation-search .search-text { background-color:#fff; background-image:linear-gradient(to bottom, #fff, #fff); }
-.navigation-search .search-button { position:absolute; top:0; right:0; }
-.navigation-search .search-button { font-family:inherit; font-size:inherit; font-weight:inherit; }
-.navigation-search .search-button { margin:5px; padding:0.3em; border:none; background-color:transparent; }
-
-/* Footer */
-
-.footer { margin-top:2em; }
-.footer .siteinfo a { color:#07d; }
-.footer .siteinfo a:hover { color:#07d; text-decoration:underline; }
-.footer .siteinfo a.socialmedia {
- display:inline-block;
- box-sizing:border-box;
- border-radius:13px;
- width:26px;
- height:26px;
- margin:-20px 0;
- padding:1px 0;
- text-align:center;
- background-color:#07d;
- color:#fff;
-}
-.footer .siteinfo a.socialmedia:hover { background-color:#039; color:#fff; }
-.footer .siteinfo-left { float:left; }
-.footer .siteinfo-right { float:right; }
-.footer .siteinfo-banner { clear:both; }
-
-/* Sidebar */
-
-.with-sidebar .main { margin-right:17em; }
-.with-sidebar .sidebar { float:right; width:16em; margin-top:3.9em; padding:2px; overflow:hidden; font-size:0.9em; }
-.with-sidebar .sidebar .search-form input { width:100%; box-sizing:border-box; }
-.with-sidebar .content:after { content:""; display:table; clear:both; }
-
-/* Forms and buttons */
-
-.form-control {
- margin:0; padding:2px 4px;
- display:inline-block; min-width:7em;
- background-color:#fff; color:#555;
- background-image:linear-gradient(to bottom, #fff, #fff);
- border:1px solid #bbb;
- border-radius:4px;
- font-size:0.9em; font-family:inherit; font-weight:normal; line-height:normal;
-}
-.btn {
- margin:0; padding:4px 22px;
- display:inline-block; min-width:7em;
- background-color:#eaeaea; color:#333333;
- background-image:linear-gradient(to bottom, #f8f8f8, #e1e1e1);
- border:1px solid #bbb;
- border-color:#c1c1c1 #c1c1c1 #aaaaaa;
- border-radius:4px;
- outline-offset:-2px;
- font-size:0.9em; font-family:inherit; font-weight:normal; line-height:1;
- text-align:center; text-decoration:none;
-}
-.btn:hover, .btn:focus, .btn:active {
- color:#333333;
- background-image:none;
- text-decoration:none;
-}
-.btn:active { box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.1); }
-
-/* Misc */
-
-.highlight .kw1, .highlight .kw2, .highlight .kw3, .highlight .kw4 { color:#b0b; }
-.highlight .st0, .highlight .st_h, .highlight .nu0 { color:#b0b; }
-.highlight .re0, .highlight .re1, .highlight .re2, .highlight .re3, .css .nu0 { color:inherit; }
-.highlight .co1, .highlight .coMULTI, .highlight .sc0, .highlight .sc-1 { color:inherit; }
-
-/* Responsive and print */
-
-.page { margin:0 auto; max-width:1000px; }
-
-@media screen and (min-width:62em) {
- body { width:60em; margin:1em auto; }
- .page{ margin:0; max-width:none; }
-}
-@media screen and (max-width:32em) {
- body { margin:0.5em; font-size:0.9em; }
- .header .sitename h1, .content h1, .content h2 { font-size:1.3em; }
- .header .sitename h1, .header .sitename h2, .footer, .page { margin:0; padding:0; }
- .header .sitename, .navigation, .navigation-tree { float:none; }
- .navigation { margin-top:0.5em; margin-bottom:0.5em; }
- .navigation-search { padding-bottom:1em; }
- .footer .siteinfo-right { display:none; }
- .footer .siteinfo a.socialmedia { width:24px; height:24px; padding:1px 0; }
- .with-sidebar .main { margin-right:0; }
- .with-sidebar .sidebar { display:none; }
-}
-@media print {
- .page { border:none !important; }
-}
-\ No newline at end of file