(.+?\<\/p\>)/s", $text, $parsedDescription, PREG_SET_ORDER);
+ foreach($parsedDescription as $matches)
+ {
+ preg_match_all("/([^\<]*)[^\>]+./s", $matches[1], $parsedUndoTag, PREG_SET_ORDER);
+ if(count($parsedUndoTag) > 0)
+ {
+ if(!empty($description)) $description .= " ";
+ foreach($parsedUndoTag as $matchTag)
+ {
+ $description .= preg_replace("/[\\x00-\\x1f]+/s", " ", $matchTag[1]);
+ }
+ }
+ if(strlen($description) > $lengthMax)
+ {
+ $description = substr($description, 0, $lengthMax-3)."...";
+ break;
+ }
+ }
+ return $description;
+ }
- // Create keywords from text string
- static function createTextKeywords($text, $keywordsMax)
- {
- $tokens = preg_split("/[,\s\(\)]/", strtolower($text));
- foreach($tokens as $key => $value) if(strlen($value) < 3) unset($tokens[$key]);
- return implode(", ", array_slice(array_unique($tokens), 0, $keywordsMax));
- }
-
- // Create title from text string
- static function createTextTitle($text)
- {
- if(preg_match("/^.*\/(\w*)/", $text, $matches)) $text = ucfirst($matches[1]);
- return $text;
- }
+ // Create keywords from text string
+ static function createTextKeywords($text, $keywordsMax)
+ {
+ $tokens = preg_split("/[,\s\(\)]/", strtolower($text));
+ foreach($tokens as $key => $value) if(strlen($value) < 3) unset($tokens[$key]);
+ return implode(", ", array_slice(array_unique($tokens), 0, $keywordsMax));
+ }
+
+ // Create title from text string
+ static function createTextTitle($text)
+ {
+ if(preg_match("/^.*\/(\w*)/", $text, $matches)) $text = ucfirst($matches[1]);
+ return $text;
+ }
+
+ // Detect web browser language
+ function detectBrowserLanguage($languagesAllowed, $languageDefault)
+ {
+ $language = $languageDefault;
+ if(isset($_SERVER["HTTP_ACCEPT_LANGUAGE"]))
+ {
+ foreach(preg_split("/,\s*/", $_SERVER["HTTP_ACCEPT_LANGUAGE"]) as $string)
+ {
+ $tokens = split(";", $string, 2);
+ if(in_array($tokens[0], $languagesAllowed))
+ {
+ $language = $tokens[0];
+ break;
+ }
+ }
+ }
+ return $language;
+ }
- // Detect PNG and JPG image dimensions
- static function detectImageDimensions($fileName)
- {
- $width = $height = 0;
- $fileHandle = @fopen($fileName, "rb");
- if($fileHandle)
- {
- if(substr($fileName, -3) == "png")
- {
- $dataSignature = fread($fileHandle, 8);
- $dataHeader = fread($fileHandle, 25);
- if(!feof($fileHandle) && $dataSignature=="\x89PNG\r\n\x1a\n")
- {
- $width = (ord($dataHeader[10])<<8) + ord($dataHeader[11]);
- $height = (ord($dataHeader[14])<<8) + ord($dataHeader[15]);
- }
- } else if(substr($fileName, -3) == "jpg") {
- $dataSignature = fread($fileHandle, 11);
- $dataHeader = fread($fileHandle, 147);
- $dataHeader = fread($fileHandle, 16);
- if(!feof($fileHandle) && $dataSignature=="\xff\xd8\xff\xe0\x00\x10JFIF\0")
- {
- $width = (ord($dataHeader[7])<<8) + ord($dataHeader[8]);
- $height = (ord($dataHeader[5])<<8) + ord($dataHeader[6]);
- }
- }
- fclose($fileHandle);
- }
- return array($width, $height);
- }
+ // Detect PNG and JPG image dimensions
+ static function detectImageDimensions($fileName)
+ {
+ $width = $height = 0;
+ $fileHandle = @fopen($fileName, "rb");
+ if($fileHandle)
+ {
+ if(substr($fileName, -3) == "png")
+ {
+ $dataSignature = fread($fileHandle, 8);
+ $dataHeader = fread($fileHandle, 25);
+ if(!feof($fileHandle) && $dataSignature=="\x89PNG\r\n\x1a\n")
+ {
+ $width = (ord($dataHeader[10])<<8) + ord($dataHeader[11]);
+ $height = (ord($dataHeader[14])<<8) + ord($dataHeader[15]);
+ }
+ } else if(substr($fileName, -3) == "jpg") {
+ $dataSignature = fread($fileHandle, 11);
+ $dataHeader = fread($fileHandle, 147);
+ $dataHeader = fread($fileHandle, 16);
+ if(!feof($fileHandle) && $dataSignature=="\xff\xd8\xff\xe0\x00\x10JFIF\0")
+ {
+ $width = (ord($dataHeader[7])<<8) + ord($dataHeader[8]);
+ $height = (ord($dataHeader[5])<<8) + ord($dataHeader[6]);
+ }
+ }
+ fclose($fileHandle);
+ }
+ return array($width, $height);
+ }
- // Start timer
- static function timerStart(&$time)
- {
- $time = microtime(true);
- }
-
- // Stop timer and calcuate elapsed time (milliseconds)
- static function timerStop(&$time)
- {
- $time = intval((microtime(true)-$time) * 1000);
- }
+ // Start timer
+ static function timerStart(&$time)
+ {
+ $time = microtime(true);
+ }
+
+ // Stop timer and calcuate elapsed time (milliseconds)
+ static function timerStop(&$time)
+ {
+ $time = intval((microtime(true)-$time) * 1000);
+ }
}
// Yellow configuration
class Yellow_Config
{
- var $config; //configuration
- var $configDefaults; //configuration defaults
-
- function __construct()
- {
- $this->config = array();
- $this->configDefaults = array();
- }
-
- // Load configuration from file
- function load($fileName)
- {
- $fileData = @file($fileName);
- if($fileData)
- {
- foreach($fileData as $line)
- {
- if(preg_match("/^\//", $line)) continue;
- preg_match("/^\s*(.*?)\s*=\s*(.*?)\s*$/", $line, $matches);
- if($matches[1]!="" && $matches[2]!="")
- {
- $this->set($matches[1], $matches[2]);
- if(defined("DEBUG") && DEBUG>=3) echo "Yellow_Config::load key:$matches[1] $matches[2]
\n";
- }
- }
- }
- }
-
- // Set default configuration
- function setDefault($key, $value)
- {
- $this->configDefaults[$key] = $value;
- }
-
- // Set configuration
- function set($key, $value)
- {
- $this->config[$key] = $value;
- }
-
- // Return configuration
- function get($key)
- {
- return is_null($this->config[$key]) ? $this->configDefaults[$key] : $this->config[$key];
- }
-
- // Return configuration, HTML encoded
- function getHtml($key)
- {
- return htmlspecialchars($this->get($key));
- }
-
- // Check if configuration exists
- function isExisting($key)
- {
- return !is_null($this->config[$key]);
- }
+ var $config; //configuration
+ var $configDefaults; //configuration defaults
+
+ function __construct()
+ {
+ $this->config = array();
+ $this->configDefaults = array();
+ }
+
+ // Load configuration from file
+ function load($fileName)
+ {
+ $fileData = @file($fileName);
+ if($fileData)
+ {
+ if(defined("DEBUG") && DEBUG>=2) echo "Yellow_Config::load file:$fileName
\n";
+ foreach($fileData as $line)
+ {
+ if(preg_match("/^\//", $line)) continue;
+ preg_match("/^\s*(.*?)\s*=\s*(.*?)\s*$/", $line, $matches);
+ if($matches[1]!="" && $matches[2]!="")
+ {
+ $this->set($matches[1], $matches[2]);
+ if(defined("DEBUG") && DEBUG>=3) echo "Yellow_Config::load key:$matches[1] $matches[2]
\n";
+ }
+ }
+ }
+ }
+
+ // Set default configuration
+ function setDefault($key, $value)
+ {
+ $this->configDefaults[$key] = $value;
+ }
+
+ // Set configuration
+ function set($key, $value)
+ {
+ $this->config[$key] = $value;
+ }
+
+ // Return configuration
+ function get($key)
+ {
+ return $this->isExisting($key) ? $this->config[$key] : $this->configDefaults[$key];
+ }
+
+ // Return configuration, HTML encoded
+ function getHtml($key)
+ {
+ return htmlspecialchars($this->get($key));
+ }
+
+ // Return configuration strings
+ function getData($filterEnd = "")
+ {
+ $config = array();
+ if($filterEnd == "")
+ {
+ $config = $this->config;
+ } else {
+ foreach($this->config as $key=>$value)
+ {
+ if(substr($key, -strlen($filterEnd)) == $filterEnd) $config[$key] = $value;
+ }
+ }
+ return $config;
+ }
+
+ // Check if configuration exists
+ function isExisting($key)
+ {
+ return !is_null($this->config[$key]);
+ }
+}
+
+// Yellow text strings
+class Yellow_Text
+{
+ var $text; //text strings
+ var $language; //current language
+
+ function __construct()
+ {
+ $this->text = array();
+ }
+
+ // Load text strings from file
+ function load($fileName, $toolbox)
+ {
+ $path = dirname($fileName);
+ $regex = basename($fileName);
+ foreach($toolbox->getDirectoryEntries($path, "/$regex/", true, false) as $entry)
+ {
+ $fileData = @file("$path/$entry");
+ if($fileData)
+ {
+ if(defined("DEBUG") && DEBUG>=2) echo "Yellow_Text::load file:$path/$entry
\n";
+ $language = "";
+ foreach($fileData as $line)
+ {
+ preg_match("/^\s*(.*?)\s*=\s*(.*?)\s*$/", $line, $matches);
+ if($matches[1]=="language" && $matches[2]!="") { $language = $matches[2]; break; }
+ }
+ foreach($fileData as $line)
+ {
+ if(preg_match("/^\//", $line)) continue;
+ preg_match("/^\s*(.*?)\s*=\s*(.*?)\s*$/", $line, $matches);
+ if($language!="" && $matches[1]!="" && $matches[2]!="")
+ {
+ $this->setLanguageText($language, $matches[1], $matches[2]);
+ if(defined("DEBUG") && DEBUG>=3) echo "Yellow_Text::load key:$matches[1] $matches[2]
\n";
+ }
+ }
+ }
+ }
+ }
+
+ // Set current language
+ function setLanguage($language)
+ {
+ $this->language = $language;
+ }
+
+ // Set text string
+ function setLanguageText($language, $key, $value)
+ {
+ if(is_null($this->text[$language])) $this->text[$language] = array();
+ $this->text[$language][$key] = $value;
+ }
+
+ // Return text string
+ function get($key)
+ {
+ return $this->isExisting($key) ? $this->text[$this->language][$key] : "[$key]";
+ }
+
+ // Return text string, HTML encoded
+ function getHtml($key)
+ {
+ return htmlspecialchars($this->get($key));
+ }
+
+ // Return text strings
+ function getData($language, $filterStart = "")
+ {
+ $text = array();
+ if(!is_null($this->text[$language]))
+ {
+ if($filterStart == "")
+ {
+ $text = $this->text[$language];
+ } else {
+ foreach($this->text[$language] as $key=>$value)
+ {
+ if(substr($key, 0, strlen("language")) == "language") $text[$key] = $value;
+ if(substr($key, 0, strlen($filterStart)) == $filterStart) $text[$key] = $value;
+ }
+ }
+ }
+ return $text;
+ }
+
+ // Check if text string exists
+ function isExisting($key)
+ {
+ return !is_null($this->text[$this->language]) && !is_null($this->text[$this->language][$key]);
+ }
}
// Yellow plugins
class Yellow_Plugins
{
- var $plugins; //registered plugins
+ var $plugins; //registered plugins
- function __construct()
- {
- $this->plugins = array();
- }
-
- // Load plugins
- function load()
+ function __construct()
+ {
+ $this->plugins = array();
+ }
+
+ // Load plugins
+ function load()
{
global $yellow;
- require_once("core_markdown.php");
- require_once("core_rawhtml.php");
- foreach($yellow->toolbox->getDirectoryEntries($yellow->config->get("pluginDir")) as $entry)
- {
- $fileName = "$entry/plugin_$entry.php";
- if(is_file($fileName)) require_once($fileName);
- }
- foreach($this->plugins as $key=>$value)
+ require_once("core_markdown.php");
+ require_once("core_rawhtml.php");
+ require_once("core_webinterface.php");
+ foreach($yellow->toolbox->getDirectoryEntries($yellow->config->get("pluginDir"), "/.*\.php/", true, false) as $entry)
{
- $this->plugins[$key]["obj"] = new $value["class"];
- if(defined("DEBUG") && DEBUG>=2) echo "Yellow_Plugins::load class:$value[class] $value[version]
\n";
- if(method_exists($this->plugins[$key]["obj"], "initPlugin"))
- {
- $this->plugins[$key]["obj"]->initPlugin($yellow);
- }
+ $fileName = $yellow->config->get("pluginDir")."/$entry";
+ require_once($fileName);
+ }
+ foreach($this->plugins as $key=>$value)
+ {
+ $this->plugins[$key]["obj"] = new $value["class"];
+ if(defined("DEBUG") && DEBUG>=2) echo "Yellow_Plugins::load class:$value[class] $value[version]
\n";
+ if(method_exists($this->plugins[$key]["obj"], "initPlugin"))
+ {
+ $this->plugins[$key]["obj"]->initPlugin($yellow);
+ }
}
}
-
- // Register plugin
+
+ // Register plugin
function register($name, $class, $version)
{
- if(is_null($this->plugins[$name]))
- {
- $this->plugins[$name] = array();
- $this->plugins[$name]["class"] = $class;
- $this->plugins[$name]["version"] = $version;
- }
+ if(!$this->isExisting($name))
+ {
+ $this->plugins[$name] = array();
+ $this->plugins[$name]["class"] = $class;
+ $this->plugins[$name]["version"] = $version;
+ }
+ }
+
+ // Check if plugin exists
+ function isExisting($name)
+ {
+ return !is_null($this->plugins[$name]);
}
}
?>
\ No newline at end of file
diff --git a/system/core/core_markdown.php b/system/core/core_markdown.php
index 9f1d028..8db6636 100755
--- a/system/core/core_markdown.php
+++ b/system/core/core_markdown.php
@@ -5,51 +5,60 @@
// Markdown parser core plugin
class Yellow_Markdown
{
- var $markdown; //markdown parser
- var $html; //generated HTML
-
- // Initialise plugin
+ const Version = "0.1.1";
+ var $markdown; //markdown parser
+ var $html; //generated HTML
+
+ // Initialise plugin
function initPlugin($yellow)
{
$this->markdown = new Yellow_MarkdownExtraParser($yellow);
}
-
- // Parse text
+
+ // Parse text
function parse($text)
{
return $this->html = $this->markdown->transform($text);
}
}
-
+
require("markdown.php");
class Yellow_MarkdownExtraParser extends MarkdownExtra_Parser
{
- var $yellow; //access to API
+ var $yellow; //access to API
- function __construct($yellow)
- {
- $this->yellow = $yellow;
- parent::__construct();
- }
-
- // Handle images
+ function __construct($yellow)
+ {
+ $this->yellow = $yellow;
+ parent::__construct();
+ }
+
+ // Transform text
+ function transform($text)
+ {
+ $baseLocation = $this->yellow->config->get("baseLocation");
+ $text = preg_replace("/@baseLocation/i", $baseLocation, $text);
+ return parent::transform($text);
+ }
+
+ // Handle images
function _doImages_inline_callback($matches)
- {
+ {
$path = $matches[3]=="" ? $matches[4] : $matches[3];
- $src = $this->yellow->config->get("baseLocation").$this->yellow->config->get("imagesLocation").$path;
- list($width, $height) = $this->yellow->toolbox->detectImageDimensions(".".$this->yellow->config->get("imagesLocation").$path);
+ $src = $this->yellow->config->get("baseLocation").$this->yellow->config->get("imagesLocation").$path;
+ list($width, $height) = $this->yellow->toolbox->detectImageDimensions(".".$this->yellow->config->get("imagesLocation").$path);
$alt = $matches[2];
- $title =& $matches[7];
-
+ $title = $matches[7];
+
$result = "encodeAttribute($src)."\"";
- if($width && $height) $result .= " width=\"$width\" height=\"$height\"";
- if(isset($alt)) $result .= " alt=\"".$this->encodeAttribute($alt)."\"";
+ if($width && $height) $result .= " width=\"$width\" height=\"$height\"";
+ if(isset($alt)) $result .= " alt=\"".$this->encodeAttribute($alt)."\"";
if(isset($title)) $result .= " title=\"".$this->encodeAttribute($title)."\"";
$result .= $this->empty_element_suffix;
-
+
return $this->hashPart($result);
}
}
-$yellow->registerPlugin("markdown", "Yellow_Markdown", "0.1.0");
+$yellow->registerPlugin("markdown", "Yellow_Markdown", Yellow_Markdown::Version);
?>
\ No newline at end of file
diff --git a/system/core/core_rawhtml.php b/system/core/core_rawhtml.php
index 8ef107b..43a6d50 100755
--- a/system/core/core_rawhtml.php
+++ b/system/core/core_rawhtml.php
@@ -5,14 +5,15 @@
// Raw HTML parser core plugin
class Yellow_RawHtml
{
- var $html; //generated HTML
+ const Version = "0.1.1";
+ var $html; //generated HTML
- // Parse text, dummy transformation
+ // Parse text, dummy transformation
function parse($text)
{
return $this->html = $text;
}
}
-$yellow->registerPlugin("rawhtml", "Yellow_RawHtml", "0.1.0");
+$yellow->registerPlugin("rawhtml", "Yellow_RawHtml", Yellow_RawHtml::Version);
?>
\ No newline at end of file
diff --git a/system/core/core_webinterface.css b/system/core/core_webinterface.css
new file mode 100644
index 0000000..08b2385
--- /dev/null
+++ b/system/core/core_webinterface.css
@@ -0,0 +1,25 @@
+.yellowlogin { width:600px; position:absolute; top:5px; padding:30px; border:1px solid #ccc; background:#fff; color:#000; }
+.yellowlogin h1 { margin:0px; padding:0px; }
+.yellowlogin p { margin:0.5em; text-align:right; }
+
+.yellowbar { width:600px; position:absolute; top:1px; background:#fff; color:#000; }
+.yellowbar img { vertical-align:top; }
+.yellowbar button { color:#05d; padding-left:0.5em; padding-right:0.5em; }
+.yellowbar button:hover { color:#f00; }
+.yellowbarleft { margin-left:0px; display:block; float:left; height:100%; }
+.yellowbarright { margin-right:0px; display:block; float:right; height:100%; }
+.yellowbarlink { cursor:pointer; font:inherit; background:none; border:none; margin:0px padding:0px; }
+.yellowbubble { -webkit-border-radius:4px; -moz-border-radius:4px; border-radius:4px; }
+
+.yellowpane { position:absolute; display:none; margin:0px; padding:5px; border:solid 1px #ccc; background:#fff; color:#000; z-index:10; }
+.yellowpane a { text-decoration:none; color:#000; }
+.yellowpane a:hover { text-decoration:none; color:#f00; }
+.yellowpane p { margin:0.5em; }
+.yellowpane ul { list-style:none; margin:0em 0.5em; padding:0px; }
+
+#yellowpaneedit { }
+#yellowpaneshow { min-width:250px; overflow:auto; }
+#yellowpaneuser { }
+#yellowedittext { margin:0px; margin-bottom:5px; padding:5px; border:solid 1px #ccc; resize:none; font-size:0.9em }
+#yelloweditbuttons { margin-bottom:5px; width:100%; }
+#yelloweditbuttons input { margin-left:5px; }
\ No newline at end of file
diff --git a/system/core/core_webinterface.js b/system/core/core_webinterface.js
new file mode 100644
index 0000000..c35aae7
--- /dev/null
+++ b/system/core/core_webinterface.js
@@ -0,0 +1,243 @@
+// Copyright (c) 2013 Datenstrom, http://www.datenstrom.se
+// This file may be used and distributed under the terms of the public license.
+
+// Yellow main API
+var yellow =
+{
+ version: "0.0.0", //Hello web interface!
+ onClick: function(e) { yellow.webinterface.hidePanesOnClick(e); },
+ onShow: function(id) { yellow.webinterface.showPane(id); },
+ onReset: function(id) { yellow.webinterface.resetPane(id); },
+ onResize: function() { yellow.webinterface.resizePanes(); },
+ webinterface:{}, page:{}, pages:{}, toolbox:{}, config:{}, text:{}
+}
+
+// Yellow web interface
+yellow.webinterface =
+{
+ created: false, //interface created? (boolean)
+ timerId: 0, //interface timer ID
+ heightOld: 0, //height of big panes
+
+ // Initialise web interface
+ init: function()
+ {
+ this.intervalId = window.setInterval("yellow.webinterface.create()", 1);
+ window.onresize = yellow.onResize;
+ window.onclick = yellow.onClick;
+ },
+
+ // Create action bar and panes
+ create: function()
+ {
+ var body = document.getElementsByTagName("body")[0];
+ if(!body || !body.firstChild || this.created) return;
+ if(yellow.debug) console.log("yellow.webinterface.create email:"+yellow.config.userEmail+" "+yellow.config.userName);
+ if(yellow.config.userEmail)
+ {
+ var location = yellow.config.baseLocation+yellow.config.pluginsLocation;
+ var element = document.createElement("div");
+ element.className = "yellowbar";
+ element.setAttribute("id", "yellowbar");
+ element.innerHTML =
+ "
Editing page...
"+ + ""; + } else if(id == "yellowpaneshow") { + outDiv.innerHTML = "Showing files...
"; + for(var n in data) + { + var outUl = document.createElement("ul"); + var outLi = document.createElement("li"); + var outA = document.createElement("a"); + outA.setAttribute("href", data[n]["location"]); + yellow.toolbox.setText(outA, data[n]["title"]); + outLi.appendChild(outA); + outUl.appendChild(outLi); + outDiv.appendChild(outUl); + } + } else if(id == "yellowpaneuser") { + outDiv.innerHTML = + ""+yellow.config.userEmail+"
"+ + ""; + } + var element = document.createElement("div"); + element.className = "yellowpane yellowbubble"; + element.setAttribute("id", id); + element.appendChild(outDiv); + return element; + }, + + // Reset pane + resetPane: function(id) + { + if(id == "yellowpaneedit") + { + document.formeditor.reset(); + yellow.toolbox.setText(document.getElementById("yellowedittext"), yellow.page.rawData); + this.hidePane(id); + } + }, + + // Show pane + showPane: function(id) + { + if(document.getElementById(id).style.display == "block") + { + this.hidePanes(); + } else { + this.hidePanes(); + if(yellow.debug) console.log("yellow.webinterface.showPane id:"+id); + document.getElementById(id).style.display = "block"; + this.resizePanes(true); + } + }, + + // Hide pane + hidePane: function(id) + { + if(document.getElementById(id)) document.getElementById(id).style.display = "none"; + }, + + // Hide all panes + hidePanes: function () + { + for(var element=document.getElementById("yellowbar"); element; element=element.nextSibling) + { + if(element.className && element.className.indexOf("yellowpane")>=0) + { + this.hidePane(element.getAttribute("id")); + } + } + }, + + // Hide all panes on mouse click + hidePanesOnClick: function(e) + { + var element = e.target || e.srcElement; + while(element = element.parentNode) + { + if(element.className) + { + if(element.className.indexOf("yellowpane")>=0 || element.className.indexOf("yellowbar")>=0) return; + } + } + this.hidePanes(); + }, + + // Resize panes, recalculate height and width where needed + resizePanes: function(force) + { + var interfaceHeight = Number(window.innerHeight); + if((interfaceHeight!=this.heightOld || force) && document.getElementById("yellowbar")) + { + this.heightOld = interfaceHeight; + var elementBar = document.getElementById("yellowbar"); + var borderRadius = 6; + var panePadding = 5; + var editPadding = 5; + var interfaceTop = elementBar.offsetHeight + 1; + interfaceHeight -= interfaceTop + borderRadius*2; + if(yellow.debug) console.log("yellow.webinterface.resizePanes windowY:"+interfaceHeight+" actionbarY:"+document.getElementById("yellowbar").offsetHeight+" buttonsY:"+document.getElementById("yelloweditbuttons").offsetHeight+" editorX:"+document.getElementById("yellowpaneedit").offsetWidth); + + this.setPaneHeight(document.getElementById("yellowpaneedit"), interfaceHeight, null, interfaceTop); + this.setPaneHeight(document.getElementById("yellowpaneshow"), null, interfaceHeight, interfaceTop); + this.setPaneHeight(document.getElementById("yellowpaneuser"), null, null, interfaceTop); + + var editTextHeight = interfaceHeight - panePadding*2 - editPadding*2 - 10 + - (document.getElementById("yellowedittext").offsetTop-document.getElementById("yellowpaneedit").getElementsByTagName("p")[0].offsetTop) + - document.getElementById("yelloweditbuttons").offsetHeight; + document.getElementById("yellowpaneedit").style.width = (elementBar.offsetWidth - panePadding*2).toString()+"px"; + document.getElementById("yellowedittext").style.height = editTextHeight.toString()+"px"; + document.getElementById("yellowedittext").style.width = (document.getElementById("yellowpaneedit").offsetWidth - 2 - panePadding*2 - editPadding*2).toString()+"px"; + document.getElementById("yellowpaneuser").style.marginLeft = (elementBar.offsetWidth - document.getElementById("yellowpaneuser").offsetWidth).toString()+"px"; + } + }, + + // Set pane height + setPaneHeight: function(element, height, maxHeight, top) + { + if(maxHeight) + { + element.style.maxHeight = maxHeight.toString()+"px"; + } else if(height) { + element.style.height = height.toString()+"px"; + } + element.style.top = top+"px"; + }, + + // Return text string + getText: function(key) + { + return ("webinterface"+key in yellow.text) ? yellow.text["webinterface"+key] : "[webinterface"+key+"]"; + } +} + +// Yellow toolbox with helpers +yellow.toolbox = +{ + // Set element text + setText: function(element, text) + { + while(element.firstChild!==null) element.removeChild(element.firstChild); + element.appendChild(document.createTextNode(text)); + }, + + // Insert element after element + insertAfter: function(newElement, referenceElement) + { + referenceElement.parentNode.insertBefore(newElement, referenceElement.nextSibling); + } +} + +yellow.webinterface.init(); \ No newline at end of file diff --git a/system/core/core_webinterface.php b/system/core/core_webinterface.php new file mode 100755 index 0000000..1bd2c9b --- /dev/null +++ b/system/core/core_webinterface.php @@ -0,0 +1,317 @@ +yellow = $yellow; + $this->yellow->config->setDefault("webinterfaceLocation", "/wiki/"); + $this->yellow->config->setDefault("webinterfaceUserFile", "user.ini"); + $this->users = new Yellow_WebinterfaceUsers(); + $this->users->load($this->yellow->config->get("configDir").$this->yellow->config->get("webinterfaceUserFile")); + } + + // Handle web interface location + function onRequest($baseLocation, $location, $fileName) + { + $statusCode = 0; + if($this->checkWebinterfaceLocation($location)) + { + $baseLocation .= rtrim($this->yellow->config->get("webinterfaceLocation"), '/'); + $location = $this->yellow->getRelativeLocation($baseLocation); + $fileName = $this->yellow->getContentFileName($location); + if($this->checkUser()) $statusCode = $this->processRequestAction($baseLocation, $location, $fileName); + if($statusCode == 0) $statusCode = $this->yellow->processRequestFile($baseLocation, $location, $fileName, + $this->activeUserFail ? 401 : 0, false); + } else { + if($this->yellow->config->get("webinterfaceLocation") == "$location/") + { + $statusCode = 301; + $this->yellow->sendStatus($statusCode, "Location: http://$_SERVER[SERVER_NAME]$baseLocation$location/"); + } + } + return $statusCode; + } + + // Handle extra HTML header lines + function onHeaderExtra() + { + $header = ""; + if($this->isWebinterfaceLocation()) + { + $location = $this->yellow->config->getHtml("baseLocation").$this->yellow->config->getHtml("pluginsLocation"); + $language = $this->isUser() ? $this->users->getLanguage($this->activeUserEmail) : $this->yellow->page->get("language"); + $header .= "\n"; + $header .= "\n"; + $header .= "\n"; + } + return $header; + } + + // Handle page before parser + function onParseBefore($text, $statusCode) + { + if($this->isWebinterfaceLocation() && $this->isUser()) + { + if($statusCode == 424) + { + $this->yellow->page->rawData = "---\r\n"; + $this->yellow->page->rawData .= "Title: ".$this->yellow->text->get("webinterface424Title")."\r\n"; + $this->yellow->page->rawData .= "Author: ".$this->users->getName($this->activeUserEmail)."\r\n"; + $this->yellow->page->rawData .= "---\r\n"; + $this->yellow->page->rawData .= $this->yellow->text->get("webinterface424Text"); + } + } + return $text; + } + + // Handle page after parser + function onParseAfter($text, $statusCode) + { + if($this->isWebinterfaceLocation() && $this->isUser()) + { + $this->yellow->toolbox->timerStart($time); + $baseLocation = $this->yellow->config->get("baseLocation"); + $webinterfaceLocation = rtrim($this->yellow->config->get("webinterfaceLocation"), '/'); + $text = preg_replace("##", + "", $text); + } + return $text; + } + + // Process request for an action + function processRequestAction($baseLocation, $location, $fileName) + { + $statusCode = 0; + if($_POST["action"] == "edit") + { + if(strlen($_POST["rawdata"])) + { + $fileHandle = @fopen($fileName, "w"); + if($fileHandle) + { + fwrite($fileHandle, $_POST["rawdata"]); + fclose($fileHandle); + } else { + die("Configuration problem: Can't write page '$fileName'!"); + } + } + } else if($_POST["action"]== "logout") { + $this->users->destroyCookie("login"); + $this->activeUserEmail = ""; + $statusCode = 302; + $newLocation = $this->yellow->config->getHtml("baseLocation").$location; + $this->yellow->sendStatus($statusCode, "Location: http://$_SERVER[SERVER_NAME]$newLocation"); + } else { + if(!is_readable($fileName)) + { + if($this->yellow->toolbox->isFileLocation($location) && is_dir($this->yellow->getContentDirectory("$location/"))) + { + $statusCode = 301; + $this->yellow->sendStatus($statusCode, "Location: http://$_SERVER[SERVER_NAME]$baseLocation$location/"); + } else { + $statusCode = $this->checkUserPermissions($location, $fileName) ? 424 : 404; + $this->yellow->processRequestFile($baseLocation, $location, $fileName, $statusCode, false); + } + } + } + return $statusCode; + } + + // Check web interface location + function checkWebinterfaceLocation($location) + { + $locationLength = strlen($this->yellow->config->get("webinterfaceLocation")); + $this->activeLocation = substr($location, 0, $locationLength) == $this->yellow->config->get("webinterfaceLocation"); + return $this->isWebinterfaceLocation(); + } + + // Check user login + function checkUser() + { + if($_POST["action"] == "login") + { + $email = $_POST["email"]; + $password = $_POST["password"]; + if($this->users->checkUser($email, $password)) + { + $this->users->createCookie("login", $email); + $this->activeUserEmail = $email; + } else { + $this->activeUserFail = true; + } + } else if(isset($_COOKIE["login"])) { + $cookie = $_COOKIE["login"]; + if($this->users->checkCookie($cookie)) + { + $this->activeUserEmail = $this->users->getCookieEmail($cookie); + } else { + $this->activeUserFail = true; + } + } + return $this->isUser(); + } + + // Check users permissions for creating new page + function checkUserPermissions($location, $fileName) + { + $path = dirname($fileName); + return is_dir($path); + } + + // Check if web interface location + function isWebinterfaceLocation() + { + return $this->activeLocation; + } + + // Check if user is logged in + function isUser() + { + return !empty($this->activeUserEmail); + } + + // Return page tree with content/media information + function getPagesData() + { + $data = array(); + foreach($this->yellow->pages->root(true) as $page) + { + $data[$page->fileName] = array(); + $data[$page->fileName]["location"] = $page->getLocation(); + $data[$page->fileName]["title"] = $page->getTitle(); + } + return $data; + } + + // Return configuration data including user information + function getConfigData($email) + { + $data = array("userEmail" => $email, + "userName" => $this->users->getName($email), + "userLanguage" => $this->users->getLanguage($email), + "baseLocation" => $this->yellow->config->get("baseLocation")); + return array_merge($data, $this->yellow->config->getData("Location")); + } +} + +// Yellow web interface users +class Yellow_WebinterfaceUsers +{ + var $users; //registered users + + function __construct() + { + $this->users = array(); + } + + // Load users from file + function load($fileName) + { + $fileData = @file($fileName); + if($fileData) + { + foreach($fileData as $line) + { + if(preg_match("/^\//", $line)) continue; + preg_match("/^(.*?)\s*,(.*?),\s*(.*?),\s*(.*?)\s*$/", $line, $matches); + if($matches[1]!="" && $matches[2]!="" && $matches[3]!="" && $matches[4]!="") + { + $this->setUser($matches[1], $matches[2], $matches[3], $matches[4]); + if(defined("DEBUG") && DEBUG>=3) echo "Yellow_WebinterfaceUsers::load email:$matches[1] $matches[3]