Преглед на файлове

System update (winter remix)

markseu преди 8 години
родител
ревизия
2ef76ab159

+ 2 - 1
system/config/config.ini

@@ -36,6 +36,7 @@ ContentDefaultFile: page.txt
 ContentExtension: .txt
 ConfigExtension: .ini
 DownloadExtension: .download
+InstallationExtension: .installation
 TextFile: language-(.*).txt
 ErrorFile: page-error-(.*).txt
 RobotsFile: robots.txt
@@ -53,6 +54,7 @@ UpdatePluginsUrl: https://github.com/datenstrom/yellow-plugins
 UpdateThemesUrl: https://github.com/datenstrom/yellow-themes
 UpdateVersionFile: version.ini
 UpdateInformationFile: update.ini
+UpdateNotification: none
 WebinterfaceLocation: /edit/
 WebinterfaceNewFile: page-new-(.*).txt
 WebinterfaceMetaFilePrefix: published
@@ -61,5 +63,4 @@ WebinterfaceUserPasswordMinLength: 4
 WebinterfaceUserHashAlgorithm: bcrypt
 WebinterfaceUserHashCost: 10
 WebinterfaceUserStatus: active
-WebinterfaceUserPending: none
 WebinterfaceUserHome: /

+ 9 - 14
system/plugins/commandline.php

@@ -1,11 +1,11 @@
 <?php
-// Copyright (c) 2013-2016 Datenstrom, http://datenstrom.se
+// Copyright (c) 2013-2017 Datenstrom, http://datenstrom.se
 // This file may be used and distributed under the terms of the public license.
 
 // Command line plugin
 class YellowCommandline
 {
-	const VERSION = "0.6.16";
+	const VERSION = "0.6.17";
 	var $yellow;					//access to API
 	var $files;						//number of files
 	var $errors;					//number of errors
@@ -412,21 +412,17 @@ class YellowCommandline
 	{
 		$locations = array();
 		$regex = "/\.(css|ico|js|jpg|png|svg|txt|woff)/";
-		$fileNames = $this->yellow->toolbox->getDirectoryEntries($this->yellow->config->get("pluginDir"), $regex, false, false);
+		$pluginDirLength = strlenu($this->yellow->config->get("pluginDir"));
+		$fileNames = $this->yellow->toolbox->getDirectoryEntriesRecursive($this->yellow->config->get("pluginDir"), $regex, false, false);
 		foreach($fileNames as $fileName)
 		{
-			array_push($locations, $this->yellow->config->get("pluginLocation").basename($fileName));
+			array_push($locations, $this->yellow->config->get("pluginLocation").substru($fileName, $pluginDirLength));
 		}
-		$fileNames = $this->yellow->toolbox->getDirectoryEntries($this->yellow->config->get("themeDir"), $regex, false, false);
+		$themeDirLength = strlenu($this->yellow->config->get("themeDir"));
+		$fileNames = $this->yellow->toolbox->getDirectoryEntriesRecursive($this->yellow->config->get("themeDir"), $regex, false, false);
 		foreach($fileNames as $fileName)
 		{
-			array_push($locations, $this->yellow->config->get("themeLocation").basename($fileName));
-		}
-		$assetDirLength = strlenu($this->yellow->config->get("assetDir"));
-		$fileNames = $this->yellow->toolbox->getDirectoryEntriesRecursive($this->yellow->config->get("assetDir"), $regex, false, false);
-		foreach($fileNames as $fileName)
-		{
-			array_push($locations, $this->yellow->config->get("assetLocation").substru($fileName, $assetDirLength));
+			array_push($locations, $this->yellow->config->get("themeLocation").substru($fileName, $themeDirLength));
 		}
 		array_push($locations, "/".$this->yellow->config->get("robotsFile"));
 		return $locations;
@@ -460,8 +456,7 @@ class YellowCommandline
 			list($statusCode, $data) = $this->yellow->plugins->get("update")->getSoftwareVersion($latest);
 		} else {
 			$statusCode = 200;
-			foreach($this->yellow->plugins->getData() as $key=>$value) $data[$key] = $value;
-			foreach($this->yellow->themes->getData() as $key=>$value) $data[$key] = $value;
+			$data = array_merge($this->yellow->plugins->getData(), $this->yellow->themes->getData());
 		}
 		return array($statusCode, $data);
 	}

+ 126 - 69
system/plugins/core.php

@@ -1,11 +1,11 @@
 <?php
-// Copyright (c) 2013-2016 Datenstrom, http://datenstrom.se
+// Copyright (c) 2013-2017 Datenstrom, http://datenstrom.se
 // This file may be used and distributed under the terms of the public license.
 
 // Yellow core
 class YellowCore
 {
-	const VERSION = "0.6.6";
+	const VERSION = "0.6.7";
 	var $page;				//current page
 	var $pages;				//pages from file system
 	var $files;				//files from file system
@@ -61,6 +61,7 @@ class YellowCore
 		$this->config->setDefault("contentExtension", ".txt");
 		$this->config->setDefault("configExtension", ".ini");
 		$this->config->setDefault("downloadExtension", ".download");
+		$this->config->setDefault("installationExtension", ".installation");
 		$this->config->setDefault("configFile", "config.ini");
 		$this->config->setDefault("textFile", "language-(.*).txt");
 		$this->config->setDefault("errorFile", "page-error-(.*).txt");
@@ -75,21 +76,26 @@ class YellowCore
 		$this->config->setDefault("parserSafeMode", "0");
 		$this->config->setDefault("multiLanguageMode", "0");
 		$this->config->setDefault("installationMode", "0");
-		$this->load();
 	}
 	
-	// Initialise configuration
+	// Handle initialisation
 	function load()
 	{
-		if(defined("DEBUG") && DEBUG>=3)
+		if(defined("DEBUG") && DEBUG>=2)
 		{
 			$serverSoftware = $this->toolbox->getServerSoftware();
 			echo "Yellow ".YellowCore::VERSION.", PHP ".PHP_VERSION.", $serverSoftware<br>\n";
 		}
+		$this->pages->requestHandler = "none";
 		$this->config->load($this->config->get("configDir").$this->config->get("configFile"));
 		$this->text->load($this->config->get("pluginDir").$this->config->get("textFile"));
 		$this->lookup->load();
+		$this->plugins->load();
 		$this->themes->load();
+		foreach($this->plugins->plugins as $key=>$value)
+		{
+			if(method_exists($value["obj"], "onUpdate")) $value["obj"]->onUpdate("");
+		}
 	}
 	
 	// Handle request
