mikuli.cz

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

commit 5a56168a87727e6cda7144cab18446f27d328b1a
parent 8a69cbb9d66604278edc0b6e1819662c06991f39
Author: markseu <mark2011@mayberg.se>
Date:   Fri, 25 Jul 2014 12:46:58 +0200

Core update (hot summer remix)

Diffstat:
MREADME.md | 2+-
Msystem/config/error424.txt | 6+++---
Msystem/config/text.ini | 5++++-
Msystem/core/core-commandline.php | 141++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------
Msystem/core/core-webinterface.css | 17++++++++++++-----
Msystem/core/core-webinterface.js | 237++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------
Msystem/core/core-webinterface.php | 354+++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------
Msystem/core/core.php | 121+++++++++++++++++++++++++++++++++++++++++++++++++------------------------------
8 files changed, 622 insertions(+), 261 deletions(-)

diff --git a/README.md b/README.md @@ -1,4 +1,4 @@ -Yellow 0.3.7 +Yellow 0.3.8 ============ Yellow is for people who make websites. [Visit website](http://datenstrom.se/yellow). diff --git a/system/config/error424.txt b/system/config/error424.txt @@ -1,4 +1,4 @@ --- -Title: Page does not exist +Title: File not found --- -You can [create this page](javascript:yellow.onShow('yellow-pane-edit');). -\ No newline at end of file +You can [create this page](javascript:yellow.action('edit');). +\ No newline at end of file diff --git a/system/config/text.ini b/system/config/text.ini @@ -8,9 +8,12 @@ webinterfaceLoginText = Yellow login webinterfaceLoginEmail = Email: webinterfaceLoginPassword = Password: webinterfaceLoginButton = Login -webinterfaceSaveButton = Save +webinterfaceCreateButton = Create +webinterfaceEditButton = Save +webinterfaceDeleteButton = Delete webinterfaceCancelButton = Cancel webinterfaceEdit = Edit +webinterfaceNew = + webinterfaceUserHelp = Help webinterfaceUserHelpUrl = https://github.com/markseu/yellowcms-extensions/blob/master/documentation/english/README.md webinterfaceUserLogout = Logout diff --git a/system/core/core-commandline.php b/system/core/core-commandline.php @@ -5,7 +5,7 @@ // Command line core plugin class YellowCommandline { - const Version = "0.3.5"; + const Version = "0.3.6"; var $yellow; //access to API var $content; //number of content pages var $media; //number of media files @@ -21,7 +21,7 @@ class YellowCommandline $this->yellow = $yellow; $this->yellow->config->setDefault("commandlineDefaultFile", "index.html"); $this->yellow->config->setDefault("commandlineErrorFile", "error404.html"); - $this->yellow->config->setDefault("commandlineSystemFile", ""); + $this->yellow->config->setDefault("commandlineSystemFile", ".htaccess"); } // Handle command help @@ -29,6 +29,7 @@ class YellowCommandline { $help .= "version\n"; $help .= "build DIRECTORY [LOCATION]\n"; + $help .= "clean DIRECTORY [LOCATION]\n"; return $help; } @@ -41,7 +42,13 @@ class YellowCommandline case "": $statusCode = $this->helpCommand(); break; case "version": $statusCode = $this->versionCommand(); break; case "build": $statusCode = $this->buildCommand($args); break; - default: $statusCode = $this->pluginCommand($args); break; + case "clean": $statusCode = $this->cleanCommand($args); break; + default: $statusCode = $this->pluginCommand($args); + } + if($statusCode == 0) + { + $statusCode = 400; + echo "Yellow $command: Command not found\n"; } return $statusCode; } @@ -94,49 +101,50 @@ class YellowCommandline $this->yellow->toolbox->timerStart($time); $pluginDir = $this->yellow->config->get("pluginDir"); $pathPlugin = rtrim($path.$this->yellow->config->get("pluginLocation"), '/'); - $this->content = $this->media = $this->system = $this->error = $statusCodeMax = 0; + $this->content = $this->media = $this->system = $this->error = $statusCode = 0; $this->locationsArguments = $this->locationsPagination = $this->fileNamesPlugin = array(); if(empty($location)) { + $statusCode = $this->cleanStatic($location, $path); foreach($this->yellow->pages->index(true) as $page) { - $statusCodeMax = max($statusCodeMax, $this->buildStaticLocation($page->location, $path, true)); + $statusCode = max($statusCode, $this->buildStaticLocation($page->location, $path, true)); } foreach($this->locationsArguments as $location) { - $statusCodeMax = max($statusCodeMax, $this->buildStaticLocation($location, $path, true)); + $statusCode = max($statusCode, $this->buildStaticLocation($location, $path, true)); } foreach($this->locationsPagination as $location) { for($pageNumber=2; $pageNumber<=999; ++$pageNumber) { - $statusCode = $this->buildStaticLocation($location.$pageNumber, $path, false, true); - $statusCodeMax = max($statusCodeMax, $statusCode); - if($statusCode == 0) break; + $statusCodeLocation = $this->buildStaticLocation($location.$pageNumber, $path, false, true); + $statusCode = max($statusCode, $statusCodeLocation); + if($statusCodeLocation == 0) break; } } $fileNamesMedia = $this->yellow->toolbox->getDirectoryEntriesRecursive( $this->yellow->config->get("mediaDir"), "/.*/", false, false); - $fileNamesSystem = preg_split("/,\s*/", $this->yellow->config->get(commandlineSystemFile)); + $fileNamesSystem = preg_split("/,\s*/", $this->yellow->config->get("commandlineSystemFile")); array_push($fileNamesSystem, $this->yellow->config->get("commandlineErrorFile")); foreach($fileNamesMedia as $fileName) { - $statusCodeMax = max($statusCodeMax, $this->buildStaticFile($fileName, "$path/$fileName")); + $statusCode = max($statusCode, $this->buildStaticFile($fileName, "$path/$fileName")); } foreach($this->fileNamesPlugin as $fileName) { - $statusCodeMax = max($statusCodeMax, $this->buildStaticFile("$pluginDir$fileName", "$pathPlugin/$fileName")); + $statusCode = max($statusCode, $this->buildStaticFile("$pluginDir$fileName", "$pathPlugin/$fileName")); } foreach($fileNamesSystem as $fileName) { - $statusCodeMax = max($statusCodeMax, $this->buildStaticFile($fileName, "$path/".basename($fileName), false)); + $statusCode = max($statusCode, $this->buildStaticFile($fileName, "$path/".basename($fileName), false)); } } else { - $statusCodeMax = $this->buildStaticLocation($location, $path); + $statusCode = $this->buildStaticLocation($location, $path); } $this->yellow->toolbox->timerStop($time); if(defined("DEBUG") && DEBUG>=1) echo "YellowCommandline::buildStatic time:$time ms\n"; - return $statusCodeMax; + return $statusCode; } // Build static location @@ -282,6 +290,87 @@ class YellowCommandline } } + // Clean static pages + function cleanCommand($args) + { + $statusCode = 0; + list($dummy, $command, $path, $location) = $args; + if(!empty($path) && $path!="/" && (empty($location) || $location[0]=='/')) + { + $statusCode = $this->cleanStatic($location, $path); + echo "Yellow $command: Static page".(empty($location) ? "s" : "")." ".($statusCode!=200 ? "not " : "")."cleaned\n"; + } else { + $statusCode = 400; + echo "Yellow $command: Invalid arguments\n"; + } + return $statusCode; + } + + // Clean static directory and files + function cleanStatic($location, $path) + { + $statusCode = 200; + if(empty($location)) + { + $statusCode = max($statusCode, $this->pluginCommand(array("all", "clean"))); + $statusCode = max($statusCode, $this->cleanStaticDirectory($path)); + } else { + $statusCode = $this->cleanStaticFile($location, $path); + } + return $statusCode; + } + + // Clean static directory + function cleanStaticDirectory($path) + { + $statusCode = 200; + if($this->isYellowDirectory($path)) + { + if(is_file("$path/yellow.php") || !$this->yellow->toolbox->deleteDirectory($path, true)) + { + $statusCode = 500; + echo "ERROR cleaning pages: Can't delete directory '$path'!\n"; + } + } + return $statusCode; + } + + // Clean static file + function cleanStaticFile($location, $path) + { + $statusCode = 200; + $fileName = $this->getStaticFileName($location, $path); + if($this->isYellowDirectory($path) && is_file($fileName)) + { + $entry = basename($fileName); + if($entry!="yellow.php" && substru($entry, 0, 1)!=".") + { + if(!$this->yellow->toolbox->deleteFile($fileName)) + { + $statusCode = 500; + echo "ERROR cleaning pages: Can't delete file '$fileName'!\n"; + } + } + } + return $statusCode; + } + + // Forward plugin command + function pluginCommand($args) + { + $statusCode = 0; + foreach($this->yellow->plugins->plugins as $key=>$value) + { + if($key == "commandline") continue; + if(method_exists($value["obj"], "onCommand")) + { + $statusCode = $value["obj"]->onCommand($args); + if($statusCode != 0) break; + } + } + return $statusCode; + } + // Check static configuration function checkStaticConfig() { @@ -336,25 +425,11 @@ class YellowCommandline return $data; } - // Forward plugin command - function pluginCommand($args) + // Check if directory contains Yellow files + function isYellowDirectory($path) { - $statusCode = 0; - foreach($this->yellow->plugins->plugins as $key=>$value) - { - if($key == "commandline") continue; - if(method_exists($value["obj"], "onCommand")) - { - $statusCode = $value["obj"]->onCommand($args); - if($statusCode != 0) break; - } - } - if($statusCode == 0) - { - $statusCode = 400; - echo "Yellow command line: Invalid arguments\n"; - } - return $statusCode; + $systemFile = preg_split("/,\s*/", $this->yellow->config->get("commandlineSystemFile"))[0]; + return is_file("$path/yellow.php") || is_file("$path/$systemFile"); } } diff --git a/system/core/core-webinterface.css b/system/core/core-webinterface.css @@ -1,9 +1,10 @@ -/* Yellow web interface 0.3.2 */ +/* Yellow web interface 0.3.3 */ .yellow-bar { position:relative; overflow:hidden; line-height:2.0em; } .yellow-bar-left { display:block; float:left; } .yellow-bar-left a { margin-right:1em; } .yellow-bar-right { display:block; float:right; } +.yellow-bar-right a { margin-left:1em; } .yellow-body-modal-open { overflow:hidden; } .yellow-pane { @@ -45,12 +46,17 @@ border-color:#b13121 #b13121 #802020; } .yellow-btn-red:hover, .yellow-btn-red:focus, .yellow-btn-red:active { color:#ffffff; } +.yellow-btn-green { + background-color:#3cc335; color:#ffffff; + background-image:linear-gradient(to bottom, #5fee5b, #36bd2f); + border-color:#31b121 #31b121 #20b020; +} +.yellow-btn-green:hover, .yellow-btn-green:focus, .yellow-btn-green:active { color:#ffffff; } #yellow-pane-login { } #yellow-pane-login h1 { margin:0.5em 0.5em; } #yellow-pane-login p { margin:0.5em; text-align:right; } #yellow-pane-edit { } -#yellow-pane-edit #yellow-edit-text { margin:0; padding:5px; border:1px solid #bbb; resize:none; font-size:0.9em } -#yellow-pane-edit #yellow-edit-info { margin:0; padding:5px; border:1px solid #bbb; display:none; } -#yellow-pane-edit #yellow-edit-buttons { margin:5px 0; } -#yellow-pane-user { } +#yellow-pane-edit-page { margin:0; padding:5px; border:1px solid #bbb; resize:none; font-size:0.9em; } +#yellow-pane-edit-buttons { margin:5px 0; } +#yellow-pane-user { } +\ No newline at end of file diff --git a/system/core/core-webinterface.js b/system/core/core-webinterface.js @@ -4,92 +4,103 @@ // Yellow main API var yellow = { - version: "0.3.2", + version: "0.3.3", + action: function(text) { yellow.webinterface.action(text); }, onClick: function(e) { yellow.webinterface.hidePanesOnClick(yellow.toolbox.getEventElement(e)); }, onKeydown: function(e) { yellow.webinterface.hidePanesOnKeydown(yellow.toolbox.getEventKeycode(e)); }, onResize: function() { yellow.webinterface.resizePanes(); }, - onShow: function(id) { yellow.webinterface.showPane(id); }, - onHide: function(id) { yellow.webinterface.hidePane(id); }, - onLogout: function() { yellow.toolbox.submitForm({"action":"logout"}); }, - webinterface:{}, page:{}, toolbox:{}, config:{}, text:{} + onUpdate: function() { yellow.webinterface.updatePane(yellow.webinterface.paneId, yellow.webinterface.paneType); }, + webinterface:{}, toolbox:{}, page:{}, config:{}, text:{} } // Yellow web interface yellow.webinterface = { - created: false, //interface created? (boolean) - intervalId: 0, //interface timer interval ID + loaded: false, //web interface loaded? (boolean) + intervalId: 0, //timer interval ID + paneId: 0, //visible pane ID + paneType: 0, //visible pane type // Initialise web interface init: function() { - this.intervalId = setInterval("yellow.webinterface.create()", 1); - yellow.toolbox.addEvent(window, "resize", yellow.onResize); + this.intervalId = setInterval("yellow.webinterface.load()", 1); yellow.toolbox.addEvent(document, "click", yellow.onClick); yellow.toolbox.addEvent(document, "keydown", yellow.onKeydown); + yellow.toolbox.addEvent(window, "resize", yellow.onResize); }, - // Create web interface - create: function() + // Load web interface + load: function() { var body = document.getElementsByTagName("body")[0]; - if(body && body.firstChild && !this.created) + if(body && body.firstChild && !this.loaded) { - this.created = true; - if(yellow.debug) console.log("yellow.webinterface.create email:"+yellow.config.userEmail+" "+yellow.config.userName); + this.loaded = true; + if(yellow.debug) console.log("yellow.webinterface.load email:"+yellow.config.userEmail+" "+yellow.config.userName); if(yellow.config.userEmail) { - yellow.toolbox.insertBefore(this.createBar("yellow-bar"), body.firstChild); - yellow.toolbox.insertAfter(this.createPane("yellow-pane-edit"), body.firstChild); - yellow.toolbox.insertAfter(this.createPane("yellow-pane-user"), body.firstChild); - yellow.toolbox.setText(document.getElementById("yellow-edit-text"), yellow.page.rawData); - if(yellow.page.permissions) - { - document.getElementById("yellow-edit-cancel").style.display = "none"; - } else { - document.getElementById("yellow-edit-save").style.display = "none"; - } + this.createBar("yellow-bar", true, body.firstChild); + this.createPane("yellow-pane-edit", true, body.firstChild); + this.createPane("yellow-pane-user", true, body.firstChild); + yellow.toolbox.addEvent(document.getElementById("yellow-pane-edit-page"), "keyup", yellow.onUpdate); + yellow.toolbox.addEvent(document.getElementById("yellow-pane-edit-page"), "change", yellow.onUpdate); } else { - yellow.toolbox.insertBefore(this.createBar("yellow-bar", true), body.firstChild); - yellow.toolbox.insertAfter(this.createPane("yellow-pane-login", true), body.firstChild); + this.createBar("yellow-bar", false, body.firstChild); + this.createPane("yellow-pane-login", false, body.firstChild); this.showPane("yellow-pane-login"); } clearInterval(this.intervalId); } }, + // Execute action + action: function(text) + { + // edit and new should be like two panes + switch(text) + { + case "edit": this.togglePane("yellow-pane-edit", "edit"); break; + case "new": this.togglePane("yellow-pane-edit", "new"); break; + case "user": this.togglePane("yellow-pane-user"); break; + case "send": this.sendPane(this.paneId, this.paneType); break; + case "logout": yellow.toolbox.submitForm({"action":"logout"}); break; + } + }, + // Create bar - createBar: function(id, simple) + createBar: function(id, normal, elementReference) { if(yellow.debug) console.log("yellow.webinterface.createBar id:"+id); var elementBar = document.createElement("div"); elementBar.className = "yellow-bar yellow"; elementBar.setAttribute("id", id); - if(!simple) + if(normal) { var location = yellow.config.serverBase+yellow.config.pluginLocation; elementBar.innerHTML = "<div class=\"yellow-bar-left\">"+ - "<a href=\"#\" onclick=\"yellow.onShow('yellow-pane-edit'); return false;\">"+this.getText("Edit")+"</a>"+ + "<a href=\"#\" onclick=\"yellow.action('edit'); return false;\">"+this.getText("Edit")+"</a>"+ "</div>"+ "<div class=\"yellow-bar-right\">"+ - "<a href=\"#\" onclick=\"yellow.onShow('yellow-pane-user'); return false;\" id=\"yellow-username\">"+yellow.config.userName+" &#9662;</a>"+ + "<a href=\"#\" onclick=\"yellow.action('new'); return false;\">"+this.getText("New")+"</a>"+ + "<a href=\"#\" onclick=\"yellow.action('user'); return false;\">"+yellow.config.userName+" &#9662;</a>"+ "</div>"; } - return elementBar; + yellow.toolbox.insertBefore(elementBar, elementReference); }, // Create pane - createPane: function(id, simple) + createPane: function(paneId, normal, elementReference) { - if(yellow.debug) console.log("yellow.webinterface.createPane id:"+id); + if(yellow.debug) console.log("yellow.webinterface.createPane id:"+paneId); var elementPane = document.createElement("div"); - elementPane.className = simple ? "yellow-pane" : "yellow-pane yellow-pane-bubble"; - elementPane.setAttribute("id", id); + elementPane.className = normal ? "yellow-pane yellow-pane-bubble" : "yellow-pane"; + elementPane.setAttribute("id", paneId); elementPane.style.display = "none"; var elementDiv = document.createElement("div"); - elementDiv.setAttribute("id", id+"-content"); - if(id == "yellow-pane-login") + elementDiv.setAttribute("id", paneId+"-content"); + if(paneId == "yellow-pane-login") { elementDiv.innerHTML = "<h1>"+this.getText("LoginText")+"</h1>"+ @@ -99,53 +110,108 @@ yellow.webinterface = "<p><label for=\"password\">"+this.getText("LoginPassword")+"</label> <input type=\"password\" name=\"password\" id=\"password\" maxlength=\"64\" /></p>"+ "<p><input class=\"yellow-btn\" type=\"submit\" value=\""+this.getText("LoginButton")+"\" /></p>"+ "</form>"; - } else if(id == "yellow-pane-edit") { + } else if(paneId == "yellow-pane-edit") { elementDiv.innerHTML = "<form method=\"post\">"+ - "<input type=\"hidden\" name=\"action\" value=\"edit\" />"+ - "<textarea id=\"yellow-edit-text\" name=\"rawdata\"></textarea>"+ - "<div id=\"yellow-edit-info\" /></div>"+ - "<div id=\"yellow-edit-buttons\">"+ - "<input id=\"yellow-edit-save\" class=\"yellow-btn\" type=\"submit\" value=\""+this.getText("SaveButton")+"\" />"+ - "<input id=\"yellow-edit-cancel\" class=\"yellow-btn\" type=\"button\" onclick=\"yellow.onHide('yellow-pane-edit'); return false;\" value=\""+this.getText("CancelButton")+"\" />"+ + "<textarea id=\"yellow-pane-edit-page\" name=\"rawdataedit\"></textarea>"+ + "<div id=\"yellow-pane-edit-buttons\">"+ + "<input id=\"yellow-pane-edit-send\" class=\"yellow-btn\" type=\"button\" onclick=\"yellow.action('send'); return false;\" value=\""+this.getText("EditButton")+"\" />"+ "</div>"+ "</form>"; - } else if(id == "yellow-pane-user") { + } else if(paneId == "yellow-pane-user") { elementDiv.innerHTML = "<p>"+yellow.config.userEmail+"</p>"+ "<p><a href=\""+this.getText("UserHelpUrl")+"\">"+this.getText("UserHelp")+"</a></p>" + - "<p><a href=\"#\" onclick=\"yellow.onLogout(); return false;\">"+this.getText("UserLogout")+"</a></p>"; + "<p><a href=\"#\" onclick=\"yellow.action('logout'); return false;\">"+this.getText("UserLogout")+"</a></p>"; } elementPane.appendChild(elementDiv); - return elementPane; + yellow.toolbox.insertAfter(elementPane, elementReference); + }, + + // Update pane + updatePane: function(paneId, paneType, init) + { + if(yellow.debug) console.log("yellow.webinterface.updatePane id:"+paneId); + if(paneId == "yellow-pane-edit") + { + if(init) + { + var string = paneType=="new" ? yellow.page.rawDataNew : yellow.page.rawDataEdit; + document.getElementById("yellow-pane-edit-page").value = string; + } + var key, className; + switch(this.getPaneAction(paneId, paneType)) + { + case "create": key = "CreateButton"; className = "yellow-btn yellow-btn-green"; break; + case "edit": key = "EditButton"; className = "yellow-btn"; break; + case "delete": key = "DeleteButton"; className = "yellow-btn yellow-btn-red"; break; + default: key = "CancelButton"; className = "yellow-btn"; + } + document.getElementById("yellow-pane-edit-send").value = this.getText(key); + document.getElementById("yellow-pane-edit-send").className = className; + } + }, + + // Send pane + sendPane: function(paneId, paneType) + { + if(yellow.debug) console.log("yellow.webinterface.sendPane id:"+paneId); + if(paneId == "yellow-pane-edit") + { + var action = this.getPaneAction(paneId, paneType); + if(action) + { + var params = {}; + params.action = action; + params.rawdatasource = yellow.page.rawDataSource; + params.rawdataedit = document.getElementById("yellow-pane-edit-page").value; + yellow.toolbox.submitForm(params, true); + } else { + this.hidePane(paneId); + } + } }, // Show or hide pane - showPane: function(id) + togglePane: function(paneId, paneType) { - var element = document.getElementById(id); + if(this.paneId!=paneId || this.paneType!=paneType) + { + this.hidePane(this.paneId); + this.showPane(paneId, paneType); + } else { + this.hidePane(paneId); + } + }, + + // Show pane + showPane: function(paneId, paneType) + { + var element = document.getElementById(paneId); if(!yellow.toolbox.isVisible(element)) { - this.hidePanes(); - if(yellow.debug) console.log("yellow.webinterface.showPane id:"+id); + if(yellow.debug) console.log("yellow.webinterface.showPane id:"+paneId); element.style.display = "block"; yellow.toolbox.addClass(document.body, "yellow-body-modal-open"); this.resizePanes(); - } else { - this.hidePane(id); + this.updatePane(paneId, paneType, true); + this.paneId = paneId; + this.paneType = paneType; } }, // Hide pane - hidePane: function(id) + hidePane: function(paneId) { - var element = document.getElementById(id); + var element = document.getElementById(paneId); if(yellow.toolbox.isVisible(element)) { - if(yellow.debug) console.log("yellow.webinterface.hidePane id:"+id); + if(yellow.debug) console.log("yellow.webinterface.hidePane id:"+paneId); element.style.display = "none"; yellow.toolbox.removeClass(document.body, "yellow-body-modal-open"); + this.paneId = 0; + this.paneType = 0; } }, @@ -198,11 +264,11 @@ yellow.webinterface = yellow.toolbox.setOuterTop(document.getElementById("yellow-pane-edit"), paneTop); yellow.toolbox.setOuterHeight(document.getElementById("yellow-pane-edit"), paneHeight); yellow.toolbox.setOuterWidth(document.getElementById("yellow-pane-edit"), paneWidth); - yellow.toolbox.setOuterWidth(document.getElementById("yellow-edit-text"), yellow.toolbox.getWidth(document.getElementById("yellow-pane-edit"))); + yellow.toolbox.setOuterWidth(document.getElementById("yellow-pane-edit-page"), yellow.toolbox.getWidth(document.getElementById("yellow-pane-edit"))); var height1 = yellow.toolbox.getHeight(document.getElementById("yellow-pane-edit")); var height2 = yellow.toolbox.getOuterHeight(document.getElementById("yellow-pane-edit-content")); - var height3 = yellow.toolbox.getOuterHeight(document.getElementById("yellow-edit-text")); - yellow.toolbox.setOuterHeight(document.getElementById("yellow-edit-text"), height1 - height2 + height3); + var height3 = yellow.toolbox.getOuterHeight(document.getElementById("yellow-pane-edit-page")); + yellow.toolbox.setOuterHeight(document.getElementById("yellow-pane-edit-page"), height1 - height2 + height3); } if(yellow.toolbox.isVisible(document.getElementById("yellow-pane-user"))) { @@ -214,6 +280,26 @@ yellow.webinterface = } }, + // Return pane action + getPaneAction: function(paneId, paneType) + { + var action = ""; + if(paneId == "yellow-pane-edit") + { + if(yellow.page.userPermission) + { + var string = document.getElementById("yellow-pane-edit-page").value; + if(yellow.page.statusCode==424 || paneType=="new") + { + action = string ? "create" : ""; + } else { + action = string ? "edit" : "delete"; + } + } + } + return action; + }, + // Return text string getText: function(key) { @@ -224,23 +310,16 @@ yellow.webinterface = // Yellow toolbox with helpers yellow.toolbox = { - // Set element text - setText: function(element, text) + // Insert element before reference element + insertBefore: function(element, elementReference) { - while(element.firstChild !== null) element.removeChild(element.firstChild); - element.appendChild(document.createTextNode(text)); - }, - - // Insert element before element - insertBefore: function(newElement, referenceElement) - { - referenceElement.parentNode.insertBefore(newElement, referenceElement); + elementReference.parentNode.insertBefore(element, elementReference); }, - // Insert element after element - insertAfter: function(newElement, referenceElement) + // Insert element after reference element + insertAfter: function(element, elementReference) { - referenceElement.parentNode.insertBefore(newElement, referenceElement.nextSibling); + elementReference.parentNode.insertBefore(element, elementReference.nextSibling); }, // Add element class @@ -420,18 +499,28 @@ yellow.toolbox = return element && element.style.display != "none"; }, + // Encode newline characters + encodeNewline: function(string) + { + return string + .replace(/[\\]/g, "\\\\") + .replace(/[\r]/g, "\\r") + .replace(/[\n]/g, "\\n"); + }, + // Submit form with post method - submitForm: function(params) + submitForm: function(params, encodeNewline) { var elementForm = document.createElement("form"); elementForm.setAttribute("method", "post"); for(var key in params) { if(!params.hasOwnProperty(key)) continue; + var value = encodeNewline ? this.encodeNewline(params[key]) : params[key]; var elementInput = document.createElement("input"); elementInput.setAttribute("type", "hidden"); elementInput.setAttribute("name", key); - elementInput.setAttribute("value", params[key]); + elementInput.setAttribute("value", value); elementForm.appendChild(elementInput); } document.body.appendChild(elementForm); diff --git a/system/core/core-webinterface.php b/system/core/core-webinterface.php @@ -9,8 +9,10 @@ class YellowWebinterface var $yellow; //access to API var $users; //web interface users var $active; //web interface is active? (boolean) - var $loginFailed; //web interface login failed? (boolean) - var $rawDataOriginal; //raw data of page in case of errors + var $userLoginFailed; //web interface login failed? (boolean) + var $userPermission; //web interface can modify page? (boolean) + var $rawDataSource; //raw data of page for comparison + var $rawDataEdit; //raw data of page for editing // Handle plugin initialisation function onLoad($yellow) @@ -33,10 +35,8 @@ class YellowWebinterface $statusCode = 0; if($this->checkRequest($location)) { - list($serverScheme, $serverName, $base, $location, $fileName) = $this->getRequestInformation(); - if($this->checkUser()) $statusCode = $this->processRequestAction($serverScheme, $serverName, $base, $location, $fileName); - if($statusCode == 0) $statusCode = $this->yellow->processRequest($serverScheme, $serverName, $base, $location, $fileName, - false, $this->loginFailed ? 401 : 0); + list($serverScheme, $serverName, $base, $location, $fileName) = $this->updateRequestInformation(); + $statusCode = $this->processRequest($serverScheme, $serverName, $base, $location, $fileName); } else { $activeLocation = $this->yellow->config->get("webinterfaceLocation"); if(rtrim($location, '/') == rtrim($activeLocation, '/')) @@ -44,8 +44,7 @@ class YellowWebinterface $statusCode = 301; $locationHeader = $this->yellow->toolbox->getLocationHeader( $this->yellow->config->get("webinterfaceServerScheme"), - $this->yellow->config->get("webinterfaceServerName"), - $base, $activeLocation); + $this->yellow->config->get("webinterfaceServerName"), $base, $activeLocation); $this->yellow->sendStatus($statusCode, $locationHeader); } } @@ -59,7 +58,13 @@ class YellowWebinterface { if($page == $this->yellow->page) { - if(empty($this->rawDataOriginal)) $this->rawDataOriginal = $page->rawData; + if(empty($this->rawDataSource)) $this->rawDataSource = $page->rawData; + if(empty($this->rawDataEdit)) $this->rawDataEdit = $page->rawData; + if($page->statusCode == 424) + { + $title = $this->yellow->toolbox->createTextTitle($page->location); + $this->rawDataEdit = $this->getDataNew($title); + } } } } @@ -70,14 +75,6 @@ class YellowWebinterface $output = NULL; if($this->isActive() && $this->isUser()) { - if($page == $this->yellow->page) - { - switch($page->statusCode) - { - case 424: $page->rawData = $this->getPageData(); break; - case 500: $page->rawData = $this->rawDataOriginal; break; - } - } $serverBase = $this->yellow->config->get("serverBase"); $activePath = trim($this->yellow->config->get("webinterfaceLocation"), '/'); $callback = function($matches) use ($serverBase, $activePath) @@ -103,10 +100,12 @@ class YellowWebinterface $header .= "// <![CDATA[\n"; if($this->isUser()) { - $permissions = $this->checkPermissions($page->location, $page->fileName); - $header .= "yellow.page.rawData = ".json_encode($page->rawData).";\n"; - $header .= "yellow.page.permissions = " .json_encode($permissions).";\n"; - $header .= "yellow.config = ".json_encode($this->getConfigData()).";\n"; + $header .= "yellow.page.userPermission = " .json_encode($this->userPermission).";\n"; + $header .= "yellow.page.rawDataSource = ".json_encode($this->rawDataSource).";\n"; + $header .= "yellow.page.rawDataEdit = ".json_encode($this->rawDataEdit).";\n"; + $header .= "yellow.page.rawDataNew = ".json_encode($this->getDataNew()).";\n"; + $header .= "yellow.page.statusCode = ".json_encode($page->statusCode).";\n"; + $header .= "yellow.config = ".json_encode($this->getDataConfig()).";\n"; } $language = $this->isUser() ? $this->users->getLanguage() : $page->get("language"); $header .= "yellow.text = ".json_encode($this->yellow->text->getData("webinterface", $language)).";\n"; @@ -151,7 +150,7 @@ class YellowWebinterface $statusCode = 500; echo "ERROR creating hash: Algorithm '$algorithm' not supported!\n"; } else { - $statusCode = $this->users->createUser($fileName, $email, $hash, $name, $language, $home) ? 200 : 500; + $statusCode = $this->users->createUser($fileName, $email, $hash, $name, $language, $home) ? 200 : 500; if($statusCode != 200) echo "ERROR updating configuration: Can't write file '$fileName'!\n"; } echo "Yellow $command: User account ".($statusCode!=200 ? "not " : ""); @@ -163,70 +162,182 @@ class YellowWebinterface return $statusCode; } - // Process request for an action - function processRequestAction($serverScheme, $serverName, $base, $location, $fileName) + // Process request + function processRequest($serverScheme, $serverName, $base, $location, $fileName) + { + $statusCode = 0; + if($this->checkUser($location, $fileName)) + { + switch($_POST["action"]) + { + case "": $statusCode = $this->processRequestShow($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 "login": $statusCode = $this->processRequestLogin($serverScheme, $serverName, $base, $location, $fileName); break; + case "logout": $statusCode = $this->processRequestLogout($serverScheme, $serverName, $base, $location, $fileName); break; + } + } + if($statusCode == 0) + { + $statusCode = $this->userLoginFailed ? 401 : 0; + $statusCode = $this->yellow->processRequest($serverScheme, $serverName, $base, $location, $fileName, false, $statusCode); + } + return $statusCode; + } + + // Process request to show page + function processRequestShow($serverScheme, $serverName, $base, $location, $fileName) + { + $statusCode = 0; + if(is_readable($fileName)) + { + $statusCode = $this->yellow->processRequest($serverScheme, $serverName, $base, $location, $fileName, false, 0); + } else { + if($this->yellow->toolbox->isFileLocation($location) && $this->yellow->isContentDirectory("$location/")) + { + $statusCode = 301; + $locationHeader = $this->yellow->toolbox->getLocationHeader($serverScheme, $serverName, $base, "$location/"); + $this->yellow->sendStatus($statusCode, $locationHeader); + } else { + $statusCode = $this->userPermission ? 424 : 404; + $this->yellow->processRequest($serverScheme, $serverName, $base, $location, $fileName, false, $statusCode); + } + } + return $statusCode; + } + + // Process request to create page + function processRequestCreate($serverScheme, $serverName, $base, $location, $fileName) + { + $statusCode = 0; + $page = $this->getPageNew($serverScheme, $serverName, $base, $location, $fileName, stripcslashes($_POST["rawdataedit"])); + if($this->userPermission && $this->getUserPermission($page->location, $page->fileName) && !empty($page->rawData)) + { + $this->rawDataSource = $this->rawDataEdit = stripcslashes($_POST["rawdatasource"]); + if(is_file($page->fileName) || $this->yellow->toolbox->createFile($page->fileName, $page->rawData)) + { + $statusCode = 303; + $locationHeader = $this->yellow->toolbox->getLocationHeader($serverScheme, $serverName, $base, $page->location); + $this->yellow->sendStatus($statusCode, $locationHeader); + } else { + $statusCode = 500; + $this->yellow->processRequest($serverScheme, $serverName, $base, $location, $fileName, false, $statusCode); + $this->yellow->page->error($statusCode, "Can't write file '$page->fileName'!"); + } + } + return $statusCode; + } + + // Process request to edit page + function processRequestEdit($serverScheme, $serverName, $base, $location, $fileName) + { + $statusCode = 0; + if($this->userPermission && !empty($_POST["rawdataedit"])) + { + $this->rawDataSource = stripcslashes($_POST["rawdatasource"]); + $this->rawDataEdit = stripcslashes($_POST["rawdataedit"]); + $fileData = $this->mergeText($location, $this->rawDataSource, $this->rawDataEdit, $fileName); + if(!empty($fileData)) + { + if($this->yellow->toolbox->createFile($fileName, $fileData)) + { + $statusCode = 303; + $locationHeader = $this->yellow->toolbox->getLocationHeader($serverScheme, $serverName, $base, $location); + $this->yellow->sendStatus($statusCode, $locationHeader); + } else { + $statusCode = 500; + $this->yellow->processRequest($serverScheme, $serverName, $base, $location, $fileName, false, $statusCode); + $this->yellow->page->error($statusCode, "Can't write file '$fileName'!"); + } + } else { + $statusCode = 500; + $this->yellow->processRequest($serverScheme, $serverName, $base, $location, $fileName, false, $statusCode); + $this->yellow->page->error($statusCode, "Page has been modified by someone else!"); + } + } + return $statusCode; + } + + // Process request to delete page + function processRequestDelete($serverScheme, $serverName, $base, $location, $fileName) { $statusCode = 0; - switch($_POST["action"]) + if($this->userPermission) { - case "edit": if(!empty($_POST["rawdata"]) && $this->checkPermissions($location, $fileName)) - { - $this->rawDataOriginal = $_POST["rawdata"]; - if($this->yellow->toolbox->createFile($fileName, $_POST["rawdata"])) - { - $statusCode = 303; - $locationHeader = $this->yellow->toolbox->getLocationHeader( - $serverScheme, $serverName, $base, $location); - $this->yellow->sendStatus($statusCode, $locationHeader); - } else { - $statusCode = 500; - $this->yellow->processRequest( - $serverScheme, $serverName, $base, $location, $fileName, false, $statusCode); - $this->yellow->page->error($statusCode, "Can't write file '$fileName'!"); - } - } - break; - case "login": $home = $this->users->getHome(); - if(substru($location, 0, strlenu($home)) == $home) - { - $statusCode = 303; - $locationHeader = $this->yellow->toolbox->getLocationHeader( - $serverScheme, $serverName, $base, $location); - $this->yellow->sendStatus($statusCode, $locationHeader); - } else { - $statusCode = 302; - $locationHeader = $this->yellow->toolbox->getLocationHeader( - $serverScheme, $serverName, $base, $home); - $this->yellow->sendStatus($statusCode, $locationHeader); - } - break; - case "logout": $this->users->destroyCookie("login"); - $this->users->email = ""; - $statusCode = 302; - $locationHeader = $this->yellow->toolbox->getLocationHeader( - $this->yellow->config->get("serverScheme"), - $this->yellow->config->get("serverName"), - $this->yellow->config->get("serverBase"), $location); - $this->yellow->sendStatus($statusCode, $locationHeader); - break; - default: if(!is_readable($fileName)) - { - if($this->yellow->toolbox->isFileLocation($location) && $this->yellow->isContentDirectory("$location/")) - { - $statusCode = 301; - $locationHeader = $this->yellow->toolbox->getLocationHeader( - $serverScheme, $serverName, $base, "$location/"); - $this->yellow->sendStatus($statusCode, $locationHeader); - } else { - $statusCode = $this->checkPermissions($location, $fileName) ? 424 : 404; - $this->yellow->processRequest( - $serverScheme, $serverName, $base, $location, $fileName, false, $statusCode); - } - } + $this->rawDataSource = $this->rawDataEdit = stripcslashes($_POST["rawdatasource"]); + if(!is_file($fileName) || $this->yellow->toolbox->deleteFile($fileName)) + { + $statusCode = 303; + $locationHeader = $this->yellow->toolbox->getLocationHeader($serverScheme, $serverName, $base, $location); + $this->yellow->sendStatus($statusCode, $locationHeader); + } else { + $statusCode = 500; + $this->yellow->processRequest($serverScheme, $serverName, $base, $location, $fileName, false, $statusCode); + $this->yellow->page->error($statusCode, "Can't delete file '$fileName'!"); + } } return $statusCode; } + + // Process request for user login + function processRequestLogin($serverScheme, $serverName, $base, $location, $fileName) + { + $statusCode = 0; + $home = $this->users->getHome(); + if(substru($location, 0, strlenu($home)) == $home) + { + $statusCode = 303; + $locationHeader = $this->yellow->toolbox->getLocationHeader($serverScheme, $serverName, $base, $location); + $this->yellow->sendStatus($statusCode, $locationHeader); + } else { + $statusCode = 302; + $locationHeader = $this->yellow->toolbox->getLocationHeader($serverScheme, $serverName, $base, $home); + $this->yellow->sendStatus($statusCode, $locationHeader); + } + return $statusCode; + } + + // Process request for user logout + function processRequestLogout($serverScheme, $serverName, $base, $location, $fileName) + { + $statusCode = 302; + $this->users->destroyCookie("login"); + $this->users->email = ""; + $locationHeader = $this->yellow->toolbox->getLocationHeader( + $this->yellow->config->get("serverScheme"), + $this->yellow->config->get("serverName"), + $this->yellow->config->get("serverBase"), $location); + $this->yellow->sendStatus($statusCode, $locationHeader); + return $statusCode; + } + // Merge text + function mergeText($location, $textSource, $textLocal, $fileName) + { + $fileHandle = @fopen($fileName, "r"); + if($fileHandle) + { + $fileData = fread($fileHandle, filesize($fileName)); + fclose($fileHandle); + } + if(!empty($fileData) && $fileData!=$textSource && $fileData!=$textLocal) + { + $output = NULL; + foreach($this->yellow->plugins->plugins as $key=>$value) + { + if(method_exists($value["obj"], "onMergeText")) + { + $output = $value["obj"]->onMergeText($location, $textSource, $textLocal, $fileData); + if(!is_null($output)) break; + } + } + } else { + $output = $textLocal; + } + return $output; + } + // Check web interface request function checkRequest($location) { @@ -240,7 +351,7 @@ class YellowWebinterface } // Check web interface user - function checkUser() + function checkUser($location, $fileName) { if($_POST["action"] == "login") { @@ -250,50 +361,97 @@ class YellowWebinterface { $this->users->createCookie("login", $email); $this->users->email = $email; + $this->userPermission = $this->getUserPermission($location, $fileName); } else { - $this->loginFailed = true; + $this->userLoginFailed = true; } } else if(isset($_COOKIE["login"])) { list($email, $session) = $this->users->getCookieInformation($_COOKIE["login"]); if($this->users->checkCookie($email, $session)) { $this->users->email = $email; + $this->userPermission = $this->getUserPermission($location, $fileName); } else { - $this->loginFailed = true; + $this->userLoginFailed = true; } } return $this->isUser(); } - // Check permissions for changing page - function checkPermissions($location, $fileName) + // Return permission to modify page + function getUserPermission($location, $fileName) { - $permissions = true; + $userPermission = true; foreach($this->yellow->plugins->plugins as $key=>$value) { - if(method_exists($value["obj"], "onCheckPermissions")) + if(method_exists($value["obj"], "onUserPermission")) { - $permissions = $value["obj"]->onCheckPermissions($location, $fileName, $this->users); - if(!$permissions) break; + $userPermission = $value["obj"]->onUserPermission($location, $fileName, $this->users); + if(!$userPermission) break; } } - $permissions &= is_dir(dirname($fileName)) && strlenu(basename($fileName))<128; - return $permissions; + $userPermission &= is_dir(dirname($fileName)) && strlenu(basename($fileName))<128; + return $userPermission; } - // Return request information - function getRequestInformation() + // Update request information + function updateRequestInformation() { $serverScheme = $this->yellow->config->get("webinterfaceServerScheme"); $serverName = $this->yellow->config->get("webinterfaceServerName"); $base = rtrim($this->yellow->config->get("serverBase").$this->yellow->config->get("webinterfaceLocation"), '/'); + $this->yellow->page->base = $base; return $this->yellow->getRequestInformation($serverScheme, $serverName, $base); } + // Update page data with title + function updateDataTitle($rawData, $title) + { + foreach(preg_split("/([\r\n]+)/", $rawData, -1, PREG_SPLIT_DELIM_CAPTURE) as $line) + { + if(preg_match("/^(\s*Title\s*:\s*)(.*?)(\s*)$/i", $line, $matches)) $line = $matches[1].$title.$matches[3]; + $rawDataNew .= $line; + } + return $rawDataNew; + } + + // Return new page + function getPageNew($serverScheme, $serverName, $base, $location, $fileName, $rawData) + { + $page = new YellowPage($this->yellow, $serverScheme, $serverName, $base, $location, $fileName); + $page->parseData($rawData, false, 0); + $page->fileName = $this->yellow->toolbox->findFileFromTitle($page->get("title"), $fileName, + $this->yellow->config->get("contentDefaultFile"), $this->yellow->config->get("contentExtension")); + $page->location = $this->yellow->toolbox->findLocationFromFile($page->fileName, + $this->yellow->config->get("contentDir"), $this->yellow->config->get("contentHomeDir"), + $this->yellow->config->get("contentDefaultFile"), $this->yellow->config->get("contentExtension")); + if($this->yellow->pages->find($page->location)) + { + if(preg_match("/^(.*?)(\d+)$/", $page->get("title"), $matches)) + { + $pageTitle = $matches[1]; + $pageNumber = max(2, $matches[2]); + } else { + $pageTitle = $page->get("title").' '; + $pageNumber = 2; + } + for(; $pageNumber<=999; ++$pageNumber) + { + $page->rawData = $this->updateDataTitle($rawData, $pageTitle.$pageNumber); + $page->fileName = $this->yellow->toolbox->findFileFromTitle($pageTitle.$pageNumber, $fileName, + $this->yellow->config->get("contentDefaultFile"), $this->yellow->config->get("contentExtension")); + $page->location = $this->yellow->toolbox->findLocationFromFile($page->fileName, + $this->yellow->config->get("contentDir"), $this->yellow->config->get("contentHomeDir"), + $this->yellow->config->get("contentDefaultFile"), $this->yellow->config->get("contentExtension")); + if(!$this->yellow->pages->find($page->location)) break; + } + } + return $page; + } + // Return content data for new page - function getPageData() + function getDataNew($title = "") { - $fileData = ""; $fileName = $this->yellow->toolbox->findFileFromLocation($this->yellow->page->location, $this->yellow->config->get("contentDir"), $this->yellow->config->get("contentHomeDir"), $this->yellow->config->get("contentDefaultFile"), $this->yellow->config->get("contentExtension")); @@ -304,13 +462,14 @@ class YellowWebinterface if($fileHandle) { $fileData = fread($fileHandle, filesize($fileName)); + if(!empty($title)) $fileData = $this->updateDataTitle($fileData, $title); fclose($fileHandle); } return $fileData; } // Return configuration data including information of current user - function getConfigData() + function getDataConfig() { $data = array("userEmail" => $this->users->email, "userName" => $this->users->getName(), @@ -383,7 +542,6 @@ class YellowWebinterfaceUsers { $email = strreplaceu(',', '-', $email); $hash = strreplaceu(',', '-', $hash); - $fileNewUser = true; $fileData = @file($fileName); if($fileData) { @@ -398,14 +556,14 @@ class YellowWebinterfaceUsers $language = strreplaceu(',', '-', empty($language) ? $matches[4] : $language); $home = strreplaceu(',', '-', empty($home) ? $matches[5] : $home); $fileDataNew .= "$email,$hash,$name,$language,$home\n"; - $fileNewUser = false; + $found = true; continue; } } $fileDataNew .= $line; } } - if($fileNewUser) + if(!$found) { $name = strreplaceu(',', '-', empty($name) ? $this->yellow->config->get("sitename") : $name); $language = strreplaceu(',', '-', empty($language) ? $this->yellow->config->get("language") : $language); diff --git a/system/core/core.php b/system/core/core.php @@ -5,7 +5,7 @@ // Yellow main class class Yellow { - const Version = "0.3.7"; + const Version = "0.3.8"; var $page; //current page var $pages; //pages from file system var $config; //configuration @@ -61,7 +61,7 @@ class Yellow ob_start(); $statusCode = 0; list($serverScheme, $serverName, $base, $location, $fileName) = $this->getRequestInformation(); - $this->page = new YellowPage($this, $serverScheme, $serverName, $base, $location); + $this->page = new YellowPage($this, $serverScheme, $serverName, $base, $location, $fileName); foreach($this->plugins->plugins as $key=>$value) { if(method_exists($value["obj"], "onRequest")) @@ -149,8 +149,8 @@ class Yellow $fileData = fread($fileHandle, filesize($fileName)); fclose($fileHandle); } - $this->page = new YellowPage($this, $serverScheme, $serverName, $base, $location); - $this->page->parseData($fileName, $fileData, $cacheable, $statusCode, $pageError); + $this->page = new YellowPage($this, $serverScheme, $serverName, $base, $location, $fileName); + $this->page->parseData($fileData, $cacheable, $statusCode, $pageError); $this->page->setHeader("Content-Type", "text/html; charset=UTF-8"); $this->page->setHeader("Last-Modified", $this->page->getModified(true)); if(!$this->page->isCacheable()) $this->page->setHeader("Cache-Control", "no-cache, must-revalidate"); @@ -352,25 +352,25 @@ class YellowPage var $cacheable; //page is cacheable? (boolean) var $statusCode; //status code - function __construct($yellow, $serverScheme, $serverName, $base, $location) + function __construct($yellow, $serverScheme, $serverName, $base, $location, $fileName) { $this->yellow = $yellow; $this->serverScheme = $serverScheme; $this->serverName = $serverName; $this->base = $base; $this->location = $location; + $this->fileName = $fileName; $this->metaData = array(); $this->headerData = array(); $this->statusCode = 0; } // Parse page data - function parseData($fileName, $rawData, $cacheable, $statusCode, $pageError = "") + function parseData($rawData, $cacheable, $statusCode, $pageError = "") { - $this->fileName = $fileName; $this->rawData = $rawData; $this->active = $this->yellow->toolbox->isActiveLocation($this->location, $this->yellow->page->location); - $this->visible = $this->yellow->toolbox->isVisibleLocation($this->location, $fileName, + $this->visible = $this->yellow->toolbox->isVisibleLocation($this->location, $this->fileName, $this->yellow->config->get("contentDir")); $this->cacheable = $cacheable; $this->statusCode = $statusCode; @@ -553,7 +553,7 @@ class YellowPage function getParent() { $parentLocation = $this->yellow->pages->getParentLocation($this->location); - return $this->yellow->pages->find($parentLocation, false)->first(); + return $this->yellow->pages->find($parentLocation); } // Return top-level parent page of current page @@ -561,7 +561,7 @@ class YellowPage { $parentTopLocation = $this->yellow->pages->getParentTopLocation($this->location); if($homeFailback && !$this->yellow->isContentDirectory($parentTopLocation)) $parentTopLocation = "/"; - return $this->yellow->pages->find($parentTopLocation, false)->first(); + return $this->yellow->pages->find($parentTopLocation); } // Return pages on the same level as current page @@ -872,10 +872,14 @@ class YellowPages $this->pages = array(); } - // Return empty page collection - function create() + // Return one page from file system + function find($location, $absoluteLocation = false) { - return new YellowPageCollection($this->yellow); + if($absoluteLocation) $location = substru($location, strlenu($this->yellow->page->base)); + $parentLocation = $this->getParentLocation($location); + $this->scanChildren($parentLocation); + foreach($this->pages[$parentLocation] as $page) if($page->location == $location) { $found = true; break; } + return $found ? $page : NULL; } // Return page collection with all pages from file system @@ -894,24 +898,20 @@ class YellowPages function path($location, $absoluteLocation = false) { if($absoluteLocation) $location = substru($location, strlenu($this->yellow->page->base)); - $pages = $this->find($location, false); - for($page=$pages->first(); $page; $page=$parent) + $pages = new YellowPageCollection($this->yellow); + if($page = $this->find($location)) { - if($parent = $page->getParent()) $pages->prepend($parent); - else if($page->location!="/" && $home = $this->find("/", false)->first()) $pages->prepend($home); + $pages->prepend($page); + for(; $parent = $page->getParent(); $page=$parent) $pages->prepend($parent); + if($page->location!="/" && $home=$this->find("/")) $pages->prepend($home); } return $pages; } - // Return page collection with one specific page - function find($location, $absoluteLocation = false) + // Return empty page collection + function create() { - if($absoluteLocation) $location = substru($location, strlenu($this->yellow->page->base)); - $parentLocation = $this->getParentLocation($location); - $this->scanChildren($parentLocation); - $pages = new YellowPageCollection($this->yellow); - foreach($this->pages[$parentLocation] as $page) if($page->location == $location) { $pages->append($page); break; } - return $pages; + return new YellowPageCollection($this->yellow); } // Find child pages @@ -969,8 +969,9 @@ class YellowPages $this->yellow->page->serverScheme, $this->yellow->page->serverName, $this->yellow->page->base, $this->yellow->toolbox->findLocationFromFile($fileName, $this->yellow->config->get("contentDir"), $this->yellow->config->get("contentHomeDir"), - $this->yellow->config->get("contentDefaultFile"), $this->yellow->config->get("contentExtension"))); - $page->parseData($fileName, $fileData, false, $statusCode); + $this->yellow->config->get("contentDefaultFile"), $this->yellow->config->get("contentExtension")), + $fileName); + $page->parseData($fileData, false, $statusCode); array_push($this->pages[$location], $page); } } @@ -1497,6 +1498,14 @@ class YellowToolbox return $invalid ? "" : $path; } + // Return file path from title + function findFileFromTitle($title, $fileName, $fileDefault, $fileExtension) + { + $token = $this->normaliseName($title, false, true); + $path = dirname($fileName)."/".(empty($token) ? $fileDefault : $token.$fileExtension); + return $path; + } + // Return file path of children from location function findChildrenFromLocation($location, $pathBase, $pathHome, $fileDefault, $fileExtension) { @@ -1548,15 +1557,6 @@ class YellowToolbox return strreplaceu(array('%3A','%2F'), array(':','/'), rawurlencode($text)); } - // Normalise file/directory/attribute name - function normaliseName($text, $removeExtension = false, $filterStrict = false) - { - if(preg_match("/^[\d\-\_\.]+(.*)$/", $text, $matches)) $text = $matches[1]; - if($removeExtension) $text = ($pos = strrposu($text, '.')) ? substru($text, 0, $pos) : $text; - if($filterStrict) $text = strreplaceu('.', '-', strtoloweru($text)); - return preg_replace("/[^\pL\d\-\_\.]/u", "-", $text); - } - // Normalise location, make absolute location function normaliseLocation($location, $pageBase, $pageLocation) { @@ -1573,7 +1573,16 @@ class YellowToolbox } return $location; } - + + // Normalise file/directory/other name + function normaliseName($text, $removeExtension = false, $filterStrict = false) + { + if(preg_match("/^[\d\-\_\.]+(.*)$/", $text, $matches)) $text = $matches[1]; + if($removeExtension) $text = ($pos = strrposu($text, '.')) ? substru($text, 0, $pos) : $text; + if($filterStrict) $text = strreplaceu('.', '-', strtoloweru($text)); + return preg_replace("/[^\pL\d\-\_\.]/u", "-", $text); + } + // Normalise text into UTF-8 NFC function normaliseUnicode($text) { @@ -1599,7 +1608,7 @@ class YellowToolbox case 400: $text = "$_SERVER[SERVER_PROTOCOL] $statusCode Bad request"; break; case 401: $text = "$_SERVER[SERVER_PROTOCOL] $statusCode Unauthorised"; break; case 404: $text = "$_SERVER[SERVER_PROTOCOL] $statusCode Not found"; break; - case 424: $text = "$_SERVER[SERVER_PROTOCOL] $statusCode Does not exist"; break; + case 424: $text = "$_SERVER[SERVER_PROTOCOL] $statusCode Not existing"; break; case 500: $text = "$_SERVER[SERVER_PROTOCOL] $statusCode Server error"; break; default: $text = "$_SERVER[SERVER_PROTOCOL] $statusCode Unknown status"; } @@ -1672,6 +1681,26 @@ class YellowToolbox } return $entries; } + + // Delete directory + function deleteDirectory($path, $recursive = false) + { + if($recursive) + { + $iterator = new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS); + $files = new RecursiveIteratorIterator($iterator, RecursiveIteratorIterator::CHILD_FIRST); + foreach($files as $file) + { + if($file->isDir()) + { + @rmdir($file->getRealPath()); + } else { + @unlink($file->getRealPath()); + } + } + } + return @rmdir($path); + } // Create file function createFile($fileName, $fileData, $mkdir = false) @@ -1702,19 +1731,19 @@ class YellowToolbox } return @copy($fileNameSource, $fileNameDest); } - - // Delete file - function deleteFile($fileName) - { - return @unlink($fileName); - } // Set file modification time, Unix time function modifyFile($fileName, $modified) { return @touch($fileName, $modified); } - + + // Delete file + function deleteFile($fileName) + { + return @unlink($fileName); + } + // Return arguments from text string function getTextArgs($text, $optional = "-") { @@ -1801,7 +1830,7 @@ class YellowToolbox // Create title from text string function createTextTitle($text) { - if(preg_match("/^.*\/([\w\-]+)/", $text, $matches)) $text = ucfirst($matches[1]); + if(preg_match("/^.*\/([\w\-]+)/", $text, $matches)) $text = strreplaceu('-', ' ', ucfirst($matches[1])); return $text; }