System update (file system support)

This commit is contained in:
markseu 2016-02-20 18:34:06 +01:00
parent 58093305a2
commit 8079b6eab8
5 changed files with 220 additions and 217 deletions

View file

@ -1,4 +1,4 @@
Yellow 0.6.2
Yellow 0.6.3
============
[![Yellow](https://raw.githubusercontent.com/wiki/datenstrom/yellow/images/yellow.jpg)](http://datenstrom.se/yellow)

View file

@ -5,7 +5,7 @@
// Command line plugin
class YellowCommandline
{
const Version = "0.6.5";
const Version = "0.6.6";
var $yellow; //access to API
var $files; //number of files
var $errors; //number of errors
@ -88,19 +88,14 @@ class YellowCommandline
list($dummy, $command, $path, $location) = $args;
if(empty($location) || $location[0]=='/')
{
if($this->checkStaticConfig() && $this->checkStaticFilesystem())
if($this->checkStaticConfig())
{
$statusCode = $this->buildStatic($path, $location);
} else {
$statusCode = 500;
$this->files = 0; $this->errors = 1;
if(!$this->checkStaticFilesystem())
{
echo "ERROR building files: Static website not supported on Windows file system!\n";
} else {
$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";
}
$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 "Yellow $command: $this->files file".($this->files!=1 ? 's' : '');
echo ", $this->errors error".($this->errors!=1 ? 's' : '');
@ -132,7 +127,7 @@ class YellowCommandline
}
foreach($this->locationsArgsPagination as $location)
{
if(substru($location, -1) != ':')
if(substru($location, -1) != $this->yellow->toolbox->getLocationArgsSeparator())
{
$statusCode = max($statusCode, $this->buildStaticFile($path, $location, false, true));
}
@ -225,7 +220,7 @@ class YellowCommandline
$serverName = $this->yellow->config->get("serverName");
$serverBase = $this->yellow->config->get("serverBase");
$pagination = $this->yellow->config->get("contentPagination");
preg_match_all("/<a(.*?)href=\"([^\"]+)\"(.*?)>/i", $text, $matches);
preg_match_all("/<(.*?)href=\"([^\"]+)\"(.*?)>/i", $text, $matches);
foreach($matches[2] as $match)
{
if(preg_match("/^(.*?)#(.*)$/", $match, $tokens)) $match = $tokens[1];
@ -344,12 +339,6 @@ class YellowCommandline
$this->yellow->lookup->isValidLocation($serverBase) && $serverBase!="/";
}
// Check static filesystem
function checkStaticFilesystem()
{
return strtoupperu(substru(PHP_OS, 0, 3)) != "WIN";
}
// Check static directory
function checkStaticDirectory($path)
{

View file

@ -5,7 +5,7 @@
// Yellow core
class YellowCore
{
const Version = "0.6.2";
const Version = "0.6.3";
var $page; //current page
var $pages; //pages from file system
var $files; //files from file system
@ -84,6 +84,21 @@ class YellowCore
$this->config->set("contentHomeDir", $pathHome);
}
// Handle command
function command($name, $args = NULL)
{
$statusCode = 0;
if($this->plugins->isExisting($name))
{
$plugin = $this->plugins->plugins[$name];
if(method_exists($plugin["obj"], "onCommand")) $statusCode = $plugin["obj"]->onCommand(func_get_args());
} else {
$statusCode = 500;
$this->page->error($statusCode, "Plugin '$name' does not exist!");
}
return $statusCode;
}
// Handle request
function request()
{
@ -124,8 +139,8 @@ class YellowCore
if($this->toolbox->isRequestCleanUrl($location))
{
$statusCode = 303;
$locationArgs = $this->toolbox->getLocationArgsCleanUrl($this->config->get("contentPagination"));
$location = $this->lookup->normaliseUrl($serverScheme, $serverName, $base, $location.$locationArgs);
$location = $location.$this->getRequestLocationArgsClean();
$location = $this->lookup->normaliseUrl($serverScheme, $serverName, $base, $location);
$this->sendStatus($statusCode, $location);
}
} else {
@ -184,7 +199,7 @@ class YellowCore
}
$this->page = new YellowPage($this);
$this->page->setRequestInformation($serverScheme, $serverName, $base, $location, $fileName);
$this->page->parseData($this->toolbox->getFileData($fileName), $cacheable, $statusCode, $pageError);
$this->page->parseData($this->toolbox->readFile($fileName), $cacheable, $statusCode, $pageError);
$this->text->setLanguage($this->page->get("language"));
$this->page->parseContent();
return $fileName;
@ -229,7 +244,7 @@ class YellowCore
if(!$cacheable) @header("Cache-Control: no-cache, must-revalidate");
@header("Content-Type: ".$this->toolbox->getMimeContentType($fileName));
@header("Last-Modified: ".$lastModifiedFormatted);
echo $this->toolbox->getFileData($fileName);
echo $this->toolbox->readFile($fileName);
}
return $statusCode;
}
@ -246,13 +261,20 @@ class YellowCore
}
}
// Parse snippet
function snippet($name, $args = NULL)
{
$this->pages->snippetArgs = func_get_args();
$this->page->parseSnippet($name);
}
// Return request information
function getRequestInformation($serverScheme = "", $serverName = "", $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->getLocationClean();
$location = $this->toolbox->getLocation();
$location = substru($location, strlenu($base));
if(preg_match("/\.(css|js|jpg|png|txt|woff)$/", $location))
{
@ -270,6 +292,12 @@ class YellowCore
return array($serverScheme, $serverName, $base, $location, $fileName);
}
// Return request location
function getRequestLocationArgsClean()
{
return $this->toolbox->getLocationArgsClean($this->config->get("contentPagination"));
}
// Return request language
function getRequestLanguage()
{
@ -291,7 +319,7 @@ class YellowCore
// Return static file from cache if available
function getStaticFileFromCache($location, $fileName, $cacheable, $statusCode)
{
if(PHP_SAPI != "cli" && $cacheable)
if(PHP_SAPI!="cli" && $cacheable)
{
if($statusCode == 200)
{
@ -328,28 +356,6 @@ class YellowCore
}
return $ok;
}
// Execute command
function command($name, $args = NULL)
{
$statusCode = 0;
if($this->plugins->isExisting($name))
{
$plugin = $this->plugins->plugins[$name];
if(method_exists($plugin["obj"], "onCommand")) $statusCode = $plugin["obj"]->onCommand(func_get_args());
} else {
$statusCode = 500;
$this->page->error($statusCode, "Plugin '$name' does not exist!");
}
return $statusCode;
}
// Execute snippet
function snippet($name, $args = NULL)
{
$this->pages->snippetArgs = func_get_args();
$this->page->parseSnippet($name);
}
}
// Yellow page
@ -418,14 +424,9 @@ class YellowPage
{
if($this->statusCode == 0)
{
$fileHandle = @fopen($this->fileName, "r");
if($fileHandle)
{
$this->statusCode = 200;
$this->rawData = fread($fileHandle, filesize($this->fileName));
fclose($fileHandle);
$this->parseMeta();
}
$this->rawData = $this->yellow->toolbox->readFile($this->fileName);
$this->statusCode = 200;
$this->parseMeta();
}
}
@ -502,7 +503,11 @@ class YellowPage
if(method_exists($plugin["obj"], "onParseContentRaw"))
{
$this->parser = $plugin["obj"];
$this->parserData = $this->parser->onParseContentRaw($this, $this->getContent(true));
$this->parserData = $this->getContent(true);
$this->parserData = preg_replace("/@pageRead/i", $this->get("pageRead"), $this->parserData);
$this->parserData = preg_replace("/@pageEdit/i", $this->get("pageEdit"), $this->parserData);
$this->parserData = preg_replace("/@pageError/i", $this->get("pageError"), $this->parserData);
$this->parserData = $this->parser->onParseContentRaw($this, $this->parserData);
foreach($this->yellow->plugins->plugins as $key=>$value)
{
if(method_exists($value["obj"], "onParseContentText"))
@ -1210,20 +1215,11 @@ class YellowPages
$fileNames = $this->yellow->lookup->findChildrenFromLocation($location);
foreach($fileNames as $fileName)
{
$fileHandle = @fopen($fileName, "r");
if($fileHandle)
{
$fileData = fread($fileHandle, 4096);
$statusCode = filesize($fileName) <= 4096 ? 200 : 0;
fclose($fileHandle);
} else {
$fileData = "";
$statusCode = 0;
}
$page = new YellowPage($this->yellow);
$page->setRequestInformation($serverScheme, $serverName, $base,
$this->yellow->lookup->findLocationFromFile($fileName), $fileName);
$page->parseData($fileData, false, $statusCode);
$page->parseData($this->yellow->toolbox->readFile($fileName, 4096), false, 0);
if(strlenb($page->rawData) < 4096) $page->statusCode = 200;
array_push($this->pages[$location], $page);
}
}
@ -1299,7 +1295,7 @@ class YellowPages
return new YellowPageCollection($this->yellow);
}
// Return available languages
// Return languages in multi language mode
function getLanguages($showInvisible = false)
{
$languages = array();
@ -1612,20 +1608,17 @@ class YellowConfig
// Load configuration from file
function load($fileName)
{
$fileData = @file($fileName);
if($fileData)
if(defined("DEBUG") && DEBUG>=2) echo "YellowConfig::load file:$fileName<br/>\n";
$this->modified = filemtime($fileName);
$fileData = $this->yellow->toolbox->readFile($fileName);
foreach($this->yellow->toolbox->getTextLines($fileData) as $line)
{
if(defined("DEBUG") && DEBUG>=2) echo "YellowConfig::load file:$fileName<br/>\n";
$this->modified = filemtime($fileName);
foreach($fileData as $line)
if(preg_match("/^\#/", $line)) continue;
preg_match("/^\s*(.*?)\s*:\s*(.*?)\s*$/", $line, $matches);
if(!empty($matches[1]) && !strempty($matches[2]))
{
if(preg_match("/^\#/", $line)) continue;
preg_match("/^\s*(.*?)\s*:\s*(.*?)\s*$/", $line, $matches);
if(!empty($matches[1]) && !strempty($matches[2]))
{
$this->set(lcfirst($matches[1]), $matches[2]);
if(defined("DEBUG") && DEBUG>=3) echo "YellowConfig::load ".lcfirst($matches[1]).":$matches[2]<br/>\n";
}
$this->set(lcfirst($matches[1]), $matches[2]);
if(defined("DEBUG") && DEBUG>=3) echo "YellowConfig::load ".lcfirst($matches[1]).":$matches[2]<br/>\n";
}
}
}
@ -1712,26 +1705,22 @@ class YellowText
$regex = "/^".basename($fileName)."$/";
foreach($this->yellow->toolbox->getDirectoryEntries($path, $regex, true, false) as $entry)
{
$fileData = @file($entry);
if($fileData)
if(defined("DEBUG") && DEBUG>=2) echo "YellowText::load file:$entry<br/>\n";
$language = "";
$this->modified = max($this->modified, filemtime($entry));
$fileData = $this->yellow->toolbox->readFile($entry);
foreach($this->yellow->toolbox->getTextLines($fileData) as $line)
{
if(defined("DEBUG") && DEBUG>=2) echo "YellowText::load file:$entry<br/>\n";
$this->modified = max($this->modified, filemtime($entry));
$language = "";
foreach($fileData as $line)
if(preg_match("/^\#/", $line)) continue;
preg_match("/^\s*(.*?)\s*:\s*(.*?)\s*$/", $line, $matches);
if(empty($language))
{
preg_match("/^\s*(.*?)\s*:\s*(.*?)\s*$/", $line, $matches);
if(lcfirst($matches[1])=="language" && !strempty($matches[2])) { $language = $matches[2]; break; }
if(lcfirst($matches[1])=="language" && !strempty($matches[2])) $language = $matches[2];
}
foreach($fileData as $line)
if(!empty($language) && !empty($matches[1]) && !strempty($matches[2]))
{
if(preg_match("/^\#/", $line)) continue;
preg_match("/^\s*(.*?)\s*:\s*(.*?)\s*$/", $line, $matches);
if(!empty($language) && !empty($matches[1]) && !strempty($matches[2]))
{
$this->setText(lcfirst($matches[1]), $matches[2], $language);
if(defined("DEBUG") && DEBUG>=3) echo "YellowText::load ".lcfirst($matches[1]).":$matches[2]<br/>\n";
}
$this->setText(lcfirst($matches[1]), $matches[2], $language);
if(defined("DEBUG") && DEBUG>=3) echo "YellowText::load ".lcfirst($matches[1]).":$matches[2]<br/>\n";
}
}
}
@ -1787,7 +1776,6 @@ class YellowText
} else {
foreach($this->text[$language] as $key=>$value)
{
if(substru($key, 0, strlenu("language")) == "language") $text[$key] = $value;
if(substru($key, 0, strlenu($filterStart)) == $filterStart) $text[$key] = $value;
}
}
@ -1809,6 +1797,14 @@ class YellowText
return date($format, $timestamp);
}
// Return languages
function getLanguages()
{
$languages = array();
foreach($this->text as $key=>$value) array_push($languages, $key);
return $languages;
}
// Return text modification date, Unix time or HTTP format
function getModified($httpFormat = false)
{
@ -2125,6 +2121,7 @@ class YellowLookup
} else if(!preg_match("#^$pageBase#", $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";
@ -2280,52 +2277,52 @@ class YellowToolbox
}
// Return location from current HTTP request
function getLocation()
function getLocation($filterStrict = true)
{
$uri = $_SERVER["REQUEST_URI"];
return rawurldecode(($pos = strposu($uri, '?')) ? substru($uri, 0, $pos) : $uri);
}
// Return location from current HTTP request, remove unwanted path tokens
function getLocationClean()
{
$string = $this->getLocation();
$location = ($string[0]=='/') ? '' : '/';
for($pos=0; $pos<strlenb($string); ++$pos)
$location = $_SERVER["REQUEST_URI"];
$location = rawurldecode(($pos = strposu($location, '?')) ? substru($location, 0, $pos) : $location);
if($filterStrict)
{
if($string[$pos] == '/')
$locationFiltered = "";
if($location[0] != '/') $location = '/'.$location;
for($pos=0; $pos<strlenb($location); ++$pos)
{
if($string[$pos+1] == '/') continue;
if($string[$pos+1] == '.')
if($location[$pos] == '/')
{
$posNew = $pos+1; while($string[$posNew] == '.') ++$posNew;
if($string[$posNew]=='/' || $string[$posNew]=='')
if($location[$pos+1] == '/') continue;
if($location[$pos+1] == '.')
{
$pos = $posNew-1;
continue;
$posNew = $pos+1; while($location[$posNew] == '.') ++$posNew;
if($location[$posNew]=='/' || $location[$posNew]=='')
{
$pos = $posNew-1;
continue;
}
}
}
$locationFiltered .= $location[$pos];
}
$location .= $string[$pos];
}
if(preg_match("/^(.*?\/)([^\/]+:.*)$/", $location, $matches))
{
$_SERVER["LOCATION"] = $location = $matches[1];
$_SERVER["LOCATION_ARGS"] = $matches[2];
foreach(explode('/', $matches[2]) as $token)
$location = $locationFiltered;
$separator = $this->getLocationArgsSeparator();
if(preg_match("/^(.*?\/)([^\/]+$separator.*)$/", $location, $matches))
{
preg_match("/^(.*?):(.*)$/", $token, $matches);
if(!empty($matches[1]) && !strempty($matches[2]))
$_SERVER["LOCATION"] = $location = $matches[1];
$_SERVER["LOCATION_ARGS"] = $matches[2];
foreach(explode('/', $matches[2]) as $token)
{
$matches[1] = strreplaceu(array("\x1c", "\x1d"), array('/', ':'), $matches[1]);
$matches[2] = strreplaceu(array("\x1c", "\x1d"), array('/', ':'), $matches[2]);
$_REQUEST[$matches[1]] = $matches[2];
preg_match("/^(.*?)$separator(.*)$/", $token, $matches);
if(!empty($matches[1]) && !strempty($matches[2]))
{
$matches[1] = strreplaceu(array("\x1c", "\x1d", "\x1e"), array('/', ':', '='), $matches[1]);
$matches[2] = strreplaceu(array("\x1c", "\x1d", "\x1e"), array('/', ':', '='), $matches[2]);
$_REQUEST[$matches[1]] = $matches[2];
}
}
} else {
$_SERVER["LOCATION"] = $location;
$_SERVER["LOCATION_ARGS"] = "";
}
} else {
$_SERVER["LOCATION"] = $location;
$_SERVER["LOCATION_ARGS"] = "";
}
}
return $location;
}
@ -2335,13 +2332,14 @@ class YellowToolbox
return $_SERVER["LOCATION_ARGS"];
}
// Return location arguments from current HTTP request, modify an argument
// Return location arguments from current HTTP request, modify existing arguments
function getLocationArgsNew($arg, $pagination)
{
$separator = $this->getLocationArgsSeparator();
preg_match("/^(.*?):(.*)$/", $arg, $args);
foreach(explode('/', $_SERVER["LOCATION_ARGS"]) as $token)
{
preg_match("/^(.*?):(.*)$/", $token, $matches);
preg_match("/^(.*?)$separator(.*)$/", $token, $matches);
if($matches[1] == $args[1]) { $matches[2] = $args[2]; $found = true; }
if(!empty($matches[1]) && !strempty($matches[2]))
{
@ -2356,43 +2354,51 @@ class YellowToolbox
}
if(!empty($locationArgs))
{
if(!$this->isLocationArgsPagination($locationArgs, $pagination)) $locationArgs .= '/';
$locationArgs = $this->normaliseArgs($locationArgs, false, false);
if(!$this->isLocationArgsPagination($locationArgs, $pagination)) $locationArgs .= '/';
}
return $locationArgs;
}
// Return location arguments from current HTTP request, convert form into clean URL
function getLocationArgsCleanUrl($pagination)
// Return location arguments from current HTTP request, convert form parameters
function getLocationArgsClean($pagination)
{
foreach(array_merge($_GET, $_POST) as $key=>$value)
{
if(!empty($key) && !strempty($value))
{
if(!empty($locationArgs)) $locationArgs .= '/';
$key = strreplaceu(array('/', ':'), array("\x1c", "\x1d"), $key);
$value = strreplaceu(array('/', ':'), array("\x1c", "\x1d"), $value);
$key = strreplaceu(array('/', ':', '='), array("\x1c", "\x1d", "\x1e"), $key);
$value = strreplaceu(array('/', ':', '='), array("\x1c", "\x1d", "\x1e"), $value);
$locationArgs .= "$key:$value";
}
}
if(!empty($locationArgs))
{
if(!$this->isLocationArgsPagination($locationArgs, $pagination)) $locationArgs .= '/';
$locationArgs = $this->normaliseArgs($locationArgs, false, false);
if(!$this->isLocationArgsPagination($locationArgs, $pagination)) $locationArgs .= '/';
}
return $locationArgs;
}
// Return location arguments separator
function getLocationArgsSeparator()
{
return (strtoupperu(substru(PHP_OS, 0, 3)) != "WIN") ? ':' : '=';
}
// Check if location contains location arguments
function isLocationArgs($location)
{
return preg_match("/[^\/]+:.*$/", $location);
$separator = $this->getLocationArgsSeparator();
return preg_match("/[^\/]+$separator.*$/", $location);
}
// Check if location contains pagination arguments
function isLocationArgsPagination($location, $pagination)
{
return preg_match("/^(.*\/)?$pagination:.*$/", $location);
$separator = $this->getLocationArgsSeparator();
return preg_match("/^(.*\/)?$pagination$separator.*$/", $location);
}
// Check if script location is requested
@ -2429,7 +2435,8 @@ class YellowToolbox
{
if($appendSlash) $text .= '/';
if($filterStrict) $text = strreplaceu(' ', '-', strtoloweru($text));
return strreplaceu(array('%3A','%2F'), array(':','/'), rawurlencode($text));
$text = strreplaceu(':', $this->getLocationArgsSeparator(), $text);
return strreplaceu(array('%2F','%3A','%3D'), array('/',':','='), rawurlencode($text));
}
// Normalise text into UTF-8 NFC
@ -2610,7 +2617,7 @@ class YellowToolbox
$path = dirname($fileName);
if(!empty($path) && !is_dir($path)) @mkdir($path, 0777, true);
}
$fileHandle = @fopen($fileName, "w");
$fileHandle = @fopen($fileName, "wb");
if($fileHandle)
{
fwrite($fileHandle, $fileData);

View file

@ -1,11 +1,11 @@
<?php
// Copyright (c) 2013-2015 Datenstrom, http://datenstrom.se
// Copyright (c) 2013-2016 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.1";
const Version = "0.6.2";
var $yellow; //access to API
// Handle initialisation
@ -43,16 +43,6 @@ class YellowMarkdownParser extends MarkdownExtraParser
};
parent::__construct();
}
// Transform text
function transform($text)
{
$text = preg_replace("/@pageRead/i", $this->page->get("pageRead"), $text);
$text = preg_replace("/@pageEdit/i", $this->page->get("pageEdit"), $text);
$text = preg_replace("/@pageError/i", $this->page->get("pageError"), $text);
$text = preg_replace("/@pageFile/i", $this->page->get("pageFile"), $text);
return parent::transform($text);
}
// Return unique id attribute
function getIdAttribute($text)
@ -209,7 +199,7 @@ class MarkdownParser {
### Version ###
const MARKDOWNLIB_VERSION = "1.5.0";
const MARKDOWNLIB_VERSION = "1.6.0";
### Simple Function Interface ###
@ -1818,6 +1808,11 @@ class MarkdownExtraParser extends MarkdownParser {
public $fn_link_class = "footnote-ref";
public $fn_backlink_class = "footnote-backref";
# Content to be displayed within footnote backlinks. The default is '↩';
# the U+FE0E on the end is a Unicode variant selector used to prevent iOS
# from displaying the arrow character as an emoji.
public $fn_backlink_html = '&#8617;&#xFE0E;';
# Class name for table cell alignment (%% replaced left/center/right)
# For instance: 'go-%%' becomes 'go-left' or 'go-right' or 'go-center'
# If empty, the align attribute is used instead of a class name.
@ -1917,9 +1912,9 @@ class MarkdownExtraParser extends MarkdownParser {
### Extra Attribute Parser ###
# Expression to use to catch attributes (includes the braces)
protected $id_class_attr_catch_re = '\{((?:[ ]*[#.a-z][-_:a-zA-Z0-9=]+){1,})[ ]*\}';
protected $id_class_attr_catch_re = '\{((?>[ ]*[#.a-z][-_:a-zA-Z0-9=]+){1,})[ ]*\}';
# Expression to use when parsing in a context when no capture is desired
protected $id_class_attr_nocatch_re = '\{(?:[ ]*[#.a-z][-_:a-zA-Z0-9=]+){1,}[ ]*\}';
protected $id_class_attr_nocatch_re = '\{(?>[ ]*[#.a-z][-_:a-zA-Z0-9=]+){1,}[ ]*\}';
protected function doExtraAttributes($tag_name, $attr, $defaultIdValue = null, $classes = array()) {
#
@ -3261,6 +3256,7 @@ class MarkdownExtraParser extends MarkdownParser {
$title = $this->encodeAttribute($title);
$attr .= " title=\"$title\"";
}
$backlink_text = $this->fn_backlink_html;
$num = 0;
while (!empty($this->footnotes_ordered)) {
@ -3280,9 +3276,9 @@ class MarkdownExtraParser extends MarkdownParser {
$note_id = $this->encodeAttribute($note_id);
# Prepare backlink, multiple backlinks if multiple references
$backlink = "<a href=\"#fnref:$note_id\"$attr>&#8617;</a>";
$backlink = "<a href=\"#fnref:$note_id\"$attr>$backlink_text</a>";
for ($ref_num = 2; $ref_num <= $ref_count; ++$ref_num) {
$backlink .= " <a href=\"#fnref$ref_num:$note_id\"$attr>&#8617;</a>";
$backlink .= " <a href=\"#fnref$ref_num:$note_id\"$attr>$backlink_text</a>";
}
# Add backlink to last paragraph; create new paragraph if needed.
if (preg_match('{</p>$}', $footnote)) {

View file

@ -1,11 +1,11 @@
<?php
// Copyright (c) 2013-2015 Datenstrom, http://datenstrom.se
// Copyright (c) 2013-2016 Datenstrom, http://datenstrom.se
// This file may be used and distributed under the terms of the public license.
// Web interface plugin
class YellowWebinterface
{
const Version = "0.6.3";
const Version = "0.6.4";
var $yellow; //access to API
var $active; //web interface is active? (boolean)
var $userLoginFailed; //web interface login failed? (boolean)
@ -21,9 +21,9 @@ class YellowWebinterface
$this->yellow = $yellow;
$this->users = new YellowUsers($yellow);
$this->merge = new YellowMerge($yellow);
$this->yellow->config->setDefault("webinterfaceLocation", "/edit/");
$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("webinterfaceUserHashAlgorithm", "bcrypt");
$this->yellow->config->setDefault("webinterfaceUserHashCost", "10");
$this->yellow->config->setDefault("webinterfaceUserHome", "/");
@ -67,7 +67,7 @@ class YellowWebinterface
if($page->statusCode == 424)
{
$title = $this->yellow->toolbox->createTextTitle($page->location);
$this->rawDataEdit = $this->getDataNew($title);
$this->rawDataEdit = $this->getRawDataNew($title);
}
}
}
@ -99,21 +99,9 @@ class YellowWebinterface
$output .= "<script type=\"text/javascript\" src=\"".htmlspecialchars($location).".js\"></script>\n";
$output .= "<script type=\"text/javascript\">\n";
$output .= "// <![CDATA[\n";
if($this->isUser())
{
$output .= "yellow.page.title = ".json_encode($this->getDataTitle($this->rawDataEdit)).";\n";
$output .= "yellow.page.rawDataSource = ".json_encode($this->rawDataSource).";\n";
$output .= "yellow.page.rawDataEdit = ".json_encode($this->rawDataEdit).";\n";
$output .= "yellow.page.rawDataNew = ".json_encode($this->getDataNew()).";\n";
$output .= "yellow.page.pageFile = ".json_encode($this->yellow->page->get("pageFile")).";\n";
$output .= "yellow.page.userPermission = ".json_encode($this->userPermission).";\n";
$output .= "yellow.page.parserSafeMode = ".json_encode($this->yellow->page->parserSafeMode).";\n";
$output .= "yellow.page.statusCode = ".json_encode($this->yellow->page->statusCode).";\n";
}
$output .= "yellow.config = ".json_encode($this->getDataConfig()).";\n";
$language = $this->isUser() ? $this->users->getLanguage() : $this->yellow->page->get("language");
if(!$this->yellow->text->isLanguage($language)) $language = $this->yellow->config->get("language");
$output .= "yellow.text = ".json_encode($this->yellow->text->getData("webinterface", $language)).";\n";
$output .= "yellow.page = ".json_encode($this->getPageData()).";\n";
$output .= "yellow.config = ".json_encode($this->getConfigData()).";\n";
$output .= "yellow.text = ".json_encode($this->getTextData()).";\n";
if(defined("DEBUG") && DEBUG>=1) $output .= "yellow.debug = ".json_encode(DEBUG).";\n";
$output .= "// ]]>\n";
$output .= "</script>\n";
@ -260,7 +248,7 @@ class YellowWebinterface
$this->rawDataSource = rawurldecode($_POST["rawdatasource"]);
$this->rawDataEdit = rawurldecode($_POST["rawdataedit"]);
$page = $this->getPageUpdate($serverScheme, $serverName, $base, $location, $fileName,
$this->rawDataSource, $this->rawDataEdit, $this->yellow->toolbox->getFileData($fileName));
$this->rawDataSource, $this->rawDataEdit, $this->yellow->toolbox->readFile($fileName));
if(!$page->isError())
{
if($this->yellow->toolbox->renameFile($fileName, $page->fileName) &&
@ -511,14 +499,14 @@ class YellowWebinterface
return $page;
}
// Return content data for new page
function getDataNew($title = "")
// Return raw data for new page
function getRawDataNew($title = "")
{
$fileName = $this->yellow->lookup->findFileFromLocation($this->yellow->page->location);
$fileName = $this->yellow->lookup->findFileNew($fileName,
$this->yellow->config->get("webinterfaceNewFile"), $this->yellow->config->get("configDir"),
$this->yellow->config->get("template"));
$fileData = $this->yellow->toolbox->getFileData($fileName);
$fileData = $this->yellow->toolbox->readFile($fileName);
$fileData = preg_replace("/@datetime/i", date("Y-m-d H:i:s"), $fileData);
$fileData = preg_replace("/@date/i", date("Y-m-d"), $fileData);
$fileData = preg_replace("/@username/i", $this->users->getName(), $fileData);
@ -527,8 +515,26 @@ class YellowWebinterface
return $fileData;
}
// Return configuration data including information of current user
function getDataConfig()
// Return page data including webinterface information
function getPageData()
{
$data = array();
if($this->isUser())
{
$data["title"] = $this->getDataTitle($this->rawDataEdit);
$data["rawDataSource"] = $this->rawDataSource;
$data["rawDataEdit"] = $this->rawDataEdit;
$data["rawDataNew"] = $this->getRawDataNew();
$data["userPermission"] = $this->userPermission;
$data["pageFile"] = $this->yellow->page->get("pageFile");
$data["parserSafeMode"] = $this->yellow->page->parserSafeMode;
$data["statusCode"] = $this->yellow->page->statusCode;
}
return $data;
}
// Return configuration data including user information
function getConfigData()
{
$data = $this->yellow->config->getData("", "Location");
if($this->isUser())
@ -541,6 +547,8 @@ class YellowWebinterface
$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"] = $this->yellow->text->getLanguages();
} else {
$data["login"] = $this->yellow->page->statusCode==200;
$data["loginEmail"] = $this->yellow->config->get("loginEmail");
@ -549,6 +557,17 @@ class YellowWebinterface
return $data;
}
// Return text strings
function getTextData()
{
$language = $this->isUser() ? $this->users->getLanguage() : $this->yellow->page->get("language");
if(!$this->yellow->text->isLanguage($language)) $language = $this->yellow->config->get("language");
$textLanguage = array_merge($this->yellow->text->getData("language", $language));
$textWebinterface = array_merge($this->yellow->text->getData("webinterface", $language));
$textYellow = array_merge($this->yellow->text->getData("yellow", $language));
return array_merge($textLanguage, $textWebinterface, $textYellow);
}
// Check if web interface request
function isActive()
{
@ -576,22 +595,19 @@ class YellowUsers
}
// Load users from file
function load($fileName)
function load($fileName)
{
$fileData = @file($fileName);
if($fileData)
if(defined("DEBUG") && DEBUG>=2) echo "YellowUsers::load file:$fileName<br/>\n";
$fileData = $this->yellow->toolbox->readFile($fileName);
foreach($this->yellow->toolbox->getTextLines($fileData) as $line)
{
if(defined("DEBUG") && DEBUG>=2) echo "YellowUsers::load file:$fileName<br/>\n";
foreach($fileData as $line)
if(preg_match("/^\#/", $line)) continue;
preg_match("/^(.*?)\s*:\s*(.*?),\s*(.*?),\s*(.*?),\s*(.*?),\s*(.*?)\s*$/", $line, $matches);
if(!empty($matches[1]) && !empty($matches[2]) && !empty($matches[3]) && !empty($matches[4]) &&
!empty($matches[5]) && !empty($matches[6]))
{
if(preg_match("/^\#/", $line)) continue;
preg_match("/^(.*?)\s*:\s*(.*?),\s*(.*?),\s*(.*?),\s*(.*?),\s*(.*?)\s*$/", $line, $matches);
if(!empty($matches[1]) && !empty($matches[2]) && !empty($matches[3]) && !empty($matches[4]) &&
!empty($matches[5]) && !empty($matches[6]))
{
$this->set($matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]);
if(defined("DEBUG") && DEBUG>=3) echo "YellowUsers::load email:$matches[1]<br/>\n";
}
$this->set($matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]);
if(defined("DEBUG") && DEBUG>=3) echo "YellowUsers::load email:$matches[1]<br/>\n";
}
}
}
@ -613,28 +629,25 @@ class YellowUsers
{
$email = strreplaceu(',', '-', $email);
$hash = strreplaceu(',', '-', $hash);
$fileData = @file($fileName);
if($fileData)
$fileData = $this->yellow->toolbox->readFile($fileName);
foreach($this->yellow->toolbox->getTextLines($fileData) as $line)
{
foreach($fileData as $line)
preg_match("/^(.*?)\s*:\s*(.*?),\s*(.*?),\s*(.*?),\s*(.*?),\s*(.*?)\s*$/", $line, $matches);
if(!empty($matches[1]) && !empty($matches[2]) && !empty($matches[3]) && !empty($matches[4]) &&
!empty($matches[5]) && !empty($matches[6]))
{
preg_match("/^(.*?)\s*:\s*(.*?),\s*(.*?),\s*(.*?),\s*(.*?),\s*(.*?)\s*$/", $line, $matches);
if(!empty($matches[1]) && !empty($matches[2]) && !empty($matches[3]) && !empty($matches[4]) &&
!empty($matches[5]) && !empty($matches[6]))
if($matches[1] == $email)
{
if($matches[1] == $email)
{
$name = strreplaceu(',', '-', empty($name) ? $matches[3] : $name);
$language = strreplaceu(',', '-', empty($language) ? $matches[4] : $language);
$status = strreplaceu(',', '-', empty($status) ? $matches[5] : $status);
$home = strreplaceu(',', '-', empty($home) ? $matches[6] : $home);
$fileDataNew .= "$email: $hash,$name,$language,$status,$home\n";
$found = true;
continue;
}
$name = strreplaceu(',', '-', empty($name) ? $matches[3] : $name);
$language = strreplaceu(',', '-', empty($language) ? $matches[4] : $language);
$status = strreplaceu(',', '-', empty($status) ? $matches[5] : $status);
$home = strreplaceu(',', '-', empty($home) ? $matches[6] : $home);
$fileDataNew .= "$email: $hash,$name,$language,$status,$home\n";
$found = true;
continue;
}
$fileDataNew .= $line;
}
$fileDataNew .= $line;
}
if(!$found)
{
@ -661,7 +674,6 @@ class YellowUsers
if($this->isExisting($email))
{
$serverScheme = $this->yellow->config->get("webinterfaceServerScheme");
$serverName = $this->yellow->config->get("webinterfaceServerName");
$location = $this->yellow->config->get("serverBase").$this->yellow->config->get("webinterfaceLocation");
$session = $this->yellow->toolbox->createHash($this->users[$email]["hash"], "sha256");
if(empty($session)) $session = "error-hash-algorithm-sha256";
@ -673,7 +685,6 @@ class YellowUsers
function destroyCookie($cookieName)
{
$serverScheme = $this->yellow->config->get("webinterfaceServerScheme");
$serverName = $this->yellow->config->get("webinterfaceServerName");
$location = $this->yellow->config->get("serverBase").$this->yellow->config->get("webinterfaceLocation");
setcookie($cookieName, "", time()-3600, $location, "", $serverScheme=="https");
}