@@ -141,24 +147,24 @@ class YellowCore
 				$this->sendStatus($statusCode, $location);
 			}
 		} else {
-			if($this->isRequestContentDirectory($location))
+			if($this->lookup->isRedirectLocation($location))
 			{
 				$statusCode = 301;
-				$location = $this->lookup->isFileLocation($location) ? "$location/" : "/".$this->getRequestLanguage(true)."/";
+				$location = $this->lookup->isFileLocation($location) ? "$location/" : "/".$this->getRequestLanguage()."/";
 				$location = $this->lookup->normaliseUrl($serverScheme, $serverName, $base, $location);
 				$this->sendStatus($statusCode, $location);
 			}
 		}
 		if($statusCode==0)
 		{
-			if($this->isStaticFile($location, $fileName, $cacheable))
+			$fileName = $this->lookup->findFileStatic($location, $fileName, $cacheable);
+			if($this->lookup->isContentFile($fileName) || !is_readable($fileName))
 			{
-				$fileName = $this->getStaticFileFromCache($location, $fileName, $cacheable);
-				$statusCode = $this->sendFile(200, $fileName, $cacheable);
-			} else {
 				$fileName = $this->readPage($serverScheme, $serverName, $base, $location, $fileName, $cacheable,
 					max(is_readable($fileName) ? 200 : 404, $this->page->statusCode), $this->page->get("pageError"));
 				$statusCode = $this->sendPage();
+			} else {
+				$statusCode = $this->sendFile(200, $fileName, true);
 			}
 		}
 		if(defined("DEBUG") && DEBUG>=1) echo "YellowCore::processRequest file:$fileName<br/>\n";
@@ -314,10 +320,9 @@ class YellowCore
 	}
 	
 	// Return request language
-	function getRequestLanguage($multiLanguage = false)
+	function getRequestLanguage()
 	{
-		$languages = $multiLanguage ? $this->pages->getLanguages() : $this->text->getLanguages();
-		return $this->toolbox->detectBrowserLanguage($languages, $this->config->get("language"));
+		return $this->toolbox->detectBrowserLanguage($this->pages->getLanguages(), $this->config->get("language"));
 	}
 	
 	// Return request handler
@@ -331,48 +336,6 @@ class YellowCore
 	{
 		return $this->pages->snippetArgs;
 	}
-	
-	// Return static file from cache if available
-	function getStaticFileFromCache($location, $fileName, $cacheable)
-	{
-		if($cacheable && PHP_SAPI!="cli")
-		{
-			$location .= $this->toolbox->getLocationArgs();
-			$fileNameStatic = rtrim($this->config->get("staticDir"), '/').$location;
-			if(!$this->lookup->isFileLocation($location)) $fileNameStatic .= $this->config->get("staticDefaultFile");
-			if(is_readable($fileNameStatic)) $fileName = $fileNameStatic;
-		}
-		return $fileName;
-	}
-	
-	// Check if static file
-	function isStaticFile($location, $fileName, $cacheable)
-	{
-		$ok = false;
-		if(is_readable($fileName))
-		{
-			$fileName = $this->getStaticFileFromCache($location, $fileName, $cacheable);
-			$staticDirLength = strlenu($this->config->get("staticDir"));
-			$systemDirLength = strlenu($this->config->get("systemDir"));
-			$ok = substru($fileName, 0, $staticDirLength)==$this->config->get("staticDir") ||
-				substru($fileName, 0, $systemDirLength)==$this->config->get("systemDir");
-		}
-		return $ok;
-	}
-	
-	// Check if request can be redirected into content directory
-	function isRequestContentDirectory($location)
-	{
-		$ok = false;
-		if($this->lookup->isFileLocation($location))
-		{
-			$path = $this->lookup->findFileFromLocation("$location/", true);
-			$ok = is_dir($path);
-		} else if($location=="/") {
-			$ok = $this->config->get("multiLanguageMode");
-		}
-		return $ok;
-	}
 }
 	
 // Yellow page
@@ -634,6 +597,7 @@ class YellowPage
 		{
 			$this->error(500, "Parser '".$this->get("parser")."' does not exist!");
 		}
+		if($this->yellow->lookup->isNestedLocation($this->location, true)) $this->error(500, "Home folder may not contain subfolders!");
 		if($this->yellow->toolbox->isRequestSelf()) $this->error(500, "Rewrite module not enabled on this server!");
 		if($this->yellow->getRequestHandler()=="core" && $this->isExisting("redirect") && $this->statusCode==200)
 		{
@@ -1644,6 +1608,11 @@ class YellowPlugins
 	// Load plugins
 	function load()
 	{
+		if(empty($this->yellow->pages->requestHandler))	//TODO: remove later, guard for old version
+		{
+			$this->yellow->load();
+			return;
+		}
 		$path = $this->yellow->config->get("pluginDir");
 		foreach($this->yellow->toolbox->getDirectoryEntries($path, "/^.*\.php$/", true, false) as $entry)
 		{
@@ -2094,9 +2063,8 @@ class YellowLookup
 				if($this->normaliseName($entry)==$home) { $token = $entry; break; }
 			}
 			$pathHome = $this->normaliseName($token)."/";
-			if(count($this->yellow->toolbox->getDirectoryEntries($path.$token, "/.*/", true, true, false))) $invalid = true;
 		}
-		return array($pathRoot, $invalid ? "invalid" : $pathHome);
+		return array($pathRoot, $pathHome);
 	}
 	
 	// Return root locations
@@ -2359,6 +2327,19 @@ class YellowLookup
 		$path .= $tokens[$i];
 		return $path;
 	}
+
+	// Return file path for static file, if possible
+	function findFileStatic($location, $fileName, $cacheable)
+	{
+		if($cacheable && PHP_SAPI!="cli")
+		{
+			$location .= $this->yellow->toolbox->getLocationArgs();
+			$fileNameStatic = rtrim($this->yellow->config->get("staticDir"), '/').$location;
+			if(!$this->isFileLocation($location)) $fileNameStatic .= $this->yellow->config->get("staticDefaultFile");
+			if(is_readable($fileNameStatic)) $fileName = $fileNameStatic;
+		}
+		return $fileName;
+	}
 	
 	// Normalise file/directory/other name
 	function normaliseName($text, $removePrefix = true, $removeExtension = false, $filterStrict = false)
@@ -2434,6 +2415,31 @@ class YellowLookup
 		return substru($location, -1, 1)!="/";
 	}
 	
+	// Check if location can be redirected into directory
+	function isRedirectLocation($location)
+	{
+		$redirect = false;
+		if($this->isFileLocation($location))
+		{
+			$redirect = is_dir($this->findFileFromLocation("$location/", true));
+		} else if($location=="/") {
+			$redirect = $this->yellow->config->get("multiLanguageMode");
+		}
+		return $redirect;
+	}
+	
+	// Check if location contains nested directories
+	function isNestedLocation($location, $checkHomeLocation = false)
+	{
+		$nested = false;
+		if(!$checkHomeLocation || $location==$this->yellow->pages->getHomeLocation($location))
+		{
+			$path = $this->yellow->lookup->findFileFromLocation($location, true);
+			if(count($this->yellow->toolbox->getDirectoryEntries($path, "/.*/", true, true, false))) $nested = true;
+		}
+		return $nested;
+	}
+	
 	// Check if location is visible
 	function isVisibleLocation($location, $fileName)
 	{
@@ -2489,12 +2495,33 @@ class YellowLookup
 			substru($fileName, 0, $mediaDirLength)==$this->yellow->config->get("mediaDir") ||
 			substru($fileName, 0, $systemDirLength)==$this->yellow->config->get("systemDir");
 	}
+	
+	// Check if content file
+	function isContentFile($fileName)
+	{
+		$contentDirLength = strlenu($this->yellow->config->get("contentDir"));
+		return substru($fileName, 0, $contentDirLength)==$this->yellow->config->get("contentDir");
+	}
+	
+	// Check if media file
+	function isMediaFile($fileName)
+	{
+		$mediaDirLength = strlenu($this->yellow->config->get("mediaDir"));
+		return substru($fileName, 0, $mediaDirLength)==$this->yellow->config->get("mediaDir");
+	}
+	
+	// Check if system file
+	function isSystemFile($fileName)
+	{
+		$systemDirLength = strlenu($this->yellow->config->get("systemDir"));
+		return substru($fileName, 0, $systemDirLength)==$this->yellow->config->get("systemDir");
+	}
 }
 
 // Yellow toolbox with helpers
 class YellowToolbox
 {
-	// Return server software from current HTTP request
+	// Return server software
 	function getServerSoftware()
 	{
 		$serverSoftware = strtoupperu(PHP_SAPI);
@@ -2502,6 +2529,15 @@ class YellowToolbox
 		return $serverSoftware." ".PHP_OS;
 	}
 	
+	// Return server URL from current HTTP request
+	function getServerUrl()
+	{
+		$serverScheme = $this->getServerScheme();
+		$serverName = $this->getServerName();
+		$serverBase = $this->getServerBase();
+		return "$serverScheme://$serverName$serverBase/";
+	}
+	
 	// Return server scheme from current HTTP request
 	function getServerScheme()
 	{
@@ -2711,6 +2747,20 @@ class YellowToolbox
 		}
 		return $text;
 	}
+
+	// Normalise array elements with different upper and lower case
+	function normaliseUpperLower($input)
+	{
+		$array = array();
+		foreach($input as $key=>$value)
+		{
+			if(empty($key) || strempty($value)) continue;
+			$keySearch = strtoloweru($key);
+			foreach($array as $keyNew=>$valueNew) if(strtoloweru($keyNew)==$keySearch) { $key = $keyNew; break; }
+			$array[$key] += $value;
+		}
+		return $array;
+	}
 	
 	// Return server time zone
 	function getServerTime()
@@ -2738,7 +2788,6 @@ class YellowToolbox
 			case 403:	$text = "Forbidden"; break;
 			case 404:	$text = "Not found"; break;
 			case 424:	$text = "Not existing"; break;
-			case 444:	$text = "No response"; break;
 			case 500:	$text = "Server error"; break;
 			case 503:	$text = "Service unavailable"; break;
 			default:	$text = "Error $statusCode";
@@ -2759,6 +2808,7 @@ class YellowToolbox
 	{
 		$mimeTypes = array(
 			"css" => "text/css",
+			"html" => "text/html; charset=utf-8",
 			"ico" => "image/x-icon",
 			"js" => "application/javascript",
 			"jpg" => "image/jpeg",
@@ -2767,9 +2817,14 @@ class YellowToolbox
 			"txt" => "text/plain",
 			"woff" => "application/font-woff",
 			"xml" => "text/xml; charset=utf-8");
-		$contentType = "text/html; charset=utf-8";
+		$contentType = "";
 		$extension = $this->getFileExtension($fileName);
-		if(array_key_exists(strtoloweru($extension), $mimeTypes)) $contentType = $mimeTypes[$extension];
+		if(empty($extension))
+		{
+			$contentType = $mimeTypes["html"];
+		} else if(array_key_exists($extension, $mimeTypes)) {
+			$contentType = $mimeTypes[$extension];
+		}
 		return $contentType;
 	}
 	
@@ -2824,7 +2879,8 @@ class YellowToolbox
 		if($fileHandle)
 		{
 			clearstatcache(true, $fileName);
-			$fileData = fread($fileHandle, $sizeMax ? $sizeMax : filesize($fileName));
+			$fileSize = $sizeMax ? $sizeMax : filesize($fileName);
+			if($fileSize) $fileData = fread($fileHandle, $fileSize);
 			fclose($fileHandle);
 		}
 		return $fileData;
@@ -2944,7 +3000,7 @@ class YellowToolbox
 		return strtoloweru(($pos = strrposu($fileName, '.')) ? substru($fileName, $pos+1) : "");
 	}
 	
-	// Return lines from text string
+	// Return lines from text string, newline separated
 	function getTextLines($text)
 	{
 		$lines = array();
@@ -2954,7 +3010,7 @@ class YellowToolbox
 		return $lines;
 	}
 	
-	// Return arguments from text string
+	// Return arguments from text string, space separated
 	function getTextArgs($text, $optional = "-")
 	{
 		$text = preg_replace("/\s+/s", " ", trim($text));
@@ -3145,7 +3201,7 @@ class YellowToolbox
 			{
 				$dataBufferSizeMax = filesize($fileName);
 				$dataBufferSize = min($dataBufferSizeMax, 4096);
-				$dataBuffer = fread($fileHandle, $dataBufferSize);
+				if($dataBufferSize) $dataBuffer = fread($fileHandle, $dataBufferSize);
 				$dataSignature = substrb($dataBuffer, 0, 4);
 				if(!feof($fileHandle) && ($dataSignature=="\xff\xd8\xff\xe0" || $dataSignature=="\xff\xd8\xff\xe1"))
 				{
@@ -3165,8 +3221,9 @@ class YellowToolbox
 							if($dataBufferSize==$dataBufferSizeMax) break;
 							$dataBufferDiff = min($dataBufferSizeMax, $dataBufferSize*2) - $dataBufferSize;
 							$dataBufferSize += $dataBufferDiff;
-							$dataBuffer .= fread($fileHandle, $dataBufferDiff);
-							if(feof($fileHandle)) { $dataBufferSize = 0; break; }
+							$dataBufferChunk = fread($fileHandle, $dataBufferDiff);
+							if(feof($fileHandle) || $dataBufferChunk===null) { $dataBufferSize = 0; break; }
+							$dataBuffer .= $dataBufferChunk;
 						}
 					}
 				}
@@ -3182,7 +3239,7 @@ class YellowToolbox
 			} else if(substru(strtoloweru($fileName), -3)=="svg") {
 				$dataBufferSizeMax = filesize($fileName);
 				$dataBufferSize = min($dataBufferSizeMax, 4096);
-				$dataBuffer = fread($fileHandle, $dataBufferSize);
+				if($dataBufferSize) $dataBuffer = fread($fileHandle, $dataBufferSize);
 				$dataSignature = substrb($dataBuffer, 0, 5);
 				if(!feof($fileHandle) && $dataSignature=="\x3csvg\x20")
 				{

+ 6 - 4
system/plugins/language-de.txt

@@ -3,7 +3,7 @@
 Language: de
 LanguageDescription: Deutsch
 LanguageTranslator: David Fehrmann
-LanguageVersion: 0.6.12
+LanguageVersion: 0.6.13
 
 BlogBy: von
 BlogFilter: Blog:
@@ -90,10 +90,12 @@ WebinterfaceWelcomeMessage: Hallo @usershort, dein Benutzerkonto wurde erstellt.
 WebinterfaceInformationSubject: Willkommen zurück
 WebinterfaceInformationMessage: Hallo @usershort, dein Benutzerkonto wurde geändert. Du kannst dich jetzt anmelden.
 WebinterfaceVersionTitle: Über diese Webseite
-WebinterfaceVersionStatusNone: Nach Aktualiserung suchen…
-WebinterfaceVersionStatusLatest: Keine Aktualisierung verfügbar.
+WebinterfaceVersionStatusNone: Yellow ist für Menschen die Webseiten machen.
+WebinterfaceVersionStatusCheck: Nach Aktualiserung suchen…
+WebinterfaceVersionStatusDone: Deine Webseite ist auf dem neusten Stand.
 WebinterfaceVersionStatusUpdates: Aktualiserung verfügbar, bitte an den Webmaster wenden.
-WebinterfaceVersionStatusRequest: Aktualiserung verfügbar, jetzt aktualisieren.
+WebinterfaceVersionUpdateNormal: Aktualiserung verfügbar, jetzt aktualisieren.
+WebinterfaceVersionUpdateForce: Update erzwingen
 WebinterfaceOkButton: Ok
 WebinterfaceCancelButton: Abbruch
 WebinterfaceCreateButton: Erzeugen

+ 6 - 4
system/plugins/language-en.txt

@@ -3,7 +3,7 @@
 Language: en
 LanguageDescription: English
 LanguageTranslator: Mark Seuffert
-LanguageVersion: 0.6.12
+LanguageVersion: 0.6.13
 
 BlogBy: by
 BlogFilter: Blog:
@@ -90,10 +90,12 @@ WebinterfaceWelcomeMessage: Hi @usershort, your user account has been created. H
 WebinterfaceInformationSubject: Welcome back
 WebinterfaceInformationMessage: Hi @usershort, your user account has been changed. You can now log in.
 WebinterfaceVersionTitle: About this website
-WebinterfaceVersionStatusNone: Checking for updates…
-WebinterfaceVersionStatusLatest: No updates available.
+WebinterfaceVersionStatusNone: Yellow is for people who make websites.
+WebinterfaceVersionStatusCheck: Checking for updates…
+WebinterfaceVersionStatusDone: Your website is up to date.
 WebinterfaceVersionStatusUpdates: Updates available, please contact the webmaster.
-WebinterfaceVersionStatusRequest: Updates available, update now.
+WebinterfaceVersionUpdateNormal: Updates available, update now.
+WebinterfaceVersionUpdateForce: Force update
 WebinterfaceOkButton: Ok
 WebinterfaceCancelButton: Cancel
 WebinterfaceCreateButton: Create

+ 6 - 4
system/plugins/language-fr.txt

@@ -3,7 +3,7 @@
 Language: fr
 LanguageDescription: Français
 LanguageTranslator: Juh Nibreh
-LanguageVersion: 0.6.12
+LanguageVersion: 0.6.13
 
 BlogBy: par
 BlogFilter: Blog:
@@ -90,10 +90,12 @@ WebinterfaceWelcomeMessage: Bonjour @usershort, votre compte utilisateur a bien
 WebinterfaceInformationSubject: Bienvenue à nouveau
 WebinterfaceInformationMessage: Bonjour @usershort, votre compte utilisateur a bien été changé. Vous pouvez maintenant vous connecter.
 WebinterfaceVersionTitle: A propos de ce site
-WebinterfaceVersionStatusNone: Vérification des mises à jour…
-WebinterfaceVersionStatusLatest: Aucune mise à jour disponible.
+WebinterfaceVersionStatusNone: Yellow est fait pour les gens qui font des sites web.
+WebinterfaceVersionStatusCheck: Vérification des mises à jour…
+WebinterfaceVersionStatusDone: Votre site est à jour.
 WebinterfaceVersionStatusUpdates: Mises à jour disponibles, s'il vous plaît contacter le webmestre.
-WebinterfaceVersionStatusRequest: Mises à jour disponibles, mettre à jour maintenant.
+WebinterfaceVersionUpdateNormal: Mises à jour disponibles, mettre à jour maintenant.
+WebinterfaceVersionUpdateForce: Forcer mise à jour
 WebinterfaceOkButton: Ok
 WebinterfaceCancelButton: Annuler
 WebinterfaceCreateButton: Créer

+ 2 - 2
system/plugins/language.php

@@ -1,11 +1,11 @@
 <?php
-// Copyright (c) 2013-2016 Datenstrom, http://datenstrom.se
+// Copyright (c) 2013-2017 Datenstrom, http://datenstrom.se
 // This file may be used and distributed under the terms of the public license.
 
 // Language plugin
 class YellowLanguage
 {
-	const VERSION = "0.6.12";
+	const VERSION = "0.6.13";
 	var $yellow;			//access to API
 	
 	// Handle initialisation

+ 155 - 117
system/plugins/update.php

@@ -1,11 +1,11 @@
 <?php
-// Copyright (c) 2013-2016 Datenstrom, http://datenstrom.se
+// Copyright (c) 2013-2017 Datenstrom, http://datenstrom.se
 // This file may be used and distributed under the terms of the public license.
 
 // Update plugin
 class YellowUpdate
 {
-	const VERSION = "0.6.10";
+	const VERSION = "0.6.11";
 	var $yellow;					//access to API
 	
 	// Handle initialisation
@@ -16,17 +16,24 @@ class YellowUpdate
 		$this->yellow->config->setDefault("updateThemesUrl", "https://github.com/datenstrom/yellow-themes");
 		$this->yellow->config->setDefault("updateVersionFile", "version.ini");
 		$this->yellow->config->setDefault("updateInformationFile", "update.ini");
+		$this->yellow->config->setDefault("updateNotification", "none");
+	}
+	
+	// Handle update
+	function onUpdate($name)
+	{
+		if(empty($name)) $this->processUpdateNotification();
 	}
 	
 	// Handle request
 	function onRequest($serverScheme, $serverName, $base, $location, $fileName)
 	{
 		$statusCode = 0;
-		if($this->isInstallation())
+		if($this->isInstallationMode())
 		{
-			$statusCode = $this->processRequestInstallation($serverScheme, $serverName, $base, $location, $fileName);
+			$statusCode = $this->processRequestInstallationMode($serverScheme, $serverName, $base, $location, $fileName);
 		} else {
-			$statusCode = $this->processRequestPending($serverScheme, $serverName, $base, $location, $fileName);
+			$statusCode = $this->processRequestInstallationPending($serverScheme, $serverName, $base, $location, $fileName);
 		}
 		return $statusCode;
 	}
@@ -37,8 +44,9 @@ class YellowUpdate
 		list($command) = $args;
 		switch($command)
 		{
+			case "clean":	$statusCode = $this->cleanCommand($args); break;				
 			case "update":	$statusCode = $this->updateCommand($args); break;
-			default:		$statusCode = $this->updateCommandPending($args); break;
+			default:		$statusCode = $this->processCommandInstallationPending($args); break;
 		}
 		return $statusCode;
 	}
@@ -49,11 +57,29 @@ class YellowUpdate
 		return "update [FEATURE]";
 	}
 	
+	// Clean downloads
+	function cleanCommand($args)
+	{
+		$statusCode = 0;
+		list($command, $path) = $args;
+		if($path=="all")
+		{
+			$path = $this->yellow->config->get("pluginDir");
+			$regex = "/^.*\\".$this->yellow->config->get("downloadExtension")."$/";
+			foreach($this->yellow->toolbox->getDirectoryEntries($path, $regex, false, false) as $entry)
+			{
+				if(!$this->yellow->toolbox->deleteFile($entry)) $statusCode = 500;
+			}
+			if($statusCode==500) echo "ERROR cleaning downloads: Can't delete files in directory '$path'!\n";
+		}
+		return $statusCode;
+	}
+	
 	// Update website
 	function updateCommand($args)
 	{
-		list($command, $feature) = $args;
-		list($statusCode, $data) = $this->getSoftwareUpdate($feature);
+		list($command, $feature, $option) = $args;
+		list($statusCode, $data) = $this->getSoftwareUpdates($feature);
 		if(!empty($data))
 		{
 			foreach($data as $key=>$value)
@@ -61,8 +87,8 @@ class YellowUpdate
 				list($version) = explode(',', $value);
 				echo "$key $version\n";
 			}
-			if($statusCode==200) $statusCode = $this->download($data);
-			if($statusCode==200) $statusCode = $this->update();
+			if($statusCode==200) $statusCode = $this->downloadSoftware($data);
+			if($statusCode==200) $statusCode = $this->updateSoftware($option);
 			if($statusCode!=200) echo "ERROR updating files: ".$this->yellow->page->get("pageError")."\n";
 			echo "Yellow $command: Website ".($statusCode!=200 ? "not " : "")."updated\n";
 		} else {
@@ -72,24 +98,8 @@ class YellowUpdate
 		return $statusCode;
 	}
 	
-	// Update pending software
-	function updateCommandPending($args)
-	{
-		$statusCode = 0;
-		if($this->isSoftwarePending())
-		{
-			$statusCode = $this->update();
-			if($statusCode!=0)
-			{
-				if($statusCode!=200) echo "ERROR updating files: ".$this->yellow->page->get("pageError")."\n";
-				echo "Yellow has ".($statusCode!=200 ? "not " : "")."been updated: Please run command again\n";
-			}
-		}
-		return $statusCode;
-	}
-	
-	// Download available software
-	function download($data)
+	// Download software
+	function downloadSoftware($data)
 	{
 		$statusCode = 0;
 		$path = $this->yellow->config->get("pluginDir");
@@ -121,85 +131,82 @@ class YellowUpdate
 		return $statusCode;
 	}
 
-	// Update downloaded software
-	function update()
+	// Update software
+	function updateSoftware($option = "")
 	{
 		$statusCode = 0;
-		foreach($this->yellow->plugins->plugins as $key=>$value)
+		$path = $this->yellow->config->get("pluginDir");
+		foreach($this->yellow->toolbox->getDirectoryEntries($path, "/^.*\.zip$/", true, false) as $entry)
 		{
-			if(method_exists($value["obj"], "onUpdate"))
-			{
-				$statusCode = $value["obj"]->onUpdate($this->yellow->getRequestHandler());
-				if($statusCode!=0) break;
-			}
+			$statusCode = max($statusCode, $this->updateSoftwareArchive($entry, $option));
 		}
-		if($statusCode==0)
+		$path = $this->yellow->config->get("themeDir");
+		foreach($this->yellow->toolbox->getDirectoryEntries($path, "/^.*\.zip$/", true, false) as $entry)
 		{
-			$path = $this->yellow->config->get("pluginDir");
-			foreach($this->yellow->toolbox->getDirectoryEntries($path, "/^.*\.zip$/", true, false) as $entry)
-			{
-				if(defined("DEBUG") && DEBUG>=2) echo "YellowUpdate::update file:$entry<br/>\n";
-				$statusCode = max($statusCode, $this->updateSoftwareArchive($entry));
-			}
-			$path = $this->yellow->config->get("themeDir");
-			foreach($this->yellow->toolbox->getDirectoryEntries($path, "/^.*\.zip$/", true, false) as $entry)
-			{
-				if(defined("DEBUG") && DEBUG>=2) echo "YellowUpdate::update file:$entry<br/>\n";
-				$statusCode = max($statusCode, $this->updateSoftwareArchive($entry));
-			}
+			$statusCode = max($statusCode, $this->updateSoftwareArchive($entry, $option));
 		}
 		return $statusCode;
 	}
-	
+
 	// Update software from archive
-	function updateSoftwareArchive($path)
+	function updateSoftwareArchive($path, $option = "")
 	{
 		$statusCode = 0;
 		$zip = new ZipArchive();
 		if($zip->open($path)===true)
 		{
-			$fileNameInformation = $this->yellow->config->get("updateInformationFile");
-			for($i=0; $i<$zip->numFiles; ++$i)
+			if(defined("DEBUG") && DEBUG>=2) echo "YellowUpdate::updateSoftwareArchive file:$path<br/>\n";
+			if(strtoloweru($option)=="force") $force = true;
+			if(preg_match("#^(.*\/).*?$#", $zip->getNameIndex(0), $matches)) $pathBase = $matches[1];
+			$fileData = $zip->getFromName($pathBase.$this->yellow->config->get("updateInformationFile"));
+			foreach($this->yellow->toolbox->getTextLines($fileData) as $line)
 			{
-				$fileName = $zip->getNameIndex($i);
-				if(empty($pathBase))
-				{
-					preg_match("#^(.*\/).*?$#", $fileName, $matches);
-					$pathBase = $matches[1];
-				}
-				if($fileName==$pathBase.$fileNameInformation)
+				preg_match("/^\s*(.*?)\s*:\s*(.*?)\s*$/", $line, $matches);
+				if(!empty($matches[1]) && !empty($matches[2]))
 				{
-					$fileData = $zip->getFromIndex($i);
-					break;
+					if(is_file($matches[1])) { $lastPublished = filemtime($matches[1]); break; }
 				}
 			}
 			foreach($this->yellow->toolbox->getTextLines($fileData) as $line)
 			{
-				if(preg_match("/^\#/", $line)) continue;
 				preg_match("/^\s*(.*?)\s*:\s*(.*?)\s*$/", $line, $matches);
 				if(lcfirst($matches[1])=="plugin" || lcfirst($matches[1])=="theme") $software = $matches[2];
+				if(lcfirst($matches[1])=="published") $modified = strtotime($matches[2]);
 				if(!empty($software) && !empty($matches[1]) && !empty($matches[2]))
 				{
-					list($fileName, $flags) = explode(',', $matches[2], 2);
-					$fileData = $zip->getFromName($pathBase.$fileName);
-					$metaData = $zip->statName($pathBase.$fileName);
-					$modified = $metaData ? $metaData["mtime"] : 0;
-					$statusCode = $this->updateSoftwareFile($matches[1], $fileData, $modified, $flags, $software);
+					list($entry, $flags) = explode(',', $matches[2], 2);
+					$fileName = $matches[1];
+					$fileData = $zip->getFromName($pathBase.$entry);
+					$lastModified = $this->yellow->toolbox->getFileModified($fileName);
+					$statusCode = $this->updateSoftwareFile($fileName, $fileData, $modified, $lastModified, $lastPublished, $flags, $force, $software);
 					if($statusCode!=200) break;
 				}
 			}
 			$zip->close();
-			if($statusCode==200 && !$this->yellow->toolbox->deleteFile($path))
+			if($statusCode==200)
 			{
-				$statusCode = 500;
-				$this->yellow->page->error($statusCode, "Can't delete file '$path'!");
+				$updateNotification = $this->yellow->config->get("updateNotification");
+				if($updateNotification=="none") $updateNotification = "";
+				if(!empty($updateNotification)) $updateNotification .= ",";
+				$updateNotification .= $software;
+				$fileNameConfig = $this->yellow->config->get("configDir").$this->yellow->config->get("configFile");
+				if(!$this->yellow->config->update($fileNameConfig, array("updateNotification" => $updateNotification)))
+				{
+					$statusCode = 500;
+					$this->yellow->page->error(500, "Can't write file '$fileNameConfig'!");
+				}
 			}
 		}
+		if(!$this->yellow->toolbox->deleteFile($path))
+		{
+			$statusCode = 500;
+			$this->yellow->page->error($statusCode, "Can't delete file '$path'!");
+		}
 		return $statusCode;
 	}
 	
 	// Update software file
-	function updateSoftwareFile($fileName, $fileData, $modified, $flags, $software)
+	function updateSoftwareFile($fileName, $fileData, $modified, $lastModified, $lastPublished, $flags, $force, $software)
 	{
 		$statusCode = 200;
 		$fileName = $this->yellow->toolbox->normaliseTokens($fileName);
@@ -209,7 +216,8 @@ class YellowUpdate
 			if(preg_match("/create/i", $flags) && !is_file($fileName) && !empty($fileData)) $create = true;
 			if(preg_match("/update/i", $flags) && is_file($fileName) && !empty($fileData)) $update = true;
 			if(preg_match("/delete/i", $flags) && is_file($fileName)) $delete = true;
-			if(preg_match("/optional/i", $flags) && $this->isSoftware($software)) $create = $update = $delete = false;
+			if(preg_match("/careful/i", $flags) && is_file($fileName) && $lastModified!=$lastPublished && !$force) $update = false;
+			if(preg_match("/optional/i", $flags) && $this->isSoftwareExisting($software)) $create = $update = $delete = false;
 			if($create)
 			{
 				if(!$this->yellow->toolbox->createFile($fileName, $fileData, true) ||
@@ -237,41 +245,77 @@ class YellowUpdate
 					$this->yellow->page->error($statusCode, "Can't delete file '$fileName'!");
 				}
 			}
-			if(defined("DEBUG") && DEBUG>=3) echo "YellowUpdate::updateSoftwareFile file:$fileName flags:$flags<br/>\n";
+			if(defined("DEBUG") && DEBUG>=2)
+			{
+				$debug = "action:".($create ? "create" : "").($update ? "update" : "").($delete ? "delete" : "");
+				if(!$create && !$update && !$delete) $debug = "action:none";
+				echo "YellowUpdate::updateSoftwareFile file:$fileName $debug<br/>\n";
+			}
 		}
 		return $statusCode;
 	}
 	
-	// Update installation files
-	function updateInstallation($feature)
+	// Update software features
+	function updateSoftwareFeatures($feature)
 	{
-		$ok = true;
+		$statusCode = 200;
 		$path = $this->yellow->config->get("pluginDir");
-		$regex = "/^.*\\".$this->yellow->config->get("downloadExtension")."$/";
+		$regex = "/^.*\\".$this->yellow->config->get("installationExtension")."$/";
 		foreach($this->yellow->toolbox->getDirectoryEntries($path, $regex, true, false) as $entry)
 		{
 			if(stristr(basename($entry), $feature))
 			{
-				if($this->updateSoftwareArchive($entry)!=200) $ok = false;
+				$statusCode = max($statusCode, $this->updateSoftwareArchive($entry));
 			}
 		}
-		if($ok)
+		if($statusCode==200)
 		{
 			foreach($this->yellow->toolbox->getDirectoryEntries($path, $regex, true, false) as $entry)
 			{
 				$this->yellow->toolbox->deleteFile($entry);
 			}
 		}
-		return $ok;
+		return $statusCode;
+	}
+	
+	// Process update notification for recently installed software
+	function processUpdateNotification()
+	{
+		if($this->yellow->config->get("updateNotification")!="none")
+		{
+			$tokens = explode(',', $this->yellow->config->get("updateNotification"));
+			foreach($this->yellow->plugins->plugins as $key=>$value)
+			{
+				if(in_array($value["plugin"], $tokens) && method_exists($value["obj"], "onUpdate")) $value["obj"]->onUpdate($key);
+			}
+			$fileNameConfig = $this->yellow->config->get("configDir").$this->yellow->config->get("configFile");
+			$this->yellow->config->update($fileNameConfig, array("updateNotification" => "none"));
+		}
+	}
+	
+	// Process command to install pending software
+	function processCommandInstallationPending($args)
+	{
+		$statusCode = 0;
+		if($this->isSoftwarePending())
+		{
+			$statusCode = $this->updateSoftware();
+			if($statusCode!=0)
+			{
+				if($statusCode!=200) echo "ERROR updating files: ".$this->yellow->page->get("pageError")."\n";
+				echo "Yellow has ".($statusCode!=200 ? "not " : "")."been updated: Please run command again\n";
+			}
+		}
+		return $statusCode;
 	}
 	
 	// Process request to install pending software
-	function processRequestPending($serverScheme, $serverName, $base, $location, $fileName)
+	function processRequestInstallationPending($serverScheme, $serverName, $base, $location, $fileName)
 	{
 		$statusCode = 0;
-		if($this->isContentFile($fileName) && $this->isSoftwarePending())
+		if($this->yellow->lookup->isContentFile($fileName) && $this->isSoftwarePending())
 		{
-			$statusCode = $this->update();
+			$statusCode = $this->updateSoftware();
 			if($statusCode==200)
 			{
 				$statusCode = 303;
@@ -283,15 +327,15 @@ class YellowUpdate
 	}
 	
 	// Process request to install website
-	function processRequestInstallation($serverScheme, $serverName, $base, $location, $fileName)
+	function processRequestInstallationMode($serverScheme, $serverName, $base, $location, $fileName)
 	{
 		$statusCode = 0;
-		if($this->isContentFile($fileName) && $this->isInstallation())
+		if($this->yellow->lookup->isContentFile($fileName) && $this->isInstallationMode())
 		{
 			$this->yellow->pages->pages["root/"] = array();
 			$this->yellow->page = new YellowPage($this->yellow);
 			$this->yellow->page->setRequestInformation($serverScheme, $serverName, $base, $location, $fileName);
-			$this->yellow->page->parseData($this->getRawDataInstallation($this->yellow->getRequestLanguage()), false, 404);
+			$this->yellow->page->parseData($this->getRawDataInstallation(), false, 404);
 			$this->yellow->page->parserSafeMode = false;
 			$this->yellow->page->parseContent();
 			$name = trim(preg_replace("/[^\pL\d\-\. ]/u", "-", $_REQUEST["name"]));
@@ -324,7 +368,7 @@ class YellowUpdate
 			{
 				if(!empty($feature))
 				{
-					$status = $this->updateInstallation($feature) ? "ok" : "error";
+					$status = $this->updateSoftwareFeatures($feature)==200 ? "ok" : "error";
 					if($status=="error") $this->yellow->page->error(500, "Can't install feature '$feature'!");
 				}
 			}
@@ -348,8 +392,9 @@ class YellowUpdate
 	}
 	
 	// Return raw data for installation page
-	function getRawDataInstallation($language)
+	function getRawDataInstallation()
 	{
+		$language = $this->yellow->toolbox->detectBrowserLanguage($this->yellow->text->getLanguages(), $this->yellow->config->get("language"));
 		$fileName = strreplaceu("(.*)", "installation", $this->yellow->config->get("configDir").$this->yellow->config->get("webinterfaceNewFile"));
 		$rawData = $this->yellow->toolbox->readFile($fileName);
 		if(empty($rawData))
@@ -370,10 +415,10 @@ class YellowUpdate
 				}
 				$rawData .= "</p>\n";
 			}
-			if(count($this->getFeatures())>1)
+			if(count($this->getSoftwareFeatures())>1)
 			{
 				$rawData .= "<p>".$this->yellow->text->get("webinterfaceInstallationFeature")."<p>";
-				foreach($this->getFeatures() as $feature)
+				foreach($this->getSoftwareFeatures() as $feature)
 				{
 					$checked = $feature=="website" ? " checked=\"checked\"" : "";
 					$rawData .= "<label for=\"$feature\"><input type=\"radio\" name=\"feature\" id=\"$feature\" value=\"$feature\"$checked> ".ucfirst($feature)."</label><br />";
@@ -394,7 +439,7 @@ class YellowUpdate
 		return $rawData;
 	}
 	
-	// Return configuration data for installation
+	// Return configuration data
 	function getConfigData()
 	{
 		$data = array();
@@ -411,12 +456,12 @@ class YellowUpdate
 		return $data;
 	}
 
-	// Return installation features
-	function getFeatures()
+	// Return software features
+	function getSoftwareFeatures()
 	{
 		$data = array("website");
 		$path = $this->yellow->config->get("pluginDir");
-		$regex = "/^.*\\".$this->yellow->config->get("downloadExtension")."$/";
+		$regex = "/^.*\\".$this->yellow->config->get("installationExtension")."$/";
 		foreach($this->yellow->toolbox->getDirectoryEntries($path, $regex, true, false, false) as $entry)
 		{
 			if(preg_match("/^(.*?)-(.*?)\./", $entry, $matches))
@@ -427,8 +472,8 @@ class YellowUpdate
 		return $data;
 	}
 	
-	// Return software update
-	function getSoftwareUpdate($feature)
+	// Return software updates
+	function getSoftwareUpdates($feature)
 	{
 		$data = array();
 		list($statusCode, $dataCurrent) = $this->getSoftwareVersion();
@@ -471,8 +516,7 @@ class YellowUpdate
 			}
 		} else {
 			$statusCode = 200;
-			foreach($this->yellow->plugins->getData() as $key=>$value) $data[$key] = $value;
-			foreach($this->yellow->themes->getData() as $key=>$value) $data[$key] = $value;
+			$data = array_merge($this->yellow->plugins->getData(), $this->yellow->themes->getData());
 		}
 		return array($statusCode, $data);
 	}
@@ -500,9 +544,10 @@ class YellowUpdate
 			{
 				$fileData = $rawData;
 			} else if($statusCode==0) {
-				$statusCode = 444;
-				$this->yellow->page->error($statusCode, "No response from server!");
+				$statusCode = 500;
+				$this->yellow->page->error($statusCode, "Can't connect to server!");
 			} else {
+				$statusCode = 500;
 				$this->yellow->page->error($statusCode, "Can't download file '$url'!");
 			}
 			if(defined("DEBUG") && DEBUG>=3) echo "YellowUpdate::getSoftwareFile status:$statusCode url:$url<br/>\n";
@@ -513,14 +558,7 @@ class YellowUpdate
 		return array($statusCode, $fileData);
 	}
 	
-	// Check if software exists
-	function isSoftware($software)
-	{
-		$data = $this->yellow->plugins->getData();
-		return !is_null($data[$software]);
-	}
-	
-	// Check if pending software exists
+	// Check if software installation is pending
 	function isSoftwarePending()
 	{
 		$path = $this->yellow->config->get("pluginDir");
@@ -529,18 +567,18 @@ class YellowUpdate
 		$foundThemes = count($this->yellow->toolbox->getDirectoryEntries($path, "/^.*\.zip$/", true, false))>0;
 		return $foundPlugins || $foundThemes;
 	}
-	
-	// Check if installation requested
-	function isInstallation()
+
+	// Check if software exists
+	function isSoftwareExisting($software)
 	{
-		return $this->yellow->config->get("installationMode") && PHP_SAPI!="cli";
+		$data = array_merge($this->yellow->plugins->getData(), $this->yellow->themes->getData());
+		return !is_null($data[$software]);
 	}
 
-	// Check if content file
-	function isContentFile($fileName)
+	// Check if installation mode
+	function isInstallationMode()
 	{
-		$contentDirLength = strlenu($this->yellow->config->get("contentDir"));
-		return substru($fileName, 0, $contentDirLength)==$this->yellow->config->get("contentDir");
+		return $this->yellow->config->get("installationMode") && PHP_SAPI!="cli";
 	}
 }
 	

+ 1 - 1
system/plugins/webinterface.css

@@ -1,4 +1,4 @@
-/* Yellow web interface 0.6.16 */
+/* Yellow web interface 0.6.17 */
 
 .yellow-bar { position:relative; overflow:hidden; height:2em; margin-bottom:10px; }
 .yellow-bar-left { display:block; float:left; }

+ 6 - 6
system/plugins/webinterface.js

@@ -1,10 +1,10 @@
-// Copyright (c) 2013-2016 Datenstrom, http://datenstrom.se
+// Copyright (c) 2013-2017 Datenstrom, http://datenstrom.se
 // This file may be used and distributed under the terms of the public license.
 
 // Yellow API
 var yellow =
 {
-	version: "0.6.16",
+	version: "0.6.17",
 	action: function(action) { yellow.webinterface.action(action, "none"); },
 	onLoad: function() { yellow.webinterface.loadInterface(); },
 	onClick: function(e) { yellow.webinterface.hidePanesOnClick(yellow.toolbox.getEventElement(e)); },
@@ -267,15 +267,15 @@ yellow.webinterface =
 				}
 				break;
 			case "yellow-pane-version":
-				if(paneStatus=="none")
+				if(paneStatus=="none" && yellow.config.pluginUpdate)
 				{
-					document.getElementById("yellow-pane-version-status").innerHTML = this.getText("VersionStatus", "", paneStatus);
+					document.getElementById("yellow-pane-version-status").innerHTML = this.getText("VersionStatusCheck");
 					document.getElementById("yellow-pane-version-fields").innerHTML = "";
-					setTimeout("yellow.action('send');", 100);
+					setTimeout("yellow.action('send');", 500);
 				}
 				if(paneStatus=="updates" && yellow.config.userWebmaster)
 				{
-					document.getElementById("yellow-pane-version-status").innerHTML = "<a href=\"#\" onclick=\"yellow.action('update'); return false;\">"+this.getText("VersionStatusRequest")+"</a>";
+					document.getElementById("yellow-pane-version-status").innerHTML = "<a href=\"#\" onclick=\"yellow.action('update'); return false;\">"+this.getText("VersionUpdateNormal")+"</a>";
 				}
 				break;
 			case "yellow-pane-edit":

+ 13 - 22
system/plugins/webinterface.php

@@ -1,11 +1,11 @@
 <?php
-// Copyright (c) 2013-2016 Datenstrom, http://datenstrom.se
+// Copyright (c) 2013-2017 Datenstrom, http://datenstrom.se
 // This file may be used and distributed under the terms of the public license.
 
 // Web interface plugin
 class YellowWebinterface
 {
-	const VERSION = "0.6.16";
+	const VERSION = "0.6.17";
 	var $yellow;			//access to API
 	var $response;			//web interface response
 	var $users;				//web interface users
@@ -28,7 +28,6 @@ class YellowWebinterface
 		$this->yellow->config->setDefault("webinterfaceUserHashAlgorithm", "bcrypt");
 		$this->yellow->config->setDefault("webinterfaceUserHashCost", "10");
 		$this->yellow->config->setDefault("webinterfaceUserStatus", "active");
-		$this->yellow->config->setDefault("webinterfaceUserPending", "none");
 		$this->yellow->config->setDefault("webinterfaceUserHome", "/");
 		$this->users->load($this->yellow->config->get("configDir").$this->yellow->config->get("webinterfaceUserFile"));
 	}
@@ -36,7 +35,7 @@ class YellowWebinterface
 	// Handle update
 	function onUpdate($name)
 	{
-		return $this->cleanCommand(array("clean", "all"));
+		if($name=="webinterface") $this->cleanCommand(array("clean", "all"));
 	}
 	
 	// Handle request
@@ -228,10 +227,10 @@ class YellowWebinterface
 		{
 			$statusCode = $this->yellow->processRequest($serverScheme, $serverName, $base, $location, $fileName, false);
 		} else {
-			if($this->yellow->isRequestContentDirectory($location))
+			if($this->yellow->lookup->isRedirectLocation($location))
 			{
 				$statusCode = 301;
-				$location = $this->yellow->lookup->isFileLocation($location) ? "$location/" : "/".$this->yellow->getRequestLanguage(true)."/";
+				$location = $this->yellow->lookup->isFileLocation($location) ? "$location/" : "/".$this->yellow->getRequestLanguage()."/";
 				$location = $this->yellow->lookup->normaliseUrl($serverScheme, $serverName, $base, $location);
 				$this->yellow->sendStatus($statusCode, $location);
 			} else {
@@ -484,14 +483,14 @@ class YellowWebinterface
 		if($this->response->status=="ok" && $email!=$emailSource)
 		{
 			$fileNameUser = $this->yellow->config->get("configDir").$this->yellow->config->get("webinterfaceUserFile");
-			$this->users->users[$emailSource]["pending"] = $this->yellow->config->get("webinterfaceUserPending");
+			$this->users->users[$emailSource]["pending"] = "none";
 			$this->response->status = $this->users->update($fileNameUser, $emailSource, "", "", "", "inactive") ? "ok" : "error";
 			if($this->response->status=="error") $this->yellow->page->error(500, "Can't write file '$fileNameUser'!");
 		}
 		if($this->response->status=="ok")
 		{
 			$this->users->users[$email]["hash"] = $hash;
-			$this->users->users[$email]["pending"] = $this->yellow->config->get("webinterfaceUserPending");
+			$this->users->users[$email]["pending"] = "none";
 			$fileNameUser = $this->yellow->config->get("configDir").$this->yellow->config->get("webinterfaceUserFile");
 			$this->response->status = $this->users->update($fileNameUser, $email, "", "", "", "active") ? "ok" : "error";
 			if($this->response->status=="error") $this->yellow->page->error(500, "Can't write file '$fileNameUser'!");
@@ -526,12 +525,8 @@ class YellowWebinterface
 					++$count; if($count>=4) { $this->response->rawDataOutput .= "…"; break; }
 				}
 			}
-			$this->response->status = $updates ? "updates" : "latest";
-			if($statusCode!=200)
-			{
-				$this->yellow->page->statusCode = 500;
-				$this->response->status = "error";
-			}
+			$this->response->status = $updates ? "updates" : "done";
+			if($statusCode!=200) $this->response->status = "error";
 		}
 		$statusCode = $this->yellow->processRequest($serverScheme, $serverName, $base, $location, $fileName, false);
 		return $statusCode;
@@ -541,7 +536,7 @@ class YellowWebinterface
 	function processRequestUpdate($serverScheme, $serverName, $base, $location, $fileName)
 	{
 		$statusCode = 0;
-		if($this->response->isUserWebmaster())
+		if($this->yellow->plugins->isExisting("update") && $this->response->isUserWebmaster())
 		{
 			$statusCode = $this->yellow->command("update");
 			if($statusCode==200)
@@ -549,11 +544,6 @@ class YellowWebinterface
 				$statusCode = 303;
 				$location = $this->yellow->lookup->normaliseUrl($serverScheme, $serverName, $base, $location);
 				$this->yellow->sendStatus($statusCode, $location);
-			} else {
-				$statusCode = 500;
-				$this->yellow->page->statusCode = 500;
-				$this->yellow->page->set("pageError", "Can't install updates on this server!");
-				$this->yellow->processRequest($serverScheme, $serverName, $base, $location, $fileName, false);
 			}
 		}
 		return $statusCode;
@@ -876,6 +866,7 @@ class YellowResponse
 			$data["userHome"] = $this->webinterface->users->getHome($this->userEmail);
 			$data["userRestrictions"] = intval($this->isUserRestrictions());
 			$data["userWebmaster"] = intval($this->isUserWebmaster());
+			$data["pluginUpdate"] = intval($this->yellow->plugins->isExisting("update"));
 			$data["serverScheme"] = $this->yellow->config->get("serverScheme");
 			$data["serverName"] = $this->yellow->config->get("serverName");
 			$data["serverBase"] = $this->yellow->config->get("serverBase");
@@ -1096,7 +1087,7 @@ class YellowUsers
 				{
 					if(!is_numeric($modified)) { $home = $pending; $pending = $modified; $modified = 946684800; } //TODO: remove later, converts old file format
 					$home = empty($home) ? $pending : $home; //TODO: remove later, converts old file format
-					$pending = $this->yellow->config->get("webinterfaceUserPending");
+					$pending = "none";
 					$fileDataNew .= "$matches[1]: $hash,$name,$language,$status,$modified,$pending,$home\n";
 				}
 			} else {
@@ -1127,7 +1118,7 @@ class YellowUsers
 			$language = strreplaceu(',', '-', empty($language) ? $this->yellow->config->get("language") : $language);
 			$status = strreplaceu(',', '-', empty($status) ? $this->yellow->config->get("webinterfaceUserStatus") : $status);
 			$modified = strreplaceu(',', '-', empty($modified) ? time() : $modified);
-			$pending = strreplaceu(',', '-', empty($pending) ? $this->yellow->config->get("webinterfaceUserPending") : $pending);
+			$pending = strreplaceu(',', '-', empty($pending) ? "none" : $pending);
 			$home = strreplaceu(',', '-', empty($home) ? $this->yellow->config->get("webinterfaceUserHome") : $home);
 		}
 		$this->set($email, $hash, $name, $language, $status, $modified, $pending, $home);

BIN
system/plugins/yellow-blog.zip.download → system/plugins/yellow-blog.zip.installation


BIN
system/plugins/yellow-wiki.zip.download → system/plugins/yellow-wiki.zip.installation